61e451cccafaf45e8f5079637234528bebe23c76
[silc.git] / lib / silcsftp / tests / sftp_server.c
1 /*
2
3   sprp_server.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silcincludes.h"
21 #include "silcsftp.h"
22
23 typedef struct {
24   SilcSchedule schedule;
25   int sock;
26   SilcSFTPFilesystem fs;
27   SilcSocketConnection socks[100];
28   SilcSFTP sftp[100];
29 } *Server;
30
31 static void send_packet(SilcSocketConnection sock,
32                         SilcBuffer packet, void *context)
33 {
34   Server server = (Server)context;
35   SilcPacketContext packetdata;
36   int ret;
37
38   memset(&packetdata, 0, sizeof(packetdata));
39   packetdata.type = SILC_PACKET_FTP;
40   packetdata.truelen = packet->len + SILC_PACKET_HEADER_LEN;
41   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, 0);
42   silc_packet_send_prepare(sock,
43                            SILC_PACKET_HEADER_LEN,
44                            packetdata.padlen,
45                            packet->len);
46   packetdata.buffer = sock->outbuf;
47   silc_buffer_put(sock->outbuf, packet->data, packet->len);
48   silc_packet_assemble(&packetdata, NULL);
49   ret = silc_packet_send(sock, TRUE);
50   if (ret != -2)
51     return;
52
53   silc_schedule_set_listen_fd(server->schedule, sock->sock, 
54                               (SILC_TASK_READ | SILC_TASK_WRITE), FALSE);
55   SILC_SET_OUTBUF_PENDING(sock);
56 }
57
58 static bool packet_parse(SilcPacketParserContext *parser, void *context)
59 {
60   Server server = (Server)parser->context;
61   SilcSocketConnection sock = parser->sock;
62   SilcPacketContext *packet = parser->packet;
63   int ret;
64   
65   ret = silc_packet_parse(packet, NULL);
66   assert(packet->type == SILC_PACKET_FTP);
67
68   silc_sftp_server_receive_process(server->sftp[sock->sock], sock, packet);
69
70   return TRUE;
71 }
72
73 SILC_TASK_CALLBACK(packet_process)
74 {
75   Server server = (Server)context;
76   SilcSocketConnection sock = server->socks[fd];
77   int ret;
78
79   if (!sock)
80     return;
81
82   if (type == SILC_TASK_WRITE) {
83     if (sock->outbuf->data - sock->outbuf->head)
84       silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
85
86     ret = silc_packet_send(sock, TRUE);
87     if (ret < 0)
88       return;
89
90     silc_schedule_set_listen_fd(server->schedule, fd, SILC_TASK_READ, FALSE);
91     SILC_UNSET_OUTBUF_PENDING(sock);
92     silc_buffer_clear(sock->outbuf);
93     return;
94   }
95
96   if (type == SILC_TASK_READ) {
97     ret = silc_packet_receive(sock);
98     if (ret < 0)
99       return;
100
101     if (ret == 0) {
102       silc_net_close_connection(sock->sock);
103       silc_schedule_unset_listen_fd(server->schedule, sock->sock);
104       server->socks[sock->sock] = NULL;
105       silc_socket_free(sock);
106       return;
107     }
108
109     silc_packet_receive_process(sock, FALSE, NULL, NULL, 0, packet_parse, 
110                                 server);
111   }
112 }
113
114 SILC_TASK_CALLBACK(accept_connection)
115 {
116   Server server = (Server)context;
117   SilcSocketConnection sc;
118   int sock;
119
120   sock = silc_net_accept_connection(server->sock);
121   if (sock < 0)
122     exit(1);
123
124   silc_net_set_socket_nonblock(sock);
125   silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
126
127   silc_socket_alloc(sock, 0, NULL, &sc);
128   server->socks[sock] = sc;
129   server->sftp[sock] = 
130     silc_sftp_server_start(sc, send_packet, server,
131                            server->fs);
132   silc_schedule_task_add(server->schedule, sock, packet_process,
133                          server, 0, 0, SILC_TASK_GENERIC,
134                          SILC_TASK_PRI_NORMAL);
135 }
136
137 int main()
138 {
139   Server server = silc_calloc(1, sizeof(*server));
140   void *dir;
141
142   silc_debug = 1;
143
144   server->schedule = silc_schedule_init(100);
145   if (!server->schedule)
146     return -1;
147
148   server->sock = silc_net_create_server(5000, NULL);
149   if (server->sock < 0)
150     return -1;
151
152   /* Make test filesystem hierarchy */
153
154   server->fs = silc_sftp_fs_memory_alloc((SILC_SFTP_FS_PERM_READ |
155                                           SILC_SFTP_FS_PERM_WRITE));
156   dir =
157     silc_sftp_fs_memory_add_dir(server->fs, NULL, (SILC_SFTP_FS_PERM_READ |
158                                                    SILC_SFTP_FS_PERM_WRITE |
159                                                    SILC_SFTP_FS_PERM_EXEC),
160                                 "sftp");
161   silc_sftp_fs_memory_add_file(server->fs, NULL, SILC_SFTP_FS_PERM_READ,
162                                "passwd", "file:///etc/passwd");
163   silc_sftp_fs_memory_add_file(server->fs, NULL, (SILC_SFTP_FS_PERM_READ |
164                                                   SILC_SFTP_FS_PERM_WRITE),
165                                "writeme", "file://./writeme-test");
166   silc_sftp_fs_memory_add_file(server->fs, dir, SILC_SFTP_FS_PERM_READ,
167                                "shadow", "file:///etc/shadow");
168   silc_sftp_fs_memory_add_file(server->fs, dir, SILC_SFTP_FS_PERM_READ,
169                                "sftp_server.c", "file://sftp_server.c");
170   silc_sftp_fs_memory_add_dir(server->fs, dir, (SILC_SFTP_FS_PERM_READ |
171                                                 SILC_SFTP_FS_PERM_WRITE |
172                                                 SILC_SFTP_FS_PERM_EXEC),
173                                "Mail");
174   silc_sftp_fs_memory_add_file(server->fs, NULL, SILC_SFTP_FS_PERM_EXEC,
175                                "testi", "file://sftp_client.c");
176
177   silc_schedule_task_add(server->schedule, server->sock, 
178                          accept_connection, server, 0, 0,
179                          SILC_TASK_FD, SILC_TASK_PRI_NORMAL);
180   silc_schedule(server->schedule);
181
182   return 0;
183 }