]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/router/router.c
added la_time as timestamp and serve_count
[OpenSRF.git] / src / router / router.c
1 #include "router.h"
2 #include <sys/types.h>
3 #include <signal.h>
4
5
6 char* router_resource;
7 transport_router_registrar* routt;
8
9 void sig_hup_handler( int a ) { 
10         router_registrar_free( routt ); 
11         config_reader_free();   
12         log_free();
13         free( router_resource );
14         exit(0); 
15 }
16
17
18 int main( int argc, char* argv[] ) {
19
20         if( argc < 2 ) {
21                 fatal_handler( "Usage: %s <path_to_config_file>", argv[0] );
22                 exit(0);
23         }
24
25
26         config_reader_init( argv[1] );  
27         if( conf_reader == NULL ) fatal_handler( "main(): Config is NULL" ); 
28
29         /* laod the config options */
30         char* server                    = config_value("//router/transport/server");
31         char* port                              = config_value("//router/transport/port");
32         char* username                  = config_value("//router/transport/username");
33         char* password                  = config_value("//router/transport/password");
34         router_resource         = config_value("//router/transport/resource");
35         char* con_timeout               = config_value("//router/transport/connect_timeout" );
36         char* max_retries               = config_value("//router/transport/max_reconnect_attempts" );
37
38         fprintf(stderr, "Router connecting as \nserver: %s \nport: %s \nuser:%s \nresource:%s\n", 
39                         server, port, username, router_resource );
40
41         int iport                       = atoi( port );
42         int con_itimeout        = atoi( con_timeout );
43         int max_retries_        = atoi(max_retries);
44
45         if( iport < 1 ) { 
46                 fatal_handler( "Port is negative or 0" );
47                 return 99;
48         }
49
50
51         /* build the router_registrar */
52         transport_router_registrar* router_registrar = 
53                 router_registrar_init( server, iport, username, password, router_resource, 0, con_itimeout ); 
54
55         routt = router_registrar;
56
57         free(server);
58         free(port);
59         free(username);
60         free(password);
61         free(con_timeout);
62         free(max_retries);
63
64         signal(SIGHUP,sig_hup_handler);
65
66
67         int counter = 0;
68         /* wait for incoming... */
69         while( ++counter <= max_retries_ ) {
70
71                 /* connect to jabber */
72                 if( router_registrar_connect( router_registrar ) )  {
73                         info_handler( "Connected..." );
74                         fprintf(stderr, "- Connected -\n");
75                         counter = 0;
76                         listen_loop( router_registrar );
77                 } else  
78                         fatal_handler( "Could not connect to Jabber Server" );
79
80                 /* this should never happen */
81                 warning_handler( "Jabber server probably went away, attempting reconnect" );
82
83                 sleep(5);
84         }
85
86
87         router_registrar_free( router_registrar );
88         config_reader_free();   
89         return 1;
90
91 }
92
93 transport_router_registrar* router_registrar_init( char* server, 
94                 int port, char* username, char* password, 
95                 char* resource, int client_timeout, int con_timeout ) {
96
97         if( server == NULL ) { return NULL; }
98         
99         /* allocate a new router_registrar object */
100         size_t size = sizeof( transport_router_registrar );
101         transport_router_registrar* router_registrar = (transport_router_registrar*) safe_malloc( size );
102
103         router_registrar->client_timeout        = client_timeout;
104         router_registrar->jabber = jabber_connect_init( server, port, username, password, resource, con_timeout );
105         return router_registrar;
106
107 }
108
109 jabber_connect* jabber_connect_init( char* server, 
110                 int port, char* username, char* password, char* resource, int connect_timeout ) {
111
112         size_t len = sizeof(jabber_connect);
113         jabber_connect* jabber = (jabber_connect*) safe_malloc( len );
114
115         jabber->port                            = port;
116         jabber->connect_timeout = connect_timeout;
117
118         jabber->server                          = strdup(server);
119         jabber->username                        = strdup(username);
120         jabber->password                        = strdup(password);
121         jabber->resource                        = strdup(resource);
122
123         if( jabber->server == NULL || jabber->username == NULL ||
124                         jabber->password == NULL || jabber->resource == NULL ) {
125                 fatal_handler( "jabber_init(): Out of Memory" );
126                 return NULL;
127         }
128
129         /* build the transport client */
130         jabber->t_client = client_init( jabber->server, jabber->port );
131
132         return jabber;
133 }
134
135 /* connect the router_registrar to jabber */
136 int router_registrar_connect( transport_router_registrar* router ) {
137         return j_connect( router->jabber );
138 }
139
140 /* connect a jabber_connect object jabber */
141 int j_connect( jabber_connect* jabber ) {
142         if( jabber == NULL ) { return 0; }
143         return client_connect( jabber->t_client, 
144                         jabber->username, jabber->password, jabber->resource, jabber->connect_timeout );
145 }
146
147 int fill_fd_set( transport_router_registrar* router, fd_set* set ) {
148         
149         int max_fd;
150         FD_ZERO(set);
151
152         int router_fd = router->jabber->t_client->session->sock_obj->sock_fd;
153         max_fd = router_fd;
154         FD_SET( router_fd, set );
155
156         server_class_node* cur_node = router->server_class_list;
157         while( cur_node != NULL ) {
158                 int cur_class_fd = cur_node->jabber->t_client->session->sock_obj->sock_fd;
159                 if( cur_class_fd > max_fd ) 
160                         max_fd = cur_class_fd;
161                 FD_SET( cur_class_fd, set );
162                 cur_node = cur_node->next;
163         }
164
165         FD_CLR( 0, set );
166         return max_fd;
167 }
168
169
170 void listen_loop( transport_router_registrar* router ) {
171
172         if( router == NULL )
173                 return;
174
175         int select_ret;
176         int router_fd = router->jabber->t_client->session->sock_obj->sock_fd;
177         transport_message* cur_msg;
178
179         while(1) {
180
181                 fd_set listen_set;
182                 int max_fd = fill_fd_set( router, &listen_set );
183
184                 if( max_fd < 1 ) 
185                         fatal_handler( "fill_fd_set return bogus max_fd: %d", max_fd );
186
187                 int num_handled = 0;
188                 info_handler( "Going into select" );
189
190                 if( (select_ret=select(max_fd+ 1, &listen_set, NULL, NULL, NULL)) < 0 ) {
191
192                         warning_handler( "Select returned error %d", select_ret );
193                         warning_handler( "Select Error %d on fd %d", errno );
194                         perror( "Select Error" );
195                         warning_handler( "Errors: EBADF %d, EINTR %d, EINVAL %d, ENOMEM %d",
196                                         EBADF, EINTR, EINVAL, ENOMEM );
197                         continue;
198
199                 } else {
200
201                         info_handler( "Select returned %d", select_ret );
202                         
203                         if( FD_ISSET( router_fd, &listen_set ) ) {
204                                 cur_msg = client_recv( router->jabber->t_client, 1 );
205                                 router_registrar_handle_msg( router, cur_msg );
206                                 message_free( cur_msg );
207                                 if( ++num_handled == select_ret ) 
208                                         continue;
209                         }
210
211                         /* cycle through the children and find any whose fd's are ready for reading */
212                         server_class_node* cur_node = router->server_class_list;
213                         while( cur_node != NULL ) {
214                                 int cur_fd = cur_node->jabber->t_client->session->sock_obj->sock_fd;
215
216                                 if( FD_ISSET(cur_fd, &listen_set) ) {
217                                         ++num_handled;
218                                         FD_CLR(cur_fd,&listen_set);
219
220                                         cur_msg = client_recv( cur_node->jabber->t_client, 1 );
221                                         info_handler( "%s received from %s", cur_node->server_class, cur_msg->sender );
222                                         int handle_ret = server_class_handle_msg( router, cur_node, cur_msg );
223
224                                         if( handle_ret == -1 ) {
225                                                 warning_handler( "server_class_handle_msg() returned -1" );
226                                                 cur_node = router->server_class_list; /*start over*/
227                                                 continue;
228
229                                         } else if( handle_ret == 0 ) {
230                                                 /* delete and continue */
231                                                 warning_handler( "server_class_handle_msg() returned 0" );
232                                                 server_class_node* tmp_node = cur_node->next;
233                                                 remove_server_class( router, cur_node );        
234                                                 cur_node = tmp_node;
235                                                 continue;
236                                         } 
237
238                                         info_handler( "%s handled message successfully", cur_node->server_class );
239                                         /* dont free message here */
240                                         if( num_handled == select_ret ) 
241                                                 break;
242                                 }
243                                 if( num_handled == select_ret ) 
244                                         break;
245                                 cur_node = cur_node->next;
246
247                         } /* cycling through the server_class list */
248
249                 } /* no select errors */
250         } 
251 }
252
253
254 /* determine where to route top level messages */
255 int router_registrar_handle_msg( transport_router_registrar* router_registrar, transport_message* msg ) {
256
257         info_handler( "Received class: %s : command %s ", msg->router_class, msg->router_command );
258
259         if( router_registrar == NULL || msg == NULL ) { return 0; }
260
261         // user issued a ruoter query
262         /* a query command has router_command="query" and the actual query type
263                 is the content of the message */
264         if( !strcmp(msg->router_command,"query")) {
265                 info_handler( "Router received query command" );
266
267                 // user issues a servers query
268                 if( !strcmp(msg->body, "servers")) {
269
270                         info_handler( "Router received servers query command" );
271                         router_return_server_info( router_registrar, msg );
272                         return 1;
273                 }
274         }
275
276
277         info_handler("Looking for server_class_node %s...",msg->router_class);
278         server_class_node* active_class_node = find_server_class( router_registrar, msg->router_class );
279
280         if( active_class_node == NULL ) { 
281                 info_handler("Could not find server_class_node %s, creating one.",msg->router_class);
282
283                 /* there is no server_class for msg->router_class so we build it here */
284                 if( strcmp( msg->router_command, "register") == 0 ) {
285
286                         info_handler("Adding server_class_node for %s",msg->router_class);
287                         active_class_node = 
288                                 init_server_class( router_registrar, msg->sender, msg->router_class ); 
289
290                         if( active_class_node == NULL ) {
291                                 fatal_handler( "router_listen(): active_class_node == NULL for %s", msg->sender );
292                                 return 0;
293                         }
294
295                         if (router_registrar->server_class_list != NULL) {
296                                 active_class_node->next = router_registrar->server_class_list;
297                                 router_registrar->server_class_list->prev = active_class_node;
298                         }
299                         router_registrar->server_class_list = active_class_node;
300
301                         //spawn_server_class( (void*) active_class_node );
302
303                 } else {
304                         warning_handler( "router_register_handler_msg(): Bad Command [%s] for class [%s]",
305                                 msg->router_command, msg->router_class );
306                 }
307
308         } else if( strcmp( msg->router_command, "register") == 0 ) {
309                 /* there is a server_class for msg->router_class so we 
310                         need to either add a new server_node or update the existing one */
311
312                 
313                 server_node* s_node = find_server_node( active_class_node, msg->sender );
314
315                 if( s_node != NULL ) {
316                         s_node->available = 1;
317                         s_node->upd_time = time(NULL);
318                         info_handler( "Found matching registered server: %s. Updating.",
319                                         s_node->remote_id );
320                 } else {
321                         s_node = init_server_node( msg->sender );
322
323                         info_handler( "Adding server_node for: %s.", s_node->remote_id );
324
325                         if (s_node == NULL ) {
326                                 warning_handler( " Could not create new xerver_node for %s.",
327                                         msg->sender );
328                                 return 0;
329                         }
330
331                         s_node->next = active_class_node->current_server_node->next;
332                         s_node->prev = active_class_node->current_server_node;
333
334                         active_class_node->current_server_node->next->prev = s_node;
335                         active_class_node->current_server_node->next = s_node;
336                 }
337
338
339         } else if( strcmp( msg->router_command, "unregister") == 0 ) {
340
341                 if( ! unregister_server_node( active_class_node, msg->sender ) )
342                         remove_server_class( router_registrar, active_class_node );
343
344         } else {
345                 warning_handler( "router_register_handler_msg(): Bad Command [%s] for class [%s]",
346                         msg->router_command, msg->router_class );
347         }
348
349         return 1;
350 }
351
352
353 /* removes a server class node from the top level router_registrar */
354 int unregister_server_node( server_class_node* active_class_node, char* remote_id ) {
355
356         server_node* d_node = find_server_node( active_class_node, remote_id );
357
358         if ( d_node != NULL ) {
359
360                 info_handler( "Removing server_node for: %s.", d_node->remote_id );
361
362                 if ( d_node->next == NULL ) {
363                         warning_handler( "NEXT is NULL in ring [%s] -- "
364                                 "THIS SHOULD NEVER HAPPEN",
365                                 d_node->remote_id );
366
367                 }
368                 
369                 if ( d_node->prev == NULL ) {
370                         warning_handler( "PREV is NULL in a ring [%s] -- "
371                                 "THIS SHOULD NEVER HAPPEN",
372                                 d_node->remote_id );
373
374                 }
375
376                 if ( d_node->next == d_node && d_node->prev == d_node) {
377                         info_handler( "Last node, setting ring to NULL: %s.",
378                                 d_node->remote_id );
379
380                         active_class_node->current_server_node = NULL;
381
382                         server_node_free( d_node );
383                         return 0;
384
385                 } else {
386                         info_handler( "Nodes remain, splicing: %s, %s",
387                                 d_node->prev->remote_id,
388                                 d_node->next->remote_id);
389
390                 info_handler( "d_node => %x, next => %x, prev => %x",
391                                         d_node, d_node->next, d_node->prev );
392
393
394                         d_node->prev->next = d_node->next;
395                         d_node->next->prev = d_node->prev;
396
397                         info_handler( "prev => %x, prev->next => %x, prev->prev => %x",
398                                 d_node->prev, d_node->prev->next, d_node->prev->prev );
399
400                         info_handler( "next => %x, next->next => %x, next->prev => %x",
401                                 d_node->next, d_node->next->next, d_node->next->prev );
402                                 
403                         if (active_class_node->current_server_node == d_node)
404                                 active_class_node->current_server_node = d_node->next;
405
406
407                         server_node_free( d_node );
408                 }
409         } 
410
411         return 1;
412 }
413
414 server_node * find_server_node ( server_class_node * class, const char * remote_id ) {
415
416         if ( class == NULL ) {
417                 warning_handler(" find_server_node(): bad arg!");
418                 return NULL;
419         }
420
421         server_node * start_node = class->current_server_node;
422         server_node * node = class->current_server_node;
423
424         do {
425                 if (node == NULL)
426                         return NULL;
427
428                 if ( strcmp(node->remote_id, remote_id) == 0 )
429                         return node;
430
431                 node = node->next;
432
433         } while ( node != start_node );
434
435         return NULL;
436 }
437
438 /* if we return -1, then we just deleted the server_class you were looking for
439         if we return 0, then some other error has occured
440         we return 1 otherwise */
441 int remove_server_class( transport_router_registrar* router, server_class_node* class ) {
442         if( class == NULL )
443                 return 0;
444
445         transport_message * msg = NULL;
446         while ( (msg = client_recv(class->jabber->t_client, 0)) != NULL ) {
447                 server_class_handle_msg(router, class, msg);
448                 message_free(msg);
449         }
450         
451         free( class->server_class );
452         class->server_class = NULL;
453
454         find_server_class( router, router_resource ); /* find deletes for us */
455
456         if( router->server_class_list == NULL ) 
457                 return 0;
458         return 1;
459 }
460
461 server_class_node * find_server_class ( transport_router_registrar * router, const char * class_id ) {
462
463         if ( router == NULL ) {
464                 warning_handler(" find_server_class(): bad arg!");
465                 return NULL;
466         }
467
468         info_handler( "Finding server class for %s", class_id );
469         server_class_node * class = router->server_class_list;
470         server_class_node * dead_class = NULL;
471
472         while ( class != NULL ) {
473
474                 if ( class->server_class == NULL ) {
475                         info_handler( "Found an empty server class" );
476
477                         if ( class->prev != NULL ) {
478                                 class->prev->next = class->next;
479                                 if( class->next != NULL ) {
480                                         class->next->prev = class->prev;
481                                 }
482
483                         } else {
484                                 info_handler( "Empty class is the first on the list" );
485                                 if( class->next != NULL ) 
486                                         router->server_class_list = class->next;
487
488                                 else { /* we're the last class node in the class node list */
489                                         info_handler( "Empty class is the last on the list" );
490                                         server_class_node_free( router->server_class_list );
491                                         router->server_class_list = NULL;
492                                         break;
493                                 }
494                                         
495                         }
496
497                         dead_class = class;
498                         class = class->next;
499
500                         info_handler( "Tossing our dead class" );
501                         server_class_node_free( dead_class );
502
503                         if ( class == NULL )
504                                 return NULL;
505                 }
506
507                 if ( strcmp(class->server_class, class_id) == 0 )
508                         return class;
509                 info_handler( "%s != %s", class->server_class, class_id );
510
511                 class = class->next;
512         }
513
514         return NULL;
515 }
516
517 /* builds a new server class and connects to the jabber server with the new resource */
518 server_class_node* init_server_class( 
519                 transport_router_registrar* router, char* remote_id, char* server_class ) {
520
521         size_t len = sizeof( server_class_node );
522         server_class_node* node = (server_class_node*) safe_malloc( len );
523
524         node->jabber = jabber_connect_init( router->jabber->server,
525                         router->jabber->port, router->jabber->username, 
526                         router->jabber->password, server_class, router->jabber->connect_timeout );
527
528
529
530         node->server_class = strdup( server_class );
531         if( server_class == NULL ) {
532                 fatal_handler( "imit_server_class(): out of memory for %s", server_class );
533                 return NULL;
534         }
535
536         info_handler( "Received class to init_server_class: %s", server_class );
537         node->current_server_node = init_server_node( remote_id );
538         if( node->current_server_node == NULL ) {
539                 fatal_handler( "init_server_class(): NULL server_node for %s", remote_id );
540                 return NULL;
541         }
542
543
544         if( ! j_connect( node->jabber ) ) {
545                 fatal_handler( "Unable to init server class %s", node->server_class );
546                 return NULL;
547         }
548
549         info_handler( "Jabber address in init for %s : address %x : username %s : resource %s", 
550                         node->server_class, node->jabber->t_client->session->sock_obj->sock_fd, 
551                         node->jabber->username,  node->jabber->resource );
552
553         return node;
554
555 }
556
557 /* builds a new server_node to be added to the ring of server_nodes */
558 server_node* init_server_node(  char* remote_id ) {
559
560         info_handler( "Initing server node for %s", remote_id );
561         server_node* current_server_node;
562         size_t size = sizeof( server_node);
563         current_server_node = (server_node*) safe_malloc( size );
564
565         current_server_node->remote_id = strdup(remote_id);
566         if( current_server_node->remote_id == NULL ) {
567                 fatal_handler("init_server_class(): Out of Memory for %s", remote_id );
568                 return NULL;
569         }
570         
571         current_server_node->reg_time = time(NULL);     
572         current_server_node->available = 1;
573         current_server_node->next = current_server_node;
574         current_server_node->prev = current_server_node;
575
576
577         return current_server_node;
578
579 }
580
581 int  server_class_handle_msg( transport_router_registrar* router, 
582                 server_class_node* s_node, transport_message* msg ) {
583
584         if( s_node->current_server_node == NULL ) {
585                 /* return error to client ??!*/
586                 /* WE have no one to send the message to */
587                 warning_handler( "We no longer have any servers for %s : " 
588                                 "no one to send the message to. Sending error message to %s", s_node->server_class, msg->sender );
589                 free( msg->recipient );  
590
591                 char* rec = strdup( msg->sender );
592                 if( rec == NULL ) {
593                         fatal_handler( "class msg_handler: out of memory");
594                         return 0;
595                 }
596
597                 info_handler( "Building error message to return for %s", s_node->server_class);
598                 msg->recipient = rec;
599                 set_msg_error(msg, "cancel", 501);
600
601                 client_send_message( s_node->jabber->t_client, msg );
602                 message_free( msg );
603
604                 remove_server_class( router, s_node );
605
606                 return -1;
607         }
608
609         info_handler( "[%s] Received \nfrom: %s \nto: %s", 
610                         s_node->server_class, msg->sender, msg->recipient );
611
612         if( msg->is_error ) {
613                 warning_handler( "We've received an error message type: %s : code: %d", 
614                                 msg->error_type, msg->error_code );
615
616                 if( strcmp( msg->error_type, "cancel" ) == 0 ) {
617                         warning_handler( "Looks like we've lost a server!" );
618                         server_node* dead_node = find_server_node( s_node, msg->sender );
619
620                         if( dead_node != NULL ) { 
621                                 //message_free( msg );
622                                 transport_message* tmp = dead_node->last_sent;
623
624                                 /* copy over last sent, it will be freed in the unregister function */
625                                 transport_message* tmp2 = message_init( tmp->body, tmp->subject, tmp->thread,
626                                                 tmp->recipient, tmp->sender );
627                                         
628                                 message_set_router_info( tmp2, tmp->router_from,  
629                                                 tmp->router_to, tmp->router_class, tmp->router_command, tmp->broadcast );
630
631                                 if( ! unregister_server_node( s_node, dead_node->remote_id ) ) { 
632                                         /* WE have no one to send the message to */
633                                         warning_handler( "We no longer have any servers for %s : " 
634                                                         "no one to send the message to.", s_node->server_class );
635                                         free( msg->recipient );  
636
637                                         char* rec = strdup( msg->router_from );
638                                         if( rec == NULL ) {
639                                                 fatal_handler( "class msg_handler: out of memory");
640                                                 return 0;
641                                         }
642
643                                         info_handler( "Building error message to return for %s", s_node->server_class);
644                                         msg->recipient = rec;
645                                         client_send_message( s_node->jabber->t_client, msg );
646                                         message_free( tmp2 );
647                                         message_free( msg );
648                                         return 0;
649
650                                 } else {
651                                         msg = tmp2;
652                                 }
653                         }
654                 }
655         } 
656
657
658         server_node* c_node = s_node->current_server_node->next;
659
660         /* not implemented yet */
661         while( ! c_node->available ) {
662                 if( c_node == s_node->current_server_node ) {
663                         warning_handler("No server_node's are available for %s", s_node->server_class );
664                         /* XXX send error message to client */
665                         return 0;
666                 }
667                 c_node = c_node->next;
668         }
669         s_node->current_server_node = c_node;
670
671         transport_message * new_msg =
672                 message_init(   msg->body, msg->subject, msg->thread, 
673                                 s_node->current_server_node->remote_id, msg->sender );
674
675         message_set_router_info( new_msg, msg->sender, NULL, NULL, NULL, 0 );
676
677         info_handler( "[%s] Routing message from [%s]\nto [%s]", s_node->server_class, msg->sender, new_msg->recipient );
678         //info_handler( "New Message Details: sender:%s recipient: %s \nbody: %s", 
679         //              new_msg->sender, new_msg->recipient, new_msg->body );
680
681         message_free( s_node->current_server_node->last_sent );
682         s_node->current_server_node->last_sent = msg;
683
684         if ( new_msg != NULL && client_send_message( s_node->jabber->t_client, new_msg ) ) {
685                 s_node->current_server_node->serve_count++;
686                 s_node->current_server_node->la_time = time(NULL);
687                 message_free( new_msg ); // XXX
688                 return 1;
689         }
690         message_free( new_msg ); // XXX
691
692         return 0;
693 }
694
695
696 int router_return_server_info( 
697                 transport_router_registrar* router, transport_message* msg ) {
698
699         server_class_node* cur_class = router->server_class_list;
700         growing_buffer* buffer = buffer_init(1024);
701
702         while( cur_class != NULL ) {
703
704                 server_node* start_node = cur_class->current_server_node;
705                 server_node* cur_node = start_node;
706                 if( cur_node == NULL ) continue; 
707
708                 do {
709
710                         char buf[36];
711                         memset(buf,0, 36);
712
713                         char* localtime = strdup( ctime( &(cur_node->la_time) ) );
714                         strcpy( buf, localtime );
715                         buf[ strlen(localtime)-1] = '\0'; // remove newline
716                         free(localtime);
717
718                         buffer_add( buffer, buf );
719                         buffer_add( buffer, " | ");
720
721                         char tbuf[124];
722                         memset(tbuf,0,124);
723                         sprintf( tbuf, "%d", cur_node->la_time );       
724                         buffer_add( buffer, tbuf );
725                         buffer_add( buffer, " | ");
726
727
728                         char sbuf[64];
729                         memset(sbuf,0,64);
730                         sprintf(sbuf,"%d",cur_node->serve_count);
731
732                         buffer_add( buffer, "serve_count: " ); 
733                         buffer_add( buffer, sbuf ); 
734                         buffer_add( buffer, " | ");
735
736                         buffer_add( buffer, cur_class->server_class );
737                         buffer_add( buffer, " | ");
738
739                         buffer_add( buffer, cur_node->remote_id );
740
741                         buffer_add( buffer, "\n" );
742                         cur_node = cur_node->next;
743
744                 } while( cur_node != start_node );
745
746                 cur_class = cur_class->next;
747
748         }
749
750         info_handler( "Router returning servers query command: %s", buffer->buf );
751
752         transport_message* new_msg; 
753
754         if( buffer->buf == NULL || strlen(buffer->buf) == 0 )
755                 new_msg = message_init( "0", NULL, NULL, msg->sender, NULL );
756         else
757                 new_msg = message_init( buffer->buf, NULL, NULL, msg->sender, NULL );
758
759         client_send_message( router->jabber->t_client, new_msg );
760         message_free( new_msg );
761
762         return 1;
763
764 }
765
766 int router_registrar_free( transport_router_registrar* router_registrar ) {
767         if( router_registrar == NULL ) return 0;
768         jabber_connect_free( router_registrar->jabber );
769
770         /* free the server_class list XXX */
771         while( router_registrar->server_class_list != NULL ) {
772                 remove_server_class(router_registrar, router_registrar->server_class_list);
773         }
774
775         free( router_registrar );
776
777
778
779         return 1;
780 }
781
782
783 int server_class_node_free( server_class_node* node ) {
784         if( node == NULL ) { return 0; }
785         if( node->server_class != NULL ) 
786                 free( node->server_class );
787
788         jabber_connect_free( node->jabber );
789
790         /* just in case, free the list */
791         while( node->current_server_node != NULL ) {
792                 unregister_server_node( node, node->current_server_node->remote_id );
793         }
794         free( node );
795         return 1;
796 }
797
798 int server_node_free( server_node* node ) {
799         if( node == NULL ) { return 0; }
800         message_free( node->last_sent );
801         free( node->remote_id );
802         free( node );
803         return 1;
804 }
805
806 int jabber_connect_free( jabber_connect* jabber ) {
807         if( jabber == NULL ) { return 0; }
808         client_free( jabber->t_client );
809         free( jabber->username );
810         free( jabber->password );
811         free( jabber->resource );
812         free( jabber->server );
813         free( jabber );
814         return 1;
815 }
816
817