- if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
- (SILC_IS_DISCONNECTED(sock) == FALSE)) {
- server->stat.packets_sent++;
-
- if (sock->outbuf->data - sock->outbuf->head)
- silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
-
- silc_packet_send(sock, TRUE);
-
- SILC_SET_CONNECTION_FOR_INPUT(server->schedule, sock->sock);
- SILC_UNSET_OUTBUF_PENDING(sock);
- silc_buffer_clear(sock->outbuf);
- }
-
- /* Send SIGNOFF notify to routers. */
- if (notify && !server->standalone && server->router)
- silc_server_send_notify_signoff(server, server->router->connection,
- server->server_type == SILC_SERVER ?
- FALSE : TRUE, client->id, signoff);
-
- /* Remove client from all channels */
- if (notify)
- silc_server_remove_from_channels(server, NULL, client,
- TRUE, signoff, TRUE);
- else
- silc_server_remove_from_channels(server, NULL, client,
- FALSE, NULL, FALSE);
-
- /* 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->router = NULL;
- client->connection = NULL;
-
- /* Free the client entry and everything in it */
- server->stat.my_clients--;
- server->stat.clients--;
- if (server->server_type == SILC_ROUTER)
- server->stat.cell_clients--;
-}
-
-/* Frees user_data pointer from socket connection object. This also sends
- appropriate notify packets to the network to inform about leaving
- entities. */
-
-void silc_server_free_sock_user_data(SilcServer server,
- SilcSocketConnection sock)
-{
- SILC_LOG_DEBUG(("Start"));
-
- switch (sock->type) {
- case SILC_SOCKET_TYPE_CLIENT:
- {
- SilcClientEntry user_data = (SilcClientEntry)sock->user_data;
- silc_server_free_client_data(server, sock, user_data, TRUE, NULL);
- break;
- }
- case SILC_SOCKET_TYPE_SERVER:
- case SILC_SOCKET_TYPE_ROUTER:
- {
- SilcServerEntry user_data = (SilcServerEntry)sock->user_data;
-
- /* Free all client entries that this server owns as they will
- become invalid now as well. */
- if (user_data->id)
- silc_server_remove_clients_by_server(server, user_data, TRUE);
-
- /* If this was our primary router connection then we're lost to
- the outside world. */
- if (server->router == user_data) {
- server->id_entry->router = NULL;
- server->router = NULL;
- server->standalone = TRUE;
- }
-
- /* Free the server entry */
- silc_idlist_del_data(user_data);
- silc_idlist_del_server(server->local_list, user_data);
- server->stat.my_servers--;
- server->stat.servers--;
- if (server->server_type == SILC_ROUTER)
- server->stat.cell_servers--;
- break;
- }
- default:
- {
- SilcUnknownEntry user_data = (SilcUnknownEntry)sock->user_data;
-
- silc_idlist_del_data(user_data);
- silc_free(user_data);
- break;
- }
- }
-
- /* If any protocol is active cancel its execution */
- if (sock->protocol) {
- silc_protocol_cancel(sock->protocol, server->schedule);
- sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute_final(sock->protocol, server->schedule);
- sock->protocol = NULL;
- }
-
- sock->user_data = NULL;
-}
-
-/* Removes the client from channels and possibly removes the channels
- as well. After removing those channels that exist, their channel
- keys are regnerated. This is called only by the function
- silc_server_remove_clients_by_server. */
-
-static void silc_server_remove_clients_channels(SilcServer server,
- SilcSocketConnection sock,
- SilcClientEntry client,
- SilcHashTable channels)
-{
- SilcChannelEntry channel;
- SilcChannelClientEntry chl;
- SilcHashTableList htl;
- SilcBuffer clidp;