xref: /haiku/src/tests/system/network/tcp_shell/tcp_shell.cpp (revision 8f4ba40520809f2c62fa05adb4e824bc05624934)
1 /*
2  * Copyright 2006-2023, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  */
8 
9 
10 #include "argv.h"
11 #include "tcp.h"
12 #include "pcap.h"
13 #include "utility.h"
14 
15 #include <AutoDeleter.h>
16 #include <NetBufferUtilities.h>
17 #include <Referenceable.h>
18 #include <net_buffer.h>
19 #include <net_datalink.h>
20 #include <net_protocol.h>
21 #include <net_socket.h>
22 #include <net_stack.h>
23 #include <slab/Slab.h>
24 #include <util/AutoLock.h>
25 #include <util/DoublyLinkedList.h>
26 
27 #include <KernelExport.h>
28 #include <Select.h>
29 #include <module.h>
30 #include <Locker.h>
31 
32 #include <netinet/in.h>
33 #include <netinet/ip.h>
34 
35 #include <ctype.h>
36 #include <errno.h>
37 #include <new>
38 #include <set>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 
44 struct context {
45 	BLocker		lock;
46 	sem_id		wait_sem;
47 	struct list list;
48 	net_route	route;
49 	bool		server;
50 	thread_id	thread;
51 };
52 
53 struct cmd_entry {
54 	const char*	name;
55 	void	(*func)(int argc, char **argv);
56 	const char*	help;
57 };
58 
59 
60 struct net_socket_private;
61 typedef DoublyLinkedList<net_socket_private> SocketList;
62 
63 struct net_socket_private : net_socket,
64 		DoublyLinkedListLinkImpl<net_socket_private> {
65 	struct net_socket		*parent;
66 
67 	team_id					owner;
68 	uint32					max_backlog;
69 	uint32					child_count;
70 	SocketList				pending_children;
71 	SocketList				connected_children;
72 
73 	struct select_sync_pool	*select_pool;
74 	mutex					lock;
75 };
76 
77 
78 struct InterfaceAddress : DoublyLinkedListLinkImpl<InterfaceAddress>,
79 		net_interface_address, BReferenceable {
80 };
81 
82 
83 extern "C" status_t _add_builtin_module(module_info *info);
84 extern "C" status_t _get_builtin_dependencies(void);
85 extern bool gDebugOutputEnabled;
86 	// from libkernelland_emu.so
87 
88 extern struct net_buffer_module_info gNetBufferModule;
89 	// from net_buffer.cpp
90 extern net_address_module_info gIPv4AddressModule;
91 	// from ipv4_address.cpp
92 extern module_info *modules[];
93 	// from tcp.cpp
94 
95 
96 extern struct net_protocol_module_info gDomainModule;
97 struct InterfaceAddress gInterfaceAddress;
98 extern struct net_socket_module_info gNetSocketModule;
99 struct net_protocol_module_info *gTCPModule;
100 struct net_socket *gServerSocket, *gClientSocket;
101 static struct context sClientContext, sServerContext;
102 
103 static int32 sPacketNumber = 1;
104 static double sRandomDrop = 0.0;
105 static std::set<uint32> sDropList;
106 static bigtime_t sRoundTripTime = 0;
107 static bool sIncreasingRoundTrip = false;
108 static bool sRandomRoundTrip = false;
109 static void (*sPacketMonitor)(net_buffer *, int32, bool) = NULL;
110 static int sPcapFD = -1;
111 static bigtime_t sStartTime;
112 static double sRandomReorder = 0.0;
113 static std::set<uint32> sReorderList;
114 static bool sSimultaneousConnect = false;
115 static bool sSimultaneousClose = false;
116 static bool sServerActiveClose = false;
117 
118 static struct net_domain sDomain = {
119 	"ipv4",
120 	AF_INET,
121 
122 	&gDomainModule,
123 	&gIPv4AddressModule
124 };
125 
126 
127 static bool
is_server(const sockaddr * addr)128 is_server(const sockaddr* addr)
129 {
130 	return ((sockaddr_in*)addr)->sin_port == htons(1024);
131 }
132 
133 
134 static uint8
tcp_segment_flags(net_buffer * buffer)135 tcp_segment_flags(net_buffer* buffer)
136 {
137 	NetBufferHeaderReader<tcp_header> bufferHeader(buffer);
138 	if (bufferHeader.Status() < B_OK)
139 		return bufferHeader.Status();
140 
141 	tcp_header &header = bufferHeader.Data();
142 	return header.flags;
143 }
144 
145 
146 static bool
is_syn(net_buffer * buffer)147 is_syn(net_buffer* buffer)
148 {
149 	return (tcp_segment_flags(buffer) & TCP_FLAG_SYNCHRONIZE) != 0;
150 }
151 
152 
153 static bool
is_fin(net_buffer * buffer)154 is_fin(net_buffer* buffer)
155 {
156 	return (tcp_segment_flags(buffer) & TCP_FLAG_FINISH) != 0;
157 }
158 
159 
160 //	#pragma mark - stack
161 
162 
163 status_t
std_ops(int32,...)164 std_ops(int32, ...)
165 {
166 	return B_OK;
167 }
168 
169 
170 net_domain *
get_domain(int family)171 get_domain(int family)
172 {
173 	return &sDomain;
174 }
175 
176 
177 status_t
register_domain_protocols(int family,int type,int protocol,...)178 register_domain_protocols(int family, int type, int protocol, ...)
179 {
180 	return B_OK;
181 }
182 
183 
184 status_t
register_domain_datalink_protocols(int family,int type,...)185 register_domain_datalink_protocols(int family, int type, ...)
186 {
187 	return B_OK;
188 }
189 
190 
191 static status_t
register_domain_receiving_protocol(int family,int type,const char * moduleName)192 register_domain_receiving_protocol(int family, int type, const char *moduleName)
193 {
194 	return B_OK;
195 }
196 
197 
198 static bool
dummy_is_syscall(void)199 dummy_is_syscall(void)
200 {
201 	return false;
202 }
203 
204 
205 static bool
dummy_is_restarted_syscall(void)206 dummy_is_restarted_syscall(void)
207 {
208 	return false;
209 }
210 
211 
212 static void
dummy_store_syscall_restart_timeout(bigtime_t timeout)213 dummy_store_syscall_restart_timeout(bigtime_t timeout)
214 {
215 }
216 
217 
218 static net_stack_module_info gNetStackModule = {
219 	{
220 		NET_STACK_MODULE_NAME,
221 		0,
222 		std_ops
223 	},
224 	NULL, // register_domain,
225 	NULL, // unregister_domain,
226 	get_domain,
227 
228 	register_domain_protocols,
229 	register_domain_datalink_protocols,
230 	register_domain_receiving_protocol,
231 
232 	NULL, // get_domain_receiving_protocol,
233 	NULL, // put_domain_receiving_protocol,
234 
235 	NULL, // register_device_deframer,
236 	NULL, // unregister_device_deframer,
237 	NULL, // register_domain_device_handler,
238 	NULL, // register_device_handler,
239 	NULL, // unregister_device_handler,
240 	NULL, // register_device_monitor,
241 	NULL, // unregister_device_monitor,
242 	NULL, // device_link_changed,
243 	NULL, // device_removed,
244 	NULL, // device_enqueue_buffer,
245 
246 	notify_socket,
247 
248 	checksum,
249 
250 	init_fifo,
251 	uninit_fifo,
252 	fifo_enqueue_buffer,
253 	fifo_dequeue_buffer,
254 	clear_fifo,
255 	fifo_socket_enqueue_buffer,
256 
257 	init_timer,
258 	set_timer,
259 	cancel_timer,
260 	wait_for_timer,
261 	is_timer_active,
262 	is_timer_running,
263 
264 	dummy_is_syscall,
265 	dummy_is_restarted_syscall,
266 	dummy_store_syscall_restart_timeout,
267 	NULL, // restore_syscall_restart_timeout
268 
269 	// ancillary data is not used by TCP
270 };
271 
272 
273 //	#pragma mark - socket
274 
275 
276 status_t
socket_create(int family,int type,int protocol,net_socket ** _socket)277 socket_create(int family, int type, int protocol, net_socket **_socket)
278 {
279 	net_protocol* domainProtocol;
280 
281 	struct net_socket_private *socket = new (std::nothrow) net_socket_private;
282 	if (socket == NULL)
283 		return B_NO_MEMORY;
284 
285 	memset(socket, 0, sizeof(net_socket));
286 	socket->family = family;
287 	socket->type = type;
288 	socket->protocol = protocol;
289 
290 	mutex_init(&socket->lock, "socket");
291 
292 	// set defaults (may be overridden by the protocols)
293 	socket->send.buffer_size = 65535;
294 	socket->send.low_water_mark = 1;
295 	socket->send.timeout = B_INFINITE_TIMEOUT;
296 	socket->receive.buffer_size = 65535;
297 	socket->receive.low_water_mark = 1;
298 	socket->receive.timeout = B_INFINITE_TIMEOUT;
299 
300 	socket->first_protocol = gTCPModule->init_protocol(socket);
301 	if (socket->first_protocol == NULL) {
302 		fprintf(stderr, "tcp_tester: cannot create protocol\n");
303 		mutex_destroy(&socket->lock);
304 		delete socket;
305 		return B_ERROR;
306 	}
307 
308 	socket->first_info = gTCPModule;
309 
310 	domainProtocol = new net_protocol;
311 	domainProtocol->module = &gDomainModule;
312 	domainProtocol->socket = socket;
313 
314 	socket->first_protocol->next = domainProtocol;
315 	socket->first_protocol->module = gTCPModule;
316 	socket->first_protocol->socket = socket;
317 
318 	*_socket = socket;
319 	return B_OK;
320 }
321 
322 
323 void
socket_delete(net_socket * _socket)324 socket_delete(net_socket *_socket)
325 {
326 	net_socket_private *socket = (net_socket_private *)_socket;
327 
328 	if (socket->parent != NULL)
329 		panic("socket still has a parent!");
330 
331 	socket->first_info->uninit_protocol(socket->first_protocol);
332 	mutex_destroy(&socket->lock);
333 	delete socket;
334 }
335 
336 
337 int
socket_accept(net_socket * socket,struct sockaddr * address,socklen_t * _addressLength,net_socket ** _acceptedSocket)338 socket_accept(net_socket *socket, struct sockaddr *address,
339 	socklen_t *_addressLength, net_socket **_acceptedSocket)
340 {
341 	net_socket *accepted;
342 	status_t status = socket->first_info->accept(socket->first_protocol,
343 		&accepted);
344 	if (status < B_OK)
345 		return status;
346 
347 	if (address && *_addressLength > 0) {
348 		memcpy(address, &accepted->peer, min_c(*_addressLength,
349 			accepted->peer.ss_len));
350 		*_addressLength = accepted->peer.ss_len;
351 	}
352 
353 	*_acceptedSocket = accepted;
354 	return B_OK;
355 }
356 
357 
358 int
socket_bind(net_socket * socket,const struct sockaddr * address,socklen_t addressLength)359 socket_bind(net_socket *socket, const struct sockaddr *address, socklen_t addressLength)
360 {
361 	sockaddr empty;
362 	if (address == NULL) {
363 		// special - try to bind to an empty address, like INADDR_ANY
364 		memset(&empty, 0, sizeof(sockaddr));
365 		empty.sa_len = sizeof(sockaddr);
366 		empty.sa_family = socket->family;
367 
368 		address = &empty;
369 		addressLength = sizeof(sockaddr);
370 	}
371 
372 	if (socket->address.ss_len != 0) {
373 		status_t status = socket->first_info->unbind(socket->first_protocol,
374 			(sockaddr *)&socket->address);
375 		if (status < B_OK)
376 			return status;
377 	}
378 
379 	memcpy(&socket->address, address, sizeof(sockaddr));
380 
381 	status_t status = socket->first_info->bind(socket->first_protocol,
382 		(sockaddr *)address);
383 	if (status < B_OK) {
384 		// clear address again, as binding failed
385 		socket->address.ss_len = 0;
386 	}
387 
388 	return status;
389 }
390 
391 
392 int
socket_connect(net_socket * socket,const struct sockaddr * address,socklen_t addressLength)393 socket_connect(net_socket *socket, const struct sockaddr *address, socklen_t addressLength)
394 {
395 	if (address == NULL || addressLength == 0)
396 		return ENETUNREACH;
397 
398 	if (socket->address.ss_len == 0) {
399 		// try to bind first
400 		status_t status = socket_bind(socket, NULL, 0);
401 		if (status < B_OK)
402 			return status;
403 	}
404 
405 	return socket->first_info->connect(socket->first_protocol, address);
406 }
407 
408 
409 int
socket_listen(net_socket * socket,int backlog)410 socket_listen(net_socket *socket, int backlog)
411 {
412 	status_t status = socket->first_info->listen(socket->first_protocol, backlog);
413 	if (status == B_OK)
414 		socket->options |= SO_ACCEPTCONN;
415 
416 	return status;
417 }
418 
419 
420 ssize_t
socket_send(net_socket * socket,const void * data,size_t length,int flags)421 socket_send(net_socket *socket, const void *data, size_t length, int flags)
422 {
423 	if (socket->peer.ss_len == 0)
424 		return EDESTADDRREQ;
425 
426 	if (socket->address.ss_len == 0) {
427 		// try to bind first
428 		status_t status = socket_bind(socket, NULL, 0);
429 		if (status < B_OK)
430 			return status;
431 	}
432 
433 	// TODO: useful, maybe even computed header space!
434 	net_buffer *buffer = gNetBufferModule.create(256);
435 	if (buffer == NULL)
436 		return ENOBUFS;
437 
438 	// copy data into buffer
439 	if (gNetBufferModule.append(buffer, data, length) < B_OK) {
440 		gNetBufferModule.free(buffer);
441 		return ENOBUFS;
442 	}
443 
444 	buffer->msg_flags = flags;
445 	memcpy(buffer->source, &socket->address, socket->address.ss_len);
446 	memcpy(buffer->destination, &socket->peer, socket->peer.ss_len);
447 
448 	status_t status = socket->first_info->send_data(socket->first_protocol, buffer);
449 	if (status < B_OK) {
450 		gNetBufferModule.free(buffer);
451 		return status;
452 	}
453 
454 	return length;
455 }
456 
457 
458 ssize_t
socket_recv(net_socket * socket,void * data,size_t length,int flags)459 socket_recv(net_socket *socket, void *data, size_t length, int flags)
460 {
461 	net_buffer *buffer;
462 	ssize_t status = socket->first_info->read_data(
463 		socket->first_protocol, length, flags, &buffer);
464 	if (status < B_OK)
465 		return status;
466 
467 	// if 0 bytes we're received, no buffer will be created
468 	if (buffer == NULL)
469 		return 0;
470 
471 	ssize_t bytesReceived = buffer->size;
472 	gNetBufferModule.read(buffer, 0, data, bytesReceived);
473 	gNetBufferModule.free(buffer);
474 
475 	return bytesReceived;
476 }
477 
478 
479 bool
socket_acquire(net_socket * _socket)480 socket_acquire(net_socket* _socket)
481 {
482 	return true;
483 }
484 
485 
486 bool
socket_release(net_socket * _socket)487 socket_release(net_socket* _socket)
488 {
489 	return true;
490 }
491 
492 
493 status_t
socket_spawn_pending(net_socket * _parent,net_socket ** _socket)494 socket_spawn_pending(net_socket *_parent, net_socket **_socket)
495 {
496 	net_socket_private *parent = (net_socket_private *)_parent;
497 
498 	MutexLocker locker(parent->lock);
499 
500 	// We actually accept more pending connections to compensate for those
501 	// that never complete, and also make sure at least a single connection
502 	// can always be accepted
503 	if (parent->child_count > 3 * parent->max_backlog / 2)
504 		return ENOBUFS;
505 
506 	net_socket_private *socket;
507 	status_t status = socket_create(parent->family, parent->type, parent->protocol,
508 		(net_socket **)&socket);
509 	if (status < B_OK)
510 		return status;
511 
512 	// inherit parent's properties
513 	socket->send = parent->send;
514 	socket->receive = parent->receive;
515 	socket->options = parent->options & ~SO_ACCEPTCONN;
516 	socket->linger = parent->linger;
517 	memcpy(&socket->address, &parent->address, parent->address.ss_len);
518 	memcpy(&socket->peer, &parent->peer, parent->peer.ss_len);
519 
520 	// add to the parent's list of pending connections
521 	parent->pending_children.Add(socket);
522 	socket->parent = parent;
523 	parent->child_count++;
524 
525 	*_socket = socket;
526 	return B_OK;
527 }
528 
529 
530 status_t
socket_dequeue_connected(net_socket * _parent,net_socket ** _socket)531 socket_dequeue_connected(net_socket *_parent, net_socket **_socket)
532 {
533 	net_socket_private *parent = (net_socket_private *)_parent;
534 
535 	mutex_lock(&parent->lock);
536 
537 	net_socket_private *socket = parent->connected_children.RemoveHead();
538 	if (socket != NULL) {
539 		socket->parent = NULL;
540 		parent->child_count--;
541 		*_socket = socket;
542 	}
543 
544 	mutex_unlock(&parent->lock);
545 	return socket != NULL ? B_OK : B_ENTRY_NOT_FOUND;
546 }
547 
548 
549 ssize_t
socket_count_connected(net_socket * _parent)550 socket_count_connected(net_socket *_parent)
551 {
552 	net_socket_private *parent = (net_socket_private *)_parent;
553 
554 	MutexLocker _(parent->lock);
555 
556 	return parent->connected_children.Count();
557 }
558 
559 
560 status_t
socket_set_max_backlog(net_socket * _socket,uint32 backlog)561 socket_set_max_backlog(net_socket *_socket, uint32 backlog)
562 {
563 	net_socket_private *socket = (net_socket_private *)_socket;
564 
565 	// we enforce an upper limit of connections waiting to be accepted
566 	if (backlog > 256)
567 		backlog = 256;
568 
569 	mutex_lock(&socket->lock);
570 
571 	// first remove the pending connections, then the already connected ones as needed
572 	net_socket_private *child;
573 	while (socket->child_count > backlog
574 		&& (child = socket->pending_children.RemoveTail()) != NULL) {
575 		child->parent = NULL;
576 		socket->child_count--;
577 	}
578 	while (socket->child_count > backlog
579 		&& (child = socket->connected_children.RemoveTail()) != NULL) {
580 		child->parent = NULL;
581 		socket_delete(child);
582 		socket->child_count--;
583 	}
584 
585 	socket->max_backlog = backlog;
586 	mutex_unlock(&socket->lock);
587 	return B_OK;
588 }
589 
590 
591 bool
socket_has_parent(net_socket * _socket)592 socket_has_parent(net_socket* _socket)
593 {
594 	net_socket_private* socket = (net_socket_private*)_socket;
595 	return socket->parent != NULL;
596 }
597 
598 
599 status_t
socket_connected(net_socket * socket)600 socket_connected(net_socket *socket)
601 {
602 	net_socket_private *socket_private = (net_socket_private *)socket;
603 	net_socket_private *parent = (net_socket_private *)socket_private->parent;
604 	if (parent == NULL)
605 		return B_BAD_VALUE;
606 
607 	mutex_lock(&parent->lock);
608 
609 	parent->pending_children.Remove(socket_private);
610 	parent->connected_children.Add(socket_private);
611 
612 	mutex_unlock(&parent->lock);
613 	return B_OK;
614 }
615 
616 
617 status_t
socket_notify(net_socket * _socket,uint8 event,int32 value)618 socket_notify(net_socket *_socket, uint8 event, int32 value)
619 {
620 	net_socket_private *socket = (net_socket_private *)_socket;
621 
622 	mutex_lock(&socket->lock);
623 
624 	bool notify = true;
625 
626 	switch (event) {
627 		case B_SELECT_READ:
628 		{
629 			if ((ssize_t)socket->receive.low_water_mark > value && value >= B_OK)
630 				notify = false;
631 			break;
632 		}
633 		case B_SELECT_WRITE:
634 		{
635 			if ((ssize_t)socket->send.low_water_mark > value && value >= B_OK)
636 				notify = false;
637 			break;
638 		}
639 		case B_SELECT_ERROR:
640 			socket->error = value;
641 			break;
642 	}
643 
644 	if (notify)
645 		;
646 
647 	mutex_unlock(&socket->lock);
648 	return B_OK;
649 }
650 
651 
652 net_socket_module_info gNetSocketModule = {
653 	{
654 		NET_SOCKET_MODULE_NAME,
655 		0,
656 		std_ops
657 	},
658 	NULL, // open,
659 	NULL, // close,
660 	NULL, // free,
661 
662 	NULL, // control,
663 
664 	NULL, // read_avail,
665 	NULL, // send_avail,
666 
667 	NULL, // send_data,
668 	NULL, // receive_data,
669 
670 	NULL, // get_option,
671 	NULL, // set_option,
672 	NULL, // get_next_stat,
673 
674 	socket_acquire,
675 	socket_release,
676 
677 	// connections
678 	socket_spawn_pending,
679 	socket_dequeue_connected,
680 	socket_count_connected,
681 	socket_set_max_backlog,
682 	socket_has_parent,
683 	socket_connected,
684 	NULL, // set_aborted
685 
686 	// notifications
687 	NULL, // request_notification,
688 	NULL, // cancel_notification,
689 	socket_notify,
690 
691 	// standard socket API
692 	NULL, // accept,
693 	NULL, // bind,
694 	NULL, // connect,
695 	NULL, // getpeername,
696 	NULL, // getsockname,
697 	NULL, // getsockopt,
698 	NULL, // listen,
699 	NULL, // receive,
700 	NULL, // send,
701 	NULL, // setsockopt,
702 	NULL, // shutdown,
703 	NULL, // socketpair
704 };
705 
706 
707 //	#pragma mark - protocol
708 
709 
710 net_protocol*
init_protocol(net_socket ** _socket)711 init_protocol(net_socket** _socket)
712 {
713 	net_socket *socket;
714 	status_t status = socket_create(AF_INET, SOCK_STREAM, IPPROTO_TCP, &socket);
715 	if (status < B_OK)
716 		return NULL;
717 
718 	status = socket->first_info->open(socket->first_protocol);
719 	if (status < B_OK) {
720 		fprintf(stderr, "tcp_tester: cannot open client: %s\n", strerror(status));
721 		socket_delete(socket);
722 		return NULL;
723 	}
724 
725 	*_socket = socket;
726 	return socket->first_protocol;
727 }
728 
729 
730 void
close_protocol(net_protocol * protocol)731 close_protocol(net_protocol* protocol)
732 {
733 	gTCPModule->close(protocol);
734 	if (gTCPModule->free(protocol) == B_OK)
735 		gTCPModule->uninit_protocol(protocol);
736 		//socket_delete(protocol->socket);
737 }
738 
739 
740 //	#pragma mark - datalink
741 
742 
743 status_t
datalink_send_data(struct net_route * route,net_buffer * buffer)744 datalink_send_data(struct net_route *route, net_buffer *buffer)
745 {
746 	struct context* context = (struct context*)route->gateway;
747 
748 	buffer->interface_address = &gInterfaceAddress;
749 	gInterfaceAddress.AcquireReference();
750 
751 	context->lock.Lock();
752 	list_add_item(&context->list, buffer);
753 	context->lock.Unlock();
754 
755 	release_sem(context->wait_sem);
756 	return B_OK;
757 }
758 
759 
760 status_t
datalink_send_datagram(net_protocol * protocol,net_domain * domain,net_buffer * buffer)761 datalink_send_datagram(net_protocol *protocol, net_domain *domain,
762 	net_buffer *buffer)
763 {
764 	panic("called");
765 	return B_ERROR;
766 }
767 
768 
769 struct net_route *
get_route(struct net_domain * _domain,const struct sockaddr * address)770 get_route(struct net_domain *_domain, const struct sockaddr *address)
771 {
772 	if (is_server(address)) {
773 		// to the server
774 		return &sServerContext.route;
775 	}
776 
777 	return &sClientContext.route;
778 }
779 
780 
781 static void
put_route(struct net_domain * _domain,net_route * route)782 put_route(struct net_domain* _domain, net_route* route)
783 {
784 }
785 
786 
787 net_datalink_module_info gNetDatalinkModule = {
788 	{
789 		NET_DATALINK_MODULE_NAME,
790 		0,
791 		std_ops
792 	},
793 
794 	NULL, // control
795 	datalink_send_data,
796 	datalink_send_datagram,
797 
798 	NULL, // is_local_address
799 	NULL, // is_local_link_address
800 
801 	NULL, // get_interface
802 	NULL, // get_interface_with_address
803 	NULL, // put_interface
804 
805 	NULL, // get_interface_address
806 	NULL, // get_next_interface_address,
807 	NULL, // put_interface_address
808 
809 	NULL, // join_multicast
810 	NULL, // leave_multicast
811 
812 	NULL, // add_route,
813 	NULL, // remove_route,
814 	get_route,
815 	NULL, // get_buffer_route
816 	put_route,
817 	NULL, // register_route_info,
818 	NULL, // unregister_route_info,
819 	NULL, // update_route_info
820 };
821 
822 
823 //	#pragma mark - domain
824 
825 
826 status_t
domain_open(net_protocol * protocol)827 domain_open(net_protocol *protocol)
828 {
829 	return B_OK;
830 }
831 
832 
833 status_t
domain_close(net_protocol * protocol)834 domain_close(net_protocol *protocol)
835 {
836 	return B_OK;
837 }
838 
839 
840 status_t
domain_free(net_protocol * protocol)841 domain_free(net_protocol *protocol)
842 {
843 	return B_OK;
844 }
845 
846 
847 status_t
domain_connect(net_protocol * protocol,const struct sockaddr * address)848 domain_connect(net_protocol *protocol, const struct sockaddr *address)
849 {
850 	return B_ERROR;
851 }
852 
853 
854 status_t
domain_accept(net_protocol * protocol,struct net_socket ** _acceptedSocket)855 domain_accept(net_protocol *protocol, struct net_socket **_acceptedSocket)
856 {
857 	return EOPNOTSUPP;
858 }
859 
860 
861 status_t
domain_control(net_protocol * protocol,int level,int option,void * value,size_t * _length)862 domain_control(net_protocol *protocol, int level, int option, void *value,
863 	size_t *_length)
864 {
865 	return B_ERROR;
866 }
867 
868 
869 status_t
domain_bind(net_protocol * protocol,const struct sockaddr * address)870 domain_bind(net_protocol *protocol, const struct sockaddr *address)
871 {
872 	memcpy(&protocol->socket->address, address, sizeof(struct sockaddr_in));
873 	protocol->socket->address.ss_len = sizeof(struct sockaddr_in);
874 		// explicitly set length, as our callers can't be trusted to
875 		// always provide the correct length!
876 	return B_OK;
877 }
878 
879 
880 status_t
domain_unbind(net_protocol * protocol,struct sockaddr * address)881 domain_unbind(net_protocol *protocol, struct sockaddr *address)
882 {
883 	return B_OK;
884 }
885 
886 
887 status_t
domain_listen(net_protocol * protocol,int count)888 domain_listen(net_protocol *protocol, int count)
889 {
890 	return EOPNOTSUPP;
891 }
892 
893 
894 status_t
domain_shutdown(net_protocol * protocol,int direction)895 domain_shutdown(net_protocol *protocol, int direction)
896 {
897 	return EOPNOTSUPP;
898 }
899 
900 
901 status_t
domain_send_data(net_protocol * protocol,net_buffer * buffer)902 domain_send_data(net_protocol *protocol, net_buffer *buffer)
903 {
904 	// find route
905 	struct net_route *route = get_route(&sDomain, (sockaddr *)&buffer->destination);
906 	if (route == NULL)
907 		return ENETUNREACH;
908 
909 	return datalink_send_data(route, buffer);
910 }
911 
912 
913 status_t
domain_send_routed_data(net_protocol * protocol,struct net_route * route,net_buffer * buffer)914 domain_send_routed_data(net_protocol *protocol, struct net_route *route,
915 	net_buffer *buffer)
916 {
917 	return datalink_send_data(route, buffer);
918 }
919 
920 
921 ssize_t
domain_send_avail(net_protocol * protocol)922 domain_send_avail(net_protocol *protocol)
923 {
924 	return B_ERROR;
925 }
926 
927 
928 status_t
domain_read_data(net_protocol * protocol,size_t numBytes,uint32 flags,net_buffer ** _buffer)929 domain_read_data(net_protocol *protocol, size_t numBytes, uint32 flags,
930 	net_buffer **_buffer)
931 {
932 	return B_ERROR;
933 }
934 
935 
936 ssize_t
domain_read_avail(net_protocol * protocol)937 domain_read_avail(net_protocol *protocol)
938 {
939 	return B_ERROR;
940 }
941 
942 
943 struct net_domain *
domain_get_domain(net_protocol * protocol)944 domain_get_domain(net_protocol *protocol)
945 {
946 	return &sDomain;
947 }
948 
949 
950 size_t
domain_get_mtu(net_protocol * protocol,const struct sockaddr * address)951 domain_get_mtu(net_protocol *protocol, const struct sockaddr *address)
952 {
953 	return 1480;
954 		// 1500 ethernet - IPv4 header
955 }
956 
957 
958 status_t
domain_receive_data(net_buffer * buffer)959 domain_receive_data(net_buffer *buffer)
960 {
961 	uint32 packetNumber = atomic_add(&sPacketNumber, 1);
962 
963 	bool drop = false;
964 	if (sDropList.find(packetNumber) != sDropList.end()
965 		|| (sRandomDrop > 0.0 && (1.0 * rand() / RAND_MAX) > sRandomDrop))
966 		drop = true;
967 
968 	if (!drop && (sRoundTripTime > 0 || sRandomRoundTrip || sIncreasingRoundTrip)) {
969 		bigtime_t add = 0;
970 		if (sRandomRoundTrip)
971 			add = (bigtime_t)(1.0 * rand() / RAND_MAX * 500000) - 250000;
972 		if (sIncreasingRoundTrip)
973 			sRoundTripTime += (bigtime_t)(1.0 * rand() / RAND_MAX * 150000);
974 
975 		snooze(sRoundTripTime / 2 + add);
976 	}
977 
978 	if (sPacketMonitor != NULL) {
979 		sPacketMonitor(buffer, packetNumber, drop);
980 	} else if (drop)
981 		printf("<**** DROPPED %ld ****>\n", packetNumber);
982 
983 	if (drop) {
984 		gNetBufferModule.free(buffer);
985 		return B_OK;
986 	}
987 
988 	return gTCPModule->receive_data(buffer);
989 }
990 
991 
992 status_t
domain_error(net_error error,net_buffer * data)993 domain_error(net_error error, net_buffer* data)
994 {
995 	return B_ERROR;
996 }
997 
998 
999 status_t
domain_error_reply(net_protocol * self,net_buffer * cause,net_error error,net_error_data * errorData)1000 domain_error_reply(net_protocol* self, net_buffer* cause,
1001 	net_error error, net_error_data* errorData)
1002 {
1003 	return B_ERROR;
1004 }
1005 
1006 
1007 net_protocol_module_info gDomainModule = {
1008 	{
1009 		NULL,
1010 		0,
1011 		std_ops
1012 	},
1013 	NET_PROTOCOL_ATOMIC_MESSAGES,
1014 
1015 	NULL, // init
1016 	NULL, // uninit
1017 	domain_open,
1018 	domain_close,
1019 	domain_free,
1020 	domain_connect,
1021 	domain_accept,
1022 	domain_control,
1023 	NULL, // getsockopt
1024 	NULL, // setsockopt
1025 	domain_bind,
1026 	domain_unbind,
1027 	domain_listen,
1028 	domain_shutdown,
1029 	domain_send_data,
1030 	domain_send_routed_data,
1031 	domain_send_avail,
1032 	domain_read_data,
1033 	domain_read_avail,
1034 	domain_get_domain,
1035 	domain_get_mtu,
1036 	domain_receive_data,
1037 	NULL, // deliver_data
1038 	domain_error,
1039 	domain_error_reply,
1040 	NULL, // attach_ancillary_data
1041 	NULL, // process_ancillary_data
1042 };
1043 
1044 
1045 //	#pragma mark - packet capture
1046 
1047 
1048 static void
dump_printf(net_buffer * buffer,int32 packetNumber,bool willBeDropped)1049 dump_printf(net_buffer* buffer, int32 packetNumber, bool willBeDropped)
1050 {
1051 	static bigtime_t lastTime = 0;
1052 
1053 	NetBufferHeaderReader<tcp_header> bufferHeader(buffer);
1054 	if (bufferHeader.Status() < B_OK)
1055 		return;
1056 
1057 	tcp_header &header = bufferHeader.Data();
1058 
1059 	bigtime_t now = system_time();
1060 	if (lastTime == 0)
1061 		lastTime = now;
1062 
1063 	printf("\33[0m% 3ld %8.6f (%8.6f) ", packetNumber, (now - sStartTime) / 1000000.0,
1064 		(now - lastTime) / 1000000.0);
1065 	lastTime = now;
1066 
1067 	if (is_server((sockaddr *)buffer->source))
1068 		printf("\33[31mserver > client: ");
1069 	else
1070 		printf("client > server: ");
1071 
1072 	int32 length = buffer->size - header.HeaderLength();
1073 
1074 	if ((header.flags & TCP_FLAG_PUSH) != 0)
1075 		putchar('P');
1076 	if ((header.flags & TCP_FLAG_SYNCHRONIZE) != 0)
1077 		putchar('S');
1078 	if ((header.flags & TCP_FLAG_FINISH) != 0)
1079 		putchar('F');
1080 	if ((header.flags & TCP_FLAG_RESET) != 0)
1081 		putchar('R');
1082 	if ((header.flags
1083 		& (TCP_FLAG_SYNCHRONIZE | TCP_FLAG_FINISH | TCP_FLAG_PUSH | TCP_FLAG_RESET)) == 0)
1084 		putchar('.');
1085 
1086 	printf(" %lu:%lu (%lu)", header.Sequence(), header.Sequence() + length, length);
1087 	if ((header.flags & TCP_FLAG_ACKNOWLEDGE) != 0)
1088 		printf(" ack %lu", header.Acknowledge());
1089 
1090 	printf(" win %u", header.AdvertisedWindow());
1091 
1092 	if (header.HeaderLength() > sizeof(tcp_header)) {
1093 		int32 size = header.HeaderLength() - sizeof(tcp_header);
1094 
1095 		tcp_option *option;
1096 		uint8 optionsBuffer[1024];
1097 		if (gBufferModule->direct_access(buffer, sizeof(tcp_header),
1098 				size, (void **)&option) != B_OK) {
1099 			if (size > 1024) {
1100 				printf("options too large to take into account (%ld bytes)\n", size);
1101 				size = 1024;
1102 			}
1103 
1104 			gBufferModule->read(buffer, sizeof(tcp_header), optionsBuffer, size);
1105 			option = (tcp_option *)optionsBuffer;
1106 		}
1107 
1108 		while (size > 0) {
1109 			uint32 length = 1;
1110 			switch (option->kind) {
1111 				case TCP_OPTION_END:
1112 				case TCP_OPTION_NOP:
1113 					break;
1114 				case TCP_OPTION_MAX_SEGMENT_SIZE:
1115 					printf(" <mss %u>", ntohs(option->max_segment_size));
1116 					length = 4;
1117 					break;
1118 				case TCP_OPTION_WINDOW_SHIFT:
1119 					printf(" <ws %u>", option->window_shift);
1120 					length = 3;
1121 					break;
1122 				case TCP_OPTION_TIMESTAMP:
1123 					printf(" <ts %lu:%lu>", option->timestamp.value, option->timestamp.reply);
1124 					length = 10;
1125 					break;
1126 
1127 				default:
1128 					length = option->length;
1129 					// make sure we don't end up in an endless loop
1130 					if (length == 0)
1131 						size = 0;
1132 					break;
1133 			}
1134 
1135 			size -= length;
1136 			option = (tcp_option *)((uint8 *)option + length);
1137 		}
1138 	}
1139 
1140 	if (willBeDropped)
1141 		printf(" <DROPPED>");
1142 	printf("\33[0m\n");
1143 }
1144 
1145 
1146 static void
dump_pcap(net_buffer * buffer,int32 packetNumber,bool willBeDropped)1147 dump_pcap(net_buffer* buffer, int32 packetNumber, bool willBeDropped)
1148 {
1149 	if (willBeDropped) {
1150 		printf(" <DROPPED>\n");
1151 		return;
1152 	}
1153 
1154 	const bigtime_t time = real_time_clock_usecs();
1155 
1156 	struct pcap_packet_header pcap_header;
1157 	pcap_header.ts_sec = time / 1000000;
1158 	pcap_header.ts_usec = time % 1000000;
1159 	pcap_header.included_len = sizeof(struct ip) + buffer->size;
1160 	pcap_header.original_len = pcap_header.included_len;
1161 
1162 	struct ip ip_header;
1163 	ip_header.ip_v = IPVERSION;
1164 	ip_header.ip_hl = sizeof(struct ip) >> 2;
1165 	ip_header.ip_tos = 0;
1166 	ip_header.ip_len = htons(sizeof(struct ip) + buffer->size);
1167 	ip_header.ip_id = htons(packetNumber);
1168 	ip_header.ip_off = 0;
1169 	ip_header.ip_ttl = 254;
1170 	ip_header.ip_p = IPPROTO_TCP;
1171 	ip_header.ip_sum = 0;
1172 	ip_header.ip_src.s_addr = ((sockaddr_in*)buffer->source)->sin_addr.s_addr;
1173 	ip_header.ip_dst.s_addr = ((sockaddr_in*)buffer->destination)->sin_addr.s_addr;
1174 
1175 	size_t count = 16, used = 0;
1176 	iovec vecs[count];
1177 
1178 	vecs[used].iov_base = &pcap_header;
1179 	vecs[used].iov_len = sizeof(pcap_header);
1180 	used++;
1181 
1182 	vecs[used].iov_base = &ip_header;
1183 	vecs[used].iov_len = sizeof(ip_header);
1184 	used++;
1185 
1186 	used += gNetBufferModule.get_iovecs(buffer, vecs + used, count - used);
1187 
1188 	static mutex writesLock = MUTEX_INITIALIZER("pcap writes");
1189 	MutexLocker _(writesLock);
1190 	ssize_t written = writev(sPcapFD, vecs, used);
1191 	if (written != (pcap_header.included_len + sizeof(pcap_packet_header))) {
1192 		fprintf(stderr, "writing to pcap file failed\n");
1193 		exit(1);
1194 	}
1195 }
1196 
1197 
1198 static bool
setup_dump_pcap(const char * file)1199 setup_dump_pcap(const char* file)
1200 {
1201 	sPcapFD = open(file, O_CREAT | O_WRONLY | O_TRUNC);
1202 	if (sPcapFD < 0) {
1203 		fprintf(stderr, "tcp_shell: Failed to open output pcap file: %d\n",
1204 			errno);
1205 		return false;
1206 	}
1207 
1208 	struct pcap_header header;
1209 	header.magic = PCAP_MAGIC;
1210 	header.version_major = 2;
1211 	header.version_minor = 4;
1212 	header.timezone = 0;
1213 	header.timestamp_accuracy = 0;
1214 	header.max_packet_length = 65535;
1215 	header.linktype = PCAP_LINKTYPE_IPV4;
1216 	if (write(sPcapFD, &header, sizeof(header)) != sizeof(header)) {
1217 		fprintf(stderr, "tcp_shell: Failed to write pcap file header: %d\n",
1218 			errno);
1219 		return false;
1220 	}
1221 
1222 	sPacketMonitor = dump_pcap;
1223 	return true;
1224 }
1225 
1226 
1227 //	#pragma mark - test
1228 
1229 
1230 int32
receiving_thread(void * _data)1231 receiving_thread(void* _data)
1232 {
1233 	struct context* context = (struct context*)_data;
1234 	struct net_buffer* reorderBuffer = NULL;
1235 
1236 	while (true) {
1237 		status_t status;
1238 		do {
1239 			status = acquire_sem(context->wait_sem);
1240 		} while (status == B_INTERRUPTED);
1241 
1242 		if (status < B_OK)
1243 			break;
1244 
1245 		while (true) {
1246 			context->lock.Lock();
1247 			net_buffer* buffer = (net_buffer*)list_remove_head_item(
1248 				&context->list);
1249 			context->lock.Unlock();
1250 
1251 			if (buffer == NULL)
1252 				break;
1253 
1254 			if (sSimultaneousConnect && context->server && is_syn(buffer)) {
1255 				// delay getting the SYN request, and connect as well
1256 				sockaddr_in address;
1257 				memset(&address, 0, sizeof(address));
1258 				address.sin_family = AF_INET;
1259 				address.sin_port = htons(1023);
1260 				address.sin_addr.s_addr = htonl(0xc0a80001);
1261 
1262 				status_t status = socket_connect(gServerSocket,
1263 					(struct sockaddr *)&address, sizeof(struct sockaddr));
1264 				if (status < B_OK)
1265 					fprintf(stderr, "tcp_tester: simultaneous connect failed: %s\n", strerror(status));
1266 
1267 				sSimultaneousConnect = false;
1268 			}
1269 			if (sSimultaneousClose && !context->server && is_fin(buffer)) {
1270 				close_protocol(gClientSocket->first_protocol);
1271 				sSimultaneousClose = false;
1272 			}
1273 			if ((sRandomReorder > 0.0
1274 					|| sReorderList.find(sPacketNumber) != sReorderList.end())
1275 				&& reorderBuffer == NULL
1276 				&& (1.0 * rand() / RAND_MAX) > sRandomReorder) {
1277 				reorderBuffer = buffer;
1278 			} else {
1279 				if (sDomain.module->receive_data(buffer) < B_OK)
1280 					gNetBufferModule.free(buffer);
1281 
1282 				if (reorderBuffer != NULL) {
1283 					if (sDomain.module->receive_data(reorderBuffer) < B_OK)
1284 						gNetBufferModule.free(reorderBuffer);
1285 					reorderBuffer = NULL;
1286 				}
1287 			}
1288 		}
1289 	}
1290 
1291 	return 0;
1292 }
1293 
1294 
1295 int32
server_thread(void *)1296 server_thread(void*)
1297 {
1298 	while (true) {
1299 		// main accept() loop
1300 		net_socket* connectionSocket;
1301 		sockaddr_in address;
1302 		socklen_t size = sizeof(struct sockaddr_in);
1303 		status_t status = socket_accept(gServerSocket,
1304 			(struct sockaddr *)&address, &size, &connectionSocket);
1305 		if (status < B_OK) {
1306 			fprintf(stderr, "SERVER: accepting failed: %s\n", strerror(status));
1307 			break;
1308 		}
1309 
1310 		printf("server: got connection from %08x\n", address.sin_addr.s_addr);
1311 
1312 		char buffer[1024];
1313 		ssize_t bytesRead;
1314 		while ((bytesRead = socket_recv(connectionSocket, buffer,
1315 				sizeof(buffer), 0)) > 0) {
1316 			printf("server: received %ld bytes\n", bytesRead);
1317 
1318 			if (sServerActiveClose) {
1319 				printf("server: active close\n");
1320 				close_protocol(connectionSocket->first_protocol);
1321 				return 0;
1322 			}
1323 		}
1324 		if (bytesRead < 0)
1325 			printf("server: receiving failed: %s\n", strerror(bytesRead));
1326 		else
1327 			printf("server: peer closed connection.\n");
1328 
1329 		snooze(1000000);
1330 		close_protocol(connectionSocket->first_protocol);
1331 	}
1332 
1333 	return 0;
1334 }
1335 
1336 
1337 void
setup_server()1338 setup_server()
1339 {
1340 	sockaddr_in address;
1341 	memset(&address, 0, sizeof(address));
1342 	address.sin_len = sizeof(sockaddr_in);
1343 	address.sin_family = AF_INET;
1344 	address.sin_port = htons(1024);
1345 	address.sin_addr.s_addr = INADDR_ANY;
1346 
1347 	status_t status = socket_bind(gServerSocket, (struct sockaddr*)&address,
1348 		sizeof(struct sockaddr));
1349 	if (status < B_OK) {
1350 		fprintf(stderr, "tcp_tester: cannot bind server: %s\n", strerror(status));
1351 		exit(1);
1352 	}
1353 	status = socket_listen(gServerSocket, 40);
1354 	if (status < B_OK) {
1355 		fprintf(stderr, "tcp_tester: server cannot listen: %s\n",
1356 			strerror(status));
1357 		exit(1);
1358 	}
1359 
1360 	thread_id serverThread = spawn_thread(server_thread, "server",
1361 		B_NORMAL_PRIORITY, NULL);
1362 	if (serverThread < B_OK) {
1363 		fprintf(stderr, "tcp_tester: cannot start server: %s\n",
1364 			strerror(serverThread));
1365 		exit(1);
1366 	}
1367 
1368 	resume_thread(serverThread);
1369 }
1370 
1371 
1372 void
setup_context(struct context & context,bool server)1373 setup_context(struct context& context, bool server)
1374 {
1375 	list_init(&context.list);
1376 	context.route.interface_address = &gInterfaceAddress;
1377 	context.route.gateway = (sockaddr *)&context;
1378 		// backpointer to the context
1379 	context.route.mtu = 1500;
1380 	context.server = server;
1381 	context.wait_sem = create_sem(0, "receive wait");
1382 
1383 	context.thread = spawn_thread(receiving_thread,
1384 		server ? "server receiver" : "client receiver", B_NORMAL_PRIORITY,
1385 		&context);
1386 	resume_thread(context.thread);
1387 }
1388 
1389 
1390 void
cleanup_context(struct context & context)1391 cleanup_context(struct context& context)
1392 {
1393 	delete_sem(context.wait_sem);
1394 
1395 	status_t status;
1396 	wait_for_thread(context.thread, &status);
1397 }
1398 
1399 
1400 //  #pragma mark -
1401 
1402 
1403 static void do_help(int argc, char** argv);
1404 
1405 
1406 static void
do_connect(int argc,char ** argv)1407 do_connect(int argc, char** argv)
1408 {
1409 	sSimultaneousConnect = false;
1410 
1411 	int port = 1024;
1412 	if (argc > 1) {
1413 		if (!strcmp(argv[1], "-s"))
1414 			sSimultaneousConnect = true;
1415 		else if (isdigit(argv[1][0]))
1416 			port = atoi(argv[1]);
1417 		else {
1418 			fprintf(stderr, "usage: connect [-s|<port-number>]\n");
1419 			return;
1420 		}
1421 	}
1422 
1423 	if (sSimultaneousConnect) {
1424 		// bind to a port first, so the other end can find us
1425 		sockaddr_in address;
1426 		memset(&address, 0, sizeof(address));
1427 		address.sin_family = AF_INET;
1428 		address.sin_port = htons(1023);
1429 		address.sin_addr.s_addr = htonl(0xc0a80001);
1430 
1431 		status_t status = socket_bind(gClientSocket, (struct sockaddr *)&address,
1432 			sizeof(struct sockaddr));
1433 		if (status < B_OK) {
1434 			fprintf(stderr, "Could not bind to port 1023: %s\n", strerror(status));
1435 			sSimultaneousConnect = false;
1436 			return;
1437 		}
1438 	}
1439 
1440 	sStartTime = system_time();
1441 
1442 	sockaddr_in address;
1443 	memset(&address, 0, sizeof(address));
1444 	address.sin_family = AF_INET;
1445 	address.sin_port = htons(port);
1446 	address.sin_addr.s_addr = htonl(0xc0a80001);
1447 
1448 	status_t status = socket_connect(gClientSocket, (struct sockaddr *)&address,
1449 		sizeof(struct sockaddr));
1450 	if (status < B_OK)
1451 		fprintf(stderr, "tcp_tester: could not connect: %s\n", strerror(status));
1452 }
1453 
1454 
1455 static ssize_t
parse_size(const char * arg)1456 parse_size(const char* arg)
1457 {
1458 	char *unit;
1459 	ssize_t size = strtoul(arg, &unit, 0);
1460 	if (unit != NULL && unit[0]) {
1461 		if (unit[0] == 'k' || unit[0] == 'K')
1462 			size *= 1024;
1463 		else if (unit[0] == 'm' || unit[0] == 'M')
1464 			size *= 1024 * 1024;
1465 		else {
1466 			fprintf(stderr, "unknown unit specified!\n");
1467 			return -1;
1468 		}
1469 	}
1470 	return size;
1471 }
1472 
1473 
1474 static void
do_send(int argc,char ** argv)1475 do_send(int argc, char** argv)
1476 {
1477 	ssize_t size = 1024;
1478 	if (argc > 1 && isdigit(argv[1][0])) {
1479 		size = parse_size(argv[1]);
1480 		if (size < 0)
1481 			return;
1482 	} else if (argc > 1) {
1483 		fprintf(stderr, "invalid args!\n");
1484 		return;
1485 	}
1486 
1487 	if (size > 4 * 1024 * 1024) {
1488 		printf("amount to send will be limited to 4 MB\n");
1489 		size = 4 * 1024 * 1024;
1490 	}
1491 
1492 	char *buffer = (char *)malloc(size);
1493 	if (buffer == NULL) {
1494 		fprintf(stderr, "not enough memory!\n");
1495 		return;
1496 	}
1497 	MemoryDeleter bufferDeleter(buffer);
1498 
1499 	// initialize buffer with some not so random data
1500 	for (uint32 i = 0; i < size; i++) {
1501 		buffer[i] = (char)(i & 0xff);
1502 	}
1503 
1504 	ssize_t bytesWritten = socket_send(gClientSocket, buffer, size, 0);
1505 	if (bytesWritten < B_OK) {
1506 		fprintf(stderr, "failed sending buffer: %s\n", strerror(bytesWritten));
1507 		return;
1508 	}
1509 }
1510 
1511 
1512 static void
do_send_loop(int argc,char ** argv)1513 do_send_loop(int argc, char** argv)
1514 {
1515 	if (argc != 2 || !isdigit(argv[1][0])) {
1516 		fprintf(stderr, "invalid args!\n");
1517 		return;
1518 	}
1519 	ssize_t size = parse_size(argv[1]);
1520 	if (size < 0)
1521 		return;
1522 
1523 	const size_t bufferSize = 4096;
1524 	char *buffer = (char *)malloc(bufferSize);
1525 	if (buffer == NULL) {
1526 		fprintf(stderr, "not enough memory!\n");
1527 		return;
1528 	}
1529 	MemoryDeleter bufferDeleter(buffer);
1530 
1531 	// initialize buffer with some not so random data
1532 	for (uint32 i = 0; i < bufferSize; i++) {
1533 		buffer[i] = (char)(i & 0xff);
1534 	}
1535 
1536 	for (ssize_t total = 0; total < size; ) {
1537 		ssize_t bytesWritten = socket_send(gClientSocket, buffer, bufferSize, 0);
1538 		if (bytesWritten < B_OK) {
1539 			fprintf(stderr, "failed sending buffer (after %" B_PRIdSSIZE "): %s\n",
1540 				total, strerror(bytesWritten));
1541 			return;
1542 		}
1543 
1544 		total += bufferSize;
1545 	}
1546 }
1547 
1548 
1549 static void
do_close(int argc,char ** argv)1550 do_close(int argc, char** argv)
1551 {
1552 	sSimultaneousClose = false;
1553 	sServerActiveClose = true;
1554 
1555 	if (argc > 1) {
1556 		if (!strcmp(argv[1], "-s"))
1557 			sSimultaneousClose = true;
1558 		else {
1559 			fprintf(stderr, "usage: close [-s]\n");
1560 			return;
1561 		}
1562 	}
1563 
1564 	gClientSocket->send.timeout = 0;
1565 
1566 	char buffer[32767] = {'q'};
1567 	ssize_t bytesWritten = socket_send(gClientSocket, buffer, sizeof(buffer), 0);
1568 	if (bytesWritten < B_OK) {
1569 		fprintf(stderr, "failed sending buffer: %s\n", strerror(bytesWritten));
1570 		return;
1571 	}
1572 }
1573 
1574 
1575 static void
do_drop(int argc,char ** argv)1576 do_drop(int argc, char** argv)
1577 {
1578 	if (argc == 1) {
1579 		// show list of dropped packets
1580 		if (sRandomDrop > 0.0)
1581 			printf("Drop probability is %f\n", sRandomDrop);
1582 
1583 		printf("Drop pakets:\n");
1584 
1585 		std::set<uint32>::iterator iterator = sDropList.begin();
1586 		uint32 count = 0;
1587 		for (; iterator != sDropList.end(); iterator++) {
1588 			printf("%4lu\n", *iterator);
1589 			count++;
1590 		}
1591 
1592 		if (count == 0)
1593 			printf("<empty>\n");
1594 	} else if (!strcmp(argv[1], "-f")) {
1595 		// flush drop list
1596 		sDropList.clear();
1597 		puts("drop list cleared.");
1598 	} else if (!strcmp(argv[1], "-r")) {
1599 		if (argc < 3) {
1600 			fprintf(stderr, "No drop probability specified.\n");
1601 			return;
1602 		}
1603 
1604 		sRandomDrop = atof(argv[2]);
1605 		if (sRandomDrop < 0.0)
1606 			sRandomDrop = 0;
1607 		else if (sRandomDrop > 1.0)
1608 			sRandomDrop = 1.0;
1609 	} else if (isdigit(argv[1][0])) {
1610 		// add to drop list
1611 		for (int i = 1; i < argc; i++) {
1612 			uint32 packet = strtoul(argv[i], NULL, 0);
1613 			if (packet == 0) {
1614 				fprintf(stderr, "invalid packet number: %s\n", argv[i]);
1615 				break;
1616 			}
1617 
1618 			sDropList.insert(packet);
1619 		}
1620 	} else {
1621 		// print usage
1622 		puts("usage: drop <packet-number> [...]\n"
1623 			"   or: drop -r <probability>\n\n"
1624 			"   or: drop [-f]\n\n"
1625 			"Specifiying -f flushes the drop list, -r sets the probability a packet\n"
1626 			"is dropped; if you called drop without any arguments, the current\n"
1627 			"drop list is dumped.");
1628 	}
1629 }
1630 
1631 
1632 static void
do_reorder(int argc,char ** argv)1633 do_reorder(int argc, char** argv)
1634 {
1635 	if (argc == 1) {
1636 		// show list of dropped packets
1637 		if (sRandomReorder > 0.0)
1638 			printf("Reorder probability is %f\n", sRandomReorder);
1639 
1640 		printf("Reorder packets:\n");
1641 
1642 		std::set<uint32>::iterator iterator = sReorderList.begin();
1643 		uint32 count = 0;
1644 		for (; iterator != sReorderList.end(); iterator++) {
1645 			printf("%4lu\n", *iterator);
1646 			count++;
1647 		}
1648 
1649 		if (count == 0)
1650 			printf("<empty>\n");
1651 	} else if (!strcmp(argv[1], "-f")) {
1652 		// flush reorder list
1653 		sReorderList.clear();
1654 		puts("reorder list cleared.");
1655 	} else if (!strcmp(argv[1], "-r")) {
1656 		if (argc < 3) {
1657 			fprintf(stderr, "No reorder probability specified.\n");
1658 			return;
1659 		}
1660 
1661 		sRandomReorder = atof(argv[2]);
1662 		if (sRandomReorder < 0.0)
1663 			sRandomReorder = 0;
1664 		else if (sRandomReorder > 1.0)
1665 			sRandomReorder = 1.0;
1666 	} else if (isdigit(argv[1][0])) {
1667 		// add to reorder list
1668 		for (int i = 1; i < argc; i++) {
1669 			uint32 packet = strtoul(argv[i], NULL, 0);
1670 			if (packet == 0) {
1671 				fprintf(stderr, "invalid packet number: %s\n", argv[i]);
1672 				break;
1673 			}
1674 
1675 			sReorderList.insert(packet);
1676 		}
1677 	} else {
1678 		// print usage
1679 		puts("usage: reorder <packet-number> [...]\n"
1680 			"   or: reorder -r <probability>\n\n"
1681 			"   or: reorder [-f]\n\n"
1682 			"Specifiying -f flushes the reorder list, -r sets the probability a packet\n"
1683 			"is reordered; if you called reorder without any arguments, the current\n"
1684 			"reorder list is dumped.");
1685 	}
1686 }
1687 
1688 
1689 static void
do_round_trip_time(int argc,char ** argv)1690 do_round_trip_time(int argc, char** argv)
1691 {
1692 	if (argc == 1) {
1693 		// show current time
1694 		printf("Current round trip time: %g ms\n", sRoundTripTime / 1000.0);
1695 	} else if (!strcmp(argv[1], "-r")) {
1696 		// toggle random time
1697 		sRandomRoundTrip = !sRandomRoundTrip;
1698 		printf("Round trip time is now %s.\n", sRandomRoundTrip ? "random" : "fixed");
1699 	} else if (!strcmp(argv[1], "-i")) {
1700 		// toggle increasing time
1701 		sIncreasingRoundTrip = !sIncreasingRoundTrip;
1702 		printf("Round trip time is now %s.\n", sIncreasingRoundTrip ? "increasing" : "fixed");
1703 	} else if (isdigit(argv[1][0])) {
1704 		// set time
1705 		sRoundTripTime = 1000LL * strtoul(argv[1], NULL, 0);
1706 	} else {
1707 		// print usage
1708 		puts("usage: rtt <time in ms>\n"
1709 			"   or: rtt [-r|-i]\n\n"
1710 			"Specifiying -r sets random time, -i causes the times to increase over time;\n"
1711 			"witout any arguments, the current time is printed.");
1712 	}
1713 }
1714 
1715 
1716 static void
do_dprintf(int argc,char ** argv)1717 do_dprintf(int argc, char** argv)
1718 {
1719 	if (argc > 1)
1720 		gDebugOutputEnabled = !strcmp(argv[1], "on");
1721 	else
1722 		gDebugOutputEnabled = !gDebugOutputEnabled;
1723 
1724 	printf("debug output turned %s.\n", gDebugOutputEnabled ? "on" : "off");
1725 }
1726 
1727 
1728 static cmd_entry sBuiltinCommands[] = {
1729 	{"connect", do_connect, "Connects the client"},
1730 	{"send", do_send, "Sends data from the client to the server"},
1731 	{"send_loop", do_send_loop, "Sends data in a loop"},
1732 	{"close", do_close, "Performs an active or simultaneous close"},
1733 	{"dprintf", do_dprintf, "Toggles debug output"},
1734 	{"drop", do_drop, "Lets you drop packets during transfer"},
1735 	{"reorder", do_reorder, "Lets you reorder packets during transfer"},
1736 	{"help", do_help, "prints this help text"},
1737 	{"rtt", do_round_trip_time, "Specifies the round trip time"},
1738 	{"quit", NULL, "exits the application"},
1739 	{NULL, NULL, NULL},
1740 };
1741 
1742 
1743 static void
do_help(int argc,char ** argv)1744 do_help(int argc, char** argv)
1745 {
1746 	printf("Available commands:\n");
1747 
1748 	for (cmd_entry* command = sBuiltinCommands; command->name != NULL; command++) {
1749 		printf("%8s - %s\n", command->name, command->help);
1750 	}
1751 }
1752 
1753 
1754 //	#pragma mark -
1755 
1756 
1757 int
main(int argc,char * argv[])1758 main(int argc, char* argv[])
1759 {
1760 	for (int i = 1; i < argc; i++) {
1761 		if (strcmp(argv[i], "-w") == 0 && (i + 1) < argc) {
1762 			if (!setup_dump_pcap(argv[++i]))
1763 				return 1;
1764 		}
1765 	}
1766 
1767 	if (sPacketMonitor == NULL)
1768 		sPacketMonitor = dump_printf;
1769 
1770 	status_t status = init_timers();
1771 	if (status < B_OK) {
1772 		fprintf(stderr, "tcp_tester: Could not initialize timers: %s\n",
1773 			strerror(status));
1774 		return 1;
1775 	}
1776 
1777 	_add_builtin_module((module_info*)&gNetStackModule);
1778 	_add_builtin_module((module_info*)&gNetBufferModule);
1779 	_add_builtin_module((module_info*)&gNetSocketModule);
1780 	_add_builtin_module((module_info*)&gNetDatalinkModule);
1781 	_add_builtin_module(modules[0]);
1782 	if (_get_builtin_dependencies() < B_OK) {
1783 		fprintf(stderr, "tcp_tester: Could not initialize modules: %s\n",
1784 			strerror(status));
1785 		return 1;
1786 	}
1787 
1788 	sockaddr_in interfaceAddress;
1789 	interfaceAddress.sin_len = sizeof(sockaddr_in);
1790 	interfaceAddress.sin_family = AF_INET;
1791 	interfaceAddress.sin_addr.s_addr = htonl(0xc0a80001);
1792 	gInterfaceAddress.local = (sockaddr*)&interfaceAddress;
1793 	gInterfaceAddress.domain = &sDomain;
1794 
1795 	status = get_module("network/protocols/tcp/v1", (module_info **)&gTCPModule);
1796 	if (status < B_OK) {
1797 		fprintf(stderr, "tcp_tester: Could not open TCP module: %s\n",
1798 			strerror(status));
1799 		return 1;
1800 	}
1801 
1802 	net_protocol* client = init_protocol(&gClientSocket);
1803 	if (client == NULL)
1804 		return 1;
1805 	net_protocol* server = init_protocol(&gServerSocket);
1806 	if (server == NULL)
1807 		return 1;
1808 
1809 	setup_context(sClientContext, false);
1810 	setup_context(sServerContext, true);
1811 
1812 	printf("*** Server: %p (%ld), Client: %p (%ld)\n", server,
1813 		sServerContext.thread, client, sClientContext.thread);
1814 
1815 	setup_server();
1816 
1817 	while (true) {
1818 		printf("> ");
1819 		fflush(stdout);
1820 
1821 		char line[1024];
1822 		if (fgets(line, sizeof(line), stdin) == NULL)
1823 			break;
1824 
1825         argc = 0;
1826         argv = build_argv(line, &argc);
1827         if (argv == NULL || argc == 0)
1828             continue;
1829 
1830         int length = strlen(argv[0]);
1831 
1832 #if 0
1833 		char *newLine = strchr(line, '\n');
1834 		if (newLine != NULL)
1835 			newLine[0] = '\0';
1836 #endif
1837 
1838 		if (!strcmp(argv[0], "quit")
1839 			|| !strcmp(argv[0], "exit")
1840 			|| !strcmp(argv[0], "q"))
1841 			break;
1842 
1843 		bool found = false;
1844 
1845 		for (cmd_entry* command = sBuiltinCommands; command->name != NULL; command++) {
1846 			if (!strncmp(command->name, argv[0], length)) {
1847 				command->func(argc, argv);
1848 				found = true;
1849 				break;
1850 			}
1851 		}
1852 
1853 		if (!found)
1854 			fprintf(stderr, "Unknown command \"%s\". Type \"help\" for a list of commands.\n", argv[0]);
1855 
1856 		free(argv);
1857 	}
1858 
1859 	close_protocol(client);
1860 	close_protocol(server);
1861 
1862 	snooze(2000000);
1863 
1864 	cleanup_context(sClientContext);
1865 	cleanup_context(sServerContext);
1866 
1867 	put_module("network/protocols/tcp/v1");
1868 	uninit_timers();
1869 	return 0;
1870 }
1871