xref: /haiku/src/kits/network/libnetapi/NetEndpoint.cpp (revision 49a22456ddda2a7cfc5c19d9ccc131125b8b690c)
1241b0480SAxel Dörfler /*
2*49a22456SOliver Tappe  * Copyright 2002-2008, Haiku, Inc. All Rights Reserved.
3241b0480SAxel Dörfler  * Distributed under the terms of the MIT License.
4241b0480SAxel Dörfler  */
56fdccb80SAxel Dörfler 
66fdccb80SAxel Dörfler #include <Message.h>
76fdccb80SAxel Dörfler #include <NetEndpoint.h>
86fdccb80SAxel Dörfler 
9241b0480SAxel Dörfler #include <errno.h>
10241b0480SAxel Dörfler #include <fcntl.h>
11241b0480SAxel Dörfler #include <netdb.h>
12241b0480SAxel Dörfler #include <netinet/in.h>
13241b0480SAxel Dörfler #include <new>
14241b0480SAxel Dörfler #include <string.h>
15241b0480SAxel Dörfler #include <sys/socket.h>
16241b0480SAxel Dörfler #include <sys/time.h>
17241b0480SAxel Dörfler #include <sys/types.h>
18241b0480SAxel Dörfler #include <unistd.h>
196fdccb80SAxel Dörfler 
20241b0480SAxel Dörfler 
21241b0480SAxel Dörfler BNetEndpoint::BNetEndpoint(int type)
22241b0480SAxel Dörfler 	:
23*49a22456SOliver Tappe 	fStatus(B_NO_INIT),
24*49a22456SOliver Tappe 	fFamily(AF_INET),
25*49a22456SOliver Tappe 	fType(type),
26*49a22456SOliver Tappe 	fProtocol(0),
27241b0480SAxel Dörfler 	fSocket(-1),
28*49a22456SOliver Tappe 	fTimeout(B_INFINITE_TIMEOUT)
29241b0480SAxel Dörfler {
30*49a22456SOliver Tappe 	_SetupSocket();
316fdccb80SAxel Dörfler }
326fdccb80SAxel Dörfler 
336fdccb80SAxel Dörfler 
346fdccb80SAxel Dörfler BNetEndpoint::BNetEndpoint(int family, int type, int protocol)
35241b0480SAxel Dörfler 	:
36*49a22456SOliver Tappe 	fStatus(B_NO_INIT),
37*49a22456SOliver Tappe 	fFamily(family),
38*49a22456SOliver Tappe 	fType(type),
39*49a22456SOliver Tappe 	fProtocol(protocol),
40241b0480SAxel Dörfler 	fSocket(-1),
41*49a22456SOliver Tappe 	fTimeout(B_INFINITE_TIMEOUT)
426fdccb80SAxel Dörfler {
43*49a22456SOliver Tappe 	_SetupSocket();
446fdccb80SAxel Dörfler }
456fdccb80SAxel Dörfler 
466fdccb80SAxel Dörfler 
476fdccb80SAxel Dörfler BNetEndpoint::BNetEndpoint(BMessage* archive)
48241b0480SAxel Dörfler 	:
49*49a22456SOliver Tappe 	fStatus(B_NO_INIT),
50*49a22456SOliver Tappe 	fFamily(AF_INET),
51*49a22456SOliver Tappe 	fProtocol(0),
52241b0480SAxel Dörfler 	fSocket(-1),
53*49a22456SOliver Tappe 	fTimeout(B_INFINITE_TIMEOUT)
546fdccb80SAxel Dörfler {
556fdccb80SAxel Dörfler 	if (!archive)
566fdccb80SAxel Dörfler 		return;
576fdccb80SAxel Dörfler 
58*49a22456SOliver Tappe 	in_addr addr, peer;
59*49a22456SOliver Tappe 	unsigned short addrPort = 0, peerPort = 0;
606fdccb80SAxel Dörfler 
61*49a22456SOliver Tappe 	fStatus = archive->FindInt32("_BNetEndpoint_addr_addr",
62*49a22456SOliver Tappe 		(int32 *)&addr.s_addr);
63*49a22456SOliver Tappe 	if (fStatus == B_OK) {
64*49a22456SOliver Tappe 		fStatus = archive->FindInt16("_BNetEndpoint_addr_port",
65*49a22456SOliver Tappe 			(int16 *)&addrPort);
66*49a22456SOliver Tappe 		if (fStatus == B_OK)
67*49a22456SOliver Tappe 			fStatus = fAddr.SetTo(addr, addrPort);
68*49a22456SOliver Tappe 	}
696fdccb80SAxel Dörfler 
70*49a22456SOliver Tappe 	fStatus = archive->FindInt32("_BNetEndpoint_peer_addr",
71*49a22456SOliver Tappe 		(int32 *)&peer.s_addr);
72*49a22456SOliver Tappe 	if (fStatus == B_OK) {
73*49a22456SOliver Tappe 		fStatus = archive->FindInt16("_BNetEndpoint_peer_port",
74*49a22456SOliver Tappe 			(int16 *)&peerPort);
75*49a22456SOliver Tappe 		if (fStatus == B_OK)
76*49a22456SOliver Tappe 			fStatus = fPeer.SetTo(peer, peerPort);
77*49a22456SOliver Tappe 	}
78*49a22456SOliver Tappe 
79*49a22456SOliver Tappe 	fStatus = archive->FindInt64("_BNetEndpoint_timeout", (int64 *)&fTimeout);
80*49a22456SOliver Tappe 	if (fStatus == B_OK)
81*49a22456SOliver Tappe 		fStatus = archive->FindInt32("_BNetEndpoint_proto", (int32 *)&fType);
82*49a22456SOliver Tappe 
83*49a22456SOliver Tappe 	if (fStatus == B_OK)
84*49a22456SOliver Tappe 		_SetupSocket();
856fdccb80SAxel Dörfler }
866fdccb80SAxel Dörfler 
876fdccb80SAxel Dörfler 
88241b0480SAxel Dörfler BNetEndpoint::BNetEndpoint(const BNetEndpoint& endpoint)
89241b0480SAxel Dörfler 	:
90*49a22456SOliver Tappe 	fStatus(endpoint.fStatus),
91*49a22456SOliver Tappe 	fFamily(endpoint.fFamily),
92*49a22456SOliver Tappe 	fType(endpoint.fType),
93*49a22456SOliver Tappe 	fProtocol(endpoint.fProtocol),
94*49a22456SOliver Tappe 	fSocket(-1),
95241b0480SAxel Dörfler 	fTimeout(endpoint.fTimeout),
96241b0480SAxel Dörfler 	fAddr(endpoint.fAddr),
97241b0480SAxel Dörfler 	fPeer(endpoint.fPeer)
98*49a22456SOliver Tappe 
996fdccb80SAxel Dörfler {
100241b0480SAxel Dörfler 	if (endpoint.fSocket >= 0) {
101241b0480SAxel Dörfler 		fSocket = dup(endpoint.fSocket);
102*49a22456SOliver Tappe 		if (fSocket < 0)
103*49a22456SOliver Tappe 			fStatus = errno;
104241b0480SAxel Dörfler 	}
1056fdccb80SAxel Dörfler }
1066fdccb80SAxel Dörfler 
1076fdccb80SAxel Dörfler 
108241b0480SAxel Dörfler BNetEndpoint&
109241b0480SAxel Dörfler BNetEndpoint::operator=(const BNetEndpoint& endpoint)
1106fdccb80SAxel Dörfler {
111*49a22456SOliver Tappe 	if (this == &endpoint)
112*49a22456SOliver Tappe 		return *this;
113*49a22456SOliver Tappe 
1146fdccb80SAxel Dörfler 	Close();
1156fdccb80SAxel Dörfler 
116*49a22456SOliver Tappe 	fStatus = endpoint.fStatus;
117*49a22456SOliver Tappe 	fFamily = endpoint.fFamily;
118*49a22456SOliver Tappe 	fType = endpoint.fType;
119*49a22456SOliver Tappe 	fProtocol = endpoint.fProtocol;
120241b0480SAxel Dörfler 	fTimeout = endpoint.fTimeout;
121241b0480SAxel Dörfler 	fAddr = endpoint.fAddr;
122241b0480SAxel Dörfler 	fPeer = endpoint.fPeer;
1236fdccb80SAxel Dörfler 
124241b0480SAxel Dörfler 	fSocket = -1;
125241b0480SAxel Dörfler 	if (endpoint.fSocket >= 0) {
126241b0480SAxel Dörfler 		fSocket = dup(endpoint.fSocket);
127*49a22456SOliver Tappe 		if (fSocket < 0)
128*49a22456SOliver Tappe 			fStatus = errno;
129241b0480SAxel Dörfler 	}
1306fdccb80SAxel Dörfler 
1316fdccb80SAxel Dörfler     return *this;
1326fdccb80SAxel Dörfler }
1336fdccb80SAxel Dörfler 
134241b0480SAxel Dörfler 
1356fdccb80SAxel Dörfler BNetEndpoint::~BNetEndpoint()
1366fdccb80SAxel Dörfler {
137*49a22456SOliver Tappe 	if (fSocket >= 0)
1386fdccb80SAxel Dörfler 		Close();
1396fdccb80SAxel Dörfler }
1406fdccb80SAxel Dörfler 
141241b0480SAxel Dörfler 
1426fdccb80SAxel Dörfler // #pragma mark -
1436fdccb80SAxel Dörfler 
144241b0480SAxel Dörfler 
145241b0480SAxel Dörfler status_t
146241b0480SAxel Dörfler BNetEndpoint::Archive(BMessage* into, bool deep) const
1476fdccb80SAxel Dörfler {
148*49a22456SOliver Tappe 	if (!into)
1496fdccb80SAxel Dörfler 		return B_ERROR;
1506fdccb80SAxel Dörfler 
151*49a22456SOliver Tappe 	status_t status = BArchivable::Archive(into, deep);
152*49a22456SOliver Tappe 	if (status != B_OK)
153*49a22456SOliver Tappe 		return status;
1546fdccb80SAxel Dörfler 
155*49a22456SOliver Tappe 	in_addr addr, peer;
156*49a22456SOliver Tappe 	unsigned short addrPort, peerPort;
1576fdccb80SAxel Dörfler 
158*49a22456SOliver Tappe 	status = fAddr.GetAddr(addr, &addrPort);
159*49a22456SOliver Tappe 	if (status == B_OK) {
160*49a22456SOliver Tappe 		status = into->AddInt32("_BNetEndpoint_addr_addr", addr.s_addr);
161*49a22456SOliver Tappe 		if (status == B_OK)
162*49a22456SOliver Tappe 			status = into->AddInt16("_BNetEndpoint_addr_port", addrPort);
163*49a22456SOliver Tappe 		if (status != B_OK)
164*49a22456SOliver Tappe 			return status;
165*49a22456SOliver Tappe 	}
166*49a22456SOliver Tappe 	status = fPeer.GetAddr(peer, &peerPort);
167*49a22456SOliver Tappe 	if (status == B_OK) {
168*49a22456SOliver Tappe 		status = into->AddInt32("_BNetEndpoint_peer_addr", peer.s_addr);
169*49a22456SOliver Tappe 		if (status == B_OK)
170*49a22456SOliver Tappe 			status = into->AddInt16("_BNetEndpoint_peer_port", peerPort);
171*49a22456SOliver Tappe 		if (status != B_OK)
172*49a22456SOliver Tappe 			return status;
173*49a22456SOliver Tappe 	}
1746fdccb80SAxel Dörfler 
175*49a22456SOliver Tappe 	status = into->AddInt64("_BNetEndpoint_timeout", fTimeout);
176*49a22456SOliver Tappe 	if (status == B_OK)
177*49a22456SOliver Tappe 		status = into->AddInt32("_BNetEndpoint_proto", fType);
178*49a22456SOliver Tappe 
179*49a22456SOliver Tappe 	return status;
1806fdccb80SAxel Dörfler }
1816fdccb80SAxel Dörfler 
1826fdccb80SAxel Dörfler 
183241b0480SAxel Dörfler BArchivable*
184241b0480SAxel Dörfler BNetEndpoint::Instantiate(BMessage* archive)
1856fdccb80SAxel Dörfler {
1866fdccb80SAxel Dörfler 	if (!archive)
1876fdccb80SAxel Dörfler 		return NULL;
1886fdccb80SAxel Dörfler 
189*49a22456SOliver Tappe 	if (!validate_instantiation(archive, "BNetEndpoint"))
1906fdccb80SAxel Dörfler 		return NULL;
1916fdccb80SAxel Dörfler 
192241b0480SAxel Dörfler 	BNetEndpoint* endpoint = new BNetEndpoint(archive);
193241b0480SAxel Dörfler 	if (endpoint && endpoint->InitCheck() == B_OK)
194241b0480SAxel Dörfler 		return endpoint;
1956fdccb80SAxel Dörfler 
196241b0480SAxel Dörfler 	delete endpoint;
1976fdccb80SAxel Dörfler 	return NULL;
1986fdccb80SAxel Dörfler }
1996fdccb80SAxel Dörfler 
200241b0480SAxel Dörfler 
2016fdccb80SAxel Dörfler // #pragma mark -
2026fdccb80SAxel Dörfler 
2036fdccb80SAxel Dörfler 
204241b0480SAxel Dörfler status_t
205*49a22456SOliver Tappe BNetEndpoint::InitCheck() const
2066fdccb80SAxel Dörfler {
207*49a22456SOliver Tappe 	return fSocket == -1 ? B_NO_INIT : B_OK;
2086fdccb80SAxel Dörfler }
2096fdccb80SAxel Dörfler 
2106fdccb80SAxel Dörfler 
211241b0480SAxel Dörfler int
212241b0480SAxel Dörfler BNetEndpoint::Socket() const
2136fdccb80SAxel Dörfler {
214241b0480SAxel Dörfler 	return fSocket;
2156fdccb80SAxel Dörfler }
2166fdccb80SAxel Dörfler 
2176fdccb80SAxel Dörfler 
218241b0480SAxel Dörfler const BNetAddress&
219*49a22456SOliver Tappe BNetEndpoint::LocalAddr() const
2206fdccb80SAxel Dörfler {
221241b0480SAxel Dörfler 	return fAddr;
2226fdccb80SAxel Dörfler }
2236fdccb80SAxel Dörfler 
2246fdccb80SAxel Dörfler 
225241b0480SAxel Dörfler const BNetAddress&
226*49a22456SOliver Tappe BNetEndpoint::RemoteAddr() const
2276fdccb80SAxel Dörfler {
228241b0480SAxel Dörfler 	return fPeer;
2296fdccb80SAxel Dörfler }
2306fdccb80SAxel Dörfler 
2316fdccb80SAxel Dörfler 
232241b0480SAxel Dörfler status_t
233241b0480SAxel Dörfler BNetEndpoint::SetProtocol(int protocol)
2346fdccb80SAxel Dörfler {
2356fdccb80SAxel Dörfler 	Close();
236*49a22456SOliver Tappe 	fType = protocol;	// sic (protocol is SOCK_DGRAM or SOCK_STREAM)
237*49a22456SOliver Tappe 	return _SetupSocket();
2386fdccb80SAxel Dörfler }
2396fdccb80SAxel Dörfler 
2406fdccb80SAxel Dörfler 
241241b0480SAxel Dörfler int
242241b0480SAxel Dörfler BNetEndpoint::SetOption(int32 option, int32 level,
2436fdccb80SAxel Dörfler 	const void* data, unsigned int length)
2446fdccb80SAxel Dörfler {
245*49a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
246*49a22456SOliver Tappe 		return fStatus;
2476fdccb80SAxel Dörfler 
248241b0480SAxel Dörfler 	if (setsockopt(fSocket, level, option, data, length) < 0) {
249*49a22456SOliver Tappe 		fStatus = errno;
2506fdccb80SAxel Dörfler 		return B_ERROR;
2516fdccb80SAxel Dörfler 	}
252241b0480SAxel Dörfler 
2536fdccb80SAxel Dörfler 	return B_OK;
2546fdccb80SAxel Dörfler }
2556fdccb80SAxel Dörfler 
2566fdccb80SAxel Dörfler 
257241b0480SAxel Dörfler int
258241b0480SAxel Dörfler BNetEndpoint::SetNonBlocking(bool enable)
2596fdccb80SAxel Dörfler {
260*49a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
261*49a22456SOliver Tappe 		return fStatus;
262*49a22456SOliver Tappe 
263241b0480SAxel Dörfler 	int flags = fcntl(fSocket, F_GETFL);
264241b0480SAxel Dörfler 	if (flags < 0) {
265*49a22456SOliver Tappe 		fStatus = errno;
266241b0480SAxel Dörfler 		return B_ERROR;
267241b0480SAxel Dörfler 	}
2686fdccb80SAxel Dörfler 
2696fdccb80SAxel Dörfler 	if (enable)
2706fdccb80SAxel Dörfler 		flags |= O_NONBLOCK;
2716fdccb80SAxel Dörfler 	else
2726fdccb80SAxel Dörfler 		flags &= ~O_NONBLOCK;
2736fdccb80SAxel Dörfler 
274241b0480SAxel Dörfler 	if (fcntl(fSocket, F_SETFL, flags) < 0) {
275*49a22456SOliver Tappe 		fStatus = errno;
2766fdccb80SAxel Dörfler 		return B_ERROR;
2776fdccb80SAxel Dörfler 	}
2786fdccb80SAxel Dörfler 
2796fdccb80SAxel Dörfler 	return B_OK;
2806fdccb80SAxel Dörfler }
2816fdccb80SAxel Dörfler 
2826fdccb80SAxel Dörfler 
283241b0480SAxel Dörfler int
284241b0480SAxel Dörfler BNetEndpoint::SetReuseAddr(bool enable)
2856fdccb80SAxel Dörfler {
286*49a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
287*49a22456SOliver Tappe 		return fStatus;
288*49a22456SOliver Tappe 
2896fdccb80SAxel Dörfler 	int onoff = (int) enable;
2906fdccb80SAxel Dörfler 	return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff));
2916fdccb80SAxel Dörfler }
2926fdccb80SAxel Dörfler 
2936fdccb80SAxel Dörfler 
294241b0480SAxel Dörfler void
295241b0480SAxel Dörfler BNetEndpoint::SetTimeout(bigtime_t timeout)
2966fdccb80SAxel Dörfler {
297241b0480SAxel Dörfler 	fTimeout = timeout;
2986fdccb80SAxel Dörfler }
2996fdccb80SAxel Dörfler 
3006fdccb80SAxel Dörfler 
301241b0480SAxel Dörfler int
302241b0480SAxel Dörfler BNetEndpoint::Error() const
3036fdccb80SAxel Dörfler {
304*49a22456SOliver Tappe 	return (int)fStatus;
3056fdccb80SAxel Dörfler }
3066fdccb80SAxel Dörfler 
3076fdccb80SAxel Dörfler 
308241b0480SAxel Dörfler char*
309241b0480SAxel Dörfler BNetEndpoint::ErrorStr() const
3106fdccb80SAxel Dörfler {
311*49a22456SOliver Tappe 	return strerror(fStatus);
3126fdccb80SAxel Dörfler }
3136fdccb80SAxel Dörfler 
3146fdccb80SAxel Dörfler 
3156fdccb80SAxel Dörfler // #pragma mark -
3166fdccb80SAxel Dörfler 
317241b0480SAxel Dörfler 
318241b0480SAxel Dörfler void
319241b0480SAxel Dörfler BNetEndpoint::Close()
3206fdccb80SAxel Dörfler {
321241b0480SAxel Dörfler 	if (fSocket >= 0)
322241b0480SAxel Dörfler 		close(fSocket);
323241b0480SAxel Dörfler 
324241b0480SAxel Dörfler 	fSocket = -1;
325*49a22456SOliver Tappe 	fStatus = B_NO_INIT;
3266fdccb80SAxel Dörfler }
3276fdccb80SAxel Dörfler 
3286fdccb80SAxel Dörfler 
329241b0480SAxel Dörfler status_t
330241b0480SAxel Dörfler BNetEndpoint::Bind(const BNetAddress& address)
3316fdccb80SAxel Dörfler {
332*49a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
333*49a22456SOliver Tappe 		return fStatus;
3346cde6bebSAxel Dörfler 
3356fdccb80SAxel Dörfler 	struct sockaddr_in addr;
336241b0480SAxel Dörfler 	status_t status = address.GetAddr(addr);
3376fdccb80SAxel Dörfler 	if (status != B_OK)
3386fdccb80SAxel Dörfler 		return status;
3396fdccb80SAxel Dörfler 
340241b0480SAxel Dörfler 	if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
341*49a22456SOliver Tappe 		fStatus = errno;
3426fdccb80SAxel Dörfler 		Close();
3436fdccb80SAxel Dörfler 		return B_ERROR;
3446fdccb80SAxel Dörfler 	}
3456fdccb80SAxel Dörfler 
346241b0480SAxel Dörfler 	socklen_t addrSize = sizeof(addr);
347241b0480SAxel Dörfler 	if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) {
348*49a22456SOliver Tappe 		fStatus = errno;
3496fdccb80SAxel Dörfler 		Close();
3506fdccb80SAxel Dörfler 		return B_ERROR;
3516fdccb80SAxel Dörfler 	}
3526fdccb80SAxel Dörfler 
353241b0480SAxel Dörfler 	fAddr.SetTo(addr);
3546fdccb80SAxel Dörfler 	return B_OK;
3556fdccb80SAxel Dörfler }
3566fdccb80SAxel Dörfler 
3576fdccb80SAxel Dörfler 
358241b0480SAxel Dörfler status_t
359241b0480SAxel Dörfler BNetEndpoint::Bind(int port)
3606fdccb80SAxel Dörfler {
3616fdccb80SAxel Dörfler 	BNetAddress addr(INADDR_ANY, port);
3626fdccb80SAxel Dörfler 	return Bind(addr);
3636fdccb80SAxel Dörfler }
3646fdccb80SAxel Dörfler 
3656fdccb80SAxel Dörfler 
366241b0480SAxel Dörfler status_t
367241b0480SAxel Dörfler BNetEndpoint::Connect(const BNetAddress& address)
3686fdccb80SAxel Dörfler {
369*49a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
370*49a22456SOliver Tappe 		return fStatus;
3716cde6bebSAxel Dörfler 
3726fdccb80SAxel Dörfler 	sockaddr_in addr;
3736fdccb80SAxel Dörfler 	if (address.GetAddr(addr) != B_OK)
3746fdccb80SAxel Dörfler 		return B_ERROR;
3756fdccb80SAxel Dörfler 
376241b0480SAxel Dörfler 	if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) {
3776fdccb80SAxel Dörfler 		Close();
378*49a22456SOliver Tappe 		fStatus = errno;
3796fdccb80SAxel Dörfler 		return B_ERROR;
3806fdccb80SAxel Dörfler 	}
3816fdccb80SAxel Dörfler 
382241b0480SAxel Dörfler 	socklen_t addrSize = sizeof(addr);
383241b0480SAxel Dörfler 	if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) {
3846fdccb80SAxel Dörfler 		Close();
385*49a22456SOliver Tappe 		fStatus = errno;
3866fdccb80SAxel Dörfler 		return B_ERROR;
3876fdccb80SAxel Dörfler 	}
388241b0480SAxel Dörfler 	fPeer.SetTo(addr);
3896fdccb80SAxel Dörfler 	return B_OK;
3906fdccb80SAxel Dörfler }
3916fdccb80SAxel Dörfler 
3926fdccb80SAxel Dörfler 
393241b0480SAxel Dörfler status_t
394241b0480SAxel Dörfler BNetEndpoint::Connect(const char *hostname, int port)
3956fdccb80SAxel Dörfler {
3966fdccb80SAxel Dörfler 	BNetAddress addr(hostname, port);
3976fdccb80SAxel Dörfler 	return Connect(addr);
3986fdccb80SAxel Dörfler }
3996fdccb80SAxel Dörfler 
4006fdccb80SAxel Dörfler 
401241b0480SAxel Dörfler status_t
402241b0480SAxel Dörfler BNetEndpoint::Listen(int backlog)
4036fdccb80SAxel Dörfler {
404*49a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
405*49a22456SOliver Tappe 		return fStatus;
4066cde6bebSAxel Dörfler 
407241b0480SAxel Dörfler 	if (listen(fSocket, backlog) < 0) {
4086fdccb80SAxel Dörfler 		Close();
409*49a22456SOliver Tappe 		fStatus = errno;
4106fdccb80SAxel Dörfler 		return B_ERROR;
4116fdccb80SAxel Dörfler 	}
4126fdccb80SAxel Dörfler 	return B_OK;
4136fdccb80SAxel Dörfler }
4146fdccb80SAxel Dörfler 
4156fdccb80SAxel Dörfler 
416241b0480SAxel Dörfler BNetEndpoint*
417241b0480SAxel Dörfler BNetEndpoint::Accept(int32 timeout)
4186fdccb80SAxel Dörfler {
4196fdccb80SAxel Dörfler 	if (!IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout))
4206fdccb80SAxel Dörfler 		return NULL;
4216fdccb80SAxel Dörfler 
4226fdccb80SAxel Dörfler 	struct sockaddr_in addr;
423241b0480SAxel Dörfler 	socklen_t addrSize = sizeof(addr);
4246fdccb80SAxel Dörfler 
425241b0480SAxel Dörfler 	int socket = accept(fSocket, (struct sockaddr *) &addr, &addrSize);
426241b0480SAxel Dörfler 	if (socket < 0) {
4276fdccb80SAxel Dörfler 		Close();
428*49a22456SOliver Tappe 		fStatus = errno;
4296fdccb80SAxel Dörfler 		return NULL;
4306fdccb80SAxel Dörfler 	}
4316fdccb80SAxel Dörfler 
432241b0480SAxel Dörfler 	BNetEndpoint* endpoint = new (std::nothrow) BNetEndpoint(*this);
433241b0480SAxel Dörfler 	if (endpoint == NULL) {
434241b0480SAxel Dörfler 		close(socket);
435*49a22456SOliver Tappe 		fStatus = B_NO_MEMORY;
4366fdccb80SAxel Dörfler 		return NULL;
4376fdccb80SAxel Dörfler 	}
4386fdccb80SAxel Dörfler 
439241b0480SAxel Dörfler 	endpoint->fSocket = socket;
440241b0480SAxel Dörfler 	endpoint->fPeer.SetTo(addr);
441241b0480SAxel Dörfler 
442241b0480SAxel Dörfler 	if (getsockname(socket, (struct sockaddr *)&addr, &addrSize) < 0) {
443241b0480SAxel Dörfler 		delete endpoint;
444*49a22456SOliver Tappe 		fStatus = errno;
4456fdccb80SAxel Dörfler 		return NULL;
4466fdccb80SAxel Dörfler 	}
4476fdccb80SAxel Dörfler 
448241b0480SAxel Dörfler 	endpoint->fAddr.SetTo(addr);
449241b0480SAxel Dörfler 	return endpoint;
4506fdccb80SAxel Dörfler }
4516fdccb80SAxel Dörfler 
452241b0480SAxel Dörfler 
4536fdccb80SAxel Dörfler // #pragma mark -
4546fdccb80SAxel Dörfler 
455241b0480SAxel Dörfler 
456241b0480SAxel Dörfler bool
457241b0480SAxel Dörfler BNetEndpoint::IsDataPending(bigtime_t timeout)
4586fdccb80SAxel Dörfler {
459241b0480SAxel Dörfler 	struct timeval tv;
4606fdccb80SAxel Dörfler 	fd_set fds;
4616fdccb80SAxel Dörfler 
4626fdccb80SAxel Dörfler 	FD_ZERO(&fds);
463241b0480SAxel Dörfler 	FD_SET(fSocket, &fds);
4646fdccb80SAxel Dörfler 
4656fdccb80SAxel Dörfler 	if (timeout > 0) {
4666fdccb80SAxel Dörfler 		tv.tv_sec = timeout / 1000000;
4676fdccb80SAxel Dörfler 		tv.tv_usec = (timeout % 1000000);
4686fdccb80SAxel Dörfler 	}
4696fdccb80SAxel Dörfler 
470241b0480SAxel Dörfler 	if (select(fSocket + 1, &fds, NULL, NULL, timeout > 0 ? &tv : NULL) < 0) {
471*49a22456SOliver Tappe 		fStatus = errno;
4726fdccb80SAxel Dörfler 		return false;
4736fdccb80SAxel Dörfler 	}
4746fdccb80SAxel Dörfler 
475241b0480SAxel Dörfler 	return FD_ISSET(fSocket, &fds);
4766fdccb80SAxel Dörfler }
4776fdccb80SAxel Dörfler 
4786fdccb80SAxel Dörfler 
479241b0480SAxel Dörfler int32
480241b0480SAxel Dörfler BNetEndpoint::Receive(void* buffer, size_t length, int flags)
4816fdccb80SAxel Dörfler {
482*49a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
483*49a22456SOliver Tappe 		return fStatus;
484*49a22456SOliver Tappe 
485241b0480SAxel Dörfler 	if (fTimeout >= 0 && IsDataPending(fTimeout) == false)
4866fdccb80SAxel Dörfler 		return 0;
4876fdccb80SAxel Dörfler 
488241b0480SAxel Dörfler 	ssize_t bytesReceived = recv(fSocket, buffer, length, flags);
489241b0480SAxel Dörfler 	if (bytesReceived < 0)
490*49a22456SOliver Tappe 		fStatus = errno;
491241b0480SAxel Dörfler 
492241b0480SAxel Dörfler 	return bytesReceived;
4936fdccb80SAxel Dörfler }
4946fdccb80SAxel Dörfler 
4956fdccb80SAxel Dörfler 
496241b0480SAxel Dörfler int32
497241b0480SAxel Dörfler BNetEndpoint::Receive(BNetBuffer& buffer, size_t length, int flags)
4986fdccb80SAxel Dörfler {
4996fdccb80SAxel Dörfler 	BNetBuffer chunk(length);
5006fdccb80SAxel Dörfler 	length = Receive(chunk.Data(), length, flags);
5016fdccb80SAxel Dörfler 	buffer.AppendData(chunk.Data(), length);
5026fdccb80SAxel Dörfler 	return length;
5036fdccb80SAxel Dörfler }
5046fdccb80SAxel Dörfler 
5056fdccb80SAxel Dörfler 
506241b0480SAxel Dörfler int32
507241b0480SAxel Dörfler BNetEndpoint::ReceiveFrom(void* buffer, size_t length,
5086fdccb80SAxel Dörfler 	BNetAddress& address, int flags)
5096fdccb80SAxel Dörfler {
510*49a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
511*49a22456SOliver Tappe 		return fStatus;
512*49a22456SOliver Tappe 
513241b0480SAxel Dörfler 	if (fTimeout >= 0 && IsDataPending(fTimeout) == false)
5146fdccb80SAxel Dörfler 		return 0;
5156fdccb80SAxel Dörfler 
5166fdccb80SAxel Dörfler 	struct sockaddr_in addr;
517241b0480SAxel Dörfler 	socklen_t addrSize = sizeof(addr);
5186fdccb80SAxel Dörfler 
519241b0480SAxel Dörfler 	length = recvfrom(fSocket, buffer, length, flags,
520241b0480SAxel Dörfler 		(struct sockaddr *)&addr, &addrSize);
5216fdccb80SAxel Dörfler 	if (length < 0)
522*49a22456SOliver Tappe 		fStatus = errno;
5236fdccb80SAxel Dörfler 	else
5246fdccb80SAxel Dörfler 		address.SetTo(addr);
525241b0480SAxel Dörfler 
5266fdccb80SAxel Dörfler 	return length;
5276fdccb80SAxel Dörfler }
5286fdccb80SAxel Dörfler 
5296fdccb80SAxel Dörfler 
530241b0480SAxel Dörfler int32
531241b0480SAxel Dörfler BNetEndpoint::ReceiveFrom(BNetBuffer& buffer, size_t length,
5326fdccb80SAxel Dörfler 	BNetAddress& address, int flags)
5336fdccb80SAxel Dörfler {
5346fdccb80SAxel Dörfler 	BNetBuffer chunk(length);
5356fdccb80SAxel Dörfler 	length = ReceiveFrom(chunk.Data(), length, address, flags);
5366fdccb80SAxel Dörfler 	buffer.AppendData(chunk.Data(), length);
5376fdccb80SAxel Dörfler 	return length;
5386fdccb80SAxel Dörfler }
5396fdccb80SAxel Dörfler 
5406fdccb80SAxel Dörfler 
541241b0480SAxel Dörfler int32
542241b0480SAxel Dörfler BNetEndpoint::Send(const void* buffer, size_t length, int flags)
5436fdccb80SAxel Dörfler {
544*49a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
545*49a22456SOliver Tappe 		return fStatus;
546*49a22456SOliver Tappe 
547241b0480SAxel Dörfler 	ssize_t bytesSent = send(fSocket, (const char *) buffer, length, flags);
548241b0480SAxel Dörfler 	if (bytesSent < 0)
549*49a22456SOliver Tappe 		fStatus = errno;
5506fdccb80SAxel Dörfler 
551241b0480SAxel Dörfler 	return bytesSent;
5526fdccb80SAxel Dörfler }
5536fdccb80SAxel Dörfler 
5546fdccb80SAxel Dörfler 
555241b0480SAxel Dörfler int32
556241b0480SAxel Dörfler BNetEndpoint::Send(BNetBuffer& buffer, int flags)
5576fdccb80SAxel Dörfler {
5586fdccb80SAxel Dörfler 	return Send(buffer.Data(), buffer.Size(), flags);
5596fdccb80SAxel Dörfler }
5606fdccb80SAxel Dörfler 
5616fdccb80SAxel Dörfler 
562241b0480SAxel Dörfler int32
563241b0480SAxel Dörfler BNetEndpoint::SendTo(const void* buffer, size_t length,
5646fdccb80SAxel Dörfler 	const BNetAddress& address, int flags)
5656fdccb80SAxel Dörfler {
566*49a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
567*49a22456SOliver Tappe 		return fStatus;
568*49a22456SOliver Tappe 
5696fdccb80SAxel Dörfler 	struct sockaddr_in addr;
5706fdccb80SAxel Dörfler 	if (address.GetAddr(addr) != B_OK)
5716fdccb80SAxel Dörfler 		return B_ERROR;
5726fdccb80SAxel Dörfler 
573241b0480SAxel Dörfler 	ssize_t	bytesSent = sendto(fSocket, buffer, length, flags,
5746fdccb80SAxel Dörfler 		(struct sockaddr *) &addr, sizeof(addr));
575241b0480SAxel Dörfler 	if (bytesSent < 0)
576*49a22456SOliver Tappe 		fStatus = errno;
577241b0480SAxel Dörfler 
578241b0480SAxel Dörfler 	return bytesSent;
5796fdccb80SAxel Dörfler }
5806fdccb80SAxel Dörfler 
581241b0480SAxel Dörfler 
582241b0480SAxel Dörfler int32
583241b0480SAxel Dörfler BNetEndpoint::SendTo(BNetBuffer& buffer,
5846fdccb80SAxel Dörfler 	const BNetAddress& address, int flags)
5856fdccb80SAxel Dörfler {
5866fdccb80SAxel Dörfler 	return SendTo(buffer.Data(), buffer.Size(), address, flags);
5876fdccb80SAxel Dörfler }
5886fdccb80SAxel Dörfler 
589241b0480SAxel Dörfler 
5906fdccb80SAxel Dörfler // #pragma mark -
5916fdccb80SAxel Dörfler 
592241b0480SAxel Dörfler 
593*49a22456SOliver Tappe status_t
594*49a22456SOliver Tappe BNetEndpoint::_SetupSocket()
595*49a22456SOliver Tappe {
596*49a22456SOliver Tappe 	if ((fSocket = socket(fFamily, fType, fProtocol)) < 0)
597*49a22456SOliver Tappe 		fStatus = errno;
598*49a22456SOliver Tappe 	else
599*49a22456SOliver Tappe 		fStatus = B_OK;
600*49a22456SOliver Tappe 	return fStatus;
601*49a22456SOliver Tappe }
602*49a22456SOliver Tappe 
603*49a22456SOliver Tappe 
604*49a22456SOliver Tappe // #pragma mark -
605*49a22456SOliver Tappe 
606*49a22456SOliver Tappe status_t BNetEndpoint::InitCheck()
607*49a22456SOliver Tappe {
608*49a22456SOliver Tappe 	return const_cast<const BNetEndpoint*>(this)->InitCheck();
609*49a22456SOliver Tappe }
610*49a22456SOliver Tappe 
611*49a22456SOliver Tappe 
612*49a22456SOliver Tappe const BNetAddress& BNetEndpoint::LocalAddr()
613*49a22456SOliver Tappe {
614*49a22456SOliver Tappe 	return const_cast<const BNetEndpoint*>(this)->LocalAddr();
615*49a22456SOliver Tappe }
616*49a22456SOliver Tappe 
617*49a22456SOliver Tappe 
618*49a22456SOliver Tappe const BNetAddress& BNetEndpoint::RemoteAddr()
619*49a22456SOliver Tappe {
620*49a22456SOliver Tappe 	return const_cast<const BNetEndpoint*>(this)->RemoteAddr();
621*49a22456SOliver Tappe }
622*49a22456SOliver Tappe 
623*49a22456SOliver Tappe 
624*49a22456SOliver Tappe // #pragma mark -
625*49a22456SOliver Tappe 
626*49a22456SOliver Tappe 
6276fdccb80SAxel Dörfler // These are virtuals, implemented for binary compatibility purpose
628241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {}
629241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {}
630241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft3() {}
631241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft4() {}
632241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft5() {}
633241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft6() {}
6346fdccb80SAxel Dörfler 
635