From 38a1cef323bda0902c36889936e6dbb8e277c479 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Wed, 3 Jan 2007 17:45:58 +0000 Subject: [PATCH] Ported SFTP library to new util library. --- CHANGES | 3 + TODO | 4 +- configure.ad | 2 + distdir/client | 3 - lib/Makefile.ad | 7 +- lib/silcsftp/sftp_client.c | 184 +++++++++++++++---------------- lib/silcsftp/sftp_fs_memory.c | 2 +- lib/silcsftp/sftp_server.c | 128 +++++++++++++++++---- lib/silcsftp/sftp_util.c | 119 ++++++++++---------- lib/silcsftp/silcsftp.h | 82 ++++++++------ lib/silcsftp/tests/Makefile.am | 2 +- lib/silcsftp/tests/sftp_client.c | 171 +++++++++------------------- lib/silcsftp/tests/sftp_server.c | 141 ++++++----------------- 13 files changed, 401 insertions(+), 447 deletions(-) diff --git a/CHANGES b/CHANGES index a650ed1b..2728fef9 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,9 @@ Wed Jan 3 18:06:33 EET 2007 Pekka Riikonen * Fixed %p formatting from silc_snprintf. Affected file is lib/silcutil/silcsnprintf.c. + * Ported SFTP library to new utility library. Ported also + the SFTP testers. Affected files in lib/silcsftp/. + Tue Jan 2 17:18:46 EET 2007 Pekka Riikonen * Added lib/silcutil/silcsnprintf.[ch]. Added in addition diff --git a/TODO b/TODO index dac81c5a..39edc027 100644 --- a/TODO +++ b/TODO @@ -76,10 +76,10 @@ lib/silcclient, The Client Library ***PARTLY DONE**** o All packet waiting timeout tests and error condition tests. -lib/silcsftp +lib/silcsftp ****DONE**** ============ - o Porting to use the new util library. + o Porting to use the new util library. (***DONE) lib/silccore/silcpacket.[ch] ****DONE**** diff --git a/configure.ad b/configure.ad index 5f014183..2dbd9bdd 100644 --- a/configure.ad +++ b/configure.ad @@ -135,6 +135,8 @@ AC_CHECK_SIZEOF(char, 0) AC_SUBST(SILC_SIZEOF_CHAR, $ac_cv_sizeof_char) AC_CHECK_SIZEOF(void *, 0) AC_SUBST(SILC_SIZEOF_VOID_P, $ac_cv_sizeof_void_p) +AC_CHECK_TYPES(long long) +AC_CHECK_TYPES(long double) # Function to check if compiler flag works # Usage: SILC_ADD_CFLAGS(FLAGS, [ACTION-IF-FAILED]) diff --git a/distdir/client b/distdir/client index c6ea8099..13f35fef 100644 --- a/distdir/client +++ b/distdir/client @@ -6,9 +6,6 @@ inherit common define SILC_DIST_CLIENT define SILC_DIST_CLIENTLIB -# XXX -undef SILC_DIST_SFTP - pre-hook distdir/pre-run post-process-dist-hook distdir/post-process-dist post-dist-hook distdir/post-dist diff --git a/lib/Makefile.ad b/lib/Makefile.ad index fbcaca3a..b12b9dc4 100644 --- a/lib/Makefile.ad +++ b/lib/Makefile.ad @@ -17,10 +17,6 @@ AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign -#ifdef SILC_DIST_SFTP -# silcsftp -#endif SILC_DIST_SFTP - # SILC Library dirs SILCLIB_DIRS = \ contrib \ @@ -44,6 +40,9 @@ SILCLIB_DIRS = \ #ifdef SILC_DIST_HTTP silchttp \ #endif SILC_DIST_HTTP +#ifdef SILC_DIST_SFTP + silcsftp +#endif SILC_DIST_SFTP #ifdef SILC_DIST_IDCACHE silcvcard \ #endif SILC_DIST_IDCACHE diff --git a/lib/silcsftp/sftp_client.c b/lib/silcsftp/sftp_client.c index a6043723..7227d33c 100644 --- a/lib/silcsftp/sftp_client.c +++ b/lib/silcsftp/sftp_client.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2005 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 @@ -25,8 +25,7 @@ /* Request context. Every request will allocate this context and set the correct callback function according the `type' field. */ typedef struct SilcSFTPRequestStruct { - SilcUInt32 id; - SilcSFTPPacket type; + struct SilcSFTPRequestStruct *next; SilcSFTPStatusCallback status; SilcSFTPHandleCallback handle; SilcSFTPDataCallback data; @@ -34,17 +33,19 @@ typedef struct SilcSFTPRequestStruct { SilcSFTPAttrCallback attr; SilcSFTPExtendedCallback extended; void *context; - struct SilcSFTPRequestStruct *next; + SilcUInt32 id; + SilcSFTPPacket type; } *SilcSFTPRequest; /* SFTP client context */ typedef struct { SilcStream stream; SilcSFTPVersionCallback version; - void *version_context; - SilcUInt32 id; + SilcSFTPErrorCallback error; + void *context; SilcList requests; SilcBuffer packet; + SilcUInt32 id; } *SilcSFTPClient; /* File handle */ @@ -54,7 +55,7 @@ struct SilcSFTPHandleStruct { }; static void silc_sftp_client_receive_process(SilcSFTP context, - SilcBuffer buffer) + SilcBuffer buffer); /* Creates SilcSFTPHandle and returns pointer to it. The caller must free the context. */ @@ -94,7 +95,7 @@ static void silc_sftp_handle_get(SilcSFTPHandle handle, *data_len = handle->data_len; } -/* General routine to send SFTP packet to the SFTP server. */ +/* Generic routine to send SFTP packet to the SFTP server. */ static void silc_sftp_send_packet(SilcSFTPClient sftp, SilcSFTPPacket type, @@ -102,6 +103,7 @@ static void silc_sftp_send_packet(SilcSFTPClient sftp, { SilcBuffer tmp; va_list vp; + int ret; va_start(vp, len); tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp); @@ -114,8 +116,17 @@ static void silc_sftp_send_packet(SilcSFTPClient sftp, silc_buffer_len(sftp->packet)); /* Send the packet */ - silc_stream_write(sftp->stream, sftp->packet->data, - silc_buffer_len(sftp->packet)); + while (silc_buffer_len(sftp->packet) > 0) { + ret = silc_stream_write(sftp->stream, silc_buffer_data(sftp->packet), + silc_buffer_len(sftp->packet)); + if (ret == -2) { + SILC_LOG_ERROR(("Error sending SFTP packet type %d", type)); + break; + } + if (ret <= 0) + break; + silc_buffer_pull(sftp->packet, ret); + } /* Clear packet */ silc_buffer_reset(sftp->packet); @@ -136,7 +147,7 @@ static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp, return req; } - SILC_LOG_DEBUG(("Unknown request ID")); + SILC_LOG_DEBUG(("Unknown request ID %d", id)); return NULL; } @@ -302,17 +313,37 @@ static void silc_sftp_call_request(SilcSFTPClient sftp, va_end(vp); } -/* Handles stream IO */ +/* Handles stream I/O */ static void silc_sftp_client_io(SilcStream stream, SilcStreamStatus status, void *context) { SilcSFTPClient sftp = context; + unsigned char inbuf[30720]; + SilcBufferStruct packet; + int ret; switch (status) { + case SILC_STREAM_CAN_READ: + SILC_LOG_DEBUG(("Reading data from stream")); + + /* Read data from stream */ + ret = silc_stream_read(stream, inbuf, sizeof(inbuf)); + if (ret <= 0) { + if (ret == 0) + sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context); + if (ret == -2) + sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context); + return; + } + + /* Now process the SFTP packet */ + silc_buffer_set(&packet, inbuf, ret); + silc_sftp_client_receive_process(context, &packet); + break; case SILC_STREAM_CAN_WRITE: - if (!silc_buffer_headlen(&sftp->packet)) + if (!silc_buffer_headlen(sftp->packet)) return; SILC_LOG_DEBUG(("Writing pending data to stream")); @@ -323,70 +354,25 @@ static void silc_sftp_client_io(SilcStream stream, SilcStreamStatus status, ret = silc_stream_write(stream, sftp->packet->data, silc_buffer_len(sftp->packet)); if (ret == 0) { - /* EOS */ - /* XXX */ + sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context); silc_buffer_reset(sftp->packet); return; } - if (i == -2) { - /* Error */ - /* XXX */ + if (ret == -2) { + sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context); silc_buffer_reset(sftp->packet); - return FALSE; + return; } - if (ret == -1) { - /* Cannot write now, write later. */ - silc_buffer_pull(sftp->packet, silc_buffer_len(sftp->packet)); + if (ret == -1) return; - } /* Wrote data */ silc_buffer_pull(sftp->packet, ret); } break; - case SILC_STREAM_CAN_READ: - SILC_LOG_DEBUG(("Reading data from stream")); - - /* Make sure we have fair amount of free space in inbuf */ - if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE) - if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) + - SILC_PACKET_DEFAULT_SIZE * 2)) - return; - - /* Read data from stream */ - ret = silc_stream_read(ps->stream, &ps->inbuf.tail, - silc_buffer_taillen(&ps->inbuf)); - - if (ret == 0) { - /* EOS */ - SILC_PACKET_CALLBACK_EOS(ps); - silc_buffer_reset(&ps->inbuf); - return; - } - - if (ret == -2) { - /* Error */ - SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ); - silc_buffer_reset(&ps->inbuf); - return; - } - - if (ret == -1) { - /* Cannot read now, do it later. */ - silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf)); - return; - } - - /* Read some data */ - silc_buffer_pull_tail(&ps->inbuf, ret); - - /* Now process the data */ - silc_sftp_client_receive_process(sftp); - break; - default: break; } @@ -395,11 +381,15 @@ static void silc_sftp_client_io(SilcStream stream, SilcStreamStatus status, /* Starts SFTP client and returns context for it. */ SilcSFTP silc_sftp_client_start(SilcStream stream, - SilcSFTPVersionCallback callback, + SilcSchedule schedule, + SilcSFTPVersionCallback version_cb, + SilcSFTPErrorCallback error_cb, void *context) { SilcSFTPClient sftp; + SILC_LOG_DEBUG(("Starting SFTP client")); + if (!stream) return NULL; @@ -407,12 +397,13 @@ SilcSFTP silc_sftp_client_start(SilcStream stream, if (!sftp) return NULL; sftp->stream = stream; - sftp->version = callback; - sftp->version_context = context; + sftp->version = version_cb; + sftp->error = error_cb; + sftp->context = context; silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next); /* We handle the stream now */ - silc_stream_set_notifier(stream, silc_sftp_client_io, sftp); + silc_stream_set_notifier(stream, schedule, silc_sftp_client_io, sftp); /* Send the SFTP session initialization to the server */ silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4, @@ -430,6 +421,7 @@ void silc_sftp_client_shutdown(SilcSFTP context) { SilcSFTPClient sftp = (SilcSFTPClient)context; + silc_stream_set_notifier(sftp->stream, NULL, NULL, NULL); if (sftp->packet) silc_buffer_free(sftp->packet); silc_free(sftp); @@ -448,10 +440,10 @@ void silc_sftp_client_receive_process(SilcSFTP context, SilcBuffer buffer) SilcBufferStruct buf; SilcUInt32 id; - SILC_LOG_DEBUG(("Start")); + SILC_LOG_DEBUG(("Process SFTP packet")); /* Parse the packet */ - type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload, + type = silc_sftp_packet_decode(buffer, (unsigned char **)&payload, &payload_len); if (!type) return; @@ -459,6 +451,31 @@ void silc_sftp_client_receive_process(SilcSFTP context, SilcBuffer buffer) silc_buffer_set(&buf, (unsigned char *)payload, payload_len); switch (type) { + case SILC_SFTP_DATA: + { + unsigned char *data = NULL; + SilcUInt32 data_len = 0; + + SILC_LOG_DEBUG(("Data packet")); + + ret = silc_buffer_unformat(&buf, + SILC_STR_UI_INT(&id), + SILC_STR_UI32_NSTRING(&data, &data_len), + SILC_STR_END); + if (ret < 0) + break; + + /* Get request */ + req = silc_sftp_find_request(sftp, id); + if (!req) + break; + + /* Call the callback */ + silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, + data, data_len); + } + break; + case SILC_SFTP_VERSION: { SilcSFTPVersion version; @@ -470,13 +487,13 @@ void silc_sftp_client_receive_process(SilcSFTP context, SilcBuffer buffer) SILC_STR_END); if (ret < 0) { (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0, - sftp->version_context); + sftp->context); break; } /* Call the callback */ (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version, - sftp->version_context); + sftp->context); } break; @@ -548,31 +565,6 @@ void silc_sftp_client_receive_process(SilcSFTP context, SilcBuffer buffer) } break; - case SILC_SFTP_DATA: - { - unsigned char *data = NULL; - SilcUInt32 data_len = 0; - - SILC_LOG_DEBUG(("Data packet")); - - ret = silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&id), - SILC_STR_UI32_NSTRING(&data, &data_len), - SILC_STR_END); - if (ret < 0) - break; - - /* Get request */ - req = silc_sftp_find_request(sftp, id); - if (!req) - break; - - /* Call the callback */ - silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, - data, data_len); - } - break; - case SILC_SFTP_NAME: { SilcUInt32 count; diff --git a/lib/silcsftp/sftp_fs_memory.c b/lib/silcsftp/sftp_fs_memory.c index 66d393ac..d23b7d2a 100644 --- a/lib/silcsftp/sftp_fs_memory.c +++ b/lib/silcsftp/sftp_fs_memory.c @@ -775,7 +775,7 @@ void mem_readdir(void *context, SilcSFTP sftp, filesize = sizeof(*entry); memset(long_name, 0, sizeof(long_name)); - date = (char *)silc_get_time(entry->created); + date = (char *)silc_time_string(entry->created); if (strrchr(date, ':')) *strrchr(date, ':') = '\0'; diff --git a/lib/silcsftp/sftp_server.c b/lib/silcsftp/sftp_server.c index de0b52ef..41e049ee 100644 --- a/lib/silcsftp/sftp_server.c +++ b/lib/silcsftp/sftp_server.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2004 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 @@ -25,15 +25,18 @@ /* SFTP Server context */ typedef struct { - SilcSFTPSendPacketCallback send_packet; - void *send_context; + SilcStream stream; SilcSFTPMonitors monitors; SilcSFTPMonitor monitor; void *monitor_context; SilcSFTPFilesystem fs; SilcBuffer packet; + SilcSFTPErrorCallback error; + void *context; } *SilcSFTPServer; +static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer); + /* General routine to send SFTP packet to the SFTP client. */ static void silc_sftp_send_packet(SilcSFTPServer sftp, @@ -42,6 +45,7 @@ static void silc_sftp_send_packet(SilcSFTPServer sftp, { SilcBuffer tmp; va_list vp; + int ret; va_start(vp, len); tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp); @@ -50,15 +54,89 @@ static void silc_sftp_send_packet(SilcSFTPServer sftp, return; sftp->packet = tmp; - SILC_LOG_HEXDUMP(("SFTP packet to client"), sftp->packet->data, - sftp->packet->len); + SILC_LOG_HEXDUMP(("SFTP packet to client"), silc_buffer_data(sftp->packet), + silc_buffer_len(sftp->packet)); /* Send the packet */ - (*sftp->send_packet)(sftp->packet, sftp->send_context); + while (silc_buffer_len(sftp->packet) > 0) { + ret = silc_stream_write(sftp->stream, silc_buffer_data(sftp->packet), + silc_buffer_len(sftp->packet)); + if (ret == -2) { + SILC_LOG_ERROR(("Error sending SFTP packet type %d", type)); + break; + } + if (ret <= 0) + break; + silc_buffer_pull(sftp->packet, ret); + } /* Clear packet */ - sftp->packet->data = sftp->packet->tail = sftp->packet->head; - sftp->packet->len = 0; + silc_buffer_reset(sftp->packet); +} + +/* Handles stream I/O */ + +static void silc_sftp_server_io(SilcStream stream, SilcStreamStatus status, + void *context) +{ + SilcSFTPServer sftp = context; + unsigned char inbuf[30720]; + SilcBufferStruct packet; + int ret; + + switch (status) { + case SILC_STREAM_CAN_READ: + SILC_LOG_DEBUG(("Reading data from stream")); + + /* Read data from stream */ + ret = silc_stream_read(stream, inbuf, sizeof(inbuf)); + if (ret <= 0) { + if (ret == 0) + sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context); + if (ret == -2) + sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context); + return; + } + + /* Now process the SFTP packet */ + silc_buffer_set(&packet, inbuf, ret); + silc_sftp_server_receive_process(context, &packet); + break; + + case SILC_STREAM_CAN_WRITE: + if (!silc_buffer_headlen(sftp->packet)) + return; + + SILC_LOG_DEBUG(("Writing pending data to stream")); + + /* Write pending data to stream */ + silc_buffer_push(sftp->packet, silc_buffer_headlen(sftp->packet)); + while (silc_buffer_len(sftp->packet) > 0) { + ret = silc_stream_write(stream, sftp->packet->data, + silc_buffer_len(sftp->packet)); + if (ret == 0) { + sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context); + silc_buffer_reset(sftp->packet); + return; + } + + if (ret == -2) { + sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context); + silc_buffer_reset(sftp->packet); + return; + } + + if (ret == -1) + return; + + /* Wrote data */ + silc_buffer_pull(sftp->packet, ret); + } + break; + + default: + break; + } } /* Sends error to the client */ @@ -194,9 +272,10 @@ static void silc_sftp_server_name(SilcSFTP sftp, return; } - silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + namebuf->len, + silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + silc_buffer_len(namebuf), SILC_STR_UI_INT(id), - SILC_STR_UI_XNSTRING(namebuf->data, namebuf->len), + SILC_STR_DATA(silc_buffer_data(namebuf), + silc_buffer_len(namebuf)), SILC_STR_END); } @@ -225,9 +304,10 @@ static void silc_sftp_server_attr(SilcSFTP sftp, return; } - silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + attr_buf->len, + silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + silc_buffer_len(attr_buf), SILC_STR_UI_INT(id), - SILC_STR_UI_XNSTRING(attr_buf->data, attr_buf->len), + SILC_STR_DATA(silc_buffer_data(attr_buf), + silc_buffer_len(attr_buf)), SILC_STR_END); silc_buffer_free(attr_buf); @@ -263,8 +343,10 @@ static void silc_sftp_server_extended(SilcSFTP sftp, by the library when it needs to send a packet. The `fs' is the structure containing filesystem access callbacks. */ -SilcSFTP silc_sftp_server_start(SilcSFTPSendPacketCallback send_packet, - void *send_context, +SilcSFTP silc_sftp_server_start(SilcStream stream, + SilcSchedule schedule, + SilcSFTPErrorCallback error_cb, + void *context, SilcSFTPFilesystem fs) { SilcSFTPServer server; @@ -272,10 +354,14 @@ SilcSFTP silc_sftp_server_start(SilcSFTPSendPacketCallback send_packet, server = silc_calloc(1, sizeof(*server)); if (!server) return NULL; - server->send_packet = send_packet; - server->send_context = send_context; + server->stream = stream; + server->error = error_cb; + server->context = context; server->fs = fs; + /* We handle the stream now */ + silc_stream_set_notifier(stream, schedule, silc_sftp_server_io, server); + SILC_LOG_DEBUG(("Starting SFTP server %p", server)); return (SilcSFTP)server; @@ -313,9 +399,7 @@ void silc_sftp_server_set_monitor(SilcSFTP sftp, /* XXX Some day this will go away and we have automatic receive callbacks for SilcSocketConnection API or SilcPacketContext API. */ -void silc_sftp_server_receive_process(SilcSFTP sftp, - SilcSocketConnection sock, - SilcPacketContext *packet) +static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer) { SilcSFTPServer server = (SilcSFTPServer)sftp; SilcSFTPPacket type; @@ -332,7 +416,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, SILC_LOG_DEBUG(("Start")); /* Parse the packet */ - type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload, + type = silc_sftp_packet_decode(buffer, (unsigned char **)&payload, &payload_len); if (!type) return; @@ -1017,11 +1101,11 @@ void silc_sftp_server_receive_process(SilcSFTP sftp, data_len = 8 + strlen(request); silc_buffer_pull(&buf, data_len); ret = silc_buffer_unformat(&buf, - SILC_STR_UI_XNSTRING(&data, buf.len), + SILC_STR_DATA(&data, silc_buffer_len(&buf)), SILC_STR_END); if (ret < 0) goto failure; - data_len = buf.len; + data_len = silc_buffer_len(&buf); /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) { diff --git a/lib/silcsftp/sftp_util.c b/lib/silcsftp/sftp_util.c index b3f79d5a..6aa40dbe 100644 --- a/lib/silcsftp/sftp_util.c +++ b/lib/silcsftp/sftp_util.c @@ -1,10 +1,10 @@ /* - sftp_util.c + sftp_util.c Author: Pekka Riikonen - Copyright (C) 2001 - 2002 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 @@ -29,7 +29,7 @@ to that buffer instead of allocating new one. If the new data cannot fit to `packet_buf' will be reallocated. */ -SilcBuffer silc_sftp_packet_encode(SilcSFTPPacket packet, +SilcBuffer silc_sftp_packet_encode(SilcSFTPPacket packet, SilcBuffer packet_buf, SilcUInt32 len, ...) { SilcBuffer buffer; @@ -45,8 +45,8 @@ SilcBuffer silc_sftp_packet_encode(SilcSFTPPacket packet, /* Same as silc_sftp_packet_encode but takes the variable argument list pointer as argument. */ -SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, - SilcBuffer packet_buf, SilcUInt32 len, +SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, + SilcBuffer packet_buf, SilcUInt32 len, va_list vp) { SilcBuffer buffer; @@ -54,7 +54,7 @@ SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, int ret; if (packet_buf) { - if (packet_buf->truelen < 4 + 1 + len) { + if (silc_buffer_truelen(packet_buf) < 4 + 1 + len) { packet_buf = silc_buffer_realloc(packet_buf, 4 + 1 + len); if (!packet_buf) return NULL; @@ -69,8 +69,8 @@ SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, dyn = TRUE; } - silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer)); - silc_buffer_format(buffer, + silc_buffer_pull_tail(buffer, 4 + 1 + len); + silc_buffer_format(buffer, SILC_STR_UI_INT(len), SILC_STR_UI_CHAR(packet), SILC_STR_END); @@ -110,11 +110,11 @@ SilcSFTPPacket silc_sftp_packet_decode(SilcBuffer packet, if (type < SILC_SFTP_INIT || type > SILC_SFTP_EXTENDED_REPLY) return 0; - if (len > (packet->len - 5)) + if (len > (silc_buffer_len(packet) - 5)) return 0; silc_buffer_pull(packet, 5); - ret = silc_buffer_unformat(packet, + ret = silc_buffer_unformat(packet, SILC_STR_UI_XNSTRING(payload, len), SILC_STR_END); if (ret < 0) @@ -148,8 +148,8 @@ SilcBuffer silc_sftp_attr_encode(SilcSFTPAttributes attr) len += 4; for (i = 0; i < attr->extended_count; i++) { len += 8; - len += attr->extended_type[i]->len; - len += attr->extended_data[i]->len; + len += silc_buffer_len(attr->extended_type[i]); + len += silc_buffer_len(attr->extended_data[i]); } } @@ -157,57 +157,58 @@ SilcBuffer silc_sftp_attr_encode(SilcSFTPAttributes attr) if (!buffer) return NULL; - silc_buffer_format(buffer, - SILC_STR_UI_INT(attr->flags), + silc_buffer_format(buffer, + SILC_STR_UI_INT(attr->flags), SILC_STR_END); silc_buffer_pull(buffer, 4); if (attr->flags & SILC_SFTP_ATTR_SIZE) { - silc_buffer_format(buffer, - SILC_STR_UI_INT64(attr->size), + silc_buffer_format(buffer, + SILC_STR_UI_INT64(attr->size), SILC_STR_END); silc_buffer_pull(buffer, 8); } if (attr->flags & SILC_SFTP_ATTR_UIDGID) { - silc_buffer_format(buffer, - SILC_STR_UI_INT(attr->uid), - SILC_STR_UI_INT(attr->gid), + silc_buffer_format(buffer, + SILC_STR_UI_INT(attr->uid), + SILC_STR_UI_INT(attr->gid), SILC_STR_END); silc_buffer_pull(buffer, 8); } if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) { - silc_buffer_format(buffer, - SILC_STR_UI_INT(attr->permissions), + silc_buffer_format(buffer, + SILC_STR_UI_INT(attr->permissions), SILC_STR_END); silc_buffer_pull(buffer, 4); } if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) { - silc_buffer_format(buffer, - SILC_STR_UI_INT(attr->atime), - SILC_STR_UI_INT(attr->mtime), + silc_buffer_format(buffer, + SILC_STR_UI_INT(attr->atime), + SILC_STR_UI_INT(attr->mtime), SILC_STR_END); silc_buffer_pull(buffer, 8); } if (attr->flags & SILC_SFTP_ATTR_EXTENDED) { - silc_buffer_format(buffer, - SILC_STR_UI_INT(attr->extended_count), + silc_buffer_format(buffer, + SILC_STR_UI_INT(attr->extended_count), SILC_STR_END); silc_buffer_pull(buffer, 4); for (i = 0; i < attr->extended_count; i++) { - ret = - silc_buffer_format(buffer, - SILC_STR_UI_INT(attr->extended_type[i]->len), - SILC_STR_UI_XNSTRING(attr->extended_type[i]->data, - attr->extended_type[i]->len), - SILC_STR_UI_INT(attr->extended_data[i]->len), - SILC_STR_UI_XNSTRING(attr->extended_data[i]->data, - attr->extended_data[i]->len), - SILC_STR_END); + ret = + silc_buffer_format( + buffer, + SILC_STR_UI_INT(silc_buffer_len(attr->extended_type[i])), + SILC_STR_DATA(silc_buffer_data(attr->extended_type[i]), + silc_buffer_len(attr->extended_type[i])), + SILC_STR_UI_INT(silc_buffer_len(attr->extended_data[i])), + SILC_STR_DATA(silc_buffer_data(attr->extended_data[i]), + silc_buffer_len(attr->extended_data[i])), + SILC_STR_END); silc_buffer_pull(buffer, ret); } } @@ -228,16 +229,16 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) if (!attr) return NULL; - if (silc_buffer_unformat(buffer, - SILC_STR_UI_INT(&attr->flags), + if (silc_buffer_unformat(buffer, + SILC_STR_UI_INT(&attr->flags), SILC_STR_END) < 0) goto out; silc_buffer_pull(buffer, 4); if (attr->flags & SILC_SFTP_ATTR_SIZE) { - if (silc_buffer_unformat(buffer, - SILC_STR_UI_INT64(&attr->size), + if (silc_buffer_unformat(buffer, + SILC_STR_UI_INT64(&attr->size), SILC_STR_END) < 0) goto out; @@ -245,9 +246,9 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) } if (attr->flags & SILC_SFTP_ATTR_UIDGID) { - if (silc_buffer_unformat(buffer, - SILC_STR_UI_INT(&attr->uid), - SILC_STR_UI_INT(&attr->gid), + if (silc_buffer_unformat(buffer, + SILC_STR_UI_INT(&attr->uid), + SILC_STR_UI_INT(&attr->gid), SILC_STR_END) < 0) goto out; @@ -255,8 +256,8 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) } if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) { - if (silc_buffer_unformat(buffer, - SILC_STR_UI_INT(&attr->permissions), + if (silc_buffer_unformat(buffer, + SILC_STR_UI_INT(&attr->permissions), SILC_STR_END) < 0) goto out; @@ -264,9 +265,9 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) } if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) { - if (silc_buffer_unformat(buffer, - SILC_STR_UI_INT(&attr->atime), - SILC_STR_UI_INT(&attr->mtime), + if (silc_buffer_unformat(buffer, + SILC_STR_UI_INT(&attr->atime), + SILC_STR_UI_INT(&attr->mtime), SILC_STR_END) < 0) goto out; @@ -276,16 +277,16 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) if (attr->flags & SILC_SFTP_ATTR_EXTENDED) { int i; - if (silc_buffer_unformat(buffer, - SILC_STR_UI_INT(&attr->extended_count), + if (silc_buffer_unformat(buffer, + SILC_STR_UI_INT(&attr->extended_count), SILC_STR_END) < 0) goto out; silc_buffer_pull(buffer, 4); - attr->extended_type = silc_calloc(attr->extended_count, + attr->extended_type = silc_calloc(attr->extended_count, sizeof(*attr->extended_type)); - attr->extended_data = silc_calloc(attr->extended_count, + attr->extended_data = silc_calloc(attr->extended_count, sizeof(*attr->extended_data)); if (!attr->extended_type || !attr->extended_data) return NULL; @@ -294,7 +295,7 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) unsigned char *tmp, *tmp2; SilcUInt32 tmp_len, tmp2_len; - if (silc_buffer_unformat(buffer, + if (silc_buffer_unformat(buffer, SILC_STR_UI32_NSTRING(&tmp, &tmp_len), SILC_STR_UI32_NSTRING(&tmp2, &tmp2_len), SILC_STR_END) < 0) @@ -340,7 +341,7 @@ void silc_sftp_name_add(SilcSFTPName name, const char *short_name, { name->filename = silc_realloc(name->filename, sizeof(*name->filename) * (name->count + 1)); - name->long_filename = silc_realloc(name->long_filename, + name->long_filename = silc_realloc(name->long_filename, sizeof(*name->long_filename) * (name->count + 1)); name->attrs = silc_realloc(name->attrs, sizeof(*name->attrs) * @@ -354,7 +355,7 @@ void silc_sftp_name_add(SilcSFTPName name, const char *short_name, name->count++; } -/* Encodes the SilcSFTPName to a buffer and returns the allocated buffer. +/* Encodes the SilcSFTPName to a buffer and returns the allocated buffer. The caller must free the buffer. */ SilcBuffer silc_sftp_name_encode(SilcSFTPName name) @@ -372,13 +373,13 @@ SilcBuffer silc_sftp_name_encode(SilcSFTPName name) attr_buf[i] = silc_sftp_attr_encode(name->attrs[i]); if (!attr_buf[i]) return NULL; - len += attr_buf[i]->len; + len += silc_buffer_len(attr_buf[i]); } buffer = silc_buffer_alloc(len); if (!buffer) return NULL; - silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer)); + silc_buffer_end(buffer); silc_buffer_format(buffer, SILC_STR_UI_INT(name->count), @@ -392,8 +393,8 @@ SilcBuffer silc_sftp_name_encode(SilcSFTPName name) SILC_STR_UI32_STRING(name->filename[i]), SILC_STR_UI_INT(strlen(name->long_filename[i])), SILC_STR_UI32_STRING(name->long_filename[i]), - SILC_STR_UI_XNSTRING(attr_buf[i]->data, - attr_buf[i]->len), + SILC_STR_DATA(silc_buffer_data(attr_buf[i]), + silc_buffer_len(attr_buf[i])), SILC_STR_END); silc_buffer_pull(buffer, len); @@ -429,7 +430,7 @@ SilcSFTPName silc_sftp_name_decode(SilcUInt32 count, SilcBuffer buffer) name->count = count; for (i = 0; i < count; i++) { - ret = + ret = silc_buffer_unformat(buffer, SILC_STR_UI32_STRING_ALLOC(&name->filename[i]), SILC_STR_UI32_STRING_ALLOC(&name->long_filename[i]), diff --git a/lib/silcsftp/silcsftp.h b/lib/silcsftp/silcsftp.h index b7036a95..87ee7039 100644 --- a/lib/silcsftp/silcsftp.h +++ b/lib/silcsftp/silcsftp.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2005 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 @@ -24,15 +24,20 @@ * * DESCRIPTION * - * SILC SFTP Interface is the implementation of the Secure File Transfer - * Protocol. The interface defines the SFTP client and the SFTP server. - * The SFTP is the mandatory file transfer protocol in the SILC protocol. - * The SFTP server implementation is filesystem independent and generic - * interface is defined to represent filesystem access. + * SILC SFTP Interface is the implementation of the Secure File Transfer + * Protocol (or SSH File Transfer Protocol). The interface defines the SFTP + * client and the SFTP server. The SFTP is the mandatory file transfer + * protocol in the SILC protocol, and when used in SILC the SFTP packets are + * encapsulated into SILC packets. The SFTP server implementation is + * filesystem independent and generic interface is defined to represent + * filesystem access. * - * The SilcSFTP context is the actual SFTP client or SFTP server, and - * each SFTP session (associated to a socket connection) must create - * own SFTP context. + * The SilcSFTP context is the actual SFTP client or SFTP server, and each + * SFTP session should create its own SFTP context. + * + * The SILC SFTP library is a generic SFTP implementation and not directly + * related to either SILC or SSH. It could be used for any general purpose + * SFTP application. * ***/ @@ -92,7 +97,7 @@ typedef enum { SILC_SFTP_STATUS_PERMISSION_DENIED = 3, /* No sufficient permissions */ SILC_SFTP_STATUS_FAILURE = 4, /* Operation failed */ SILC_SFTP_STATUS_BAD_MESSAGE = 5, /* Bad message received */ - SILC_SFTP_STATUS_NO_CONNECTION = 6, /* No connection to server */ + SILC_SFTP_STATUS_NO_CONNECTION = 6, /* No connection to remote */ SILC_SFTP_STATUS_CONNECTION_LOST = 7, /* Connection lost to server */ SILC_SFTP_STATUS_OP_UNSUPPORTED = 8, /* Operation unsupported */ SILC_SFTP_STATUS_INVALID_HANDLE = 9, /* Invalid file handle */ @@ -205,22 +210,6 @@ typedef struct { ***/ typedef struct SilcSFTPHandleStruct *SilcSFTPHandle; -/****f* silcsftp/SilcSFTPAPI/SilcSFTPSendPacketCallback - * - * SYNOPSIS - * - * typedef void (*SilcSFTPSendPacketCallback)(SilcBuffer packet, - * void *context); - * - * DESCRIPTION - * - * Packet sending callback. The caller of this interface will provide this - * function for the library. The libary will call this function everytime - * it needs to send a packet to the remote host. - * - ***/ -typedef void (*SilcSFTPSendPacketCallback)(SilcBuffer packet, void *context); - /****f* silcsftp/SilcSFTPAPI/SilcSFTPVersionCallback * * SYNOPSIS @@ -242,6 +231,25 @@ typedef void (*SilcSFTPVersionCallback)(SilcSFTP sftp, SilcSFTPVersion version, void *context); +/****f* silcsftp/SilcSFTPAPI/SilcSFTPErrorCallback + * + * SYNOPSIS + * + * typedef void (*SilcSFTPErrorCallback)(SilcSFTP sftp, + * SilcSFTPStatus status, + * void *context); + * + * DESCRIPTION + * + * Error callback is called if a connection error occurs during SFTP + * session. If the connection or stream is closed this callback is + * called. Other errors are delivered in other callbacks. + * + ***/ +typedef void (*SilcSFTPErrorCallback)(SilcSFTP sftp, + SilcSFTPStatus status, + void *context); + /****f* silcsftp/SilcSFTPAPI/SilcSFTPStatusCallback * * SYNOPSIS @@ -387,7 +395,9 @@ typedef void (*SilcSFTPExtendedCallback)(SilcSFTP sftp, * SYNOPSIS * * SilcSFTP silc_sftp_client_start(SilcStream stream, - * SilcSFTPVersionCallback callback, + * SilcSchedule schedule, + * SilcSFTPVersionCallback version_cb, + * SilcSFTPErrorCallback error_cb, * void *context); * * DESCRIPTION @@ -397,11 +407,13 @@ typedef void (*SilcSFTPExtendedCallback)(SilcSFTP sftp, * been started and server has returned the version of the protocol. The * SFTP client context is returned in the callback too. This returns the * allocated SFTP client context or NULL on error. The `stream' will be - * used to read from and write to the SFTP packets. + * used to read and write the SFTP packets. * ***/ SilcSFTP silc_sftp_client_start(SilcStream stream, - SilcSFTPVersionCallback callback, + SilcSchedule schedule, + SilcSFTPVersionCallback version_cb, + SilcSFTPErrorCallback error_cb, void *context); /****f* silcsftp/SilcSFTPAPI/silc_sftp_client_shutdown @@ -846,8 +858,10 @@ void silc_sftp_extended(SilcSFTP sftp, * * SYNOPSIS * - * SilcSFTP silc_sftp_server_start(SilcSFTPSendPacketCallback send_packet, - * void *send_context, + * SilcSFTP silc_sftp_server_start(SilcStream stream, + * SilcSchedule schedule, + * SilcSFTPErrorCallback error_cb, + * void *context, * SilcSFTPFilesystem fs); * * DESCRIPTION @@ -859,8 +873,10 @@ void silc_sftp_extended(SilcSFTP sftp, * should start its own server by calling this function. * ***/ -SilcSFTP silc_sftp_server_start(SilcSFTPSendPacketCallback send_packet, - void *send_context, +SilcSFTP silc_sftp_server_start(SilcStream stream, + SilcSchedule schedule, + SilcSFTPErrorCallback error_cb, + void *context, SilcSFTPFilesystem fs); /****f* silcsftp/SilcSFTPAPI/silc_sftp_server_shutdown diff --git a/lib/silcsftp/tests/Makefile.am b/lib/silcsftp/tests/Makefile.am index 4df05655..6dbf79a8 100644 --- a/lib/silcsftp/tests/Makefile.am +++ b/lib/silcsftp/tests/Makefile.am @@ -18,7 +18,7 @@ AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign -bin_PROGRAMS = sftp_server sftp_client +bin_PROGRAMS = sftp_client sftp_server sftp_server_SOURCES = sftp_server.c sftp_client_SOURCES = sftp_client.c diff --git a/lib/silcsftp/tests/sftp_client.c b/lib/silcsftp/tests/sftp_client.c index e181403d..71ec8982 100644 --- a/lib/silcsftp/tests/sftp_client.c +++ b/lib/silcsftp/tests/sftp_client.c @@ -1,10 +1,10 @@ /* - sftp_client.c + sftp_client.c Author: Pekka Riikonen - 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 @@ -34,7 +34,7 @@ typedef struct { SilcSchedule schedule; - SilcSocketConnection sock; + SilcStream stream; SilcSFTP sftp; } *Client; @@ -55,81 +55,6 @@ static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status, void *context); static void end_test(void); -static void send_packet(SilcBuffer packet, void *context) -{ - Client client = (Client)context; - SilcSocketConnection sock = client->sock; - SilcPacketContext packetdata; - const SilcBufferStruct p; - int ret; - - memset(&packetdata, 0, sizeof(packetdata)); - packetdata.type = SILC_PACKET_FTP; - packetdata.truelen = packet->len + SILC_PACKET_HEADER_LEN; - SILC_PACKET_PADLEN(packetdata.truelen, 0, packetdata.padlen); - silc_packet_assemble(&packetdata, NULL, NULL, NULL, sock, - packet->data, packet->len, (const SilcBuffer)&p); - ret = silc_packet_send(sock, TRUE); - if (ret != -2) - return; - - silc_schedule_set_listen_fd(client->schedule, sock->sock, - (SILC_TASK_READ | SILC_TASK_WRITE), FALSE); - SILC_SET_OUTBUF_PENDING(sock); -} - -static bool packet_parse(SilcPacketParserContext *parser, void *context) -{ - Client client = (Client)parser->context; - SilcSocketConnection sock = parser->sock; - SilcPacketContext *packet = parser->packet; - int ret; - - ret = silc_packet_parse(packet, NULL); - assert(packet->type == SILC_PACKET_FTP); - - silc_sftp_client_receive_process(client->sftp, sock, packet); - - return TRUE; -} - -SILC_TASK_CALLBACK(packet_process) -{ - 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; - - silc_schedule_set_listen_fd(client->schedule, fd, SILC_TASK_READ, FALSE); - SILC_UNSET_OUTBUF_PENDING(sock); - silc_buffer_clear(sock->outbuf); - 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_packet_receive_process(sock, FALSE, NULL, NULL, 0, - packet_parse, client); - } -} - static void sftp_status(SilcSFTP sftp, SilcSFTPStatus status, const char *message, const char *lang_tag, void *context) @@ -150,9 +75,8 @@ static void sftp_attr(SilcSFTP sftp, SilcSFTPStatus status, const SilcSFTPAttributes attrs, void *context) { SilcSFTPHandle handle = (SilcSFTPHandle)context; - int debug = silc_debug; int i; - + fprintf(stderr, "Status %d\n", status); if (status != SILC_SFTP_STATUS_OK) { SILC_LOG_DEBUG(("Error status")); @@ -160,9 +84,7 @@ static void sftp_attr(SilcSFTP sftp, SilcSFTPStatus status, end_test(); return; } - - if (!debug) - silc_debug = 1; + SILC_LOG_DEBUG(("Attr.flags: %d", attrs->flags)); SILC_LOG_DEBUG(("Attr.size: %lu", attrs->size)); @@ -175,21 +97,19 @@ static void sftp_attr(SilcSFTP sftp, SilcSFTPStatus status, for (i = 0; i < attrs->extended_count; i++) { SILC_LOG_HEXDUMP(("Attr.extended_type[i]:", i), attrs->extended_type[i]->data, - attrs->extended_type[i]->len); + silc_buffer_len(attrs->extended_type[i])); SILC_LOG_HEXDUMP(("Attr.extended_data[i]:", i), attrs->extended_data[i]->data, - attrs->extended_data[i]->len); + silc_buffer_len(attrs->extended_data[i])); } - - silc_debug = debug; if (!file) { - fprintf(stderr, "Closing file\n"); + fprintf(stderr, "Closing file\n"); silc_sftp_close(sftp, handle, sftp_status, context); return; } - - fprintf(stderr, "LStatting file %s\n", file); + + fprintf(stderr, "LStatting file %s\n", file); silc_sftp_lstat(sftp, file, sftp_attr, context); file = NULL; } @@ -199,7 +119,6 @@ static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status, void *context) { SilcSFTPHandle handle = (SilcSFTPHandle)context; - int debug = silc_debug; if (status != SILC_SFTP_STATUS_OK) { SilcSFTPAttributesStruct attrs; @@ -212,13 +131,13 @@ static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status, end_test(); return; } - + if (!strcmp(file, "/sftp/sftp_server.c")) { - fprintf(stderr, "FStatting file handle %s\n", file); + fprintf(stderr, "FStatting file handle %s\n", file); silc_sftp_fstat(sftp, handle, sftp_attr, context); return; } - + /* Open another file */ opendir = FALSE; memset(&attrs, 0, sizeof(attrs)); @@ -230,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; @@ -257,7 +173,7 @@ static void sftp_name(SilcSFTP sftp, SilcSFTPStatus status, end_test(); return; } - + fprintf(stderr, "Directory: %s\n", dir); for (i = 0; i < name->count; i++) { fprintf(stderr, "%s\n", name->long_filename[i]); @@ -300,7 +216,7 @@ static void sftp_handle(SilcSFTP sftp, SilcSFTPStatus status, end_test(); return; } - + if (opendir) { fprintf(stderr, "Reading %s\n", dir); /* Readdir */ @@ -335,35 +251,58 @@ 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; - silc_debug_hexdump = 1; - silc_log_set_debug_string("*sftp*"); + 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, NULL); + client->schedule = silc_schedule_init(0, 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(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; diff --git a/lib/silcsftp/tests/sftp_server.c b/lib/silcsftp/tests/sftp_server.c index 9510e53e..294c2933 100644 --- a/lib/silcsftp/tests/sftp_server.c +++ b/lib/silcsftp/tests/sftp_server.c @@ -1,10 +1,10 @@ /* - sprp_server.c + sprp_server.c Author: Pekka Riikonen - 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 @@ -20,141 +20,65 @@ #include "silc.h" #include "silcsftp.h" -typedef struct { - SilcSocketConnection sock; - void *server; +typedef struct ServerSessionStruct { + SilcStream stream; + SilcSFTP sftp; } *ServerSession; typedef struct { SilcSchedule schedule; - int sock; + SilcNetListener listener; SilcSFTPFilesystem fs; - ServerSession sessions[100]; - SilcSFTP sftp[100]; } *Server; -static void send_packet(SilcBuffer packet, void *context) +static void error_cb(SilcSFTP sftp, SilcSFTPStatus status, void *context) { ServerSession session = context; - Server server = session->server; - SilcPacketContext packetdata; - const SilcBufferStruct p; - int ret; - - memset(&packetdata, 0, sizeof(packetdata)); - packetdata.type = SILC_PACKET_FTP; - packetdata.truelen = packet->len + SILC_PACKET_HEADER_LEN; - SILC_PACKET_PADLEN(packetdata.truelen, 0, packetdata.padlen); - silc_packet_assemble(&packetdata, NULL, NULL, NULL, session->sock, - packet->data, packet->len, (const SilcBuffer)&p); - ret = silc_packet_send(session->sock, TRUE); - if (ret != -2) - return; - silc_schedule_set_listen_fd(server->schedule, session->sock->sock, - (SILC_TASK_READ | SILC_TASK_WRITE), FALSE); - SILC_SET_OUTBUF_PENDING(session->sock); -} - -static bool packet_parse(SilcPacketParserContext *parser, void *context) -{ - Server server = (Server)parser->context; - SilcSocketConnection sock = parser->sock; - SilcPacketContext *packet = parser->packet; - int ret; - - ret = silc_packet_parse(packet, NULL); - assert(packet->type == SILC_PACKET_FTP); - - silc_sftp_server_receive_process(server->sftp[sock->sock], sock, packet); + if (status == SILC_SFTP_STATUS_EOF) { + SILC_LOG_DEBUG(("Eof")); + silc_stream_destroy(session->stream); + silc_free(session); + } - return TRUE; + SILC_LOG_DEBUG(("Error %d", status)); } -SILC_TASK_CALLBACK(packet_process) +static void net_callback(SilcNetStatus status, SilcStream stream, + void *context) { Server server = context; - ServerSession session = server->sessions[fd]; - SilcSocketConnection sock; - int ret; - - if (!session) - return; - sock = session->sock; - - if (type == SILC_TASK_WRITE) { - if (sock->outbuf->data - sock->outbuf->head) - silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head); + ServerSession session; - ret = silc_packet_send(sock, TRUE); - if (ret < 0) - return; + SILC_LOG_DEBUG(("New connection")); - silc_schedule_set_listen_fd(server->schedule, fd, SILC_TASK_READ, FALSE); - SILC_UNSET_OUTBUF_PENDING(sock); - silc_buffer_clear(sock->outbuf); + session = silc_calloc(1, sizeof(*session)); + if (!session) return; - } + session->stream = stream; + session->sftp = silc_sftp_server_start(stream, server->schedule, error_cb, + session, server->fs); - if (type == SILC_TASK_READ) { - ret = silc_packet_receive(sock); - if (ret < 0) - return; - - if (ret == 0) { - silc_net_close_connection(sock->sock); - silc_schedule_unset_listen_fd(server->schedule, sock->sock); - silc_free(server->sessions[sock->sock]); - server->sessions[sock->sock] = NULL; - silc_socket_free(sock); - return; - } - - silc_packet_receive_process(sock, FALSE, NULL, NULL, 0, packet_parse, - server); - } -} - -SILC_TASK_CALLBACK(accept_connection) -{ - Server server = (Server)context; - SilcSocketConnection sc; - int sock; - - sock = silc_net_accept_connection(server->sock); - if (sock < 0) - exit(1); - - silc_net_set_socket_nonblock(sock); - silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1); - - silc_socket_alloc(sock, 0, NULL, &sc); - server->sessions[sock] = silc_calloc(1, sizeof(server->sessions[0])); - server->sessions[sock]->sock = sc; - server->sessions[sock]->server = server; - server->sftp[sock] = - silc_sftp_server_start(send_packet, server->sessions[sock], - server->fs); - silc_schedule_task_add(server->schedule, sock, packet_process, - server, 0, 0, SILC_TASK_GENERIC, - SILC_TASK_PRI_NORMAL); } int main() { Server server = silc_calloc(1, sizeof(*server)); void *dir; + const char *ip = "127.0.0.1"; - silc_debug = 1; - silc_debug_hexdump = 1; + silc_log_debug(TRUE); + silc_log_debug_hexdump(TRUE); silc_log_set_debug_string("*sftp*"); - - server->schedule = silc_schedule_init(100, NULL); + + server->schedule = silc_schedule_init(0, NULL); if (!server->schedule) return -1; - server->sock = silc_net_create_server(5000, NULL); - if (server->sock < 0) + server->listener = silc_net_tcp_create_listener(&ip, 1, 5000, FALSE, + FALSE, server->schedule, + net_callback, server); + if (!server->listener) return -1; /* Make test filesystem hierarchy */ @@ -182,9 +106,6 @@ int main() silc_sftp_fs_memory_add_file(server->fs, NULL, SILC_SFTP_FS_PERM_EXEC, "testi", "file://sftp_client.c"); - silc_schedule_task_add(server->schedule, server->sock, - accept_connection, server, 0, 0, - SILC_TASK_FD, SILC_TASK_PRI_NORMAL); silc_schedule(server->schedule); return 0; -- 2.24.0