updates.
[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 #include "silcsftp_fs.h"
23
24 typedef struct {
25   SilcSchedule schedule;
26   int sock;
27   void *fs;
28   SilcSocketConnection socks[100];
29   SilcSFTP sftp[100];
30 } *Server;
31
32 static void send_packet(SilcSocketConnection sock,
33                         SilcBuffer packet, void *context)
34 {
35   Server server = (Server)context;
36   SilcPacketContext packetdata;
37   int ret;
38
39   memset(&packetdata, 0, sizeof(packetdata));
40   packetdata.type = SILC_PACKET_FTP;
41   packetdata.truelen = packet->len + SILC_PACKET_HEADER_LEN;
42   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
43   silc_packet_send_prepare(sock,
44                            SILC_PACKET_HEADER_LEN,
45                            packetdata.padlen,
46                            packet->len);
47   packetdata.buffer = sock->outbuf;
48   silc_buffer_put(sock->outbuf, packet->data, packet->len);
49   silc_packet_assemble(&packetdata);
50   ret = silc_packet_send(sock, TRUE);
51   if (ret != -2)
52     return;
53
54   silc_schedule_set_listen_fd(server->schedule, sock->sock, 
55                               (SILC_TASK_READ | SILC_TASK_WRITE));
56   SILC_SET_OUTBUF_PENDING(sock);
57 }
58
59 static void packet_parse(SilcPacketParserContext *parser)
60 {
61   Server server = (Server)parser->context;
62   SilcSocketConnection sock = parser->sock;
63   SilcPacketContext *packet = parser->packet;
64   int ret;
65   
66   ret = silc_packet_parse(packet);
67   assert(packet->type == SILC_PACKET_FTP);
68
69   silc_sftp_server_receive_process(server->sftp[sock->sock], sock, packet);
70 }
71
72 SILC_TASK_CALLBACK(packet_process)
73 {
74   Server server = (Server)context;
75   SilcSocketConnection sock = server->socks[fd];
76   int ret;
77
78   if (!sock)
79     return;
80
81   if (type == SILC_TASK_WRITE) {
82     if (sock->outbuf->data - sock->outbuf->head)
83       silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
84
85     ret = silc_packet_send(sock, TRUE);
86     if (ret < 0)
87       return;
88
89     silc_schedule_set_listen_fd(server->schedule, fd, SILC_TASK_READ);
90     SILC_UNSET_OUTBUF_PENDING(sock);
91     silc_buffer_clear(sock->outbuf);
92     return;
93   }
94
95   if (type == SILC_TASK_READ) {
96     ret = silc_packet_receive(sock);
97     if (ret < 0)
98       return;
99
100     if (ret == 0) {
101       silc_net_close_connection(sock->sock);
102       silc_schedule_unset_listen_fd(server->schedule, sock->sock);
103       server->socks[sock->sock] = NULL;
104       silc_socket_free(sock);
105       return;
106     }
107
108     silc_packet_receive_process(sock, NULL, NULL, packet_parse, server);
109   }
110 }
111
112 SILC_TASK_CALLBACK(accept_connection)
113 {
114   Server server = (Server)context;
115   SilcSocketConnection sc;
116   int sock;
117
118   sock = silc_net_accept_connection(server->sock);
119   if (sock < 0)
120     exit(1);
121
122   silc_net_set_socket_nonblock(sock);
123   silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
124
125   silc_socket_alloc(sock, 0, NULL, &sc);
126   server->socks[sock] = sc;
127   server->sftp[sock] = 
128     silc_sftp_server_start(sc, send_packet, server,
129                            (SilcSFTPFilesystem)&silc_sftp_fs_memory, 
130                            server->fs);
131   silc_schedule_task_add(server->schedule, sock, packet_process,
132                          server, 0, 0, SILC_TASK_GENERIC,
133                          SILC_TASK_PRI_NORMAL);
134 }
135
136 int main()
137 {
138   Server server = silc_calloc(1, sizeof(*server));
139   void *dir;
140
141   silc_debug = 1;
142
143   server->schedule = silc_schedule_init(100);
144   if (!server->schedule)
145     return -1;
146
147   server->sock = silc_net_create_server(5000, NULL);
148   if (server->sock < 0)
149     return -1;
150
151   /* Make test filesystem hierarchy */
152
153   server->fs = silc_sftp_fs_memory_alloc((SILC_SFTP_FS_PERM_READ |
154                                           SILC_SFTP_FS_PERM_WRITE));
155   dir =
156     silc_sftp_fs_memory_add_dir(server->fs, NULL, (SILC_SFTP_FS_PERM_READ |
157                                                    SILC_SFTP_FS_PERM_WRITE |
158                                                    SILC_SFTP_FS_PERM_EXEC),
159                                 "sftp");
160   silc_sftp_fs_memory_add_file(server->fs, NULL, SILC_SFTP_FS_PERM_READ,
161                                "passwd", "file:///etc/passwd");
162   silc_sftp_fs_memory_add_file(server->fs, NULL, (SILC_SFTP_FS_PERM_READ |
163                                                   SILC_SFTP_FS_PERM_WRITE),
164                                "writeme", "file://./writeme-test");
165   silc_sftp_fs_memory_add_file(server->fs, dir, SILC_SFTP_FS_PERM_READ,
166                                "shadow", "file:///etc/shadow");
167   silc_sftp_fs_memory_add_file(server->fs, dir, SILC_SFTP_FS_PERM_READ,
168                                "sftp_server.c", "file://sftp_server.c");
169   silc_sftp_fs_memory_add_dir(server->fs, dir, (SILC_SFTP_FS_PERM_READ |
170                                                 SILC_SFTP_FS_PERM_WRITE |
171                                                 SILC_SFTP_FS_PERM_EXEC),
172                                "Mail");
173   silc_sftp_fs_memory_add_file(server->fs, NULL, SILC_SFTP_FS_PERM_EXEC,
174                                "testi", "file://sftp_client.c");
175
176   silc_schedule_task_add(server->schedule, server->sock, 
177                          accept_connection, server, 0, 0,
178                          SILC_TASK_FD, SILC_TASK_PRI_NORMAL);
179   silc_schedule(server->schedule);
180
181   return 0;
182 }