Browse Source

Updated FTP to use data-xfer API.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
0dfd5b84fd
2 changed files with 206 additions and 230 deletions
  1. 0
    56
      src/include/gpxe/ftp.h
  2. 206
    174
      src/net/tcp/ftp.c

+ 0
- 56
src/include/gpxe/ftp.h View File

7
  *
7
  *
8
  */
8
  */
9
 
9
 
10
-#include <stdint.h>
11
-#include <gpxe/async.h>
12
-#include <gpxe/stream.h>
13
-
14
-struct buffer;
15
-
16
 /** FTP default port */
10
 /** FTP default port */
17
 #define FTP_PORT 21
11
 #define FTP_PORT 21
18
 
12
 
19
-/**
20
- * FTP states
21
- *
22
- * These @b must be sequential, i.e. a successful FTP session must
23
- * pass through each of these states in order.
24
- */
25
-enum ftp_state {
26
-	FTP_CONNECT = 0,
27
-	FTP_USER,
28
-	FTP_PASS,
29
-	FTP_TYPE,
30
-	FTP_PASV,
31
-	FTP_RETR,
32
-	FTP_QUIT,
33
-	FTP_DONE,
34
-};
35
-
36
-/**
37
- * An FTP request
38
- *
39
- */
40
-struct ftp_request {
41
-	/** URI being fetched */
42
-	struct uri *uri;
43
-	/** Data buffer to fill */
44
-	struct buffer *buffer;
45
-	/** Asynchronous operation */
46
-	struct async async;
47
-
48
-	/** Current state */
49
-	enum ftp_state state;
50
-	/** Amount of current message already transmitted */
51
-	size_t already_sent;
52
-	/** Buffer to be filled with data received via the control channel */
53
-	char *recvbuf;
54
-	/** Remaining size of recvbuf */
55
-	size_t recvsize;
56
-	/** FTP status code, as text */
57
-	char status_text[4];
58
-	/** Passive-mode parameters, as text */
59
-	char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
60
-	/** Stream application for the control channel */
61
-	struct stream_application stream;
62
-	/** Stream application for the data channel */
63
-	struct stream_application stream_data;
64
-};
65
-
66
-extern int ftp_get ( struct uri *uri, struct buffer *buffer,
67
-		     struct async *parent );
68
-
69
 #endif /* _GPXE_FTP_H */
13
 #endif /* _GPXE_FTP_H */

+ 206
- 174
src/net/tcp/ftp.c View File

1
-#include <stddef.h>
1
+#include <stdint.h>
2
 #include <stdlib.h>
2
 #include <stdlib.h>
3
 #include <stdio.h>
3
 #include <stdio.h>
4
 #include <string.h>
4
 #include <string.h>
5
 #include <assert.h>
5
 #include <assert.h>
6
 #include <errno.h>
6
 #include <errno.h>
7
 #include <byteswap.h>
7
 #include <byteswap.h>
8
-#include <gpxe/async.h>
9
-#include <gpxe/buffer.h>
8
+#include <gpxe/socket.h>
9
+#include <gpxe/tcpip.h>
10
+#include <gpxe/in.h>
11
+#include <gpxe/xfer.h>
12
+#include <gpxe/open.h>
10
 #include <gpxe/uri.h>
13
 #include <gpxe/uri.h>
11
-#include <gpxe/download.h>
12
-#include <gpxe/tcp.h>
13
 #include <gpxe/ftp.h>
14
 #include <gpxe/ftp.h>
14
 
15
 
15
 /** @file
16
 /** @file
18
  *
19
  *
19
  */
20
  */
20
 
21
 
22
+/**
23
+ * FTP states
24
+ *
25
+ * These @b must be sequential, i.e. a successful FTP session must
26
+ * pass through each of these states in order.
27
+ */
28
+enum ftp_state {
29
+	FTP_CONNECT = 0,
30
+	FTP_USER,
31
+	FTP_PASS,
32
+	FTP_TYPE,
33
+	FTP_PASV,
34
+	FTP_RETR,
35
+	FTP_QUIT,
36
+	FTP_DONE,
37
+};
38
+
39
+/**
40
+ * An FTP request
41
+ *
42
+ */
43
+struct ftp_request {
44
+	/** Reference counter */
45
+	struct refcnt refcnt;
46
+	/** Data transfer interface */
47
+	struct xfer_interface xfer;
48
+
49
+	/** URI being fetched */
50
+	struct uri *uri;
51
+	/** FTP control channel interface */
52
+	struct xfer_interface control;
53
+	/** FTP data channel interface */
54
+	struct xfer_interface data;
55
+
56
+	/** Current state */
57
+	enum ftp_state state;
58
+	/** Buffer to be filled with data received via the control channel */
59
+	char *recvbuf;
60
+	/** Remaining size of recvbuf */
61
+	size_t recvsize;
62
+	/** FTP status code, as text */
63
+	char status_text[5];
64
+	/** Passive-mode parameters, as text */
65
+	char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
66
+};
67
+
68
+/**
69
+ * Free FTP request
70
+ *
71
+ * @v refcnt		Reference counter
72
+ */
73
+static void ftp_free ( struct refcnt *refcnt ) {
74
+	struct ftp_request *ftp =
75
+		container_of ( refcnt, struct ftp_request, refcnt );
76
+
77
+	DBGC ( ftp, "FTP %p freed\n", ftp );
78
+
79
+	uri_put ( ftp->uri );
80
+	free ( ftp );
81
+}
82
+
83
+/**
84
+ * Mark FTP operation as complete
85
+ *
86
+ * @v ftp		FTP request
87
+ * @v rc		Return status code
88
+ */
89
+static void ftp_done ( struct ftp_request *ftp, int rc ) {
90
+
91
+	DBGC ( ftp, "FTP %p completed (%s)\n", ftp, strerror ( rc ) );
92
+
93
+	/* Close all data transfer interfaces */
94
+	xfer_nullify ( &ftp->xfer );
95
+	xfer_close ( &ftp->xfer, rc );
96
+	xfer_nullify ( &ftp->control );
97
+	xfer_close ( &ftp->control, rc );
98
+	xfer_nullify ( &ftp->data );
99
+	xfer_close ( &ftp->data, rc );
100
+}
101
+
21
 /*****************************************************************************
102
 /*****************************************************************************
22
  *
103
  *
23
  * FTP control channel
104
  * FTP control channel
24
  *
105
  *
25
  */
106
  */
26
 
107
 
27
-/** FTP control channel strings
108
+/**
109
+ * FTP control channel strings
28
  *
110
  *
29
  * These are used as printf() format strings.  Since only one of them
111
  * These are used as printf() format strings.  Since only one of them
30
  * (RETR) takes an argument, we always supply that argument to the
112
  * (RETR) takes an argument, we always supply that argument to the
42
 };
124
 };
43
 
125
 
44
 /**
126
 /**
45
- * Get FTP request from control stream application
127
+ * Handle control channel being closed
46
  *
128
  *
47
- * @v app		Stream application
48
- * @ret ftp		FTP request
49
- */
50
-static inline struct ftp_request *
51
-stream_to_ftp ( struct stream_application *app ) {
52
-	return container_of ( app, struct ftp_request, stream );
53
-}
54
-
55
-/**
56
- * Mark FTP operation as complete
129
+ * @v control		FTP control channel interface
130
+ * @v rc		Reason for close
57
  *
131
  *
58
- * @v ftp		FTP request
59
- * @v rc		Return status code
132
+ * When the control channel is closed, the data channel must also be
133
+ * closed, if it is currently open.
60
  */
134
  */
61
-static void ftp_done ( struct ftp_request *ftp, int rc ) {
62
-
63
-	DBGC ( ftp, "FTP %p completed with status %d\n", ftp, rc );
135
+static void ftp_control_close ( struct xfer_interface *control, int rc ) {
136
+	struct ftp_request *ftp =
137
+		container_of ( control, struct ftp_request, control );
64
 
138
 
65
-	/* Close both stream connections */
66
-	stream_close ( &ftp->stream );
67
-	stream_close ( &ftp->stream_data );
139
+	DBGC ( ftp, "FTP %p control connection closed: %s\n",
140
+	       ftp, strerror ( rc ) );
68
 
141
 
69
-	/* Mark asynchronous operation as complete */
70
-	async_done ( &ftp->async, rc );
142
+	/* Complete FTP operation */
143
+	ftp_done ( ftp, rc );
71
 }
144
 }
72
 
145
 
73
 /**
146
 /**
102
  */
175
  */
103
 static void ftp_reply ( struct ftp_request *ftp ) {
176
 static void ftp_reply ( struct ftp_request *ftp ) {
104
 	char status_major = ftp->status_text[0];
177
 	char status_major = ftp->status_text[0];
178
+	char separator = ftp->status_text[3];
105
 
179
 
106
 	DBGC ( ftp, "FTP %p received status %s\n", ftp, ftp->status_text );
180
 	DBGC ( ftp, "FTP %p received status %s\n", ftp, ftp->status_text );
107
 
181
 
182
+	/* Ignore malformed lines */
183
+	if ( separator != ' ' )
184
+		return;
185
+
108
 	/* Ignore "intermediate" responses (1xx codes) */
186
 	/* Ignore "intermediate" responses (1xx codes) */
109
 	if ( status_major == '1' )
187
 	if ( status_major == '1' )
110
 		return;
188
 		return;
133
 				  sizeof ( sa.sin.sin_addr ) );
211
 				  sizeof ( sa.sin.sin_addr ) );
134
 		ftp_parse_value ( &ptr, ( uint8_t * ) &sa.sin.sin_port,
212
 		ftp_parse_value ( &ptr, ( uint8_t * ) &sa.sin.sin_port,
135
 				  sizeof ( sa.sin.sin_port ) );
213
 				  sizeof ( sa.sin.sin_port ) );
136
-		if ( ( rc = tcp_open ( &ftp->stream_data ) ) != 0 ) {
214
+		if ( ( rc = xfer_open_socket ( &ftp->data, SOCK_STREAM,
215
+					       &sa.sa, NULL ) ) != 0 ) {
137
 			DBGC ( ftp, "FTP %p could not open data connection\n",
216
 			DBGC ( ftp, "FTP %p could not open data connection\n",
138
 			       ftp );
217
 			       ftp );
139
 			ftp_done ( ftp, rc );
218
 			ftp_done ( ftp, rc );
140
 			return;
219
 			return;
141
 		}
220
 		}
142
-		if ( ( rc = stream_connect ( &ftp->stream_data,
143
-					     &sa.sa ) ) != 0 ){
144
-			DBGC ( ftp, "FTP %p could not make data connection\n",
145
-			       ftp );
146
-			ftp_done ( ftp, rc );
147
-			return;
148
-		}
149
 	}
221
 	}
150
 
222
 
151
 	/* Move to next state */
223
 	/* Move to next state */
152
 	if ( ftp->state < FTP_DONE )
224
 	if ( ftp->state < FTP_DONE )
153
 		ftp->state++;
225
 		ftp->state++;
154
-	ftp->already_sent = 0;
155
 
226
 
227
+	/* Send control string */
156
 	if ( ftp->state < FTP_DONE ) {
228
 	if ( ftp->state < FTP_DONE ) {
157
 		DBGC ( ftp, "FTP %p sending ", ftp );
229
 		DBGC ( ftp, "FTP %p sending ", ftp );
158
 		DBGC ( ftp, ftp_strings[ftp->state], ftp->uri->path );
230
 		DBGC ( ftp, ftp_strings[ftp->state], ftp->uri->path );
231
+		xfer_printf ( &ftp->control, ftp_strings[ftp->state],
232
+			      ftp->uri->path );
159
 	}
233
 	}
160
-
161
-	return;
162
 }
234
 }
163
 
235
 
164
 /**
236
 /**
165
  * Handle new data arriving on FTP control channel
237
  * Handle new data arriving on FTP control channel
166
  *
238
  *
167
- * @v app		Stream application
239
+ * @v control		FTP control channel interface
168
  * @v data		New data
240
  * @v data		New data
169
  * @v len		Length of new data
241
  * @v len		Length of new data
170
  *
242
  *
171
  * Data is collected until a complete line is received, at which point
243
  * Data is collected until a complete line is received, at which point
172
  * its information is passed to ftp_reply().
244
  * its information is passed to ftp_reply().
173
  */
245
  */
174
-static void ftp_newdata ( struct stream_application *app,
175
-			  void *data, size_t len ) {
176
-	struct ftp_request *ftp = stream_to_ftp ( app );
246
+static int ftp_control_deliver_raw ( struct xfer_interface *control,
247
+				     const void *data, size_t len ) {
248
+	struct ftp_request *ftp =
249
+		container_of ( control, struct ftp_request, control );
177
 	char *recvbuf = ftp->recvbuf;
250
 	char *recvbuf = ftp->recvbuf;
178
 	size_t recvsize = ftp->recvsize;
251
 	size_t recvsize = ftp->recvsize;
179
 	char c;
252
 	char c;
215
 	/* Store for next invocation */
288
 	/* Store for next invocation */
216
 	ftp->recvbuf = recvbuf;
289
 	ftp->recvbuf = recvbuf;
217
 	ftp->recvsize = recvsize;
290
 	ftp->recvsize = recvsize;
218
-}
219
 
291
 
220
-/**
221
- * Handle acknowledgement of data sent on FTP control channel
222
- *
223
- * @v app		Stream application
224
- */
225
-static void ftp_acked ( struct stream_application *app, size_t len ) {
226
-	struct ftp_request *ftp = stream_to_ftp ( app );
227
-	
228
-	/* Mark off ACKed portion of the currently-transmitted data */
229
-	ftp->already_sent += len;
230
-}
231
-
232
-/**
233
- * Construct data to send on FTP control channel
234
- *
235
- * @v app		Stream application
236
- * @v buf		Temporary data buffer
237
- * @v len		Length of temporary data buffer
238
- */
239
-static void ftp_senddata ( struct stream_application *app,
240
-			   void *buf, size_t len ) {
241
-	struct ftp_request *ftp = stream_to_ftp ( app );
242
-
243
-	/* Send the as-yet-unACKed portion of the string for the
244
-	 * current state.
245
-	 */
246
-	len = snprintf ( buf, len, ftp_strings[ftp->state], ftp->uri->path );
247
-	stream_send ( app, buf + ftp->already_sent, len - ftp->already_sent );
248
-}
249
-
250
-/**
251
- * Handle control channel being closed
252
- *
253
- * @v app		Stream application
254
- *
255
- * When the control channel is closed, the data channel must also be
256
- * closed, if it is currently open.
257
- */
258
-static void ftp_closed ( struct stream_application *app, int rc ) {
259
-	struct ftp_request *ftp = stream_to_ftp ( app );
260
-
261
-	DBGC ( ftp, "FTP %p control connection closed: %s\n",
262
-	       ftp, strerror ( rc ) );
263
-
264
-	/* Complete FTP operation */
265
-	ftp_done ( ftp, rc );
292
+	return 0;
266
 }
293
 }
267
 
294
 
268
 /** FTP control channel operations */
295
 /** FTP control channel operations */
269
-static struct stream_application_operations ftp_stream_operations = {
270
-	.closed		= ftp_closed,
271
-	.acked		= ftp_acked,
272
-	.newdata	= ftp_newdata,
273
-	.senddata	= ftp_senddata,
296
+static struct xfer_interface_operations ftp_control_operations = {
297
+	.close		= ftp_control_close,
298
+	.vredirect	= xfer_vopen,
299
+	.request	= ignore_xfer_request,
300
+	.seek		= ignore_xfer_seek,
301
+	.alloc_iob	= default_xfer_alloc_iob,
302
+	.deliver_iob	= xfer_deliver_as_raw,
303
+	.deliver_raw	= ftp_control_deliver_raw,
274
 };
304
 };
275
 
305
 
276
 /*****************************************************************************
306
 /*****************************************************************************
280
  */
310
  */
281
 
311
 
282
 /**
312
 /**
283
- * Get FTP request from data stream application
313
+ * Handle FTP data channel being closed
284
  *
314
  *
285
- * @v app		Stream application
286
- * @ret ftp		FTP request
287
- */
288
-static inline struct ftp_request *
289
-stream_to_ftp_data ( struct stream_application *app ) {
290
-	return container_of ( app, struct ftp_request, stream_data );
291
-}
292
-
293
-/**
294
- * Handle data channel being closed
295
- *
296
- * @v app		Stream application
315
+ * @v data		FTP data channel interface
316
+ * @v rc		Reason for closure
297
  *
317
  *
298
  * When the data channel is closed, the control channel should be left
318
  * When the data channel is closed, the control channel should be left
299
  * alone; the server will send a completion message via the control
319
  * alone; the server will send a completion message via the control
301
  *
321
  *
302
  * If the data channel is closed due to an error, we abort the request.
322
  * If the data channel is closed due to an error, we abort the request.
303
  */
323
  */
304
-static void ftp_data_closed ( struct stream_application *app, int rc ) {
305
-	struct ftp_request *ftp = stream_to_ftp_data ( app );
324
+static void ftp_data_closed ( struct xfer_interface *data, int rc ) {
325
+	struct ftp_request *ftp =
326
+		container_of ( data, struct ftp_request, data );
306
 
327
 
307
 	DBGC ( ftp, "FTP %p data connection closed: %s\n",
328
 	DBGC ( ftp, "FTP %p data connection closed: %s\n",
308
 	       ftp, strerror ( rc ) );
329
 	       ftp, strerror ( rc ) );
313
 }
334
 }
314
 
335
 
315
 /**
336
 /**
316
- * Handle new data arriving on the FTP data channel
337
+ * Handle data delivery via FTP data channel
317
  *
338
  *
318
- * @v app		Stream application
319
- * @v data		New data
320
- * @v len		Length of new data
339
+ * @v xfer		FTP data channel interface
340
+ * @v iobuf		I/O buffer
341
+ * @ret rc		Return status code
321
  */
342
  */
322
-static void ftp_data_newdata ( struct stream_application *app,
323
-			       void *data, size_t len ) {
324
-	struct ftp_request *ftp = stream_to_ftp_data ( app );
343
+static int ftp_data_deliver_iob ( struct xfer_interface *data,
344
+				  struct io_buffer *iobuf ) {
345
+	struct ftp_request *ftp =
346
+		container_of ( data, struct ftp_request, data );
325
 	int rc;
347
 	int rc;
326
 
348
 
327
-	/* Fill data buffer */
328
-	if ( ( rc = fill_buffer ( ftp->buffer, data,
329
-				  ftp->buffer->fill, len ) ) != 0 ){
330
-		DBGC ( ftp, "FTP %p failed to fill data buffer: %s\n",
349
+	if ( ( rc = xfer_deliver_iob ( &ftp->xfer, iobuf ) ) != 0 ) {
350
+		DBGC ( ftp, "FTP %p failed to deliver data: %s\n",
331
 		       ftp, strerror ( rc ) );
351
 		       ftp, strerror ( rc ) );
332
-		ftp_done ( ftp, rc );
333
-		return;
352
+		return rc;
334
 	}
353
 	}
354
+
355
+	return 0;
335
 }
356
 }
336
 
357
 
337
 /** FTP data channel operations */
358
 /** FTP data channel operations */
338
-static struct stream_application_operations ftp_data_stream_operations = {
339
-	.closed		= ftp_data_closed,
340
-	.newdata	= ftp_data_newdata,
359
+static struct xfer_interface_operations ftp_data_operations = {
360
+	.close		= ftp_data_closed,
361
+	.vredirect	= xfer_vopen,
362
+	.request	= ignore_xfer_request,
363
+	.seek		= ignore_xfer_seek,
364
+	.alloc_iob	= default_xfer_alloc_iob,
365
+	.deliver_iob	= ftp_data_deliver_iob,
366
+	.deliver_raw	= xfer_deliver_as_iob,
341
 };
367
 };
342
 
368
 
343
 /*****************************************************************************
369
 /*****************************************************************************
344
  *
370
  *
345
- * API
371
+ * Data transfer interface
346
  *
372
  *
347
  */
373
  */
348
 
374
 
349
 /**
375
 /**
350
- * Reap asynchronous operation
376
+ * Close FTP data transfer interface
351
  *
377
  *
352
- * @v async		Asynchronous operation
378
+ * @v xfer		FTP data transfer interface
379
+ * @v rc		Reason for close
353
  */
380
  */
354
-static void ftp_reap ( struct async *async ) {
381
+static void ftp_xfer_closed ( struct xfer_interface *xfer, int rc ) {
355
 	struct ftp_request *ftp =
382
 	struct ftp_request *ftp =
356
-		container_of ( async, struct ftp_request, async );
383
+		container_of ( xfer, struct ftp_request, xfer );
357
 
384
 
358
-	free ( ftp );
385
+	DBGC ( ftp, "FTP %p data transfer interface closed: %s\n",
386
+	       ftp, strerror ( rc ) );
387
+	
388
+	ftp_done ( ftp, rc );
359
 }
389
 }
360
 
390
 
361
-/** FTP asynchronous operations */
362
-static struct async_operations ftp_async_operations = {
363
-	.reap = ftp_reap,
391
+/** FTP data transfer interface operations */
392
+static struct xfer_interface_operations ftp_xfer_operations = {
393
+	.close		= ftp_xfer_closed,
394
+	.vredirect	= ignore_xfer_vredirect,
395
+	.request	= ignore_xfer_request,
396
+	.seek		= ignore_xfer_seek,
397
+	.alloc_iob	= default_xfer_alloc_iob,
398
+	.deliver_iob	= xfer_deliver_as_raw,
399
+	.deliver_raw	= ignore_xfer_deliver_raw,
364
 };
400
 };
365
 
401
 
402
+/*****************************************************************************
403
+ *
404
+ * URI opener
405
+ *
406
+ */
407
+
366
 /**
408
 /**
367
  * Initiate an FTP connection
409
  * Initiate an FTP connection
368
  *
410
  *
411
+ * @v xfer		Data transfer interface
369
  * @v uri		Uniform Resource Identifier
412
  * @v uri		Uniform Resource Identifier
370
- * @v buffer		Buffer into which to download file
371
- * @v parent		Parent asynchronous operation
372
  * @ret rc		Return status code
413
  * @ret rc		Return status code
373
  */
414
  */
374
-int ftp_get ( struct uri *uri, struct buffer *buffer, struct async *parent ) {
375
-	struct ftp_request *ftp = NULL;
415
+static int ftp_open ( struct xfer_interface *xfer, struct uri *uri ) {
416
+	struct ftp_request *ftp;
417
+	struct sockaddr_tcpip server;
376
 	int rc;
418
 	int rc;
377
 
419
 
378
 	/* Sanity checks */
420
 	/* Sanity checks */
379
-	if ( ! uri->path ) {
380
-		rc = -EINVAL;
381
-		goto err;
382
-	}
421
+	if ( ! uri->path )
422
+		return -EINVAL;
423
+	if ( ! uri->host )
424
+		return -EINVAL;
383
 
425
 
384
-	/* Allocate and populate FTP structure */
426
+	/* Allocate and populate structure */
385
 	ftp = malloc ( sizeof ( *ftp ) );
427
 	ftp = malloc ( sizeof ( *ftp ) );
386
-	if ( ! ftp ) {
387
-		rc = -ENOMEM;
388
-		goto err;
389
-	}
428
+	if ( ! ftp )
429
+		return -ENOMEM;
390
 	memset ( ftp, 0, sizeof ( *ftp ) );
430
 	memset ( ftp, 0, sizeof ( *ftp ) );
391
-	ftp->uri = uri;
392
-	ftp->buffer = buffer;
393
-	ftp->state = FTP_CONNECT;
394
-	ftp->already_sent = 0;
431
+	ftp->refcnt.free = ftp_free;
432
+	xfer_init ( &ftp->xfer, &ftp_xfer_operations, &ftp->refcnt );
433
+	ftp->uri = uri_get ( uri );
434
+	xfer_init ( &ftp->control, &ftp_control_operations, &ftp->refcnt );
435
+	xfer_init ( &ftp->data, &ftp_data_operations, &ftp->refcnt );
395
 	ftp->recvbuf = ftp->status_text;
436
 	ftp->recvbuf = ftp->status_text;
396
 	ftp->recvsize = sizeof ( ftp->status_text ) - 1;
437
 	ftp->recvsize = sizeof ( ftp->status_text ) - 1;
397
-	ftp->stream.op = &ftp_stream_operations;
398
-	ftp->stream_data.op = &ftp_data_stream_operations;
399
-
400
-#warning "Quick name resolution hack"
401
-	union {
402
-		struct sockaddr sa;
403
-		struct sockaddr_in sin;
404
-	} server;
405
-	server.sin.sin_port = htons ( FTP_PORT );
406
-	server.sin.sin_family = AF_INET;
407
-	if ( inet_aton ( uri->host, &server.sin.sin_addr ) == 0 ) {
408
-		rc = -EINVAL;
409
-		goto err;
410
-	}
411
 
438
 
412
 	DBGC ( ftp, "FTP %p fetching %s\n", ftp, ftp->uri->path );
439
 	DBGC ( ftp, "FTP %p fetching %s\n", ftp, ftp->uri->path );
413
 
440
 
414
-	if ( ( rc = tcp_open ( &ftp->stream ) ) != 0 )
415
-		goto err;
416
-	if ( ( rc = stream_connect ( &ftp->stream, &server.sa ) ) != 0 )
441
+	/* Open control connection */
442
+	memset ( &server, 0, sizeof ( server ) );
443
+	server.st_port = htons ( uri_port ( uri, FTP_PORT ) );
444
+	if ( ( rc = xfer_open_named_socket ( &ftp->control, SOCK_STREAM,
445
+					     ( struct sockaddr * ) &server,
446
+					     uri->host, NULL ) ) != 0 )
417
 		goto err;
447
 		goto err;
418
 
448
 
419
-	async_init ( &ftp->async, &ftp_async_operations, parent );
449
+	/* Attach to parent interface, mortalise self, and return */
450
+	xfer_plug_plug ( &ftp->xfer, xfer );
451
+	ref_put ( &ftp->refcnt );
420
 	return 0;
452
 	return 0;
421
 
453
 
422
  err:
454
  err:
423
 	DBGC ( ftp, "FTP %p could not create request: %s\n", 
455
 	DBGC ( ftp, "FTP %p could not create request: %s\n", 
424
 	       ftp, strerror ( rc ) );
456
 	       ftp, strerror ( rc ) );
425
-	free ( ftp );
457
+	ref_put ( &ftp->refcnt );
426
 	return rc;
458
 	return rc;
427
 }
459
 }
428
 
460
 
429
-/** HTTP download protocol */
430
-struct download_protocol ftp_download_protocol __download_protocol = {
431
-	.name = "ftp",
432
-	.start_download = ftp_get,
461
+/** FTP URI opener */
462
+struct uri_opener ftp_uri_opener __uri_opener = {
463
+	.scheme	= "ftp",
464
+	.open	= ftp_open,
433
 };
465
 };

Loading…
Cancel
Save