Integer type name change.
[silc.git] / lib / silcsftp / tests / sftp_client.c
1 /*
2
3   sftp_client.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   SilcSocketConnection sock;
26   SilcSFTP sftp;
27 } *Client;
28
29 Client gclient;
30
31 char *dir;
32 char *file;
33 bool opendir;
34 SilcUInt64 offset;
35
36 static void sftp_name(SilcSFTP sftp, SilcSFTPStatus status,
37                       const SilcSFTPName name, void *context);
38 static void sftp_handle(SilcSFTP sftp, SilcSFTPStatus status,
39                         SilcSFTPHandle handle, void *context);
40 static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status,
41                       const unsigned char *data, SilcUInt32 data_len,
42                       void *context);
43
44 static void send_packet(SilcSocketConnection sock,
45                         SilcBuffer packet, void *context)
46 {
47   Client client = (Client)context;
48   SilcPacketContext packetdata;
49   int ret;
50
51   memset(&packetdata, 0, sizeof(packetdata));
52   packetdata.type = SILC_PACKET_FTP;
53   packetdata.truelen = packet->len + SILC_PACKET_HEADER_LEN;
54   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, 0);
55   silc_packet_send_prepare(sock,
56                            SILC_PACKET_HEADER_LEN,
57                            packetdata.padlen,
58                            packet->len);
59   packetdata.buffer = sock->outbuf;
60   silc_buffer_put(sock->outbuf, packet->data, packet->len);
61   silc_packet_assemble(&packetdata, NULL);
62   ret = silc_packet_send(sock, TRUE);
63   if (ret != -2)
64     return;
65
66   silc_schedule_set_listen_fd(client->schedule, sock->sock, 
67                               (SILC_TASK_READ | SILC_TASK_WRITE));
68   SILC_SET_OUTBUF_PENDING(sock);
69 }
70
71 static bool packet_parse(SilcPacketParserContext *parser, void *context)
72 {
73   Client client = (Client)parser->context;
74   SilcSocketConnection sock = parser->sock;
75   SilcPacketContext *packet = parser->packet;
76   int ret;
77   
78   ret = silc_packet_parse(packet, NULL);
79   assert(packet->type == SILC_PACKET_FTP);
80
81   silc_sftp_client_receive_process(client->sftp, sock, packet);
82
83   return TRUE;
84 }
85
86 SILC_TASK_CALLBACK(packet_process)
87 {
88   Client client = (Client)context;
89   SilcSocketConnection sock = client->sock;
90   int ret;
91
92   if (type == SILC_TASK_WRITE) {
93     if (sock->outbuf->data - sock->outbuf->head)
94      silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
95
96     ret = silc_packet_send(sock, TRUE);
97     if (ret < 0)
98       return;
99
100     silc_schedule_set_listen_fd(client->schedule, fd, SILC_TASK_READ);
101     SILC_UNSET_OUTBUF_PENDING(sock);
102     silc_buffer_clear(sock->outbuf);
103     return;
104   }
105
106   if (type == SILC_TASK_READ) {
107     ret = silc_packet_receive(sock);
108     if (ret < 0)
109       return;
110
111     if (ret == 0) {
112       silc_net_close_connection(sock->sock);
113       silc_socket_free(sock);
114       exit(0);
115     }
116
117     silc_packet_receive_process(sock, FALSE, NULL, NULL, 0, 
118                                 packet_parse, client);
119   }
120 }
121
122 static void sftp_data(SilcSFTP sftp, SilcSFTPStatus status,
123                       const unsigned char *data, SilcUInt32 data_len,
124                       void *context)
125 {
126   SilcSFTPHandle handle = (SilcSFTPHandle)context;
127   int debug = silc_debug;
128
129   if (status != SILC_SFTP_STATUS_OK) {
130     SilcSFTPAttributesStruct attrs;
131
132     fprintf(stderr, "Status %d\n", status);
133
134     if (!strcmp(file, "/sftp/sftp_server.c"))
135       return;
136
137     /* Open another file */
138     opendir = FALSE;
139     memset(&attrs, 0, sizeof(attrs));
140     file = "/sftp/sftp_server.c";
141     fprintf(stderr, "Opening file %s\n", file);
142     offset = 0;
143     silc_sftp_open(sftp, file, SILC_SFTP_FXF_READ,
144                    &attrs, sftp_handle, gclient);
145     return;
146   }
147
148   if (!debug)
149     silc_debug = 1;
150   SILC_LOG_HEXDUMP(("data"), (unsigned char *)data, data_len);
151   silc_debug = debug;
152
153   offset += data_len;
154
155   /* Attempt to read more */
156   fprintf(stderr, "Reading more of file %s\n", file);
157   silc_sftp_read(sftp, handle, offset, 2048, sftp_data, handle);
158 }
159
160 static void sftp_name(SilcSFTP sftp, SilcSFTPStatus status,
161                       const SilcSFTPName name, void *context)
162 {
163   Client client = (Client)context;
164   int i;
165
166   SILC_LOG_DEBUG(("Name"));
167   fprintf(stderr, "Status %d\n", status);
168
169   fprintf(stderr, "Directory: %s\n", dir);
170   for (i = 0; i < name->count; i++) {
171     fprintf(stderr, "%s\n", name->long_filename[i]);
172   }
173
174   if (!strcmp(dir, "sftp")) {
175     SilcSFTPAttributesStruct attrs;
176
177     /* open */
178     opendir = FALSE;
179     memset(&attrs, 0, sizeof(attrs));
180     file = "passwd";
181     fprintf(stderr, "Opening file %s\n", file);
182     offset = 0;
183     silc_sftp_open(sftp, file, SILC_SFTP_FXF_READ,
184                    &attrs, sftp_handle, client);
185     return;
186   }
187
188   if (!strcmp(dir, "/"))
189     dir = "sftp";
190
191   fprintf(stderr, "Opening %s\n", dir);
192
193   /* opendir */
194   opendir = TRUE;
195   silc_sftp_opendir(sftp, dir, sftp_handle, client);
196 }
197
198 static void sftp_handle(SilcSFTP sftp, SilcSFTPStatus status,
199                         SilcSFTPHandle handle, void *context)
200 {
201   Client client = (Client)context;
202
203   SILC_LOG_DEBUG(("Handle"));
204   fprintf(stderr, "Status %d\n", status);
205   if (status != SILC_SFTP_STATUS_OK)
206     return;
207
208   if (opendir) {
209     fprintf(stderr, "Reading %s\n", dir);
210     /* Readdir */
211     silc_sftp_readdir(sftp, handle, sftp_name, client);
212   } else {
213     fprintf(stderr, "Reading file %s\n", file);
214
215     /* Read */
216     silc_sftp_read(sftp, handle, 0, 2048, sftp_data, handle);
217   }
218 }
219
220 static void sftp_version(SilcSFTP sftp, SilcSFTPStatus status,
221                          SilcSFTPVersion version, void *context)
222 {
223   Client client = (Client)context;
224   fprintf(stderr, "Version: %d\n", (int)version);
225
226   SILC_LOG_DEBUG(("Version"));
227   fprintf(stderr, "Status %d\n", status);
228
229   /* opendir */
230   dir = "/";
231   fprintf(stderr, "Opening %s\n", dir);
232   opendir = TRUE;
233   silc_sftp_opendir(sftp, dir, sftp_handle, client);
234 }
235
236 int main(int argc, char **argv)
237 {
238   Client client = silc_calloc(1, sizeof(*client));
239   int sock;
240
241   gclient = client;
242
243   if (argc > 1 && !strcmp(argv[1], "-d")) {
244     silc_debug = 1;
245     silc_debug_hexdump = 1;
246     silc_log_set_debug_string("");
247   }
248
249   client->schedule = silc_schedule_init(100);
250   if (!client->schedule)
251     return -1;
252
253   /* Connecto to server */
254   sock = silc_net_create_connection(NULL, 5000, "127.0.0.1");
255   if (sock < 0)
256     return -1;
257   silc_socket_alloc(sock, 0, NULL, &client->sock);
258   silc_schedule_task_add(client->schedule, sock,
259                          packet_process, client, 0, 0,
260                          SILC_TASK_GENERIC, SILC_TASK_PRI_NORMAL);
261
262   /* Start SFTP session */
263   client->sftp = silc_sftp_client_start(client->sock, send_packet, client,
264                                         sftp_version, client);
265
266   silc_schedule(client->schedule);
267   return 0;
268 }