+Thu Jan 17 18:59:11 EET 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * Do not save client history information in SERVER_SIGNOFF.
+ Fixes the bug in normal server that it does not detect
+ the client becoming valid after the server becomes back
+ online. Affected file silcd/server_util.c.
+
+ * Added `sock_error' field into the SilcSocketConnection
+ context. When error occurs during socket operation (read
+ or write) the error is saved. Added also new function
+ silc_socket_get_error to return human readable socket error
+ message. Affected files are lib/silcutil/silcsockconn.[ch],
+ lib/silcutil/unix/silcunixsockconn.c, and
+ lib/silcutil/win32/silcwin32sockconn.c.
+
+ * The server now prints the socket error message in the
+ signoff for client. Affected file silcd/server.c.
+
+ * Fixed the `created' channel information sending from router
+ to server in JOIN command. Checks now whether the channel
+ really was created or not and set it according that.
+
+ Fixed the JOIN command to use the client entry's current
+ ID during the joining procedure instead of the one it sent
+ in the command (it is checked though), since it can change
+ between the packet processing and command processing, and
+ would just case unnecessary pain in the client end. Affected
+ file silcd/command.c.
+
+ * Fixed a channel key payload sending to use correct channel
+ ID when the server was forced to change the channel's ID by
+ router. Router sent the key payload with the old Channel ID.
+ Affected file silcd/packet_receive.c.
+
Wed Jan 16 22:26:30 EET 2002 Pekka Riikonen <priikone@silcnet.org>
* Call silc_server_save_channel_key only if the key payload
TODO/bugs In SILC Server
========================
+ o Topic notifications seem to go double times occasionally to a channel.
+
o Backup router related issues
o Channel user mode changes are notified unnecessarely when
tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
if (tmp) {
char invite[512];
+ bool resolve;
dest_id = silc_id_payload_parse_id(tmp, len);
if (!dest_id) {
}
/* Get the client entry */
- dest = silc_server_get_client_resolve(server, dest_id);
+ dest = silc_server_get_client_resolve(server, dest_id, &resolve);
if (!dest) {
- if (server->server_type != SILC_SERVER) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
- SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+ if (server->server_type != SILC_SERVER || !resolve) {
+ silc_server_command_send_status_reply(
+ cmd, SILC_COMMAND_INVITE,
+ SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
goto out;
}
uint16 ident = silc_command_get_ident(cmd->payload);
char check[512], check2[512];
bool founder = FALSE;
+ bool resolve;
SILC_LOG_DEBUG(("Start"));
if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
client = (SilcClientEntry)sock->user_data;
} else {
- client = silc_server_get_client_resolve(server, client_id);
+ client = silc_server_get_client_resolve(server, client_id, &resolve);
if (!client) {
if (cmd->pending)
goto out;
+ if (!resolve) {
+ silc_server_command_send_status_reply(
+ cmd, SILC_COMMAND_JOIN,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
+
/* The client info is being resolved. Reprocess this packet after
receiving the reply to the query. */
silc_server_command_pending(server, SILC_COMMAND_WHOIS,
channel_name, NULL);
if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
- /* If this is coming from client the Client ID in the command packet must
- be same as the client's ID. */
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
- SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
- if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- goto out;
- }
- }
+ SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
+ client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
if (!channel || channel->disabled) {
/* Channel not found */
channel = silc_server_create_new_channel(server, server->id, cipher,
hmac, channel_name, TRUE);
if (!channel) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
- SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
+ silc_server_command_send_status_reply(
+ cmd, SILC_COMMAND_JOIN,
+ SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
goto out;
}
create_key = FALSE; /* Router returned the key already */
}
- if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS)
+ if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
+ !silc_hash_table_count(channel->user_list))
created = TRUE;
}
channel->mode = silc_channel_get_mode(payload);
/* 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);
chk = silc_channel_key_payload_encode(id_len, id,
strlen(channel->channel_key->
cipher->name),
/* 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_CHANNEL_LEN;
-
+ id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+
/* Send to the server */
chk = silc_channel_key_payload_encode(id_len, id,
strlen(channel->channel_key->
SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
SILC_SET_DISCONNECTING(sock);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
- else if (server->router_conn && server->router_conn->sock == sock &&
+ if (sock->user_data) {
+ char tmp[128];
+ if (silc_socket_get_error(sock, tmp, sizeof(tmp) - 1))
+ silc_server_free_sock_user_data(server, sock, tmp);
+ else
+ silc_server_free_sock_user_data(server, sock, NULL);
+ } else if (server->router_conn && server->router_conn->sock == sock &&
!server->router && server->standalone)
silc_schedule_task_add(server->schedule, 0,
silc_server_connect_to_router,
SilcIDCacheEntry cache;
bool global;
+ SILC_LOG_DEBUG(("Start"));
+
for (i = 0; i < user_count; i++) {
/* Client ID */
SILC_GET16_MSB(idp_len, user_list->data + 2);
it using WHOIS command. */
SilcClientEntry silc_server_get_client_resolve(SilcServer server,
- SilcClientID *client_id)
+ SilcClientID *client_id,
+ bool *resolved)
{
SilcClientEntry client;
+ if (resolved)
+ *resolved = FALSE;
+
client = silc_idlist_find_client_by_id(server->local_list, client_id,
TRUE, NULL);
if (!client) {
buffer->data, buffer->len, FALSE);
silc_buffer_free(idp);
silc_buffer_free(buffer);
+
+ if (resolved)
+ *resolved = TRUE;
+
return NULL;
}
SilcBuffer silc_server_get_client_channel_list(SilcServer server,
SilcClientEntry client);
SilcClientEntry silc_server_get_client_resolve(SilcServer server,
- SilcClientID *client_id);
+ SilcClientID *client_id,
+ bool *resolved);
#endif
/* Remove the client entry */
silc_server_remove_clients_channels(server, NULL, client, channels);
- client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
- id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+ if (!server_signoff) {
+ client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+ id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+ } else {
+ silc_idlist_del_client(server->local_list, client);
+ }
server->stat.clients--;
if (server->server_type == SILC_ROUTER)
server->stat.cell_clients--;
/* Remove the client entry */
silc_server_remove_clients_channels(server, NULL, client, channels);
- client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
- id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+ if (!server_signoff) {
+ client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+ id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+ } else {
+ silc_idlist_del_client(server->global_list, client);
+ }
server->stat.clients--;
if (server->server_type == SILC_ROUTER)
server->stat.cell_clients--;
void *user_data;
SilcProtocol protocol;
uint32 flags;
+ uint8 sock_error;
int users;
char *hostname;
***/
int silc_socket_write(SilcSocketConnection sock);
+/****f* silcutil/SilcSocketConnectionAPI/silc_socket_get_error
+ *
+ * SYNOPSIS
+ *
+ * bool silc_socket_get_error(SilcSocketConnection sock, char *error,
+ * uint32 error_len);
+ *
+ * DESCRIPTION
+ *
+ * Returns human readable error message into the `error' buffer if
+ * the socket is int error status. Returns TRUE if error message was
+ * written into the buffer and FALSE if there is not socket error.
+ *
+ ***/
+bool silc_socket_get_error(SilcSocketConnection sock, char *error,
+ uint32 error_len);
+
/****f* silcutil/SilcSocketConnectionAPI/SilcSocketConnectionHBCb
*
* SYNOPSIS
return -2;
}
SILC_LOG_DEBUG(("Cannot write to socket: %s", strerror(errno)));
+ sock->sock_error = errno;
return -1;
}
return -2;
}
SILC_LOG_DEBUG(("Cannot read from socket: %d:%s", fd, strerror(errno)));
+ sock->sock_error = errno;
return -1;
}
return len;
}
+
+/* Returns human readable socket error message */
+
+bool silc_socket_get_error(SilcSocketConnection sock, char *error,
+ uint32 error_len)
+{
+ char *err;
+
+ if (!sock->sock_error)
+ return FALSE;
+
+ err = strerror(sock->sock_error);
+ if (strlen(err) > error_len)
+ return FALSE;
+
+ memset(error, 0, error_len);
+ memcpy(error, err, strlen(err));
+}
return -2;
}
SILC_LOG_ERROR(("Cannot write to socket: %d", (int)fd));
+ sock->sock_error = err;
return -1;
}
return -2;
}
SILC_LOG_ERROR(("Cannot read from socket: %d", (int)fd));
+ sock->sock_error = err;
return -1;
}
return len;
}
+
+/* Returns human readable socket error message */
+
+bool silc_socket_get_error(SilcSocketConnection sock, char *error,
+ uint32 error_len)
+{
+ /* XXX TODO */
+ return FALSE;
+}