Added SILC Thread Queue API
[crypto.git] / lib / silcserver / server.c
1 /*
2
3   server.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2006 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /*
20  * This is the actual SILC server than handles everything relating to
21  * servicing the SILC connections. This is also a SILC router as a router
22  * is also normal server.
23  */
24 /* $Id$ */
25
26 #include "silc.h"
27 #include "silcserver.h"
28 #include "server_internal.h"
29
30 /************************** Types and definitions ***************************/
31
32
33 /************************ Static utility functions **************************/
34
35 /* Packet engine callback to receive a packet */
36
37 static SilcBool silc_server_packet_receive(SilcPacketEngine engine,
38                                            SilcPacketStream stream,
39                                            SilcPacket packet,
40                                            void *callback_context,
41                                            void *stream_context)
42 {
43   SilcServerThread thread = callback_context;
44   SilcEntryData data = silc_packet_get_context(stream);
45
46   /* Packets we do not handle */
47   switch (packet->type) {
48   case SILC_PACKET_HEARTBEAT:
49   case SILC_PACKET_SUCCESS:
50   case SILC_PACKET_FAILURE:
51   case SILC_PACKET_REJECT:
52   case SILC_PACKET_KEY_EXCHANGE:
53   case SILC_PACKET_KEY_EXCHANGE_1:
54   case SILC_PACKET_KEY_EXCHANGE_2:
55   case SILC_PACKET_REKEY:
56   case SILC_PACKET_REKEY_DONE:
57   case SILC_PACKET_CONNECTION_AUTH:
58   case SILC_PACKET_CONNECTION_AUTH_REQUEST:
59     return FALSE;
60     break;
61   }
62
63   /* Only specific packets can come without source ID present. */
64   if ((!packet->src_id || data->registered == FALSE) &&
65       packet->type != SILC_PACKET_NEW_CLIENT &&
66       packet->type != SILC_PACKET_NEW_SERVER &&
67       packet->type != SILC_PACKET_DISCONNECT)
68     return FALSE;
69
70   /* NEW_CLIENT and NEW_SERVER are accepted only without source ID
71      and for unregistered connection. */
72   if (packet->src_id && (packet->type == SILC_PACKET_NEW_CLIENT ||
73                          packet->type == SILC_PACKET_NEW_SERVER) &&
74       data->registered == TRUE)
75     return FALSE;
76
77   /* Add the packet to packet queue */
78   silc_list_add(thread->packet_queue, packet);
79
80   /* Signal thread that packet has arrived */
81   if (!thread->new_packet) {
82     thread->new_packet = TRUE;
83     SILC_FSM_EVENT_SIGNAL(&thread->wait_event);
84   }
85
86   return TRUE;
87 }
88
89 /* Packet engine callback to indicate end of stream */
90
91 static void silc_server_packet_eos(SilcPacketEngine engine,
92                                    SilcPacketStream stream,
93                                    void *callback_context,
94                                    void *stream_context)
95 {
96   SILC_LOG_DEBUG(("End of stream received"));
97 }
98
99 /* Packet engine callback to indicate error */
100
101 static void silc_server_packet_error(SilcPacketEngine engine,
102                                      SilcPacketStream stream,
103                                      SilcPacketError error,
104                                      void *callback_context,
105                                      void *stream_context)
106 {
107
108 }
109
110 /* Packet stream callbacks */
111 static SilcPacketCallbacks silc_server_stream_cbs =
112 {
113   silc_server_packet_receive,
114   silc_server_packet_eos,
115   silc_server_packet_error
116 };
117
118 /* Server FSM destructor */
119
120 static void silc_server_destructor(SilcFSM fsm, void *fsm_context,
121                                    void *destructor_context)
122 {
123
124 }
125
126 /* Creates new server thread.  Adds to server threads list automatically and
127    starts the thread.  Depending on server configuration the created thread
128    is either FSM thread of real thread. */
129
130 static SilcServerThread silc_server_new_thread(SilcServer server)
131 {
132   SilcServerThread thread;
133
134   SILC_LOG_DEBUG(("Creating new server thread"));
135
136   thread = silc_calloc(1, sizeof(*thread));
137   if (!thread)
138     return NULL;
139
140   thread->server = server;
141   silc_list_init(thread->new_conns, struct SilcServerAcceptStruct, next);
142
143   /* Start packet engine */
144   thread->packet_engine =
145     silc_packet_engine_start(server->rng, server->server_type == SILC_ROUTER,
146                              &silc_server_stream_cbs, thread);
147   if (!thread->packet_engine) {
148     silc_free(thread);
149     return NULL;
150   }
151
152   /* Add to server */
153   silc_list_add(server->threads, thread);
154
155   /* Start the thread */
156   silc_fsm_thread_init(&thread->thread, &server->fsm, thread,
157                        NULL, NULL, server->params->use_threads);
158   silc_fsm_start(&thread->thread, silc_server_thread_st_start);
159
160   /* Allocate data stack.  Its allocation is allowed to fail so we don't
161      check for it. */
162   thread->stack = silc_stack_alloc(0);
163
164   return thread;
165 }
166
167 /* Network listener callback to accept new connections */
168
169 static void silc_server_accept_connection(SilcNetStatus status,
170                                           SilcStream stream, void *context)
171 {
172   SilcServer server = context;
173   SilcServerAccept ac;
174
175   if (status != SILC_NET_OK) {
176     SILC_LOG_ERROR(("Error %d accepting new connection", status));
177     return;
178   }
179
180   ac = silc_calloc(1, sizeof(*ac));
181   if (!ac) {
182     silc_stream_destroy(stream);
183     return;
184   }
185   ac->stream = stream;
186
187   /* Add as new connection */
188   silc_list_add(server->new_conns, ac);
189
190   /* Signal server of new connection */
191   if (!server->new_connection) {
192     server->new_connection = TRUE;
193     SILC_FSM_EVENT_SIGNAL(&server->wait_event);
194   }
195 }
196
197 /* Packet thread destructor */
198
199 static void silc_server_thread_packet_dest(SilcFSM fsm, void *fsm_context,
200                                            void *destructor_context)
201 {
202   silc_fsm_free(fsm);
203 }
204
205
206 /****************************** Server thread *******************************/
207
208 /* Thread's start function.  This may be FSM thread or real system thread,
209    depending on server configuration. */
210
211 SILC_FSM_STATE(silc_server_thread_st_start)
212 {
213   SilcServerThread thread = fsm_context;
214
215   SILC_LOG_DEBUG(("New server thread started"));
216
217   /*** Run thread's machine */
218   silc_fsm_init(&thread->fsm, thread, NULL, NULL, silc_fsm_get_schedule(fsm));
219   silc_fsm_event_init(&thread->wait_event, &thread->fsm, 0);
220   silc_fsm_start_sync(&thread->fsm, silc_server_thread_st_run);
221
222   /* Signal server that we are up */
223   SILC_FSM_EVENT_SIGNAL(&thread->server->thread_up);
224
225   /* Wait here for this thread to finish */
226   return SILC_FSM_WAIT;
227 }
228
229 /* Thread's machine's main state where we wait for various events. */
230
231 SILC_FSM_STATE(silc_server_thread_st_run)
232 {
233   SilcServerThread thread = fsm_context;
234
235   SILC_LOG_DEBUG(("Start"));
236
237   /* Wait for events */
238   SILC_FSM_EVENT_WAIT(&thread->wait_event);
239
240   /* Process events */
241
242   if (thread->new_packet) {
243     /*** Packet received */
244     SilcPacket packet;
245     SilcFSMThread t;
246
247     SILC_LOG_DEBUG(("Processing incoming packets"));
248
249     /* Each packet is processed in FSM thread */
250     silc_list_start(thread->packet_queue);
251     while ((packet = silc_list_get(thread->packet_queue)) != SILC_LIST_END) {
252       /* XXX shouldn't the fsm be &thread->fsm */
253       t = silc_fsm_thread_alloc(fsm, thread, silc_server_thread_packet_dest,
254                                 NULL, FALSE);
255       if (t) {
256         silc_fsm_set_state_context(t, packet);
257         silc_fsm_start_sync(t, silc_server_st_packet_received);
258       }
259     }
260
261     /* Empty the queue */
262     silc_list_init(thread->packet_queue, struct SilcPacketStruct, next);
263
264     thread->new_packet = FALSE;
265     return SILC_FSM_CONTINUE;
266   }
267
268   silc_mutex_lock(thread->server->lock);
269
270   if (thread->new_connection) {
271     /*** Accept new connection */
272     SilcServerAccept ac;
273
274     SILC_LOG_DEBUG(("Processing incoming connections"));
275
276     /* Accept the new connection in own thread */
277     silc_list_start(thread->new_conns);
278     while ((ac = silc_list_get(thread->new_conns)) != SILC_LIST_END) {
279       ac->thread = thread;
280       silc_fsm_thread_init(&ac->t, &thread->fsm, ac,
281                            silc_server_accept_connection_dest,
282                            NULL, FALSE);
283       silc_fsm_start(&ac->t, silc_server_st_accept_connection);
284     }
285
286     /* Empty the list */
287     silc_list_init(thread->new_conns, struct SilcServerAcceptStruct, next);
288
289     thread->new_connection = FALSE;
290     silc_mutex_unlock(thread->server->lock);
291     return SILC_FSM_CONTINUE;
292   }
293
294   /* NOT REACHED */
295 #if defined(SILC_DEBUG)
296   assert(FALSE);
297 #endif /* SILC_DEBUG */
298   return SILC_FSM_CONTINUE;
299 }
300
301
302 /*************************** Main server machine ****************************/
303
304 /* The server's main state where we wait for various events */
305
306 SILC_FSM_STATE(silc_server_st_run)
307 {
308   SilcServer server = fsm_context;
309
310   SILC_LOG_DEBUG(("Start"));
311
312   /* Wait for events */
313   SILC_FSM_EVENT_WAIT(&server->wait_event);
314
315   /* Process events */
316
317   if (server->run_callback && server->running) {
318     /* Call running callbcak back to application */
319     server->run_callback = FALSE;
320     server->running(server, server->running_context);
321     return SILC_FSM_CONTINUE;
322   }
323
324   if (server->new_connection) {
325     /** New connection */
326     silc_fsm_next(fsm, silc_server_st_new_connection);
327     return SILC_FSM_CONTINUE;
328   }
329
330   if (server->connect_router) {
331     /** Connect to router(s) */
332     silc_fsm_next(fsm, silc_server_st_connect_router);
333     return SILC_FSM_CONTINUE;
334   }
335
336   if (server->get_statistics) {
337     /** Retrieve statistics */
338     silc_fsm_next(fsm, silc_server_st_get_stats);
339     return SILC_FSM_CONTINUE;
340   }
341
342   if (server->reconfigure) {
343     /** Reconfigure server */
344     silc_fsm_next(fsm, silc_server_st_reconfigure);
345     return SILC_FSM_CONTINUE;
346   }
347
348   if (server->server_shutdown) {
349     /** Shutdown server */
350     silc_fsm_next(fsm, silc_server_st_stop);
351     return SILC_FSM_CONTINUE;
352   }
353
354   /* NOT REACHED */
355 #if defined(SILC_DEBUG)
356   assert(FALSE);
357 #endif /* SILC_DEBUG */
358   return SILC_FSM_CONTINUE;
359 }
360
361 /* New connection received */
362
363 SILC_FSM_STATE(silc_server_st_new_connection)
364 {
365   SilcServer server = fsm_context;
366   SilcServerThread thread;
367   SilcServerAccept ac;
368
369   SILC_LOG_DEBUG(("Process new connections"));
370
371   silc_list_start(server->new_conns);
372   while ((ac = silc_list_get(server->new_conns)) != SILC_LIST_END) {
373
374     /* Find thread where to put this connection */
375     silc_list_start(server->threads);
376     while ((thread = silc_list_get(server->threads)) != SILC_LIST_END) {
377       if (!server->params->use_threads)
378         break;
379       if (thread->num_conns < server->params->connections_per_thread)
380         break;
381     }
382
383     if (!thread) {
384       /** Create new thread */
385       thread = silc_server_new_thread(server);
386       if (!thread) {
387         silc_list_del(server->new_conns, ac);
388         silc_stream_destroy(ac->stream);
389         silc_free(ac);
390         continue;
391       }
392
393       silc_fsm_next(fsm, silc_server_st_wait_new_thread);
394       return SILC_FSM_CONTINUE;
395     }
396
397     silc_list_del(server->new_conns, ac);
398
399     /* Give this connection to this thread */
400     silc_mutex_lock(server->lock);
401     silc_list_add(thread->new_conns, ac);
402     thread->num_conns++;
403
404     SILC_LOG_DEBUG(("Signal thread for new connection"));
405
406     /* Signal the thread for new connection */
407     if (!thread->new_connection) {
408       thread->new_connection = TRUE;
409       SILC_FSM_EVENT_SIGNAL(&thread->wait_event);
410     }
411     silc_mutex_unlock(server->lock);
412   }
413
414   server->new_connection = FALSE;
415
416   /** Connections processed */
417   silc_fsm_next(fsm, silc_server_st_run);
418   return SILC_FSM_CONTINUE;
419 }
420
421 /* Wait here until newly created thread is up */
422
423 SILC_FSM_STATE(silc_server_st_wait_new_thread)
424 {
425   SilcServer server = fsm_context;
426
427   /* Wait here until new thread is up */
428   SILC_FSM_EVENT_WAIT(&server->thread_up);
429
430   /** Process new connections */
431   silc_fsm_next(fsm, silc_server_st_new_connection);
432   return SILC_FSM_CONTINUE;
433 }
434
435 /* Stops server */
436
437 SILC_FSM_STATE(silc_server_st_stop)
438 {
439 #if 0
440   SilcServer server = fsm_context;
441
442   SILC_LOG_INFO(("SILC Server shutting down"));
443
444   if (server->schedule) {
445     int i;
446
447     server->server_shutdown = TRUE;
448
449     /* Close all connections */
450     for (i = 0; i < server->config->param.connections_max; i++) {
451       if (!server->sockets[i])
452         continue;
453       if (!SILC_IS_LISTENER(server->sockets[i])) {
454         SilcSocketConnection sock = server->sockets[i];
455         SilcIDListData idata = sock->user_data;
456
457         if (idata)
458           idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
459
460         silc_schedule_task_del_by_context(server->schedule,
461                                           server->sockets[i]);
462         silc_schedule_task_del_by_fd(server->schedule,
463                                      server->sockets[i]->sock);
464         silc_server_disconnect_remote(server, server->sockets[i],
465                                       SILC_STATUS_OK,
466                                       "Server is shutting down");
467         if (server->sockets[i]) {
468           if (sock->user_data)
469             silc_server_free_sock_user_data(server, sock,
470                                             "Server is shutting down");
471           silc_socket_free(sock);
472         }
473       } else {
474         silc_socket_free(server->sockets[i]);
475         server->sockets[i] = NULL;
476         server->stat.conn_num--;
477       }
478     }
479
480     /* We are not connected to network anymore */
481     server->standalone = TRUE;
482
483     silc_schedule_stop(server->schedule);
484     silc_schedule_uninit(server->schedule);
485     server->schedule = NULL;
486
487     silc_free(server->sockets);
488     server->sockets = NULL;
489   }
490
491   silc_server_protocols_unregister();
492 #endif /* 0 */
493
494   /** Wait events */
495   silc_fsm_next(fsm, silc_server_st_run);
496   return SILC_FSM_CONTINUE;
497 }
498
499 /* Reconfigure server */
500
501 SILC_FSM_STATE(silc_server_st_reconfigure)
502 {
503   SilcServer server = fsm_context;
504
505   SILC_LOG_DEBUG(("Reconfiguring server"));
506
507   /** Wait events */
508   server->reconfigure = FALSE;
509   silc_fsm_next(fsm, silc_server_st_run);
510   return SILC_FSM_CONTINUE;
511 }
512
513 /* Get statistics */
514
515 SILC_FSM_STATE(silc_server_st_get_stats)
516 {
517   SilcServer server = fsm_context;
518
519   SILC_LOG_DEBUG(("Getting statistics"));
520
521   /** Wait events */
522   server->get_statistics = FALSE;
523   silc_fsm_next(fsm, silc_server_st_run);
524   return SILC_FSM_CONTINUE;
525 }
526
527
528 /**************************** Public interface ******************************/
529
530 /* Allocates server context and returns it */
531
532 SilcServer silc_server_alloc(void *app_context, SilcServerParams params,
533                              SilcSchedule schedule)
534 {
535   SilcServer server;
536   SilcServerParamInterface iface;
537   SilcBool id_created = FALSE;
538
539   SILC_LOG_DEBUG(("Allocating new server"));
540
541   if (!schedule || !params)
542     return NULL;
543
544   server = silc_calloc(1, sizeof(*server));
545   if (!server)
546     return NULL;
547
548   server->app_context = app_context;
549   server->schedule = schedule;
550   server->params = params;
551   server->server_type = SILC_SERVER;
552   server->standalone = TRUE;
553 #ifdef SILC_SIM
554   server->sim = silc_dlist_init();
555 #endif
556
557 #if defined(SILC_DEBUG)
558   /* Set debugging on if configured */
559   if (params->debug_string) {
560     silc_log_debug(TRUE);
561     silc_log_set_debug_string(params->debug_string);
562   }
563 #endif /* SILC_DEBUG */
564
565   /* Allocate ID caches */
566   server->clients = silc_idcache_alloc(0, SILC_ID_CLIENT,
567                                        silc_server_destructor_client, server);
568   server->servers = silc_idcache_alloc(0, SILC_ID_SERVER,
569                                        silc_server_destructor_server, server);
570   server->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL,
571                                         silc_server_destructor_channel,
572                                         server);
573   if (!server->clients || !server->servers || !server->channels) {
574     SILC_LOG_ERROR(("Could not allocate ID cache"));
575     goto err;
576   }
577
578   /* Allocate key repository */
579   server->repository = silc_skr_alloc(schedule);
580   if (!server->repository) {
581     SILC_LOG_ERROR(("Could not allocate key repository"));
582     goto err;
583   }
584
585   /* Allocate server lock */
586   if (!silc_mutex_alloc(&server->lock)) {
587     SILC_LOG_DEBUG(("Could not allocate server lock"));
588     goto err;
589   }
590
591   /* Init FSM */
592   silc_fsm_init(&server->fsm, server, silc_server_destructor, NULL, schedule);
593
594   /* Init semaphore signallers */
595   silc_fsm_event_init(&server->wait_event, &server->fsm, 0);
596   silc_fsm_event_init(&server->thread_up, &server->fsm, 0);
597
598   /* Initialize lists */
599   silc_list_init(server->new_conns, struct SilcServerAcceptStruct, next);
600   silc_list_init(server->command_pool, struct SilcServerCommandStruct, next);
601
602 #if 0
603   /* Register all paramsured ciphers, PKCS and hash functions. */
604   if (!silc_server_params_register_ciphers(server))
605     silc_cipher_register_default();
606   if (!silc_server_params_register_pkcs(server))
607     silc_pkcs_register_default();
608   if (!silc_server_params_register_hashfuncs(server))
609     silc_hash_register_default();
610   if (!silc_server_params_register_hmacs(server))
611     silc_hmac_register_default();
612 #else
613     silc_cipher_register_default();
614     silc_pkcs_register_default();
615     silc_hash_register_default();
616     silc_hmac_register_default();
617 #endif /* 0 */
618
619   /* Initialize random number generator for the server. */
620   server->rng = silc_rng_alloc();
621   if (!server->rng) {
622     SILC_LOG_ERROR(("Could not allocate RNG"));
623     goto err;
624   }
625   silc_rng_init(server->rng);
626   silc_rng_global_init(server->rng);
627
628   /* Initialize hash functions for server to use */
629   silc_hash_alloc("md5", &server->md5hash);
630   silc_hash_alloc("sha1", &server->sha1hash);
631
632   /* Steal public and private key from the params object */
633   server->public_key = server->params->server_info->public_key;
634   server->private_key = server->params->server_info->private_key;
635   server->params->server_info->public_key = NULL;
636   server->params->server_info->private_key = NULL;
637
638   /* Create network listener(s) */
639   server->listeners = silc_dlist_init();
640   if (!server->listeners)
641     goto err;
642   silc_list_start(params->server_info->interfaces);
643   while ((iface = silc_list_get(params->server_info->interfaces)) !=
644          SILC_LIST_END) {
645
646     if (!id_created) {
647       /* Create a Server ID for the server */
648       if (!silc_server_create_server_id(server, iface->ip, iface->port,
649                                         &server->id)) {
650         SILC_LOG_ERROR(("Could not create Server ID"));
651         goto err;
652       }
653
654       id_created = TRUE;
655     }
656
657     SilcNetServer listener =
658       silc_net_create_server((const char **)&iface->ip, 1, iface->port,
659                              params->require_reverse_lookup,
660                              server->schedule,
661                              silc_server_accept_connection, server);
662     if (!listener) {
663       SILC_LOG_ERROR(("Could not bind %s on %d", iface->ip, iface->port));
664       goto err;
665     }
666
667     silc_dlist_add(server->listeners, listener);
668   }
669
670   /* First, register log files paramsuration for error output */
671   //  silc_server_params_setlogfiles(server);
672
673   /* Init watcher lists */
674   server->watcher_list =
675     silc_hash_table_alloc(1, silc_hash_client_id_hash, NULL,
676                           silc_hash_data_compare, (void *)CLIENTID_HASH_LEN,
677                           NULL, NULL, TRUE);
678   if (!server->watcher_list)
679     goto err;
680 #if 0
681   server->watcher_list_pk =
682     silc_hash_table_alloc(1, silc_hash_public_key, NULL,
683                           silc_hash_public_key_compare, NULL,
684                           NULL, NULL, TRUE);
685   if (!server->watcher_list_pk)
686     goto err;
687 #endif /* 0 */
688
689   server->server_name = server->params->server_info->server_name;
690   server->params->server_info->server_name = NULL;
691
692 #if 0
693   /* If server connections has been paramsured then we must be router as
694      normal server cannot have server connections, only router connections. */
695   if (server->params->servers) {
696     SilcServerParamsServer *ptr = server->params->servers;
697
698     server->server_type = SILC_ROUTER;
699     while (ptr) {
700       if (ptr->backup_router) {
701         server->server_type = SILC_BACKUP_ROUTER;
702         server->backup_router = TRUE;
703         server->id_entry->server_type = SILC_BACKUP_ROUTER;
704         break;
705       }
706       ptr = ptr->next;
707     }
708   }
709 #endif /* 0 */
710
711   if (server->server_type == SILC_ROUTER)
712     server->stat.routers++;
713
714   return server;
715
716  err:
717   return NULL;
718 }
719
720 /* Free's the SILC server context */
721
722 void silc_server_free(SilcServer server)
723 {
724 #if 0
725   SilcIDCacheList list;
726   SilcIDCacheEntry cache;
727
728   if (!server)
729     return;
730
731 #ifdef SILC_SIM
732   {
733     SilcSim sim;
734     silc_dlist_start(server->sim);
735     while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
736       silc_dlist_del(server->sim, sim);
737       silc_sim_close(sim);
738       silc_sim_free(sim);
739     }
740     silc_dlist_uninit(server->sim);
741   }
742 #endif
743
744   silc_server_backup_free(server);
745   silc_server_params_unref(&server->params_ref);
746   if (server->rng)
747     silc_rng_free(server->rng);
748   if (server->pkcs)
749     silc_pkcs_free(server->pkcs);
750   if (server->public_key)
751     silc_pkcs_public_key_free(server->public_key);
752   if (server->private_key)
753     silc_pkcs_private_key_free(server->private_key);
754   if (server->pending_commands)
755     silc_dlist_uninit(server->pending_commands);
756   if (server->id_entry)
757     silc_idlist_del_server(server->local_list, server->id_entry);
758
759   /* Delete all channels */
760   list = NULL;
761   if (silc_idcache_get_all(server->local_list->channels, &list) &&
762       silc_idcache_list_first(list, &cache)) {
763     silc_idlist_del_channel(server->local_list, cache->context);
764     while (silc_idcache_list_next(list, &cache))
765       silc_idlist_del_channel(server->local_list, cache->context);
766   }
767   if (list)
768     silc_idcache_list_free(list);
769   list = NULL;
770   if (silc_idcache_get_all(server->global_list->channels, &list) &&
771       silc_idcache_list_first(list, &cache)) {
772     silc_idlist_del_channel(server->global_list, cache->context);
773     while (silc_idcache_list_next(list, &cache))
774       silc_idlist_del_channel(server->global_list, cache->context);
775   }
776   if (list)
777     silc_idcache_list_free(list);
778
779   if (server->pk_hash)
780     silc_hash_table_free(server->pk_hash);
781
782   /* Delete all clients */
783   list = NULL;
784   if (silc_idcache_get_all(server->local_list->clients, &list) &&
785       silc_idcache_list_first(list, &cache)) {
786     silc_idlist_del_client(server->local_list, cache->context);
787     while (silc_idcache_list_next(list, &cache))
788       silc_idlist_del_client(server->local_list, cache->context);
789   }
790   if (list)
791     silc_idcache_list_free(list);
792   list = NULL;
793   if (silc_idcache_get_all(server->global_list->clients, &list) &&
794       silc_idcache_list_first(list, &cache)) {
795     silc_idlist_del_client(server->global_list, cache->context);
796     while (silc_idcache_list_next(list, &cache))
797       silc_idlist_del_client(server->global_list, cache->context);
798   }
799   if (list)
800     silc_idcache_list_free(list);
801
802
803   /* Delete all servers */
804   list = NULL;
805   if (silc_idcache_get_all(server->local_list->servers, &list) &&
806       silc_idcache_list_first(list, &cache)) {
807     silc_idlist_del_server(server->local_list, cache->context);
808     while (silc_idcache_list_next(list, &cache))
809       silc_idlist_del_server(server->local_list, cache->context);
810   }
811   if (list)
812     silc_idcache_list_free(list);
813   list = NULL;
814   if (silc_idcache_get_all(server->global_list->servers, &list) &&
815       silc_idcache_list_first(list, &cache)) {
816     silc_idlist_del_server(server->global_list, cache->context);
817     while (silc_idcache_list_next(list, &cache))
818       silc_idlist_del_server(server->global_list, cache->context);
819   }
820   if (list)
821     silc_idcache_list_free(list);
822
823 #endif /* 0 */
824
825   silc_idcache_free(server->clients);
826   silc_idcache_free(server->servers);
827   silc_idcache_free(server->channels);
828   silc_hash_table_free(server->watcher_list);
829   silc_hash_table_free(server->watcher_list_pk);
830
831   silc_hash_free(server->md5hash);
832   silc_hash_free(server->sha1hash);
833   silc_hmac_unregister_all();
834   silc_hash_unregister_all();
835   silc_cipher_unregister_all();
836   silc_pkcs_unregister_all();
837 }
838
839 /* Starts the SILC server FSM machine and returns immediately.  The
840    scheduler must be run or be running already when this returns. */
841
842 void silc_server_run(SilcServer server, SilcServerRunning running,
843                      void *running_context)
844 {
845   SILC_LOG_INFO(("Starting SILC server"));
846
847   server->starttime = time(NULL);
848   server->running = running;
849   server->running_context = running_context;
850
851   /* Start the server */
852   silc_fsm_start_sync(&server->fsm, silc_server_st_run);
853
854   /* Signal the application when we are running */
855   server->run_callback = TRUE;
856   SILC_FSM_EVENT_SIGNAL(&server->wait_event);
857
858   /* Signal to connect to router */
859   server->connect_router = TRUE;
860   SILC_FSM_EVENT_SIGNAL(&server->wait_event);
861
862   /* Start getting statistics from the network on normal server */
863   if (server->server_type != SILC_ROUTER) {
864     server->get_statistics = TRUE;
865     SILC_FSM_EVENT_SIGNAL(&server->wait_event);
866   }
867 }
868
869 /* Stops the SILC server */
870
871 void silc_server_stop(SilcServer server, SilcServerStop stopped,
872                       void *stop_context)
873 {
874   SILC_LOG_INFO(("Stopping SILC server"));
875
876   server->stopped = stopped;
877   server->stop_context = stop_context;
878
879   /* Signal that server is going down */
880   server->server_shutdown = TRUE;
881   SILC_FSM_EVENT_SIGNAL(&server->wait_event);
882 }
883
884 /* Disconnects remote connection */
885
886 SilcBool silc_server_disconnect(SilcServer server,
887                                 SilcPacketStream stream,
888                                 SilcStatus error,
889                                 const char *error_string)
890 {
891   return TRUE;
892 }