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