Browse Source

Moved "hello world" protocol implementation out of prototester.c and into

the first standalong uIP-based protocol module.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
7e61f38799
3 changed files with 180 additions and 103 deletions
  1. 46
    0
      src/include/gpxe/hello.h
  2. 133
    0
      src/proto/hello.c
  3. 1
    103
      src/util/prototester.c

+ 46
- 0
src/include/gpxe/hello.h View File

@@ -0,0 +1,46 @@
1
+#ifndef _HELLO_H
2
+#define _HELLO_H
3
+
4
+/** @file
5
+ *
6
+ * "Hello world" TCP protocol
7
+ *
8
+ */
9
+
10
+#include <stdint.h>
11
+#include <gpxe/tcp.h>
12
+
13
+enum hello_state {
14
+	HELLO_SENDING_MESSAGE = 1,
15
+	HELLO_SENDING_ENDL,
16
+};
17
+
18
+/**
19
+ * A "hello world" request
20
+ *
21
+ */
22
+struct hello_request {
23
+	/** TCP connection for this request */
24
+	struct tcp_connection tcp;
25
+	/** Current state */
26
+	enum hello_state state;
27
+	/** Message to be transmitted */
28
+	const char *message;
29
+	/** Amount of message remaining to be transmitted */
30
+	size_t remaining;
31
+	/** Callback function
32
+	 *
33
+	 * @v data	Received data
34
+	 * @v len	Length of received data
35
+	 *
36
+	 * This function is called for all data received from the
37
+	 * remote server.
38
+	 */
39
+	void ( *callback ) ( char *data, size_t len );
40
+	/** Connection complete indicator */
41
+	int complete;
42
+};
43
+
44
+extern int hello_connect ( struct hello_request *hello );
45
+
46
+#endif

+ 133
- 0
src/proto/hello.c View File

@@ -0,0 +1,133 @@
1
+#include <stddef.h>
2
+#include <string.h>
3
+#include <vsprintf.h>
4
+#include <assert.h>
5
+#include <gpxe/hello.h>
6
+
7
+/** @file
8
+ *
9
+ * "Hello world" TCP protocol
10
+ *
11
+ * This file implements a trivial TCP-based protocol.  It connects to
12
+ * the server specified in hello_request::tcp and transmits a single
13
+ * message (hello_request::message).  Any data received from the
14
+ * server will be passed to the callback function,
15
+ * hello_request::callback(), and once the connection has been closed,
16
+ * hello_request::complete will be set to 1.
17
+ *
18
+ * To use this code, do something like:
19
+ *
20
+ * @code
21
+ *
22
+ *   static void my_callback ( char *data, size_t len ) {
23
+ *     ... process data ...
24
+ *   }
25
+ *
26
+ *   struct hello_request hello = {
27
+ *     .message = "hello world!",
28
+ *     .callback = my_callback,
29
+ *   };
30
+ *
31
+ *   hello.sin.sin_addr.s_addr = ... server IP address ...
32
+ *   hello.sin.sin_port = ... server port ...
33
+ *
34
+ *   hello_connect ( &hello );
35
+ *   while ( ! hello.completed ) {
36
+ *     run_tcpip();
37
+ *   }
38
+ *
39
+ * @endcode
40
+ *
41
+ * It's worth noting that this trivial protocol would be entirely
42
+ * adequate to implement a TCP-based version of TFTP; just use "RRQ
43
+ * <filename>" as the message.  Now, if only an appropriate server
44
+ * existed...
45
+ */
46
+
47
+static inline struct hello_request *
48
+tcp_to_hello ( struct tcp_connection *conn ) {
49
+	return container_of ( conn, struct hello_request, tcp );
50
+}
51
+
52
+static void hello_aborted ( struct tcp_connection *conn ) {
53
+	struct hello_request *hello = tcp_to_hello ( conn );
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;
70
+}
71
+
72
+static void hello_connected ( struct tcp_connection *conn ) {
73
+	struct hello_request *hello = tcp_to_hello ( conn );
74
+
75
+	hello->remaining = strlen ( hello->message );
76
+	hello->state = HELLO_SENDING_MESSAGE;
77
+}
78
+
79
+static void hello_acked ( struct tcp_connection *conn, size_t len ) {
80
+	struct hello_request *hello = tcp_to_hello ( conn );
81
+	
82
+	hello->message += len;
83
+	hello->remaining -= len;
84
+	if ( hello->remaining == 0 ) {
85
+		switch ( hello->state ) {
86
+		case HELLO_SENDING_MESSAGE:
87
+			hello->message = "\r\n";
88
+			hello->remaining = 2;
89
+			hello->state = HELLO_SENDING_ENDL;
90
+			break;
91
+		case HELLO_SENDING_ENDL:
92
+			/* Nothing to do once we've finished sending
93
+			 * the end-of-line indicator.
94
+			 */
95
+			break;
96
+		default:
97
+			assert ( 0 );
98
+		}
99
+	}
100
+}
101
+
102
+static void hello_newdata ( struct tcp_connection *conn, void *data,
103
+			    size_t len ) {
104
+	struct hello_request *hello = tcp_to_hello ( conn );
105
+
106
+	hello->callback ( data, len );
107
+}
108
+
109
+static void hello_senddata ( struct tcp_connection *conn ) {
110
+	struct hello_request *hello = tcp_to_hello ( conn );
111
+
112
+	tcp_send ( conn, hello->message, hello->remaining );
113
+}
114
+
115
+static struct tcp_operations hello_tcp_operations = {
116
+	.aborted	= hello_aborted,
117
+	.timedout	= hello_timedout,
118
+	.closed		= hello_closed,
119
+	.connected	= hello_connected,
120
+	.acked		= hello_acked,
121
+	.newdata	= hello_newdata,
122
+	.senddata	= hello_senddata,
123
+};
124
+
125
+/**
126
+ * Initiate a "hello world" connection
127
+ *
128
+ * @v hello	"Hello world" request
129
+ */
130
+int hello_connect ( struct hello_request *hello ) {
131
+	hello->tcp.tcp_op = &hello_tcp_operations;
132
+	return tcp_connect ( &hello->tcp );
133
+}

+ 1
- 103
src/util/prototester.c View File

@@ -12,6 +12,7 @@
12 12
 #include <assert.h>
13 13
 
14 14
 #include <gpxe/tcp.h>
15
+#include <gpxe/hello.h>
15 16
 
16 17
 typedef int irq_action_t;
17 18
 
@@ -251,109 +252,6 @@ static void hijack_disable ( struct hijack_device *hijack_dev ) {
251 252
  *
252 253
  */
253 254
 
254
-#include <stddef.h>
255
-#define container_of(ptr, type, member) ({                      \
256
-	const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
257
-	(type *)( (char *)__mptr - offsetof(type,member) );})
258
-
259
-enum hello_state {
260
-	HELLO_SENDING_MESSAGE = 1,
261
-	HELLO_SENDING_ENDL,
262
-};
263
-
264
-struct hello_request {
265
-	struct tcp_connection tcp;
266
-	const char *message;
267
-	enum hello_state state;
268
-	size_t remaining;
269
-	void ( *callback ) ( char *data, size_t len );
270
-	int complete;
271
-};
272
-
273
-static inline struct hello_request *
274
-tcp_to_hello ( struct tcp_connection *conn ) {
275
-	return container_of ( conn, struct hello_request, tcp );
276
-}
277
-
278
-static void hello_aborted ( struct tcp_connection *conn ) {
279
-	struct hello_request *hello = tcp_to_hello ( conn );
280
-
281
-	printf ( "Connection aborted\n" );
282
-	hello->complete = 1;
283
-}
284
-
285
-static void hello_timedout ( struct tcp_connection *conn ) {
286
-	struct hello_request *hello = tcp_to_hello ( conn );
287
-
288
-	printf ( "Connection timed out\n" );
289
-	hello->complete = 1;
290
-}
291
-
292
-static void hello_closed ( struct tcp_connection *conn ) {
293
-	struct hello_request *hello = tcp_to_hello ( conn );
294
-
295
-	hello->complete = 1;
296
-}
297
-
298
-static void hello_connected ( struct tcp_connection *conn ) {
299
-	struct hello_request *hello = tcp_to_hello ( conn );
300
-
301
-	printf ( "Connection established\n" );
302
-	hello->state = HELLO_SENDING_MESSAGE;
303
-}
304
-
305
-static void hello_acked ( struct tcp_connection *conn, size_t len ) {
306
-	struct hello_request *hello = tcp_to_hello ( conn );
307
-
308
-	hello->message += len;
309
-	hello->remaining -= len;
310
-	if ( hello->remaining == 0 ) {
311
-		switch ( hello->state ) {
312
-		case HELLO_SENDING_MESSAGE:
313
-			hello->state = HELLO_SENDING_ENDL;
314
-			hello->message = "\r\n";
315
-			hello->remaining = 2;
316
-			break;
317
-		case HELLO_SENDING_ENDL:
318
-			/* Nothing to do once we've finished sending
319
-			 * the end-of-line indicator.
320
-			 */
321
-			break;
322
-		default:
323
-			assert ( 0 );
324
-		}
325
-	}
326
-}
327
-
328
-static void hello_newdata ( struct tcp_connection *conn, void *data,
329
-			    size_t len ) {
330
-	struct hello_request *hello = tcp_to_hello ( conn );
331
-
332
-	hello->callback ( data, len );
333
-}
334
-
335
-static void hello_senddata ( struct tcp_connection *conn ) {
336
-	struct hello_request *hello = tcp_to_hello ( conn );
337
-
338
-	tcp_send ( conn, hello->message, hello->remaining );
339
-}
340
-
341
-static struct tcp_operations hello_tcp_operations = {
342
-	.aborted	= hello_aborted,
343
-	.timedout	= hello_timedout,
344
-	.closed		= hello_closed,
345
-	.connected	= hello_connected,
346
-	.acked		= hello_acked,
347
-	.newdata	= hello_newdata,
348
-	.senddata	= hello_senddata,
349
-};
350
-
351
-static int hello_connect ( struct hello_request *hello ) {
352
-	hello->tcp.tcp_op = &hello_tcp_operations;
353
-	hello->remaining = strlen ( hello->message );
354
-	return tcp_connect ( &hello->tcp );
355
-}
356
-
357 255
 struct hello_options {
358 256
 	struct sockaddr_in server;
359 257
 	const char *message;

Loading…
Cancel
Save