return ctx;
}
+/* Timeout for pending command. If reply to pending command never arrives
+ this is called to free resources. */
+
+SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
+{
+ SilcServer server = app_context;
+ SilcServerCommandPending *reply = context;
+ SilcServerCommandReplyContext cmdr;
+ SilcBuffer tmpreply;
+ int i;
+
+ SILC_LOG_DEBUG(("Timeout pending command"));
+
+ /* Allocate temporary and bogus command reply context */
+ cmdr = silc_calloc(1, sizeof(*cmdr));
+ cmdr->server = server;
+ cmdr->ident = reply->ident;
+
+ /* Check for pending commands and mark to be exeucted */
+ cmdr->callbacks =
+ silc_server_command_pending_check(server, reply->reply_cmd,
+ reply->ident, &cmdr->callbacks_count);
+
+ /* Create bogus command reply with an error inside */
+ tmpreply =
+ silc_command_reply_payload_encode_va(reply->reply_cmd,
+ SILC_STATUS_ERR_TIMEDOUT, 0,
+ reply->ident, 0);
+ cmdr->payload = silc_command_payload_parse(tmpreply->data, tmpreply->len);
+ silc_buffer_free(tmpreply);
+
+ /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
+ for (i = 0; i < cmdr->callbacks_count; i++)
+ if (cmdr->callbacks[i].callback)
+ (*cmdr->callbacks[i].callback)(cmdr->callbacks[i].context, cmdr);
+
+ silc_server_command_pending_del(server, reply->reply_cmd, reply->ident);
+ silc_server_command_reply_free(cmdr);
+}
+
/* Add new pending command to be executed when reply to a command has been
received. The `reply_cmd' is the command that will call the `callback'
with `context' when reply has been received. It can be SILC_COMMAND_NONE
SilcUInt16 ident,
SilcCommandCb callback,
void *context)
+{
+ return silc_server_command_pending_timed(server, reply_cmd, ident, callback,
+ context, 0);
+}
+
+/* Same as silc_server_command_pending with specific timeout for pending
+ commands. If the `timeout' is zero default timeout is used. */
+
+bool silc_server_command_pending_timed(SilcServer server,
+ SilcCommand reply_cmd,
+ SilcUInt16 ident,
+ SilcCommandCb callback,
+ void *context,
+ SilcUInt16 timeout)
{
SilcServerCommandPending *reply;
reply->ident = ident;
reply->context = context;
reply->callback = callback;
+ reply->timeout =
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_command_pending_timeout, reply,
+ timeout ? timeout : 10, 0,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
silc_dlist_add(server->pending_commands, reply);
return TRUE;
r->reply_check))
&& r->ident == ident) {
silc_dlist_del(server->pending_commands, r);
+ if (r->timeout)
+ silc_schedule_task_del(server->schedule, r->timeout);
silc_free(r);
}
}
SilcServerCommandPendingCallbacks
silc_server_command_pending_check(SilcServer server,
- SilcServerCommandReplyContext ctx,
SilcCommand command,
SilcUInt16 ident,
SilcUInt32 *callbacks_count)
callbacks[i].context = r->context;
callbacks[i].callback = r->callback;
r->reply_check = TRUE;
- ctx->ident = ident;
i++;
}
}
SilcBuffer buffer;
/* Send the same command reply payload */
+ silc_command_set_command(cmdr->payload, silc_command_get(cmd->payload));
silc_command_set_ident(cmdr->payload,
silc_command_get_ident(cmd->payload));
buffer = silc_command_payload_encode_payload(cmdr->payload);
char **server_name,
int *count,
ResolveError *error_client,
- SilcUInt32 *error_client_count)
+ SilcUInt32 *error_client_count,
+ SilcDList *attrs)
{
unsigned char *tmp;
SilcUInt32 len;
else
*count = 0;
+ /* Get requested attributes if set */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+ if (tmp && attrs)
+ *attrs = silc_attribute_payload_parse_list(tmp, len);
+
return TRUE;
}
/* Resolve context used by both WHOIS and IDENTIFY commands */
typedef struct {
- SilcServerEntry router;
+ SilcSocketConnection sock;
SilcUInt16 ident;
unsigned char **res_argv;
SilcUInt32 *res_argv_lens;
SilcUInt32 *res_argv_types;
SilcUInt32 res_argc;
+ SilcUInt32 res_timeout;
} *SilcServerResolveContext;
static bool
silc_server_command_whois_check(SilcServerCommandContext cmd,
SilcClientEntry *clients,
- SilcUInt32 clients_count)
+ SilcUInt32 clients_count,
+ SilcDList attrs)
{
SilcServer server = cmd->server;
SilcClientEntry entry;
if (!entry)
continue;
- if ((entry->nickname && entry->username && entry->userinfo) ||
- !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
- if (!entry->router)
- continue;
-
- /* If we are normal server, and we've not resolved this client from
- router and it is global client, we'll check whether it is on some
- channel. If not then we cannot be sure about its validity, and
- we'll resolve it from router. */
- if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
- entry->connection || silc_hash_table_count(entry->channels))
- continue;
+ /* If requested attributes is set then we always resolve the client
+ information, if not then check whether the entry is complete or not
+ and decide whether we need to resolve or not. Usually attributes
+ are not present so the this test is performed all the time. */
+ if (!attrs) {
+ if ((entry->nickname && entry->username && entry->userinfo) ||
+ !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
+ if (!entry->router)
+ continue;
+
+ /* If we are normal server, and we've not resolved this client from
+ router and it is global client, we'll check whether it is on some
+ channel. If not then we cannot be sure about its validity, and
+ we'll resolve it from router. */
+ if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
+ entry->connection || silc_hash_table_count(entry->channels))
+ continue;
+ }
}
+ /* When requested attributes is present and local client is detached
+ we cannot send the command to the client, we'll reply on behalf of
+ the client instead. */
+ if (attrs && SILC_IS_LOCAL(entry) && entry->mode & SILC_UMODE_DETACHED)
+ continue;
+
/* We need to resolve this entry since it is not complete */
if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
/* The entry is being resolved (and we are not the resolver) so attach
to the command reply and we're done with this one. */
- silc_server_command_pending(server, SILC_COMMAND_NONE,
+ silc_server_command_pending(server, SILC_COMMAND_NONE,
entry->resolve_cmd_ident,
silc_server_command_whois,
silc_server_command_dup(cmd));
no_res = FALSE;
} else {
+ SilcBuffer idp;
+ SilcSocketConnection sock;
+
if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
/* We've resolved this and it still is not ready. We'll return
and are that this will be handled again after it is resolved. */
}
silc_free(resolve);
return FALSE;
- } else {
- /* We'll resolve this client */
- SilcBuffer idp;
+ }
- r = NULL;
- for (k = 0; k < resolve_count; k++) {
- if (resolve[k].router == entry->router) {
- r = &resolve[k];
- break;
- }
- }
+ /* We'll resolve this client now */
- if (!r) {
- resolve = silc_realloc(resolve, sizeof(*resolve) *
- (resolve_count + 1));
- r = &resolve[resolve_count];
- memset(r, 0, sizeof(*r));
- r->router = entry->router;
- r->ident = ++server->cmd_ident;
- resolve_count++;
+ sock = (SILC_IS_LOCAL(entry) ? entry->connection :
+ entry->router->connection);
+ if (!sock)
+ continue;
+
+ r = NULL;
+ for (k = 0; k < resolve_count; k++) {
+ if (resolve[k].sock == sock) {
+ r = &resolve[k];
+ break;
}
+ }
+
+ if (!r) {
+ resolve = silc_realloc(resolve, sizeof(*resolve) *
+ (resolve_count + 1));
+ r = &resolve[resolve_count];
+ memset(r, 0, sizeof(*r));
+ r->sock = sock;
+ r->ident = ++server->cmd_ident;
+ if (SILC_IS_LOCAL(entry))
+ r->res_timeout = 2;
+ else
+ r->res_timeout = 0;
+ resolve_count++;
+ }
+
+ r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
+ (r->res_argc + 1));
+ r->res_argv_lens = silc_realloc(r->res_argv_lens,
+ sizeof(*r->res_argv_lens) *
+ (r->res_argc + 1));
+ r->res_argv_types = silc_realloc(r->res_argv_types,
+ sizeof(*r->res_argv_types) *
+ (r->res_argc + 1));
+ idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
+ r->res_argv[r->res_argc] = silc_calloc(idp->len,
+ sizeof(**r->res_argv));
+ memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
+ r->res_argv_lens[r->res_argc] = idp->len;
+ r->res_argv_types[r->res_argc] = r->res_argc + 4;
+ r->res_argc++;
+ silc_buffer_free(idp);
+ entry->resolve_cmd_ident = r->ident;
+ entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
+ entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
+ }
+ }
+
+ /* Do the resolving */
+ for (i = 0; i < resolve_count; i++) {
+ SilcBuffer res_cmd;
+ unsigned char *attrs_buf;
+ SilcUInt32 attrs_buf_len;
+
+ r = &resolve[i];
+
+ /* If attributes were present put them to this resolving as well */
+ if (attrs) {
+ attrs_buf = silc_argument_get_arg_type(cmd->args, 3, &attrs_buf_len);
+ if (attrs_buf) {
r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
(r->res_argc + 1));
r->res_argv_lens = silc_realloc(r->res_argv_lens,
r->res_argv_types = silc_realloc(r->res_argv_types,
sizeof(*r->res_argv_types) *
(r->res_argc + 1));
- idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
- r->res_argv[r->res_argc] = silc_calloc(idp->len,
- sizeof(**r->res_argv));
- memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
- r->res_argv_lens[r->res_argc] = idp->len;
- r->res_argv_types[r->res_argc] = r->res_argc + 4;
+ r->res_argv[r->res_argc] = silc_memdup(attrs_buf, attrs_buf_len);
+ r->res_argv_lens[r->res_argc] = attrs_buf_len;
+ r->res_argv_types[r->res_argc] = 3;
r->res_argc++;
- silc_buffer_free(idp);
-
- entry->resolve_cmd_ident = r->ident;
- entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
- entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
}
}
- }
- /* Do the resolving */
- for (i = 0; i < resolve_count; i++) {
- SilcBuffer res_cmd;
-
- r = &resolve[i];
-
- /* Send WHOIS request. We send WHOIS since we're doing the requesting
- now anyway so make it a good one. */
+ /* Send WHOIS command */
res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
r->res_argc, r->res_argv,
r->res_argv_lens,
r->res_argv_types,
r->ident);
- silc_server_packet_send(server, r->router->connection,
- SILC_PACKET_COMMAND, cmd->packet->flags,
- res_cmd->data, res_cmd->len, FALSE);
+ silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND,
+ cmd->packet->flags, res_cmd->data,
+ res_cmd->len, FALSE);
/* Reprocess this packet after received reply */
- silc_server_command_pending(server, SILC_COMMAND_WHOIS,
- r->ident,
- silc_server_command_whois,
- silc_server_command_dup(cmd));
+ silc_server_command_pending_timed(server, SILC_COMMAND_WHOIS, r->ident,
+ silc_server_command_whois,
+ silc_server_command_dup(cmd),
+ r->res_timeout);
cmd->pending = TRUE;
silc_buffer_free(res_cmd);
SilcClientID **client_id = NULL;
SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
ResolveError error_client = NULL;
+ SilcDList attrs = NULL;
int i, ret = 0;
bool check_global = FALSE;
/* Parse the whois request */
- if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
+ if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
&nick, &server_name, &count,
- &error_client, &error_client_count))
+ &error_client, &error_client_count,
+ &attrs))
return 0;
/* Send the WHOIS request to the router only if it included nickname.
if (client_id_count) {
/* Check all Client ID's received in the command packet */
for (i = 0; i < client_id_count; i++) {
- entry = silc_idlist_find_client_by_id(server->local_list,
+ entry = silc_idlist_find_client_by_id(server->local_list,
client_id[i], TRUE, NULL);
if (!entry && check_global)
- entry = silc_idlist_find_client_by_id(server->global_list,
+ entry = silc_idlist_find_client_by_id(server->global_list,
client_id[i], TRUE, NULL);
if (entry) {
- clients = silc_realloc(clients, sizeof(*clients) *
+ clients = silc_realloc(clients, sizeof(*clients) *
(clients_count + 1));
clients[clients_count++] = entry;
} else {
/* If we are normal server and did not send the request first to router
do it now, since we do not have the Client ID information. */
if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
- server->server_type == SILC_SERVER && !cmd->pending &&
+ server->server_type == SILC_SERVER && !cmd->pending &&
!server->standalone) {
silc_server_command_whois_send_router(cmd);
ret = -1;
goto out;
}
- ADD_ERROR(error_client, error_client_count, client_id[i],
+ ADD_ERROR(error_client, error_client_count, client_id[i],
SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
}
}
} else if (nick) {
/* Find by nickname */
- if (!silc_idlist_get_clients_by_hash(server->local_list,
+ if (!silc_idlist_get_clients_by_hash(server->local_list,
nick, server->md5hash,
&clients, &clients_count))
- silc_idlist_get_clients_by_nickname(server->local_list,
+ silc_idlist_get_clients_by_nickname(server->local_list,
nick, server_name,
&clients, &clients_count);
if (check_global) {
- if (!silc_idlist_get_clients_by_hash(server->global_list,
+ if (!silc_idlist_get_clients_by_hash(server->global_list,
nick, server->md5hash,
&clients, &clients_count))
- silc_idlist_get_clients_by_nickname(server->global_list,
+ silc_idlist_get_clients_by_nickname(server->global_list,
nick, server_name,
&clients, &clients_count);
}
/* If we are normal server and did not send the request first to router
do it now, since we do not have the information. */
if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
- server->server_type == SILC_SERVER && !cmd->pending &&
+ server->server_type == SILC_SERVER && !cmd->pending &&
!server->standalone) {
silc_server_command_whois_send_router(cmd);
ret = -1;
mandatory fields that WHOIS command reply requires. Check for these and
make query from the server who owns the client if some fields are
missing. */
- if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
+ if (!silc_server_command_whois_check(cmd, clients, clients_count, attrs)) {
ret = -1;
goto out;
}
silc_free(error_client);
silc_free(nick);
silc_free(server_name);
+ if (attrs)
+ silc_attribute_payload_list_free(attrs);
return ret;
}
r = NULL;
for (k = 0; k < resolve_count; k++) {
- if (resolve[k].router == entry->router) {
+ if (resolve[k].sock == entry->router->connection) {
r = &resolve[k];
break;
}
(resolve_count + 1));
r = &resolve[resolve_count];
memset(r, 0, sizeof(*r));
- r->router = entry->router;
+ r->sock = entry->router->connection;
r->ident = ++server->cmd_ident;
resolve_count++;
}
r->res_argv_lens,
r->res_argv_types,
r->ident);
- silc_server_packet_send(server, r->router->connection,
- SILC_PACKET_COMMAND, cmd->packet->flags,
- res_cmd->data, res_cmd->len, FALSE);
+ silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND,
+ cmd->packet->flags, res_cmd->data,
+ res_cmd->len, FALSE);
/* Reprocess this packet after received reply */
silc_server_command_pending(server, SILC_COMMAND_WHOIS,
}
typedef struct {
- SilcServer server;
SilcSocketConnection sock;
char *signoff;
} *QuitInternal;
SILC_TASK_CALLBACK(silc_server_command_quit_cb)
{
+ SilcServer server = app_context;
QuitInternal q = (QuitInternal)context;
/* Free all client specific data, such as client entry and entires
on channels this client may be on. */
- silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
+ silc_server_free_client_data(server, q->sock, q->sock->user_data,
TRUE, q->signoff);
q->sock->user_data = NULL;
/* Close the connection on our side */
- silc_server_close_connection(q->server, q->sock);
+ silc_server_close_connection(server, q->sock);
+ silc_socket_free(q->sock);
silc_free(q->signoff);
silc_free(q);
}
tmp = NULL;
q = silc_calloc(1, sizeof(*q));
- q->server = server;
- q->sock = sock;
+ q->sock = silc_socket_dup(sock);
q->signoff = tmp ? strdup(tmp) : NULL;
/* We quit the connection with little timeout */
SILC_TASK_CALLBACK(silc_server_command_detach_cb)
{
+ SilcServer server = app_context;
QuitInternal q = (QuitInternal)context;
SilcClientID *client_id = (SilcClientID *)q->sock;
SilcClientEntry client;
SilcSocketConnection sock;
- client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
+ client = silc_idlist_find_client_by_id(server->local_list, client_id,
TRUE, NULL);
if (client && client->connection) {
sock = client->connection;
/* If there is pending outgoing data for the client then purge it
to the network before closing connection. */
- silc_server_packet_queue_purge(q->server, sock);
+ silc_server_packet_queue_purge(server, sock);
/* Close the connection on our side */
client->router = NULL;
client->connection = NULL;
sock->user_data = NULL;
- silc_server_close_connection(q->server, sock);
+ silc_server_close_connection(server, sock);
}
silc_free(client_id);
SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
{
+ SilcServer server = app_context;
QuitInternal q = (QuitInternal)context;
SilcClientID *client_id = (SilcClientID *)q->sock;
SilcClientEntry client;
- client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
+ client = silc_idlist_find_client_by_id(server->local_list, client_id,
TRUE, NULL);
if (client && client->mode & SILC_UMODE_DETACHED) {
SILC_LOG_DEBUG(("Detach timeout"));
- silc_server_free_client_data(q->server, NULL, client, TRUE,
+ silc_server_free_client_data(server, NULL, client, TRUE,
"Detach timeout");
}
SILC_NOTIFY_TYPE_UMODE_CHANGE);
q = silc_calloc(1, sizeof(*q));
- q->server = server;
q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
if (server->config->detach_timeout) {
q = silc_calloc(1, sizeof(*q));
- q->server = server;
q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
silc_schedule_task_add(server->schedule, 0,
silc_server_command_detach_timeout,
silc_pkcs_private_key_set(server->pkcs, server->private_key);
/* Initialize the scheduler */
- server->schedule = silc_schedule_init(server->config->param.connections_max);
+ server->schedule = silc_schedule_init(server->config->param.connections_max,
+ server);
if (!server->schedule)
goto err;
/* Clients local list */
server->purge_i = purge = silc_calloc(1, sizeof(*purge));
purge->cache = server->local_list->clients;
- purge->schedule = server->schedule;
purge->timeout = 600;
- silc_schedule_task_add(purge->schedule, 0,
- silc_idlist_purge,
+ silc_schedule_task_add(server->schedule, 0, silc_idlist_purge,
(void *)purge, purge->timeout, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
/* Clients global list */
server->purge_g = purge = silc_calloc(1, sizeof(*purge));
purge->cache = server->global_list->clients;
- purge->schedule = server->schedule;
purge->timeout = 300;
- silc_schedule_task_add(purge->schedule, 0,
- silc_idlist_purge,
+ silc_schedule_task_add(server->schedule, 0, silc_idlist_purge,
(void *)purge, purge->timeout, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
/* If we are normal server we'll retrieve network statisticial information
once in a while from the router. */
if (server->server_type == SILC_SERVER)
- silc_schedule_task_add(purge->schedule, 0, silc_server_get_stats,
+ silc_schedule_task_add(server->schedule, 0, silc_server_get_stats,
server, 10, 0, SILC_TASK_TIMEOUT,
SILC_TASK_PRI_LOW);
/* Check whether new config has this one too */
for (newptr = newconfig->routers; newptr; newptr = newptr->next) {
- if (!strcmp(newptr->host, ptr->host) && newptr->port == ptr->port &&
+ if (silc_string_compare(newptr->host, ptr->host) &&
+ newptr->port == ptr->port &&
newptr->initiator == ptr->initiator) {
found = TRUE;
break;
}
}
- if (!found) {
+ if (!found && ptr->host) {
/* Remove this connection */
SilcSocketConnection sock;
sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_ROUTER,
/* Check whether new config has this one too */
for (newptr = newconfig->servers; newptr; newptr = newptr->next) {
- if (!strcmp(newptr->host, ptr->host)) {
+ if (silc_string_compare(newptr->host, ptr->host)) {
found = TRUE;
break;
}
}
- if (!found) {
+ if (!found && ptr->host) {
/* Remove this connection */
SilcSocketConnection sock;
sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_SERVER,
}
}
+ if (server->config->clients) {
+ SilcServerConfigClient *ptr;
+ SilcServerConfigClient *newptr;
+ bool found;
+
+ for (ptr = server->config->clients; ptr; ptr = ptr->next) {
+ found = FALSE;
+
+ /* Check whether new config has this one too */
+ for (newptr = newconfig->clients; newptr; newptr = newptr->next) {
+ if (silc_string_compare(newptr->host, ptr->host)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found && ptr->host) {
+ /* Remove this connection */
+ SilcSocketConnection sock;
+ sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_CLIENT,
+ ptr->host, 0);
+ if (sock)
+ silc_schedule_task_add(server->schedule, sock->sock,
+ silc_server_rehash_close_connection,
+ server, 0, 1, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ }
+ }
+ }
+
/* Go through all configured routers after rehash */
silc_schedule_task_add(server->schedule, 0,
silc_server_connect_to_router,
SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
{
+ SilcServer server = app_context;
SilcServerConnection sconn = (SilcServerConnection)context;
- SilcServer server = sconn->server;
SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
SilcServerConfigConnParams *param =
(conn->param ? conn->param : &server->config->param);
SILC_TASK_CALLBACK(silc_server_connect_router)
{
+ SilcServer server = app_context;
SilcServerConnection sconn = (SilcServerConnection)context;
- SilcServer server = sconn->server;
SilcServerConfigRouter *rconn;
int sock;
/* Allocate connection object for hold connection specific stuff. */
sconn = silc_calloc(1, sizeof(*sconn));
- sconn->server = server;
sconn->remote_host = strdup(ptr->host);
sconn->remote_port = ptr->port;
sconn->backup = ptr->backup_router;
SilcSocketConnection sock = ctx->sock;
SilcServerEntry id_entry = NULL;
SilcBuffer packet;
- SilcServerHBContext hb_context;
unsigned char *id_string;
SilcUInt32 id_len;
SilcIDListData idata;
/* Perform keepalive. The `hb_context' will be freed automatically
when finally calling the silc_socket_free function. */
- hb_context = silc_calloc(1, sizeof(*hb_context));
- hb_context->server = server;
- silc_socket_set_heartbeat(sock, param->keepalive_secs, hb_context,
+ silc_socket_set_heartbeat(sock, param->keepalive_secs, server,
silc_server_perform_heartbeat,
server->schedule);
/* Register re-key timeout */
idata->rekey->timeout = param->key_exchange_rekey;
- idata->rekey->context = (void *)server;
silc_schedule_task_add(server->schedule, sock->sock,
silc_server_rekey_callback,
(void *)sock, idata->rekey->timeout, 0,
(SilcServerConnAuthInternalContext *)protocol->context;
SilcServer server = (SilcServer)ctx->server;
SilcSocketConnection sock = ctx->sock;
- SilcServerHBContext hb_context;
SilcUnknownEntry entry = (SilcUnknownEntry)sock->user_data;
void *id_entry;
SilcUInt32 hearbeat_timeout = server->config->param.keepalive_secs;
/* Perform keepalive. The `hb_context' will be freed automatically
when finally calling the silc_socket_free function. */
- hb_context = silc_calloc(1, sizeof(*hb_context));
- hb_context->server = server;
- silc_socket_set_heartbeat(sock, hearbeat_timeout, hb_context,
+ silc_socket_set_heartbeat(sock, hearbeat_timeout, server,
silc_server_perform_heartbeat,
server->schedule);
(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,
+ silc_server_packet_parse_real(server->schedule, server, 0, sock->sock,
parser_context);
/* Reprocess data since we'll return FALSE here. This is because
case SILC_SOCKET_TYPE_SERVER:
case SILC_SOCKET_TYPE_ROUTER:
/* Packets from servers are parsed immediately */
- silc_server_packet_parse_real(server->schedule, 0, sock->sock,
+ silc_server_packet_parse_real(server->schedule, server, 0, sock->sock,
parser_context);
break;
default:
if (sock->protocol) {
SilcServerFailureContext f;
f = silc_calloc(1, sizeof(*f));
- f->server = server;
- f->sock = sock;
+ f->sock = silc_socket_dup(sock);
/* We will wait 5 seconds to process this failure packet */
silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_failure_callback, (void *)f, 5, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ silc_server_failure_callback, (void *)f, 5, 0,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
}
break;
/* Allocate connection object for hold connection specific stuff. */
sconn = silc_calloc(1, sizeof(*sconn));
- sconn->server = server;
sconn->remote_host = strdup(remote_host);
sconn->remote_port = port;
sconn->no_reconnect = TRUE;
silc_server_close_connection(server, sock);
}
-typedef struct {
- SilcServer server;
- SilcClientEntry client;
-} *FreeClientInternal;
-
SILC_TASK_CALLBACK(silc_server_free_client_data_timeout)
{
- FreeClientInternal i = (FreeClientInternal)context;
+ SilcServer server = app_context;
+ SilcClientEntry client = context;
- assert(!silc_hash_table_count(i->client->channels));
+ assert(!silc_hash_table_count(client->channels));
- silc_idlist_del_data(i->client);
- silc_idcache_purge_by_context(i->server->local_list->clients, i->client);
- silc_free(i);
+ silc_idlist_del_data(client);
+ silc_idcache_purge_by_context(server->local_list->clients, client);
}
/* Frees client data and notifies about client's signoff. */
{
SILC_LOG_DEBUG(("Freeing client data"));
-#if 1
- if (!client->router && !client->connection &&
- !(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
- SILC_LOG_ERROR(("****** freeing data for already unregistered client -s"));
- SILC_LOG_ERROR(("****** Contact Pekka"));
- SILC_LOG_ERROR(("****** freeing data for already unregistered client -e"));
- return;
- }
-#endif
-
/* If there is pending outgoing data for the client then purge it
to the network before removing the client entry. */
silc_server_packet_queue_purge(server, sock);
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,
+ client, 300, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
SILC_TASK_CALLBACK(silc_server_channel_key_rekey)
{
+ SilcServer server = app_context;
SilcServerChannelRekey rekey = (SilcServerChannelRekey)context;
- SilcServer server = (SilcServer)rekey->context;
rekey->task = NULL;
if (server->server_type == SILC_ROUTER) {
if (!channel->rekey)
channel->rekey = silc_calloc(1, sizeof(*channel->rekey));
- channel->rekey->context = (void *)server;
channel->rekey->channel = channel;
channel->rekey->key_len = key_len;
if (channel->rekey->task)
if (server->server_type == SILC_ROUTER) {
if (!channel->rekey)
channel->rekey = silc_calloc(1, sizeof(*channel->rekey));
- channel->rekey->context = (void *)server;
channel->rekey->channel = channel;
if (channel->rekey->task)
silc_schedule_task_del(server->schedule, channel->rekey->task);
void silc_server_perform_heartbeat(SilcSocketConnection sock,
void *hb_context)
{
- SilcServerHBContext hb = (SilcServerHBContext)hb_context;
+ SilcServer server = hb_context;
SILC_LOG_DEBUG(("Sending heartbeat to %s:%d (%s)", sock->hostname,
sock->port, sock->ip));
/* Send the heartbeat */
- silc_server_send_heartbeat(hb->server, sock);
+ silc_server_send_heartbeat(server, sock);
}
/* Returns assembled of all servers in the given ID list. The packet's
SILC_TASK_CALLBACK(silc_server_failure_callback)
{
+ SilcServer server = app_context;
SilcServerFailureContext f = (SilcServerFailureContext)context;
if (f->sock->protocol) {
f->sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
- silc_protocol_execute(f->sock->protocol, f->server->schedule, 0, 0);
+ silc_protocol_execute(f->sock->protocol, server->schedule, 0, 0);
}
+ silc_socket_free(f->sock);
silc_free(f);
}
SILC_TASK_CALLBACK(silc_server_rekey_callback)
{
+ SilcServer server = app_context;
SilcSocketConnection sock = (SilcSocketConnection)context;
SilcIDListData idata = (SilcIDListData)sock->user_data;
- SilcServer server = (SilcServer)idata->rekey->context;
SilcProtocol protocol;
SilcServerRekeyInternalContext *proto_ctx;