server->id_entry = id_entry;
}
- /* Register the task queues. In SILC we have by default three task queues.
- One task queue for non-timeout tasks which perform different kind of
- I/O on file descriptors, timeout task queue for timeout tasks, and,
- generic non-timeout task queue whose tasks apply to all connections. */
- silc_task_queue_alloc(&server->io_queue, TRUE);
- if (!server->io_queue) {
- goto err0;
- }
- silc_task_queue_alloc(&server->timeout_queue, TRUE);
- if (!server->timeout_queue) {
- goto err1;
- }
- silc_task_queue_alloc(&server->generic_queue, TRUE);
- if (!server->generic_queue) {
- goto err1;
- }
-
/* Register protocols */
silc_server_protocols_register();
- /* Initialize the scheduler */
- silc_schedule_init(&server->io_queue, &server->timeout_queue,
- &server->generic_queue,
- SILC_SERVER_MAX_CONNECTIONS);
+ /* Initialize the scheduler. This will register the task queues as well.
+ In SILC we have by default three task queues. One task queue for
+ non-timeout tasks which perform different kind of I/O on file
+ descriptors, timeout task queue for timeout tasks, and, generic
+ non-timeout task queue whose tasks apply to all connections. */
+ server->schedule = silc_schedule_init(&server->io_queue,
+ &server->timeout_queue,
+ &server->generic_queue,
+ SILC_SERVER_MAX_CONNECTIONS);
+ if (!server->schedule)
+ goto err0;
/* Add the first task to the queue. This is task that is executed by
timeout. It expires as soon as the caller calls silc_server_run. This
/* We are done here, return succesfully */
return TRUE;
- silc_task_queue_free(server->timeout_queue);
- err1:
- silc_task_queue_free(server->io_queue);
err0:
for (i = 0; i < sock_count; i++)
silc_net_close_server(sock[i]);
/* Stop the scheduler, although it might be already stopped. This
doesn't hurt anyone. This removes all the tasks and task queues,
as well. */
- silc_schedule_stop();
- silc_schedule_uninit();
+ silc_schedule_stop(server->schedule);
+ silc_schedule_uninit(server->schedule);
silc_server_protocols_unregister();
/* Start the scheduler, the heart of the SILC server. When this returns
the program will be terminated. */
- silc_schedule();
+ silc_schedule(server->schedule);
}
/* Timeout callback that will be called to retry connecting to remote
later when outgoing data is available. */
SILC_REGISTER_CONNECTION_FOR_IO(sock);
+ SILC_LOG_INFO(("Incoming connection from %s (%s)", newsocket->hostname,
+ newsocket->ip));
+
port = server->sockets[fd]->port; /* Listenning port */
/* Check whether this connection is denied to connect to us. */
port);
if (deny) {
/* The connection is denied */
+ SILC_LOG_INFO(("Connection %s (%s) is denied",
+ newsocket->hostname, newsocket->ip));
silc_server_disconnect_remote(server, newsocket, deny->comment ?
deny->comment :
"Server closed connection: "
/* The connection is allowed */
- SILC_LOG_INFO(("Incoming connection from %s (%s)", newsocket->hostname,
- newsocket->ip));
-
/* Allocate internal context for key exchange protocol. This is
sent as context for the protocol. */
proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
back to only for input. When there is again some outgoing data
available for this connection it will be set for output as well.
This call clears the output setting and sets it only for input. */
- SILC_SET_CONNECTION_FOR_INPUT(fd);
+ SILC_SET_CONNECTION_FOR_INPUT(server->schedule, fd);
SILC_UNSET_OUTBUF_PENDING(sock);
silc_buffer_clear(sock->outbuf);
sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
"Router"), sock->sock));
+ /* If any protocol is active cancel its execution */
+ if (sock->protocol) {
+ silc_protocol_cancel(sock->protocol, server->timeout_queue);
+ sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
+ silc_protocol_execute_final(sock->protocol, server->timeout_queue);
+ sock->protocol = NULL;
+ }
+
/* We won't listen for this connection anymore */
- silc_schedule_unset_listen_fd(sock->sock);
+ silc_schedule_unset_listen_fd(server->schedule, sock->sock);
/* Unregister all tasks */
silc_task_unregister_by_fd(server->io_queue, sock->sock);
silc_packet_send(sock, TRUE);
- SILC_SET_CONNECTION_FOR_INPUT(sock->sock);
+ SILC_SET_CONNECTION_FOR_INPUT(server->schedule, sock->sock);
SILC_UNSET_OUTBUF_PENDING(sock);
silc_buffer_clear(sock->outbuf);
}
SilcBuffer args;
/* Send SERVER_SIGNOFF notify to our primary router */
- if (!server->standalone && server->router) {
+ if (!server->standalone && server->router &&
+ server->router != entry) {
args = silc_argument_payload_encode(1, argv, argv_lens,
argv_types);
silc_server_send_notify_args(server,
SilcIDList id_list,
SilcBuffer *channels,
SilcBuffer *channel_users,
- SilcBuffer *channel_users_modes)
+ SilcBuffer **channel_users_modes,
+ uint32 *channel_users_modes_c,
+ SilcChannelID ***channel_ids)
{
SilcIDCacheList list;
SilcIDCacheEntry id_cache;
uint32 id_len;
uint16 name_len;
int len;
+ int i = *channel_users_modes_c;
SILC_LOG_DEBUG(("Start"));
SILC_STR_END);
silc_buffer_pull(*channels, len);
+ *channel_users_modes = silc_realloc(*channel_users_modes,
+ sizeof(**channel_users_modes) *
+ (i + 1));
+ (*channel_users_modes)[i] = NULL;
+ *channel_ids = silc_realloc(*channel_ids,
+ sizeof(**channel_ids) * (i + 1));
+ (*channel_ids)[i] = NULL;
silc_server_announce_get_channel_users(server, channel,
channel_users,
- channel_users_modes);
-
- silc_free(cid);
+ channel_users_modes[i]);
+ (*channel_ids)[i] = channel->id;
+ i++;
if (!silc_idcache_list_next(list, &id_cache))
break;
}
+
+ *channel_users_modes_c += i;
}
silc_idcache_list_free(list);
void silc_server_announce_channels(SilcServer server)
{
- SilcBuffer channels = NULL, channel_users = NULL, channel_users_modes = NULL;
+ SilcBuffer channels = NULL, channel_users = NULL;
+ SilcBuffer *channel_users_modes = NULL;
+ uint32 channel_users_modes_c = 0;
+ SilcChannelID **channel_ids = NULL;
SILC_LOG_DEBUG(("Announcing channels and channel users"));
/* Get channels and channel users in local list */
silc_server_announce_get_channels(server, server->local_list,
&channels, &channel_users,
- &channel_users_modes);
+ &channel_users_modes,
+ &channel_users_modes_c,
+ &channel_ids);
/* Get channels and channel users in global list */
silc_server_announce_get_channels(server, server->global_list,
&channels, &channel_users,
- &channel_users_modes);
+ &channel_users_modes,
+ &channel_users_modes_c,
+ &channel_ids);
if (channels) {
silc_buffer_push(channels, channels->data - channels->head);
}
if (channel_users_modes) {
- silc_buffer_push(channel_users_modes,
- channel_users_modes->data - channel_users_modes->head);
- SILC_LOG_HEXDUMP(("channel users modes"), channel_users_modes->data,
- channel_users_modes->len);
-
- /* Send the packet */
- silc_server_packet_send(server, server->router->connection,
- SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
- channel_users_modes->data,
- channel_users_modes->len,
- FALSE);
-
- silc_buffer_free(channel_users_modes);
+ int i;
+
+ for (i = 0; i < channel_users_modes_c; i++) {
+ silc_buffer_push(channel_users_modes[i],
+ channel_users_modes[i]->data -
+ channel_users_modes[i]->head);
+ SILC_LOG_HEXDUMP(("channel users modes"), channel_users_modes[i]->data,
+ channel_users_modes[i]->len);
+ silc_server_packet_send_dest(server, server->router->connection,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ channel_ids[i], SILC_ID_CHANNEL,
+ channel_users_modes[i]->data,
+ channel_users_modes[i]->len,
+ FALSE);
+ silc_buffer_free(channel_users_modes[i]);
+ }
+ silc_free(channel_users_modes);
+ silc_free(channel_ids);
}
}