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