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;
8 js->mgr->on_socket_closed = &jserver_socket_closed;
14 void jserver_free(jserver* js) {
15 if(js == NULL) return;
18 node = js->client->next;
19 _jserver_remove_client_id(js, js->client->id);
22 socket_manager_free(js->mgr);
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);
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;
39 status = socket_open_tcp_server(js->mgr, port, listen_ip);
40 if(status == -1) return status;
43 if(unix_path != NULL) {
44 status = socket_open_unix_server(js->mgr, unix_path);
45 if(status == -1) return status;
51 void _free_jclient_node(jclient_node* node) {
52 if(node == NULL) return;
54 jserver_session_free(node->session);
58 /* allocates a new client node */
59 jclient_node* _new_jclient_node(int id) {
60 jclient_node* node = safe_malloc(sizeof(jclient_node));
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;
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);
82 void jserver_client_from_found(void* blob, char* from) {
83 jclient_node* node = (jclient_node*) blob;
84 if(node == NULL || from == NULL) return;
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);
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);
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);
108 void jserver_client_handle_msg(
109 void* blob, char* xml, char* from, char* to ) {
111 jclient_node* node = (jclient_node*) blob;
112 if(node == NULL || xml == NULL || to == NULL) return;
115 jclient_node* from_node = jserver_find_client(node->parent, from);
117 from_id = from_node->id;
120 debug_handler("Client %d received from %s message : %s",
121 node->id, from, xml );
123 jserver_send(node->parent, from_id, to, xml);
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;
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;
141 jclient_node* node = js->client;
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);
151 debug_handler("Searching for jclient to remove");
152 jclient_node* tail_node = 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);
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;
173 jclient_node* node = js->client;
175 debug_handler("Searching for jclient to remove with id %d", id);
176 debug_handler("First node in list has id %d", node->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);
186 jclient_node* tail_node = node;
190 debug_handler("Checking node %d to remove", node->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);
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;
208 if(node->addr && !strcmp(node->addr, addr))
215 jclient_node* jserver_find_client_id(jserver* js, int id) {
216 if(js == NULL) return NULL;
217 jclient_node* node = js->client;
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;
231 jclient_node* node = jserver_find_client(js, to_addr);
234 info_handler("message to non-existent client %s", to_addr);
236 jclient_node* from = jserver_find_client_id(js, from_id);
239 info_handler("replying with error...");
241 memset(buf, 0, 2048);
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 );
248 snprintf(buf, 2047, JSTRING_NO_RECIPIENT, to_addr, from->addr );
249 jserver_send_id(from_id, buf);
255 return jserver_send_id(node->id, msg_xml);
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 );
263 /* waits for any incoming data */
264 int jserver_wait(jserver* js) {
265 if(js == NULL) return -1;
267 if(socket_wait_all(js->mgr, -1) < 0)
269 "jserver_wait(): socket_wait_all() returned error");
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);
280 void jserver_handle_request(void* js_blob,
281 socket_manager* mgr, int sock_id, char* data, int parent_id ) {
283 jserver* js = (jserver*) js_blob;
285 debug_handler("jsever received data from socket %d (parent %d)", sock_id, parent_id );
287 jclient_node* node = jserver_find_client_id(js, sock_id);
289 debug_handler("We have a new client connection, adding to list");
290 node = _jserver_add_client(js, sock_id);
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);
300 debug_handler("Client data successfully parsed");