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
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);
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);
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));
55   SILC_SET_OUTBUF_PENDING(sock);
56 }
57
58 static void packet_parse(SilcPacketParserContext *parser)
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);
66   assert(packet->type == SILC_PACKET_FTP);
67
68   silc_sftp_server_receive_process(server->sftp[sock->sock], sock, packet);
69 }
70
71 SILC_TASK_CALLBACK(packet_process)
72 {
73   Server server = (Server)context;
74   SilcSocketConnection sock = server->socks[fd];
75   int ret;
76
77   if (!sock)
78     return;
79
80   if (type == SILC_TASK_WRITE) {
81     if (sock->outbuf->data - sock->outbuf->head)
82       silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
83
84     ret = silc_packet_send(sock, TRUE);
85     if (ret < 0)
86       return;
87
88     silc_schedule_set_listen_fd(server->schedule, fd, SILC_TASK_READ);
89     SILC_UNSET_OUTBUF_PENDING(sock);
90     silc_buffer_clear(sock->outbuf);
91     return;
92   }
93
94   if (type == SILC_TASK_READ) {
95     ret = silc_packet_receive(sock);
96     if (ret < 0)
97       return;
98
99     if (ret == 0) {
100       silc_net_close_connection(sock->sock);
101       silc_schedule_unset_listen_fd(server->schedule, sock->sock);
102       server->socks[sock->sock] = NULL;
103       silc_socket_free(sock);
104       return;
105     }
106
107     silc_packet_receive_process(sock, NULL, NULL, packet_parse, server);
108   }
109 }
110
111 SILC_TASK_CALLBACK(accept_connection)
112 {
113   Server server = (Server)context;
114   SilcSocketConnection sc;
115   int sock;
116
117   sock = silc_net_accept_connection(server->sock);
118   if (sock < 0)
119     exit(1);
120
121   silc_net_set_socket_nonblock(sock);
122   silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
123
124   silc_socket_alloc(sock, 0, NULL, &sc);
125   server->socks[sock] = sc;
126   server->sftp[sock] = 
127     silc_sftp_server_start(sc, send_packet, server,
128                            server->fs);
129   silc_schedule_task_add(server->schedule, sock, packet_process,
130                          server, 0, 0, SILC_TASK_GENERIC,
131                          SILC_TASK_PRI_NORMAL);
132 }
133
134 int main()
135 {
136   Server server = silc_calloc(1, sizeof(*server));
137   void *dir;
138
139   silc_debug = 1;
140
141   server->schedule = silc_schedule_init(100);
142   if (!server->schedule)
143     return -1;
144
145   server->sock = silc_net_create_server(5000, NULL);
146   if (server->sock < 0)
147     return -1;
148
149   /* Make test filesystem hierarchy */
150
151   server->fs = silc_sftp_fs_memory_alloc((SILC_SFTP_FS_PERM_READ |
152                                           SILC_SFTP_FS_PERM_WRITE));
153   dir =
154     silc_sftp_fs_memory_add_dir(server->fs, NULL, (SILC_SFTP_FS_PERM_READ |
155                                                    SILC_SFTP_FS_PERM_WRITE |
156                                                    SILC_SFTP_FS_PERM_EXEC),
157                                 "sftp");
158   silc_sftp_fs_memory_add_file(server->fs, NULL, SILC_SFTP_FS_PERM_READ,
159                                "passwd", "file:///etc/passwd");
160   silc_sftp_fs_memory_add_file(server->fs, NULL, (SILC_SFTP_FS_PERM_READ |
161                                                   SILC_SFTP_FS_PERM_WRITE),
162                                "writeme", "file://./writeme-test");
163   silc_sftp_fs_memory_add_file(server->fs, dir, SILC_SFTP_FS_PERM_READ,
164                                "shadow", "file:///etc/shadow");
165   silc_sftp_fs_memory_add_file(server->fs, dir, SILC_SFTP_FS_PERM_READ,
166                                "sftp_server.c", "file://sftp_server.c");
167   silc_sftp_fs_memory_add_dir(server->fs, dir, (SILC_SFTP_FS_PERM_READ |
168                                                 SILC_SFTP_FS_PERM_WRITE |
169                                                 SILC_SFTP_FS_PERM_EXEC),
170                                "Mail");
171   silc_sftp_fs_memory_add_file(server->fs, NULL, SILC_SFTP_FS_PERM_EXEC,
172                                "testi", "file://sftp_client.c");
173
174   silc_schedule_task_add(server->schedule, server->sock, 
175                          accept_connection, server, 0, 0,
176                          SILC_TASK_FD, SILC_TASK_PRI_NORMAL);
177   silc_schedule(server->schedule);
178
179   return 0;
180 }