logging returned content at info level
[OpenSRF.git] / src / jserver / jserver-c.c
1 #include "jserver-c.h"
2
3 jserver* jserver_init() {
4         jserver* js                                     = safe_malloc(sizeof(jserver));
5         js->mgr                                         = safe_malloc(sizeof(socket_manager));
6         js->mgr->data_received  = &jserver_handle_request;
7         js->mgr->blob                           = js;
8         js->mgr->on_socket_closed       = &jserver_socket_closed;
9         js->client                                      = NULL;
10
11         return js;
12 }
13
14 void jserver_free(jserver* js) {
15         if(js == NULL) return;
16         jclient_node* node; 
17         while(js->client) {
18                 node = js->client->next;
19                 _jserver_remove_client_id(js, js->client->id);
20                 js->client = node;
21         }
22         socket_manager_free(js->mgr);
23         free(js);
24 }
25
26 void jserver_socket_closed(void* blob, int sock_id) {
27         jserver* js = (jserver*) blob;
28         if(js == NULL) return;
29         info_handler("Removing client %d - site closed socket",sock_id);
30         _jserver_remove_client_id(js, sock_id);
31 }
32
33 /* opens the inet and unix sockets that we're listening on */
34 int jserver_connect(jserver* js, int port, char* listen_ip, char* unix_path) {
35         if(js == NULL || js->mgr == NULL) return -1;
36         int status = 0;
37
38         if(port > 0) {
39                 status = socket_open_tcp_server(js->mgr, port, listen_ip);
40                 if(status == -1) return status;
41         }
42
43         if(unix_path != NULL) {
44                 status = socket_open_unix_server(js->mgr, unix_path);
45                 if(status == -1) return status;
46         }
47
48         return 0;
49 }
50
51 void _free_jclient_node(jclient_node* node) {
52         if(node == NULL) return;
53         free(node->addr);
54         jserver_session_free(node->session);
55         free(node);
56 }
57
58 /* allocates a new client node */
59 jclient_node* _new_jclient_node(int id) {
60         jclient_node* node = safe_malloc(sizeof(jclient_node));
61         node->id = id;
62         node->addr = NULL;
63         node->session = jserver_session_init();
64         node->session->blob = node;
65         node->session->on_msg_complete = &jserver_client_handle_msg; 
66         node->session->on_from_discovered = &jserver_client_from_found;
67         node->session->on_login_init = &jserver_client_login_init;
68         node->session->on_login_ok = &jserver_client_login_ok;
69         node->session->on_client_finish = &jserver_client_finish;
70         return node;
71 }
72
73 /* client has sent the end of it's session doc, we may now disconnect */
74 void jserver_client_finish(void* blob) {
75         jclient_node* node = (jclient_node*) blob;
76         if(node == NULL) return;
77         jserver_send_id(node->id, "</stream:stream>");
78         _jserver_remove_client(node->parent, node->addr);
79
80 }
81
82 void jserver_client_from_found(void* blob, char* from) {
83         jclient_node* node = (jclient_node*) blob;
84         if(node == NULL || from == NULL) return;
85
86         /* prevent duplicate login - kick off original */
87         _jserver_remove_client(node->parent, from);
88         info_handler("logged in: %s", from);
89         node->addr = strdup(from);
90 }
91
92 void jserver_client_login_init(void* blob, char* reply) {
93         debug_handler("here");
94         jclient_node* node = (jclient_node*) blob;
95         if(node == NULL || reply == NULL) return;
96         debug_handler("jserver handling login init");
97         jserver_send_id(node->id, reply);
98 }
99
100 void jserver_client_login_ok(void* blob) {
101         jclient_node* node = (jclient_node*) blob;
102         if(node == NULL) return;
103         info_handler("Client logging in ok => %d", node->id);
104         //jserver_send_id(node->id, xml_login_ok);
105         jserver_send_id(node->id, JSTRING_LOGIN_OK);
106 }
107
108 void jserver_client_handle_msg( 
109         void* blob, char* xml, char* from, char* to ) {
110
111         jclient_node* node = (jclient_node*) blob;
112         if(node == NULL || xml == NULL || to == NULL) return;
113         int from_id = 0;
114
115         jclient_node* from_node = jserver_find_client(node->parent, from);
116         if(from_node)
117                 from_id = from_node->id;
118
119
120         debug_handler("Client %d received from %s message : %s", 
121                         node->id, from, xml );
122
123         jserver_send(node->parent, from_id, to, xml);
124 }
125
126 /* allocates a new client node and adds it to the set */
127 jclient_node* _jserver_add_client(jserver* js, int id) {
128         if(js == NULL) return NULL;
129         jclient_node* node = _new_jclient_node(id);
130         node->next = js->client;
131         js->client = node;
132         node->parent = js;
133         return node;
134 }
135
136
137 /* removes and frees a client node */
138 void _jserver_remove_client(jserver* js, char* addr) {
139         if(js == NULL || js->client == NULL || addr == NULL) return;
140
141         jclient_node* node = js->client;
142
143         if(node->addr && !strcmp(node->addr,addr)) {
144                 js->client = node->next;
145                 debug_handler("Removing the first jserver client");
146                 socket_disconnect(js->mgr, node->id);
147                 _free_jclient_node(node);
148                 return;
149         }
150
151         debug_handler("Searching for jclient to remove");
152         jclient_node* tail_node = node;
153         node = node->next;
154
155         while(node) {
156                 if(node->addr && !strcmp(node->addr,addr)) {
157                         tail_node->next = node->next;
158                         debug_handler("Removing a jserver client");
159                         socket_disconnect(js->mgr, node->id);
160                         _free_jclient_node(node);
161                         return;
162                 }
163                 tail_node = node;
164                 node = node->next;
165         }
166 }
167
168
169 /* removes and frees a client node */
170 void _jserver_remove_client_id(jserver* js, int id) {
171         if(js == NULL || js->client == NULL) return;
172
173         jclient_node* node = js->client;
174
175         debug_handler("Searching for jclient to remove with id %d", id);
176         debug_handler("First node in list has id %d", node->id );
177
178         if(node->id == id) {
179                 js->client = node->next;
180                 debug_handler("Removing the first jserver client");
181                 socket_disconnect(js->mgr, node->id);
182                 _free_jclient_node(node);
183                 return;
184         }
185
186         jclient_node* tail_node = node;
187         node = node->next;
188
189         while(node) {
190                 debug_handler("Checking node %d to remove", node->id);
191                 if(node->id == id) {
192                         tail_node->next = node->next;
193                         debug_handler("Removing a jserver client");
194                         socket_disconnect(js->mgr, node->id);
195                         _free_jclient_node(node);
196                         return;
197                 }
198                 tail_node = node;
199                 node = node->next;
200         }
201 }
202
203 /* finds a client node by addr */
204 jclient_node* jserver_find_client(jserver* js, char* addr) {
205         if(js == NULL || addr == NULL) return NULL;
206         jclient_node* node = js->client;
207         while(node) {
208                 if(node->addr && !strcmp(node->addr, addr)) 
209                         return node;
210                 node = node->next;
211         }
212         return NULL;
213 }
214
215 jclient_node* jserver_find_client_id(jserver* js, int id) {
216         if(js == NULL) return NULL;
217         jclient_node* node = js->client;
218         while(node) {
219                 if(node->id == id) 
220                         return node;
221                 node = node->next;
222         }
223         return NULL;
224 }
225
226 /* sends msg to client at 'to_addr' */
227 int jserver_send(jserver* js, int from_id, char* to_addr, const char* msg_xml) {
228         debug_handler("sending message to %s : %s", to_addr, msg_xml);
229         if(to_addr == NULL || msg_xml == NULL) return -1;
230
231         jclient_node* node = jserver_find_client(js, to_addr);
232
233         if(node == NULL) {
234                 info_handler("message to non-existent client %s", to_addr);
235                 if(from_id > 0) {
236                         jclient_node* from = jserver_find_client_id(js, from_id);
237
238                         if(from) {
239                                 info_handler("replying with error...");
240                                 char buf[2048];
241                                 memset(buf, 0, 2048);
242                                 /*
243                                 snprintf(buf, 2047, "<message xmlns='jabber:client' type='error' from='%s' "
244                                         "to='%s'><error type='cancel' code='404'><item-not-found "
245                                         "xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error>"
246                                         "<body>NOT ADDING BODY</body></message>", to_addr, from->addr );
247                                         */
248                                 snprintf(buf, 2047, JSTRING_NO_RECIPIENT, to_addr, from->addr );
249                                 jserver_send_id(from_id, buf);
250                         }
251                 }
252                 return -1;
253         }
254
255         return jserver_send_id(node->id, msg_xml);
256 }
257
258 int jserver_send_id(int client_id, const char* msg_xml) {
259         if(msg_xml == NULL || client_id < 1) return -1;
260         return socket_send(client_id, msg_xml );
261 }
262
263 /* waits for any incoming data */
264 int jserver_wait(jserver* js) {
265         if(js == NULL) return -1;
266         while(1) {
267                 if(socket_wait_all(js->mgr, -1) < 0)
268                         warning_handler(
269                                 "jserver_wait(): socket_wait_all() returned error");
270
271         }
272 }
273
274
275 int _jserver_push_client_data(jclient_node* node, char* data) {
276         if(node == NULL || data == NULL) return -1;
277         return jserver_session_push_data( node->session, data);
278 }
279
280 void jserver_handle_request(void* js_blob, 
281         socket_manager* mgr, int sock_id, char* data, int parent_id ) {
282
283         jserver* js = (jserver*) js_blob;
284
285         debug_handler("jsever received data from socket %d (parent %d)", sock_id, parent_id );
286
287         jclient_node* node = jserver_find_client_id(js, sock_id);
288         if(!node) {
289                 debug_handler("We have a new client connection, adding to list");
290                 node = _jserver_add_client(js, sock_id);
291         }
292
293         if(_jserver_push_client_data(node, data) == -1) {
294                 warning_handler("Client sent bad data, disconnecting...");
295                 //jserver_send_id(node->id, xml_parse_error);
296                 jserver_send_id(node->id, JSTRING_PARSE_ERROR);
297                 _jserver_remove_client(js, node->addr);         
298
299         } else {
300                 debug_handler("Client data successfully parsed");
301         }
302
303 }
304
305
306