Browse Source

Change FTP to use a data buffer rather than a callback function.

tags/v0.9.3
Michael Brown 18 years ago
parent
commit
6918cf9e9e
3 changed files with 47 additions and 25 deletions
  1. 6
    9
      src/include/gpxe/ftp.h
  2. 27
    14
      src/net/tcp/ftp.c
  3. 14
    2
      src/tests/ftptest.c

+ 6
- 9
src/include/gpxe/ftp.h View File

11
 #include <gpxe/async.h>
11
 #include <gpxe/async.h>
12
 #include <gpxe/tcp.h>
12
 #include <gpxe/tcp.h>
13
 
13
 
14
+struct buffer;
15
+
14
 /** FTP default port */
16
 /** FTP default port */
15
 #define FTP_PORT 21
17
 #define FTP_PORT 21
16
 
18
 
40
 	struct sockaddr_tcpip server;
42
 	struct sockaddr_tcpip server;
41
 	/** File to download */
43
 	/** File to download */
42
 	const char *filename;
44
 	const char *filename;
43
-	/** Callback function
44
-	 *
45
-	 * @v data	Received data
46
-	 * @v len	Length of received data
47
-	 *
48
-	 * This function is called for all data received from the
49
-	 * remote server.
50
-	 */
51
-	void ( *callback ) ( char *data, size_t len );
45
+	/** Data buffer to fill */
46
+	struct buffer *buffer;
52
 
47
 
53
 	/** Current state */
48
 	/** Current state */
54
 	enum ftp_state state;
49
 	enum ftp_state state;
62
 	char status_text[4];
57
 	char status_text[4];
63
 	/** Passive-mode parameters, as text */
58
 	/** Passive-mode parameters, as text */
64
 	char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
59
 	char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
60
+	/** Amount of data received */
61
+	size_t data_rcvd;
65
 
62
 
66
 	/** TCP application for the control channel */
63
 	/** TCP application for the control channel */
67
 	struct tcp_application tcp;
64
 	struct tcp_application tcp;

+ 27
- 14
src/net/tcp/ftp.c View File

5
 #include <assert.h>
5
 #include <assert.h>
6
 #include <errno.h>
6
 #include <errno.h>
7
 #include <gpxe/async.h>
7
 #include <gpxe/async.h>
8
+#include <gpxe/buffer.h>
8
 #include <gpxe/ftp.h>
9
 #include <gpxe/ftp.h>
9
 
10
 
10
 /** @file
11
 /** @file
268
  * When the control channel is closed, the data channel must also be
269
  * When the control channel is closed, the data channel must also be
269
  * closed, if it is currently open.
270
  * closed, if it is currently open.
270
  */
271
  */
271
-static void ftp_closed ( struct tcp_application *app, int status ) {
272
+static void ftp_closed ( struct tcp_application *app, int rc ) {
272
 	struct ftp_request *ftp = tcp_to_ftp ( app );
273
 	struct ftp_request *ftp = tcp_to_ftp ( app );
273
 
274
 
274
-	DBGC ( ftp, "FTP %p control connection closed (status %d)\n",
275
-	       ftp, status );
275
+	DBGC ( ftp, "FTP %p control connection closed: %s\n",
276
+	       ftp, strerror ( rc ) );
276
 
277
 
277
 	/* Complete FTP operation */
278
 	/* Complete FTP operation */
278
-	ftp_done ( ftp, status );
279
+	ftp_done ( ftp, rc );
279
 }
280
 }
280
 
281
 
281
 /** FTP control channel operations */
282
 /** FTP control channel operations */
314
  *
315
  *
315
  * If the data channel is closed due to an error, we abort the request.
316
  * If the data channel is closed due to an error, we abort the request.
316
  */
317
  */
317
-static void ftp_data_closed ( struct tcp_application *app, int status ) {
318
+static void ftp_data_closed ( struct tcp_application *app, int rc ) {
318
 	struct ftp_request *ftp = tcp_to_ftp_data ( app );
319
 	struct ftp_request *ftp = tcp_to_ftp_data ( app );
319
 
320
 
320
-	DBGC ( ftp, "FTP %p data connection closed (status %d)\n",
321
-	       ftp, status );
321
+	DBGC ( ftp, "FTP %p data connection closed: %s\n",
322
+	       ftp, strerror ( rc ) );
322
 	
323
 	
323
 	/* If there was an error, close control channel and record status */
324
 	/* If there was an error, close control channel and record status */
324
-	if ( status )
325
-		ftp_done ( ftp, status );
325
+	if ( rc )
326
+		ftp_done ( ftp, rc );
326
 }
327
 }
327
 
328
 
328
 /**
329
 /**
331
  * @v app	TCP application
332
  * @v app	TCP application
332
  * @v data	New data
333
  * @v data	New data
333
  * @v len	Length of new data
334
  * @v len	Length of new data
334
- *
335
- * Data is handed off to the callback registered in the FTP request.
336
  */
335
  */
337
 static void ftp_data_newdata ( struct tcp_application *app,
336
 static void ftp_data_newdata ( struct tcp_application *app,
338
 			       void *data, size_t len ) {
337
 			       void *data, size_t len ) {
339
 	struct ftp_request *ftp = tcp_to_ftp_data ( app );
338
 	struct ftp_request *ftp = tcp_to_ftp_data ( app );
339
+	int rc;
340
+
341
+	/* Fill data buffer */
342
+	if ( ( rc = fill_buffer ( ftp->buffer, data,
343
+				  ftp->data_rcvd, len ) ) != 0 ){
344
+		DBGC ( ftp, "FTP %p failed to fill data buffer: %s\n",
345
+		       ftp, strerror ( rc ) );
346
+		ftp_done ( ftp, rc );
347
+		return;
348
+	}
340
 
349
 
341
-	ftp->callback ( data, len );
350
+	/* Update received data total */
351
+	ftp->data_rcvd += len;
342
 }
352
 }
343
 
353
 
344
 /** FTP data channel operations */
354
 /** FTP data channel operations */
363
 
373
 
364
 	DBGC ( ftp, "FTP %p fetching %s\n", ftp, ftp->filename );
374
 	DBGC ( ftp, "FTP %p fetching %s\n", ftp, ftp->filename );
365
 
375
 
366
-	ftp->tcp.tcp_op = &ftp_tcp_operations;
367
-	ftp->tcp_data.tcp_op = &ftp_data_tcp_operations;
376
+	ftp->state = FTP_CONNECT;
377
+	ftp->already_sent = 0;
368
 	ftp->recvbuf = ftp->status_text;
378
 	ftp->recvbuf = ftp->status_text;
369
 	ftp->recvsize = sizeof ( ftp->status_text ) - 1;
379
 	ftp->recvsize = sizeof ( ftp->status_text ) - 1;
380
+	ftp->data_rcvd = 0;
381
+	ftp->tcp.tcp_op = &ftp_tcp_operations;
382
+	ftp->tcp_data.tcp_op = &ftp_data_tcp_operations;
370
 	if ( ( rc = tcp_connect ( &ftp->tcp, &ftp->server, 0 ) ) != 0 )
383
 	if ( ( rc = tcp_connect ( &ftp->tcp, &ftp->server, 0 ) ) != 0 )
371
 		ftp_done ( ftp, rc );
384
 		ftp_done ( ftp, rc );
372
 
385
 

+ 14
- 2
src/tests/ftptest.c View File

4
 #include <console.h>
4
 #include <console.h>
5
 #include <vsprintf.h>
5
 #include <vsprintf.h>
6
 #include <gpxe/async.h>
6
 #include <gpxe/async.h>
7
+#include <gpxe/buffer.h>
7
 #include <gpxe/ftp.h>
8
 #include <gpxe/ftp.h>
8
 
9
 
9
-static void test_ftp_callback ( char *data, size_t len ) {
10
+static void print_ftp_response ( char *data, size_t len ) {
10
 	unsigned int i;
11
 	unsigned int i;
11
 	char c;
12
 	char c;
12
 
13
 
23
 }
24
 }
24
 
25
 
25
 void test_ftp ( struct sockaddr_tcpip *server, const char *filename ) {
26
 void test_ftp ( struct sockaddr_tcpip *server, const char *filename ) {
27
+	char data[256];
28
+	struct buffer buffer;
26
 	struct ftp_request ftp;
29
 	struct ftp_request ftp;
27
 	int rc;
30
 	int rc;
28
 
31
 
29
 	printf ( "FTP fetching %s\n", filename );
32
 	printf ( "FTP fetching %s\n", filename );
30
 	
33
 	
34
+	memset ( &buffer, 0, sizeof ( buffer ) );
35
+	buffer.addr = virt_to_phys ( data );
36
+	buffer.len = sizeof ( data );
37
+
31
 	memset ( &ftp, 0, sizeof ( ftp ) );
38
 	memset ( &ftp, 0, sizeof ( ftp ) );
32
 	memcpy ( &ftp.server, server, sizeof ( ftp.server ) );
39
 	memcpy ( &ftp.server, server, sizeof ( ftp.server ) );
33
 	ftp.filename = filename;
40
 	ftp.filename = filename;
34
-	ftp.callback = test_ftp_callback;
41
+	ftp.buffer = &buffer;
35
 
42
 
36
 	rc = async_wait ( ftp_get ( &ftp ) );
43
 	rc = async_wait ( ftp_get ( &ftp ) );
37
 	if ( rc ) {
44
 	if ( rc ) {
38
 		printf ( "FTP fetch failed\n" );
45
 		printf ( "FTP fetch failed\n" );
46
+		return;
39
 	}
47
 	}
48
+
49
+	printf ( "FTP received %d bytes\n", buffer.fill );
50
+
51
+	print_ftp_response ( data, buffer.fill );
40
 }
52
 }

Loading…
Cancel
Save