Merge commit 'origin/silc.1.1.branch'
[silc.git] / lib / silcsftp / tests / sftp_client.c
index 196b67681065b2aff3c94298fc935c2cf9a662e9..403e50715d1ffd721d1d4f161dc461fe18ee8235 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  sftp_client.c 
+  sftp_client.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2007 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
 
 */
 
-#include "silcincludes.h"
+/* Tests:
+   silc_sftp_client_start();
+   silc_sftp_client_receive_process();
+   silc_sftp_opendir();
+   silc_sftp_readdir();
+   silc_sftp_open();
+   silc_sftp_read();
+   silc_sftp_fstat();
+   silc_sftp_lstat();
+   silc_sftp_close();
+*/
+
+#include "silc.h"
 #include "silcsftp.h"
 
 typedef struct {
   SilcSchedule schedule;
-  SilcSocketConnection sock;
+  SilcStream stream;
   SilcSFTP sftp;
 } *Client;
 
@@ -31,105 +43,100 @@ Client gclient;
 char *dir;
 char *file;
 bool opendir;
-uint64 offset;
+SilcUInt64 offset;
+bool success = FALSE;
 
 static void sftp_name(SilcSFTP sftp, SilcSFTPStatus status,
                      const SilcSFTPName name, void *context);
 static void sftp_handle(SilcSFTP sftp, SilcSFTPStatus status,
                        SilcSFTPHandle handle, void *context);
 static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status,
-                     const unsigned char *data, uint32 data_len,
+                     const unsigned char *data, SilcUInt32 data_len,
                      void *context);
+static void end_test(void);
 
-static void send_packet(SilcSocketConnection sock,
-                       SilcBuffer packet, void *context)
+static void sftp_status(SilcSFTP sftp, SilcSFTPStatus status,
+                       const char *message, const char *lang_tag,
+                       void *context)
 {
-  Client client = (Client)context;
-  SilcPacketContext packetdata;
-  int ret;
-
-  memset(&packetdata, 0, sizeof(packetdata));
-  packetdata.type = SILC_PACKET_FTP;
-  packetdata.truelen = packet->len + SILC_PACKET_HEADER_LEN;
-  packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
-  silc_packet_send_prepare(sock,
-                          SILC_PACKET_HEADER_LEN,
-                          packetdata.padlen,
-                          packet->len);
-  packetdata.buffer = sock->outbuf;
-  silc_buffer_put(sock->outbuf, packet->data, packet->len);
-  silc_packet_assemble(&packetdata);
-  ret = silc_packet_send(sock, TRUE);
-  if (ret != -2)
+  fprintf(stderr, "Status %d\n", status);
+  if (status != SILC_SFTP_STATUS_OK) {
+    SILC_LOG_DEBUG(("Error status"));
+    success = FALSE;
+    end_test();
     return;
+  }
 
-  silc_schedule_set_listen_fd(client->schedule, sock->sock, 
-                             (SILC_TASK_READ | SILC_TASK_WRITE));
-  SILC_SET_OUTBUF_PENDING(sock);
-}
-
-static void packet_parse(SilcPacketParserContext *parser)
-{
-  Client client = (Client)parser->context;
-  SilcSocketConnection sock = parser->sock;
-  SilcPacketContext *packet = parser->packet;
-  int ret;
-  
-  ret = silc_packet_parse(packet);
-  assert(packet->type == SILC_PACKET_FTP);
-
-  silc_sftp_client_receive_process(client->sftp, sock, packet);
+  success = TRUE;
+  end_test();
 }
 
-SILC_TASK_CALLBACK(packet_process)
+static void sftp_attr(SilcSFTP sftp, SilcSFTPStatus status,
+                     const SilcSFTPAttributes attrs, void *context)
 {
-  Client client = (Client)context;
-  SilcSocketConnection sock = client->sock;
-  int ret;
-
-  if (type == SILC_TASK_WRITE) {
-    if (sock->outbuf->data - sock->outbuf->head)
-     silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
-
-    ret = silc_packet_send(sock, TRUE);
-    if (ret < 0)
-      return;
+  SilcSFTPHandle handle = (SilcSFTPHandle)context;
+  int i;
 
-    silc_schedule_set_listen_fd(client->schedule, fd, SILC_TASK_READ);
-    SILC_UNSET_OUTBUF_PENDING(sock);
-    silc_buffer_clear(sock->outbuf);
+  fprintf(stderr, "Status %d\n", status);
+  if (status != SILC_SFTP_STATUS_OK) {
+    SILC_LOG_DEBUG(("Error status"));
+    success = FALSE;
+    end_test();
     return;
   }
 
-  if (type == SILC_TASK_READ) {
-    ret = silc_packet_receive(sock);
-    if (ret < 0)
-      return;
 
-    if (ret == 0) {
-      silc_net_close_connection(sock->sock);
-      silc_socket_free(sock);
-      exit(0);
-    }
+  SILC_LOG_DEBUG(("Attr.flags: %d", attrs->flags));
+  SILC_LOG_DEBUG(("Attr.size: %lu", attrs->size));
+  SILC_LOG_DEBUG(("Attr.uid: %d", attrs->uid));
+  SILC_LOG_DEBUG(("Attr.gid: %d", attrs->gid));
+  SILC_LOG_DEBUG(("Attr.permissions: %d", attrs->permissions));
+  SILC_LOG_DEBUG(("Attr.atime: %d", attrs->atime));
+  SILC_LOG_DEBUG(("Attr.mtime: %d", attrs->mtime));
+  SILC_LOG_DEBUG(("Attr.extended count: %d", attrs->extended_count));
+  for (i = 0; i < attrs->extended_count; i++) {
+    SILC_LOG_HEXDUMP(("Attr.extended_type[i]:", i),
+                    attrs->extended_type[i]->data,
+                    silc_buffer_len(attrs->extended_type[i]));
+    SILC_LOG_HEXDUMP(("Attr.extended_data[i]:", i),
+                    attrs->extended_data[i]->data,
+                    silc_buffer_len(attrs->extended_data[i]));
+  }
 
-    silc_packet_receive_process(sock, NULL, NULL, packet_parse, client);
+  if (!file) {
+    fprintf(stderr, "Closing file\n");
+    silc_sftp_close(sftp, handle, sftp_status, context);
+    return;
   }
+
+  fprintf(stderr, "LStatting file %s\n", file);
+  silc_sftp_lstat(sftp, file, sftp_attr, context);
+  file = NULL;
 }
 
 static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status,
-                     const unsigned char *data, uint32 data_len,
+                     const unsigned char *data, SilcUInt32 data_len,
                      void *context)
 {
   SilcSFTPHandle handle = (SilcSFTPHandle)context;
-  int debug = silc_debug;
 
   if (status != SILC_SFTP_STATUS_OK) {
     SilcSFTPAttributesStruct attrs;
 
     fprintf(stderr, "Status %d\n", status);
 
-    if (!strcmp(file, "/sftp/sftp_server.c"))
+    if (status != SILC_SFTP_STATUS_EOF) {
+      SILC_LOG_DEBUG(("Error status"));
+      success = FALSE;
+      end_test();
+      return;
+    }
+
+    if (!strcmp(file, "/sftp/sftp_server.c")) {
+      fprintf(stderr, "FStatting file handle %s\n", file);
+      silc_sftp_fstat(sftp, handle, sftp_attr, context);
       return;
+    }
 
     /* Open another file */
     opendir = FALSE;
@@ -142,10 +149,7 @@ static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status,
     return;
   }
 
-  if (!debug)
-    silc_debug = 1;
   SILC_LOG_HEXDUMP(("data"), (unsigned char *)data, data_len);
-  silc_debug = debug;
 
   offset += data_len;
 
@@ -163,6 +167,13 @@ static void sftp_name(SilcSFTP sftp, SilcSFTPStatus status,
   SILC_LOG_DEBUG(("Name"));
   fprintf(stderr, "Status %d\n", status);
 
+  if (status != SILC_SFTP_STATUS_OK) {
+    SILC_LOG_DEBUG(("Error status"));
+    success = FALSE;
+    end_test();
+    return;
+  }
+
   fprintf(stderr, "Directory: %s\n", dir);
   for (i = 0; i < name->count; i++) {
     fprintf(stderr, "%s\n", name->long_filename[i]);
@@ -199,8 +210,12 @@ static void sftp_handle(SilcSFTP sftp, SilcSFTPStatus status,
 
   SILC_LOG_DEBUG(("Handle"));
   fprintf(stderr, "Status %d\n", status);
-  if (status != SILC_SFTP_STATUS_OK)
+  if (status != SILC_SFTP_STATUS_OK) {
+    SILC_LOG_DEBUG(("Error status"));
+    success = FALSE;
+    end_test();
     return;
+  }
 
   if (opendir) {
     fprintf(stderr, "Reading %s\n", dir);
@@ -222,6 +237,12 @@ static void sftp_version(SilcSFTP sftp, SilcSFTPStatus status,
 
   SILC_LOG_DEBUG(("Version"));
   fprintf(stderr, "Status %d\n", status);
+  if (status != SILC_SFTP_STATUS_OK) {
+    SILC_LOG_DEBUG(("Error status"));
+    success = FALSE;
+    end_test();
+    return;
+  }
 
   /* opendir */
   dir = "/";
@@ -230,33 +251,66 @@ static void sftp_version(SilcSFTP sftp, SilcSFTPStatus status,
   silc_sftp_opendir(sftp, dir, sftp_handle, client);
 }
 
+static void sftp_error(SilcSFTP sftp, SilcSFTPStatus status,
+                      void *context)
+{
+  Client client = context;
+  SILC_LOG_DEBUG(("Error %d", status));
+  silc_stream_destroy(client->stream);
+  success = FALSE;
+  end_test();
+}
+
+static void connect_callback(SilcNetStatus status, SilcStream stream,
+                            void *context)
+{
+  Client client = context;
+
+  if (!stream) {
+    SILC_LOG_DEBUG(("Connect error"));
+    success = FALSE;
+    end_test();
+  }
+
+  /* Start SFTP session */
+  client->stream = stream;
+  client->sftp = silc_sftp_client_start(stream, client->schedule, sftp_version,
+                                       sftp_error, client);
+  if (!client->sftp) {
+    success = FALSE;
+    end_test();
+  }
+}
+
 int main(int argc, char **argv)
 {
   Client client = silc_calloc(1, sizeof(*client));
-  int sock;
 
   gclient = client;
 
-  if (argc > 1 && !strcmp(argv[1], "-d"))
-    silc_debug = 1;
+  if (argc > 1) {
+    if (!strcmp(argv[1], "-d"))
+      silc_log_debug(TRUE);
+    if (argc > 2 && !strcmp(argv[2], "-x"))
+      silc_log_debug_hexdump(TRUE);
+    silc_log_set_debug_string("*");
+  }
 
-  client->schedule = silc_schedule_init(100);
+  client->schedule = silc_schedule_init(0, NULL, NULL);
   if (!client->schedule)
     return -1;
 
   /* Connecto to server */
-  sock = silc_net_create_connection(NULL, 5000, "127.0.0.1");
-  if (sock < 0)
-    return -1;
-  silc_socket_alloc(sock, 0, NULL, &client->sock);
-  silc_schedule_task_add(client->schedule, sock,
-                        packet_process, client, 0, 0,
-                        SILC_TASK_GENERIC, SILC_TASK_PRI_NORMAL);
-
-  /* Start SFTP session */
-  client->sftp = silc_sftp_client_start(client->sock, send_packet, client,
-                                       sftp_version, client);
+  silc_net_tcp_connect(NULL, "127.0.0.1", 5000, client->schedule,
+                      connect_callback, client);
 
   silc_schedule(client->schedule);
   return 0;
 }
+
+static void end_test(void)
+{
+  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
+  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
+  exit(success);
+}