tmp = silc_net_create_server(server->config->listen_port->port,
server->config->listen_port->listener_ip);
- if (tmp < 0)
+ if (tmp < 0) {
+ SILC_LOG_ERROR(("Could not create server listener: %s on %d",
+ server->config->listen_port->listener_ip,
+ server->config->listen_port->port));
goto err0;
+ }
sock = silc_realloc(sock, (sizeof(int *) * (sock_count + 1)));
sock[sock_count] = tmp;
silc_ske_free(ctx->ske);
silc_free(ctx->dest_id);
silc_free(ctx);
- if (sock)
- sock->protocol = NULL;
silc_schedule_task_del_by_callback(server->schedule,
silc_server_failure_callback);
silc_server_disconnect_remote(server, sock, "Server closed connection: "
/* Parser callback called by silc_packet_receive_process. This merely
registers timeout that will handle the actual parsing when appropriate. */
-void silc_server_packet_parse(SilcPacketParserContext *parser_context,
+bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
void *context)
{
SilcServer server = (SilcServer)context;
if (idata)
idata->psn_receive = parser_context->packet->sequence + 1;
+ /* If protocol for this connection is key exchange or rekey then we'll
+ process all packets synchronously, since there might be packets in
+ queue that we are not able to decrypt without first processing the
+ packets before them. */
+ if (sock->protocol && sock->protocol->protocol &&
+ (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
+ sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
+ silc_server_packet_parse_real(server->schedule, 0, sock->sock,
+ parser_context);
+
+ /* Reprocess data since we'll return FALSE here. This is because
+ the idata->receive_key might have become valid in the last packet
+ and we want to call this processor with valid cipher. */
+ if (idata)
+ silc_packet_receive_process(sock, server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, idata->receive_key,
+ idata->hmac_receive, idata->psn_receive,
+ silc_server_packet_parse, server);
+ else
+ silc_packet_receive_process(sock, server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, NULL, NULL, 0,
+ silc_server_packet_parse, server);
+ return FALSE;
+ }
+
switch (sock->type) {
case SILC_SOCKET_TYPE_UNKNOWN:
case SILC_SOCKET_TYPE_CLIENT:
break;
case SILC_SOCKET_TYPE_SERVER:
case SILC_SOCKET_TYPE_ROUTER:
- /* Packets from servers are parsed as soon as possible */
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_packet_parse_real,
- (void *)parser_context, 0, 1,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ /* Packets from servers are parsed immediately */
+ silc_server_packet_parse_real(server->schedule, 0, sock->sock,
+ parser_context);
break;
default:
- return;
+ return TRUE;
}
+
+ return TRUE;
}
/* Parses the packet type and calls what ever routines the packet type
break;
case SILC_PACKET_FTP:
- /* Ignored */
+ /* FTP packet */
+ SILC_LOG_DEBUG(("FTP packet"));
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ silc_server_ftp(server, sock, packet);
break;
case SILC_PACKET_RESUME_ROUTER:
void silc_server_close_connection(SilcServer server,
SilcSocketConnection sock)
{
+ if (!server->sockets[sock->sock])
+ return;
+
SILC_LOG_INFO(("Closing connection %s:%d [%s]", sock->hostname,
sock->port,
(sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
silc_schedule_task_del_by_context(server->schedule, channel->rekey);
if (silc_idlist_del_channel(server->local_list, channel))
server->stat.my_channels--;
- else if (silc_idlist_del_channel(server->global_list, channel))
- server->stat.my_channels--;
+ else
+ silc_idlist_del_channel(server->global_list, channel);
continue;
}
SilcChannelClientEntry chl2;
SilcHashTableList htl2;
- channel->id = NULL;
+ channel->disabled = TRUE;
silc_hash_table_list(channel->user_list, &htl2);
while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
/* Remove the channel entry */
if (silc_idlist_del_channel(server->local_list, channel))
server->stat.my_channels--;
- else if (silc_idlist_del_channel(server->global_list, channel))
- server->stat.my_channels--;
+ else
+ silc_idlist_del_channel(server->global_list, channel);
continue;
}
silc_schedule_task_del_by_context(server->schedule, channel->rekey);
if (silc_idlist_del_channel(server->local_list, channel))
server->stat.my_channels--;
- else if (silc_idlist_del_channel(server->global_list, channel))
- server->stat.my_channels--;
+ else
+ silc_idlist_del_channel(server->global_list, channel);
silc_buffer_free(clidp);
return FALSE;
}
SilcChannelClientEntry chl2;
SilcHashTableList htl2;
- channel->id = NULL;
+ channel->disabled = TRUE;
silc_hash_table_list(channel->user_list, &htl2);
while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
/* Remove the channel entry */
if (silc_idlist_del_channel(server->local_list, channel))
server->stat.my_channels--;
- else if (silc_idlist_del_channel(server->global_list, channel))
- server->stat.my_channels--;
+ else
+ silc_idlist_del_channel(server->global_list, channel);
return FALSE;
}