1/*
2 * Copyright 2006-2010, 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 "stack_private.h"
11
12#include <stdlib.h>
13#include <string.h>
14#include <sys/ioctl.h>
15#include <sys/time.h>
16
17#include <new>
18
19#include <Drivers.h>
20#include <KernelExport.h>
21#include <Select.h>
22
23#include <AutoDeleter.h>
24#include <team.h>
25#include <util/AutoLock.h>
26#include <util/list.h>
27#include <WeakReferenceable.h>
28
29#include <fs/select_sync_pool.h>
30#include <kernel.h>
31
32#include <net_protocol.h>
33#include <net_stack.h>
34#include <net_stat.h>
35
36#include "ancillary_data.h"
37#include "utility.h"
38
39
40//#define TRACE_SOCKET
41#ifdef TRACE_SOCKET
42#	define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x)
43#else
44#	define TRACE(x...) ;
45#endif
46
47
48struct net_socket_private;
49typedef DoublyLinkedList<net_socket_private> SocketList;
50
51struct net_socket_private : net_socket,
52		DoublyLinkedListLinkImpl<net_socket_private>,
53		BWeakReferenceable {
54	net_socket_private();
55	~net_socket_private();
56
57	void RemoveFromParent();
58
59	BWeakReference<net_socket_private> parent;
60	team_id						owner;
61	uint32						max_backlog;
62	uint32						child_count;
63	SocketList					pending_children;
64	SocketList					connected_children;
65
66	struct select_sync_pool*	select_pool;
67	mutex						lock;
68
69	bool						is_connected;
70	bool						is_in_socket_list;
71};
72
73
74int socket_bind(net_socket* socket, const struct sockaddr* address,
75	socklen_t addressLength);
76int socket_setsockopt(net_socket* socket, int level, int option,
77	const void* value, int length);
78ssize_t socket_read_avail(net_socket* socket);
79
80static SocketList sSocketList;
81static mutex sSocketLock;
82
83
84net_socket_private::net_socket_private()
85	:
86	owner(-1),
87	max_backlog(0),
88	child_count(0),
89	select_pool(NULL),
90	is_connected(false),
91	is_in_socket_list(false)
92{
93	first_protocol = NULL;
94	first_info = NULL;
95	options = 0;
96	linger = 0;
97	bound_to_device = 0;
98	error = 0;
99
100	address.ss_len = 0;
101	peer.ss_len = 0;
102
103	mutex_init(&lock, "socket");
104
105	// set defaults (may be overridden by the protocols)
106	send.buffer_size = 65535;
107	send.low_water_mark = 1;
108	send.timeout = B_INFINITE_TIMEOUT;
109	receive.buffer_size = 65535;
110	receive.low_water_mark = 1;
111	receive.timeout = B_INFINITE_TIMEOUT;
112}
113
114
115net_socket_private::~net_socket_private()
116{
117	TRACE("delete net_socket %p\n", this);
118
119	if (parent != NULL)
120		panic("socket still has a parent!");
121
122	if (is_in_socket_list) {
123		MutexLocker _(sSocketLock);
124		sSocketList.Remove(this);
125	}
126
127	mutex_lock(&lock);
128
129	// also delete all children of this socket
130	while (net_socket_private* child = pending_children.RemoveHead()) {
131		child->RemoveFromParent();
132	}
133	while (net_socket_private* child = connected_children.RemoveHead()) {
134		child->RemoveFromParent();
135	}
136
137	mutex_unlock(&lock);
138
139	put_domain_protocols(this);
140
141	mutex_destroy(&lock);
142}
143
144
145void
146net_socket_private::RemoveFromParent()
147{
148	ASSERT(!is_in_socket_list && parent != NULL);
149
150	parent = NULL;
151
152	mutex_lock(&sSocketLock);
153	sSocketList.Add(this);
154	mutex_unlock(&sSocketLock);
155
156	is_in_socket_list = true;
157
158	ReleaseReference();
159}
160
161
162//	#pragma mark -
163
164
165static size_t
166compute_user_iovec_length(iovec* userVec, uint32 count)
167{
168	size_t length = 0;
169
170	for (uint32 i = 0; i < count; i++) {
171		iovec vec;
172		if (user_memcpy(&vec, userVec + i, sizeof(iovec)) < B_OK)
173			return 0;
174
175		length += vec.iov_len;
176	}
177
178	return length;
179}
180
181
182static status_t
183create_socket(int family, int type, int protocol, net_socket_private** _socket)
184{
185	struct net_socket_private* socket = new(std::nothrow) net_socket_private;
186	if (socket == NULL)
187		return B_NO_MEMORY;
188	status_t status = socket->InitCheck();
189	if (status != B_OK) {
190		delete socket;
191		return status;
192	}
193
194	socket->family = family;
195	socket->type = type;
196	socket->protocol = protocol;
197
198	status = get_domain_protocols(socket);
199	if (status != B_OK) {
200		delete socket;
201		return status;
202	}
203
204	TRACE("create net_socket %p (%u.%u.%u):\n", socket, socket->family,
205		socket->type, socket->protocol);
206
207#ifdef TRACE_SOCKET
208	net_protocol* current = socket->first_protocol;
209	for (int i = 0; current != NULL; current = current->next, i++)
210		TRACE("  [%d] %p  %s\n", i, current, current->module->info.name);
211#endif
212
213	*_socket = socket;
214	return B_OK;
215}
216
217
218static status_t
219add_ancillary_data(net_socket* socket, ancillary_data_container* container,
220	void* data, size_t dataLen)
221{
222	cmsghdr* header = (cmsghdr*)data;
223
224	while (dataLen > 0) {
225		if (header->cmsg_len < sizeof(cmsghdr) || header->cmsg_len > dataLen)
226			return B_BAD_VALUE;
227
228		if (socket->first_info->add_ancillary_data == NULL)
229			return B_NOT_SUPPORTED;
230
231		status_t status = socket->first_info->add_ancillary_data(
232			socket->first_protocol, container, header);
233		if (status != B_OK)
234			return status;
235
236		dataLen -= _ALIGN(header->cmsg_len);
237		header = (cmsghdr*)((uint8*)header + _ALIGN(header->cmsg_len));
238	}
239
240	return B_OK;
241}
242
243
244static status_t
245process_ancillary_data(net_socket* socket, ancillary_data_container* container,
246	msghdr* messageHeader)
247{
248	uint8* dataBuffer = (uint8*)messageHeader->msg_control;
249	int dataBufferLen = messageHeader->msg_controllen;
250
251	if (container == NULL || dataBuffer == NULL) {
252		messageHeader->msg_controllen = 0;
253		return B_OK;
254	}
255
256	ancillary_data_header header;
257	void* data = NULL;
258
259	while ((data = next_ancillary_data(container, data, &header)) != NULL) {
260		if (socket->first_info->process_ancillary_data == NULL)
261			return B_NOT_SUPPORTED;
262
263		ssize_t bytesWritten = socket->first_info->process_ancillary_data(
264			socket->first_protocol, &header, data, dataBuffer, dataBufferLen);
265		if (bytesWritten < 0)
266			return bytesWritten;
267
268		dataBuffer += bytesWritten;
269		dataBufferLen -= bytesWritten;
270	}
271
272	messageHeader->msg_controllen -= dataBufferLen;
273
274	return B_OK;
275}
276
277
278static status_t
279process_ancillary_data(net_socket* socket,
280	net_buffer* buffer, msghdr* messageHeader)
281{
282	void *dataBuffer = messageHeader->msg_control;
283	ssize_t bytesWritten;
284
285	if (dataBuffer == NULL) {
286		messageHeader->msg_controllen = 0;
287		return B_OK;
288	}
289
290	if (socket->first_info->process_ancillary_data_no_container == NULL)
291		return B_NOT_SUPPORTED;
292
293	bytesWritten = socket->first_info->process_ancillary_data_no_container(
294		socket->first_protocol, buffer, dataBuffer,
295		messageHeader->msg_controllen);
296	if (bytesWritten < 0)
297		return bytesWritten;
298	messageHeader->msg_controllen = bytesWritten;
299
300	return B_OK;
301}
302
303
304static ssize_t
305socket_receive_no_buffer(net_socket* socket, msghdr* header, void* data,
306	size_t length, int flags)
307{
308	iovec stackVec = { data, length };
309	iovec* vecs = header ? header->msg_iov : &stackVec;
310	int vecCount = header ? header->msg_iovlen : 1;
311	sockaddr* address = header ? (sockaddr*)header->msg_name : NULL;
312	socklen_t* addressLen = header ? &header->msg_namelen : NULL;
313
314	ancillary_data_container* ancillaryData = NULL;
315	ssize_t bytesRead = socket->first_info->read_data_no_buffer(
316		socket->first_protocol, vecs, vecCount, &ancillaryData, address,
317		addressLen);
318	if (bytesRead < 0)
319		return bytesRead;
320
321	CObjectDeleter<ancillary_data_container> ancillaryDataDeleter(ancillaryData,
322		&delete_ancillary_data_container);
323
324	// process ancillary data
325	if (header != NULL) {
326		status_t status = process_ancillary_data(socket, ancillaryData, header);
327		if (status != B_OK)
328			return status;
329
330		header->msg_flags = 0;
331	}
332
333	return bytesRead;
334}
335
336
337#if ENABLE_DEBUGGER_COMMANDS
338
339
340static void
341print_socket_line(net_socket_private* socket, const char* prefix)
342{
343	BReference<net_socket_private> parent = socket->parent.GetReference();
344	kprintf("%s%p %2d.%2d.%2d %6" B_PRId32 " %p %p  %p%s\n", prefix, socket,
345		socket->family, socket->type, socket->protocol, socket->owner,
346		socket->first_protocol, socket->first_info, parent.Get(),
347		parent.Get() != NULL ? socket->is_connected ? " (c)" : " (p)" : "");
348}
349
350
351static int
352dump_socket(int argc, char** argv)
353{
354	if (argc < 2) {
355		kprintf("usage: %s [address]\n", argv[0]);
356		return 0;
357	}
358
359	net_socket_private* socket = (net_socket_private*)parse_expression(argv[1]);
360
361	kprintf("SOCKET %p\n", socket);
362	kprintf("  family.type.protocol: %d.%d.%d\n",
363		socket->family, socket->type, socket->protocol);
364	BReference<net_socket_private> parent = socket->parent.GetReference();
365	kprintf("  parent:               %p\n", parent.Get());
366	kprintf("  first protocol:       %p\n", socket->first_protocol);
367	kprintf("  first module_info:    %p\n", socket->first_info);
368	kprintf("  options:              %x\n", socket->options);
369	kprintf("  linger:               %d\n", socket->linger);
370	kprintf("  bound to device:      %" B_PRIu32 "\n", socket->bound_to_device);
371	kprintf("  owner:                %" B_PRId32 "\n", socket->owner);
372	kprintf("  max backlog:          %" B_PRId32 "\n", socket->max_backlog);
373	kprintf("  is connected:         %d\n", socket->is_connected);
374	kprintf("  child_count:          %" B_PRIu32 "\n", socket->child_count);
375
376	if (socket->child_count == 0)
377		return 0;
378
379	kprintf("    pending children:\n");
380	SocketList::Iterator iterator = socket->pending_children.GetIterator();
381	while (net_socket_private* child = iterator.Next()) {
382		print_socket_line(child, "      ");
383	}
384
385	kprintf("    connected children:\n");
386	iterator = socket->connected_children.GetIterator();
387	while (net_socket_private* child = iterator.Next()) {
388		print_socket_line(child, "      ");
389	}
390
391	return 0;
392}
393
394
395static int
396dump_sockets(int argc, char** argv)
397{
398	kprintf("address        kind  owner protocol   module_info parent\n");
399
400	SocketList::Iterator iterator = sSocketList.GetIterator();
401	while (net_socket_private* socket = iterator.Next()) {
402		print_socket_line(socket, "");
403
404		SocketList::Iterator childIterator
405			= socket->pending_children.GetIterator();
406		while (net_socket_private* child = childIterator.Next()) {
407			print_socket_line(child, " ");
408		}
409
410		childIterator = socket->connected_children.GetIterator();
411		while (net_socket_private* child = childIterator.Next()) {
412			print_socket_line(child, " ");
413		}
414	}
415
416	return 0;
417}
418
419
420#endif	// ENABLE_DEBUGGER_COMMANDS
421
422
423//	#pragma mark -
424
425
426status_t
427socket_open(int family, int type, int protocol, net_socket** _socket)
428{
429	net_socket_private* socket;
430	status_t status = create_socket(family, type, protocol, &socket);
431	if (status != B_OK)
432		return status;
433
434	status = socket->first_info->open(socket->first_protocol);
435	if (status != B_OK) {
436		delete socket;
437		return status;
438	}
439
440	socket->owner = team_get_current_team_id();
441	socket->is_in_socket_list = true;
442
443	mutex_lock(&sSocketLock);
444	sSocketList.Add(socket);
445	mutex_unlock(&sSocketLock);
446
447	*_socket = socket;
448	return B_OK;
449}
450
451
452status_t
453socket_close(net_socket* _socket)
454{
455	net_socket_private* socket = (net_socket_private*)_socket;
456	return socket->first_info->close(socket->first_protocol);
457}
458
459
460void
461socket_free(net_socket* _socket)
462{
463	net_socket_private* socket = (net_socket_private*)_socket;
464	socket->first_info->free(socket->first_protocol);
465	socket->ReleaseReference();
466}
467
468
469status_t
470socket_readv(net_socket* socket, const iovec* vecs, size_t vecCount,
471	size_t* _length)
472{
473	return -1;
474}
475
476
477status_t
478socket_writev(net_socket* socket, const iovec* vecs, size_t vecCount,
479	size_t* _length)
480{
481	if (socket->peer.ss_len == 0)
482		return ECONNRESET;
483
484	if (socket->address.ss_len == 0) {
485		// try to bind first
486		status_t status = socket_bind(socket, NULL, 0);
487		if (status != B_OK)
488			return status;
489	}
490
491	// TODO: useful, maybe even computed header space!
492	net_buffer* buffer = gNetBufferModule.create(256);
493	if (buffer == NULL)
494		return ENOBUFS;
495
496	// copy data into buffer
497
498	for (uint32 i = 0; i < vecCount; i++) {
499		if (gNetBufferModule.append(buffer, vecs[i].iov_base,
500				vecs[i].iov_len) < B_OK) {
501			gNetBufferModule.free(buffer);
502			return ENOBUFS;
503		}
504	}
505
506	memcpy(buffer->source, &socket->address, socket->address.ss_len);
507	memcpy(buffer->destination, &socket->peer, socket->peer.ss_len);
508	size_t size = buffer->size;
509
510	ssize_t bytesWritten = socket->first_info->send_data(socket->first_protocol,
511		buffer);
512	if (bytesWritten < B_OK) {
513		if (buffer->size != size) {
514			// this appears to be a partial write
515			*_length = size - buffer->size;
516		}
517		gNetBufferModule.free(buffer);
518		return bytesWritten;
519	}
520
521	*_length = bytesWritten;
522	return B_OK;
523}
524
525
526status_t
527socket_control(net_socket* socket, int32 op, void* data, size_t length)
528{
529	switch (op) {
530		case FIONBIO:
531		{
532			if (data == NULL)
533				return B_BAD_VALUE;
534
535			int value;
536			if (is_syscall()) {
537				if (!IS_USER_ADDRESS(data)
538					|| user_memcpy(&value, data, sizeof(int)) != B_OK) {
539					return B_BAD_ADDRESS;
540				}
541			} else
542				value = *(int*)data;
543
544			return socket_setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &value,
545				sizeof(int));
546		}
547
548		case FIONREAD:
549		{
550			if (data == NULL)
551				return B_BAD_VALUE;
552
553			ssize_t available = socket_read_avail(socket);
554			if (available < B_OK)
555				return available;
556
557			if (is_syscall()) {
558				if (!IS_USER_ADDRESS(data)
559					|| user_memcpy(data, &available, sizeof(ssize_t)) != B_OK) {
560					return B_BAD_ADDRESS;
561				}
562			} else
563				*(ssize_t *)data = available;
564
565			return B_OK;
566		}
567
568		case B_SET_BLOCKING_IO:
569		case B_SET_NONBLOCKING_IO:
570		{
571			int value = op == B_SET_NONBLOCKING_IO;
572			return socket_setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &value,
573				sizeof(int));
574		}
575	}
576
577	return socket->first_info->control(socket->first_protocol,
578		LEVEL_DRIVER_IOCTL, op, data, &length);
579}
580
581
582ssize_t
583socket_read_avail(net_socket* socket)
584{
585	return socket->first_info->read_avail(socket->first_protocol);
586}
587
588
589ssize_t
590socket_send_avail(net_socket* socket)
591{
592	return socket->first_info->send_avail(socket->first_protocol);
593}
594
595
596status_t
597socket_send_data(net_socket* socket, net_buffer* buffer)
598{
599	return socket->first_info->send_data(socket->first_protocol,
600		buffer);
601}
602
603
604status_t
605socket_receive_data(net_socket* socket, size_t length, uint32 flags,
606	net_buffer** _buffer)
607{
608	status_t status = socket->first_info->read_data(socket->first_protocol,
609		length, flags, _buffer);
610	if (status != B_OK)
611		return status;
612
613	if (*_buffer && length < (*_buffer)->size) {
614		// discard any data behind the amount requested
615		gNetBufferModule.trim(*_buffer, length);
616	}
617
618	return status;
619}
620
621
622status_t
623socket_get_next_stat(uint32* _cookie, int family, struct net_stat* stat)
624{
625	MutexLocker locker(sSocketLock);
626
627	net_socket_private* socket = NULL;
628	SocketList::Iterator iterator = sSocketList.GetIterator();
629	uint32 cookie = *_cookie;
630	uint32 count = 0;
631
632	while (true) {
633		socket = iterator.Next();
634		if (socket == NULL)
635			return B_ENTRY_NOT_FOUND;
636
637		// TODO: also traverse the pending connections
638		if (count == cookie)
639			break;
640
641		if (family == -1 || family == socket->family)
642			count++;
643	}
644
645	*_cookie = count + 1;
646
647	stat->family = socket->family;
648	stat->type = socket->type;
649	stat->protocol = socket->protocol;
650	stat->owner = socket->owner;
651	stat->state[0] = '\0';
652	memcpy(&stat->address, &socket->address, sizeof(struct sockaddr_storage));
653	memcpy(&stat->peer, &socket->peer, sizeof(struct sockaddr_storage));
654	stat->receive_queue_size = 0;
655	stat->send_queue_size = 0;
656
657	// fill in protocol specific data (if supported by the protocol)
658	size_t length = sizeof(net_stat);
659	socket->first_info->control(socket->first_protocol, socket->protocol,
660		NET_STAT_SOCKET, stat, &length);
661
662	return B_OK;
663}
664
665
666//	#pragma mark - connections
667
668
669bool
670socket_acquire(net_socket* _socket)
671{
672	net_socket_private* socket = (net_socket_private*)_socket;
673
674	// During destruction, the socket might still be accessible over its
675	// endpoint protocol. We need to make sure the endpoint cannot acquire the
676	// socket anymore -- while not obvious, the endpoint protocol is responsible
677	// for the proper locking here.
678	if (socket->CountReferences() == 0)
679		return false;
680
681	socket->AcquireReference();
682	return true;
683}
684
685
686bool
687socket_release(net_socket* _socket)
688{
689	net_socket_private* socket = (net_socket_private*)_socket;
690	return socket->ReleaseReference();
691}
692
693
694status_t
695socket_spawn_pending(net_socket* _parent, net_socket** _socket)
696{
697	net_socket_private* parent = (net_socket_private*)_parent;
698
699	TRACE("%s(%p)\n", __FUNCTION__, parent);
700
701	MutexLocker locker(parent->lock);
702
703	// We actually accept more pending connections to compensate for those
704	// that never complete, and also make sure at least a single connection
705	// can always be accepted
706	if (parent->child_count > 3 * parent->max_backlog / 2)
707		return ENOBUFS;
708
709	net_socket_private* socket;
710	status_t status = create_socket(parent->family, parent->type,
711		parent->protocol, &socket);
712	if (status != B_OK)
713		return status;
714
715	// inherit parent's properties
716	socket->send = parent->send;
717	socket->receive = parent->receive;
718	socket->options = parent->options & ~SO_ACCEPTCONN;
719	socket->linger = parent->linger;
720	socket->owner = parent->owner;
721	memcpy(&socket->address, &parent->address, parent->address.ss_len);
722	memcpy(&socket->peer, &parent->peer, parent->peer.ss_len);
723
724	// add to the parent's list of pending connections
725	parent->pending_children.Add(socket);
726	socket->parent = parent;
727	parent->child_count++;
728
729	*_socket = socket;
730	return B_OK;
731}
732
733
734/*!	Dequeues a connected child from a parent socket.
735	It also returns a reference with the child socket.
736*/
737status_t
738socket_dequeue_connected(net_socket* _parent, net_socket** _socket)
739{
740	net_socket_private* parent = (net_socket_private*)_parent;
741
742	mutex_lock(&parent->lock);
743
744	net_socket_private* socket = parent->connected_children.RemoveHead();
745	if (socket != NULL) {
746		socket->AcquireReference();
747		socket->RemoveFromParent();
748		parent->child_count--;
749		*_socket = socket;
750	}
751
752	mutex_unlock(&parent->lock);
753
754	if (socket == NULL)
755		return B_ENTRY_NOT_FOUND;
756
757	return B_OK;
758}
759
760
761ssize_t
762socket_count_connected(net_socket* _parent)
763{
764	net_socket_private* parent = (net_socket_private*)_parent;
765
766	MutexLocker _(parent->lock);
767	return parent->connected_children.Count();
768}
769
770
771status_t
772socket_set_max_backlog(net_socket* _socket, uint32 backlog)
773{
774	net_socket_private* socket = (net_socket_private*)_socket;
775
776	// we enforce an upper limit of connections waiting to be accepted
777	if (backlog > 256)
778		backlog = 256;
779
780	MutexLocker _(socket->lock);
781
782	// first remove the pending connections, then the already connected
783	// ones as needed
784	net_socket_private* child;
785	while (socket->child_count > backlog
786		&& (child = socket->pending_children.RemoveTail()) != NULL) {
787		child->RemoveFromParent();
788		socket->child_count--;
789	}
790	while (socket->child_count > backlog
791		&& (child = socket->connected_children.RemoveTail()) != NULL) {
792		child->RemoveFromParent();
793		socket->child_count--;
794	}
795
796	socket->max_backlog = backlog;
797	return B_OK;
798}
799
800
801/*!	Returns whether or not this socket has a parent. The parent might not be
802	valid anymore, though.
803*/
804bool
805socket_has_parent(net_socket* _socket)
806{
807	net_socket_private* socket = (net_socket_private*)_socket;
808	return socket->parent != NULL;
809}
810
811
812/*!	The socket has been connected. It will be moved to the connected queue
813	of its parent socket.
814*/
815status_t
816socket_connected(net_socket* _socket)
817{
818	net_socket_private* socket = (net_socket_private*)_socket;
819
820	TRACE("socket_connected(%p)\n", socket);
821
822	BReference<net_socket_private> parent = socket->parent.GetReference();
823	if (parent.Get() == NULL)
824		return B_BAD_VALUE;
825
826	MutexLocker _(parent->lock);
827
828	parent->pending_children.Remove(socket);
829	parent->connected_children.Add(socket);
830	socket->is_connected = true;
831
832	// notify parent
833	if (parent->select_pool)
834		notify_select_event_pool(parent->select_pool, B_SELECT_READ);
835
836	return B_OK;
837}
838
839
840/*!	The socket has been aborted. Steals the parent's reference, and releases
841	it.
842*/
843status_t
844socket_aborted(net_socket* _socket)
845{
846	net_socket_private* socket = (net_socket_private*)_socket;
847
848	TRACE("socket_aborted(%p)\n", socket);
849
850	BReference<net_socket_private> parent = socket->parent.GetReference();
851	if (parent.Get() == NULL)
852		return B_BAD_VALUE;
853
854	MutexLocker _(parent->lock);
855
856	if (socket->is_connected)
857		parent->connected_children.Remove(socket);
858	else
859		parent->pending_children.Remove(socket);
860
861	parent->child_count--;
862	socket->RemoveFromParent();
863
864	return B_OK;
865}
866
867
868//	#pragma mark - notifications
869
870
871status_t
872socket_request_notification(net_socket* _socket, uint8 event, selectsync* sync)
873{
874	net_socket_private* socket = (net_socket_private*)_socket;
875
876	mutex_lock(&socket->lock);
877
878	status_t status = add_select_sync_pool_entry(&socket->select_pool, sync,
879		event);
880
881	mutex_unlock(&socket->lock);
882
883	if (status != B_OK)
884		return status;
885
886	// check if the event is already present
887	// TODO: add support for poll() types
888
889	switch (event) {
890		case B_SELECT_READ:
891		{
892			ssize_t available = socket_read_avail(socket);
893			if ((ssize_t)socket->receive.low_water_mark <= available
894				|| available < B_OK)
895				notify_select_event(sync, event);
896			break;
897		}
898		case B_SELECT_WRITE:
899		{
900			ssize_t available = socket_send_avail(socket);
901			if ((ssize_t)socket->send.low_water_mark <= available
902				|| available < B_OK)
903				notify_select_event(sync, event);
904			break;
905		}
906		case B_SELECT_ERROR:
907			// TODO: B_SELECT_ERROR condition!
908			break;
909	}
910
911	return B_OK;
912}
913
914
915status_t
916socket_cancel_notification(net_socket* _socket, uint8 event, selectsync* sync)
917{
918	net_socket_private* socket = (net_socket_private*)_socket;
919
920	MutexLocker _(socket->lock);
921	return remove_select_sync_pool_entry(&socket->select_pool, sync, event);
922}
923
924
925status_t
926socket_notify(net_socket* _socket, uint8 event, int32 value)
927{
928	net_socket_private* socket = (net_socket_private*)_socket;
929	bool notify = true;
930
931	switch (event) {
932		case B_SELECT_READ:
933			if ((ssize_t)socket->receive.low_water_mark > value
934				&& value >= B_OK)
935				notify = false;
936			break;
937
938		case B_SELECT_WRITE:
939			if ((ssize_t)socket->send.low_water_mark > value && value >= B_OK)
940				notify = false;
941			break;
942
943		case B_SELECT_ERROR:
944			socket->error = value;
945			break;
946	}
947
948	MutexLocker _(socket->lock);
949
950	if (notify && socket->select_pool != NULL) {
951		notify_select_event_pool(socket->select_pool, event);
952
953		if (event == B_SELECT_ERROR) {
954			// always notify read/write on error
955			notify_select_event_pool(socket->select_pool, B_SELECT_READ);
956			notify_select_event_pool(socket->select_pool, B_SELECT_WRITE);
957		}
958	}
959
960	return B_OK;
961}
962
963
964//	#pragma mark - standard socket API
965
966
967int
968socket_accept(net_socket* socket, struct sockaddr* address,
969	socklen_t* _addressLength, net_socket** _acceptedSocket)
970{
971	if ((socket->options & SO_ACCEPTCONN) == 0)
972		return B_BAD_VALUE;
973
974	net_socket* accepted;
975	status_t status = socket->first_info->accept(socket->first_protocol,
976		&accepted);
977	if (status != B_OK)
978		return status;
979
980	if (address && *_addressLength > 0) {
981		memcpy(address, &accepted->peer, min_c(*_addressLength,
982			min_c(accepted->peer.ss_len, sizeof(sockaddr_storage))));
983		*_addressLength = accepted->peer.ss_len;
984	}
985
986	*_acceptedSocket = accepted;
987	return B_OK;
988}
989
990
991int
992socket_bind(net_socket* socket, const struct sockaddr* address,
993	socklen_t addressLength)
994{
995	sockaddr empty;
996	if (address == NULL) {
997		// special - try to bind to an empty address, like INADDR_ANY
998		memset(&empty, 0, sizeof(sockaddr));
999		empty.sa_len = sizeof(sockaddr);
1000		empty.sa_family = socket->family;
1001
1002		address = &empty;
1003		addressLength = sizeof(sockaddr);
1004	}
1005
1006	if (socket->address.ss_len != 0) {
1007		status_t status = socket->first_info->unbind(socket->first_protocol,
1008			(sockaddr*)&socket->address);
1009		if (status != B_OK)
1010			return status;
1011	}
1012
1013	memcpy(&socket->address, address, sizeof(sockaddr));
1014	socket->address.ss_len = sizeof(sockaddr_storage);
1015
1016	status_t status = socket->first_info->bind(socket->first_protocol,
1017		(sockaddr*)address);
1018	if (status != B_OK) {
1019		// clear address again, as binding failed
1020		socket->address.ss_len = 0;
1021	}
1022
1023	return status;
1024}
1025
1026
1027int
1028socket_connect(net_socket* socket, const struct sockaddr* address,
1029	socklen_t addressLength)
1030{
1031	if (address == NULL || addressLength == 0)
1032		return ENETUNREACH;
1033
1034	if (socket->address.ss_len == 0) {
1035		// try to bind first
1036		status_t status = socket_bind(socket, NULL, 0);
1037		if (status != B_OK)
1038			return status;
1039	}
1040
1041	return socket->first_info->connect(socket->first_protocol, address);
1042}
1043
1044
1045int
1046socket_getpeername(net_socket* socket, struct sockaddr* address,
1047	socklen_t* _addressLength)
1048{
1049	if (socket->peer.ss_len == 0)
1050		return ENOTCONN;
1051
1052	memcpy(address, &socket->peer, min_c(*_addressLength, socket->peer.ss_len));
1053	*_addressLength = socket->peer.ss_len;
1054	return B_OK;
1055}
1056
1057
1058int
1059socket_getsockname(net_socket* socket, struct sockaddr* address,
1060	socklen_t* _addressLength)
1061{
1062	if (socket->address.ss_len == 0)
1063		return ENOTCONN;
1064
1065	memcpy(address, &socket->address, min_c(*_addressLength,
1066		socket->address.ss_len));
1067	*_addressLength = socket->address.ss_len;
1068	return B_OK;
1069}
1070
1071
1072status_t
1073socket_get_option(net_socket* socket, int level, int option, void* value,
1074	int* _length)
1075{
1076	if (level != SOL_SOCKET)
1077		return ENOPROTOOPT;
1078
1079	switch (option) {
1080		case SO_SNDBUF:
1081		{
1082			uint32* size = (uint32*)value;
1083			*size = socket->send.buffer_size;
1084			*_length = sizeof(uint32);
1085			return B_OK;
1086		}
1087
1088		case SO_RCVBUF:
1089		{
1090			uint32* size = (uint32*)value;
1091			*size = socket->receive.buffer_size;
1092			*_length = sizeof(uint32);
1093			return B_OK;
1094		}
1095
1096		case SO_SNDLOWAT:
1097		{
1098			uint32* size = (uint32*)value;
1099			*size = socket->send.low_water_mark;
1100			*_length = sizeof(uint32);
1101			return B_OK;
1102		}
1103
1104		case SO_RCVLOWAT:
1105		{
1106			uint32* size = (uint32*)value;
1107			*size = socket->receive.low_water_mark;
1108			*_length = sizeof(uint32);
1109			return B_OK;
1110		}
1111
1112		case SO_RCVTIMEO:
1113		case SO_SNDTIMEO:
1114		{
1115			if (*_length < (int)sizeof(struct timeval))
1116				return B_BAD_VALUE;
1117
1118			bigtime_t timeout;
1119			if (option == SO_SNDTIMEO)
1120				timeout = socket->send.timeout;
1121			else
1122				timeout = socket->receive.timeout;
1123			if (timeout == B_INFINITE_TIMEOUT)
1124				timeout = 0;
1125
1126			struct timeval* timeval = (struct timeval*)value;
1127			timeval->tv_sec = timeout / 1000000LL;
1128			timeval->tv_usec = timeout % 1000000LL;
1129
1130			*_length = sizeof(struct timeval);
1131			return B_OK;
1132		}
1133
1134		case SO_NONBLOCK:
1135		{
1136			int32* _set = (int32*)value;
1137			*_set = socket->receive.timeout == 0 && socket->send.timeout == 0;
1138			*_length = sizeof(int32);
1139			return B_OK;
1140		}
1141
1142		case SO_ACCEPTCONN:
1143		case SO_BROADCAST:
1144		case SO_DEBUG:
1145		case SO_DONTROUTE:
1146		case SO_KEEPALIVE:
1147		case SO_OOBINLINE:
1148		case SO_REUSEADDR:
1149		case SO_REUSEPORT:
1150		case SO_USELOOPBACK:
1151		{
1152			int32* _set = (int32*)value;
1153			*_set = (socket->options & option) != 0;
1154			*_length = sizeof(int32);
1155			return B_OK;
1156		}
1157
1158		case SO_TYPE:
1159		{
1160			int32* _set = (int32*)value;
1161			*_set = socket->type;
1162			*_length = sizeof(int32);
1163			return B_OK;
1164		}
1165
1166		case SO_ERROR:
1167		{
1168			int32* _set = (int32*)value;
1169			*_set = socket->error;
1170			*_length = sizeof(int32);
1171
1172			socket->error = B_OK;
1173				// clear error upon retrieval
1174			return B_OK;
1175		}
1176
1177		default:
1178			break;
1179	}
1180
1181	dprintf("socket_getsockopt: unknown option %d\n", option);
1182	return ENOPROTOOPT;
1183}
1184
1185
1186int
1187socket_getsockopt(net_socket* socket, int level, int option, void* value,
1188	int* _length)
1189{
1190	return socket->first_protocol->module->getsockopt(socket->first_protocol,
1191		level, option, value, _length);
1192}
1193
1194
1195int
1196socket_listen(net_socket* socket, int backlog)
1197{
1198	status_t status = socket->first_info->listen(socket->first_protocol,
1199		backlog);
1200	if (status == B_OK)
1201		socket->options |= SO_ACCEPTCONN;
1202
1203	return status;
1204}
1205
1206
1207ssize_t
1208socket_receive(net_socket* socket, msghdr* header, void* data, size_t length,
1209	int flags)
1210{
1211	// If the protocol sports read_data_no_buffer() we use it.
1212	if (socket->first_info->read_data_no_buffer != NULL)
1213		return socket_receive_no_buffer(socket, header, data, length, flags);
1214
1215	size_t totalLength = length;
1216	net_buffer* buffer;
1217	int i;
1218
1219	// the convention to this function is that have header been
1220	// present, { data, length } would have been iovec[0] and is
1221	// always considered like that
1222
1223	if (header) {
1224		// calculate the length considering all of the extra buffers
1225		for (i = 1; i < header->msg_iovlen; i++)
1226			totalLength += header->msg_iov[i].iov_len;
1227	}
1228
1229	status_t status = socket->first_info->read_data(
1230		socket->first_protocol, totalLength, flags, &buffer);
1231	if (status != B_OK)
1232		return status;
1233
1234	// process ancillary data
1235	if (header != NULL) {
1236		if (buffer != NULL && header->msg_control != NULL) {
1237			ancillary_data_container* container
1238				= gNetBufferModule.get_ancillary_data(buffer);
1239			if (container != NULL)
1240				status = process_ancillary_data(socket, container, header);
1241			else
1242				status = process_ancillary_data(socket, buffer, header);
1243			if (status != B_OK) {
1244				gNetBufferModule.free(buffer);
1245				return status;
1246			}
1247		} else
1248			header->msg_controllen = 0;
1249	}
1250
1251	// TODO: - returning a NULL buffer when received 0 bytes
1252	//         may not make much sense as we still need the address
1253	//       - gNetBufferModule.read() uses memcpy() instead of user_memcpy
1254
1255	size_t nameLen = 0;
1256
1257	if (header) {
1258		// TODO: - consider the control buffer options
1259		nameLen = header->msg_namelen;
1260		header->msg_namelen = 0;
1261		header->msg_flags = 0;
1262	}
1263
1264	if (buffer == NULL)
1265		return 0;
1266
1267	size_t bytesReceived = buffer->size, bytesCopied = 0;
1268
1269	length = min_c(bytesReceived, length);
1270	if (gNetBufferModule.read(buffer, 0, data, length) < B_OK) {
1271		gNetBufferModule.free(buffer);
1272		return ENOBUFS;
1273	}
1274
1275	// if first copy was a success, proceed to following
1276	// copies as required
1277	bytesCopied += length;
1278
1279	if (header) {
1280		// we only start considering at iovec[1]
1281		// as { data, length } is iovec[0]
1282		for (i = 1; i < header->msg_iovlen && bytesCopied < bytesReceived; i++) {
1283			iovec& vec = header->msg_iov[i];
1284			size_t toRead = min_c(bytesReceived - bytesCopied, vec.iov_len);
1285			if (gNetBufferModule.read(buffer, bytesCopied, vec.iov_base,
1286					toRead) < B_OK) {
1287				break;
1288			}
1289
1290			bytesCopied += toRead;
1291		}
1292
1293		if (header->msg_name != NULL) {
1294			header->msg_namelen = min_c(nameLen, buffer->source->sa_len);
1295			memcpy(header->msg_name, buffer->source, header->msg_namelen);
1296		}
1297	}
1298
1299	gNetBufferModule.free(buffer);
1300
1301	if (bytesCopied < bytesReceived) {
1302		if (header)
1303			header->msg_flags = MSG_TRUNC;
1304
1305		if (flags & MSG_TRUNC)
1306			return bytesReceived;
1307	}
1308
1309	return bytesCopied;
1310}
1311
1312
1313ssize_t
1314socket_send(net_socket* socket, msghdr* header, const void* data, size_t length,
1315	int flags)
1316{
1317	const sockaddr* address = NULL;
1318	socklen_t addressLength = 0;
1319	size_t bytesLeft = length;
1320
1321	if (length > SSIZE_MAX)
1322		return B_BAD_VALUE;
1323
1324	ancillary_data_container* ancillaryData = NULL;
1325	CObjectDeleter<ancillary_data_container> ancillaryDataDeleter(NULL,
1326		&delete_ancillary_data_container);
1327
1328	if (header != NULL) {
1329		address = (const sockaddr*)header->msg_name;
1330		addressLength = header->msg_namelen;
1331
1332		// get the ancillary data
1333		if (header->msg_control != NULL) {
1334			ancillaryData = create_ancillary_data_container();
1335			if (ancillaryData == NULL)
1336				return B_NO_MEMORY;
1337			ancillaryDataDeleter.SetTo(ancillaryData);
1338
1339			status_t status = add_ancillary_data(socket, ancillaryData,
1340				(cmsghdr*)header->msg_control, header->msg_controllen);
1341			if (status != B_OK)
1342				return status;
1343		}
1344	}
1345
1346	if (addressLength == 0)
1347		address = NULL;
1348	else if (address == NULL)
1349		return B_BAD_VALUE;
1350
1351	if (socket->peer.ss_len != 0) {
1352		if (address != NULL)
1353			return EISCONN;
1354
1355		// socket is connected, we use that address
1356		address = (struct sockaddr*)&socket->peer;
1357		addressLength = socket->peer.ss_len;
1358	}
1359
1360	if (address == NULL || addressLength == 0) {
1361		// don't know where to send to:
1362		return EDESTADDRREQ;
1363	}
1364
1365	if ((socket->first_info->flags & NET_PROTOCOL_ATOMIC_MESSAGES) != 0
1366		&& bytesLeft > socket->send.buffer_size)
1367		return EMSGSIZE;
1368
1369	if (socket->address.ss_len == 0) {
1370		// try to bind first
1371		status_t status = socket_bind(socket, NULL, 0);
1372		if (status != B_OK)
1373			return status;
1374	}
1375
1376	// If the protocol has a send_data_no_buffer() hook, we use that one.
1377	if (socket->first_info->send_data_no_buffer != NULL) {
1378		iovec stackVec = { (void*)data, length };
1379		iovec* vecs = header ? header->msg_iov : &stackVec;
1380		int vecCount = header ? header->msg_iovlen : 1;
1381
1382		ssize_t written = socket->first_info->send_data_no_buffer(
1383			socket->first_protocol, vecs, vecCount, ancillaryData, address,
1384			addressLength);
1385		if (written > 0)
1386			ancillaryDataDeleter.Detach();
1387		return written;
1388	}
1389
1390	// By convention, if a header is given, the (data, length) equals the first
1391	// iovec. So drop the header, if it is the only iovec. Otherwise compute
1392	// the size of the remaining ones.
1393	if (header != NULL) {
1394		if (header->msg_iovlen <= 1)
1395			header = NULL;
1396		else {
1397// TODO: The iovecs have already been copied to kernel space. Simplify!
1398			bytesLeft += compute_user_iovec_length(header->msg_iov + 1,
1399				header->msg_iovlen - 1);
1400		}
1401	}
1402
1403	ssize_t bytesSent = 0;
1404	size_t vecOffset = 0;
1405	uint32 vecIndex = 0;
1406
1407	while (bytesLeft > 0) {
1408		// TODO: useful, maybe even computed header space!
1409		net_buffer* buffer = gNetBufferModule.create(256);
1410		if (buffer == NULL)
1411			return ENOBUFS;
1412
1413		while (buffer->size < socket->send.buffer_size
1414			&& buffer->size < bytesLeft) {
1415			if (vecIndex > 0 && vecOffset == 0) {
1416				// retrieve next iovec buffer from header
1417				iovec vec;
1418				if (user_memcpy(&vec, header->msg_iov + vecIndex, sizeof(iovec))
1419						< B_OK) {
1420					gNetBufferModule.free(buffer);
1421					return B_BAD_ADDRESS;
1422				}
1423
1424				data = vec.iov_base;
1425				length = vec.iov_len;
1426			}
1427
1428			size_t bytes = length;
1429			if (buffer->size + bytes > socket->send.buffer_size)
1430				bytes = socket->send.buffer_size - buffer->size;
1431
1432			if (gNetBufferModule.append(buffer, data, bytes) < B_OK) {
1433				gNetBufferModule.free(buffer);
1434				return ENOBUFS;
1435			}
1436
1437			if (bytes != length) {
1438				// partial send
1439				vecOffset = bytes;
1440				length -= vecOffset;
1441				data = (uint8*)data + vecOffset;
1442			} else if (header != NULL) {
1443				// proceed with next buffer, if any
1444				vecOffset = 0;
1445				vecIndex++;
1446
1447				if (vecIndex >= (uint32)header->msg_iovlen)
1448					break;
1449			}
1450		}
1451
1452		// attach ancillary data to the first buffer
1453		status_t status = B_OK;
1454		if (ancillaryData != NULL) {
1455			gNetBufferModule.set_ancillary_data(buffer, ancillaryData);
1456			ancillaryDataDeleter.Detach();
1457			ancillaryData = NULL;
1458		}
1459
1460		size_t bufferSize = buffer->size;
1461		buffer->flags = flags;
1462		memcpy(buffer->source, &socket->address, socket->address.ss_len);
1463		memcpy(buffer->destination, address, addressLength);
1464		buffer->destination->sa_len = addressLength;
1465
1466		if (status == B_OK) {
1467			status = socket->first_info->send_data(socket->first_protocol,
1468				buffer);
1469		}
1470		if (status != B_OK) {
1471			size_t sizeAfterSend = buffer->size;
1472			gNetBufferModule.free(buffer);
1473
1474			if ((sizeAfterSend != bufferSize || bytesSent > 0)
1475				&& (status == B_INTERRUPTED || status == B_WOULD_BLOCK)) {
1476				// this appears to be a partial write
1477				return bytesSent + (bufferSize - sizeAfterSend);
1478			}
1479			return status;
1480		}
1481
1482		bytesLeft -= bufferSize;
1483		bytesSent += bufferSize;
1484	}
1485
1486	return bytesSent;
1487}
1488
1489
1490status_t
1491socket_set_option(net_socket* socket, int level, int option, const void* value,
1492	int length)
1493{
1494	if (level != SOL_SOCKET)
1495		return ENOPROTOOPT;
1496
1497	TRACE("%s(socket %p, option %d\n", __FUNCTION__, socket, option);
1498
1499	switch (option) {
1500		// TODO: implement other options!
1501		case SO_LINGER:
1502		{
1503			if (length < (int)sizeof(struct linger))
1504				return B_BAD_VALUE;
1505
1506			struct linger* linger = (struct linger*)value;
1507			if (linger->l_onoff) {
1508				socket->options |= SO_LINGER;
1509				socket->linger = linger->l_linger;
1510			} else {
1511				socket->options &= ~SO_LINGER;
1512				socket->linger = 0;
1513			}
1514			return B_OK;
1515		}
1516
1517		case SO_SNDBUF:
1518			if (length != sizeof(uint32))
1519				return B_BAD_VALUE;
1520
1521			socket->send.buffer_size = *(const uint32*)value;
1522			return B_OK;
1523
1524		case SO_RCVBUF:
1525			if (length != sizeof(uint32))
1526				return B_BAD_VALUE;
1527
1528			socket->receive.buffer_size = *(const uint32*)value;
1529			return B_OK;
1530
1531		case SO_SNDLOWAT:
1532			if (length != sizeof(uint32))
1533				return B_BAD_VALUE;
1534
1535			socket->send.low_water_mark = *(const uint32*)value;
1536			return B_OK;
1537
1538		case SO_RCVLOWAT:
1539			if (length != sizeof(uint32))
1540				return B_BAD_VALUE;
1541
1542			socket->receive.low_water_mark = *(const uint32*)value;
1543			return B_OK;
1544
1545		case SO_RCVTIMEO:
1546		case SO_SNDTIMEO:
1547		{
1548			if (length != sizeof(struct timeval))
1549				return B_BAD_VALUE;
1550
1551			const struct timeval* timeval = (const struct timeval*)value;
1552			bigtime_t timeout = timeval->tv_sec * 1000000LL + timeval->tv_usec;
1553			if (timeout == 0)
1554				timeout = B_INFINITE_TIMEOUT;
1555
1556			if (option == SO_SNDTIMEO)
1557				socket->send.timeout = timeout;
1558			else
1559				socket->receive.timeout = timeout;
1560			return B_OK;
1561		}
1562
1563		case SO_NONBLOCK:
1564			if (length != sizeof(int32))
1565				return B_BAD_VALUE;
1566
1567			if (*(const int32*)value) {
1568				socket->send.timeout = 0;
1569				socket->receive.timeout = 0;
1570			} else {
1571				socket->send.timeout = B_INFINITE_TIMEOUT;
1572				socket->receive.timeout = B_INFINITE_TIMEOUT;
1573			}
1574			return B_OK;
1575
1576		case SO_BROADCAST:
1577		case SO_DEBUG:
1578		case SO_DONTROUTE:
1579		case SO_KEEPALIVE:
1580		case SO_OOBINLINE:
1581		case SO_REUSEADDR:
1582		case SO_REUSEPORT:
1583		case SO_USELOOPBACK:
1584			if (length != sizeof(int32))
1585				return B_BAD_VALUE;
1586
1587			if (*(const int32*)value)
1588				socket->options |= option;
1589			else
1590				socket->options &= ~option;
1591			return B_OK;
1592
1593		case SO_BINDTODEVICE:
1594		{
1595			if (length != sizeof(uint32))
1596				return B_BAD_VALUE;
1597
1598			// TODO: we might want to check if the device exists at all
1599			// (although it doesn't really harm when we don't)
1600			socket->bound_to_device = *(const uint32*)value;
1601			return B_OK;
1602		}
1603
1604		default:
1605			break;
1606	}
1607
1608	dprintf("socket_setsockopt: unknown option %d\n", option);
1609	return ENOPROTOOPT;
1610}
1611
1612
1613int
1614socket_setsockopt(net_socket* socket, int level, int option, const void* value,
1615	int length)
1616{
1617	return socket->first_protocol->module->setsockopt(socket->first_protocol,
1618		level, option, value, length);
1619}
1620
1621
1622int
1623socket_shutdown(net_socket* socket, int direction)
1624{
1625	return socket->first_info->shutdown(socket->first_protocol, direction);
1626}
1627
1628
1629status_t
1630socket_socketpair(int family, int type, int protocol, net_socket* sockets[2])
1631{
1632	sockets[0] = NULL;
1633	sockets[1] = NULL;
1634
1635	// create sockets
1636	status_t error = socket_open(family, type, protocol, &sockets[0]);
1637	if (error != B_OK)
1638		return error;
1639
1640	if (error == B_OK)
1641		error = socket_open(family, type, protocol, &sockets[1]);
1642
1643	// bind one
1644	if (error == B_OK)
1645		error = socket_bind(sockets[0], NULL, 0);
1646
1647	// start listening
1648	if (error == B_OK)
1649		error = socket_listen(sockets[0], 1);
1650
1651	// connect them
1652	if (error == B_OK) {
1653		error = socket_connect(sockets[1], (sockaddr*)&sockets[0]->address,
1654			sockets[0]->address.ss_len);
1655	}
1656
1657	// accept a socket
1658	net_socket* acceptedSocket = NULL;
1659	if (error == B_OK)
1660		error = socket_accept(sockets[0], NULL, NULL, &acceptedSocket);
1661
1662	if (error == B_OK) {
1663		// everything worked: close the listener socket
1664		socket_close(sockets[0]);
1665		socket_free(sockets[0]);
1666		sockets[0] = acceptedSocket;
1667	} else {
1668		// close sockets on error
1669		for (int i = 0; i < 2; i++) {
1670			if (sockets[i] != NULL) {
1671				socket_close(sockets[i]);
1672				socket_free(sockets[i]);
1673				sockets[i] = NULL;
1674			}
1675		}
1676	}
1677
1678	return error;
1679}
1680
1681
1682//	#pragma mark -
1683
1684
1685static status_t
1686socket_std_ops(int32 op, ...)
1687{
1688	switch (op) {
1689		case B_MODULE_INIT:
1690		{
1691			new (&sSocketList) SocketList;
1692			mutex_init(&sSocketLock, "socket list");
1693
1694#if ENABLE_DEBUGGER_COMMANDS
1695			add_debugger_command("sockets", dump_sockets, "lists all sockets");
1696			add_debugger_command("socket", dump_socket, "dumps a socket");
1697#endif
1698			return B_OK;
1699		}
1700		case B_MODULE_UNINIT:
1701			ASSERT(sSocketList.IsEmpty());
1702			mutex_destroy(&sSocketLock);
1703
1704#if ENABLE_DEBUGGER_COMMANDS
1705			remove_debugger_command("socket", dump_socket);
1706			remove_debugger_command("sockets", dump_sockets);
1707#endif
1708			return B_OK;
1709
1710		default:
1711			return B_ERROR;
1712	}
1713}
1714
1715
1716net_socket_module_info gNetSocketModule = {
1717	{
1718		NET_SOCKET_MODULE_NAME,
1719		0,
1720		socket_std_ops
1721	},
1722	socket_open,
1723	socket_close,
1724	socket_free,
1725
1726	socket_readv,
1727	socket_writev,
1728	socket_control,
1729
1730	socket_read_avail,
1731	socket_send_avail,
1732
1733	socket_send_data,
1734	socket_receive_data,
1735
1736	socket_get_option,
1737	socket_set_option,
1738
1739	socket_get_next_stat,
1740
1741	// connections
1742	socket_acquire,
1743	socket_release,
1744	socket_spawn_pending,
1745	socket_dequeue_connected,
1746	socket_count_connected,
1747	socket_set_max_backlog,
1748	socket_has_parent,
1749	socket_connected,
1750	socket_aborted,
1751
1752	// notifications
1753	socket_request_notification,
1754	socket_cancel_notification,
1755	socket_notify,
1756
1757	// standard socket API
1758	socket_accept,
1759	socket_bind,
1760	socket_connect,
1761	socket_getpeername,
1762	socket_getsockname,
1763	socket_getsockopt,
1764	socket_listen,
1765	socket_receive,
1766	socket_send,
1767	socket_setsockopt,
1768	socket_shutdown,
1769	socket_socketpair
1770};
1771
1772