Allow client-ip to be logged for each log entry. Speciy
[yazproxy-moved-to-github.git] / src / t-server.cpp
1 /*
2  * Copyright (c) 2005, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Id: t-server.cpp,v 1.9 2006-03-30 14:19:19 adam Exp $
6  */
7
8 #include <stdlib.h>
9 #include <pthread.h>
10 #include <yaz/log.h>
11 #include <yaz/diagbib1.h>
12 #include <yaz/options.h>
13 #include "msg-thread.h"
14 #include <yazpp/z-assoc.h>
15 #include <yazpp/pdu-assoc.h>
16 #include <yazpp/gdu.h>
17 #include <yazpp/gduqueue.h>
18 #include <yazpp/socket-manager.h>
19
20 #if HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23
24 using namespace yazpp_1;
25
26 class MyServer;
27
28 class Auth_Msg : public IMsg_Thread {
29 public:
30     int m_close_flag;
31     GDU *m_gdu;
32     GDU *m_output;
33     MyServer *m_front;
34     IMsg_Thread *handle();
35     void result();
36     Auth_Msg(GDU *gdu, MyServer *front);
37     virtual ~Auth_Msg();
38 };
39
40 Auth_Msg::Auth_Msg(GDU *gdu, MyServer *front)
41 {
42     m_front = front;
43     m_output = 0;
44     m_gdu = gdu;
45     m_close_flag = 0;
46 }
47
48 Auth_Msg::~Auth_Msg()
49 {
50     delete m_output;
51     delete m_gdu;
52 }
53     
54 IMsg_Thread *Auth_Msg::handle()
55 {
56     ODR odr = odr_createmem(ODR_ENCODE);
57     yaz_log(YLOG_LOG, "Auth_Msg:handle begin");
58     Z_GDU *z_gdu = m_gdu->get();
59     if (z_gdu->which == Z_GDU_Z3950)
60     {
61         Z_APDU *apdu = 0;
62         switch(z_gdu->u.z3950->which)
63         {
64         case Z_APDU_initRequest:
65             apdu = zget_APDU(odr, Z_APDU_initResponse);
66             ODR_MASK_SET(apdu->u.initResponse->options, Z_Options_triggerResourceCtrl);
67             ODR_MASK_SET(apdu->u.initResponse->options, Z_Options_search);
68             ODR_MASK_SET(apdu->u.initResponse->options, Z_Options_present);
69             break;
70         case Z_APDU_searchRequest:
71 #if HAVE_UNISTD_H
72             sleep(5);
73 #endif
74             apdu = zget_APDU(odr, Z_APDU_searchResponse);
75             break;
76         case Z_APDU_triggerResourceControlRequest:
77             break;
78         default:
79             apdu = zget_APDU(odr, Z_APDU_close);
80             m_close_flag = 1;
81             break;
82         }
83         if (apdu)
84             m_output = new GDU(apdu);
85     }
86     yaz_log(YLOG_LOG, "Auth_Msg:handle end");
87     odr_destroy(odr);
88     return this;
89 }
90
91 class MyServer : public Z_Assoc {
92 public:
93     ~MyServer();
94     MyServer(IPDU_Observable *the_PDU_Observable,
95              Msg_Thread *m_my_thread
96         );
97     IPDU_Observer* sessionNotify(IPDU_Observable *the_PDU_Observable,
98                                  int fd);
99
100     void recv_GDU(Z_GDU *apdu, int len);
101
102     void failNotify();
103     void timeoutNotify();
104     void connectNotify();
105
106     int m_no_requests;
107     int m_delete_flag;
108 private:
109     yazpp_1::GDUQueue m_in_queue;
110     Msg_Thread *m_my_thread;
111 };
112
113 void Auth_Msg::result()
114 {
115     m_front->m_no_requests--;
116     if (!m_front->m_delete_flag)
117     {
118         if (m_output)
119         {
120             int len;
121             m_front->send_GDU(m_output->get(), &len);
122         }
123         if (m_close_flag)
124         {
125             m_front->close();
126             m_front->m_delete_flag = 1;
127         }
128     }
129     if (m_front->m_delete_flag && m_front->m_no_requests == 0)
130         delete m_front;
131     delete this;
132 }
133
134 MyServer::MyServer(IPDU_Observable *the_PDU_Observable,
135                    Msg_Thread *my_thread
136 )
137     :  Z_Assoc(the_PDU_Observable)
138 {
139     m_my_thread = my_thread;
140     m_no_requests = 0;
141     m_delete_flag = 0;
142     yaz_log(YLOG_LOG, "Construct Myserver=%p", this);
143 }
144
145 IPDU_Observer *MyServer::sessionNotify(IPDU_Observable
146                                        *the_PDU_Observable, int fd)
147 {
148     MyServer *my = new MyServer(the_PDU_Observable, m_my_thread);
149     yaz_log(YLOG_LOG, "New session %s", the_PDU_Observable->getpeername());
150     return my;
151 }
152
153 MyServer::~MyServer()
154 {
155     yaz_log(YLOG_LOG, "Destroy Myserver=%p", this);
156 }
157
158 void MyServer::recv_GDU(Z_GDU *apdu, int len)
159 {
160     GDU *gdu = new GDU(apdu);
161     Auth_Msg *m = new Auth_Msg(gdu, this);
162     m_no_requests++;
163     m_my_thread->put(m);    
164 }
165
166 void MyServer::failNotify()
167 {
168     m_delete_flag = 1;
169     if (m_no_requests == 0)
170         delete this;
171     
172 }
173
174 void MyServer::timeoutNotify()
175 {
176     m_delete_flag = 1;
177     if (m_no_requests == 0)
178         delete this;
179 }
180
181 void MyServer::connectNotify()
182 {
183
184 }
185
186 void usage(const char *prog)
187 {
188     fprintf (stderr, "%s: [-a log] [-v level] [-T] @:port\n", prog);
189     exit (1);
190 }
191
192 int main(int argc, char **argv)
193 {
194     char *arg;
195     char *prog = *argv;
196     int thread_flag = 0;
197     int ret;
198     const char *addr = "tcp:@:9999";
199     char *apdu_log = 0;
200     int no_threads = 1;
201
202     while ((ret = options("n:a:v:T", argv, argc, &arg)) != -2)
203     {
204         switch (ret)
205         {
206         case 0:
207             addr = xstrdup(arg);
208             break;
209         case 'n':
210             no_threads = atoi(arg);
211             break;
212         case 'a':
213             apdu_log = xstrdup(arg);
214             break;
215         case 'v':
216             yaz_log_init_level (yaz_log_mask_str(arg));
217             break;
218         case 'T':
219             thread_flag = 1;
220             break;
221         default:
222             usage(prog);
223             return 1;
224         }
225     }
226
227     SocketManager mySocketManager;
228
229     PDU_Assoc *my_PDU_Assoc = 0;
230     
231     MyServer *z = 0;
232
233     Msg_Thread *my_thread = new Msg_Thread(&mySocketManager, no_threads);
234
235 #if YAZ_POSIX_THREADS
236     if (thread_flag)
237         my_PDU_Assoc = new PDU_AssocThread(&mySocketManager);
238     else
239         my_PDU_Assoc = new PDU_Assoc(&mySocketManager);
240 #else
241     my_PDU_Assoc = new PDU_Assoc(&mySocketManager);
242 #endif
243     
244     z = new MyServer(my_PDU_Assoc, my_thread);
245     z->server(addr);
246     if (apdu_log)
247     {
248         yaz_log (YLOG_LOG, "set_APDU_log %s", apdu_log);
249         z->set_APDU_log(apdu_log);
250     }
251
252     while (mySocketManager.processEvent() > 0)
253         ;
254     delete z;
255     delete my_thread;
256     return 0;    
257 }
258 /*
259  * Local variables:
260  * c-basic-offset: 4
261  * indent-tabs-mode: nil
262  * End:
263  * vim: shiftwidth=4 tabstop=8 expandtab
264  */
265