/*
- server.c
+ server.c
Author: Pekka Riikonen <priikone@silcnet.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
void silc_server_free(SilcServer server)
{
+ SilcIDCacheList list;
+ SilcIDCacheEntry cache;
+
if (!server)
return;
}
#endif
+ silc_server_backup_free(server);
silc_server_config_unref(&server->config_ref);
if (server->rng)
silc_rng_free(server->rng);
if (server->id_entry)
silc_idlist_del_server(server->local_list, server->id_entry);
+ /* Delete all channels */
+ list = NULL;
+ if (silc_idcache_get_all(server->local_list->channels, &list) &&
+ silc_idcache_list_first(list, &cache)) {
+ silc_idlist_del_channel(server->local_list, cache->context);
+ while (silc_idcache_list_next(list, &cache))
+ silc_idlist_del_channel(server->local_list, cache->context);
+ }
+ if (list)
+ silc_idcache_list_free(list);
+ list = NULL;
+ if (silc_idcache_get_all(server->global_list->channels, &list) &&
+ silc_idcache_list_first(list, &cache)) {
+ silc_idlist_del_channel(server->global_list, cache->context);
+ while (silc_idcache_list_next(list, &cache))
+ silc_idlist_del_channel(server->global_list, cache->context);
+ }
+ if (list)
+ silc_idcache_list_free(list);
+
+ /* Delete all clients */
+ list = NULL;
+ if (silc_idcache_get_all(server->local_list->clients, &list) &&
+ silc_idcache_list_first(list, &cache)) {
+ silc_idlist_del_client(server->local_list, cache->context);
+ while (silc_idcache_list_next(list, &cache))
+ silc_idlist_del_client(server->local_list, cache->context);
+ }
+ if (list)
+ silc_idcache_list_free(list);
+ list = NULL;
+ if (silc_idcache_get_all(server->global_list->clients, &list) &&
+ silc_idcache_list_first(list, &cache)) {
+ silc_idlist_del_client(server->global_list, cache->context);
+ while (silc_idcache_list_next(list, &cache))
+ silc_idlist_del_client(server->global_list, cache->context);
+ }
+ if (list)
+ silc_idcache_list_free(list);
+
+ /* Delete all servers */
+ list = NULL;
+ if (silc_idcache_get_all(server->local_list->servers, &list) &&
+ silc_idcache_list_first(list, &cache)) {
+ silc_idlist_del_server(server->local_list, cache->context);
+ while (silc_idcache_list_next(list, &cache))
+ silc_idlist_del_server(server->local_list, cache->context);
+ }
+ if (list)
+ silc_idcache_list_free(list);
+ list = NULL;
+ if (silc_idcache_get_all(server->global_list->servers, &list) &&
+ silc_idcache_list_first(list, &cache)) {
+ silc_idlist_del_server(server->global_list, cache->context);
+ while (silc_idcache_list_next(list, &cache))
+ silc_idlist_del_server(server->global_list, cache->context);
+ }
+ if (list)
+ silc_idcache_list_free(list);
+
silc_idcache_free(server->local_list->clients);
silc_idcache_free(server->local_list->servers);
silc_idcache_free(server->local_list->channels);
if (!sock)
return;
- SILC_LOG_INFO(("Closing connection %s:%d [%s]: connection is unconfigured",
+ SILC_LOG_INFO(("Connection %s:%d [%s] is unconfigured",
sock->hostname, sock->port,
(sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
if (!server->sockets[i])
continue;
if (!SILC_IS_LISTENER(server->sockets[i])) {
- SilcIDListData idata = server->sockets[i]->user_data;
+ SilcSocketConnection sock = server->sockets[i];
+ SilcIDListData idata = sock->user_data;
if (idata)
idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
silc_server_disconnect_remote(server, server->sockets[i],
SILC_STATUS_OK,
"Server is shutting down");
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock,
+ "Server is shutting down");
+ silc_socket_free(sock);
} else {
silc_socket_free(server->sockets[i]);
server->sockets[i] = NULL;
SilcServerConfigConnParams *param =
(conn->param ? conn->param : &server->config->param);
+ /* Don't retry if we are shutting down. */
+ if (server->server_shutdown) {
+ silc_server_config_unref(&sconn->conn);
+ silc_free(sconn->remote_host);
+ silc_free(sconn->backup_replace_ip);
+ silc_free(sconn);
+ return;
+ }
+
SILC_LOG_INFO(("Retrying connecting to a router"));
/* Calculate next timeout */
SilcServerConfigRouter *rconn;
int sock;
+ /* Don't connect if we are shutting down. */
+ if (server->server_shutdown) {
+ silc_free(sconn->remote_host);
+ silc_free(sconn->backup_replace_ip);
+ silc_free(sconn);
+ return;
+ }
+
SILC_LOG_INFO(("Connecting to the %s %s on port %d",
(sconn->backup ? "backup router" : "router"),
sconn->remote_host, sconn->remote_port));
SilcServerConnection sconn;
SilcServerConfigRouter *ptr;
+ /* Don't connect if we are shutting down. */
+ if (server->server_shutdown)
+ return;
+
SILC_LOG_DEBUG(("We are %s",
(server->server_type == SILC_SERVER ?
"normal server" : server->server_type == SILC_ROUTER ?
out:
/* Call the completion callback to indicate that we've connected to
the router */
- if (sconn->callback)
+ if (sconn && sconn->callback)
(*sconn->callback)(server, id_entry, sconn->callback_context);
/* Free the temporary connection data context */
ret = silc_packet_parse_special(packet, idata ? idata->receive_key : NULL);
/* If entry is disabled ignore what we got. */
- if (ret != SILC_PACKET_RESUME_ROUTER &&
- idata && idata->status & SILC_IDLIST_STATUS_DISABLED) {
- SILC_LOG_DEBUG(("Connection is disabled"));
- goto out;
- }
- if (ret != SILC_PACKET_HEARTBEAT &&
- idata && idata->status & SILC_IDLIST_STATUS_DISABLED) {
+ if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
+ ret != SILC_PACKET_HEARTBEAT && ret != SILC_PACKET_RESUME_ROUTER &&
+ ret != SILC_PACKET_REKEY && ret != SILC_PACKET_REKEY_DONE) {
SILC_LOG_DEBUG(("Connection is disabled"));
goto out;
}
int notify,
const char *signoff)
{
- FreeClientInternal i = silc_calloc(1, sizeof(*i));
-
SILC_LOG_DEBUG(("Freeing client data"));
#if 1
silc_schedule_task_del_by_context(server->schedule, client);
/* We will not delete the client entry right away. We will take it
- into history (for WHOWAS command) for 5 minutes */
- i->server = server;
- i->client = client;
- silc_schedule_task_add(server->schedule, 0,
- silc_server_free_client_data_timeout,
- (void *)i, 300, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
- client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
- client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
- client->mode = 0;
- client->router = NULL;
- client->connection = NULL;
+ into history (for WHOWAS command) for 5 minutes, unless we're
+ shutting down server. */
+ if (!server->server_shutdown) {
+ FreeClientInternal i = silc_calloc(1, sizeof(*i));
+ i->server = server;
+ i->client = client;
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_free_client_data_timeout,
+ (void *)i, 300, 0,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+ client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
+ client->mode = 0;
+ client->router = NULL;
+ client->connection = NULL;
+ } else {
+ /* Delete directly since we're shutting down server */
+ silc_idlist_del_data(client);
+ silc_idlist_del_client(server->local_list, client);
+ }
}
/* Frees user_data pointer from socket connection object. This also sends
sock->type != SILC_SOCKET_TYPE_ROUTER)
backup_router = NULL;
+ if (server->server_shutdown)
+ backup_router = NULL;
+
/* If this was our primary router connection then we're lost to
the outside world. */
if (server->router == user_data) {
SilcIDCacheEntry cache;
SilcChannelClientEntry chl;
- SILC_LOG_DEBUG(("Start"));
+ SILC_LOG_DEBUG(("Saving %d users on %s channel", user_count,
+ channel->channel_name));
for (i = 0; i < user_count; i++) {
/* Client ID */
if (!client) {
/* If router did not find such Client ID in its lists then this must
be bogus client or some router in the net is buggy. */
- if (server->server_type == SILC_ROUTER) {
+ if (server->server_type != SILC_SERVER) {
silc_free(client_id);
continue;
}