From: Pekka Riikonen Date: Tue, 5 Nov 2002 14:06:56 +0000 (+0000) Subject: Added tutorials. X-Git-Tag: 1.2.beta1~935 X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=commitdiff_plain;h=8b519f93f08155aee3a68463d1a783cf9b392d43 Added tutorials. --- diff --git a/Makefile.am.pre b/Makefile.am.pre index 8d8974aa..d34eacba 100644 --- a/Makefile.am.pre +++ b/Makefile.am.pre @@ -44,7 +44,7 @@ modulesdir = $(DESTDIR)$(silc_modulesdir) helpdir = $(DESTDIR)$(silc_helpdir) docdir = $(DESTDIR)$(silc_docdir) logsdir = $(DESTDIR)$(silc_logsdir) -mandir = $(DESTDIR)/man +manualdir = $(DESTDIR)/man install-dirs: -mkdir -p $(etcdir) @@ -52,9 +52,9 @@ install-dirs: -mkdir -p $(helpdir) -mkdir -p $(docdir) -mkdir -p $(logsdir) - -mkdir -p $(mandir)/man1 - -mkdir -p $(mandir)/man5 - -mkdir -p $(mandir)/man8 + -mkdir -p $(manualdir)/man1 + -mkdir -p $(manualdir)/man5 + -mkdir -p $(manualdir)/man8 generate-server-key: @@ -70,9 +70,9 @@ doc-install: $(INSTALL_DATA) $(srcdir)/doc/FAQ $(docdir)/ $(INSTALL_DATA) $(srcdir)/doc/example_* $(docdir)/ $(INSTALL_DATA) $(srcdir)/doc/*.txt $(docdir)/ - $(INSTALL_DATA) $(srcdir)/doc/silc.1 $(mandir)/man1 - $(INSTALL_DATA) $(srcdir)/doc/silcd.8 $(mandir)/man8 - $(INSTALL_DATA) $(srcdir)/doc/silcd.conf.5 $(mandir)/man5 + $(INSTALL_DATA) $(srcdir)/doc/silc.1 $(manualdir)/man1 + $(INSTALL_DATA) $(srcdir)/doc/silcd.8 $(manualdir)/man8 + $(INSTALL_DATA) $(srcdir)/doc/silcd.conf.5 $(manualdir)/man5 $(INSTALL_DATA) $(srcdir)/COPYING $(docdir)/ $(INSTALL_DATA) $(srcdir)/CHANGES $(docdir)/ $(INSTALL_DATA) $(srcdir)/CREDITS $(docdir)/ @@ -80,17 +80,16 @@ doc-install: $(INSTALL_DATA) $(srcdir)/INSTALL $(docdir)/ $(INSTALL_DATA) $(srcdir)/TODO $(docdir)/ - toolkit-install: -mkdir -p $(docdir)/toolkit/ -$(INSTALL_DATA) $(srcdir)/doc/toolkit/* $(docdir)/toolkit -$(INSTALL_DATA) $(srcdir)/lib/doc/*.gif $(docdir)/toolkit + -cp -R $(srcdir)/tutorial $(prefix) examples-install: -mkdir -p $(docdir)/examples/ $(INSTALL_DATA) $(srcdir)/doc/examples/README $(docdir)/examples/ $(INSTALL_DATA) $(srcdir)/doc/examples/silc* $(docdir)/examples/ - $(INSTALL_DATA) $(srcdir)/doc/examples/cell* $(docdir)/examples/ etc-install: -@if test '!' -f $(etcdir)/silcd.conf ; then \ diff --git a/Makefile.defines.pre b/Makefile.defines.pre index e85d49b6..192ff0f5 100644 --- a/Makefile.defines.pre +++ b/Makefile.defines.pre @@ -41,7 +41,7 @@ # # INCLUDE defines # -INCLUDES = $(ADD_INCLUDES) $(SILC_CFLAGS) \ +INCLUDES = $(ADD_INCLUDES) $(SILC_CFLAGS) -DHAVE_SILCDEFS_H \ -I$(srcdir) -I$(top_srcdir) \ -I$(silc_top_srcdir) \ -I$(silc_top_srcdir)/lib/silccore \ diff --git a/configure.in.pre b/configure.in.pre index 89917785..3940ce84 100644 --- a/configure.in.pre +++ b/configure.in.pre @@ -1000,12 +1000,12 @@ silc/Makefile win32/Makefile win32/libsilc/Makefile win32/libsilcclient/Makefile +tutorial/Makefile +tutorial/Makefile.defines +tutorial/Makefile.defines_int ) fi -# Use our configuration in compilation -CFLAGS="-DHAVE_SILCDEFS_H $CFLAGS" - AC_OUTPUT s_bindir=`eval echo $bindir`;s_bindir=`eval echo $s_bindir` diff --git a/distributions b/distributions index 87573877..a0a16cb6 100644 --- a/distributions +++ b/distributions @@ -53,7 +53,7 @@ toolkit_SUBDIRS=lib irssi silc silcd doc includes win32 toolkit_SUBDIRS_lib=$(COMMONDIRS) toolkit_SUBDIRS_doc=$(COMMONDIRS) toolkit_DISTLABEL=SILC_DIST_TOOLKIT -toolkit_EXTRA_DIST=README.CVS README.WIN32 README.MACOSX silcer +toolkit_EXTRA_DIST=README.CVS README.WIN32 README.MACOSX silcer tutorial # Irssi SILC Client distribution client_SUBDIRS=lib irssi doc includes diff --git a/doc/Makefile.am.pre b/doc/Makefile.am.pre index e1047f73..579e98f9 100644 --- a/doc/Makefile.am.pre +++ b/doc/Makefile.am.pre @@ -31,17 +31,6 @@ all: touch draft-riikonen-silc-flags-payloads-00.txt touch draft-riikonen-presence-attrs-00.txt -if SILC_DIST_CLIENT -dist-hook: - $(SILC_TOP_SRCDIR)/scripts/manpages.pl - rm draft-riikonen*.txt - touch draft-riikonen-silc-spec-05.txt - touch draft-riikonen-silc-pp-05.txt - touch draft-riikonen-silc-ke-auth-05.txt - touch draft-riikonen-silc-commands-03.txt - touch draft-riikonen-silc-flags-payloads-00.txt - touch draft-riikonen-presence-attrs-00.txt -else if SILC_DIST_TOOLKIT toolkit-ref-html: -@if test -f $(SILC_TOP_SRCDIR)/util/robodoc/Source/robodoc ; then \ @@ -65,7 +54,6 @@ toolkit-ref-ps: toolkit-ref-pdf: -ps2pdf $(SILC_TOP_SRCDIR)/doc/toolkit.ps $(SILC_TOP_SRCDIR)/doc/toolkit.pdf -endif dist-hook: $(SILC_TOP_SRCDIR)/scripts/manpages.pl @@ -88,6 +76,16 @@ dist-hook: $(makerfc) draft-riikonen-presence-attrs-00.nroff \ draft-riikonen-presence-attrs-00.txt +else +dist-hook: + $(SILC_TOP_SRCDIR)/scripts/manpages.pl + rm draft-riikonen*.txt + touch draft-riikonen-silc-spec-05.txt + touch draft-riikonen-silc-pp-05.txt + touch draft-riikonen-silc-ke-auth-05.txt + touch draft-riikonen-silc-commands-03.txt + touch draft-riikonen-silc-flags-payloads-00.txt + touch draft-riikonen-presence-attrs-00.txt endif if SILC_DIST_TOOLKIT diff --git a/tutorial/Makefile.defines.in b/tutorial/Makefile.defines.in new file mode 100644 index 00000000..03403dae --- /dev/null +++ b/tutorial/Makefile.defines.in @@ -0,0 +1,21 @@ +# +# Makefile.defines.pre +# +# Author: Pekka Riikonen +# +# Copyright (C) 2002 Pekka Riikonen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +include ../Makefile.defines_int + +INCLUDES = $(ADD_INCLUDES) $(SILC_CFLAGS) \ + -I./ -I/usr/local/silc/include -I$(silc_install_prefix)/include diff --git a/tutorial/Makefile.defines_int.in b/tutorial/Makefile.defines_int.in new file mode 100644 index 00000000..03ee3ff3 --- /dev/null +++ b/tutorial/Makefile.defines_int.in @@ -0,0 +1,26 @@ +# +# Makefile.defines_int.pre +# +# Author: Pekka Riikonen +# +# Copyright (C) 2002 Pekka Riikonen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +silc_install_prefix=@prefix@ +SILC_COMMON_LIBS= @LIBS@ -L$(silc_install_prefix)/lib \ + -L/usr/local/silc/lib -lsilc -lsilcclient +SILC_CFLAGS=@CFLAGS@ +CC=@CC@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LDFLAGS = @LDFLAGS@ + diff --git a/tutorial/Makefile.in b/tutorial/Makefile.in new file mode 100644 index 00000000..8f3e50c3 --- /dev/null +++ b/tutorial/Makefile.in @@ -0,0 +1,31 @@ +# +# Makefile.am +# +# Author: Pekka Riikonen +# +# Copyright (C) 2002 Pekka Riikonen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign + +SUBDIRS = mybot + +all: make-all + +clean: make-clean-all + +make-all: + for i in $(SUBDIRS); do cd $$i && $(MAKE) && cd ..; done; + +make-clean-all: + for i in $(SUBDIRS); do cd $$i && $(MAKE) clean && cd ..; done; + diff --git a/tutorial/README b/tutorial/README new file mode 100644 index 00000000..a8a7eff2 --- /dev/null +++ b/tutorial/README @@ -0,0 +1,6 @@ +This directory holds short tutorials and examples for the SILC Toolkit. +These tutorials are not compiled automatically when compiling the Toolkit. + +To compile all tutorials give 'make' in this directory. You may also +compile only a specific tutorial in its subdirectory by giving 'make' +command. diff --git a/tutorial/mybot/Makefile b/tutorial/mybot/Makefile new file mode 100644 index 00000000..4cda00a6 --- /dev/null +++ b/tutorial/mybot/Makefile @@ -0,0 +1,33 @@ +# +# Makefile.am +# +# Author: Pekka Riikonen +# +# Copyright (C) 2002 Pekka Riikonen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign + +CFLAGS = $(INCLUDES) $(SILC_COMMON_LIBS) $(LDFLAGS) +SOURCES = mybot.c + +all: mybot + +clean: + -rm -rf *.o + -rm -rf mybot + +mybot: + $(CC) -o mybot $(SOURCES) $(CFLAGS) + +include ../Makefile.defines.in + diff --git a/tutorial/mybot/mybot.c b/tutorial/mybot/mybot.c new file mode 100644 index 00000000..aea502c5 --- /dev/null +++ b/tutorial/mybot/mybot.c @@ -0,0 +1,525 @@ +/* + + mybot.c + + Author: Pekka Riikonen , November 2002 + This code is Public Domain. + + MyBot + + Example SILC client called "mybot". It is a robot client which + connects to SILC Network into silc.silcnet.org server and joins + channel called "mybot" and says "hello" on the channel. + + This code use the SILC Client Library provided by the SILC + Toolkit distribution. + + Compilation: + + gcc -o mybot mybot.c -I/usr/local/silc/include -L/usr/local/silc/lib \ + -lsilc -lsilcclient -lpthread -ldl + + The MyBot works as follows (logicly): + + main -> mybot_start -> silc_client_connect_to_server + v + silc_client_run (message loop...) + v + silc_verify_public_key + v + silc_get_auth_method + v + silc_connected -> silc_client_send_command (JOIN) + v + silc_command_reply -> silc_send_channel_message ("hello") + v + message loop... + v + main <- mybot_start + +*/ + +#include "silcincludes.h" /* Mandatory include for SILC applications */ +#include "silcclient.h" /* SILC Client Library API */ + +SilcClientOperations ops; + +/******* MyBot code **********************************************************/ + +/* This is context for our MyBot client */ +typedef struct { + SilcClient client; /* The actual SILC Client */ + SilcClientConnection conn; /* Connection to the server */ +} *MyBot; + +/* Start the MyBot, by creating the SILC Client entity by using the + SILC Client Library API. */ +int mybot_start(void) +{ + MyBot mybot; + + /* Allocate the MyBot structure */ + mybot = silc_calloc(1, sizeof(*mybot)); + if (!mybot) { + perror("Out of memory"); + return 1; + } + + /* Allocate our SILC Client which is the MyBot. The arguments to the + function are: + + ops - our client operations that the library requires + param - parameters, but we don't have any so we pass NULL, + application - our application, ie. the MyBot of course! + version - silc version, provided by the library if we put NULL + */ + mybot->client = silc_client_alloc(&ops, NULL, mybot, + /* NULL */"SILC-1.1-0.9.4"); + if (!mybot->client) { + perror("Could not allocate SILC Client"); + return 1; + } + + /* Now fill the allocated client with mandatory parameters the library + requires: username, hostname and "real name". */ + mybot->client->username = silc_get_username(); + mybot->client->hostname = silc_net_localhost(); + mybot->client->realname = strdup("I am the MyBot"); + + /* Now we initialize the client. */ + if (!silc_client_init(mybot->client)) { + perror("Could not init client"); + return 1; + } + + /* Then we load our public key from the file. The library requires + the key pair loaded before the client is started. The SILC Toolkit + provides nice routines to do just that so we don't have to worry + about much. + + Oh, and if the key pair doesn't exist, we create one here + automatically, and save them to files for future. */ + if (!silc_load_key_pair("mybot.pub", "mybot.prv", NULL, + &mybot->client->pkcs, + &mybot->client->public_key, + &mybot->client->private_key)) { + /* The keys don't exist. Let's generate us a key pair then! There's + nice ready routine for that too. Let's do 2048 bit RSA key pair. */ + fprintf(stdout, "MyBot: Key pair does not exist, generating it.\n"); + if (!silc_create_key_pair("rsa", 2048, "mybot.pub", "mybot.prv", NULL, + NULL, &mybot->client->pkcs, + &mybot->client->public_key, + &mybot->client->private_key, FALSE)) { + perror("Could not generated key pair"); + return 1; + } + } + + /* Start connecting to server. This is asynchronous connecting so the + connection is actually created later after we run the client. */ + silc_client_connect_to_server(mybot->client, NULL, 706, + "silc.silcnet.org", mybot); + + /* And, then we are ready to go. Since we are really simple client we + don't have user interface and we don't have to deal with message loops + or interactivity. That's why we can just hand over the execution + to the library by calling silc_client_run. */ + silc_client_run(mybot->client); + + /* When we get here, we have quit the client, so clean up and exit */ + silc_client_free(mybot->client); + silc_free(mybot); + return 0; +} + +/******* SILC Client Operations **********************************************/ + +/* The SILC Client Library requires these "client operations". They are + functions that the library may call at any time to indicate to application + that something happened, like message was received, or authentication + is required or something else. Since our MyBot is really simple client + we don't need most of the operations, so we just define them and don't + do anything in them. */ + +/* "say" client operation is a message from the client library to the + application. It may include error messages or something else. We + just dump them to screen. */ + +static void +silc_say(SilcClient client, SilcClientConnection conn, + SilcClientMessageType type, char *msg, ...) +{ + char str[200]; + va_list va; + va_start(va, msg); + vsnprintf(str, sizeof(str) - 1, msg, va); + fprintf(stdout, "MyBot: %s\n", str); + va_end(va); +} + + +/* Message for a channel. The `sender' is the sender of the message + The `channel' is the channel. The `message' is the message. Note + that `message' maybe NULL. The `flags' indicates message flags + and it is used to determine how the message can be interpreted + (like it may tell the message is multimedia message). */ + +static void +silc_channel_message(SilcClient client, SilcClientConnection conn, + SilcClientEntry sender, SilcChannelEntry channel, + SilcMessageFlags flags, const unsigned char *message, + SilcUInt32 message_len) +{ + /* Yay! We got a message from channel. */ + fprintf(stdout, "<%s> %s\n", sender->nickname, message); +} + + +/* Private message to the client. The `sender' is the sender of the + message. The message is `message'and maybe NULL. The `flags' + indicates message flags and it is used to determine how the message + can be interpreted (like it may tell the message is multimedia + message). */ + +static void +silc_private_message(SilcClient client, SilcClientConnection conn, + SilcClientEntry sender, SilcMessageFlags flags, + const unsigned char *message, + SilcUInt32 message_len) +{ + /* MyBot does not support private message receiving */ +} + + +/* Notify message to the client. The notify arguments are sent in the + same order as servers sends them. The arguments are same as received + from the server except for ID's. If ID is received application receives + the corresponding entry to the ID. For example, if Client ID is received + application receives SilcClientEntry. Also, if the notify type is + for channel the channel entry is sent to application (even if server + does not send it because client library gets the channel entry from + the Channel ID in the packet's header). */ + +static void +silc_notify(SilcClient client, SilcClientConnection conn, + SilcNotifyType type, ...) +{ + char *str; + va_list va; + + va_start(va, type); + + /* Here we can receive all kinds of different data from the server, but + our simple bot is interested only in receiving the "not-so-important" + stuff, just for fun. :) */ + switch (type) { + case SILC_NOTIFY_TYPE_NONE: + /* Received something that we are just going to dump to screen. */ + str = va_arg(va, char *); + fprintf(stdout, "--- %s\n", str); + break; + + case SILC_NOTIFY_TYPE_MOTD: + /* Received the Message of the Day from the server. */ + str = va_arg(va, char *); + fprintf(stdout, "%s", str); + fprintf(stdout, "\n"); + break; + + default: + /* Ignore rest */ + break; + } + + va_end(va); +} + + +/* Command handler. This function is called always in the command function. + If error occurs it will be called as well. `conn' is the associated + client connection. `cmd_context' is the command context that was + originally sent to the command. `success' is FALSE if error occurred + during command. `command' is the command being processed. It must be + noted that this is not reply from server. This is merely called just + after application has called the command. Just to tell application + that the command really was processed. */ + +static void +silc_command(SilcClient client, SilcClientConnection conn, + SilcClientCommandContext cmd_context, bool success, + SilcCommand command, SilcStatus status) +{ + /* If error occurred in client library with our command, print the error */ + if (status != SILC_STATUS_OK) + fprintf(stderr, "MyBot: COMMAND %s: %s\n", + silc_get_command_name(command), + silc_get_status_message(status)); +} + + +/* Command reply handler. This function is called always in the command reply + function. If error occurs it will be called as well. Normal scenario + is that it will be called after the received command data has been parsed + and processed. The function is used to pass the received command data to + the application. + + `conn' is the associated client connection. `cmd_payload' is the command + payload data received from server and it can be ignored. It is provided + if the application would like to re-parse the received command data, + however, it must be noted that the data is parsed already by the library + thus the payload can be ignored. `success' is FALSE if error occurred. + In this case arguments are not sent to the application. The `status' is + the command reply status server returned. The `command' is the command + reply being processed. The function has variable argument list and each + command defines the number and type of arguments it passes to the + application (on error they are not sent). */ + +static void +silc_command_reply(SilcClient client, SilcClientConnection conn, + SilcCommandPayload cmd_payload, bool success, + SilcCommand command, SilcStatus status, ...) +{ + va_list va; + + /* If error occurred in client library with our command, print the error */ + if (status != SILC_STATUS_OK) + fprintf(stderr, "MyBot: COMMAND REPLY %s: %s\n", + silc_get_command_name(command), + silc_get_status_message(status)); + + va_start(va, status); + + /* Check for successful JOIN */ + if (command == SILC_COMMAND_JOIN) { + SilcChannelEntry channel; + + (void)va_arg(va, SilcClientEntry); + channel = va_arg(va, SilcChannelEntry); + + fprintf(stdout, "MyBot: Joined '%s' channel\n", channel->channel_name); + + /* Now send the "hello" to the channel */ + silc_client_send_channel_message(client, conn, channel, NULL, 0, + "hello", strlen("hello"), FALSE); + fprintf(stdout, "MyBot: Sent 'hello' to channel\n"); + } + + va_end(va); +} + + +/* Called to indicate that connection was either successfully established + or connecting failed. This is also the first time application receives + the SilcClientConnection objecet which it should save somewhere. + If the `success' is FALSE the application must always call the function + silc_client_close_connection. */ + +static void +silc_connected(SilcClient client, SilcClientConnection conn, + SilcClientConnectionStatus status) +{ + MyBot mybot = client->application; + SilcBuffer idp; + + if (status == SILC_CLIENT_CONN_ERROR) { + fprintf(stderr, "MyBot: Could not connect to server\n"); + silc_client_close_connection(client, conn); + return; + } + + fprintf(stdout, "MyBot: Connected to server.\n"); + + /* Save the connection context */ + mybot->conn = conn; + + /* Now that we are connected, send the JOIN command to the "mybot" + channel */ + idp = silc_id_payload_encode(conn->local_id, SILC_ID_CLIENT); + silc_client_command_send(client, conn, SILC_COMMAND_JOIN, 0, 2, + 1, "mybot", strlen("mybot"), + 2, idp->data, idp->len); + silc_buffer_free(idp); +} + + +/* Called to indicate that connection was disconnected to the server. + The `status' may tell the reason of the disconnection, and if the + `message' is non-NULL it may include the disconnection message + received from server. */ + +static void +silc_disconnected(SilcClient client, SilcClientConnection conn, + SilcStatus status, const char *message) +{ + MyBot mybot = client->application; + + /* We got disconnected from server */ + mybot->conn = NULL; + fprintf(stdout, "MyBot: %s:%s\n", silc_get_status_message(status), + message); +} + + +/* Find authentication method and authentication data by hostname and + port. The hostname may be IP address as well. When the authentication + method has been resolved the `completion' callback with the found + authentication method and authentication data is called. The `conn' + may be NULL. */ + +static void +silc_get_auth_method(SilcClient client, SilcClientConnection conn, + char *hostname, SilcUInt16 port, + SilcGetAuthMeth completion, + void *context) +{ + /* MyBot assumes that there is no authentication requirement in the + server and sends nothing as authentication. We just reply with + TRUE, meaning we know what is the authentication method. :). */ + completion(TRUE, SILC_AUTH_NONE, NULL, 0, context); +} + + +/* Verifies received public key. The `conn_type' indicates which entity + (server, client etc.) has sent the public key. If user decides to trust + the application may save the key as trusted public key for later + use. The `completion' must be called after the public key has been + verified. */ + +static void +silc_verify_public_key(SilcClient client, SilcClientConnection conn, + SilcSocketType conn_type, unsigned char *pk, + SilcUInt32 pk_len, SilcSKEPKType pk_type, + SilcVerifyPublicKey completion, void *context) +{ + /* MyBot is also very trusting, so we just accept the public key + we get here. Of course, we would have to verify the authenticity + of the public key but our bot is too simple for that. We just + reply with TRUE, meaning "yeah, we trust it". :) */ + completion(TRUE, context); +} + + +/* Ask (interact, that is) a passphrase from user. The passphrase is + returned to the library by calling the `completion' callback with + the `context'. The returned passphrase SHOULD be in UTF-8 encoded, + if not then the library will attempt to encode. */ + +static void +silc_ask_passphrase(SilcClient client, SilcClientConnection conn, + SilcAskPassphrase completion, void *context) +{ + /* MyBot does not support asking passphrases from users since there + is no user in our little client. We just reply with nothing. */ + completion(NULL, 0, context); +} + + +/* Notifies application that failure packet was received. This is called + if there is some protocol active in the client. The `protocol' is the + protocol context. The `failure' is opaque pointer to the failure + indication. Note, that the `failure' is protocol dependant and + application must explicitly cast it to correct type. Usually `failure' + is 32 bit failure type (see protocol specs for all protocol failure + types). */ + +static void +silc_failure(SilcClient client, SilcClientConnection conn, + SilcProtocol protocol, void *failure) +{ + /* Well, something bad must have happened during connecting to the + server since we got here. Let's just print that something failed. + The "failure" would include more information but let's not bother + with that now. */ + fprintf(stderr, "MyBot: Connecting failed (protocol failure)\n"); +} + + +/* Asks whether the user would like to perform the key agreement protocol. + This is called after we have received an key agreement packet or an + reply to our key agreement packet. This returns TRUE if the user wants + the library to perform the key agreement protocol and FALSE if it is not + desired (application may start it later by calling the function + silc_client_perform_key_agreement). If TRUE is returned also the + `completion' and `context' arguments must be set by the application. */ + +static bool +silc_key_agreement(SilcClient client, SilcClientConnection conn, + SilcClientEntry client_entry, const char *hostname, + SilcUInt16 port, SilcKeyAgreementCallback *completion, + void **context) +{ + /* MyBot does not support incoming key agreement protocols, it's too + simple for that. */ + return FALSE; +} + + +/* Notifies application that file transfer protocol session is being + requested by the remote client indicated by the `client_entry' from + the `hostname' and `port'. The `session_id' is the file transfer + session and it can be used to either accept or reject the file + transfer request, by calling the silc_client_file_receive or + silc_client_file_close, respectively. */ + +static void +silc_ftp(SilcClient client, SilcClientConnection conn, + SilcClientEntry client_entry, SilcUInt32 session_id, + const char *hostname, SilcUInt16 port) +{ + /* MyBot does not support file transfer, it's too simple for that too. */ +} + + +/* Delivers SILC session detachment data indicated by `detach_data' to the + application. If application has issued SILC_COMMAND_DETACH command + the client session in the SILC network is not quit. The client remains + in the network but is detached. The detachment data may be used later + to resume the session in the SILC Network. The appliation is + responsible of saving the `detach_data', to for example in a file. + + The detachment data can be given as argument to the functions + silc_client_connect_to_server, or silc_client_add_connection when + creating connection to remote server, inside SilcClientConnectionParams + structure. If it is provided the client library will attempt to resume + the session in the network. After the connection is created + successfully, the application is responsible of setting the user + interface for user into the same state it was before detaching (showing + same channels, channel modes, etc). It can do this by fetching the + information (like joined channels) from the client library. */ + +static void +silc_detach(SilcClient client, SilcClientConnection conn, + const unsigned char *detach_data, SilcUInt32 detach_data_len) +{ + /* Oh, and MyBot does not support session detaching either. */ +} + +/* Our client operations for the MyBot. This structure is filled with + functions and given as argument to the silc_client_alloc function. + Even though our little bot does not need all these functions we must + provide them since the SILC Client Library wants them all. */ +/* This structure and all the functions were taken from the + lib/silcclient/client_ops_example.c. */ +SilcClientOperations ops = { + silc_say, + silc_channel_message, + silc_private_message, + silc_notify, + silc_command, + silc_command_reply, + silc_connected, + silc_disconnected, + silc_get_auth_method, + silc_verify_public_key, + silc_ask_passphrase, + silc_failure, + silc_key_agreement, + silc_ftp, + silc_detach +}; + +int main(int argc, char **argv) +{ + /* Start the bot */ + return mybot_start(); +}