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