5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2003 Pekka Riikonen
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.
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.
20 #include "silcincludes.h"
21 #include "silcclient.h"
24 /******* Map Client Routines *************************************************/
26 SILC_TASK_CALLBACK(silc_map_process_done)
28 SilcMap map = context;
31 silc_schedule_stop(map->client->schedule);
34 /* This function processes the data that was gathered from the server
35 and producess the outputs and the map. */
37 void silc_map_process_data(SilcMap map, SilcMapConnection mapconn)
41 SilcInt16 r, g, b, lr, lg, lb;
45 SILC_LOG_DEBUG(("Processing the data from server (%d/%d)",
46 map->conn_num, map->conns_num));
48 /* Change colors according to server status */
49 silc_map_parse_color(mapconn->up_color, &r, &g, &b);
50 silc_map_parse_color(mapconn->up_text_color, &lr, &lg, &lb);
52 silc_map_parse_color(mapconn->down_color, &r, &g, &b);
53 silc_map_parse_color(mapconn->down_text_color, &lr, &lg, &lb);
56 /* Execute the map commands */
57 silc_dlist_start(mapconn->commands);
58 while ((cmd = silc_dlist_get(mapconn->commands)) != SILC_LIST_END) {
60 if (silc_map_cut(map, cmd->x, cmd->y, cmd->width,
61 cmd->height, &ret_map)) {
62 silc_map_write_ppm(ret_map, cmd->filename);
63 silc_map_free(ret_map);
74 silc_map_draw_line(map, cmd->width, cmd->x, cmd->y, cmd->x2, cmd->y2,
85 silc_map_draw_text(map, cmd->text, cmd->x, cmd->y, lr, lg, lb);
90 if (cmd->draw_circle) {
96 if (cmd->lcolor_set) {
101 silc_map_draw_circle(map, cmd->x, cmd->y, r, g, b,
102 cmd->text, cmd->lposx, cmd->lposy, lr, lg, lb);
106 if (cmd->draw_rectangle) {
107 if (cmd->color_set) {
112 if (cmd->lcolor_set) {
117 silc_map_draw_rectangle(map, cmd->x, cmd->y, r, g, b,
118 cmd->text, cmd->lposx, cmd->lposy, lr, lg, lb);
124 /* Write the html data file */
125 if (map->writehtml.writehtml)
126 silc_map_writehtml(map, mapconn);
128 /* If this was last connection, we are done and ready to quit. */
129 if (map->conn_num == map->conns_num) {
130 SILC_LOG_DEBUG(("All connections processed"));
133 if (map->writemap.writemap)
134 silc_map_write_ppm(map, map->writemap.filename);
135 for (i = 0; i < map->cut_count; i++) {
136 if (silc_map_cut(map, map->cut[i].x, map->cut[i].y, map->cut[i].width,
137 map->cut[i].height, &ret_map)) {
138 silc_map_write_ppm(ret_map, map->cut[i].filename);
139 silc_map_free(ret_map);
143 /* Write the HTML index file */
144 if (map->writehtml.writehtml)
145 silc_map_writehtml_index(map);
147 /* Write the HTML map file(s) */
148 silc_map_writemaphtml(map);
150 /* Schedule to stop */
151 silc_schedule_task_add(map->client->schedule, 0,
152 silc_map_process_done, map, 0, 1,
153 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
157 /* Timeout callback to detect if server is down. */
159 SILC_TASK_CALLBACK(silc_map_connect_timeout)
161 SilcMapConnection mapconn = context;
163 SILC_LOG_DEBUG(("Connection timeout"));
165 /* The server is down. */
166 mapconn->down = TRUE;
168 /* Continue to produce the data and the map. */
169 silc_map_process_data(mapconn->map, mapconn);
172 /* Close connection to server */
174 SILC_TASK_CALLBACK(silc_map_connect_close)
176 SilcMapConnection mapconn = context;
178 SILC_LOG_DEBUG(("Closing connection to %s:%d", mapconn->conn->remote_host,
179 mapconn->conn->remote_port));
181 silc_client_close_connection(mapconn->conn->client, mapconn->conn);
183 /* Continue to produce the data and the map. */
184 silc_map_process_data(mapconn->map, mapconn);
187 /* Create connection to remote server to gather information about it. */
189 void silc_map_connect(SilcMap map, SilcMapConnection mapconn)
193 if (!mapconn->connect) {
194 silc_schedule_task_add(map->client->schedule, 0,
195 silc_map_connect_timeout, mapconn, 0, 1,
196 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
200 /* First configure IP is used to connect. */
201 silc_dlist_start(mapconn->ips);
202 ip = silc_dlist_get(mapconn->ips);
204 SILC_LOG_DEBUG(("Creating connection to server %s:%d", ip, mapconn->port));
206 /* Create connection. We'll continue in the silc_connected after
207 connection is created. */
208 silc_client_connect_to_server(map->client, NULL,
209 mapconn->port, ip, mapconn);
211 /* Set connect timeout to detect if the server is down. */
212 silc_schedule_task_add(map->client->schedule, 0,
213 silc_map_connect_timeout, mapconn,
214 mapconn->connect_timeout, 0,
215 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
219 /******* SILC Client Operations **********************************************/
221 /* "say" client operation is a message from the client library to the
222 application. It may include error messages or something else. We
223 just dump them to screen. */
226 silc_say(SilcClient client, SilcClientConnection conn,
227 SilcClientMessageType type, char *msg, ...)
233 /* Message for a channel. The `sender' is the sender of the message
234 The `channel' is the channel. The `message' is the message. Note
235 that `message' maybe NULL. The `flags' indicates message flags
236 and it is used to determine how the message can be interpreted
237 (like it may tell the message is multimedia message). */
240 silc_channel_message(SilcClient client, SilcClientConnection conn,
241 SilcClientEntry sender, SilcChannelEntry channel,
242 SilcMessagePayload payload,
243 SilcMessageFlags flags, const unsigned char *message,
244 SilcUInt32 message_len)
250 /* Private message to the client. The `sender' is the sender of the
251 message. The message is `message'and maybe NULL. The `flags'
252 indicates message flags and it is used to determine how the message
253 can be interpreted (like it may tell the message is multimedia
257 silc_private_message(SilcClient client, SilcClientConnection conn,
258 SilcClientEntry sender, SilcMessagePayload payload,
259 SilcMessageFlags flags,
260 const unsigned char *message,
261 SilcUInt32 message_len)
267 /* Notify message to the client. The notify arguments are sent in the
268 same order as servers sends them. The arguments are same as received
269 from the server except for ID's. If ID is received application receives
270 the corresponding entry to the ID. For example, if Client ID is received
271 application receives SilcClientEntry. Also, if the notify type is
272 for channel the channel entry is sent to application (even if server
273 does not send it because client library gets the channel entry from
274 the Channel ID in the packet's header). */
277 silc_notify(SilcClient client, SilcClientConnection conn,
278 SilcNotifyType type, ...)
284 /* Command handler. This function is called always in the command function.
285 If error occurs it will be called as well. `conn' is the associated
286 client connection. `cmd_context' is the command context that was
287 originally sent to the command. `success' is FALSE if error occurred
288 during command. `command' is the command being processed. It must be
289 noted that this is not reply from server. This is merely called just
290 after application has called the command. Just to tell application
291 that the command really was processed. */
294 silc_command(SilcClient client, SilcClientConnection conn,
295 SilcClientCommandContext cmd_context, bool success,
296 SilcCommand command, SilcStatus status)
302 /* Command reply handler. This function is called always in the command reply
303 function. If error occurs it will be called as well. Normal scenario
304 is that it will be called after the received command data has been parsed
305 and processed. The function is used to pass the received command data to
308 `conn' is the associated client connection. `cmd_payload' is the command
309 payload data received from server and it can be ignored. It is provided
310 if the application would like to re-parse the received command data,
311 however, it must be noted that the data is parsed already by the library
312 thus the payload can be ignored. `success' is FALSE if error occurred.
313 In this case arguments are not sent to the application. The `status' is
314 the command reply status server returned. The `command' is the command
315 reply being processed. The function has variable argument list and each
316 command defines the number and type of arguments it passes to the
317 application (on error they are not sent). */
320 silc_command_reply(SilcClient client, SilcClientConnection conn,
321 SilcCommandPayload cmd_payload, bool success,
322 SilcCommand command, SilcStatus status, ...)
324 SilcMapConnection mapconn = conn->context;
327 /* If error occurred in client library with our command, print the error */
328 if (status != SILC_STATUS_OK)
329 fprintf(stderr, "COMMAND REPLY %s: %s\n",
330 silc_get_command_name(command),
331 silc_get_status_message(status));
336 va_start(va, status);
339 case SILC_COMMAND_STATS:
341 unsigned char *stats = va_arg(va, unsigned char *);
342 SilcUInt32 stats_len = va_arg(va, SilcUInt32);
343 SilcBufferStruct buf;
345 SILC_LOG_DEBUG(("STATS command reply"));
347 /* Get statistics structure */
348 silc_buffer_set(&buf, stats, stats_len);
349 silc_buffer_unformat(&buf,
350 SILC_STR_UI_INT(&mapconn->data.starttime),
351 SILC_STR_UI_INT(&mapconn->data.uptime),
352 SILC_STR_UI_INT(&mapconn->data.clients),
353 SILC_STR_UI_INT(&mapconn->data.channels),
354 SILC_STR_UI_INT(&mapconn->data.server_ops),
355 SILC_STR_UI_INT(&mapconn->data.router_ops),
356 SILC_STR_UI_INT(&mapconn->data.cell_clients),
357 SILC_STR_UI_INT(&mapconn->data.cell_channels),
358 SILC_STR_UI_INT(&mapconn->data.cell_servers),
359 SILC_STR_UI_INT(&mapconn->data.all_clients),
360 SILC_STR_UI_INT(&mapconn->data.all_channels),
361 SILC_STR_UI_INT(&mapconn->data.all_servers),
362 SILC_STR_UI_INT(&mapconn->data.all_routers),
363 SILC_STR_UI_INT(&mapconn->data.all_server_ops),
364 SILC_STR_UI_INT(&mapconn->data.all_router_ops),
367 mapconn->stats_received = TRUE;
371 case SILC_COMMAND_MOTD:
373 char *motd = va_arg(va, char *);
375 SILC_LOG_DEBUG(("MOTD command reply"));
377 mapconn->data.motd = strdup(motd);
378 mapconn->motd_received = TRUE;
388 if (mapconn->motd && !mapconn->motd_received)
390 if (!mapconn->stats_received)
393 /* All data is gathered, time to disconnect from the server. */
394 silc_schedule_task_add(client->schedule, 0,
395 silc_map_connect_close, mapconn, 0, 1,
396 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
400 /* Called to indicate that connection was either successfully established
401 or connecting failed. This is also the first time application receives
402 the SilcClientConnection objecet which it should save somewhere.
403 If the `success' is FALSE the application must always call the function
404 silc_client_close_connection. */
407 silc_connected(SilcClient client, SilcClientConnection conn,
408 SilcClientConnectionStatus status)
410 SilcMapConnection mapconn = conn->context;
411 SilcMap map = mapconn->map;
413 silc_schedule_task_del_by_context(client->schedule, mapconn);
415 if (status == SILC_CLIENT_CONN_ERROR) {
416 fprintf(stderr, "Could not connect to server\n");
417 silc_client_close_connection(client, conn);
419 /* Mark that this server is down. */
420 silc_schedule_task_add(map->client->schedule, 0,
421 silc_map_connect_timeout, mapconn, 0, 1,
422 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
427 /* Already timeouted */
428 silc_client_close_connection(client, conn);
432 SILC_LOG_DEBUG(("Connected to server %s:%d", conn->remote_host,
435 mapconn->conn = conn;
438 silc_client_command_call(client, conn, "STATS");
440 /* Get motd if requested */
444 silc_dlist_start(mapconn->hostnames);
445 hostname = silc_dlist_get(mapconn->hostnames);
446 memset(motd, 0, sizeof(motd));
447 silc_strncat(motd, sizeof(motd), "MOTD ", 5);
448 silc_strncat(motd, sizeof(motd), hostname, strlen(hostname));
449 silc_client_command_call(client, conn, motd);
454 /* Called to indicate that connection was disconnected to the server.
455 The `status' may tell the reason of the disconnection, and if the
456 `message' is non-NULL it may include the disconnection message
457 received from server. */
460 silc_disconnected(SilcClient client, SilcClientConnection conn,
461 SilcStatus status, const char *message)
463 SilcMapConnection mapconn = conn->context;
465 silc_schedule_task_del_by_context(client->schedule, mapconn);
467 SILC_LOG_DEBUG(("Disconnected from server %s:%d", conn->remote_host,
470 mapconn->conn = NULL;
474 /* Find authentication method and authentication data by hostname and
475 port. The hostname may be IP address as well. When the authentication
476 method has been resolved the `completion' callback with the found
477 authentication method and authentication data is called. The `conn'
481 silc_get_auth_method(SilcClient client, SilcClientConnection conn,
482 char *hostname, SilcUInt16 port,
483 SilcGetAuthMeth completion,
487 completion(TRUE, SILC_AUTH_NONE, NULL, 0, context);
491 /* Verifies received public key. The `conn_type' indicates which entity
492 (server, client etc.) has sent the public key. If user decides to trust
493 the application may save the key as trusted public key for later
494 use. The `completion' must be called after the public key has been
498 silc_verify_public_key(SilcClient client, SilcClientConnection conn,
499 SilcSocketType conn_type, unsigned char *pk,
500 SilcUInt32 pk_len, SilcSKEPKType pk_type,
501 SilcVerifyPublicKey completion, void *context)
503 /* Accept all keys without verification */
504 completion(TRUE, context);
508 /* Ask (interact, that is) a passphrase from user. The passphrase is
509 returned to the library by calling the `completion' callback with
510 the `context'. The returned passphrase SHOULD be in UTF-8 encoded,
511 if not then the library will attempt to encode. */
514 silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
515 SilcAskPassphrase completion, void *context)
517 completion(NULL, 0, context);
521 /* Notifies application that failure packet was received. This is called
522 if there is some protocol active in the client. The `protocol' is the
523 protocol context. The `failure' is opaque pointer to the failure
524 indication. Note, that the `failure' is protocol dependant and
525 application must explicitly cast it to correct type. Usually `failure'
526 is 32 bit failure type (see protocol specs for all protocol failure
530 silc_failure(SilcClient client, SilcClientConnection conn,
531 SilcProtocol protocol, void *failure)
533 fprintf(stderr, "Connecting failed (protocol failure)\n");
537 /* Asks whether the user would like to perform the key agreement protocol.
538 This is called after we have received an key agreement packet or an
539 reply to our key agreement packet. This returns TRUE if the user wants
540 the library to perform the key agreement protocol and FALSE if it is not
541 desired (application may start it later by calling the function
542 silc_client_perform_key_agreement). If TRUE is returned also the
543 `completion' and `context' arguments must be set by the application. */
546 silc_key_agreement(SilcClient client, SilcClientConnection conn,
547 SilcClientEntry client_entry, const char *hostname,
548 SilcUInt16 port, SilcKeyAgreementCallback *completion,
555 /* Notifies application that file transfer protocol session is being
556 requested by the remote client indicated by the `client_entry' from
557 the `hostname' and `port'. The `session_id' is the file transfer
558 session and it can be used to either accept or reject the file
559 transfer request, by calling the silc_client_file_receive or
560 silc_client_file_close, respectively. */
563 silc_ftp(SilcClient client, SilcClientConnection conn,
564 SilcClientEntry client_entry, SilcUInt32 session_id,
565 const char *hostname, SilcUInt16 port)
571 /* Delivers SILC session detachment data indicated by `detach_data' to the
572 application. If application has issued SILC_COMMAND_DETACH command
573 the client session in the SILC network is not quit. The client remains
574 in the network but is detached. The detachment data may be used later
575 to resume the session in the SILC Network. The appliation is
576 responsible of saving the `detach_data', to for example in a file.
578 The detachment data can be given as argument to the functions
579 silc_client_connect_to_server, or silc_client_add_connection when
580 creating connection to remote server, inside SilcClientConnectionParams
581 structure. If it is provided the client library will attempt to resume
582 the session in the network. After the connection is created
583 successfully, the application is responsible of setting the user
584 interface for user into the same state it was before detaching (showing
585 same channels, channel modes, etc). It can do this by fetching the
586 information (like joined channels) from the client library. */
589 silc_detach(SilcClient client, SilcClientConnection conn,
590 const unsigned char *detach_data, SilcUInt32 detach_data_len)
595 /* This structure and all the functions were taken from the
596 lib/silcclient/client_ops_example.c. */
597 SilcClientOperations silc_map_client_ops = {
599 silc_channel_message,
600 silc_private_message,
606 silc_get_auth_method,
607 silc_verify_public_key,