Added SilcIDListData structure and added it to ClientEntry and
[silc.git] / apps / silcd / command_reply.c
1 /*
2
3   command_reply.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24 #include "command_reply.h"
25
26 /* Server command reply list. Not all commands have reply function as
27    they are never sent by server. More maybe added later if need appears. */
28 SilcServerCommandReply silc_command_reply_list[] =
29 {
30   SILC_SERVER_CMD_REPLY(join, JOIN),
31   SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
32
33   { NULL, 0 },
34 };
35
36 /* Process received command reply. */
37
38 void silc_server_command_reply_process(SilcServer server,
39                                        SilcSocketConnection sock,
40                                        SilcBuffer buffer)
41 {
42   SilcServerCommandReplyContext ctx;
43   SilcCommandPayload payload;
44
45   /* Get command reply payload from packet */
46   payload = silc_command_payload_parse(buffer);
47   if (!payload) {
48     /* Silently ignore bad reply packet */
49     SILC_LOG_DEBUG(("Bad command reply packet"));
50     return;
51   }
52   
53   /* Allocate command reply context. This must be free'd by the
54      command reply routine receiving it. */
55   ctx = silc_calloc(1, sizeof(*ctx));
56   ctx->server = server;
57   ctx->sock = sock;
58   ctx->payload = payload;
59   ctx->args = silc_command_get_args(ctx->payload);
60       
61   /* Check for pending commands and mark to be exeucted */
62   SILC_SERVER_COMMAND_CHECK_PENDING(ctx);
63   
64   /* Execute command reply */
65   SILC_SERVER_COMMAND_REPLY_EXEC(ctx);
66 }
67
68 /* Free command reply context and its internals. */
69
70 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
71 {
72   if (cmd) {
73     silc_command_free_payload(cmd->payload);
74     silc_free(cmd);
75   }
76 }
77
78 /* Received reply for forwarded JOIN command. Router has created or joined
79    the client to the channel. We save some channel information locally
80    for future use. */
81
82 SILC_SERVER_CMD_REPLY_FUNC(join)
83 {
84   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
85   SilcServer server = cmd->server;
86   SilcCommandStatus status;
87   SilcChannelID *id;
88   SilcChannelEntry entry;
89   unsigned int len;
90   unsigned char *id_string;
91   char *channel_name, *tmp;
92
93   SILC_LOG_DEBUG(("Start"));
94
95   tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
96   SILC_GET16_MSB(status, tmp);
97   if (status != SILC_STATUS_OK)
98     goto out;
99
100   /* Get channel name */
101   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
102   if (!tmp)
103     goto out;
104
105   /* Get channel ID */
106   id_string = silc_argument_get_arg_type(cmd->args, 3, &len);
107   if (!id_string)
108     goto out;
109
110   channel_name = strdup(tmp);
111
112   /* Add the channel to our local list. */
113   id = silc_id_payload_parse_id(id_string, len);
114   entry = silc_idlist_add_channel(server->local_list, channel_name, 
115                                   SILC_CHANNEL_MODE_NONE, id, 
116                                   server->id_entry->router, NULL);
117   if (!entry) {
118     silc_free(channel_name);
119     silc_free(id);
120     goto out;
121   }
122
123   entry->global_users = TRUE;
124
125   /* Execute pending JOIN command so that the client who originally
126      wanted to join the channel will be joined after all. */
127   SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN);
128
129  out:
130   silc_server_command_reply_free(cmd);
131 }
132
133 /* Received reply for forwarded IDENTIFY command. We have received the
134    requested identify information now and we will cache it. After this we
135    will call the pending command so that the requestee gets the information
136    after all. */
137
138 SILC_SERVER_CMD_REPLY_FUNC(identify)
139 {
140   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
141   SilcServer server = cmd->server;
142   SilcCommandStatus status;
143
144   SILC_LOG_DEBUG(("Start"));
145
146   SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
147   if (status != SILC_STATUS_OK)
148     goto out;
149
150   /* Process one identify reply */
151   if (status == SILC_STATUS_OK) {
152     SilcClientID *client_id;
153     unsigned int len;
154     unsigned char *id_data;
155     char *nickname, *username;
156
157     id_data = silc_argument_get_arg_type(cmd->args, 2, &len);
158     nickname = silc_argument_get_arg_type(cmd->args, 3, NULL);
159     if (!id_data || !nickname)
160       goto out;
161
162     username = silc_argument_get_arg_type(cmd->args, 4, NULL);
163     client_id = silc_id_payload_parse_id(id_data, len);
164
165     /* Add the client always to our global list. If normal or router server
166        ever gets here it means they don't have this client's information
167        in their cache. */
168     silc_idlist_add_client(server->global_list, strdup(nickname),
169                            username, NULL, client_id, NULL, NULL);
170   }
171
172   if (status == SILC_STATUS_LIST_START) {
173
174   }
175
176   if (status == SILC_STATUS_LIST_END) {
177
178   }
179
180   /* Execute pending IDENTIFY command so that the client who originally
181      requested the identify information will get it after all. */
182   SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_IDENTIFY);
183
184  out:
185   silc_server_command_reply_free(cmd);
186 }