The SILC Project

source navigation ]
identifier search ]
freetext search ]
file search ]

silc/silcmap/silcmap_client.c

  1 /*
  2 
  3   silcmap_client.c
  4 
  5   Author: Pekka Riikonen <priikone@silcnet.org>
  6 
  7   Copyright (C) 2003 - 2004 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 
 20 #include "silcincludes.h"
 21 #include "silcclient.h"
 22 #include "silcmap.h"
 23 
 24 /******* Map Client Routines *************************************************/
 25 
 26 SILC_TASK_CALLBACK(silc_map_process_done)
 27 {
 28   SilcMap map = context;
 29 
 30   /* Program stops */
 31   silc_schedule_stop(map->client->schedule);
 32 }
 33 
 34 /* This function processes the data that was gathered from the server
 35    and producess the outputs and the map. */
 36 
 37 void silc_map_process_data(SilcMap map, SilcMapConnection mapconn)
 38 {
 39   SilcMapCommand cmd;
 40   SilcMap ret_map;
 41   SilcInt16 r, g, b, lr, lg, lb;
 42   int i;
 43 
 44   map->conn_num++;
 45 
 46   SILC_LOG_DEBUG(("Processing the data from server (%d/%d)",
 47                   map->conn_num, map->conns_num));
 48 
 49   if (map->conn_num != map->conns_num)
 50     return;
 51 
 52   /* Load the map image to be processed */
 53   silc_free(map->bitmap);
 54   if (!map->loadmap.loadmap || !map->loadmap.filename) {
 55     silc_schedule_task_add(map->client->schedule, 0,
 56                            silc_map_process_done, map, 0, 1,
 57                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 58     return;
 59   }
 60 
 61   if (!silc_map_load_ppm(map, map->loadmap.filename)) {
 62     silc_schedule_task_add(map->client->schedule, 0,
 63                            silc_map_process_done, map, 0, 1,
 64                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 65     return;
 66   }
 67 
 68   /* Now process all received data one by one */
 69   silc_dlist_start(map->conns);
 70   while ((mapconn = silc_dlist_get(map->conns)) != SILC_LIST_END) {
 71 
 72     /* Change colors according to server status */
 73     silc_map_parse_color(mapconn->up_color, &r, &g, &b);
 74     silc_map_parse_color(mapconn->up_text_color, &lr, &lg, &lb);
 75     if (mapconn->down) {
 76       silc_map_parse_color(mapconn->down_color, &r, &g, &b);
 77       silc_map_parse_color(mapconn->down_text_color, &lr, &lg, &lb);
 78     }
 79 
 80     /* Execute the map commands */
 81     silc_dlist_start(mapconn->commands);
 82     while ((cmd = silc_dlist_get(mapconn->commands)) != SILC_LIST_END) {
 83       if (cmd->alon && cmd->alat) {
 84         cmd->x = silc_map_lon2x(map, cmd->alon);
 85         cmd->y = silc_map_lat2y(map, cmd->alat);
 86         if (cmd->blon && cmd->blat) {
 87           cmd->x2 = silc_map_lon2x(map, cmd->blon);
 88           cmd->y2 = silc_map_lat2y(map, cmd->blat);
 89         }
 90       }
 91 
 92       if (cmd->cut) {
 93         if (silc_map_cut(map, cmd->x, cmd->y, cmd->width,
 94                          cmd->height, &ret_map)) {
 95           silc_map_write_ppm(ret_map, cmd->filename);
 96           silc_map_free(ret_map);
 97         }
 98         continue;
 99       }
100 
101       if (cmd->draw_line) {
102         if (cmd->color_set) {
103           r = cmd->r;
104           g = cmd->g;
105           b = cmd->b;
106         }
107         silc_map_draw_line(map, cmd->width, cmd->x, cmd->y, cmd->x2, cmd->y2,
108                            r, g, b);
109         continue;
110       }
111 
112       if (cmd->draw_text) {
113         if (cmd->color_set) {
114           lr = cmd->r;
115           lg = cmd->g;
116           lb = cmd->b;
117         }
118         silc_map_draw_text(map, cmd->text, cmd->x, cmd->y, lr, lg, lb);
119         continue;
120       }
121 
122       if (cmd->draw_circle) {
123         if (cmd->color_set) {
124           r = cmd->r;
125           g = cmd->g;
126           b = cmd->b;
127         }
128         if (cmd->lcolor_set) {
129           lr = cmd->lr;
130           lg = cmd->lg;
131           lb = cmd->lb;
132         }
133         silc_map_draw_circle(map, cmd->x, cmd->y, r, g, b,
134                              cmd->text, cmd->lposx, cmd->lposy, lr, lg, lb);
135         continue;
136       }
137 
138       if (cmd->draw_rectangle) {
139         if (cmd->color_set) {
140           r = cmd->r;
141           g = cmd->g;
142           b = cmd->b;
143         }
144         if (cmd->lcolor_set) {
145           lr = cmd->lr;
146           lg = cmd->lg;
147           lb = cmd->lb;
148         }
149         silc_map_draw_rectangle(map, cmd->x, cmd->y, r, g, b,
150                                 cmd->text, cmd->lposx, cmd->lposy, lr, lg, lb);
151         continue;
152       }
153     }
154 
155     /* Write the html data file */
156     if (map->writehtml.writehtml)
157       silc_map_writehtml(map, mapconn);
158 
159     /* Write uptime reliability data */
160     if (map->writerel.writerel)
161       silc_map_writerel(map, mapconn);
162   }
163 
164   SILC_LOG_DEBUG(("All connections processed"));
165 
166   /* Produce output */
167   if (map->writemap.writemap)
168     silc_map_write_ppm(map, map->writemap.filename);
169   for (i = 0; i < map->cut_count; i++) {
170     if (map->cut[i].alon && map->cut[i].alat) {
171       map->cut[i].x = silc_map_lon2x(map, map->cut[i].alon);
172       map->cut[i].y = silc_map_lat2y(map, map->cut[i].alat);
173     }
174     if (silc_map_cut(map, map->cut[i].x, map->cut[i].y, map->cut[i].width,
175                      map->cut[i].height, &ret_map)) {
176       silc_map_write_ppm(ret_map, map->cut[i].filename);
177       silc_map_free(ret_map);
178     }
179   }
180 
181   /* Write the HTML index file */
182   if (map->writehtml.writehtml)
183     silc_map_writehtml_index(map);
184 
185   /* Write the HTML map file(s) */
186   silc_map_writemaphtml(map);
187 
188   /* Write uptime reliability graph */
189   if (map->writerel.writerel)
190     silc_map_writerelhtml(map);
191 
192   /* Schedule to stop */
193   silc_schedule_task_add(map->client->schedule, 0,
194                          silc_map_process_done, map, 0, 1,
195                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
196 }
197 
198 /* Timeout callback to detect if server is down. */
199 
200 SILC_TASK_CALLBACK(silc_map_connect_timeout)
201 {
202   SilcMapConnection mapconn = context;
203 
204   SILC_LOG_DEBUG(("Connection timeout"));
205 
206   silc_schedule_task_del_by_context(mapconn->map->client->schedule, mapconn);
207 
208   /* The server is down. */
209   mapconn->down = TRUE;
210 
211   /* Continue to produce the data and the map. */
212   silc_map_process_data(mapconn->map, mapconn);
213 }
214 
215 /* Timeout callback to detect if server is down. */
216 
217 SILC_TASK_CALLBACK(silc_map_data_timeout)
218 {
219   SilcMapConnection mapconn = context;
220 
221   SILC_LOG_DEBUG(("data timeout"));
222 
223   silc_schedule_task_del_by_context(mapconn->map->client->schedule, mapconn);
224 
225   /* The server is down. */
226   mapconn->down = TRUE;
227 
228   /* Close connection, we didn't get any data. */
229   SILC_LOG_DEBUG(("Closing connection to %s:%d", mapconn->conn->remote_host,
230                   mapconn->conn->remote_port));
231   silc_client_close_connection(mapconn->conn->client, mapconn->conn);
232 
233   /* Continue to produce the data and the map. */
234   silc_map_process_data(mapconn->map, mapconn);
235 }
236 
237 /* Close connection to server */
238 
239 SILC_TASK_CALLBACK(silc_map_connect_close)
240 {
241   SilcMapConnection mapconn = context;
242 
243   SILC_LOG_DEBUG(("Closing connection to %s:%d", mapconn->conn->remote_host,
244                   mapconn->conn->remote_port));
245 
246   silc_client_close_connection(mapconn->conn->client, mapconn->conn);
247 
248   /* Continue to produce the data and the map. */
249   silc_map_process_data(mapconn->map, mapconn);
250 }
251 
252 /* Create connection to remote server to gather information about it. */
253 
254 void silc_map_connect(SilcMap map, SilcMapConnection mapconn)
255 {
256   char *ip;
257 
258   if (!mapconn->connect) {
259     silc_schedule_task_add(map->client->schedule, 0,
260                            silc_map_connect_timeout, mapconn, 0, 1,
261                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
262     return;
263   }
264 
265   /* First configure IP is used to connect. */
266   silc_dlist_start(mapconn->ips);
267   ip = silc_dlist_get(mapconn->ips);
268 
269   SILC_LOG_DEBUG(("Creating connection to server %s:%d", ip, mapconn->port));
270 
271   /* Create connection.  We'll continue in the silc_connected after
272      connection is created. */
273   silc_client_connect_to_server(map->client, NULL,
274                                 mapconn->port, ip, mapconn);
275 
276   /* Set connect timeout to detect if the server is down. */
277   silc_schedule_task_add(map->client->schedule, 0,
278                          silc_map_connect_timeout, mapconn,
279                          mapconn->connect_timeout, 0,
280                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
281 }
282 
283 
284 /******* SILC Client Operations **********************************************/
285 
286 /* "say" client operation is a message from the client library to the
287    application.  It may include error messages or something else.  We
288    just dump them to screen. */
289 
290 static void
291 silc_say(SilcClient client, SilcClientConnection conn,
292          SilcClientMessageType type, char *msg, ...)
293 {
294 
295 }
296 
297 
298 /* Message for a channel. The `sender' is the sender of the message
299    The `channel' is the channel. The `message' is the message.  Note
300    that `message' maybe NULL.  The `flags' indicates message flags
301    and it is used to determine how the message can be interpreted
302    (like it may tell the message is multimedia message). */
303 
304 static void
305 silc_channel_message(SilcClient client, SilcClientConnection conn,
306                      SilcClientEntry sender, SilcChannelEntry channel,
307                      SilcMessagePayload payload,
308                      SilcMessageFlags flags, const unsigned char *message,
309                      SilcUInt32 message_len)
310 {
311 
312 }
313 
314 
315 /* Private message to the client. The `sender' is the sender of the
316    message. The message is `message'and maybe NULL.  The `flags'
317    indicates message flags  and it is used to determine how the message
318    can be interpreted (like it may tell the message is multimedia
319    message). */
320 
321 static void
322 silc_private_message(SilcClient client, SilcClientConnection conn,
323                      SilcClientEntry sender, SilcMessagePayload payload,
324                      SilcMessageFlags flags,
325                      const unsigned char *message,
326                      SilcUInt32 message_len)
327 {
328 
329 }
330 
331 
332 /* Notify message to the client. The notify arguments are sent in the
333    same order as servers sends them. The arguments are same as received
334    from the server except for ID's.  If ID is received application receives
335    the corresponding entry to the ID. For example, if Client ID is received
336    application receives SilcClientEntry.  Also, if the notify type is
337    for channel the channel entry is sent to application (even if server
338    does not send it because client library gets the channel entry from
339    the Channel ID in the packet's header). */
340 
341 static void
342 silc_notify(SilcClient client, SilcClientConnection conn,
343             SilcNotifyType type, ...)
344 {
345 
346 }
347 
348 
349 /* Command handler. This function is called always in the command function.
350    If error occurs it will be called as well. `conn' is the associated
351    client connection. `cmd_context' is the command context that was
352    originally sent to the command. `success' is FALSE if error occurred
353    during command. `command' is the command being processed. It must be
354    noted that this is not reply from server. This is merely called just
355    after application has called the command. Just to tell application
356    that the command really was processed. */
357 
358 static void
359 silc_command(SilcClient client, SilcClientConnection conn,
360              SilcClientCommandContext cmd_context, bool success,
361              SilcCommand command, SilcStatus status)
362 {
363 
364 }
365 
366 
367 /* Command reply handler. This function is called always in the command reply
368    function. If error occurs it will be called as well. Normal scenario
369    is that it will be called after the received command data has been parsed
370    and processed. The function is used to pass the received command data to
371    the application.
372 
373    `conn' is the associated client connection. `cmd_payload' is the command
374    payload data received from server and it can be ignored. It is provided
375    if the application would like to re-parse the received command data,
376    however, it must be noted that the data is parsed already by the library
377    thus the payload can be ignored. `success' is FALSE if error occurred.
378    In this case arguments are not sent to the application. The `status' is
379    the command reply status server returned. The `command' is the command
380    reply being processed. The function has variable argument list and each
381    command defines the number and type of arguments it passes to the
382    application (on error they are not sent). */
383 
384 static void
385 silc_command_reply(SilcClient client, SilcClientConnection conn,
386                    SilcCommandPayload cmd_payload, bool success,
387                    SilcCommand command, SilcStatus status, ...)
388 {
389   SilcMapConnection mapconn = conn->context;
390   va_list va;
391 
392   /* If error occurred in client library with our command, print the error */
393   if (status != SILC_STATUS_OK)
394     fprintf(stderr, "COMMAND REPLY %s: %s\n",
395             silc_get_command_name(command),
396             silc_get_status_message(status));
397 
398   if (!success)
399     return;
400 
401   va_start(va, status);
402 
403   switch (command) {
404   case SILC_COMMAND_STATS:
405     {
406       unsigned char *stats = va_arg(va, unsigned char *);
407       SilcUInt32 stats_len = va_arg(va, SilcUInt32);
408       SilcBufferStruct buf;
409 
410       SILC_LOG_DEBUG(("STATS command reply"));
411 
412       /* Get statistics structure */
413       silc_buffer_set(&buf, stats, stats_len);
414       silc_buffer_unformat(&buf,
415                            SILC_STR_UI_INT(&mapconn->data.starttime),
416                            SILC_STR_UI_INT(&mapconn->data.uptime),
417                            SILC_STR_UI_INT(&mapconn->data.clients),
418                            SILC_STR_UI_INT(&mapconn->data.channels),
419                            SILC_STR_UI_INT(&mapconn->data.server_ops),
420                            SILC_STR_UI_INT(&mapconn->data.router_ops),
421                            SILC_STR_UI_INT(&mapconn->data.cell_clients),
422                            SILC_STR_UI_INT(&mapconn->data.cell_channels),
423                            SILC_STR_UI_INT(&mapconn->data.cell_servers),
424                            SILC_STR_UI_INT(&mapconn->data.all_clients),
425                            SILC_STR_UI_INT(&mapconn->data.all_channels),
426                            SILC_STR_UI_INT(&mapconn->data.all_servers),
427                            SILC_STR_UI_INT(&mapconn->data.all_routers),
428                            SILC_STR_UI_INT(&mapconn->data.all_server_ops),
429                            SILC_STR_UI_INT(&mapconn->data.all_router_ops),
430                            SILC_STR_END);
431 
432       mapconn->stats_received = TRUE;
433     }
434     break;
435 
436   case SILC_COMMAND_MOTD:
437     {
438       char *motd = va_arg(va, char *);
439 
440       SILC_LOG_DEBUG(("MOTD command reply"));
441 
442       mapconn->data.motd = strdup(motd);
443       mapconn->motd_received = TRUE;
444     }
445     break;
446 
447   default:
448     break;
449   };
450 
451   va_end(va);
452 
453   if (mapconn->motd && !mapconn->motd_received)
454     return;
455   if (!mapconn->stats_received)
456     return;
457 
458   silc_schedule_task_del_by_context(client->schedule, mapconn);
459 
460   /* All data is gathered, time to disconnect from the server. */
461   silc_schedule_task_add(client->schedule, 0,
462                          silc_map_connect_close, mapconn, 0, 1,
463                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
464 }
465 
466 
467 /* Called to indicate that connection was either successfully established
468    or connecting failed.  This is also the first time application receives
469    the SilcClientConnection objecet which it should save somewhere.
470    If the `success' is FALSE the application must always call the function
471    silc_client_close_connection. */
472 
473 static void
474 silc_connected(SilcClient client, SilcClientConnection conn,
475                SilcClientConnectionStatus status)
476 {
477   SilcMapConnection mapconn = conn->context;
478   SilcMap map = mapconn->map;
479 
480   silc_schedule_task_del_by_context(client->schedule, mapconn);
481 
482   if (status == SILC_CLIENT_CONN_ERROR) {
483     fprintf(stderr, "Could not connect to server %s\n",
484                      conn->remote_host ? conn->remote_host : "");
485     silc_client_close_connection(client, conn);
486 
487     /* Mark that this server is down. */
488     silc_schedule_task_add(map->client->schedule, 0,
489                            silc_map_connect_timeout, mapconn, 0, 1,
490                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
491     return;
492   }
493 
494   if (mapconn->down) {
495     /* Already timeouted */
496     SILC_LOG_DEBUG(("Connection already timedout"));
497     silc_client_close_connection(client, conn);
498     return;
499   }
500 
501   SILC_LOG_DEBUG(("Connected to server %s:%d", conn->remote_host,
502                   conn->remote_port));
503 
504   mapconn->conn = conn;
505 
506   /* Get statistics */
507   silc_client_command_call(client, conn, "STATS");
508 
509   /* Get motd if requested */
510   if (mapconn->motd) {
511     char motd[256];
512     char *hostname;
513     silc_dlist_start(mapconn->hostnames);
514     hostname = silc_dlist_get(mapconn->hostnames);
515     memset(motd, 0, sizeof(motd));
516     silc_strncat(motd, sizeof(motd), "MOTD ", 5);
517     silc_strncat(motd, sizeof(motd), hostname, strlen(hostname));
518     silc_client_command_call(client, conn, motd);
519   }
520 
521   /* Set data timeout to detect if the server is down. */
522   silc_schedule_task_add(map->client->schedule, 0,
523                          silc_map_data_timeout, mapconn,
524                          mapconn->connect_timeout, 0,
525                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
526 }
527 
528 
529 /* Called to indicate that connection was disconnected to the server.
530    The `status' may tell the reason of the disconnection, and if the
531    `message' is non-NULL it may include the disconnection message
532    received from server. */
533 
534 static void
535 silc_disconnected(SilcClient client, SilcClientConnection conn,
536                   SilcStatus status, const char *message)
537 {
538   SilcMapConnection mapconn = conn->context;
539 
540   silc_schedule_task_del_by_context(client->schedule, mapconn);
541 
542   SILC_LOG_DEBUG(("Disconnected from server %s:%d", conn->remote_host,
543                   conn->remote_port));
544 
545   mapconn->conn = NULL;
546 }
547 
548 
549 /* Find authentication method and authentication data by hostname and
550    port. The hostname may be IP address as well. When the authentication
551    method has been resolved the `completion' callback with the found
552    authentication method and authentication data is called. The `conn'
553    may be NULL. */
554 
555 static void
556 silc_get_auth_method(SilcClient client, SilcClientConnection conn,
557                      char *hostname, SilcUInt16 port,
558                      SilcGetAuthMeth completion,
559                      void *context)
560 {
561   /* No auth */
562   completion(TRUE, SILC_AUTH_NONE, NULL, 0, context);
563 }
564 
565 
566 /* Verifies received public key. The `conn_type' indicates which entity
567    (server, client etc.) has sent the public key. If user decides to trust
568    the application may save the key as trusted public key for later
569    use. The `completion' must be called after the public key has been
570    verified. */
571 
572 static void
573 silc_verify_public_key(SilcClient client, SilcClientConnection conn,
574                        SilcSocketType conn_type, unsigned char *pk,
575                        SilcUInt32 pk_len, SilcSKEPKType pk_type,
576                        SilcVerifyPublicKey completion, void *context)
577 {
578   /* Accept all keys without verification */
579   completion(TRUE, context);
580 }
581 
582 
583 /* Ask (interact, that is) a passphrase from user. The passphrase is
584    returned to the library by calling the `completion' callback with
585    the `context'. The returned passphrase SHOULD be in UTF-8 encoded,
586    if not then the library will attempt to encode. */
587 
588 static void
589 silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
590                     SilcAskPassphrase completion, void *context)
591 {
592   completion(NULL, 0, context);
593 }
594 
595 
596 /* Notifies application that failure packet was received.  This is called
597    if there is some protocol active in the client.  The `protocol' is the
598    protocol context.  The `failure' is opaque pointer to the failure
599    indication.  Note, that the `failure' is protocol dependant and
600    application must explicitly cast it to correct type.  Usually `failure'
601    is 32 bit failure type (see protocol specs for all protocol failure
602    types). */
603 
604 static void
605 silc_failure(SilcClient client, SilcClientConnection conn,
606              SilcProtocol protocol, void *failure)
607 {
608   fprintf(stderr, "Connecting failed (protocol failure)\n");
609 }
610 
611 
612 /* Asks whether the user would like to perform the key agreement protocol.
613    This is called after we have received an key agreement packet or an
614    reply to our key agreement packet. This returns TRUE if the user wants
615    the library to perform the key agreement protocol and FALSE if it is not
616    desired (application may start it later by calling the function
617    silc_client_perform_key_agreement). If TRUE is returned also the
618    `completion' and `context' arguments must be set by the application. */
619 
620 static bool
621 silc_key_agreement(SilcClient client, SilcClientConnection conn,
622                    SilcClientEntry client_entry, const char *hostname,
623                    SilcUInt16 port, SilcKeyAgreementCallback *completion,
624                    void **context)
625 {
626   return FALSE;
627 }
628 
629 
630 /* Notifies application that file transfer protocol session is being
631    requested by the remote client indicated by the `client_entry' from
632    the `hostname' and `port'. The `session_id' is the file transfer
633    session and it can be used to either accept or reject the file
634    transfer request, by calling the silc_client_file_receive or
635    silc_client_file_close, respectively. */
636 
637 static void
638 silc_ftp(SilcClient client, SilcClientConnection conn,
639          SilcClientEntry client_entry, SilcUInt32 session_id,
640          const char *hostname, SilcUInt16 port)
641 {
642 
643 }
644 
645 
646 /* Delivers SILC session detachment data indicated by `detach_data' to the
647    application.  If application has issued SILC_COMMAND_DETACH command
648    the client session in the SILC network is not quit.  The client remains
649    in the network but is detached.  The detachment data may be used later
650    to resume the session in the SILC Network.  The appliation is
651    responsible of saving the `detach_data', to for example in a file.
652 
653    The detachment data can be given as argument to the functions
654    silc_client_connect_to_server, or silc_client_add_connection when
655    creating connection to remote server, inside SilcClientConnectionParams
656    structure.  If it is provided the client library will attempt to resume
657    the session in the network.  After the connection is created
658    successfully, the application is responsible of setting the user
659    interface for user into the same state it was before detaching (showing
660    same channels, channel modes, etc).  It can do this by fetching the
661    information (like joined channels) from the client library. */
662 
663 static void
664 silc_detach(SilcClient client, SilcClientConnection conn,
665             const unsigned char *detach_data, SilcUInt32 detach_data_len)
666 {
667 
668 }
669 
670 /* This structure and all the functions were taken from the
671    lib/silcclient/client_ops_example.c. */
672 SilcClientOperations silc_map_client_ops = {
673   silc_say,
674   silc_channel_message,
675   silc_private_message,
676   silc_notify,
677   silc_command,
678   silc_command_reply,
679   silc_connected,
680   silc_disconnected,
681   silc_get_auth_method,
682   silc_verify_public_key,
683   silc_ask_passphrase,
684   silc_failure,
685   silc_key_agreement,
686   silc_ftp,
687   silc_detach
688 };
689 

This page was automatically generated by the LXR engine.
Free-text search provided by Glimpse