--- /dev/null
+/*
+
+ sprp_server.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2001 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcsftp.h"
+#include "silcsftp_fs.h"
+
+typedef struct {
+ SilcSchedule schedule;
+ int sock;
+ void *fs;
+ SilcSocketConnection socks[100];
+ SilcSFTP sftp[100];
+} *Server;
+
+static void send_packet(SilcSocketConnection sock,
+ SilcBuffer packet, void *context)
+{
+ Server server = (Server)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)
+ return;
+
+ silc_schedule_set_listen_fd(server->schedule, sock->sock,
+ (SILC_TASK_READ | SILC_TASK_WRITE));
+ SILC_SET_OUTBUF_PENDING(sock);
+}
+
+static void packet_parse(SilcPacketParserContext *parser)
+{
+ Server server = (Server)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_server_receive_process(server->sftp[sock->sock], sock, packet);
+}
+
+SILC_TASK_CALLBACK(packet_process)
+{
+ Server server = (Server)context;
+ SilcSocketConnection sock = server->socks[fd];
+ int ret;
+
+ if (!sock)
+ return;
+
+ 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(server->schedule, fd, SILC_TASK_READ);
+ 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_schedule_unset_listen_fd(server->schedule, sock->sock);
+ server->socks[sock->sock] = NULL;
+ silc_socket_free(sock);
+ return;
+ }
+
+ silc_packet_receive_process(sock, NULL, NULL, 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->socks[sock] = sc;
+ server->sftp[sock] =
+ silc_sftp_server_start(sc, send_packet, server,
+ (SilcSFTPFilesystem)&silc_sftp_fs_memory,
+ 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;
+
+ silc_debug = 1;
+
+ server->schedule = silc_schedule_init(100);
+ if (!server->schedule)
+ return -1;
+
+ server->sock = silc_net_create_server(5000, NULL);
+ if (server->sock < 0)
+ return -1;
+
+ /* Make test filesystem hierarchy */
+
+ server->fs = silc_sftp_fs_memory_alloc((SILC_SFTP_FS_PERM_READ |
+ SILC_SFTP_FS_PERM_WRITE));
+ dir =
+ silc_sftp_fs_memory_add_dir(server->fs, NULL, (SILC_SFTP_FS_PERM_READ |
+ SILC_SFTP_FS_PERM_WRITE |
+ SILC_SFTP_FS_PERM_EXEC),
+ "sftp");
+ silc_sftp_fs_memory_add_file(server->fs, NULL, SILC_SFTP_FS_PERM_READ,
+ "passwd", "file:///etc/passwd");
+ silc_sftp_fs_memory_add_file(server->fs, NULL, (SILC_SFTP_FS_PERM_READ |
+ SILC_SFTP_FS_PERM_WRITE),
+ "writeme", "file://./writeme-test");
+ silc_sftp_fs_memory_add_file(server->fs, dir, SILC_SFTP_FS_PERM_READ,
+ "shadow", "file:///etc/shadow");
+ silc_sftp_fs_memory_add_file(server->fs, dir, SILC_SFTP_FS_PERM_READ,
+ "sftp_server.c", "file://sftp_server.c");
+ silc_sftp_fs_memory_add_dir(server->fs, dir, (SILC_SFTP_FS_PERM_READ |
+ SILC_SFTP_FS_PERM_WRITE |
+ SILC_SFTP_FS_PERM_EXEC),
+ "Mail");
+ 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;
+}