Changed to use new generic payloads.
[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 char *id_string;
90   char *channel_name, *tmp;
91
92   SILC_LOG_DEBUG(("Start"));
93
94   tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
95   SILC_GET16_MSB(status, tmp);
96   if (status != SILC_STATUS_OK)
97     goto out;
98
99   /* Get channel name */
100   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
101   if (!tmp)
102     goto out;
103
104   /* Get channel ID */
105   id_string = silc_argument_get_arg_type(cmd->args, 3, NULL);
106   if (!id_string)
107     goto out;
108
109   channel_name = strdup(tmp);
110
111   /* Add the channel to our local list. */
112   id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
113   entry = silc_idlist_add_channel(server->local_list, channel_name, 
114                                   SILC_CHANNEL_MODE_NONE, id, 
115                                   server->id_entry->router, NULL);
116   if (!entry)
117     goto out;
118
119   entry->global_users = TRUE;
120
121   /* Execute pending JOIN command so that the client who originally
122      wanted to join the channel will be joined after all. */
123   SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN);
124
125  out:
126   silc_server_command_reply_free(cmd);
127 }
128
129 /* Received reply for forwarded IDENTIFY command. We have received the
130    requested identify information now and we will cache it. After this we
131    will call the pending command so that the requestee gets the information
132    after all. */
133
134 SILC_SERVER_CMD_REPLY_FUNC(identify)
135 {
136   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
137   SilcServer server = cmd->server;
138   SilcCommandStatus status;
139   unsigned char *tmp;
140
141   SILC_LOG_DEBUG(("Start"));
142
143   tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
144   SILC_GET16_MSB(status, tmp);
145   if (status != SILC_STATUS_OK)
146     goto out;
147
148   /* Process one identify reply */
149   if (status == SILC_STATUS_OK) {
150     SilcClientID *client_id;
151     unsigned char *id_data;
152     char *nickname, *username;
153
154     id_data = silc_argument_get_arg_type(cmd->args, 2, NULL);
155     nickname = silc_argument_get_arg_type(cmd->args, 3, NULL);
156     if (!id_data || !nickname)
157       goto out;
158
159     username = silc_argument_get_arg_type(cmd->args, 4, NULL);
160
161     client_id = silc_id_str2id(id_data, SILC_ID_CLIENT);
162
163     /* Add the client always to our global list. If normal or router server
164        ever gets here it means they don't have this client's information
165        in their cache. */
166     silc_idlist_add_client(server->global_list, strdup(nickname),
167                            username, NULL, client_id, NULL, NULL, NULL,
168                            NULL, NULL, NULL, NULL);
169   }
170
171   if (status == SILC_STATUS_LIST_START) {
172
173   }
174
175   if (status == SILC_STATUS_LIST_END) {
176
177   }
178
179   /* Execute pending IDENTIFY command so that the client who originally
180      requested the identify information will get it after all. */
181   SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_IDENTIFY);
182
183  out:
184   silc_server_command_reply_free(cmd);
185 }