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