Added SILC Server library.
[silc.git] / lib / silcserver / server.c
1 /*
2
3   server.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2005 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_SEMA_POST(&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_SEMA_POST(&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_sema_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_SEMA_POST(&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_SEMA_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       t = silc_fsm_thread_alloc(fsm, thread, silc_server_thread_packet_dest,
253                                 NULL, FALSE);
254       if (t) {
255         silc_fsm_set_state_context(t, packet);
256         silc_fsm_start_sync(t, silc_server_st_packet_received);
257       }
258     }
259
260     /* Empty the queue */
261     silc_list_init(thread->packet_queue, struct SilcPacketStruct, next);
262
263     thread->new_packet = FALSE;
264     return SILC_FSM_CONTINUE;
265   }
266
267   silc_mutex_lock(thread->server->lock);
268
269   if (thread->new_connection) {
270     /*** Accept new connection */
271     SilcServerAccept ac;
272
273     SILC_LOG_DEBUG(("Processing incoming connections"));
274
275     /* Accept the new connection in own thread */
276     silc_list_start(thread->new_conns);
277     while ((ac = silc_list_get(thread->new_conns)) != SILC_LIST_END) {
278       ac->thread = thread;
279       ac->t = silc_fsm_thread_alloc(&thread->fsm, ac,
280                                     silc_server_accept_connection_dest,
281                                     NULL, FALSE);
282       silc_fsm_start(ac->t, silc_server_st_accept_connection);
283     }
284
285     /* Empty the list */
286     silc_list_init(thread->new_conns, struct SilcServerAcceptStruct, next);
287
288     thread->new_connection = FALSE;
289     silc_mutex_unlock(thread->server->lock);
290     return SILC_FSM_CONTINUE;
291   }
292
293   /* NOT REACHED */
294 #if defined(SILC_DEBUG)
295   assert(FALSE);
296 #endif /* SILC_DEBUG */
297   return SILC_FSM_CONTINUE;
298 }
299
300
301 /*************************** Main server machine ****************************/
302
303 /* The server's main state where we wait for various events */
304
305 SILC_FSM_STATE(silc_server_st_run)
306 {
307   SilcServer server = fsm_context;
308
309   SILC_LOG_DEBUG(("Start"));
310
311   /* Wait for events */
312   SILC_FSM_SEMA_WAIT(&server->wait_event);
313
314   /* Process events */
315
316   if (server->run_callback && server->running) {
317     /* Call running callbcak back to application */
318     server->run_callback = FALSE;
319     server->running(server, server->running_context);
320     return SILC_FSM_CONTINUE;
321   }
322
323   if (server->new_connection) {
324     /** New connection */
325     silc_fsm_next(fsm, silc_server_st_new_connection);
326     return SILC_FSM_CONTINUE;
327   }
328
329   if (server->connect_router) {
330     /** Connect to router(s) */
331     silc_fsm_next(fsm, silc_server_st_connect_router);
332     return SILC_FSM_CONTINUE;
333   }
334
335   if (server->get_statistics) {
336     /** Retrieve statistics */
337     silc_fsm_next(fsm, silc_server_st_get_stats);
338     return SILC_FSM_CONTINUE;
339   }
340
341   if (server->reconfigure) {
342     /** Reconfigure server */
343     silc_fsm_next(fsm, silc_server_st_reconfigure);
344     return SILC_FSM_CONTINUE;
345   }
346
347   if (server->server_shutdown) {
348     /** Shutdown server */
349     silc_fsm_next(fsm, silc_server_st_stop);
350     return SILC_FSM_CONTINUE;
351   }
352
353   /* NOT REACHED */
354 #if defined(SILC_DEBUG)
355   assert(FALSE);
356 #endif /* SILC_DEBUG */
357   return SILC_FSM_CONTINUE;
358 }
359
360 /* New connection received */
361
362 SILC_FSM_STATE(silc_server_st_new_connection)
363 {
364   SilcServer server = fsm_context;
365   SilcServerThread thread;
366   SilcServerAccept ac;
367
368   SILC_LOG_DEBUG(("Process new connections"));
369
370   silc_list_start(server->new_conns);
371   while ((ac = silc_list_get(server->new_conns)) != SILC_LIST_END) {
372
373     /* Find thread where to put this connection */
374     silc_list_start(server->threads);
375     while ((thread = silc_list_get(server->threads)) != SILC_LIST_END) {
376       if (!server->params->use_threads)
377         break;
378       if (thread->num_conns < server->params->connections_per_thread)
379         break;
380     }
381
382     if (!thread) {
383       /** Create new thread */
384       thread = silc_server_new_thread(server);
385       if (!thread) {
386         silc_list_del(server->new_conns, ac);
387         silc_stream_destroy(ac->stream);
388         silc_free(ac);
389         continue;
390       }
391
392       silc_fsm_next(fsm, silc_server_st_wait_new_thread);
393       return SILC_FSM_CONTINUE;
394     }
395
396     silc_list_del(server->new_conns, ac);
397
398     /* Give this connection to this thread */
399     silc_mutex_lock(server->lock);
400     silc_list_add(thread->new_conns, ac);
401     thread->num_conns++;
402
403     SILC_LOG_DEBUG(("Signal thread for new connection"));
404
405     /* Signal the thread for new connection */
406     if (!thread->new_connection) {
407       thread->new_connection = TRUE;
408       SILC_FSM_SEMA_POST(&thread->wait_event);
409     }
410     silc_mutex_unlock(server->lock);
411   }
412
413   server->new_connection = FALSE;
414
415   /** Connections processed */
416   silc_fsm_next(fsm, silc_server_st_run);
417   return SILC_FSM_CONTINUE;
418 }
419
420 /* Wait here until newly created thread is up */
421
422 SILC_FSM_STATE(silc_server_st_wait_new_thread)
423 {
424   SilcServer server = fsm_context;
425
426   /* Wait here until new thread is up */
427   SILC_FSM_SEMA_WAIT(&server->thread_up);
428
429   /** Process new connections */
430   silc_fsm_next(fsm, silc_server_st_new_connection);
431   return SILC_FSM_CONTINUE;
432 }
433
434 /* Stops server */
435
436 SILC_FSM_STATE(silc_server_st_stop)
437 {
438 #if 0
439   SilcServer server = fsm_context;
440
441   SILC_LOG_INFO(("SILC Server shutting down"));
442
443   if (server->schedule) {
444     int i;
445
446     server->server_shutdown = TRUE;
447
448     /* Close all connections */
449     for (i = 0; i < server->config->param.connections_max; i++) {
450       if (!server->sockets[i])
451         continue;
452       if (!SILC_IS_LISTENER(server->sockets[i])) {
453         SilcSocketConnection sock = server->sockets[i];
454         SilcIDListData idata = sock->user_data;
455
456         if (idata)
457           idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
458
459         silc_schedule_task_del_by_context(server->schedule,
460                                           server->sockets[i]);
461         silc_schedule_task_del_by_fd(server->schedule,
462                                      server->sockets[i]->sock);
463         silc_server_disconnect_remote(server, server->sockets[i],
464                                       SILC_STATUS_OK,
465                                       "Server is shutting down");
466         if (server->sockets[i]) {
467           if (sock->user_data)
468             silc_server_free_sock_user_data(server, sock,
469                                             "Server is shutting down");
470           silc_socket_free(sock);
471         }
472       } else {
473         silc_socket_free(server->sockets[i]);
474         server->sockets[i] = NULL;
475         server->stat.conn_num--;
476       }
477     }
478
479     /* We are not connected to network anymore */
480     server->standalone = TRUE;
481
482     silc_schedule_stop(server->schedule);
483     silc_schedule_uninit(server->schedule);
484     server->schedule = NULL;
485
486     silc_free(server->sockets);
487     server->sockets = NULL;
488   }
489
490   silc_server_protocols_unregister();
491 #endif /* 0 */
492
493   /** Wait events */
494   silc_fsm_next(fsm, silc_server_st_run);
495   return SILC_FSM_CONTINUE;
496 }
497
498 /* Reconfigure server */
499
500 SILC_FSM_STATE(silc_server_st_reconfigure)
501 {
502   SilcServer server = fsm_context;
503
504   SILC_LOG_DEBUG(("Reconfiguring server"));
505
506   /** Wait events */
507   server->reconfigure = FALSE;
508   silc_fsm_next(fsm, silc_server_st_run);
509   return SILC_FSM_CONTINUE;
510 }
511
512 /* Get statistics */
513
514 SILC_FSM_STATE(silc_server_st_get_stats)
515 {
516   SilcServer server = fsm_context;
517
518   SILC_LOG_DEBUG(("Getting statistics"));
519
520   /** Wait events */
521   server->get_statistics = FALSE;
522   silc_fsm_next(fsm, silc_server_st_run);
523   return SILC_FSM_CONTINUE;
524 }
525
526
527 /**************************** Public interface ******************************/
528
529 /* Allocates server context and returns it */
530
531 SilcServer silc_server_alloc(void *app_context, SilcServerParams params,
532                              SilcSchedule schedule)
533 {
534   SilcServer server;
535   SilcServerParamInterface iface;
536   SilcBool id_created = FALSE;
537
538   SILC_LOG_DEBUG(("Allocating new server"));
539
540   if (!schedule || !params)
541     return NULL;
542
543   server = silc_calloc(1, sizeof(*server));
544   if (!server)
545     return NULL;
546
547   server->app_context = app_context;
548   server->schedule = schedule;
549   server->params = params;
550   server->server_type = SILC_SERVER;
551   server->standalone = TRUE;
552 #ifdef SILC_SIM
553   server->sim = silc_dlist_init();
554 #endif
555
556 #if defined(SILC_DEBUG)
557   /* Set debugging on if configured */
558   if (params->debug_string) {
559     silc_log_debug(TRUE);
560     silc_log_set_debug_string(params->debug_string);
561   }
562 #endif /* SILC_DEBUG */
563
564   /* Allocate ID caches */
565   server->clients = silc_idcache_alloc(0, SILC_ID_CLIENT,
566                                        silc_server_destructor_client, server);
567   server->servers = silc_idcache_alloc(0, SILC_ID_SERVER,
568                                        silc_server_destructor_server, server);
569   server->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL,
570                                         silc_server_destructor_channel,
571                                         server);
572   if (!server->clients || !server->servers || !server->channels) {
573     SILC_LOG_ERROR(("Could not allocate ID cache"));
574     goto err;
575   }
576
577   /* Allocate key repository */
578   server->repository = silc_skr_alloc(schedule);
579   if (!server->repository) {
580     SILC_LOG_ERROR(("Could not allocate key repository"));
581     goto err;
582   }
583
584   /* Allocate server lock */
585   if (!silc_mutex_alloc(&server->lock)) {
586     SILC_LOG_DEBUG(("Could not allocate server lock"));
587     goto err;
588   }
589
590   /* Init FSM */
591   silc_fsm_init(&server->fsm, server, silc_server_destructor, NULL, schedule);
592
593   /* Init semaphore signallers */
594   silc_fsm_sema_init(&server->wait_event, &server->fsm, 0);
595   silc_fsm_sema_init(&server->thread_up, &server->fsm, 0);
596
597   /* Initialize lists */
598   silc_list_init(server->new_conns, struct SilcServerAcceptStruct, next);
599   silc_list_init(server->command_pool, struct SilcServerCommandStruct, next);
600
601 #if 0
602   /* Register all paramsured ciphers, PKCS and hash functions. */
603   if (!silc_server_params_register_ciphers(server))
604     silc_cipher_register_default();
605   if (!silc_server_params_register_pkcs(server))
606     silc_pkcs_register_default();
607   if (!silc_server_params_register_hashfuncs(server))
608     silc_hash_register_default();
609   if (!silc_server_params_register_hmacs(server))
610     silc_hmac_register_default();
611 #else
612     silc_cipher_register_default();
613     silc_pkcs_register_default();
614     silc_hash_register_default();
615     silc_hmac_register_default();
616 #endif /* 0 */
617
618   /* Initialize random number generator for the server. */
619   server->rng = silc_rng_alloc();
620   if (!server->rng) {
621     SILC_LOG_ERROR(("Could not allocate RNG"));
622     goto err;
623   }
624   silc_rng_init(server->rng);
625   silc_rng_global_init(server->rng);
626
627   /* Initialize hash functions for server to use */
628   silc_hash_alloc("md5", &server->md5hash);
629   silc_hash_alloc("sha1", &server->sha1hash);
630
631   /* Steal public and private key from the params object */
632   server->public_key = server->params->server_info->public_key;
633   server->private_key = server->params->server_info->private_key;
634   server->params->server_info->public_key = NULL;
635   server->params->server_info->private_key = NULL;
636
637   /* Allocate PKCS context for local public and private keys */
638   if (!silc_pkcs_alloc(server->public_key->name, SILC_PKCS_SILC,
639                        &server->pkcs))
640     goto err;
641   silc_pkcs_public_key_set(server->pkcs, server->public_key);
642   silc_pkcs_private_key_set(server->pkcs, server->private_key);
643
644   /* Create network listener(s) */
645   server->listeners = silc_dlist_init();
646   if (!server->listeners)
647     goto err;
648   silc_list_start(params->server_info->interfaces);
649   while ((iface = silc_list_get(params->server_info->interfaces)) !=
650          SILC_LIST_END) {
651
652     if (!id_created) {
653       /* Create a Server ID for the server */
654       if (!silc_server_create_server_id(server, iface->ip, iface->port,
655                                         &server->id)) {
656         SILC_LOG_ERROR(("Could not create Server ID"));
657         goto err;
658       }
659
660       id_created = TRUE;
661     }
662
663     SilcNetServer listener =
664       silc_net_create_server((const char **)&iface->ip, 1, iface->port,
665                              params->require_reverse_lookup,
666                              server->schedule,
667                              silc_server_accept_connection, server);
668     if (!listener) {
669       SILC_LOG_ERROR(("Could not bind %s on %d", iface->ip, iface->port));
670       goto err;
671     }
672
673     silc_dlist_add(server->listeners, listener);
674   }
675
676   /* First, register log files paramsuration for error output */
677   //  silc_server_params_setlogfiles(server);
678
679   /* Init watcher lists */
680   server->watcher_list =
681     silc_hash_table_alloc(1, silc_hash_client_id_hash, NULL,
682                           silc_hash_data_compare, (void *)CLIENTID_HASH_LEN,
683                           NULL, NULL, TRUE);
684   if (!server->watcher_list)
685     goto err;
686 #if 0
687   server->watcher_list_pk =
688     silc_hash_table_alloc(1, silc_hash_public_key, NULL,
689                           silc_hash_public_key_compare, NULL,
690                           NULL, NULL, TRUE);
691   if (!server->watcher_list_pk)
692     goto err;
693 #endif /* 0 */
694
695   server->server_name = server->params->server_info->server_name;
696   server->params->server_info->server_name = NULL;
697
698 #if 0
699   /* If server connections has been paramsured then we must be router as
700      normal server cannot have server connections, only router connections. */
701   if (server->params->servers) {
702     SilcServerParamsServer *ptr = server->params->servers;
703
704     server->server_type = SILC_ROUTER;
705     while (ptr) {
706       if (ptr->backup_router) {
707         server->server_type = SILC_BACKUP_ROUTER;
708         server->backup_router = TRUE;
709         server->id_entry->server_type = SILC_BACKUP_ROUTER;
710         break;
711       }
712       ptr = ptr->next;
713     }
714   }
715 #endif /* 0 */
716
717   if (server->server_type == SILC_ROUTER)
718     server->stat.routers++;
719
720   return server;
721
722  err:
723   return NULL;
724 }
725
726 /* Free's the SILC server context */
727
728 void silc_server_free(SilcServer server)
729 {
730 #if 0
731   SilcIDCacheList list;
732   SilcIDCacheEntry cache;
733
734   if (!server)
735     return;
736
737 #ifdef SILC_SIM
738   {
739     SilcSim sim;
740     silc_dlist_start(server->sim);
741     while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
742       silc_dlist_del(server->sim, sim);
743       silc_sim_close(sim);
744       silc_sim_free(sim);
745     }
746     silc_dlist_uninit(server->sim);
747   }
748 #endif
749
750   silc_server_backup_free(server);
751   silc_server_params_unref(&server->params_ref);
752   if (server->rng)
753     silc_rng_free(server->rng);
754   if (server->pkcs)
755     silc_pkcs_free(server->pkcs);
756   if (server->public_key)
757     silc_pkcs_public_key_free(server->public_key);
758   if (server->private_key)
759     silc_pkcs_private_key_free(server->private_key);
760   if (server->pending_commands)
761     silc_dlist_uninit(server->pending_commands);
762   if (server->id_entry)
763     silc_idlist_del_server(server->local_list, server->id_entry);
764
765   /* Delete all channels */
766   list = NULL;
767   if (silc_idcache_get_all(server->local_list->channels, &list) &&
768       silc_idcache_list_first(list, &cache)) {
769     silc_idlist_del_channel(server->local_list, cache->context);
770     while (silc_idcache_list_next(list, &cache))
771       silc_idlist_del_channel(server->local_list, cache->context);
772   }
773   if (list)
774     silc_idcache_list_free(list);
775   list = NULL;
776   if (silc_idcache_get_all(server->global_list->channels, &list) &&
777       silc_idcache_list_first(list, &cache)) {
778     silc_idlist_del_channel(server->global_list, cache->context);
779     while (silc_idcache_list_next(list, &cache))
780       silc_idlist_del_channel(server->global_list, cache->context);
781   }
782   if (list)
783     silc_idcache_list_free(list);
784
785   if (server->pk_hash)
786     silc_hash_table_free(server->pk_hash);
787
788   /* Delete all clients */
789   list = NULL;
790   if (silc_idcache_get_all(server->local_list->clients, &list) &&
791       silc_idcache_list_first(list, &cache)) {
792     silc_idlist_del_client(server->local_list, cache->context);
793     while (silc_idcache_list_next(list, &cache))
794       silc_idlist_del_client(server->local_list, cache->context);
795   }
796   if (list)
797     silc_idcache_list_free(list);
798   list = NULL;
799   if (silc_idcache_get_all(server->global_list->clients, &list) &&
800       silc_idcache_list_first(list, &cache)) {
801     silc_idlist_del_client(server->global_list, cache->context);
802     while (silc_idcache_list_next(list, &cache))
803       silc_idlist_del_client(server->global_list, cache->context);
804   }
805   if (list)
806     silc_idcache_list_free(list);
807
808
809   /* Delete all servers */
810   list = NULL;
811   if (silc_idcache_get_all(server->local_list->servers, &list) &&
812       silc_idcache_list_first(list, &cache)) {
813     silc_idlist_del_server(server->local_list, cache->context);
814     while (silc_idcache_list_next(list, &cache))
815       silc_idlist_del_server(server->local_list, cache->context);
816   }
817   if (list)
818     silc_idcache_list_free(list);
819   list = NULL;
820   if (silc_idcache_get_all(server->global_list->servers, &list) &&
821       silc_idcache_list_first(list, &cache)) {
822     silc_idlist_del_server(server->global_list, cache->context);
823     while (silc_idcache_list_next(list, &cache))
824       silc_idlist_del_server(server->global_list, cache->context);
825   }
826   if (list)
827     silc_idcache_list_free(list);
828
829 #endif /* 0 */
830
831   silc_idcache_free(server->clients);
832   silc_idcache_free(server->servers);
833   silc_idcache_free(server->channels);
834   silc_hash_table_free(server->watcher_list);
835   silc_hash_table_free(server->watcher_list_pk);
836
837   silc_hash_free(server->md5hash);
838   silc_hash_free(server->sha1hash);
839   silc_hmac_unregister_all();
840   silc_hash_unregister_all();
841   silc_cipher_unregister_all();
842   silc_pkcs_unregister_all();
843 }
844
845 /* Starts the SILC server FSM machine and returns immediately.  The
846    scheduler must be run or be running already when this returns. */
847
848 void silc_server_run(SilcServer server, SilcServerRunning running,
849                      void *running_context)
850 {
851   SILC_LOG_INFO(("Starting SILC server"));
852
853   server->starttime = time(NULL);
854   server->running = running;
855   server->running_context = running_context;
856
857   /* Start the server */
858   silc_fsm_start_sync(&server->fsm, silc_server_st_run);
859
860   /* Signal the application when we are running */
861   server->run_callback = TRUE;
862   SILC_FSM_SEMA_POST(&server->wait_event);
863
864   /* Signal to connect to router */
865   server->connect_router = TRUE;
866   SILC_FSM_SEMA_POST(&server->wait_event);
867
868   /* Start getting statistics from the network on normal server */
869   if (server->server_type != SILC_ROUTER) {
870     server->get_statistics = TRUE;
871     SILC_FSM_SEMA_POST(&server->wait_event);
872   }
873 }
874
875 /* Stops the SILC server */
876
877 void silc_server_stop(SilcServer server, SilcServerStop stopped,
878                       void *stop_context)
879 {
880   SILC_LOG_INFO(("Stopping SILC server"));
881
882   server->stopped = stopped;
883   server->stop_context = stop_context;
884
885   /* Signal that server is going down */
886   server->server_shutdown = TRUE;
887   SILC_FSM_SEMA_POST(&server->wait_event);
888 }
889
890 /* Disconnects remote connection */
891
892 SilcBool silc_server_disconnect(SilcServer server,
893                                 SilcPacketStream stream,
894                                 SilcStatus error,
895                                 const char *error_string)
896 {
897   return TRUE;
898 }