SilcClientEntry client = NULL, client2 = NULL;
SilcServerEntry server_entry = NULL;
SilcChannelClientEntry chl;
- SilcIDCacheEntry cache;
+ SilcIDCacheEntry cache = NULL;
SilcHashTableList htl;
SilcUInt32 mode;
unsigned char *tmp;
channel_id, SILC_ID_CHANNEL,
packet->buffer->data,
packet->buffer->len, FALSE);
- silc_server_backup_send_dest(server, (SilcServerEntry)sock->user_data,
+ silc_server_backup_send_dest(server, sock->user_data,
packet->type, packet->flags,
channel_id, SILC_ID_CHANNEL,
packet->buffer->data, packet->buffer->len,
packet->flags | SILC_PACKET_FLAG_BROADCAST,
packet->buffer->data, packet->buffer->len,
FALSE);
- silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
+ silc_server_backup_send(server, sock->user_data,
packet->type, packet->flags,
packet->buffer->data, packet->buffer->len,
FALSE, TRUE);
*/
SILC_LOG_DEBUG(("JOIN notify"));
+ if (channel_id)
+ silc_free(channel_id);
+
/* Get Channel ID */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (!tmp)
entry for the client. */
client = silc_idlist_find_client_by_id(server->global_list,
client_id, server->server_type,
- NULL);
+ &cache);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
client_id, server->server_type,
- NULL);
+ &cache);
if (!client) {
/* If router did not find the client the it is bogus */
- if (server->server_type != SILC_SERVER)
+ if (server->server_type != SILC_SERVER) {
+ silc_free(client_id);
goto out;
+ }
client =
silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
}
}
+ silc_free(client_id);
/* Do not process the notify if the client is not registered */
if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED))
/* Do not add client to channel if it is there already */
if (silc_server_client_on_channel(client, channel, NULL)) {
- SILC_LOG_DEBUG(("Client already on channel"));
+ SILC_LOG_DEBUG(("Client already on channel %s",
+ channel->channel_name));
break;
}
chl->client = client;
chl->channel = channel;
- /* If this is the first one on the channel then it is the founder of
- the channel. */
- if (!silc_hash_table_count(channel->user_list))
- chl->mode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
+ if (server->server_type != SILC_ROUTER ||
+ sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ /* If this is the first one on the channel then it is the founder of
+ the channel. This is done on normal server and on router if this
+ notify is coming from router */
+ if (!silc_hash_table_count(channel->user_list)) {
+ SILC_LOG_DEBUG(("Client %s is founder on channel",
+ silc_id_render(chl->client->id, SILC_ID_CLIENT)));
+ chl->mode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
+ }
+ }
silc_hash_table_add(channel->user_list, client, chl);
silc_hash_table_add(client->channels, channel, chl);
- silc_free(client_id);
channel->user_count++;
channel->disabled = FALSE;
+ /* Make sure we don't expire clients that are on channel */
+ if (cache)
+ cache->expire = 0;
+
/* Update statistics */
if (server->server_type == SILC_ROUTER) {
if (sock->type != SILC_SOCKET_TYPE_ROUTER)
}
}
silc_free(client_id);
+ silc_free(channel_id);
/* Check if on channel */
if (!silc_server_client_on_channel(client, channel, NULL))
goto out;
}
}
+ silc_free(channel_id);
if (channel->topic && !strcmp(channel->topic, tmp)) {
SILC_LOG_DEBUG(("Topic is already set and same"));
silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
FALSE, packet->buffer->data,
packet->buffer->len, FALSE);
- silc_free(channel_id);
break;
case SILC_NOTIFY_TYPE_NICK_CHANGE:
if (!id2)
goto out;
client_id2 = silc_id_payload_parse_id(id2, tmp_len, NULL);
- if (!client_id2)
+ if (!client_id2) {
+ silc_free(client_id);
goto out;
+ }
SILC_LOG_DEBUG(("Old Client ID id(%s)",
silc_id_render(client_id, SILC_ID_CLIENT)));
goto out;
}
}
- silc_free(client_id);
}
+ silc_free(client_id);
if (!channel_id) {
channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
if (server->server_type == SILC_SERVER &&
sock == SILC_PRIMARY_ROUTE(server) &&
mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
- SILC_LOG_DEBUG(("Founder public key received from primary router"));
+ SILC_LOG_DEBUG(("Founder public key received from router"));
tmp = silc_argument_get_arg_type(args, 6, &tmp_len);
if (!tmp)
break;
if (channel->founder_key)
silc_pkcs_public_key_free(channel->founder_key);
channel->founder_key = NULL;
- silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
+ silc_pkcs_public_key_payload_decode(tmp, tmp_len,
+ &channel->founder_key);
}
break;
if (channel->founder_key)
silc_pkcs_public_key_free(channel->founder_key);
channel->founder_key = NULL;
- silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
+ silc_pkcs_public_key_payload_decode(tmp, tmp_len, &channel->founder_key);
if (!channel->founder_key ||
(client && client->data.public_key &&
goto out;
}
}
- silc_free(client_id);
}
+ silc_free(client_id);
if (!channel_id) {
channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
is set on the channel now check whether this is the client that
originally set the mode. */
- /* Get public key that must be present in notify */
- tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
- if (!tmp || !silc_pkcs_public_key_decode(tmp, tmp_len,
- &founder_key)) {
- chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
- silc_server_force_cumode_change(server, sock, channel, chl, mode);
- notify_sent = TRUE;
- break;
- }
-
if (channel->founder_key) {
+ /* Get public key that must be present in notify */
+ tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
+ if (!tmp || !silc_pkcs_public_key_payload_decode(tmp, tmp_len,
+ &founder_key)) {
+ chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ silc_server_force_cumode_change(server, sock, channel, chl, mode);
+ notify_sent = TRUE;
+ break;
+ }
+
/* Now match the public key we have cached and public key sent.
They must match. */
+#if 0 /* The key may be other than the client's in 1.2 */
if (client && client->data.public_key &&
!silc_pkcs_public_key_compare(channel->founder_key,
client->data.public_key)) {
notify_sent = TRUE;
break;
}
+#endif
if (!silc_pkcs_public_key_compare(channel->founder_key,
founder_key)) {
chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
/* Send the same notify to the channel */
if (!notify_sent)
- silc_server_packet_send_to_channel(server, NULL, channel,
- packet->type,
- FALSE, packet->buffer->data,
+ silc_server_packet_send_to_channel(server, NULL, channel,
+ packet->type,
+ FALSE, packet->buffer->data,
packet->buffer->len, FALSE);
silc_free(channel_id);
if (!server_id)
goto out;
+ /* If the ID is mine, this notify is not allowed. */
+ if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
+ SILC_LOG_DEBUG(("Ignoring my own ID for SERVER_SIGNOFF"));
+ break;
+ }
+
/* Get server entry */
server_entry = silc_idlist_find_server_by_id(server->global_list,
server_id, TRUE, NULL);
- local = TRUE;
+ local = FALSE;
if (!server_entry) {
server_entry = silc_idlist_find_server_by_id(server->local_list,
server_id, TRUE, NULL);
silc_server_del_from_watcher_list(server, client);
/* Remove the client */
+ silc_idlist_del_data(client);
silc_idlist_del_client(local ? server->local_list :
server->global_list, client);
}
}
silc_free(server_id);
- /* Free all client entries that this server owns as they will
- become invalid now as well. */
- silc_server_remove_clients_by_server(server, server_entry, TRUE);
+ /* Sending SERVER_SIGNOFF is not right way to signoff local connection */
+ if (SILC_IS_LOCAL(server_entry))
+ break;
+
+ /* Remove all servers that are originated from this server, and
+ remove the clients of those servers too. */
+ silc_server_remove_servers_by_server(server, server_entry, TRUE);
+
+ /* Remove the clients that this server owns as they will become
+ invalid now too. */
+ silc_server_remove_clients_by_server(server, server_entry->router,
+ server_entry, TRUE);
+ silc_server_backup_del(server, server_entry);
/* Remove the server entry */
silc_idlist_del_server(local ? server->local_list :
goto out;
SILC_GET32_MSB(mode, tmp);
- /* Check that mode changing is allowed. */
- if (!silc_server_check_umode_rights(server, client, mode)) {
- SILC_LOG_DEBUG(("UMODE change is not allowed"));
- goto out;
- }
-
/* Remove internal resumed flag if client is marked detached now */
if (mode & SILC_UMODE_DETACHED)
client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
server->stat.detached--;
}
}
+ SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
+ SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
/* Change the mode */
client->mode = mode;
if (client) {
silc_server_remove_from_channels(server, NULL, client, TRUE,
NULL, TRUE);
+ silc_idlist_del_data(client);
silc_idlist_del_client(server->global_list, client);
}
silc_free(client_id);
SILC_LOG_DEBUG(("Start"));
- /* Source must be server or router */
- if (packet->src_id_type != SILC_ID_SERVER &&
- sock->type != SILC_SOCKET_TYPE_ROUTER)
- return;
-
if (packet->dst_id_type == SILC_ID_CHANNEL)
return;
SilcChannelEntry channel;
if (packet->src_id_type != SILC_ID_SERVER ||
- (server->server_type == SILC_ROUTER &&
+ (server->server_type == SILC_ROUTER && !server->backup_router &&
sock->type == SILC_SOCKET_TYPE_ROUTER))
return;
if (server->server_type != SILC_BACKUP_ROUTER) {
/* Distribute to local cell backup routers. */
- silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
+ silc_server_backup_send(server, sock->user_data,
SILC_PACKET_CHANNEL_KEY, 0,
buffer->data, buffer->len, FALSE, TRUE);
}
snprintf(&nickname[strlen(nickname) - 1], 1, "%d", nickfail);
}
+ /* If client marked as anonymous, scramble the username and hostname */
+ if (client->mode & SILC_UMODE_ANONYMOUS) {
+ char *scramble;
+
+ if (strlen(username) >= 2) {
+ username[0] = silc_rng_get_byte_fast(server->rng);
+ username[1] = silc_rng_get_byte_fast(server->rng);
+ }
+
+ scramble = silc_hash_babbleprint(server->sha1hash, username,
+ strlen(username));
+ scramble[5] = '@';
+ scramble[11] = '.';
+ memcpy(&scramble[16], ".silc", 5);
+ scramble[21] = '\0';
+ silc_free(username);
+ username = scramble;
+ }
+
/* Update client entry */
idata->status |= SILC_IDLIST_STATUS_REGISTERED;
client->nickname = nickname;
client->username = username;
- client->userinfo = realname ? realname : strdup(" ");
+ client->userinfo = realname ? realname : strdup(username);
client->id = client_id;
id_len = silc_id_get_len(client_id, SILC_ID_CLIENT);
/* Distribute to backup routers */
if (server->server_type == SILC_ROUTER) {
SilcBuffer idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- silc_server_backup_send(server, NULL, SILC_PACKET_NEW_ID, 0,
+ silc_server_backup_send(server, sock->user_data, SILC_PACKET_NEW_ID, 0,
idp->data, idp->len, FALSE, TRUE);
silc_buffer_free(idp);
}
if (server->server_type == SILC_ROUTER) {
/* Distribute to backup routers */
SilcBuffer idp = silc_id_payload_encode(new_server->id, SILC_ID_SERVER);
- silc_server_backup_send(server, NULL, SILC_PACKET_NEW_ID, 0,
+ silc_server_backup_send(server, sock->user_data, SILC_PACKET_NEW_ID, 0,
idp->data, idp->len, FALSE, TRUE);
silc_buffer_free(idp);
silc_server_announce_clients(server, 0, sock);
silc_server_announce_channels(server, 0, sock);
}
+
+ /* Announce our information to backup router */
+ if (new_server->server_type == SILC_BACKUP_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ server->server_type == SILC_ROUTER) {
+ silc_server_announce_servers(server, TRUE, 0, sock);
+ silc_server_announce_clients(server, 0, sock);
+ silc_server_announce_channels(server, 0, sock);
+ }
+
+ /* If backup router, mark it as one of ours. This server is considered
+ to be backup router after this setting. */
+ if (new_server->server_type == SILC_BACKUP_ROUTER) {
+ SilcServerConfigRouter *backup;
+ backup = silc_server_config_find_backup_conn(server, sock->ip);
+ if (!backup)
+ backup = silc_server_config_find_backup_conn(server, sock->hostname);
+ if (backup) {
+ /* Add as our backup router */
+ silc_server_backup_add(server, new_server, backup->backup_replace_ip,
+ backup->backup_replace_port,
+ backup->backup_local);
+ }
+ }
+
+ /* By default the servers connected to backup router are disabled
+ until backup router has become the primary */
+ if (server->server_type == SILC_BACKUP_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER)
+ idata->status |= SILC_IDLIST_STATUS_DISABLED;
}
return new_server;
packet->type,
packet->flags | SILC_PACKET_FLAG_BROADCAST,
buffer->data, buffer->len, FALSE);
- silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
+ silc_server_backup_send(server, sock->user_data,
packet->type, packet->flags,
packet->buffer->data, packet->buffer->len,
FALSE, TRUE);
packet->flags | SILC_PACKET_FLAG_BROADCAST,
packet->buffer->data,
packet->buffer->len, FALSE);
- silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
+ silc_server_backup_send(server, sock->user_data,
packet->type, packet->flags,
packet->buffer->data, packet->buffer->len,
FALSE, TRUE);
data buffer, which we will here now fetch from the original buffer. */
new_id = silc_packet_context_alloc();
new_id->type = SILC_PACKET_NEW_ID;
- new_id->flags = packet->flags;
+ new_id->flags = packet->flags & (~SILC_PACKET_FLAG_LIST);
new_id->src_id = packet->src_id;
new_id->src_id_len = packet->src_id_len;
new_id->src_id_type = packet->src_id_type;
char *channel_name;
SilcUInt32 name_len;
unsigned char *id;
- SilcUInt32 id_len;
+ SilcUInt32 id_len, cipher_len;
SilcServerEntry server_entry;
SilcChannelEntry channel;
+ const char *cipher;
if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
packet->src_id_type != SILC_ID_SERVER ||
channel =
silc_idlist_add_channel(server->global_list, strdup(channel_name),
0, channel_id, sock->user_data, NULL, NULL, 0);
- if (!channel)
+ if (!channel) {
+ silc_channel_payload_free(payload);
+ silc_free(channel_id);
return;
- channel->disabled = TRUE;
+ }
+ channel->disabled = TRUE; /* Disabled until someone JOINs */
server->stat.channels++;
if (server->server_type == SILC_ROUTER)
!SILC_ID_COMPARE(channel_id, server->id, server->id->ip.data_len)) {
SilcChannelID *tmp;
SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
-
if (silc_id_create_channel_id(server, server->id, server->rng, &tmp)) {
silc_server_send_notify_channel_change(server, sock, FALSE,
channel_id, tmp);
+ silc_channel_payload_free(payload);
silc_free(channel_id);
- channel_id = tmp;
+ silc_free(tmp);
}
+
+ /* Wait that server re-announces this channel */
+ return;
}
/* Create the channel with the provided Channel ID */
silc_free(channel_id);
return;
}
- channel->disabled = TRUE;
- channel->mode = silc_channel_get_mode(payload);
+ channel->disabled = TRUE; /* Disabled until someone JOINs */
+
+#if 0 /* We assume that CMODE_CHANGE notify is sent to us after this. */
+
+ /* XXX Dunno if this is supposed to be set in any server type. If set
+ here the CMODE_CHANGE that may follow sets mode that we already
+ have, and we may loose data from the CMODE_CHANGE notify. */
+ if (server_entry->server_type != SILC_BACKUP_ROUTER)
+ channel->mode = silc_channel_get_mode(payload);
+#endif
/* Send the new channel key to the server */
id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+ cipher = silc_cipher_get_name(channel->channel_key);
+ cipher_len = strlen(cipher);
chk = silc_channel_key_payload_encode(id_len, id,
- strlen(channel->channel_key->
- cipher->name),
- channel->channel_key->cipher->name,
+ cipher_len, cipher,
channel->key_len / 8,
channel->key);
silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
chk->data, chk->len, FALSE);
silc_buffer_free(chk);
+ silc_free(id);
} else {
/* The channel exist by that name, check whether the ID's match.
If they don't then we'll force the server to use the ID we have.
SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
silc_server_send_notify_channel_change(server, sock, FALSE,
channel_id, channel->id);
+ silc_channel_payload_free(payload);
+ silc_free(channel_id);
/* Wait that server re-announces this channel */
return;
/* Create new key for the channel and send it to the server and
everybody else possibly on the channel. */
if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
- if (!silc_server_create_channel_key(server, channel, 0))
- return;
-
- /* Send to the channel */
- silc_server_send_channel_key(server, sock, channel, FALSE);
- id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+
+ if (silc_hash_table_count(channel->user_list)) {
+ if (!silc_server_create_channel_key(server, channel, 0)) {
+ silc_channel_payload_free(payload);
+ silc_free(channel_id);
+ return;
+ }
+
+ /* Send to the channel */
+ silc_server_send_channel_key(server, sock, channel, FALSE);
+ }
/* Send to the server */
+ id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
+ id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+ cipher = silc_cipher_get_name(channel->channel_key);
+ cipher_len = strlen(cipher);
chk = silc_channel_key_payload_encode(id_len, id,
- strlen(channel->channel_key->
- cipher->name),
- channel->channel_key->
- cipher->name,
+ cipher_len, cipher,
channel->key_len / 8,
channel->key);
silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
silc_free(channel_id);
- /* Update statistics */
- server->stat.channels++;
- server->stat.cell_channels++;
-
/* Since the channel is coming from server and we also know about it
then send the JOIN notify to the server so that it see's our
users on the channel "joining" the channel. */
}
}
+ /* If the sender of this packet is server and we are router we need to
+ broadcast this packet to other routers in the network. Broadcast
+ this list packet instead of multiple New Channel packets. */
+ if (server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+ SILC_LOG_DEBUG(("Broadcasting received New Channel packet"));
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ packet->buffer->data,
+ packet->buffer->len, FALSE);
+ silc_server_backup_send(server, sock->user_data,
+ packet->type, packet->flags,
+ packet->buffer->data, packet->buffer->len,
+ FALSE, TRUE);
+ }
+
silc_channel_payload_free(payload);
}
server->server_type == SILC_SERVER)
return;
- /* If the sender of this packet is server and we are router we need to
- broadcast this packet to other routers in the network. Broadcast
- this list packet instead of multiple New Channel packets. */
- if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER &&
- !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
- SILC_LOG_DEBUG(("Broadcasting received New Channel List packet"));
- silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
- packet->type,
- packet->flags | SILC_PACKET_FLAG_BROADCAST,
- packet->buffer->data,
- packet->buffer->len, FALSE);
- silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
- packet->type, packet->flags,
- packet->buffer->data, packet->buffer->len,
- FALSE, TRUE);
- }
-
/* Make copy of the original packet context, except for the actual
data buffer, which we will here now fetch from the original buffer. */
new = silc_packet_context_alloc();
new->type = SILC_PACKET_NEW_CHANNEL;
- new->flags = packet->flags;
+ new->flags = packet->flags & (~SILC_PACKET_FLAG_LIST);
new->src_id = packet->src_id;
new->src_id_len = packet->src_id_len;
new->src_id_type = packet->src_id_type;
silc_server_free_sock_user_data(server, sock, NULL);
goto out;
}
+
+ client->data.status |= SILC_IDLIST_STATUS_RESUME_RES;
}
/* Reprocess the packet */
{
SilcBuffer buffer = packet->buffer, buf;
SilcIDListData idata;
+ SilcIDCacheEntry id_cache = NULL;
SilcClientEntry detached_client;
SilcClientID *client_id = NULL;
unsigned char *id_string, *auth = NULL;
SilcHashTableList htl;
SilcChannelClientEntry chl;
SilcServerResumeResolve r;
+ const char *cipher;
ret = silc_buffer_unformat(buffer,
SILC_STR_UI16_NSTRING(&id_string, &id_len),
idata = (SilcIDListData)client;
/* Get entry to the client, and resolve it if we don't have it. */
- detached_client = silc_server_get_client_resolve(server, client_id, FALSE,
- &resolved);
+ detached_client = silc_server_query_client(server, client_id, FALSE,
+ &resolved);
if (!detached_client) {
if (resolved) {
/* The client info is being resolved. Reprocess this packet after
resolve = TRUE;
if (!detached_client->nickname)
resolve = TRUE;
+ if (detached_client->data.status & SILC_IDLIST_STATUS_RESUME_RES)
+ resolve = FALSE;
if (resolve) {
if (server->server_type == SILC_SERVER && !server->standalone) {
/* The client info is being resolved. Reprocess this packet after
receiving the reply to the query. */
SILC_LOG_DEBUG(("Resolving client info"));
- silc_server_get_client_resolve(server, client_id, TRUE, NULL);
+ silc_server_query_client(server, client_id, TRUE, NULL);
r = silc_calloc(1, sizeof(*r));
if (!r)
return;
silc_idlist_add_data(detached_client, idata);
detached_client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
+ detached_client->data.status &= ~SILC_IDLIST_STATUS_RESUME_RES;
detached_client->mode &= ~SILC_UMODE_DETACHED;
server->stat.my_detached--;
silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
SILC_PACKET_RESUME_CLIENT, 0,
buf->data, buf->len, TRUE);
+ silc_server_backup_send(server, detached_client->router,
+ SILC_PACKET_RESUME_CLIENT, 0,
+ buf->data, buf->len, TRUE, TRUE);
/* As router we must deliver this packet directly to the original
server whom this client was earlier. */
server->stat.clients--;
if (server->stat.cell_clients)
server->stat.cell_clients--;
+ silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, FALSE);
silc_server_del_from_watcher_list(server, client);
- silc_idlist_del_client(server->local_list, client);
+ if (!silc_idlist_del_client(server->local_list, client))
+ silc_idlist_del_client(server->global_list, client);
client = detached_client;
+ silc_free(client->servername);
+ client->servername = strdup(server->server_name);
/* If the ID is not based in our ID then change it */
if (!SILC_ID_COMPARE(client->id, server->id, server->id->ip.data_len)) {
}
id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
+ cipher = silc_cipher_get_name(channel->channel_key);
keyp =
silc_channel_key_payload_encode(silc_id_get_len(channel->id,
SILC_ID_CHANNEL),
id_string,
- strlen(channel->channel_key->
- cipher->name),
- channel->channel_key->cipher->name,
+ strlen(cipher), cipher,
channel->key_len / 8, channel->key);
silc_free(id_string);
- /* Send the key packet to client */
+ /* Send the channel key to the client */
silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
keyp->data, keyp->len, FALSE);
- if (created && server->server_type == SILC_SERVER)
- silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
- SILC_PACKET_CHANNEL_KEY, 0,
- keyp->data, keyp->len, FALSE);
+ /* Distribute the channel key to channel */
+ if (created) {
+ silc_server_send_channel_key(server, NULL, channel,
+ server->server_type == SILC_ROUTER ?
+ FALSE : !server->standalone);
+ silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
+ keyp->data, keyp->len, FALSE, TRUE);
+ }
silc_buffer_free(keyp);
}
/* Get entry to the client, and resolve it if we don't have it. */
detached_client = silc_idlist_find_client_by_id(server->local_list,
- client_id, TRUE, NULL);
+ client_id, TRUE,
+ &id_cache);
if (!detached_client) {
detached_client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, NULL);
+ client_id, TRUE,
+ &id_cache);
if (!detached_client) {
SILC_LOG_DEBUG(("Resuming client is unknown"));
silc_free(client_id);
return;
}
+ SILC_LOG_DEBUG(("Resuming detached client"));
+
+ /* If the sender of this packet is server and we are router we need to
+ broadcast this packet to other routers in the network. */
+ if (server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+ SILC_LOG_DEBUG(("Broadcasting received Resume Client packet"));
+ silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ buffer->data, buffer->len, FALSE);
+ silc_server_backup_send(server, sock->user_data,
+ packet->type, packet->flags,
+ packet->buffer->data, packet->buffer->len,
+ FALSE, TRUE);
+ }
+
/* Client is detached, and now it is resumed. Remove the detached
mode and mark that it is resumed. */
detached_client->mode &= ~SILC_UMODE_DETACHED;
detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
+ detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
+ id_cache->expire = 0;
+
+ silc_schedule_task_del_by_context(server->schedule, detached_client);
/* Get the new owner of the resumed client */
server_id = silc_id_str2id(packet->src_id, packet->src_id_len,
/* Get server entry */
server_entry = silc_idlist_find_server_by_id(server->global_list,
server_id, TRUE, NULL);
- local = TRUE;
+ local = FALSE;
if (!server_entry) {
server_entry = silc_idlist_find_server_by_id(server->local_list,
server_id, TRUE, NULL);
- local = FALSE;
+ local = TRUE;
if (!server_entry) {
silc_free(server_id);
silc_free(client_id);
}
if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_ROUTER &&
server_entry->server_type == SILC_ROUTER)
local = FALSE;
- SILC_LOG_DEBUG(("Resuming detached client"));
-
/* Change the client to correct list. */
if (!silc_idcache_del_by_context(server->local_list->clients,
detached_client))
silc_idcache_del_by_context(server->global_list->clients,
detached_client);
- silc_idcache_add(local && server->server_type == SILC_ROUTER ?
- server->local_list->clients :
- server->global_list->clients,
+ silc_idcache_add(local && server->server_type == SILC_ROUTER ?
+ server->local_list->clients :
+ server->global_list->clients,
detached_client->nickname,
detached_client->id, detached_client, FALSE, NULL);
- detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
- /* Change the owner of the client if needed */
- if (detached_client->router != server_entry)
- detached_client->router = server_entry;
+ /* Change the owner of the client */
+ detached_client->router = server_entry;
/* Update channel information regarding global clients on channel. */
- if (server->server_type == SILC_SERVER) {
+ if (server->server_type != SILC_ROUTER) {
silc_hash_table_list(detached_client->channels, &htl);
while (silc_hash_table_get(&htl, NULL, (void **)&chl))
chl->channel->global_users =
silc_hash_table_list_reset(&htl);
}
- silc_schedule_task_del_by_context(server->schedule, detached_client);
-
- /* If the sender of this packet is server and we are router we need to
- broadcast this packet to other routers in the network. */
- if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER &&
- !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
- SILC_LOG_DEBUG(("Broadcasting received Resume Client packet"));
- silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
- packet->type,
- packet->flags | SILC_PACKET_FLAG_BROADCAST,
- buffer->data, buffer->len, FALSE);
- silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
- packet->type, packet->flags,
- packet->buffer->data, packet->buffer->len,
- FALSE, TRUE);
- }
-
silc_free(server_id);
}