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