From: Pekka Riikonen Date: Tue, 30 Jan 2001 21:40:21 +0000 (+0000) Subject: updates. X-Git-Tag: SILC.0.1~287 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=cf12445d208b8e7a43de5353b4267451340eb23d updates. --- diff --git a/CHANGES b/CHANGES index 076bb258..b147d908 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,47 @@ +Tue Jan 30 22:39:15 EET 2001 Pekka Riikonen + + * Changed the client's pending command handling to the same as the + server's pending command handling. It is also now possible to + execute command reply functions from other command reply + function as the function callbacks for commands and command + replies are one and same. The pending commands are not static + list anymore, it is mallocated SilcDList in lib/silcclient/client.h + in client connection context. Thus, pending commands are server + connection specific as it is convenient. + + Changed the function silc_client_command_pending and + silc_client_command_pending_del and added new function + silc_client_command_pending_check. Removed the + SILC_CLIENT_CMD_REPLY_EXEC, and SILC_CLIENT_PENDING_COMMAND_CHECK + macros. + + * Added cmd_ident, current command identifier, to the client + connection context in lib/silcclient/client.h to keep track on + command identifiers used in command sending. Client's command reply + function handling now supports the mandatory command identifiers. + + * Added SILC_CLIENT_COMMAND_EXEC_PENDING macros to all command reply + funtions in client to fully support pending command callbacks. + + * NOTE: the name_list in USERS (old NAMES) command is NOT sent anymore + as one of the arguments to the application in the command reply + client operation. + + * NOTE: The FORWARDED flag is depracated. It used to be depracated + before first releasing SILC but came back. Now it is removed again + and should come back nomore. The FORWARDED flag was used only + by the JOINing procedure by forwarding the command packet to router. + Now, the JOINing procedure has been changed to more generic (due + to various router environment issues) and FORWARDED is not needed + anymore for anything. The protocol specification is yet to be + updated. + + Now, removed silc_server_packet_forward from server and the flag + SILC_PACKET_FORWARDED from lib/silccore/silcpacket.h. + Tue Jan 30 00:05:05 EET 2001 Pekka Riikonen - * Renames NAMES command to USERS command. The NAMES was named that + * Renamed NAMES command to USERS command. The NAMES was named that due to historical reasons. Now it is renamed. Also, rewrote parts of the USERS command. The nickname list is not sent anymore by the server. Only Client ID and mode lists are sent in the USERS @@ -14,7 +55,7 @@ Tue Jan 30 00:05:05 EET 2001 Pekka Riikonen in the network by sending only one WHOIS or IDENTIFY command. Changed the code and the protocol specifications. - * Remove silc_server_command_identify_parse and changed that IDENTIFY + * Removed silc_server_command_identify_parse and changed that IDENTIFY uses silc_server_command_whois_parse to parse the request. */ * If normal server, do not parse the WHOIS and IDENTIFY requests diff --git a/apps/silc/local_command.c b/apps/silc/local_command.c index 3d969f78..110a8eb8 100644 --- a/apps/silc/local_command.c +++ b/apps/silc/local_command.c @@ -20,6 +20,9 @@ /* * $Id$ * $Log$ + * Revision 1.2 2001/01/30 21:40:21 priikone + * updates. + * * Revision 1.1 2000/09/13 17:47:54 priikone * Created SILC Client Libary by moving stuff from silc/ directory. * SILC client library is SILC client without UI. Old UI still exists @@ -137,7 +140,7 @@ SILC_CLIENT_LCMD_FUNC(msg) if (!client_entry) { /* Client entry not found, it was requested thus mark this to be pending command. */ - silc_client_command_pending(SILC_COMMAND_IDENTIFY, + silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 0, silc_client_local_command_msg, context); return; } diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 16513946..57bdc9e8 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -559,12 +559,12 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock, { SilcBuffer buffer = packet->buffer; SilcIDList id_list; - SilcServerEntry tmpserver, router; + SilcServerEntry router; SilcSocketConnection router_sock; SilcIDPayload idp; SilcIdType id_type; unsigned char *hash = NULL; - void *id, *tmpid; + void *id; SILC_LOG_DEBUG(("Processing new ID")); diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index bbae2c24..70911cf0 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -180,52 +180,6 @@ void silc_server_packet_send_dest(SilcServer server, silc_free(packetdata.dst_id); } -/* Forwards packet. Packets sent with this function will be marked as - forwarded (in the SILC header flags) so that the receiver knows that - we have forwarded the packet to it. Forwarded packets are handled - specially by the receiver as they are not destined to the receiver - originally. However, the receiver knows this because the forwarded - flag has been set (and the flag is authenticated). */ - -void silc_server_packet_forward(SilcServer server, - SilcSocketConnection sock, - unsigned char *data, unsigned int data_len, - int force_send) -{ - SilcIDListData idata; - SilcCipher cipher = NULL; - SilcHmac hmac = NULL; - - SILC_LOG_DEBUG(("Forwarding packet")); - - /* Get data used in the packet sending, keys and stuff */ - idata = (SilcIDListData)sock->user_data; - - /* Prepare outgoing data buffer for packet sending */ - silc_packet_send_prepare(sock, 0, 0, data_len); - - /* Put the data to the buffer */ - if (data && data_len) - silc_buffer_put(sock->outbuf, data, data_len); - - /* Add the FORWARDED flag to packet flags */ - sock->outbuf->data[2] |= (unsigned char)SILC_PACKET_FLAG_FORWARDED; - - if (idata) { - cipher = idata->send_key; - hmac = idata->hmac; - } - - /* Encrypt the packet */ - silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len); - - SILC_LOG_HEXDUMP(("Forwarded packet, len %d", sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); - - /* Now actually send the packet */ - silc_server_packet_send_real(server, sock, force_send); -} - /* Broadcast received packet to our primary route. This function is used by router to further route received broadcast packet. It is expected that the broadcast flag from the packet is checked before calling this diff --git a/apps/silcd/packet_send.h b/apps/silcd/packet_send.h index c4d71e1f..c60bace9 100644 --- a/apps/silcd/packet_send.h +++ b/apps/silcd/packet_send.h @@ -42,10 +42,6 @@ void silc_server_packet_send_dest(SilcServer server, unsigned char *data, unsigned int data_len, int force_send); -void silc_server_packet_forward(SilcServer server, - SilcSocketConnection sock, - unsigned char *data, unsigned int data_len, - int force_send); void silc_server_packet_broadcast(SilcServer server, SilcSocketConnection sock, SilcPacketContext *packet); diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 21b865e2..c562e868 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -71,7 +71,9 @@ int silc_server_alloc(SilcServer *new_server) void silc_server_free(SilcServer server) { if (server) { +#ifdef SILC_SIM SilcSimContext *sim; +#endif if (server->local_list) silc_free(server->local_list); @@ -1164,8 +1166,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real) if (server->server_type == SILC_ROUTER) { /* Route the packet if it is not destined to us. Other ID types but server are handled separately after processing them. */ - if (packet->dst_id_type == SILC_ID_SERVER && - !(packet->flags & SILC_PACKET_FLAG_FORWARDED) && + if (packet->dst_id_type == SILC_ID_SERVER && sock->type != SILC_SOCKET_TYPE_CLIENT && SILC_ID_SERVER_COMPARE(packet->dst_id, server->id_string)) { @@ -1327,7 +1328,7 @@ void silc_server_packet_parse_type(SilcServer server, /* * Received command reply packet. Received command reply to command. It * may be reply to command sent by us or reply to command sent by client - * that we've forwarded. + * that we've routed further. */ SILC_LOG_DEBUG(("Command Reply packet")); silc_server_command_reply(server, sock, packet); diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index eaf4db45..8403f44a 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -141,6 +141,7 @@ SilcClientConnection silc_client_add_connection(SilcClient client, conn->remote_host = strdup(hostname); conn->remote_port = port; conn->context = context; + conn->pending_commands = silc_dlist_init(); /* Add the connection to connections table */ for (i = 0; i < client->conns_count; i++) @@ -165,6 +166,8 @@ void silc_client_del_connection(SilcClient client, SilcClientConnection conn) for (i = 0; i < client->conns_count; i++) if (client->conns[i] == conn) { + if (conn->pending_commands) + silc_dlist_uninit(conn->pending_commands); silc_free(conn); client->conns[i] = NULL; } @@ -1195,6 +1198,8 @@ void silc_client_close_connection(SilcClient client, memset(conn->hmac_key, 0, conn->hmac_key_len); silc_free(conn->hmac_key); } + if (conn->pending_commands) + silc_dlist_uninit(conn->pending_commands); conn->sock = NULL; conn->remote_port = 0; @@ -1208,6 +1213,7 @@ void silc_client_close_connection(SilcClient client, conn->local_id_data = NULL; conn->remote_host = NULL; conn->current_channel = NULL; + conn->pending_commands = NULL; silc_client_del_connection(client, conn); } @@ -1277,7 +1283,6 @@ void silc_client_notify_by_server(SilcClient client, SilcNotifyPayload payload; SilcNotifyType type; SilcArgumentPayload args; - int i; SilcClientID *client_id = NULL; SilcChannelID *channel_id = NULL; @@ -1321,7 +1326,7 @@ void silc_client_notify_by_server(SilcClient client, SilcPacketContext *p = silc_packet_context_dup(packet); p->context = (void *)client; p->sock = sock; - silc_client_command_pending(SILC_COMMAND_WHOIS, + silc_client_command_pending(conn,SILC_COMMAND_WHOIS, 0, silc_client_notify_by_server_pending, p); goto out; } @@ -1367,7 +1372,7 @@ void silc_client_notify_by_server(SilcClient client, SilcPacketContext *p = silc_packet_context_dup(packet); p->context = (void *)client; p->sock = sock; - silc_client_command_pending(SILC_COMMAND_WHOIS, + silc_client_command_pending(conn, SILC_COMMAND_WHOIS, 0, silc_client_notify_by_server_pending, p); goto out; } @@ -1541,7 +1546,7 @@ void silc_client_notify_by_server(SilcClient client, SilcPacketContext *p = silc_packet_context_dup(packet); p->context = (void *)client; p->sock = sock; - silc_client_command_pending(SILC_COMMAND_WHOIS, + silc_client_command_pending(conn, SILC_COMMAND_WHOIS, 0, silc_client_notify_by_server_pending, p); goto out; } @@ -1872,7 +1877,6 @@ void silc_client_channel_message(SilcClient client, SilcChannelUser chu; SilcIDCacheEntry id_cache = NULL; SilcClientID *client_id = NULL; - int i; char *nickname; /* Sanity checks */ @@ -2011,7 +2015,6 @@ void silc_client_remove_from_channels(SilcClient client, SilcIDCacheList list; SilcChannelEntry channel; SilcChannelUser chu; - int i; if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY, SILC_ID_CHANNEL, &list)) @@ -2055,7 +2058,6 @@ void silc_client_replace_from_channels(SilcClient client, SilcIDCacheList list; SilcChannelEntry channel; SilcChannelUser chu; - int i; if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY, SILC_ID_CHANNEL, &list)) diff --git a/lib/silcclient/client.h b/lib/silcclient/client.h index f6d2215a..0cf57a49 100644 --- a/lib/silcclient/client.h +++ b/lib/silcclient/client.h @@ -110,6 +110,12 @@ struct SilcClientConnectionObject { referencing (sock->user_data). */ SilcSocketConnection sock; + /* Pending command queue for this connection */ + SilcDList pending_commands; + + /* Current command identifier, 0 not used */ + unsigned short cmd_ident; + /* Requested pings. */ SilcClientPing *ping; unsigned int ping_count; diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index 2dc94102..c543ed90 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -74,9 +74,6 @@ SilcClientCommand silc_command_list[] = #define COMMAND_ERROR cmd->client->ops->command(cmd->client, cmd->conn, \ cmd, FALSE, cmd->command->cmd) -/* List of pending commands. */ -SilcClientCommandPending *silc_command_pending = NULL; - /* Generic function to send any command. The arguments must be sent already encoded into correct form in correct order. */ @@ -110,63 +107,66 @@ SilcClientCommand *silc_client_command_find(const char *name) return NULL; } -/* Add new pending command to the list of pending commands. Currently - pending commands are executed from command replies, thus we can - execute any command after receiving some specific command reply. - - The argument `reply_cmd' is the command reply from where the callback - function is to be called, thus, it IS NOT the command to be executed. +/* 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. If `ident is non-zero + the `callback' will be executed when received reply with command + identifier `ident'. */ - XXX: If needed in the future this support may be extended for - commands as well, when any command could be executed after executing - some specific command. */ - -void silc_client_command_pending(SilcCommand reply_cmd, - SilcClientCommandCallback callback, +void silc_client_command_pending(SilcClientConnection conn, + SilcCommand reply_cmd, + unsigned short ident, + SilcCommandCb callback, void *context) { - SilcClientCommandPending *reply, *r; + SilcClientCommandPending *reply; reply = silc_calloc(1, sizeof(*reply)); reply->reply_cmd = reply_cmd; + reply->ident = ident; reply->context = context; reply->callback = callback; + silc_dlist_add(conn->pending_commands, reply); +} - if (silc_command_pending == NULL) { - silc_command_pending = reply; - return; - } +/* Deletes pending command by reply command type. */ - for (r = silc_command_pending; r; r = r->next) { - if (r->next == NULL) { - r->next = reply; +void silc_client_command_pending_del(SilcClientConnection conn, + SilcCommand reply_cmd, + unsigned short ident) +{ + SilcClientCommandPending *r; + + silc_dlist_start(conn->pending_commands); + while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END) { + if (r->reply_cmd == reply_cmd && r->ident == ident) { + silc_dlist_del(conn->pending_commands, r); break; } } } -/* Deletes pending command by reply command type. */ +/* Checks for pending commands and marks callbacks to be called from + the command reply function. Returns TRUE if there were pending command. */ -void silc_client_command_pending_del(SilcCommand reply_cmd) +int silc_client_command_pending_check(SilcClientConnection conn, + SilcClientCommandReplyContext ctx, + SilcCommand command, + unsigned short ident) { - SilcClientCommandPending *r, *tmp; - - if (silc_command_pending) { - if (silc_command_pending->reply_cmd == reply_cmd) { - silc_free(silc_command_pending); - silc_command_pending = NULL; - return; - } - - for (r = silc_command_pending; r; r = r->next) { - if (r->next && r->next->reply_cmd == reply_cmd) { - tmp = r->next; - r->next = r->next->next; - silc_free(tmp); - break; - } + SilcClientCommandPending *r; + + silc_dlist_start(conn->pending_commands); + while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END) { + if (r->reply_cmd == command && r->ident == ident) { + ctx->context = r->context; + ctx->callback = r->callback; + ctx->ident = ident; + return TRUE; } } + + return FALSE; } /* Free command context and its internals */ @@ -445,7 +445,7 @@ SILC_CLIENT_CMD_FUNC(invite) /* Client entry not found, it was requested thus mark this to be pending command. */ - silc_client_command_pending(SILC_COMMAND_IDENTIFY, + silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 0, silc_client_command_invite, context); return; } @@ -988,7 +988,7 @@ SILC_CLIENT_CMD_FUNC(cumode) if (!client_entry) { /* Client entry not found, it was requested thus mark this to be pending command. */ - silc_client_command_pending(SILC_COMMAND_CUMODE, + silc_client_command_pending(conn, SILC_COMMAND_CUMODE, 0, silc_client_command_cumode, context); return; } @@ -1230,7 +1230,7 @@ SILC_CLIENT_CMD_FUNC(users) /* XXX this is kludge and should be removed after pending command reply support is added. Currently only commands may be pending not command replies. */ - silc_client_command_pending(SILC_COMMAND_USERS, + silc_client_command_pending(conn, SILC_COMMAND_USERS, 0, silc_client_command_users, NULL); /* Notify application */ diff --git a/lib/silcclient/command.h b/lib/silcclient/command.h index 7e7db0e9..dfe4f586 100644 --- a/lib/silcclient/command.h +++ b/lib/silcclient/command.h @@ -21,6 +21,8 @@ #ifndef COMMAND_H #define COMMAND_H +#include "command_reply.h" + /* Structure holding one command and pointer to its function. @@ -59,10 +61,6 @@ typedef struct { /* All client commands */ extern SilcClientCommand silc_command_list[]; -/* Client command callback function. This included into Command Context, - and if it is defined it will be executed when executing the command. */ -typedef void (*SilcClientCommandCallback)(void *context); - /* Context sent as argument to all commands */ typedef struct { SilcClient client; @@ -80,9 +78,9 @@ typedef struct { replies, if needed later. */ typedef struct SilcClientCommandPendingStruct { SilcCommand reply_cmd; + SilcCommandCb callback; void *context; - SilcClientCommandCallback callback; - + unsigned short ident; struct SilcClientCommandPendingStruct *next; } SilcClientCommandPending; @@ -99,31 +97,14 @@ extern SilcClientCommandPending *silc_command_pending; #define SILC_CLIENT_CMD_FUNC(func) \ void silc_client_command_##func(void *context) -/* Checks for pending commands */ -#define SILC_CLIENT_COMMAND_CHECK_PENDING(ctx) \ -do { \ - if (silc_command_pending) { \ - SilcClientCommandPending *r; \ - SilcCommand cmd; \ - \ - cmd = silc_command_get(payload); \ - for (r = silc_command_pending; r; r = r->next) { \ - if (r->reply_cmd == cmd) { \ - ctx->context = r->context; \ - ctx->callback = r->callback; \ - break; \ - } \ - } \ - } \ -} while(0) - -/* Executed pending command */ -#define SILC_CLIENT_COMMAND_EXEC_PENDING(ctx, cmd) \ -do { \ - if (ctx->callback) { \ - (*ctx->callback)(ctx->context); \ - silc_client_command_pending_del((cmd)); \ - } \ +/* Executed pending command callback */ +#define SILC_CLIENT_COMMAND_EXEC_PENDING(ctx, cmd) \ +do { \ + if ((ctx)->callback) { \ + (*ctx->callback)(ctx->context); \ + silc_client_command_pending_del((ctx)->sock->user_data, (cmd), \ + (ctx)->ident); \ + } \ } while(0) /* Prototypes */ @@ -131,10 +112,18 @@ void silc_client_command_free(SilcClientCommandContext cmd); void silc_client_send_command(SilcClient client, SilcClientConnection conn, SilcCommand command, unsigned int argc, ...); SilcClientCommand *silc_client_command_find(const char *name); -void silc_client_command_pending(SilcCommand reply_cmd, - SilcClientCommandCallback callback, +void silc_client_command_pending(SilcClientConnection conn, + SilcCommand reply_cmd, + unsigned short ident, + SilcCommandCb callback, void *context); -void silc_client_command_pending_del(SilcCommand reply_cmd); +void silc_client_command_pending_del(SilcClientConnection conn, + SilcCommand reply_cmd, + unsigned short ident); +int silc_client_command_pending_check(SilcClientConnection conn, + SilcClientCommandReplyContext ctx, + SilcCommand command, + unsigned short ident); SILC_CLIENT_CMD_FUNC(whois); SILC_CLIENT_CMD_FUNC(whowas); SILC_CLIENT_CMD_FUNC(identify); diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index a4e98d55..51716566 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -134,8 +134,11 @@ void silc_client_command_reply_process(SilcClient client, SilcPacketContext *packet) { SilcBuffer buffer = packet->buffer; + SilcClientCommandReply *cmd; SilcClientCommandReplyContext ctx; SilcCommandPayload payload; + SilcCommand command; + unsigned short ident; /* Get command reply payload from packet */ payload = silc_command_payload_parse(buffer); @@ -153,12 +156,24 @@ void silc_client_command_reply_process(SilcClient client, ctx->payload = payload; ctx->args = silc_command_get_args(ctx->payload); ctx->packet = packet; + ident = silc_command_get_ident(ctx->payload); /* Check for pending commands and mark to be exeucted */ - SILC_CLIENT_COMMAND_CHECK_PENDING(ctx); - + silc_client_command_pending_check(sock->user_data, ctx, + silc_command_get(ctx->payload), ident); + /* Execute command reply */ - SILC_CLIENT_COMMAND_REPLY_EXEC(ctx); + command = silc_command_get(ctx->payload); + for (cmd = silc_command_reply_list; cmd->cb; cmd++) + if (cmd->cmd == command) + break; + + if (cmd == NULL || !cmd->cb) { + silc_free(ctx); + return; + } + + cmd->cb(ctx); } /* Returns status message string */ @@ -332,6 +347,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(whois) silc_client_command_reply_whois_print(cmd, status); } + /* Execute any pending command callbacks */ SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_WHOIS); out: @@ -439,6 +455,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(identify) } + /* Execute any pending command callbacks */ SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_IDENTIFY); out: @@ -483,6 +500,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick) /* Notify application */ COMMAND_REPLY((ARGS, conn->local_entry)); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_NICK); + out: silc_client_command_reply_free(cmd); } @@ -549,6 +569,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic) /* Notify application */ COMMAND_REPLY((ARGS, channel, topic)); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_TOPIC); + out: silc_client_command_reply_free(cmd); } @@ -575,6 +598,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite) /* Notify application */ COMMAND_REPLY((ARGS)); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_INVITE); + silc_client_command_reply_free(cmd); } @@ -624,6 +650,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(info) /* Notify application */ COMMAND_REPLY((ARGS, NULL, (char *)tmp)); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_INFO); + out: silc_client_command_reply_free(cmd); } @@ -676,6 +705,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(ping) silc_free(id); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_PING); + out: silc_client_command_reply_free(cmd); } @@ -774,6 +806,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) COMMAND_REPLY((ARGS, channel_name, conn->current_channel, mode, NULL, NULL, topic)); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN); + out: silc_client_command_reply_free(cmd); } @@ -834,6 +869,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd) /* Notify application */ COMMAND_REPLY((ARGS, motd)); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_MOTD); + out: silc_client_command_reply_free(cmd); } @@ -869,6 +907,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode) /* Notify application */ COMMAND_REPLY((ARGS, tmp)); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_CMODE); + out: silc_client_command_reply_free(cmd); } @@ -919,6 +960,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode) COMMAND_REPLY((ARGS, tmp, (SilcClientEntry)id_cache->context)); silc_free(client_id); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_CUMODE); + out: silc_client_command_reply_free(cmd); } @@ -964,6 +1008,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(leave) /* Notify application */ COMMAND_REPLY((ARGS)); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_LEAVE); + silc_client_command_reply_free(cmd); } @@ -982,11 +1029,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) SilcBuffer client_id_list; SilcBuffer client_mode_list; unsigned char *tmp; - unsigned int tmp_len; - int i, k, len1, len2, list_count; + unsigned int tmp_len, list_count; + int i; unsigned char **res_argv = NULL; unsigned int *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0; - char *name_list, *cp; SILC_LOG_DEBUG(("Start")); @@ -1094,59 +1140,46 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) /* Query the client information from server if the list included clients that we don't know about. */ if (res_argc) { -#if 0 SilcBuffer res_cmd; + /* Send the IDENTIFY command to server */ res_cmd = silc_command_payload_encode(SILC_COMMAND_IDENTIFY, res_argc, res_argv, res_argv_lens, - res_argv_types, 0); - silc_client_packet_send(cmd->client, cmd->conn->sock, - SILC_PACKET_COMMAND, NULL, 0, NULL, NULL, - buffer->data, buffer->len, TRUE); - goto out; -#endif + res_argv_types, ++conn->cmd_ident); + silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, + NULL, 0, NULL, NULL, res_cmd->data, res_cmd->len, + TRUE); + + /* Register pending command callback. After we've received the IDENTIFY + command reply we will reprocess this command reply by re-calling this + USERS command reply callback. */ + silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident, + silc_client_command_reply_users, cmd); + + silc_buffer_free(res_cmd); + if (channel_id) + silc_free(channel_id); + + for (i = 0; i < res_argc; i++) + silc_free(res_argv[i]); + silc_free(res_argv); + silc_free(res_argv_lens); + silc_free(res_argv_types); + return; } - name_list = cp; - for (i = 0; i < list_count; i++) { - int c = 0; - int nick_len = strcspn(name_list, " "); - char *nickname = silc_calloc(nick_len + 1, sizeof(*nickname)); - memcpy(nickname, name_list, nick_len); - - silc_list_start(channel->clients); - while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { - if (!strncmp(chu->client->nickname, nickname, - strlen(chu->client->nickname))) { - char t[8]; - - if (!c) { - c++; - continue; - } - - memset(t, 0, sizeof(t)); - chu->client->nickname = silc_calloc(strlen(nickname) + 8, 1); - snprintf(t, sizeof(t), "[%d]", c++); - strncat(chu->client->nickname, t, strlen(t)); - strncat(chu->client->nickname, nickname, strlen(nickname)); - } - } - - silc_free(nickname); - } + /* We have all the clients on the channel cached now. Create a nice + output for user interface and notify application. */ - /* XXX hmm... actually it is applications business to display this - information. We should just pass (as we do) the data to application and - let it to parse it and display it the way it wants. */ if (cmd->callback) { + /* User has called USERS command on user interface. */ cmd->client->ops->say(cmd->client, conn, "Users on %s", channel->channel_name); silc_list_start(channel->clients); while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { SilcClientEntry e = chu->client; - char *m, tmp[80], line[80]; + char *m, tmp[80], line[80], len1; memset(line, 0, sizeof(line)); memset(tmp, 0, sizeof(tmp)); @@ -1186,9 +1219,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) } } else { - name_list = NULL; - len1 = 0; - k = 0; + /* Server has sent us USERS reply even when we haven't actually sent + USERS command. This is normal behaviour when joining to a channel. + Display some nice information on the user interface. */ + int k = 0, len1 = 0, len2 = 0; + char *name_list = NULL; silc_list_start(channel->clients); while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { @@ -1220,12 +1255,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) silc_free(name_list); } - name_list = silc_argument_get_arg_type(cmd->args, 3, &len1); - /* Notify application */ - COMMAND_REPLY((ARGS, channel, name_list, client_id_list->head, + COMMAND_REPLY((ARGS, channel, client_id_list->head, client_mode_list->head)); + /* Execute any pending command callbacks */ + SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_USERS); + silc_buffer_free(client_id_list); silc_buffer_free(client_mode_list); diff --git a/lib/silcclient/command_reply.h b/lib/silcclient/command_reply.h index 2b7acf7f..c681ee4b 100644 --- a/lib/silcclient/command_reply.h +++ b/lib/silcclient/command_reply.h @@ -40,7 +40,8 @@ typedef struct { /* If defined this executes the pending command. */ void *context; - SilcClientCommandCallback callback; + SilcCommandCb callback; + unsigned short ident; } *SilcClientCommandReplyContext; /* Macros */ @@ -53,23 +54,6 @@ typedef struct { #define SILC_CLIENT_CMD_REPLY_FUNC(func) \ void silc_client_command_reply_##func(void *context) -/* Macro used to execute command replies */ -#define SILC_CLIENT_COMMAND_REPLY_EXEC(ctx) \ -do { \ - SilcClientCommandReply *cmd; \ - \ - for (cmd = silc_command_reply_list; cmd->cb; cmd++) \ - if (cmd->cmd == silc_command_get(ctx->payload)) { \ - cmd->cb(ctx); \ - break; \ - } \ - \ - if (cmd == NULL) { \ - silc_free(ctx); \ - return; \ - } \ -} while(0) - /* Prototypes */ void silc_client_command_reply_process(SilcClient client, SilcSocketConnection sock, diff --git a/lib/silccore/silcpacket.h b/lib/silccore/silcpacket.h index 86689b09..cf1e8edc 100644 --- a/lib/silccore/silcpacket.h +++ b/lib/silccore/silcpacket.h @@ -59,10 +59,10 @@ typedef unsigned char SilcPacketFlags; /* All defined packet flags */ #define SILC_PACKET_FLAG_NONE 0x00 #define SILC_PACKET_FLAG_PRIVMSG_KEY 0x01 -#define SILC_PACKET_FLAG_FORWARDED 0x02 -#define SILC_PACKET_FLAG_BROADCAST 0x04 -#define SILC_PACKET_FLAG_TUNNELED 0x08 +#define SILC_PACKET_FLAG_BROADCAST 0x02 +#define SILC_PACKET_FLAG_TUNNELED 0x04 /* Rest of flags still available +#define SILC_PACKET_FLAG_XXX 0x08 #define SILC_PACKET_FLAG_XXX 0x10 #define SILC_PACKET_FLAG_XXX 0x20 #define SILC_PACKET_FLAG_XXX 0x40