Added SILC Server library.
[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 - 2005 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   vsnprintf(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 /****************************** Notify packets ******************************/
89
90 /* Sends notify packet.  Each variable argument format in the argument list
91    must be { argument data, argument length }. */
92
93 SilcBool silc_server_send_notify(SilcServer server,
94                                  SilcPacketStream stream,
95                                  SilcBool broadcast,
96                                  SilcNotifyType type,
97                                  SilcUInt32 argc, ...)
98 {
99   va_list ap;
100   SilcBuffer packet;
101   SilcBool ret = FALSE;
102
103   if (!stream)
104     return FALSE;
105
106   va_start(ap, argc);
107
108   packet = silc_notify_payload_encode(type, argc, ap);
109   if (!packet) {
110     va_end(ap);
111     return ret;
112   }
113
114   ret = silc_packet_send(stream, SILC_PACKET_NOTIFY,
115                          broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
116                          packet->data, silc_buffer_len(packet));
117
118 #if 0
119   /* Send to backup routers if this is being broadcasted to primary
120      router.  The silc_server_backup_send checks further whether to
121      actually send it or not. */
122   if ((broadcast && stream == SILC_PRIMARY_ROUTE(server)) ||
123       (broadcast && !SILC_PRIMARY_ROUTE(server)))
124     silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
125                             packet->data, packet->len, FALSE, TRUE);
126 #endif /* 0 */
127
128   silc_buffer_free(packet);
129   va_end(ap);
130
131   return ret;
132 }
133
134 /* Sends current motd to client in notify packet */
135
136 SilcBool silc_server_send_motd(SilcServer server, SilcPacketStream stream)
137 {
138   char *motd, *motd_file = NULL;
139   SilcUInt32 motd_len;
140   SilcBool ret = FALSE;
141
142   if (!stream || !server->params)
143     return FALSE;
144
145   motd_file = server->params->server_info->motd_file;
146   if (!motd_file)
147     return FALSE;
148
149   motd = silc_file_readfile(motd_file, &motd_len);
150   if (!motd)
151     return FALSE;
152
153   motd[motd_len] = 0;
154   ret = silc_server_send_notify(server, stream, FALSE,
155                                 SILC_NOTIFY_TYPE_MOTD, 1, motd, motd_len);
156   silc_free(motd);
157
158   return ret;
159 }
160
161
162 /* Sends notify packet and gets the arguments from the `args' Argument
163    Payloads. */
164
165 SilcBool silc_server_send_notify_args(SilcPacketStream stream,
166                                       SilcBool broadcast,
167                                       SilcNotifyType type,
168                                       SilcUInt32 argc,
169                                       SilcBuffer args)
170 {
171   SilcBuffer packet;
172   SilcBool ret = FALSE;
173
174   if (!stream)
175     return FALSE;
176
177   packet = silc_notify_payload_encode_args(type, argc, args);
178   if (!packet)
179     return ret;
180
181   ret = silc_packet_send(stream, SILC_PACKET_NOTIFY,
182                          broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
183                          packet->data, silc_buffer_len(packet));
184
185   silc_buffer_free(packet);
186   return ret;
187 }
188
189 /* Send CHANNEL_CHANGE notify type. This tells the receiver to replace the
190    `old_id' with the `new_id'. */
191
192 SilcBool silc_server_send_notify_channel_change(SilcServer server,
193                                                 SilcPacketStream stream,
194                                                 SilcBool broadcast,
195                                                 SilcChannelID *old_id,
196                                                 SilcChannelID *new_id)
197 {
198   SilcBuffer idp1, idp2;
199   SilcBool ret = FALSE;
200
201   if (!server || !stream)
202     return ret;
203
204   idp1 = silc_id_payload_encode((void *)old_id, SILC_ID_CHANNEL);
205   idp2 = silc_id_payload_encode((void *)new_id, SILC_ID_CHANNEL);
206   if (!idp1 || !idp2)
207     return ret;
208
209   ret = silc_server_send_notify(server, stream, broadcast,
210                                 SILC_NOTIFY_TYPE_CHANNEL_CHANGE,
211                                 2, idp1->data, silc_buffer_len(idp1),
212                                 idp2->data, silc_buffer_len(idp2));
213   silc_buffer_free(idp1);
214   silc_buffer_free(idp2);
215
216   return ret;
217 }