Browse Source

Merge TCP aborted(), timedout() and closed() methods into a single

closed() method with a reason code.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
9e1becaf8a
6 changed files with 131 additions and 102 deletions
  1. 6
    0
      src/include/gpxe/ftp.h
  2. 11
    15
      src/include/gpxe/tcp.h
  3. 9
    12
      src/net/tcp.c
  4. 101
    43
      src/net/tcp/ftp.c
  5. 3
    19
      src/net/tcp/hello.c
  6. 1
    13
      src/proto/iscsi.c

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

10
 #include <stdint.h>
10
 #include <stdint.h>
11
 #include <gpxe/tcp.h>
11
 #include <gpxe/tcp.h>
12
 
12
 
13
+/**
14
+ * FTP states
15
+ *
16
+ * These @b must be sequential, i.e. a successful FTP session must
17
+ * pass through each of these states in order.
18
+ */
13
 enum ftp_state {
19
 enum ftp_state {
14
 	FTP_CONNECT = 0,
20
 	FTP_CONNECT = 0,
15
 	FTP_USER,
21
 	FTP_USER,

+ 11
- 15
src/include/gpxe/tcp.h View File

19
  *
19
  *
20
  */
20
  */
21
 struct tcp_operations {
21
 struct tcp_operations {
22
-	/**
23
-	 * Connection aborted (RST received)
24
-	 *
25
-	 * @v conn	TCP connection
26
-	 */
27
-	void ( * aborted ) ( struct tcp_connection *conn );
28
-	/**
29
-	 * Connection timed out
22
+	/*
23
+	 * Connection closed
30
 	 *
24
 	 *
31
 	 * @v conn	TCP connection
25
 	 * @v conn	TCP connection
32
-	 */
33
-	void ( * timedout ) ( struct tcp_connection *conn );
34
-	/**
35
-	 * Connection aborted (FIN received)
26
+	 * @v status	Error code, if any
36
 	 *
27
 	 *
37
-	 * @v conn	TCP connection
28
+	 * This is called when the connection is closed for any
29
+	 * reason, including timeouts or aborts.  The status code
30
+	 * contains the negative error number, if the closure is due
31
+	 * to an error.
38
 	 *
32
 	 *
39
 	 * Note that acked() and newdata() may be called after
33
 	 * Note that acked() and newdata() may be called after
40
 	 * closed(), if the packet containing the FIN also
34
 	 * closed(), if the packet containing the FIN also
41
-	 * acknowledged data or contained new data.
35
+	 * acknowledged data or contained new data.  Note also that
36
+	 * connected() may not have been called before closed(), if
37
+	 * the close is due to an error.
42
 	 */
38
 	 */
43
-	void ( * closed ) ( struct tcp_connection *conn );
39
+	void ( * closed ) ( struct tcp_connection *conn, int status );
44
 	/**
40
 	/**
45
 	 * Connection established (SYNACK received)
41
 	 * Connection established (SYNACK received)
46
 	 *
42
 	 *

+ 9
- 12
src/net/tcp.c View File

2
 #include <assert.h>
2
 #include <assert.h>
3
 #include <byteswap.h>
3
 #include <byteswap.h>
4
 #include <latch.h>
4
 #include <latch.h>
5
+#include <errno.h>
5
 #include <gpxe/process.h>
6
 #include <gpxe/process.h>
6
 #include <gpxe/init.h>
7
 #include <gpxe/init.h>
7
 #include <gpxe/netdevice.h>
8
 #include <gpxe/netdevice.h>
131
 	struct tcp_connection *conn = *( ( void ** ) uip_conn->appstate );
132
 	struct tcp_connection *conn = *( ( void ** ) uip_conn->appstate );
132
 	struct tcp_operations *op = conn->tcp_op;
133
 	struct tcp_operations *op = conn->tcp_op;
133
 
134
 
134
-	assert ( conn->tcp_op->closed != NULL );
135
-	assert ( conn->tcp_op->connected != NULL );
136
-	assert ( conn->tcp_op->acked != NULL );
137
-	assert ( conn->tcp_op->newdata != NULL );
138
-	assert ( conn->tcp_op->senddata != NULL );
139
-
140
-	if ( uip_aborted() && op->aborted )
141
-		op->aborted ( conn );
142
-	if ( uip_timedout() && op->timedout )
143
-		op->timedout ( conn );
144
-	if ( uip_closed() && op->closed )
145
-		op->closed ( conn );
135
+	if ( op->closed ) {
136
+		if ( uip_aborted() )
137
+			op->closed ( conn, -ECONNABORTED );
138
+		if ( uip_timedout() )
139
+			op->closed ( conn, -ETIMEDOUT );
140
+		if ( uip_closed() )
141
+			op->closed ( conn, 0 );
142
+	}
146
 	if ( uip_connected() && op->connected )
143
 	if ( uip_connected() && op->connected )
147
 		op->connected ( conn );
144
 		op->connected ( conn );
148
 	if ( uip_acked() && op->acked )
145
 	if ( uip_acked() && op->acked )

+ 101
- 43
src/net/tcp/ftp.c View File

12
  *
12
  *
13
  */
13
  */
14
 
14
 
15
+/*****************************************************************************
16
+ *
17
+ * FTP control channel
18
+ *
19
+ */
20
+
15
 /** An FTP control channel string */
21
 /** An FTP control channel string */
16
 struct ftp_string {
22
 struct ftp_string {
17
 	/** String format */
23
 	/** String format */
25
 	off_t data_offset;
31
 	off_t data_offset;
26
 };
32
 };
27
 
33
 
28
-#define ftp_string_offset( fieldname ) \
29
-	offsetof ( struct ftp_request, fieldname )
34
+/** FTP control channel strings */
35
+static const struct ftp_string ftp_strings[] = {
36
+	[FTP_CONNECT]	= { "", 0 },
37
+	[FTP_USER]	= { "USER anonymous\r\n", 0 },
38
+	[FTP_PASS]	= { "PASS etherboot@etherboot.org\r\n", 0 },
39
+	[FTP_TYPE]	= { "TYPE I\r\n", 0 },
40
+	[FTP_PASV]	= { "PASV\r\n", 0 },
41
+	[FTP_RETR]	= { "RETR %s\r\n", 
42
+			    offsetof ( struct ftp_request, filename ) },
43
+	[FTP_QUIT]	= { "QUIT\r\n", 0 },
44
+	[FTP_DONE]	= { "", 0 },
45
+};
30
 
46
 
31
 /**
47
 /**
32
  * Get data associated with an FTP control channel string
48
  * Get data associated with an FTP control channel string
40
 	return * ( ( void ** ) ( ( ( void * ) ftp ) + data_offset ) );
56
 	return * ( ( void ** ) ( ( ( void * ) ftp ) + data_offset ) );
41
 }
57
 }
42
 
58
 
43
-/** FTP control channel strings */
44
-const struct ftp_string ftp_strings[] = {
45
-	[FTP_CONNECT]	= { "", 0 },
46
-	[FTP_USER]	= { "USER anonymous\r\n", 0 },
47
-	[FTP_PASS]	= { "PASS etherboot@etherboot.org\r\n", 0 },
48
-	[FTP_TYPE]	= { "TYPE I\r\n", 0 },
49
-	[FTP_PASV]	= { "PASV\r\n", 0 },
50
-	[FTP_RETR]	= { "RETR %s\r\n", ftp_string_offset ( filename ) },
51
-	[FTP_QUIT]	= { "QUIT\r\n", 0 },
52
-	[FTP_DONE]	= { "", 0 },
53
-};
54
-
55
-static inline struct ftp_request *
56
-tcp_to_ftp ( struct tcp_connection *conn ) {
59
+/**
60
+ * Get FTP request from control TCP connection
61
+ *
62
+ * @v conn		TCP connection
63
+ * @ret ftp		FTP request
64
+ */
65
+static inline struct ftp_request * tcp_to_ftp ( struct tcp_connection *conn ) {
57
 	return container_of ( conn, struct ftp_request, tcp );
66
 	return container_of ( conn, struct ftp_request, tcp );
58
 }
67
 }
59
 
68
 
69
+/**
70
+ * Mark FTP request as complete
71
+ *
72
+ * @v ftp		FTP request
73
+ * @v complete		Completion indicator
74
+ *
75
+ */
60
 static void ftp_complete ( struct ftp_request *ftp, int complete ) {
76
 static void ftp_complete ( struct ftp_request *ftp, int complete ) {
61
 	ftp->complete = complete;
77
 	ftp->complete = complete;
62
 	tcp_close ( &ftp->tcp_data );
78
 	tcp_close ( &ftp->tcp_data );
87
 }
103
 }
88
 
104
 
89
 /**
105
 /**
90
- * Handle a response from an FTP server
106
+ * Handle an FTP control channel response
91
  *
107
  *
92
  * @v ftp	FTP request
108
  * @v ftp	FTP request
93
  *
109
  *
132
 	ftp_complete ( ftp, -EPROTO );
148
 	ftp_complete ( ftp, -EPROTO );
133
 }
149
 }
134
 
150
 
151
+/**
152
+ * Handle new data arriving on FTP control channel
153
+ *
154
+ * @v conn	TCP connection
155
+ * @v data	New data
156
+ * @v len	Length of new data
157
+ *
158
+ * Data is collected until a complete line is received, at which point
159
+ * its information is passed to ftp_reply().
160
+ */
135
 static void ftp_newdata ( struct tcp_connection *conn,
161
 static void ftp_newdata ( struct tcp_connection *conn,
136
 			  void *data, size_t len ) {
162
 			  void *data, size_t len ) {
137
 	struct ftp_request *ftp = tcp_to_ftp ( conn );
163
 	struct ftp_request *ftp = tcp_to_ftp ( conn );
178
 	ftp->recvsize = recvsize;
204
 	ftp->recvsize = recvsize;
179
 }
205
 }
180
 
206
 
207
+/**
208
+ * Handle acknowledgement of data sent on FTP control channel
209
+ *
210
+ * @v conn	TCP connection
211
+ */
181
 static void ftp_acked ( struct tcp_connection *conn, size_t len ) {
212
 static void ftp_acked ( struct tcp_connection *conn, size_t len ) {
182
 	struct ftp_request *ftp = tcp_to_ftp ( conn );
213
 	struct ftp_request *ftp = tcp_to_ftp ( conn );
183
 	
214
 	
185
 	ftp->already_sent += len;
216
 	ftp->already_sent += len;
186
 }
217
 }
187
 
218
 
219
+/**
220
+ * Construct data to send on FTP control channel
221
+ *
222
+ * @v conn	TCP connection
223
+ */
188
 static void ftp_senddata ( struct tcp_connection *conn ) {
224
 static void ftp_senddata ( struct tcp_connection *conn ) {
189
 	struct ftp_request *ftp = tcp_to_ftp ( conn );
225
 	struct ftp_request *ftp = tcp_to_ftp ( conn );
190
 	const struct ftp_string *string;
226
 	const struct ftp_string *string;
200
 		   len - ftp->already_sent );
236
 		   len - ftp->already_sent );
201
 }
237
 }
202
 
238
 
203
-static void ftp_aborted ( struct tcp_connection *conn ) {
204
-	struct ftp_request *ftp = tcp_to_ftp ( conn );
205
-
206
-	ftp_complete ( ftp, -ECONNABORTED );
207
-}
208
-
209
-static void ftp_timedout ( struct tcp_connection *conn ) {
210
-	struct ftp_request *ftp = tcp_to_ftp ( conn );
211
-
212
-	ftp_complete ( ftp, -ETIMEDOUT );
213
-}
214
-
215
-static void ftp_closed ( struct tcp_connection *conn ) {
239
+/**
240
+ * Handle control channel being closed
241
+ *
242
+ * @v conn		TCP connection
243
+ *
244
+ * When the control channel is closed, the data channel must also be
245
+ * closed, if it is currently open.
246
+ */
247
+static void ftp_closed ( struct tcp_connection *conn, int status ) {
216
 	struct ftp_request *ftp = tcp_to_ftp ( conn );
248
 	struct ftp_request *ftp = tcp_to_ftp ( conn );
217
 
249
 
218
-	ftp_complete ( ftp, 1 );
250
+	ftp_complete ( ftp, status ? status : 1 );
219
 }
251
 }
220
 
252
 
253
+/** FTP control channel operations */
221
 static struct tcp_operations ftp_tcp_operations = {
254
 static struct tcp_operations ftp_tcp_operations = {
222
-	.aborted	= ftp_aborted,
223
-	.timedout	= ftp_timedout,
224
 	.closed		= ftp_closed,
255
 	.closed		= ftp_closed,
225
 	.acked		= ftp_acked,
256
 	.acked		= ftp_acked,
226
 	.newdata	= ftp_newdata,
257
 	.newdata	= ftp_newdata,
227
 	.senddata	= ftp_senddata,
258
 	.senddata	= ftp_senddata,
228
 };
259
 };
229
 
260
 
261
+/*****************************************************************************
262
+ *
263
+ * FTP control channel
264
+ *
265
+ */
266
+
267
+/**
268
+ * Get FTP request from data TCP connection
269
+ *
270
+ * @v conn		TCP connection
271
+ * @ret ftp		FTP request
272
+ */
230
 static inline struct ftp_request *
273
 static inline struct ftp_request *
231
 tcp_to_ftp_data ( struct tcp_connection *conn ) {
274
 tcp_to_ftp_data ( struct tcp_connection *conn ) {
232
 	return container_of ( conn, struct ftp_request, tcp_data );
275
 	return container_of ( conn, struct ftp_request, tcp_data );
233
 }
276
 }
234
 
277
 
235
-static void ftp_data_aborted ( struct tcp_connection *conn ) {
236
-	struct ftp_request *ftp = tcp_to_ftp_data ( conn );
237
-
238
-	ftp_complete ( ftp, -ECONNABORTED );
239
-}
240
-
241
-static void ftp_data_timedout ( struct tcp_connection *conn ) {
278
+/**
279
+ * Handle data channel being closed
280
+ *
281
+ * @v conn		TCP connection
282
+ *
283
+ * When the data channel is closed, the control channel should be left
284
+ * alone; the server will send a completion message via the control
285
+ * channel which we'll pick up.
286
+ *
287
+ * If the data channel is closed due to an error, we abort the request.
288
+ */
289
+static void ftp_data_closed ( struct tcp_connection *conn, int status ) {
242
 	struct ftp_request *ftp = tcp_to_ftp_data ( conn );
290
 	struct ftp_request *ftp = tcp_to_ftp_data ( conn );
243
 
291
 
244
-	ftp_complete ( ftp, -ETIMEDOUT );
292
+	if ( status )
293
+		ftp_complete ( ftp, status );
245
 }
294
 }
246
 
295
 
296
+/**
297
+ * Handle new data arriving on the FTP data channel
298
+ *
299
+ * @v conn	TCP connection
300
+ * @v data	New data
301
+ * @v len	Length of new data
302
+ *
303
+ * Data is handed off to the callback registered in the FTP request.
304
+ */
247
 static void ftp_data_newdata ( struct tcp_connection *conn,
305
 static void ftp_data_newdata ( struct tcp_connection *conn,
248
 			       void *data, size_t len ) {
306
 			       void *data, size_t len ) {
249
 	struct ftp_request *ftp = tcp_to_ftp_data ( conn );
307
 	struct ftp_request *ftp = tcp_to_ftp_data ( conn );
251
 	ftp->callback ( data, len );
309
 	ftp->callback ( data, len );
252
 }
310
 }
253
 
311
 
312
+/** FTP data channel operations */
254
 static struct tcp_operations ftp_data_tcp_operations = {
313
 static struct tcp_operations ftp_data_tcp_operations = {
255
-	.aborted	= ftp_data_aborted,
256
-	.timedout	= ftp_data_timedout,
314
+	.closed		= ftp_data_closed,
257
 	.newdata	= ftp_data_newdata,
315
 	.newdata	= ftp_data_newdata,
258
 };
316
 };
259
 
317
 

+ 3
- 19
src/net/tcp/hello.c View File

13
  * message (hello_request::message).  Any data received from the
13
  * message (hello_request::message).  Any data received from the
14
  * server will be passed to the callback function,
14
  * server will be passed to the callback function,
15
  * hello_request::callback(), and once the connection has been closed,
15
  * hello_request::callback(), and once the connection has been closed,
16
- * hello_request::complete will be set to 1.
16
+ * hello_request::complete will be set to a non-zero value.
17
  *
17
  *
18
  * To use this code, do something like:
18
  * To use this code, do something like:
19
  *
19
  *
49
 	return container_of ( conn, struct hello_request, tcp );
49
 	return container_of ( conn, struct hello_request, tcp );
50
 }
50
 }
51
 
51
 
52
-static void hello_aborted ( struct tcp_connection *conn ) {
52
+static void hello_closed ( struct tcp_connection *conn, int status ) {
53
 	struct hello_request *hello = tcp_to_hello ( conn );
53
 	struct hello_request *hello = tcp_to_hello ( conn );
54
 
54
 
55
-	printf ( "Connection aborted\n" );
56
-	hello->complete = 1;
57
-}
58
-
59
-static void hello_timedout ( struct tcp_connection *conn ) {
60
-	struct hello_request *hello = tcp_to_hello ( conn );
61
-
62
-	printf ( "Connection timed out\n" );
63
-	hello->complete = 1;
64
-}
65
-
66
-static void hello_closed ( struct tcp_connection *conn ) {
67
-	struct hello_request *hello = tcp_to_hello ( conn );
68
-
69
-	hello->complete = 1;
55
+	hello->complete = ( status ? status : 1 );
70
 }
56
 }
71
 
57
 
72
 static void hello_connected ( struct tcp_connection *conn ) {
58
 static void hello_connected ( struct tcp_connection *conn ) {
113
 }
99
 }
114
 
100
 
115
 static struct tcp_operations hello_tcp_operations = {
101
 static struct tcp_operations hello_tcp_operations = {
116
-	.aborted	= hello_aborted,
117
-	.timedout	= hello_timedout,
118
 	.closed		= hello_closed,
102
 	.closed		= hello_closed,
119
 	.connected	= hello_connected,
103
 	.connected	= hello_connected,
120
 	.acked		= hello_acked,
104
 	.acked		= hello_acked,

+ 1
- 13
src/proto/iscsi.c View File

251
 	return container_of ( conn, struct iscsi_session, tcp );
251
 	return container_of ( conn, struct iscsi_session, tcp );
252
 }
252
 }
253
 
253
 
254
-static void iscsi_aborted ( struct tcp_connection *conn ) {
255
-	struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
256
-
257
-}
258
-
259
-static void iscsi_timedout ( struct tcp_connection *conn ) {
260
-	struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
261
-
262
-}
263
-
264
-static void iscsi_closed ( struct tcp_connection *conn ) {
254
+static void iscsi_closed ( struct tcp_connection *conn, int status ) {
265
 	struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
255
 	struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
266
 
256
 
267
 }
257
 }
523
 
513
 
524
 /** iSCSI TCP operations */
514
 /** iSCSI TCP operations */
525
 static struct tcp_operations iscsi_tcp_operations = {
515
 static struct tcp_operations iscsi_tcp_operations = {
526
-	.aborted	= iscsi_aborted,
527
-	.timedout	= iscsi_timedout,
528
 	.closed		= iscsi_closed,
516
 	.closed		= iscsi_closed,
529
 	.connected	= iscsi_connected,
517
 	.connected	= iscsi_connected,
530
 	.acked		= iscsi_acked,
518
 	.acked		= iscsi_acked,

Loading…
Cancel
Save