Browse Source

Now capable of sending "Hello world!" via TCP.

tags/v0.9.3
Michael Brown 19 years ago
parent
commit
0d506a5c6a
1 changed files with 212 additions and 49 deletions
  1. 212
    49
      src/util/prototester.c

+ 212
- 49
src/util/prototester.c View File

@@ -11,6 +11,7 @@
11 11
 #include <netinet/in.h>
12 12
 #include <arpa/inet.h>
13 13
 #include <getopt.h>
14
+#include <assert.h>
14 15
 
15 16
 typedef int irq_action_t;
16 17
 
@@ -253,11 +254,80 @@ static void hijack_disable ( struct hijack_device *hijack_dev ) {
253 254
 #include "../proto/uip/uip.h"
254 255
 #include "../proto/uip/uip_arp.h"
255 256
 
256
-void UIP_APPCALL ( void ) {
257
-	printf ( "appcall\n" );
257
+struct tcp_connection;
258
+
259
+struct tcp_operations {
260
+	void ( * aborted ) ( struct tcp_connection *conn );
261
+	void ( * timedout ) ( struct tcp_connection *conn );
262
+	void ( * closed ) ( struct tcp_connection *conn );
263
+	void ( * connected ) ( struct tcp_connection *conn );
264
+	void ( * acked ) ( struct tcp_connection *conn, size_t len );
265
+	void ( * newdata ) ( struct tcp_connection *conn );
266
+	void ( * senddata ) ( struct tcp_connection *conn );
267
+};
268
+
269
+struct tcp_connection {
270
+	struct sockaddr_in sin;
271
+	struct tcp_operations *tcp_op;
272
+};
273
+
274
+static int tcp_connect ( struct tcp_connection *conn ) {
275
+	struct uip_conn *uip_conn;
276
+	u16_t ipaddr[2];
277
+
278
+	assert ( conn->sin.sin_addr.s_addr != 0 );
279
+	assert ( conn->sin.sin_port != 0 );
280
+	assert ( conn->tcp_op != NULL );
281
+	assert ( sizeof ( uip_conn->appstate ) == sizeof ( conn ) );
282
+
283
+	* ( ( uint32_t * ) ipaddr ) = conn->sin.sin_addr.s_addr;
284
+	uip_conn = uip_connect ( ipaddr, conn->sin.sin_port );
285
+	if ( ! uip_conn )
286
+		return -1;
287
+
288
+	*( ( void ** ) uip_conn->appstate ) = conn;
289
+	return 0;
290
+}
291
+
292
+static void tcp_send ( struct tcp_connection *conn, const void *data,
293
+		       size_t len ) {
294
+	assert ( conn = *( ( void ** ) uip_conn->appstate ) );
295
+	uip_send ( ( void * ) data, len );
258 296
 }
259 297
 
260
-void udp_appcall ( void ) {
298
+static void tcp_close ( struct tcp_connection *conn ) {
299
+	assert ( conn = *( ( void ** ) uip_conn->appstate ) );
300
+	uip_close();
301
+}
302
+
303
+void uip_tcp_appcall ( void ) {
304
+	struct tcp_connection *conn = *( ( void ** ) uip_conn->appstate );
305
+	struct tcp_operations *op = conn->tcp_op;
306
+
307
+	assert ( conn->tcp_op->closed != NULL );
308
+	assert ( conn->tcp_op->connected != NULL );
309
+	assert ( conn->tcp_op->acked != NULL );
310
+	assert ( conn->tcp_op->newdata != NULL );
311
+	assert ( conn->tcp_op->senddata != NULL );
312
+
313
+	if ( uip_aborted() && op->aborted ) /* optional method */
314
+		op->aborted ( conn );
315
+	if ( uip_timedout() && op->timedout ) /* optional method */
316
+		op->timedout ( conn );
317
+	if ( uip_closed() && op->closed ) /* optional method */
318
+		op->closed ( conn );
319
+	if ( uip_connected() )
320
+		op->connected ( conn );
321
+	if ( uip_acked() )
322
+		op->acked ( conn, uip_conn->len );
323
+	if ( uip_newdata() )
324
+		op->newdata ( conn );
325
+	if ( uip_rexmit() || uip_newdata() || uip_acked() ||
326
+	     uip_connected() || uip_poll() )
327
+		op->senddata ( conn );
328
+}
329
+
330
+void uip_udp_appcall ( void ) {
261 331
 }
262 332
 
263 333
 static void init_tcpip ( void ) {
@@ -265,19 +335,18 @@ static void init_tcpip ( void ) {
265 335
 	uip_arp_init();
266 336
 }
267 337
 
338
+#define UIP_HLEN ( 40 + UIP_LLH_LEN )
339
+
268 340
 static void uip_transmit ( void ) {
269 341
 	uip_arp_out();
342
+	if ( uip_len > UIP_HLEN ) {
343
+		memcpy ( uip_buf + UIP_HLEN, ( void * ) uip_appdata,
344
+			 uip_len - UIP_HLEN );
345
+	}
270 346
 	netdev_transmit ( uip_buf, uip_len );
271 347
 	uip_len = 0;
272 348
 }
273 349
 
274
-static int tcp_connect ( struct sockaddr_in *sin ) {
275
-	u16_t ipaddr[2];
276
-
277
-	* ( ( uint32_t * ) ipaddr ) = sin->sin_addr.s_addr;
278
-	return uip_connect ( ipaddr, sin->sin_port ) ? 1 : 0;
279
-}
280
-
281 350
 static void run_tcpip ( void ) {
282 351
 	void *data;
283 352
 	size_t len;
@@ -308,59 +377,143 @@ static void run_tcpip ( void ) {
308 377
 
309 378
 /*****************************************************************************
310 379
  *
311
- * HTTP protocol tester
380
+ * "Hello world" protocol tester
312 381
  *
313 382
  */
314 383
 
315
-struct http_request {
316
-	struct sockaddr_in sin;
317
-	const char *filename;
318
-	void ( *callback ) ( struct http_request *http );
384
+#include <stddef.h>
385
+#define container_of(ptr, type, member) ({                      \
386
+	const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
387
+	(type *)( (char *)__mptr - offsetof(type,member) );})
388
+
389
+enum hello_state {
390
+	HELLO_SENDING_MESSAGE = 0,
391
+	HELLO_SENDING_ENDL,
392
+};
393
+
394
+struct hello_request {
395
+	struct tcp_connection tcp;
396
+	const char *message;
397
+	enum hello_state state;
398
+	int remaining;
399
+	void ( *callback ) ( struct hello_request *hello );
319 400
 	int complete;
320 401
 };
321 402
 
322
-static int http_get ( struct http_request *http ) {
323
-	return tcp_connect ( &http->sin );
403
+static inline struct hello_request *
404
+tcp_to_hello ( struct tcp_connection *conn ) {
405
+	return container_of ( conn, struct hello_request, tcp );
324 406
 }
325 407
 
408
+static void hello_aborted ( struct tcp_connection *conn ) {
409
+	struct hello_request *hello = tcp_to_hello ( conn );
326 410
 
411
+	printf ( "Connection aborted\n" );
412
+	hello->complete = 1;
413
+}
414
+
415
+static void hello_timedout ( struct tcp_connection *conn ) {
416
+	struct hello_request *hello = tcp_to_hello ( conn );
417
+
418
+	printf ( "Connection timed out\n" );
419
+	hello->complete = 1;
420
+}
421
+
422
+static void hello_closed ( struct tcp_connection *conn ) {
423
+	struct hello_request *hello = tcp_to_hello ( conn );
424
+
425
+	hello->complete = 1;
426
+}
427
+
428
+static void hello_connected ( struct tcp_connection *conn ) {
429
+	struct hello_request *hello = tcp_to_hello ( conn );
430
+}
431
+
432
+static void hello_acked ( struct tcp_connection *conn, size_t len ) {
433
+	struct hello_request *hello = tcp_to_hello ( conn );
434
+
435
+	hello->message += len;
436
+	hello->remaining -= len;
437
+	if ( hello->remaining <= 0 ) {
438
+		switch ( hello->state ) {
439
+		case HELLO_SENDING_MESSAGE:
440
+			hello->state = HELLO_SENDING_ENDL;
441
+			hello->message = "\r\n";
442
+			hello->remaining = 2;
443
+			break;
444
+		case HELLO_SENDING_ENDL:
445
+			tcp_close ( conn );
446
+			break;
447
+		default:
448
+			assert ( 0 );
449
+		}
450
+	}
451
+}
452
+
453
+static void hello_newdata ( struct tcp_connection *conn ) {
454
+	struct hello_request *hello = tcp_to_hello ( conn );
455
+}
456
+
457
+static void hello_senddata ( struct tcp_connection *conn ) {
458
+	struct hello_request *hello = tcp_to_hello ( conn );
459
+
460
+	tcp_send ( conn, hello->message, hello->remaining );
461
+}
327 462
 
463
+static struct tcp_operations hello_tcp_operations = {
464
+	.aborted	= hello_aborted,
465
+	.timedout	= hello_timedout,
466
+	.closed		= hello_closed,
467
+	.connected	= hello_connected,
468
+	.acked		= hello_acked,
469
+	.newdata	= hello_newdata,
470
+	.senddata	= hello_senddata,
471
+};
472
+
473
+static int hello_connect ( struct hello_request *hello ) {
474
+	hello->tcp.tcp_op = &hello_tcp_operations;
475
+	hello->remaining = strlen ( hello->message );
476
+	return tcp_connect ( &hello->tcp );
477
+}
328 478
 
329
-struct http_options {
479
+struct hello_options {
330 480
 	struct sockaddr_in server;
331
-	char *filename;
481
+	const char *message;
332 482
 };
333 483
 
334
-static void http_usage ( char **argv ) {
484
+static void hello_usage ( char **argv ) {
335 485
 	fprintf ( stderr,
336
-		  "Usage: %s [global options] http [http-specific options]\n"
486
+		  "Usage: %s [global options] hello [hello-specific options]\n"
337 487
 		  "\n"
338
-		  "http-specific options:\n"
488
+		  "hello-specific options:\n"
339 489
 		  "  -h|--host              Host IP address\n"
340
-		  "  -f|--file              Filename\n",
490
+		  "  -p|--port              Port number\n"
491
+		  "  -m|--message           Message to send\n",
341 492
 		  argv[0] );
342 493
 }
343 494
 
344
-static int http_parse_options ( int argc, char **argv,
345
-				struct http_options *options ) {
495
+static int hello_parse_options ( int argc, char **argv,
496
+				 struct hello_options *options ) {
346 497
 	static struct option long_options[] = {
347 498
 		{ "host", 1, NULL, 'h' },
348
-		{ "file", 1, NULL, 'f' },
499
+		{ "port", 1, NULL, 'p' },
500
+		{ "message", 1, NULL, 'm' },
349 501
 		{ },
350 502
 	};
351 503
 	int c;
504
+	char *endptr;
352 505
 
353 506
 	/* Set default options */
354 507
 	memset ( options, 0, sizeof ( *options ) );
355 508
 	inet_aton ( "192.168.0.1", &options->server.sin_addr );
356 509
 	options->server.sin_port = htons ( 80 );
357
-	options->filename = "index.html";
510
+	options->message = "Hello world!";
358 511
 
359 512
 	/* Parse command-line options */
360 513
 	while ( 1 ) {
361 514
 		int option_index = 0;
362 515
 		
363
-		c = getopt_long ( argc, argv, "h:f:", long_options,
516
+		c = getopt_long ( argc, argv, "h:p:", long_options,
364 517
 				  &option_index );
365 518
 		if ( c < 0 )
366 519
 			break;
@@ -374,8 +527,17 @@ static int http_parse_options ( int argc, char **argv,
374 527
 				return -1;
375 528
 			}
376 529
 			break;
377
-		case 'f':
378
-			options->filename = optarg;
530
+		case 'p':
531
+			options->server.sin_port =
532
+				htons ( strtoul ( optarg, &endptr, 0 ) );
533
+			if ( *endptr != '\0' ) {
534
+				fprintf ( stderr, "Invalid port %s\n",
535
+					  optarg );
536
+				return -1;
537
+			}
538
+			break;
539
+		case 'm':
540
+			options->message = optarg;
379 541
 			break;
380 542
 		case '?':
381 543
 			/* Unrecognised option */
@@ -388,36 +550,37 @@ static int http_parse_options ( int argc, char **argv,
388 550
 
389 551
 	/* Check there are no remaining arguments */
390 552
 	if ( optind != argc ) {
391
-		http_usage ( argv );
553
+		hello_usage ( argv );
392 554
 		return -1;
393 555
 	}
394 556
 	
395 557
 	return optind;
396 558
 }
397 559
 
398
-static void test_http_callback ( struct http_request *http ) {
560
+static void test_hello_callback ( struct hello_request *hello ) {
399 561
 	
400 562
 }
401 563
 
402
-static int test_http ( int argc, char **argv ) {
403
-	struct http_options options;
404
-	struct http_request http;
564
+static int test_hello ( int argc, char **argv ) {
565
+	struct hello_options options;
566
+	struct hello_request hello;
405 567
 
406
-	/* Parse http-specific options */
407
-	if ( http_parse_options ( argc, argv, &options ) < 0 )
568
+	/* Parse hello-specific options */
569
+	if ( hello_parse_options ( argc, argv, &options ) < 0 )
408 570
 		return -1;
409 571
 
410
-	/* Construct http request */
411
-	memset ( &http, 0, sizeof ( http ) );
412
-	http.filename = options.filename;
413
-	http.sin = options.server;
414
-	http.callback = test_http_callback;
415
-	fprintf ( stderr, "http fetching http://%s/%s\n",
416
-		  inet_ntoa ( http.sin.sin_addr ), http.filename );
417
-
418
-	/* Issue http request and run to completion */
419
-	http_get ( &http );
420
-	while ( ! http.complete ) {
572
+	/* Construct hello request */
573
+	memset ( &hello, 0, sizeof ( hello ) );
574
+	hello.tcp.sin = options.server;
575
+	hello.message = options.message;
576
+	hello.callback = test_hello_callback;
577
+	fprintf ( stderr, "Saying \"%s\" to %s:%d\n", hello.message,
578
+		  inet_ntoa ( hello.tcp.sin.sin_addr ),
579
+		  ntohs ( hello.tcp.sin.sin_port ) );
580
+
581
+	/* Issue hello request and run to completion */
582
+	hello_connect ( &hello );
583
+	while ( ! hello.complete ) {
421 584
 		run_tcpip ();
422 585
 	}
423 586
 
@@ -436,7 +599,7 @@ struct protocol_test {
436 599
 };
437 600
 
438 601
 static struct protocol_test tests[] = {
439
-	{ "http", test_http },
602
+	{ "hello", test_hello },
440 603
 };
441 604
 
442 605
 #define NUM_TESTS ( sizeof ( tests ) / sizeof ( tests[0] ) )

Loading…
Cancel
Save