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
43struct 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
52struct cmd_entry {
53	const char*	name;
54	void	(*func)(int argc, char **argv);
55	const char*	help;
56};
57
58
59struct net_socket_private;
60typedef DoublyLinkedList<net_socket_private> SocketList;
61
62struct 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
77extern "C" status_t _add_builtin_module(module_info *info);
78extern "C" status_t _get_builtin_dependencies(void);
79extern bool gDebugOutputEnabled;
80	// from libkernelland_emu.so
81
82extern struct net_buffer_module_info gNetBufferModule;
83	// from net_buffer.cpp
84extern net_address_module_info gIPv4AddressModule;
85	// from ipv4_address.cpp
86extern module_info *modules[];
87	// from tcp.cpp
88
89
90extern struct net_protocol_module_info gDomainModule;
91struct net_interface_address gInterfaceAddress = {};
92extern struct net_socket_module_info gNetSocketModule;
93struct net_protocol_module_info *gTCPModule;
94struct net_socket *gServerSocket, *gClientSocket;
95static struct context sClientContext, sServerContext;
96
97static int32 sPacketNumber = 1;
98static double sRandomDrop = 0.0;
99static std::set<uint32> sDropList;
100static bigtime_t sRoundTripTime = 0;
101static bool sIncreasingRoundTrip = false;
102static bool sRandomRoundTrip = false;
103static void (*sPacketMonitor)(net_buffer *, int32, bool) = NULL;
104static int sPcapFD = -1;
105static bigtime_t sStartTime;
106static double sRandomReorder = 0.0;
107static std::set<uint32> sReorderList;
108static bool sSimultaneousConnect = false;
109static bool sSimultaneousClose = false;
110static bool sServerActiveClose = false;
111
112static struct net_domain sDomain = {
113	"ipv4",
114	AF_INET,
115
116	&gDomainModule,
117	&gIPv4AddressModule
118};
119
120
121static bool
122is_server(const sockaddr* addr)
123{
124	return ((sockaddr_in*)addr)->sin_port == htons(1024);
125}
126
127
128static uint8
129tcp_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
140static bool
141is_syn(net_buffer* buffer)
142{
143	return (tcp_segment_flags(buffer) & TCP_FLAG_SYNCHRONIZE) != 0;
144}
145
146
147static bool
148is_fin(net_buffer* buffer)
149{
150	return (tcp_segment_flags(buffer) & TCP_FLAG_FINISH) != 0;
151}
152
153
154//	#pragma mark - stack
155
156
157status_t
158std_ops(int32, ...)
159{
160	return B_OK;
161}
162
163
164net_domain *
165get_domain(int family)
166{
167	return &sDomain;
168}
169
170
171status_t
172register_domain_protocols(int family, int type, int protocol, ...)
173{
174	return B_OK;
175}
176
177
178status_t
179register_domain_datalink_protocols(int family, int type, ...)
180{
181	return B_OK;
182}
183
184
185static status_t
186register_domain_receiving_protocol(int family, int type, const char *moduleName)
187{
188	return B_OK;
189}
190
191
192static bool
193dummy_is_syscall(void)
194{
195	return false;
196}
197
198
199static bool
200dummy_is_restarted_syscall(void)
201{
202	return false;
203}
204
205
206static void
207dummy_store_syscall_restart_timeout(bigtime_t timeout)
208{
209}
210
211
212static 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
270status_t
271socket_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
317void
318socket_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
331int
332socket_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
352int
353socket_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
386int
387socket_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
403int
404socket_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
414ssize_t
415socket_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
452ssize_t
453socket_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
473bool
474socket_acquire(net_socket* _socket)
475{
476	return true;
477}
478
479
480bool
481socket_release(net_socket* _socket)
482{
483	return true;
484}
485
486
487status_t
488socket_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
524status_t
525socket_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
543ssize_t
544socket_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
554status_t
555socket_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
585bool
586socket_has_parent(net_socket* _socket)
587{
588	net_socket_private* socket = (net_socket_private*)_socket;
589	return socket->parent != NULL;
590}
591
592
593status_t
594socket_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
611status_t
612socket_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
646net_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
704net_protocol*
705init_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
724void
725close_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
737status_t
738datalink_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
753status_t
754datalink_send_datagram(net_protocol *protocol, net_domain *domain,
755	net_buffer *buffer)
756{
757	panic("called");
758	return B_ERROR;
759}
760
761
762struct net_route *
763get_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
774static void
775put_route(struct net_domain* _domain, net_route* route)
776{
777}
778
779
780net_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
819status_t
820domain_open(net_protocol *protocol)
821{
822	return B_OK;
823}
824
825
826status_t
827domain_close(net_protocol *protocol)
828{
829	return B_OK;
830}
831
832
833status_t
834domain_free(net_protocol *protocol)
835{
836	return B_OK;
837}
838
839
840status_t
841domain_connect(net_protocol *protocol, const struct sockaddr *address)
842{
843	return B_ERROR;
844}
845
846
847status_t
848domain_accept(net_protocol *protocol, struct net_socket **_acceptedSocket)
849{
850	return EOPNOTSUPP;
851}
852
853
854status_t
855domain_control(net_protocol *protocol, int level, int option, void *value,
856	size_t *_length)
857{
858	return B_ERROR;
859}
860
861
862status_t
863domain_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
873status_t
874domain_unbind(net_protocol *protocol, struct sockaddr *address)
875{
876	return B_OK;
877}
878
879
880status_t
881domain_listen(net_protocol *protocol, int count)
882{
883	return EOPNOTSUPP;
884}
885
886
887status_t
888domain_shutdown(net_protocol *protocol, int direction)
889{
890	return EOPNOTSUPP;
891}
892
893
894status_t
895domain_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
906status_t
907domain_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
914ssize_t
915domain_send_avail(net_protocol *protocol)
916{
917	return B_ERROR;
918}
919
920
921status_t
922domain_read_data(net_protocol *protocol, size_t numBytes, uint32 flags,
923	net_buffer **_buffer)
924{
925	return B_ERROR;
926}
927
928
929ssize_t
930domain_read_avail(net_protocol *protocol)
931{
932	return B_ERROR;
933}
934
935
936struct net_domain *
937domain_get_domain(net_protocol *protocol)
938{
939	return &sDomain;
940}
941
942
943size_t
944domain_get_mtu(net_protocol *protocol, const struct sockaddr *address)
945{
946	return 1480;
947		// 1500 ethernet - IPv4 header
948}
949
950
951status_t
952domain_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
985status_t
986domain_error(net_error error, net_buffer* data)
987{
988	return B_ERROR;
989}
990
991
992status_t
993domain_error_reply(net_protocol* self, net_buffer* cause,
994	net_error error, net_error_data* errorData)
995{
996	return B_ERROR;
997}
998
999
1000net_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
1041static void
1042dump_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
1139static void
1140dump_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
1191static bool
1192setup_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
1223int32
1224receiving_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
1288int32
1289server_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
1330void
1331setup_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
1365void
1366setup_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
1383void
1384cleanup_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
1396static void do_help(int argc, char** argv);
1397
1398
1399static void
1400do_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
1448static ssize_t
1449parse_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
1467static void
1468do_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
1505static void
1506do_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
1542static void
1543do_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
1568static void
1569do_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
1625static void
1626do_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
1682static void
1683do_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
1709static void
1710do_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
1721static 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
1736static void
1737do_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
1750int
1751main(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