updates.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 28 Oct 2001 20:53:55 +0000 (20:53 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 28 Oct 2001 20:53:55 +0000 (20:53 +0000)
28 files changed:
CHANGES
Makefile.am.pre
TODO
apps/irssi/docs/help/in/file.in [new file with mode: 0644]
apps/irssi/src/fe-common/silc/module-formats.c
apps/irssi/src/fe-common/silc/module-formats.h
apps/irssi/src/silc/core/silc-core.c
apps/irssi/src/silc/core/silc-servers.c
apps/irssi/src/silc/core/silc-servers.h
apps/silcd/server.c
includes/Makefile.am
lib/silcclient/Makefile.am
lib/silcclient/client.c
lib/silcclient/client_ftp.c
lib/silcclient/client_prvmsg.c
lib/silcclient/silcapi.h
lib/silccore/Makefile.am
lib/silccore/silcpacket.c
lib/silccrypt/Makefile.am
lib/silccrypt/silcrng.c
lib/silccrypt/silcrng.h
lib/silcmath/Makefile.am
lib/silcsftp/Makefile.am
lib/silcsim/Makefile.am
lib/silcske/Makefile.am
lib/silcutil/Makefile.am
lib/silcutil/silcbufutil.h
lib/silcutil/unix/silcunixsockconn.c

diff --git a/CHANGES b/CHANGES
index 28f84fd8e49108dcf6bea512e3c8c2d9fd3450bf..77fa1102e5695688d458edfb434c857578e3b688 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -31,6 +31,9 @@ Sun Oct 28 18:46:27 EST 2001  Pekka Riikonen <priikone@silcnet.org>
          now in server, to optimize packet processing.  Affected file
          silcd/server.c.
 
+       * Include files are installed now only in Toolkit distribution
+         if make install is given.  Affected files: all Makefile.am's.
+
 Thu Oct 25 22:44:06 EDT 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * Assure that silc_client_notify_by_server_resolve does not
index 5be670a0961cf6578eb4c20b529ff70c20b87211..5c0696c5ebbf4d3643996957589b9863d1c99148 100644 (file)
@@ -37,11 +37,11 @@ EXTRA_DIST = CHANGES CREDITS $(SILC_EXTRA_DIST)
 # Installing of SILC into the system
 #
 
-etcdir = $(silc_etcdir)
-modulesdir = $(silc_modulesdir)
-helpdir = $(silc_helpdir)
-docdir = $(silc_docdir)
-logsdir = $(silc_logsdir)
+etcdir = $(DESTDIR)$(silc_etcdir)
+modulesdir = $(DESTDIR)$(silc_modulesdir)
+helpdir = $(DESTDIR)$(silc_helpdir)
+docdir = $(DESTDIR)$(silc_docdir)
+logsdir = $(DESTDIR)$(silc_logsdir)
 
 install-dirs:
        -mkdir -p $(etcdir)
@@ -81,4 +81,8 @@ etc-install:
          $(etcdir)/silc.conf; \
        fi
 
+if SILC_DIST_CLIENT
+install-data-hook: install-dirs sim-install doc-install etc-install
+else
 install-data-hook: install-dirs generate-server-key sim-install doc-install etc-install
+endif
diff --git a/TODO b/TODO
index eab9ad3a051359988415b7dcbaf11602e54b8b8a..dd3db5c99346f42833a4d35d2da5a698afb2d97a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,8 +1,6 @@
 TODO/bugs in Irssi SILC client
 ==============================
 
- o Add the SFTP support.
-
  o /NAMES kees showing things wrong after JOIN and after ppl has left
    channel.
 
@@ -40,8 +38,6 @@ TODO/bugs in Irssi SILC client
 TODO/bugs In SILC Client Library
 ================================
 
- o Add the SFTP support.
-
  o JOIN command's argument handling is buggy.  See the XXX in the code.
 
 
@@ -122,9 +118,6 @@ TODO/bugs In SILC Server
 TODO/bugs In SILC Libraries
 ===========================
 
- o Add some silc_rng_get_byte_fast that read directly from /dev/urandom.
-   That can be used for padding generation.  The current is too slow.
-
  o Compression routines are missing.  The protocol supports packet
    compression thus it must be implemented.  SILC Comp API must be
    defined.  zlib package is already included into the lib dir (in CVS,
diff --git a/apps/irssi/docs/help/in/file.in b/apps/irssi/docs/help/in/file.in
new file mode 100644 (file)
index 0000000..a7a07ee
--- /dev/null
@@ -0,0 +1,34 @@
+
+@SYNTAX:file@
+
+This command is used to tranfer files between clients.
+The actual file transfer stream is sent outside SILC network
+peer to peer between the clients.  Before the file transfer
+begins the SILC Key Exchange protocol is performed between
+the two clients to exchange key material.  This key material
+is then used to secure the file transfer stream between the
+clients.
+
+The currently active file transfer sessions can be seen by
+giving the FILE command without arguments.
+
+Commands:
+
+    SEND       <filepath> <nickname>
+
+      Sends file transfer request to <nickname>.  This
+      makes the <filepath> available to <nickname>.
+
+    RECEIVE    [<nickname>]
+
+      Accepts the file transfer request and starts
+      the file transfer session.  If the <nickname> is
+      omitted the last received request is used.
+
+    CLOSE      [<nickname>]
+
+      Closes the file transfer session, or rejects
+      file transfer request.  If this command is given
+      during the file transfer process it will be cancelled.
+
+
index 19ae4cb320a4a4604352d3cddd812298cc463e87..6ccbbe88bcb69e2d0fd1ce2596d05ce649a0d7d4 100644 (file)
@@ -121,16 +121,19 @@ FORMAT_REC fecommon_silc_formats[] = {
 
        { "file_send", "File transfer request sent to {nick $0} for $1", 2, { 0, 0 } },
        { "file_transmit", "Transmitting file {hilight $0} [$1kB] to {nick $2}", 3, { 0, 0, 0 } },
-       { "file_transmitted", "Transmitted file {hilight $0} [$1kB] to {nick $2} [{hilight $3kB/s}]", 4, { 0, 0, 0, 0 } },
+       { "file_transmitted", "Transmitted file {hilight $0} [$1kB] to {nick $2} [{hilight $3kB/s}]", 4, { 0, 0, 0, 3 } },
        { "file_receive", "Receiving file {hilight $0} [$1kB] from {nick $2}", 3, { 0, 0 } },
-       { "file_received", "Received file {hilight $0} [$1kB] from {nick $2} [{hilight $3kB/s}]", 4, { 0, 0 } },
+       { "file_received", "Received file {hilight $0} [$1kB] from {nick $2} [{hilight $3kB/s}]", 4, { 0, 0, 0, 3 } },
        { "file_request", "File transfer request from {nick $0}", 1, { 0 } },
        { "file_request_host", "File transfer request from {nick $0} [$1 port $2]", 3, { 0, 0, 0 } },
        { "file_key_exchange", "Negotiating keys for file transfer with {nick $0}", 1, { 0 } },
        { "file_na", "No file transfers available", 0 },
        { "file_client_na", "No file transfer offered by {nick $0}", 1, { 0 } },
        { "file_show_header", "File transfers", 0 },
-       { "file_show_line", "  $0 $1 ($2)", 3, { 0, 0, 0 } },
+       { "file_show_line", "  $0 $1: $2kB of $3kB ($4%%) - $5kB/s - $6", 7, { 0, 0, 1, 1, 1, 3, 0 } },
+       { "file_already_started", "File transfer already started with {nick $0}", 1, { 0  } },
+       { "file_error", "Error during file transfer with {nick $0}", 1, { 0  } },
+       { "file_close", "File transfer closed with {nick $0}", 1, { 0  } },
 
        { NULL, NULL, 0 }
 };
index 89726a55724a61ee2045a8470af51d1c76cc9cd1..a7bb8ad818b7ca96ea96b3efe9fbe3aa95086e4e 100644 (file)
@@ -124,6 +124,9 @@ enum {
   SILCTXT_FILE_CLIENT_NA,
   SILCTXT_FILE_SHOW_HEADER,
   SILCTXT_FILE_SHOW_LINE,
+  SILCTXT_FILE_ALREADY_STARTED,
+  SILCTXT_FILE_ERROR,
+  SILCTXT_FILE_CLOSED,
 };
 
 extern FORMAT_REC fecommon_silc_formats[];
index 9936826d50f8ac12e3e1133e7cced32caac9335b..1a8336615fcbc667827e2ec4c96835a917b32767 100644 (file)
@@ -353,7 +353,7 @@ void silc_core_init_finish(void)
   silc_channels_init();
   silc_queries_init();
 
-  idletag = g_timeout_add(50, (GSourceFunc) my_silc_scheduler, NULL);
+  idletag = g_timeout_add(5, (GSourceFunc) my_silc_scheduler, NULL);
 }
 
 /* Deinit SILC. Called from src/fe-text/silc.c */
index e20a2d4b0ebd15765c2e33a3404fc3897f5f30b1..e63578f0cabe506ddea53094d8ef6e84be7ae8d5 100644 (file)
@@ -308,10 +308,10 @@ char *silc_server_get_channels(SILC_SERVER_REC *server)
 /* SYNTAX: PING */
 /* SYNTAX: SCONNECT <server> [<port>] */
 /* SYNTAX: USERS <channel> */
-/* SYNTAX: FILE SEND <filename> <nickname> */
+/* SYNTAX: FILE SEND <filepath> <nickname> */
 /* SYNTAX: FILE RECEIVE [<nickname>] */
 /* SYNTAX: FILE CLOSE [<nickname>] */
-/* SYNTAX: FILE SHOW */
+/* SYNTAX: FILE */
 
 void silc_command_exec(SILC_SERVER_REC *server,
                       const char *command, const char *args)
@@ -439,47 +439,80 @@ static void silc_client_file_monitor(SilcClient client,
     if (ftp->client_entry == client_entry) {
       ftp->session_id = session_id;
 
-      if (!ftp->filepath)
+      if (!ftp->filepath && filepath)
        ftp->filepath = strdup(filepath);
       break;
     }
   }
 
+  if (ftp == SILC_LIST_END)
+    return;
+
+  if (status == SILC_CLIENT_FILE_MONITOR_ERROR) {
+    printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
+                      SILCTXT_FILE_ERROR, client_entry->nickname);
+    silc_schedule_task_add(silc_client->schedule, 0,
+                          silc_client_file_close_later, ftp,
+                          1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+    if (ftp == server->current_session)
+      server->current_session = NULL;
+    silc_dlist_del(server->ftp_sessions, ftp);
+  }
+
+  if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT) {
+    printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
+                      SILCTXT_FILE_KEY_EXCHANGE, client_entry->nickname);
+  }
+
   if (status == SILC_CLIENT_FILE_MONITOR_SEND) {
-    if (offset == 0)
+    if (offset == 0) {
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_FILE_TRANSMIT, filepath, fsize,
                         client_entry->nickname);
+      ftp->starttime = time(NULL);
+    }
     if (offset == filesize) {
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_FILE_TRANSMITTED, filepath, fsize,
-                        client_entry->nickname, "1024");
-      if (ftp != SILC_LIST_END) {
-       silc_schedule_task_add(silc_client->schedule, 0,
-                              silc_client_file_close_later, ftp,
-                              1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-       silc_dlist_del(server->ftp_sessions, ftp);
-      }
+                        client_entry->nickname, ftp->kps);
+      silc_schedule_task_add(silc_client->schedule, 0,
+                            silc_client_file_close_later, ftp,
+                            1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+      if (ftp == server->current_session)
+       server->current_session = NULL;
+      silc_dlist_del(server->ftp_sessions, ftp);
     }
   }
 
   if (status == SILC_CLIENT_FILE_MONITOR_RECEIVE) {
-    if (offset == 0)
+    if (offset == 0) {
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_FILE_RECEIVE, filepath, fsize,
                         client_entry->nickname);
+      ftp->starttime = time(NULL);
+    }
+
     if (offset == filesize) {
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_FILE_RECEIVED, filepath, fsize,
-                        client_entry->nickname, "1024");
-      if (ftp != SILC_LIST_END) {
-       silc_schedule_task_add(silc_client->schedule, 0,
-                              silc_client_file_close_later, ftp,
-                              1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-       silc_dlist_del(server->ftp_sessions, ftp);
-      }
+                        client_entry->nickname, ftp->kps);
+      silc_schedule_task_add(silc_client->schedule, 0,
+                            silc_client_file_close_later, ftp,
+                            1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+      if (ftp == server->current_session)
+       server->current_session = NULL;
+      silc_dlist_del(server->ftp_sessions, ftp);
     }
   }
+
+  /* Save some transmission data */
+  if (offset && filesize) {
+    ftp->percent = ((double)offset / (double)filesize) * (double)100.0;
+    ftp->kps = (double)((offset / (double)(time(NULL) - ftp->starttime)) + 
+                       1023) / (double)1024;
+    ftp->offset = offset;
+    ftp->filesize = filesize;
+  }
 }
 
 typedef struct {
@@ -519,12 +552,13 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
 {
   SilcClientConnection conn;
   SilcClientEntry *entrys, client_entry;
+  SilcClientFileError ret;
   uint32 entry_count;
   char *nickname = NULL, *tmp;
   unsigned char **argv;
   uint32 argc;
   uint32 *argv_lens, *argv_types;
-  int type;
+  int type = 0;
   FtpSession ftp;
 
   if (!server || !IS_SILC_SERVER(server) || !server->connected)
@@ -533,22 +567,21 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
   conn = server->conn;
 
   /* Now parse all arguments */
-  tmp = g_strconcat("KEY", " ", data, NULL);
+  tmp = g_strconcat("FILE", " ", data, NULL);
   silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 4);
   g_free(tmp);
 
-  if (argc < 2)
-    cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
-
-  type = 0;
-  if (!strcasecmp(argv[1], "send"))
-    type = 1;
-  if (!strcasecmp(argv[1], "receive"))
-    type = 2;
-  if (!strcasecmp(argv[1], "close"))
-    type = 3;
-  if (!strcasecmp(argv[1], "show"))
+  if (argc == 1)
     type = 4;
+
+  if (argc >= 2) {
+    if (!strcasecmp(argv[1], "send"))
+      type = 1;
+    if (!strcasecmp(argv[1], "receive"))
+      type = 2;
+    if (!strcasecmp(argv[1], "close"))
+      type = 3;
+  }
   
   if (type == 0)
     cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
@@ -628,13 +661,20 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
        goto out;
       }
 
-      if (!silc_client_file_receive(silc_client, conn, 
-                                   silc_client_file_monitor, server,
-                                   server->current_session->client_entry,
-                                   server->current_session->session_id))
-       printformat_module("fe-common/silc", server, NULL,
-                          MSGLEVEL_CRAP, SILCTXT_FILE_CLIENT_NA,
-                          server->current_session->client_entry->nickname);
+      ret = silc_client_file_receive(silc_client, conn, 
+                                    silc_client_file_monitor, server,
+                                    server->current_session->client_entry,
+                                    server->current_session->session_id);
+      if (ret != SILC_CLIENT_FILE_OK) {
+       if (ret == SILC_CLIENT_FILE_ALREADY_STARTED)
+         printformat_module("fe-common/silc", server, NULL,
+                            MSGLEVEL_CRAP, SILCTXT_FILE_ALREADY_STARTED,
+                            server->current_session->client_entry->nickname);
+       else
+         printformat_module("fe-common/silc", server, NULL,
+                            MSGLEVEL_CRAP, SILCTXT_FILE_CLIENT_NA,
+                            server->current_session->client_entry->nickname);
+      }
 
       goto out;
     }
@@ -642,13 +682,20 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
     silc_dlist_start(server->ftp_sessions);
     while ((ftp = silc_dlist_get(server->ftp_sessions)) != SILC_LIST_END) {
       if (ftp->client_entry == client_entry) {
-       if (!silc_client_file_receive(silc_client, conn, 
-                                     silc_client_file_monitor, server,
-                                     ftp->client_entry,
-                                     ftp->session_id))
-         printformat_module("fe-common/silc", server, NULL,
-                            MSGLEVEL_CRAP, SILCTXT_FILE_CLIENT_NA,
-                            server->current_session->client_entry->nickname);
+       ret = silc_client_file_receive(silc_client, conn, 
+                                      silc_client_file_monitor, server,
+                                      ftp->client_entry,
+                                      ftp->session_id);
+       if (ret != SILC_CLIENT_FILE_OK) {
+         if (ret == SILC_CLIENT_FILE_ALREADY_STARTED)
+           printformat_module("fe-common/silc", server, NULL,
+                              MSGLEVEL_CRAP, SILCTXT_FILE_ALREADY_STARTED,
+                              client_entry->nickname);
+         else
+           printformat_module("fe-common/silc", server, NULL,
+                              MSGLEVEL_CRAP, SILCTXT_FILE_CLIENT_NA,
+                              client_entry->nickname);
+       }
        break;
       }
     }
@@ -692,22 +739,44 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
        goto out;
       }
  
-      if (!silc_client_file_close(silc_client, conn, 
-                                 server->current_session->session_id))
+      ret = silc_client_file_close(silc_client, conn, 
+                                  server->current_session->session_id);
+      if (ret != SILC_CLIENT_FILE_OK) {
+       if (ret == SILC_CLIENT_FILE_ALREADY_STARTED)
+         printformat_module("fe-common/silc", server, NULL,
+                            MSGLEVEL_CRAP, SILCTXT_FILE_ALREADY_STARTED,
+                            server->current_session->client_entry->nickname);
+       else
+         printformat_module("fe-common/silc", server, NULL,
+                            MSGLEVEL_CRAP, SILCTXT_FILE_CLIENT_NA,
+                            server->current_session->client_entry->nickname);
+      } else {
        printformat_module("fe-common/silc", server, NULL,
-                          MSGLEVEL_CRAP, SILCTXT_FILE_CLIENT_NA,
+                          MSGLEVEL_CRAP, SILCTXT_FILE_CLOSED,
                           server->current_session->client_entry->nickname);
-
+      }
       goto out;
     }
 
     silc_dlist_start(server->ftp_sessions);
     while ((ftp = silc_dlist_get(server->ftp_sessions)) != SILC_LIST_END) {
       if (ftp->client_entry == client_entry) {
-       if (!silc_client_file_close(silc_client, conn, ftp->session_id))
+       ret = silc_client_file_close(silc_client, conn, ftp->session_id);
+       if (ret != SILC_CLIENT_FILE_OK) {
+         if (ret == SILC_CLIENT_FILE_ALREADY_STARTED)
+           printformat_module("fe-common/silc", server, NULL,
+                              MSGLEVEL_CRAP, SILCTXT_FILE_ALREADY_STARTED,
+                              client_entry->nickname);
+         else
+           printformat_module("fe-common/silc", server, NULL,
+                              MSGLEVEL_CRAP, SILCTXT_FILE_CLIENT_NA,
+                              client_entry->nickname);
+       } else {
          printformat_module("fe-common/silc", server, NULL,
-                            MSGLEVEL_CRAP, SILCTXT_FILE_CLIENT_NA,
-                            server->current_session->client_entry->nickname);
+                            MSGLEVEL_CRAP, SILCTXT_FILE_CLOSED,
+                            client_entry->nickname);
+       }
+
        silc_dlist_del(server->ftp_sessions, ftp);
        silc_free(ftp->filepath);
        silc_free(ftp);
@@ -739,8 +808,11 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
       printformat_module("fe-common/silc", server, NULL,
                         MSGLEVEL_CRAP, SILCTXT_FILE_SHOW_LINE,
                         ftp->client_entry->nickname, 
-                        ftp->filepath ? ftp->filepath : "[unknown]",
-                        ftp->send ? "send" : "receive");
+                        ftp->send ? "send" : "receive",
+                        (uint32)(ftp->offset + 1023) / 1024,
+                        (uint32)(ftp->filesize + 1023) / 1024,
+                        ftp->percent, ftp->kps,
+                        ftp->filepath ? ftp->filepath : "[N/A]");
     }
 
     break;
index a790fa39cb4d5fbbb50db716502e2180b3d8ad12..7add2f55494dc71f66ee9cdab5924a228a44c019 100644 (file)
@@ -27,6 +27,12 @@ typedef struct {
   uint32 session_id;
   char *filepath;
   bool send;
+
+  long starttime;              /* Start time of transfer */
+  double kps;                  /* Kilos per second */
+  uint64 offset;               /* Current offset */
+  uint64 filesize;             /* Total file size */
+  uint32 percent;              /* Percent of current transmission */
 } *FtpSession;
 
 #define STRUCT_SERVER_CONNECT_REC SILC_SERVER_CONNECT_REC
index 8f2c8d830cd75c049666776bd134a74e592c2b85..a735140a7009c1f68cc03afb64683d693ed40f5a 100644 (file)
@@ -1697,12 +1697,9 @@ bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
     break;
   case SILC_SOCKET_TYPE_SERVER:
   case SILC_SOCKET_TYPE_ROUTER:
-    /* Packets from servers are parsed as soon as possible */
-    silc_schedule_task_add(server->schedule, sock->sock,
-                          silc_server_packet_parse_real,
-                          (void *)parser_context, 0, 1,
-                          SILC_TASK_TIMEOUT,
-                          SILC_TASK_PRI_NORMAL);
+    /* Packets from servers are parsed immediately */
+    silc_server_packet_parse_real(server->schedule, 0, sock->sock,
+                                 parser_context);
     break;
   default:
     return TRUE;
index a5fb029faf604d2d49f352a6f7d0594add108428..cd5ecd16d3a5d7f8785f5944c6e60ef9e6f63040 100644 (file)
@@ -32,4 +32,4 @@ include_HEADERS = \
 endif
 
 EXTRA_DIST = \
-       silcdefs.h.in
+       silcdefs.h.in *.h
index b9b36334934b7fcd9548c60f201c7dcda7251b73..29ab9c5a244ddbb01157e13fd32d314921bdeac7 100644 (file)
@@ -32,6 +32,7 @@ libsilcclient_a_SOURCES = \
        idlist.c \
        protocol.c
 
+if SILC_DIST_TOOLKIT
 include_HEADERS=       \
        client.h        \
        command.h       \
@@ -39,6 +40,7 @@ include_HEADERS=      \
        idlist.h        \
        protocol.h      \
        silcapi.h
+endif
 
 EXTRA_DIST = *.h
 
index 3e0032f673df36152bd9150b3b43032188ff8fe0..8c950acb0f8baa70ea47720479f0bf730aef3145 100644 (file)
@@ -26,7 +26,6 @@
 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
-SILC_TASK_CALLBACK(silc_client_packet_parse_real);
 SILC_TASK_CALLBACK(silc_client_rekey_callback);
 SILC_TASK_CALLBACK(silc_client_rekey_final);
 
@@ -767,37 +766,6 @@ SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
   }
 }
 
-/* Parses whole packet, received earlier. */
-
-SILC_TASK_CALLBACK(silc_client_packet_parse_real)
-{
-  SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
-  SilcClient client = (SilcClient)parse_ctx->context;
-  SilcPacketContext *packet = parse_ctx->packet;
-  SilcSocketConnection sock = parse_ctx->sock;
-  SilcClientConnection conn = (SilcClientConnection)sock->user_data;
-  int ret;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  /* Parse the packet */
-  if (parse_ctx->normal)
-    ret = silc_packet_parse(packet, conn->receive_key);
-  else
-    ret = silc_packet_parse_special(packet, conn->receive_key);
-
-  if (ret == SILC_PACKET_NONE)
-    goto out;
-
-  /* Parse the incoming packet type */
-  silc_client_packet_parse_type(client, sock, packet);
-
- out:
-  /*  silc_buffer_clear(sock->inbuf); */
-  silc_packet_context_free(packet);
-  silc_free(parse_ctx);
-}
-
 /* Parser callback called by silc_packet_receive_process. Thie merely
    registers timeout that will handle the actual parsing when appropriate. */
 
@@ -807,10 +775,24 @@ static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
   SilcClient client = (SilcClient)context;
   SilcSocketConnection sock = parser_context->sock;
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
+  SilcPacketContext *packet = parser_context->packet;
+  SilcPacketType ret;
 
   if (conn && conn->hmac_receive)
     conn->psn_receive = parser_context->packet->sequence + 1;
 
+  /* Parse the packet immediately */
+  if (parser_context->normal)
+    ret = silc_packet_parse(packet, conn->receive_key);
+  else
+    ret = silc_packet_parse_special(packet, conn->receive_key);
+
+  if (ret == SILC_PACKET_NONE) {
+    silc_packet_context_free(packet);
+    silc_free(parser_context);
+    return FALSE;
+  }
+  
   /* If protocol for this connection is key exchange or rekey then we'll
      process all packets synchronously, since there might be packets in
      queue that we are not able to decrypt without first processing the
@@ -818,11 +800,14 @@ static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
   if (sock->protocol && sock->protocol->protocol && 
       (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
        sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
-    silc_client_packet_parse_real(client->schedule, 0, sock->sock,
-                                 parser_context);
+
+    /* Parse the incoming packet type */
+    silc_client_packet_parse_type(client, sock, packet);
+    silc_packet_context_free(packet);
+    silc_free(parser_context);
 
     /* Reprocess the buffer since we'll return FALSE. This is because
-       the `conn->receive_key' might have become valid bu processing
+       the `conn->receive_key' might have become valid by processing
        the previous packet */
     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
       silc_packet_receive_process(sock, FALSE, conn->receive_key, 
@@ -831,16 +816,14 @@ static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
     else
       silc_packet_receive_process(sock, FALSE, NULL, NULL, 0, 
                                  silc_client_packet_parse, client);
+    
     return FALSE;
   }
 
-  /* Parse the packet */
-  silc_schedule_task_add(client->schedule, sock->sock, 
-                        silc_client_packet_parse_real,
-                        (void *)parser_context, 0, 1, 
-                        SILC_TASK_TIMEOUT,
-                        SILC_TASK_PRI_NORMAL);
-
+  /* Parse the incoming packet type */
+  silc_client_packet_parse_type(client, sock, packet);
+  silc_packet_context_free(packet);
+  silc_free(parser_context);
   return TRUE;
 }
 
index 5d554d3764160ffac59901486a77ff34933b6462..9badcc72d8c66cf6fb5200f1a7e9d0026401888c 100644 (file)
@@ -39,6 +39,7 @@ struct SilcClientFtpSessionStruct {
   SilcClientEntry client_entry;
 
   SilcSocketConnection sock;
+  SilcBuffer packet;
 
   char *hostname;
   uint16 port;
@@ -59,66 +60,137 @@ struct SilcClientFtpSessionStruct {
   int fd;
 };
 
-void silc_client_ftp_free_sessions(SilcClient client,
-                                  SilcClientConnection conn)
+SILC_TASK_CALLBACK(silc_client_ftp_connected)
 {
-  if (conn->ftp_sessions) {
-    SilcClientFtpSession session;
-    silc_dlist_start(conn->ftp_sessions);
-    while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
-      session->sock->user_data = NULL;
+  SilcClientInternalConnectContext *ctx =
+    (SilcClientInternalConnectContext *)context;
+  SilcClient client = ctx->client;
+  SilcClientConnection conn = ctx->conn;
+  SilcClientFtpSession session = (SilcClientFtpSession)ctx->context;
+  int opt, opt_len = sizeof(opt);
+
+  SILC_LOG_DEBUG(("Start"));
+
+  /* Check the socket status as it might be in error */
+  silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
+  if (opt != 0) {
+    if (ctx->tries < 2) {
+      /* Connection failed but lets try again */
+      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                      "Could not connect to client %s: %s",
+                      ctx->host, strerror(opt));
+      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
+                      "Connecting to port %d of client %s resumed", 
+                      ctx->port, ctx->host);
+
+      /* Unregister old connection try */
+      silc_schedule_unset_listen_fd(client->schedule, fd);
+      silc_net_close_connection(fd);
+      silc_schedule_task_del(client->schedule, ctx->task);
+
+      /* Try again */
+      silc_client_connect_to_client_internal(ctx);
+      ctx->tries++;
+    } else {
+      /* Connection failed and we won't try anymore */
+      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                      "Could not connect to client %s: %s",
+                      ctx->host, strerror(opt));
+      silc_schedule_unset_listen_fd(client->schedule, fd);
+      silc_net_close_connection(fd);
+      silc_schedule_task_del(client->schedule, ctx->task);
+      silc_free(ctx);
       silc_client_ftp_session_free(session);
     }
-    silc_dlist_del(conn->ftp_sessions, session);
-    silc_dlist_uninit(conn->ftp_sessions);
+    return;
   }
+
+  silc_schedule_unset_listen_fd(client->schedule, fd);
+  silc_schedule_task_del(client->schedule, ctx->task);
+
+  /* Start the key agreement */
+  silc_client_ftp_start_key_agreement(session, fd);
 }
 
-void silc_client_ftp_session_free_client(SilcClientConnection conn,
-                                        SilcClientEntry client_entry)
+static int 
+silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
 {
-  SilcClientFtpSession session;
+  int sock;
 
-  if (!conn->ftp_sessions)
-    return;
+  /* Create connection to server asynchronously */
+  sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
+  if (sock < 0)
+    return -1;
 
-  /* Get the session */
-  silc_dlist_start(conn->ftp_sessions);
-  while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
-    if (session->client_entry == client_entry) {
-      session->sock->user_data = NULL;
-      silc_client_ftp_session_free(session);
-      break;
-    }
-  }
+  /* Register task that will receive the async connect and will
+     read the result. */
+  ctx->task = silc_schedule_task_add(ctx->client->schedule, sock, 
+                                    silc_client_ftp_connected,
+                                    (void *)ctx, 0, 0, 
+                                    SILC_TASK_FD,
+                                    SILC_TASK_PRI_NORMAL);
+  silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
+  ctx->sock = sock;
+  return sock;
 }
 
-/* SFTP packet send callback */
+static int
+silc_client_connect_to_client(SilcClient client, 
+                             SilcClientConnection conn, int port,
+                             char *host, void *context)
+{
+  SilcClientInternalConnectContext *ctx;
+
+  /* Allocate internal context for connection process. This is
+     needed as we are doing async connecting. */
+  ctx = silc_calloc(1, sizeof(*ctx));
+  ctx->client = client;
+  ctx->conn = conn;
+  ctx->host = strdup(host);
+  ctx->port = port;
+  ctx->tries = 0;
+  ctx->context = context;
+
+  /* Do the actual connecting process */
+  return silc_client_connect_to_client_internal(ctx);
+}
+
+/* SFTP packet send callback. This will use preallocated buffer to avoid
+   reallocation of outgoing data buffer everytime. */
 
 static void silc_client_ftp_send_packet(SilcSocketConnection sock,
                                        SilcBuffer packet, void *context)
 {
   SilcClientFtpSession session = (SilcClientFtpSession)context;
   SilcClient client = session->client;
-  SilcBuffer buffer;
 
   SILC_LOG_DEBUG(("Start"));
 
-  buffer = silc_buffer_alloc(1 + packet->len);
-  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
-  silc_buffer_format(buffer, 
+  /* Allocate outgoing packet */
+  if (!session->packet)
+    session->packet = silc_buffer_alloc(1 + packet->len);
+
+  /* Enlarge outgoing packet if needed */
+  if (session->packet->truelen < 1 + packet->len)
+    session->packet = silc_buffer_realloc(session->packet, 1 + packet->len);
+
+  /* Encode packet */
+  silc_buffer_pull_tail(session->packet, 1 + packet->len);
+  silc_buffer_format(session->packet,
                     SILC_STR_UI_CHAR(1),
                     SILC_STR_UI_XNSTRING(packet->data, packet->len),
                     SILC_STR_END);
 
   /* Send the packet immediately */
   silc_client_packet_send(client, sock, SILC_PACKET_FTP, NULL, 0, NULL, NULL,
-                         buffer->data, buffer->len, TRUE);
+                         session->packet->data, session->packet->len, TRUE);
 
-  silc_buffer_free(buffer);
+  silc_buffer_clear(session->packet);
 }
 
-/* SFTP monitor callback for SFTP server */
+/* SFTP monitor callback for SFTP server. This reports the application 
+   how the transmission is going along. This function is for the client
+   who made the file available for download. */
 
 static void silc_client_ftp_monitor(SilcSFTP sftp,
                                    SilcSFTPMonitors type,
@@ -138,7 +210,10 @@ static void silc_client_ftp_monitor(SilcSFTP sftp,
   }
 }
 
-/* Returns the read data */
+/* Returns the read data. This is the downloader's function (client side)
+   to receive the read data and read more until EOF is received from
+   the other side. This will also monitor the transmission and notify
+   the application. */
 
 static void silc_client_ftp_data(SilcSFTP sftp,
                                 SilcSFTPStatus status,
@@ -151,6 +226,7 @@ static void silc_client_ftp_data(SilcSFTP sftp,
   SILC_LOG_DEBUG(("Start"));
 
   if (status == SILC_SFTP_STATUS_EOF) {
+    /* EOF received */
 
     /* Close the handle */
     silc_sftp_close(sftp, session->read_handle, NULL, NULL);
@@ -162,7 +238,12 @@ static void silc_client_ftp_data(SilcSFTP sftp,
   }
 
   if (status != SILC_SFTP_STATUS_OK) {
-    /* XXX errror */
+    /* Call monitor callback */
+    if (session->monitor)
+      (*session->monitor)(session->client, session->conn,
+                         SILC_CLIENT_FILE_MONITOR_ERROR, 0, 0,
+                         session->client_entry, session->session_id,
+                         session->filepath, session->monitor_context);
 
     /* Close the handle */
     silc_sftp_close(sftp, session->read_handle, NULL, NULL);
@@ -175,7 +256,7 @@ static void silc_client_ftp_data(SilcSFTP sftp,
 
   /* Read more, until EOF is received */
   session->read_offset += data_len;
-  silc_sftp_read(sftp, session->read_handle, session->read_offset, 16384,
+  silc_sftp_read(sftp, session->read_handle, session->read_offset, 64512,
                 silc_client_ftp_data, session);
 
   /* Call monitor callback */
@@ -186,10 +267,13 @@ static void silc_client_ftp_data(SilcSFTP sftp,
                        session->client_entry, session->session_id,
                        session->filepath, session->monitor_context);
 
-  /* Write the read data */
+  /* Write the read data to the real file */
   silc_file_write(session->fd, data, data_len);
 }
 
+/* Returns handle for the opened file. This is the downloader's function.
+   This will begin reading the data from the file. */
+
 static void silc_client_ftp_open_handle(SilcSFTP sftp,
                                        SilcSFTPStatus status,
                                        SilcSFTPHandle handle,
@@ -200,21 +284,31 @@ static void silc_client_ftp_open_handle(SilcSFTP sftp,
   SILC_LOG_DEBUG(("Start"));
 
   if (status != SILC_SFTP_STATUS_OK) {
-    /* XXX errror */
+    /* Call monitor callback */
+    if (session->monitor)
+      (*session->monitor)(session->client, session->conn,
+                         SILC_CLIENT_FILE_MONITOR_ERROR, 0, 0,
+                         session->client_entry, session->session_id,
+                         session->filepath, session->monitor_context);
     return;
   }
 
   /* Open the actual local file */
   session->fd = silc_file_open(session->filepath, O_RDWR | O_CREAT);
   if (session->fd < 0) {
-    /* XXX errror */
+    /* Call monitor callback */
+    if (session->monitor)
+      (*session->monitor)(session->client, session->conn,
+                         SILC_CLIENT_FILE_MONITOR_ERROR, 0, 0,
+                         session->client_entry, session->session_id,
+                         session->filepath, session->monitor_context);
     return;
   }
 
-  session->read_handle =  handle;
+  session->read_handle = handle;
 
   /* Now, start reading the file */
-  silc_sftp_read(sftp, session->read_handle, session->read_offset, 16384,
+  silc_sftp_read(sftp, session->read_handle, session->read_offset, 64512,
                 silc_client_ftp_data, session);
 
   /* Call monitor callback */
@@ -226,7 +320,8 @@ static void silc_client_ftp_open_handle(SilcSFTP sftp,
                        session->filepath, session->monitor_context);
 }
 
-/* Returns the file name available for download. */
+/* Returns the file name available for download. This is the downloader's
+   function. */
 
 static void silc_client_ftp_readdir_name(SilcSFTP sftp,
                                         SilcSFTPStatus status,
@@ -239,7 +334,13 @@ static void silc_client_ftp_readdir_name(SilcSFTP sftp,
   SILC_LOG_DEBUG(("Start"));
 
   if (status != SILC_SFTP_STATUS_OK) {
-    /* XXX errror */
+    /* Call monitor callback */
+    if (session->monitor)
+      (*session->monitor)(session->client, session->conn,
+                         SILC_CLIENT_FILE_MONITOR_ERROR, 0, 0,
+                         session->client_entry, session->session_id,
+                         session->filepath, session->monitor_context);
+    return;
   }
 
   /* Now open the file */
@@ -256,7 +357,8 @@ static void silc_client_ftp_readdir_name(SilcSFTP sftp,
   session->dir_handle = NULL;
 }
 
-/* Returns the file handle after giving opendir command. */
+/* Returns the file handle after giving opendir command. This is the
+   downloader's function. */
 
 static void silc_client_ftp_opendir_handle(SilcSFTP sftp,
                                           SilcSFTPStatus status,
@@ -268,7 +370,13 @@ static void silc_client_ftp_opendir_handle(SilcSFTP sftp,
   SILC_LOG_DEBUG(("Start"));
 
   if (status != SILC_SFTP_STATUS_OK) {
-    /* XXX errror */
+    /* Call monitor callback */
+    if (session->monitor)
+      (*session->monitor)(session->client, session->conn,
+                         SILC_CLIENT_FILE_MONITOR_ERROR, 0, 0,
+                         session->client_entry, session->session_id,
+                         session->filepath, session->monitor_context);
+    return;
   }
 
   /* Now, read the directory */
@@ -276,7 +384,9 @@ static void silc_client_ftp_opendir_handle(SilcSFTP sftp,
   session->dir_handle = handle;
 }
 
-/* SFTP version callback for SFTP client */
+/* SFTP version callback for SFTP client. This is the downloader's function
+   after initializing the SFTP connection to the remote client. This will
+   find out the filename available for download. */
 
 static void silc_client_ftp_version(SilcSFTP sftp,
                                    SilcSFTPStatus status,
@@ -288,7 +398,13 @@ static void silc_client_ftp_version(SilcSFTP sftp,
   SILC_LOG_DEBUG(("Start"));
 
   if (status != SILC_SFTP_STATUS_OK) {
-    /* XXX errror */
+    /* Call monitor callback */
+    if (session->monitor)
+      (*session->monitor)(session->client, session->conn,
+                         SILC_CLIENT_FILE_MONITOR_ERROR, 0, 0,
+                         session->client_entry, session->session_id,
+                         session->filepath, session->monitor_context);
+    return;
   }
 
   /* The SFTP session is open, now retrieve the info about available file. */
@@ -347,6 +463,9 @@ SILC_TASK_CALLBACK(silc_client_ftp_key_agreement_final)
   silc_protocol_free(protocol);
 }
 
+/* The downloader's function to start the key agreement protocol with the
+   remote client after we have connected to it. */
+
 static void silc_client_ftp_start_key_agreement(SilcClientFtpSession session,
                                                int sock)
 {
@@ -358,6 +477,13 @@ static void silc_client_ftp_start_key_agreement(SilcClientFtpSession session,
 
   SILC_LOG_DEBUG(("Start"));
 
+  /* Call monitor callback */
+  if (session->monitor)
+    (*session->monitor)(session->client, session->conn,
+                       SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT, 0, 0,
+                       session->client_entry, session->session_id,
+                       NULL, session->monitor_context);
+
   /* Add new connection for this session */
   conn = silc_client_add_connection(client, session->hostname,
                                    session->port, session);
@@ -409,148 +535,9 @@ static void silc_client_ftp_start_key_agreement(SilcClientFtpSession session,
   silc_protocol_execute(protocol, client->schedule, 0, 0);
 }
 
-SILC_TASK_CALLBACK(silc_client_ftp_connected)
-{
-  SilcClientInternalConnectContext *ctx =
-    (SilcClientInternalConnectContext *)context;
-  SilcClient client = ctx->client;
-  SilcClientConnection conn = ctx->conn;
-  SilcClientFtpSession session = (SilcClientFtpSession)ctx->context;
-  int opt, opt_len = sizeof(opt);
-
-  SILC_LOG_DEBUG(("Start"));
-
-  /* Check the socket status as it might be in error */
-  silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
-  if (opt != 0) {
-    if (ctx->tries < 2) {
-      /* Connection failed but lets try again */
-      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
-                      "Could not connect to client %s: %s",
-                      ctx->host, strerror(opt));
-      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
-                      "Connecting to port %d of client %s resumed", 
-                      ctx->port, ctx->host);
-
-      /* Unregister old connection try */
-      silc_schedule_unset_listen_fd(client->schedule, fd);
-      silc_net_close_connection(fd);
-      silc_schedule_task_del(client->schedule, ctx->task);
-
-      /* Try again */
-      silc_client_connect_to_client_internal(ctx);
-      ctx->tries++;
-    } else {
-      /* Connection failed and we won't try anymore */
-      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
-                      "Could not connect to client %s: %s",
-                      ctx->host, strerror(opt));
-      silc_schedule_unset_listen_fd(client->schedule, fd);
-      silc_net_close_connection(fd);
-      silc_schedule_task_del(client->schedule, ctx->task);
-      silc_free(ctx);
-      silc_client_ftp_session_free(session);
-    }
-    return;
-  }
-
-  silc_schedule_unset_listen_fd(client->schedule, fd);
-  silc_schedule_task_del(client->schedule, ctx->task);
-
-  /* Start the key agreement */
-  silc_client_ftp_start_key_agreement(session, fd);
-}
-
-static int 
-silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
-{
-  int sock;
-
-  /* Create connection to server asynchronously */
-  sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
-  if (sock < 0)
-    return -1;
-
-  /* Register task that will receive the async connect and will
-     read the result. */
-  ctx->task = silc_schedule_task_add(ctx->client->schedule, sock, 
-                                    silc_client_ftp_connected,
-                                    (void *)ctx, 0, 0, 
-                                    SILC_TASK_FD,
-                                    SILC_TASK_PRI_NORMAL);
-  silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
-
-  ctx->sock = sock;
-
-  return sock;
-}
-
-static int
-silc_client_connect_to_client(SilcClient client, 
-                             SilcClientConnection conn, int port,
-                             char *host, void *context)
-{
-  SilcClientInternalConnectContext *ctx;
-
-  /* Allocate internal context for connection process. This is
-     needed as we are doing async connecting. */
-  ctx = silc_calloc(1, sizeof(*ctx));
-  ctx->client = client;
-  ctx->conn = conn;
-  ctx->host = strdup(host);
-  ctx->port = port;
-  ctx->tries = 0;
-  ctx->context = context;
-
-  /* Do the actual connecting process */
-  return silc_client_connect_to_client_internal(ctx);
-}
-
-/* Free session */
-
-void silc_client_ftp_session_free(SilcClientFtpSession session)
-{
-  SilcClientConnection conn;
-
-  silc_dlist_del(session->conn->ftp_sessions, session);
-
-  if (session->sftp) {
-    if (session->server)
-      silc_sftp_server_shutdown(session->sftp);
-    else
-      silc_sftp_client_shutdown(session->sftp);
-  }
-
-  if (session->fs)
-    silc_sftp_fs_memory_free(session->fs);
-
-  if (session->listener) {
-    silc_schedule_unset_listen_fd(session->client->schedule, 
-                                 session->listener);
-    silc_net_close_connection(session->listener);
-  }
-
-  if (session->sock) {
-    silc_schedule_unset_listen_fd(session->client->schedule, 
-                                 session->sock->sock);
-    silc_net_close_connection(session->sock->sock);
-
-    if (session->sock->user_data) {
-      conn = (SilcClientConnection)session->sock->user_data;
-
-      if (conn->active_session == session)
-       conn->active_session = NULL;
-
-      silc_client_close_connection(session->client, session->sock, conn);
-    } else {
-      silc_socket_free(session->sock);
-    }
-  }
-
-  silc_free(session->hostname);
-  silc_free(session->filepath);
-  silc_free(session);
-}
+/* The remote client's (the client who made the file available for download)
+   function for accepting incoming connection. This will also start the
+   key agreement protocol with the other client. */
 
 SILC_TASK_CALLBACK(silc_client_ftp_process_key_agreement)
 {
@@ -565,7 +552,12 @@ SILC_TASK_CALLBACK(silc_client_ftp_process_key_agreement)
 
   sock = silc_net_accept_connection(session->listener);
   if (sock < 0) {
-    /* XXX error */
+    /* Call monitor callback */
+    if (session->monitor)
+      (*session->monitor)(session->client, session->conn,
+                         SILC_CLIENT_FILE_MONITOR_ERROR, 0, 0,
+                         session->client_entry, session->session_id,
+                         session->filepath, session->monitor_context);
     return;
   }
 
@@ -579,13 +571,25 @@ SILC_TASK_CALLBACK(silc_client_ftp_process_key_agreement)
   /* Perform name and address lookups for the remote host. */
   silc_net_check_host_by_sock(sock, &newsocket->hostname, &newsocket->ip);
   if (!newsocket->hostname && !newsocket->ip) {
-    /* XXX error */
+    /* Call monitor callback */
+    if (session->monitor)
+      (*session->monitor)(session->client, session->conn,
+                         SILC_CLIENT_FILE_MONITOR_ERROR, 0, 0,
+                         session->client_entry, session->session_id,
+                         session->filepath, session->monitor_context);
     return;
   }
   if (!newsocket->hostname)
     newsocket->hostname = strdup(newsocket->ip);
   newsocket->port = silc_net_get_remote_port(sock);
 
+  /* Call monitor callback */
+  if (session->monitor)
+    (*session->monitor)(session->client, session->conn,
+                       SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT, 0, 0,
+                       session->client_entry, session->session_id,
+                       NULL, session->monitor_context);
+
   /* Add new connection for this session */
   conn = silc_client_add_connection(client, newsocket->hostname,
                                    newsocket->port, session);
@@ -622,6 +626,111 @@ SILC_TASK_CALLBACK(silc_client_ftp_process_key_agreement)
   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(sock);
 }
 
+/* Free all file transfer sessions. */
+
+void silc_client_ftp_free_sessions(SilcClient client,
+                                  SilcClientConnection conn)
+{
+  if (conn->ftp_sessions) {
+    SilcClientFtpSession session;
+    silc_dlist_start(conn->ftp_sessions);
+    while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+      session->sock->user_data = NULL;
+      silc_client_ftp_session_free(session);
+    }
+    silc_dlist_del(conn->ftp_sessions, session);
+    silc_dlist_uninit(conn->ftp_sessions);
+  }
+}
+
+/* Free file transfer session by client entry. */
+
+void silc_client_ftp_session_free_client(SilcClientConnection conn,
+                                        SilcClientEntry client_entry)
+{
+  SilcClientFtpSession session;
+
+  if (!conn->ftp_sessions)
+    return;
+
+  /* Get the session */
+  silc_dlist_start(conn->ftp_sessions);
+  while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+    if (session->client_entry == client_entry) {
+      session->sock->user_data = NULL;
+      silc_client_ftp_session_free(session);
+      break;
+    }
+  }
+}
+
+/* Free session resources. */
+
+void silc_client_ftp_session_free(SilcClientFtpSession session)
+{
+  SilcClientConnection conn;
+
+  SILC_LOG_DEBUG(("Free session"));
+
+  silc_dlist_del(session->conn->ftp_sessions, session);
+
+  if (session->sftp) {
+    if (session->server)
+      silc_sftp_server_shutdown(session->sftp);
+    else
+      silc_sftp_client_shutdown(session->sftp);
+  }
+
+  if (session->fs)
+    silc_sftp_fs_memory_free(session->fs);
+
+  /* Destroy listener */
+  if (session->listener) {
+    silc_schedule_unset_listen_fd(session->client->schedule, 
+                                 session->listener);
+    silc_net_close_connection(session->listener);
+    silc_schedule_task_del_by_fd(session->client->schedule, session->listener);
+  }
+
+  /* Destroy session connection */
+  if (session->sock) {
+    silc_schedule_unset_listen_fd(session->client->schedule, 
+                                 session->sock->sock);
+    silc_net_close_connection(session->sock->sock);
+
+    if (session->sock->user_data) {
+      conn = (SilcClientConnection)session->sock->user_data;
+
+      if (conn->active_session == session)
+       conn->active_session = NULL;
+
+      silc_client_close_connection(session->client, session->sock, conn);
+    } else {
+      silc_socket_free(session->sock);
+    }
+  }
+
+  if (session->packet)
+    silc_buffer_free(session->packet);
+
+  silc_free(session->hostname);
+  silc_free(session->filepath);
+  silc_free(session);
+}
+
+/* Sends a file indicated by the `filepath' to the remote client 
+   indicated by the `client_entry'.  This will negotiate a secret key
+   with the remote client before actually starting the transmission of
+   the file.  The `monitor' callback will be called to monitor the
+   transmission of the file.
+
+   This returns a file session ID for the file transmission.  It can
+   be used to close the session (and abort the file transmission) by
+   calling the silc_client_file_close function.  The session ID is
+   also returned in the `monitor' callback. This returns 0 if the
+   file indicated by the `filepath' is being transmitted to the remote
+   client indicated by the `client_entry', already. */
+
 uint32 silc_client_file_send(SilcClient client,
                             SilcClientConnection conn,
                             SilcClientFileMonitor monitor,
@@ -645,7 +754,7 @@ uint32 silc_client_file_send(SilcClient client,
 
   /* Add new session */
   session = silc_calloc(1, sizeof(*session));
-  session->session_id = conn->next_session_id++;
+  session->session_id = ++conn->next_session_id;
   session->client = client;
   session->conn = conn;
   session->client_entry = client_entry;
@@ -691,12 +800,20 @@ uint32 silc_client_file_send(SilcClient client,
   return session->session_id;
 }
 
-bool silc_client_file_receive(SilcClient client,
-                             SilcClientConnection conn,
-                             SilcClientFileMonitor monitor,
-                             void *monitor_context,
-                             SilcClientEntry client_entry,
-                             uint32 session_id)
+/* Receives a file from a client indicated by the `client_entry'.  The
+   `session_id' indicates the file transmission session and it has been
+   received in the `ftp' client operation function.  This will actually
+   perform the key agreement protocol with the remote client before
+   actually starting the file transmission.  The `monitor' callback
+   will be called to monitor the transmission. */
+
+SilcClientFileError 
+silc_client_file_receive(SilcClient client,
+                        SilcClientConnection conn,
+                        SilcClientFileMonitor monitor,
+                        void *monitor_context,
+                        SilcClientEntry client_entry,
+                        uint32 session_id)
 {
   SilcClientFtpSession session;
   SilcBuffer keyagr, ftp;
@@ -713,13 +830,13 @@ bool silc_client_file_receive(SilcClient client,
 
   if (session == SILC_LIST_END) {
     SILC_LOG_DEBUG(("Unknown session ID: %d\n", session_id));
-    return FALSE;
+    return SILC_CLIENT_FILE_UNKNOWN_SESSION;
   }
 
   /* See if we have this session running already */
   if (session->sftp || session->listener) {
     SILC_LOG_DEBUG(("Session already started"));
-    return FALSE;
+    return SILC_CLIENT_FILE_ALREADY_STARTED;
   }
 
   session->monitor = monitor;
@@ -727,43 +844,55 @@ bool silc_client_file_receive(SilcClient client,
   session->client_entry = client_entry;
   session->conn = conn;
 
-  /* Add the listener for the key agreement */
-  session->hostname = silc_net_localip();
-  session->listener = silc_net_create_server(0, session->hostname);
-  if (session->listener < 0) {
-    /* XXX Error */
-    SILC_LOG_DEBUG(("Could not create listener"));
-    return FALSE;
+  /* If the hostname and port already exists then the remote client did
+     provide the connection point to us and we won't create listener, but
+     create the connection ourselves. */
+  if (session->hostname && session->port) {
+    if (silc_client_connect_to_client(client, conn, session->port, 
+                                     session->hostname, session) < 0)
+      return SILC_CLIENT_FILE_ERROR;
+  } else {
+    /* Add the listener for the key agreement */
+    session->hostname = silc_net_localip();
+    session->listener = silc_net_create_server(0, session->hostname);
+    if (session->listener < 0) {
+      SILC_LOG_DEBUG(("Could not create listener"));
+      return SILC_CLIENT_FILE_ERROR;
+    }
+    session->port = silc_net_get_local_port(session->listener);
+    silc_schedule_task_add(client->schedule, session->listener,
+                          silc_client_ftp_process_key_agreement, session,
+                          0, 0, SILC_TASK_FD, SILC_TASK_PRI_NORMAL);
+    
+    /* Send the key agreement inside FTP packet */
+    keyagr = silc_key_agreement_payload_encode(session->hostname, 
+                                              session->port);
+    ftp = silc_buffer_alloc(1 + keyagr->len);
+    silc_buffer_pull_tail(ftp, SILC_BUFFER_END(ftp));
+    silc_buffer_format(ftp,
+                      SILC_STR_UI_CHAR(1),
+                      SILC_STR_UI_XNSTRING(keyagr->data, keyagr->len),
+                      SILC_STR_END);
+    silc_client_packet_send(client, conn->sock, SILC_PACKET_FTP,
+                           client_entry->id, SILC_ID_CLIENT, NULL, NULL,
+                           ftp->data, ftp->len, FALSE);
+    
+    silc_buffer_free(keyagr);
+    silc_buffer_free(ftp);
   }
-  session->port = silc_net_get_local_port(session->listener);
-  silc_schedule_task_add(client->schedule, session->listener,
-                        silc_client_ftp_process_key_agreement, session,
-                        0, 0, SILC_TASK_FD, SILC_TASK_PRI_NORMAL);
-
-  /* Send the key agreement inside FTP packet */
-  keyagr = silc_key_agreement_payload_encode(session->hostname, session->port);
 
-  ftp = silc_buffer_alloc(1 + keyagr->len);
-  silc_buffer_pull_tail(ftp, SILC_BUFFER_END(ftp));
-  silc_buffer_format(ftp,
-                    SILC_STR_UI_CHAR(1),
-                    SILC_STR_UI_XNSTRING(keyagr->data, keyagr->len),
-                    SILC_STR_END);
-  silc_client_packet_send(client, conn->sock, SILC_PACKET_FTP,
-                         client_entry->id, SILC_ID_CLIENT, NULL, NULL,
-                         ftp->data, ftp->len, FALSE);
-
-  silc_buffer_free(keyagr);
-  silc_buffer_free(ftp);
-
-  return TRUE;
+  return SILC_CLIENT_FILE_OK;
 }
 
-/* Closes FTP session */
+/* Closes file transmission session indicated by the `session_id'.
+   If file transmission is being conducted it will be aborted
+   automatically. This function is also used to close the session
+   after successful file transmission. This function can be used
+   also to reject incoming file transmission request. */
 
-bool silc_client_file_close(SilcClient client,
-                           SilcClientConnection conn,
-                           uint32 session_id)
+SilcClientFileError silc_client_file_close(SilcClient client,
+                                          SilcClientConnection conn,
+                                          uint32 session_id)
 {
   SilcClientFtpSession session;
 
@@ -779,12 +908,12 @@ bool silc_client_file_close(SilcClient client,
 
   if (session == SILC_LIST_END) {
     SILC_LOG_DEBUG(("Unknown session ID: %d\n", session_id));
-    return FALSE;
+    return SILC_CLIENT_FILE_UNKNOWN_SESSION;
   }
 
   silc_client_ftp_session_free(session);
 
-  return TRUE;
+  return SILC_CLIENT_FILE_OK;
 }
 
 /* Callback called after remote client information has been resolved.
@@ -792,20 +921,18 @@ bool silc_client_file_close(SilcClient client,
    then continue with the key agreement protocol.  If not then it means
    this is a file transfer request and we let the application know. */
 
-static void 
-silc_client_ftp_resolve_cb(SilcClient client,
-                          SilcClientConnection conn,
-                          SilcClientEntry *clients,
-                          uint32 clients_count,
-                          void *context)
+static void silc_client_ftp_resolve_cb(SilcClient client,
+                                      SilcClientConnection conn,
+                                      SilcClientEntry *clients,
+                                      uint32 clients_count,
+                                      void *context)
 {
   SilcPacketContext *packet = (SilcPacketContext *)context;
   SilcClientFtpSession session;
-  SilcKeyAgreementPayload payload;
+  SilcKeyAgreementPayload payload = NULL;
   SilcClientEntry client_entry;
   char *hostname;
   uint16 port;
-  int sock;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -830,11 +957,11 @@ silc_client_ftp_resolve_cb(SilcClient client,
 
   if (session == SILC_LIST_END) {
     /* No session found, create one and let the application know about
-       incomoing file transfer request. */
+       incoming file transfer request. */
     
     /* Add new session */
     session = silc_calloc(1, sizeof(*session));
-    session->session_id = conn->next_session_id++;
+    session->session_id = ++conn->next_session_id;
     session->client = client;
     session->conn = conn;
     silc_dlist_add(conn->ftp_sessions, session);
@@ -843,12 +970,11 @@ silc_client_ftp_resolve_cb(SilcClient client,
     client->ops->ftp(client, conn, client_entry,
                     session->session_id, hostname, port);
 
-    /* If hostname was provided we'll start the key exchange now. */
     if (hostname && port) {
-      /* XXX */
+      session->hostname = strdup(hostname);
+      session->port = port;
     }
-
-    silc_key_agreement_payload_free(payload);
+    
     goto out;
   }
 
@@ -859,12 +985,19 @@ silc_client_ftp_resolve_cb(SilcClient client,
   session->port = port;
 
   /* Session exists, continue with key agreement protocol. */
-  sock = silc_client_connect_to_client(client, conn, port, hostname,
-                                      session);
-  if (sock < 0)
-    goto out;
+  if (silc_client_connect_to_client(client, conn, port, 
+                                   hostname, session) < 0) {
+    /* Call monitor callback */
+    if (session->monitor)
+      (*session->monitor)(session->client, session->conn,
+                         SILC_CLIENT_FILE_MONITOR_ERROR, 0, 0,
+                         session->client_entry, session->session_id,
+                         session->filepath, session->monitor_context);
+  }
 
  out:
+  if (payload)
+    silc_key_agreement_payload_free(payload);
   silc_packet_context_free(packet);
 }
 
@@ -894,7 +1027,7 @@ void silc_client_ftp(SilcClient client,
 
   silc_buffer_pull(packet->buffer, 1);
 
-  /* If we have active FTP session then give the packet to the
+  /* If we have active FTP session then give the packet directly to the
      protocol processor. */
   if (conn->active_session) {
     /* Give it to the SFTP */
index a5c6d7d171c1bf442bf737636d2faa8e247d0bb2..2f10542746658fd3fe4856463164d5e79c93933c 100644 (file)
@@ -166,6 +166,16 @@ void silc_client_private_message(SilcClient client,
                                       silc_hash_client_id_compare, NULL,
                                       &id_cache) || 
       ((SilcClientEntry)id_cache->context)->nickname == NULL) {
+
+    if (id_cache && id_cache->context) {
+      remote_client = (SilcClientEntry)id_cache->context;
+      if (remote_client->status & SILC_CLIENT_STATUS_RESOLVING) {
+       remote_client->status &= ~SILC_CLIENT_STATUS_RESOLVING;
+       goto out;
+      }
+      remote_client->status |= SILC_CLIENT_STATUS_RESOLVING;
+    }
+
     /* Resolve the client info */
     silc_client_get_client_by_id_resolve(client, conn, remote_id,
                                         silc_client_private_message_cb,
@@ -208,8 +218,7 @@ void silc_client_private_message(SilcClient client,
  out:
   if (payload)
     silc_private_message_payload_free(payload);
-  if (remote_id)
-    silc_free(remote_id);
+  silc_free(remote_id);
 }
 
 /* Function that actually employes the received private message key */
index 7ee729e2cd218459d12f6f5bdba31581dd56e156..c09023f916e9028c7e6dfdc8dee9010ee94054f4 100644 (file)
@@ -1767,13 +1767,22 @@ silc_client_request_authentication_method(SilcClient client,
                                          void *context);
 
 typedef enum {
+  SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT,
   SILC_CLIENT_FILE_MONITOR_SEND,
   SILC_CLIENT_FILE_MONITOR_RECEIVE,
   SILC_CLIENT_FILE_MONITOR_GET,
   SILC_CLIENT_FILE_MONITOR_PUT,
   SILC_CLIENT_FILE_MONITOR_CLOSE,
+  SILC_CLIENT_FILE_MONITOR_ERROR,
 } SilcClientMonitorStatus;
 
+typedef enum {
+  SILC_CLIENT_FILE_OK,
+  SILC_CLIENT_FILE_ERROR,
+  SILC_CLIENT_FILE_UNKNOWN_SESSION,
+  SILC_CLIENT_FILE_ALREADY_STARTED,
+} SilcClientFileError;
+
 /****f* silcclient/SilcClientAPI/silc_client_file_receive
  *
  * SYNOPSIS
@@ -1834,6 +1843,11 @@ typedef void (*SilcClientFileMonitor)(SilcClient client,
  *    file indicated by the `filepath' is being transmitted to the remote
  *    client indicated by the `client_entry', already.
  *
+ *    If error will occur during the file transfer process the error
+ *    status will be returned in the monitor callback.  In this case
+ *    the application must call silc_client_file_close to close the
+ *    session.
+ *
  ***/
 uint32 silc_client_file_send(SilcClient client,
                             SilcClientConnection conn,
@@ -1846,12 +1860,13 @@ uint32 silc_client_file_send(SilcClient client,
  *
  * SYNOPSIS
  *
- *    bool silc_client_file_receive(SilcClient client,
- *                                  SilcClientConnection conn,
- *                                  SilcClientFileMonitor monitor,
- *                                  void *monitor_context,
- *                                  SilcClientEntry client_entry,
- *                                  uint32 session_id);
+ *    SilcClientFileError 
+ *    silc_client_file_receive(SilcClient client,
+ *                             SilcClientConnection conn,
+ *                             SilcClientFileMonitor monitor,
+ *                             void *monitor_context,
+ *                             SilcClientEntry client_entry,
+ *                             uint32 session_id);
  *
  * DESCRIPTION
  *
@@ -1862,21 +1877,27 @@ uint32 silc_client_file_send(SilcClient client,
  *    actually starting the file transmission.  The `monitor' callback
  *    will be called to monitor the transmission.
  *
+ *    If error will occur during the file transfer process the error
+ *    status will be returned in the monitor callback.  In this case
+ *    the application must call silc_client_file_close to close the
+ *    session.
+ *
  ***/
-bool silc_client_file_receive(SilcClient client,
-                             SilcClientConnection conn,
-                             SilcClientFileMonitor monitor,
-                             void *monitor_context,
-                             SilcClientEntry client_entry,
-                             uint32 session_id);
+SilcClientFileError 
+silc_client_file_receive(SilcClient client,
+                        SilcClientConnection conn,
+                        SilcClientFileMonitor monitor,
+                        void *monitor_context,
+                        SilcClientEntry client_entry,
+                        uint32 session_id);
 
 /****f* silcclient/SilcClientAPI/silc_client_file_close
  *
  * SYNOPSIS
  *
- *    bool silc_client_file_close(SilcClient client,
- *                                SilcClientConnection conn,
- *                                uint32 session_id);
+ *    SilcClientFileError silc_client_file_close(SilcClient client,
+ *                                               SilcClientConnection conn,
+ *                                               uint32 session_id);
  *
  * DESCRIPTION
  *
@@ -1884,12 +1905,11 @@ bool silc_client_file_receive(SilcClient client,
  *    If file transmission is being conducted it will be aborted
  *    automatically. This function is also used to close the session
  *    after successful file transmission. This function can be used
- *    also to reject incoming file transmission request.  Returns TRUE
- *    if the session was closed and FALSE if such session does not exist.
+ *    also to reject incoming file transmission request.
  *
  ***/
-bool silc_client_file_close(SilcClient client,
-                           SilcClientConnection conn,
-                           uint32 session_id);
+SilcClientFileError silc_client_file_close(SilcClient client,
+                                          SilcClientConnection conn,
+                                          uint32 session_id);
 
 #endif
index f77b6c05e80cf96378615491ddd0b4ba3bcf1633..04e898cd4da4800a965c9f327de913a1a6fb42e4 100644 (file)
@@ -31,6 +31,7 @@ libsilccore_a_SOURCES = \
        silcauth.c \
        silcprivate.c
 
+if SILC_DIST_TOOLKIT
 include_HEADERS =      \
        silcauth.h      \
        silcchannel.h   \
@@ -42,6 +43,7 @@ include_HEADERS =     \
        silcpacket.h    \
        silcpayload.h   \
        silcprivate.h
+endif
 
 EXTRA_DIST = *.h
 
index 68cb566c884fe99a6e3857416d97698ce84eff02..d05c0bd104196fd37b6217ed7b9ef27d6cfc8b4e 100644 (file)
@@ -187,7 +187,8 @@ void silc_packet_assemble(SilcPacketContext *ctx, SilcCipher cipher)
 
   /* Get random padding */
 #if 1
-  for (i = 0; i < ctx->padlen; i++) tmppad[i] = silc_rng_global_get_byte();
+  for (i = 0; i < ctx->padlen; i++) tmppad[i] = 
+                                     silc_rng_global_get_byte_fast();
 #else
   /* XXX: For testing - to be removed */
   memset(tmppad, 65, sizeof(tmppad));
@@ -402,8 +403,16 @@ void silc_packet_receive_process(SilcSocketConnection sock,
 
     /* Decrypt rest of the packet */
     if (cipher)
-      silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence, 
-                         parse_ctx->packet->buffer, parse_ctx->normal);
+      if (silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence, 
+                             parse_ctx->packet->buffer, 
+                             parse_ctx->normal) == -1) {
+       SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s]", 
+                         sock->hostname, sock->port,
+                         (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
+                          sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
+                          sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
+                          "Router")));
+      }
 
     /* Pull the packet from inbuf thus we'll get the next one
        in the inbuf. */
@@ -445,9 +454,6 @@ static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
     /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
     if (memcmp(mac, buffer->tail, mac_len)) {
       SILC_LOG_ERROR(("MAC failed"));
-
-      /* XXX Remove */
-      assert(FALSE);
       return FALSE;
     }
     
index e55cb151c4197e0f1ec814bc0df0885058e9b4ca..cce35796f149d7f2b1c4cefe300b37edde72d852 100644 (file)
@@ -39,6 +39,7 @@ libsilccrypt_a_SOURCES = \
        silcpkcs.c \
        pkcs1.c
 
+if SILC_DIST_TOOLKIT
 include_HEADERS =      \
        aes.h           \
        blowfish.h      \
@@ -60,6 +61,7 @@ include_HEADERS =     \
        silcpkcs.h      \
        silcrng.h       \
        twofish.h
+endif
 
 EXTRA_DIST = *.h
 
index 67ee08fe47d9277da047bb2f16830a98cb5ca5fb..a52b4eea9efba6cb6b7d7f0fe253918e52aad8c0 100644 (file)
@@ -116,6 +116,7 @@ typedef struct SilcRngObjectStruct {
   SilcHash sha1;
   uint8 threshhold;
   char *devrandom;
+  int fd_devurandom;
 } SilcRngObject;
 
 /* Allocates new RNG object. */
@@ -127,6 +128,7 @@ SilcRng silc_rng_alloc()
   SILC_LOG_DEBUG(("Allocating new RNG object"));
 
   new = silc_calloc(1, sizeof(*new));
+  new->fd_devurandom = -1;
 
   memset(new->pool, 0, sizeof(new->pool));
   memset(new->key, 0, sizeof(new->key));
@@ -147,6 +149,10 @@ void silc_rng_free(SilcRng rng)
     memset(rng->key, 0, sizeof(rng->key));
     silc_hash_free(rng->sha1);
     silc_free(rng->devrandom);
+
+    if (rng->fd_devurandom != -1)
+      close(rng->fd_devurandom);
+
     silc_free(rng);
   }
 }
@@ -278,7 +284,7 @@ static void silc_rng_get_medium_noise(SilcRng rng)
 static void silc_rng_get_hard_noise(SilcRng rng)
 {
 #ifndef SILC_WIN32
-  char buf[32];
+  unsigned char buf[32];
   int fd, len, i;
   
   /* Get noise from /dev/[u]random if available */
@@ -310,7 +316,7 @@ static void silc_rng_get_hard_noise(SilcRng rng)
 static void silc_rng_exec_command(SilcRng rng, char *command)
 {
 #ifndef SILC_WIN32
-  char buf[1024];
+  unsigned char buf[1024];
   FILE *fd;
   int i;
   int c;
@@ -546,6 +552,33 @@ unsigned char silc_rng_global_get_byte()
   return global_rng ? silc_rng_get_byte(global_rng) : 0;
 }
 
+/* Return random byte as fast as possible. Reads from /dev/urandom if
+   available. If not then return from normal RNG (not so fast). */
+
+unsigned char silc_rng_global_get_byte_fast()
+{
+#ifndef SILC_WIN32
+  unsigned char buf[1];
+
+  if (!global_rng)
+    return 0;
+
+  if (global_rng->fd_devurandom == -1) {
+    global_rng->fd_devurandom = open("/dev/urandom", O_RDONLY);
+    if (global_rng < 0)
+      return silc_rng_global_get_byte();
+    fcntl(global_rng->fd_devurandom, F_SETFL, O_NONBLOCK);
+  }
+
+  if (read(global_rng->fd_devurandom, buf, sizeof(buf)) < 0)
+    return silc_rng_global_get_byte();
+
+  return buf[0];
+#else
+  return silc_rng_global_get_byte();
+#endif
+}
+
 uint16 silc_rng_global_get_rn16()
 {
   return global_rng ? silc_rng_get_rn16(global_rng) : 0;
index d8eacad21005ae1b6c8497d27f206e233800d4f6..ef52b03a49f9a31e620dba153ee7208ca34419e3 100644 (file)
@@ -191,6 +191,7 @@ void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, uint32 len);
 int silc_rng_global_init(SilcRng rng);
 int silc_rng_global_uninit();
 unsigned char silc_rng_global_get_byte();
+unsigned char silc_rng_global_get_byte_fast();
 uint16 silc_rng_global_get_rn16();
 uint32 silc_rng_global_get_rn32();
 unsigned char *silc_rng_global_get_rn_string(uint32 len);
index d4f5b7e206dc17a6125f6bf0288464726eb95ba6..d1e75ab6d8af9347233e767a305880d34cd064d5 100644 (file)
@@ -38,11 +38,13 @@ libsilcmath_a_SOURCES = \
        mpbin.c \
        $(MP_SOURCE)
 
+if SILC_DIST_TOOLKIT
 include_HEADERS =      \
        mp_gmp.h        \
        mp_mpi.h        \
        silcmath.h      \
        silcmp.h
+endif
 
 EXTRA_DIST = *.h
 
index 83cf39d3de7d4cc9f43f48bc71cb7af97ca388d1..e05612ea9b76321543b928f45f12dfd081cc2bdc 100644 (file)
@@ -26,8 +26,10 @@ libsilcsftp_a_SOURCES =      \
        sftp_util.c             \
        sftp_fs_memory.c
 
+if SILC_DIST_TOOLKIT
 include_HEADERS =      \
        silcsftp.h
+endif
 
 EXTRA_DIST = *.h tests
 
index ad45d5be586e64f9c65301fb661fbf8f130fd866..fdb14dc55f7b35f786a590a861f766787e981dd2 100644 (file)
@@ -75,7 +75,9 @@ $(SIM_HASH_OBJS): ../silccrypt/libsilccrypt.a
 
 CLEANFILES = $(SIM_MODULES_DIR)/*.sim.so
 
+if SILC_DIST_TOOLKIT
 include_HEADERS = silcsim.h silcsimutil.h
+endif
 
 EXTRA_DIST = *.h
 
index 94dffa260e4159824c311fe7fcfcab36ac0f284e..b233c42da5ccf4c94b80589315d98524e1f49462 100644 (file)
@@ -25,11 +25,13 @@ libsilcske_a_SOURCES = \
        payload.c \
         groups.c
 
+if SILC_DIST_TOOLKIT
 include_HEADERS =      \
        groups.h        \
        payload.h       \
        silcske.h       \
        silcske_status.h
+endif
 
 EXTRA_DIST = *.h
 
index e2de4414ed19909264b2d6b0a5c08a66e08242d6..93cd4a3b2591e883b0d9eb627ba7de8961af91f9 100644 (file)
@@ -38,6 +38,7 @@ libsilcutil_a_SOURCES = \
        silcsockconn.c  \
        silcprotocol.c
 
+if SILC_DIST_TOOLKIT
 include_HEADERS =      \
        silcbuffer.h    \
        silcbuffmt.h    \
@@ -53,6 +54,7 @@ include_HEADERS =     \
        silcprotocol.h  \
        silcthread.h    \
        silcutil.h
+endif
 
 EXTRA_DIST = *.h
 
index 1717d14b0085edbb097b9d7c48a09441a42cd1f4..7016b71e6ab231607cbeef4e048fbb9e26abdcb7 100644 (file)
@@ -82,6 +82,9 @@ SilcBuffer silc_buffer_realloc(SilcBuffer sb, uint32 newsize)
   if (!sb)
     return silc_buffer_alloc(newsize);
 
+  if (newsize <= sb->truelen)
+    return sb;
+
   sb_new = silc_buffer_alloc(newsize);
   silc_buffer_pull_tail(sb_new, SILC_BUFFER_END(sb_new));
   silc_buffer_put(sb_new, sb->head, sb->truelen);
index 330bab2dafa8631610875b698a913bc08dd36c5d..3120e8ef3e499cc424897e04f2f172654e44e514 100644 (file)
@@ -45,7 +45,7 @@ int silc_socket_write(SilcSocketConnection sock)
        SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
        return -2;
       }
-      SILC_LOG_ERROR(("Cannot write to socket: %s", strerror(errno)));
+      SILC_LOG_DEBUG(("Cannot write to socket: %s", strerror(errno)));
       return -1;
     }
 
@@ -80,7 +80,7 @@ int silc_socket_read(SilcSocketConnection sock)
       SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
       return -2;
     }
-    SILC_LOG_ERROR(("Cannot read from socket: %d:%s", fd, strerror(errno)));
+    SILC_LOG_DEBUG(("Cannot read from socket: %d:%s", fd, strerror(errno)));
     return -1;
   }