libary is freed. The affected files are
lib/silcske/silcske[_status].[ch].
+ * Resolve the client entry information in the function
+ silc_client_channel_message to assure that NULL pointer is not
+ passed as client entry to the application. */
+
+ * Fixed the task timeout calculation to assure that there is
+ never negative timeouts. The affected file is
+ lib/silcutil/silcschedule.c.
+
+ * Fixed the channel user mode notification sending in server.
+ It was sent point-to-point to the router (or to server by router)
+ but it needs to be destined to a channel. The routines now
+ supports sending the channel user mode notifys to the channels
+ when announcing clients and channels. Affected files are
+ silcd/server.c and silcd/packet_receive.c.
+
+ * Fixed the CHANNEL_CHANGE notify handling in the client libary.
+ It did not actually replace the old channel entry in the cache.
+ Affected file lib/silcclient/client_notify.c.
+
Tue Jun 19 22:10:36 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Fixed a possible crash in silc_packet_send_prepare. It now
TODO/bugs In SILC Client Library
================================
- o If the silc_client_channel_message does not find the client entry
- then it should attempt to resolve it at least once and no return
- NULL entry to the application.
-
o Add some silc_client_del_client and other deletion funtions for
application to delete client entrys from the cache.
TODO/bugs In SILC Libraries
===========================
- o The timeout calculation can go negative at least on BSD, so rewrite
- in in lib/silcutil/silcschdule.c.
-
o Incomplete IPv6 support:
o All network routines in lib/silcutil/silcnet.[ch] does not
}
if (users_modes) {
silc_buffer_push(users_modes, users_modes->data - users_modes->head);
- silc_server_packet_send(server, sock,
- SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
- users_modes->data, users_modes->len, FALSE);
+ silc_server_packet_send_dest(server, sock,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ channel->id, SILC_ID_CHANNEL,
+ users_modes->data,
+ users_modes->len, FALSE);
silc_buffer_free(users_modes);
}
}
}
if (users_modes) {
silc_buffer_push(users_modes, users_modes->data - users_modes->head);
- silc_server_packet_send(server, sock,
- SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
- users_modes->data, users_modes->len, FALSE);
+ silc_server_packet_send_dest(server, sock,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ channel->id, SILC_ID_CHANNEL,
+ users_modes->data,
+ users_modes->len, FALSE);
silc_buffer_free(users_modes);
}
}
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);
}
}
SilcIDList id_list,
SilcBuffer *channels,
SilcBuffer *channel_users,
- SilcBuffer *channel_users_modes);
+ SilcBuffer **channel_users_modes,
+ uint32 *channel_users_modes_c,
+ SilcChannelID ***channel_ids);
void silc_server_announce_servers(SilcServer server);
void silc_server_announce_clients(SilcServer server);
void silc_server_announce_channels(SilcServer server);
silc_free(id_string);
}
+static void silc_client_channel_message_cb(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry *clients,
+ uint32 clients_count,
+ void *context)
+{
+ SilcPacketContext *packet = (SilcPacketContext *)context;
+
+ if (clients)
+ silc_client_channel_message(client, conn->sock, packet);
+ silc_packet_context_free(packet);
+}
+
/* Process received message to a channel (or from a channel, really). This
decrypts the channel message with channel specific key and parses the
channel payload. Finally it displays the message on the screen. */
SilcChannelUser chu;
SilcIDCacheEntry id_cache = NULL;
SilcClientID *client_id = NULL;
- int found = FALSE;
+ bool found = FALSE;
unsigned char *message;
SILC_LOG_DEBUG(("Start"));
goto out;
}
- message = silc_channel_message_get_data(payload, NULL);
-
/* Find client entry */
silc_list_start(channel->clients);
while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
}
}
+ if (!found) {
+ /* Resolve the client info */
+ silc_client_get_client_by_id_resolve(client, conn, client_id,
+ silc_client_channel_message_cb,
+ silc_packet_context_dup(packet));
+ goto out;
+ }
+
+ message = silc_channel_message_get_data(payload, NULL);
+
/* Pass the message to application */
- client->ops->channel_message(client, conn, found ? chu->client : NULL,
- channel,
+ client->ops->channel_message(client, conn, chu->client, channel,
silc_channel_message_get_flags(payload),
message);
goto out;
/* Find Client entry */
- client_entry =
- silc_client_get_client_by_id(client, conn, client_id);
- if (!client_entry)
+ client_entry = silc_client_get_client_by_id(client, conn, client_id);
+ if (!client_entry) {
+ silc_client_notify_by_server_resolve(client, conn, packet, client_id);
goto out;
+ }
/* Get the mode */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
/* Get the channel entry */
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- &id_cache))
+ &id_cache))
break;
channel = (SilcChannelEntry)id_cache->context;
+ SILC_LOG_DEBUG(("Old Channel ID id(%s)",
+ silc_id_render(channel->id, SILC_ID_CHANNEL)));
+
/* Free the old ID */
silc_free(channel->id);
if (!channel->id)
goto out;
- id_cache->id = (void *)channel->id;
+ SILC_LOG_DEBUG(("New Channel ID id(%s)",
+ silc_id_render(channel->id, SILC_ID_CHANNEL)));
+
+ /* Remove the old cache entry and create a new one */
+ silc_idcache_del_by_context(conn->channel_cache, channel);
+ silc_idcache_add(conn->channel_cache, channel->channel_name,
+ channel->id, channel, FALSE);
/* Notify application */
client->ops->notify(client, conn, type, channel, channel);
/* Calculate the next timeout for select() */ \
queue->timeout.tv_sec = task->timeout.tv_sec - curtime.tv_sec; \
queue->timeout.tv_usec = task->timeout.tv_usec - curtime.tv_usec; \
+ if (queue->timeout.tv_sec < 0) \
+ queue->timeout.tv_sec = 0; \
\
/* We wouldn't want to go under zero, check for it. */ \
if (queue->timeout.tv_usec < 0) { \
queue->timeout.tv_sec -= 1; \
+ if (queue->timeout.tv_sec < 0) \
+ queue->timeout.tv_sec = 0; \
queue->timeout.tv_usec += 1000000L; \
} \
} \