Added preliminary Symbian support.
[silc.git] / lib / silcserver / server_send.c
1 /*
2
3   server_send.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2006 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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id: */
20
21 #include "silc.h"
22 #include "silcserver.h"
23 #include "server_internal.h"
24
25 /******************************* Heartbeat **********************************/
26
27 /* Send the heartbeat packet. */
28
29 SilcBool silc_server_send_heartbeat(SilcPacketStream stream)
30 {
31   return stream ? silc_packet_send(stream, SILC_PACKET_HEARTBEAT, 0,
32                                    NULL, 0) : FALSE;
33 }
34
35
36 /********************************* Error ************************************/
37
38 /* Sends error packet. */
39
40 SilcBool silc_server_send_error(SilcPacketStream stream, const char *fmt, ...)
41 {
42   unsigned char buf[2048];
43   va_list ap;
44
45   if (!stream)
46     return FALSE;
47
48   memset(buf, 0, sizeof(buf));
49   va_start(ap, fmt);
50   vsilc_snprintf(buf, sizeof(buf) - 1, fmt, ap);
51   va_end(ap);
52
53   return silc_packet_send(stream, SILC_PACKET_ERROR, 0, buf, strlen(buf));
54 }
55
56
57 /********************************* New ID ***********************************/
58
59 /* Sends New ID packet.  The packet is used to distribute information about
60    new registered clients, servers and channels.  If the argument `broadcast'
61    is TRUE then the packet is sent as broadcast packet. */
62
63 SilcBool silc_server_send_new_id(SilcPacketStream stream,
64                                  SilcBool broadcast,
65                                  void *id, SilcIdType id_type)
66 {
67   SilcBuffer idp;
68   SilcBool ret = FALSE;
69
70   if (!stream || !id)
71     return ret;
72
73   SILC_LOG_DEBUG(("Sending new ID (%s)", silc_id_render(id, id_type)));
74
75   idp = silc_id_payload_encode(id, id_type);
76   if (!idp)
77     return ret;
78
79   ret = silc_packet_send(stream, SILC_PACKET_NEW_ID,
80                          broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
81                          idp->data, silc_buffer_len(idp));
82
83   silc_buffer_free(idp);
84   return ret;
85 }
86
87
88 /****************************** Command packets *****************************/
89
90 /* Generic function to send any command. The arguments must be sent already
91    encoded into correct form in correct order, and they must as follows:
92    { argument type, argument data, argument length }. */
93
94 SilcBool silc_server_send_command(SilcServer server,
95                                   SilcPacketStream stream,
96                                   SilcCommand command,
97                                   SilcUInt16 ident,
98                                   SilcUInt32 argc, ...)
99 {
100   SilcBuffer packet;
101   va_list ap;
102   SilcBool ret = FALSE;
103
104   /* Statistics */
105   server->stat.commands_sent++;
106
107   va_start(ap, argc);
108
109   packet = silc_command_payload_encode_vap(command, ident, argc, ap);
110   if (!packet) {
111     va_end(ap);
112     return ret;
113   }
114
115   ret = silc_packet_send(stream, SILC_PACKET_COMMAND, 0,
116                          packet->data, silc_buffer_len(packet));
117
118   silc_buffer_free(packet);
119   va_end(ap);
120
121   return ret;
122 }
123
124 /* Generic function to send a command reply.  The arguments must be sent
125    already encoded into correct form in correct order, and they must be
126    { argument type, argument data, argument length }. */
127
128 SilcBool silc_server_send_command_reply(SilcServer server,
129                                         SilcPacketStream stream,
130                                         SilcCommand command,
131                                         SilcStatus status,
132                                         SilcStatus error,
133                                         SilcUInt16 ident,
134                                         SilcUInt32 argc, ...)
135 {
136   SilcBuffer packet;
137   va_list ap;
138   SilcBool ret = FALSE;
139
140   /* Statistics */
141   server->stat.commands_sent++;
142
143   va_start(ap, argc);
144
145   packet = silc_command_reply_payload_encode_vap(command, status, error,
146                                                  ident, argc, ap);
147   if (!packet) {
148     va_end(ap);
149     return ret;
150   }
151
152   ret = silc_packet_send(stream, SILC_PACKET_COMMAND_REPLY, 0,
153                          packet->data, silc_buffer_len(packet));
154
155   silc_buffer_free(packet);
156   va_end(ap);
157
158   return ret;
159 }
160
161
162 /****************************** Notify packets ******************************/
163
164 /* Sends notify packet.  Each variable argument format in the argument list
165    must be { argument data, argument length }. */
166
167 SilcBool silc_server_send_notify(SilcServer server,
168                                  SilcPacketStream stream,
169                                  SilcBool broadcast,
170                                  SilcNotifyType type,
171                                  SilcUInt32 argc, ...)
172 {
173   va_list ap;
174   SilcBuffer packet;
175   SilcBool ret = FALSE;
176
177   if (!stream)
178     return FALSE;
179
180   va_start(ap, argc);
181
182   packet = silc_notify_payload_encode(type, argc, ap);
183   if (!packet) {
184     va_end(ap);
185     return ret;
186   }
187
188   ret = silc_packet_send(stream, SILC_PACKET_NOTIFY,
189                          broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
190                          packet->data, silc_buffer_len(packet));
191
192 #if 0
193   /* Send to backup routers if this is being broadcasted to primary
194      router.  The silc_server_backup_send checks further whether to
195      actually send it or not. */
196   if ((broadcast && stream == SILC_PRIMARY_ROUTE(server)) ||
197       (broadcast && !SILC_PRIMARY_ROUTE(server)))
198     silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
199                             packet->data, packet->len, FALSE, TRUE);
200 #endif /* 0 */
201
202   silc_buffer_free(packet);
203   va_end(ap);
204
205   return ret;
206 }
207
208 /* Sends current motd to client in notify packet */
209
210 SilcBool silc_server_send_motd(SilcServer server, SilcPacketStream stream)
211 {
212   char *motd, *motd_file = NULL;
213   SilcUInt32 motd_len;
214   SilcBool ret = FALSE;
215
216   if (!stream || !server->params)
217     return FALSE;
218
219   motd_file = server->params->server_info->motd_file;
220   if (!motd_file)
221     return FALSE;
222
223   motd = silc_file_readfile(motd_file, &motd_len);
224   if (!motd)
225     return FALSE;
226
227   motd[motd_len] = 0;
228   ret = silc_server_send_notify(server, stream, FALSE,
229                                 SILC_NOTIFY_TYPE_MOTD, 1, motd, motd_len);
230   silc_free(motd);
231
232   return ret;
233 }
234
235
236 /* Sends notify packet and gets the arguments from the `args' Argument
237    Payloads. */
238
239 SilcBool silc_server_send_notify_args(SilcPacketStream stream,
240                                       SilcBool broadcast,
241                                       SilcNotifyType type,
242                                       SilcUInt32 argc,
243                                       SilcBuffer args)
244 {
245   SilcBuffer packet;
246   SilcBool ret = FALSE;
247
248   if (!stream)
249     return FALSE;
250
251   packet = silc_notify_payload_encode_args(type, argc, args);
252   if (!packet)
253     return ret;
254
255   ret = silc_packet_send(stream, SILC_PACKET_NOTIFY,
256                          broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
257                          packet->data, silc_buffer_len(packet));
258
259   silc_buffer_free(packet);
260   return ret;
261 }
262
263 /* Send CHANNEL_CHANGE notify type. This tells the receiver to replace the
264    `old_id' with the `new_id'. */
265
266 SilcBool silc_server_send_notify_channel_change(SilcServer server,
267                                                 SilcPacketStream stream,
268                                                 SilcBool broadcast,
269                                                 SilcChannelID *old_id,
270                                                 SilcChannelID *new_id)
271 {
272   SilcBuffer idp1, idp2;
273   SilcBool ret = FALSE;
274
275   if (!server || !stream)
276     return ret;
277
278   idp1 = silc_id_payload_encode((void *)old_id, SILC_ID_CHANNEL);
279   idp2 = silc_id_payload_encode((void *)new_id, SILC_ID_CHANNEL);
280   if (!idp1 || !idp2)
281     return ret;
282
283   ret = silc_server_send_notify(server, stream, broadcast,
284                                 SILC_NOTIFY_TYPE_CHANNEL_CHANGE,
285                                 2, idp1->data, silc_buffer_len(idp1),
286                                 idp2->data, silc_buffer_len(idp2));
287   silc_buffer_free(idp1);
288   silc_buffer_free(idp2);
289
290   return ret;
291 }