xref: /haiku/src/kits/network/libnetapi/NetEndpoint.cpp (revision 0ce3a760d3c43f97bd9fca913696126738ad45b3)
1241b0480SAxel Dörfler /*
249a22456SOliver 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 
BNetEndpoint(int type)21241b0480SAxel Dörfler BNetEndpoint::BNetEndpoint(int type)
22241b0480SAxel Dörfler 	:
2349a22456SOliver Tappe 	fStatus(B_NO_INIT),
2449a22456SOliver Tappe 	fFamily(AF_INET),
2549a22456SOliver Tappe 	fType(type),
2649a22456SOliver Tappe 	fProtocol(0),
27241b0480SAxel Dörfler 	fSocket(-1),
2849a22456SOliver Tappe 	fTimeout(B_INFINITE_TIMEOUT)
29241b0480SAxel Dörfler {
3049a22456SOliver Tappe 	_SetupSocket();
316fdccb80SAxel Dörfler }
326fdccb80SAxel Dörfler 
336fdccb80SAxel Dörfler 
BNetEndpoint(int family,int type,int protocol)346fdccb80SAxel Dörfler BNetEndpoint::BNetEndpoint(int family, int type, int protocol)
35241b0480SAxel Dörfler 	:
3649a22456SOliver Tappe 	fStatus(B_NO_INIT),
3749a22456SOliver Tappe 	fFamily(family),
3849a22456SOliver Tappe 	fType(type),
3949a22456SOliver Tappe 	fProtocol(protocol),
40241b0480SAxel Dörfler 	fSocket(-1),
4149a22456SOliver Tappe 	fTimeout(B_INFINITE_TIMEOUT)
426fdccb80SAxel Dörfler {
4349a22456SOliver Tappe 	_SetupSocket();
446fdccb80SAxel Dörfler }
456fdccb80SAxel Dörfler 
466fdccb80SAxel Dörfler 
BNetEndpoint(BMessage * archive)476fdccb80SAxel Dörfler BNetEndpoint::BNetEndpoint(BMessage* archive)
48241b0480SAxel Dörfler 	:
4949a22456SOliver Tappe 	fStatus(B_NO_INIT),
5049a22456SOliver Tappe 	fFamily(AF_INET),
5149a22456SOliver Tappe 	fProtocol(0),
52241b0480SAxel Dörfler 	fSocket(-1),
5349a22456SOliver Tappe 	fTimeout(B_INFINITE_TIMEOUT)
546fdccb80SAxel Dörfler {
556fdccb80SAxel Dörfler 	if (!archive)
566fdccb80SAxel Dörfler 		return;
576fdccb80SAxel Dörfler 
5849a22456SOliver Tappe 	in_addr addr, peer;
5949a22456SOliver Tappe 	unsigned short addrPort = 0, peerPort = 0;
606fdccb80SAxel Dörfler 
6149a22456SOliver Tappe 	fStatus = archive->FindInt32("_BNetEndpoint_addr_addr",
6249a22456SOliver Tappe 		(int32 *)&addr.s_addr);
6349a22456SOliver Tappe 	if (fStatus == B_OK) {
6449a22456SOliver Tappe 		fStatus = archive->FindInt16("_BNetEndpoint_addr_port",
6549a22456SOliver Tappe 			(int16 *)&addrPort);
6649a22456SOliver Tappe 		if (fStatus == B_OK)
6749a22456SOliver Tappe 			fStatus = fAddr.SetTo(addr, addrPort);
6849a22456SOliver Tappe 	}
696fdccb80SAxel Dörfler 
7049a22456SOliver Tappe 	fStatus = archive->FindInt32("_BNetEndpoint_peer_addr",
7149a22456SOliver Tappe 		(int32 *)&peer.s_addr);
7249a22456SOliver Tappe 	if (fStatus == B_OK) {
7349a22456SOliver Tappe 		fStatus = archive->FindInt16("_BNetEndpoint_peer_port",
7449a22456SOliver Tappe 			(int16 *)&peerPort);
7549a22456SOliver Tappe 		if (fStatus == B_OK)
7649a22456SOliver Tappe 			fStatus = fPeer.SetTo(peer, peerPort);
7749a22456SOliver Tappe 	}
7849a22456SOliver Tappe 
7949a22456SOliver Tappe 	fStatus = archive->FindInt64("_BNetEndpoint_timeout", (int64 *)&fTimeout);
8049a22456SOliver Tappe 	if (fStatus == B_OK)
8149a22456SOliver Tappe 		fStatus = archive->FindInt32("_BNetEndpoint_proto", (int32 *)&fType);
8249a22456SOliver Tappe 
8349a22456SOliver Tappe 	if (fStatus == B_OK)
8449a22456SOliver Tappe 		_SetupSocket();
856fdccb80SAxel Dörfler }
866fdccb80SAxel Dörfler 
876fdccb80SAxel Dörfler 
BNetEndpoint(const BNetEndpoint & endpoint)88241b0480SAxel Dörfler BNetEndpoint::BNetEndpoint(const BNetEndpoint& endpoint)
89241b0480SAxel Dörfler 	:
9049a22456SOliver Tappe 	fStatus(endpoint.fStatus),
9149a22456SOliver Tappe 	fFamily(endpoint.fFamily),
9249a22456SOliver Tappe 	fType(endpoint.fType),
9349a22456SOliver Tappe 	fProtocol(endpoint.fProtocol),
9449a22456SOliver Tappe 	fSocket(-1),
95241b0480SAxel Dörfler 	fTimeout(endpoint.fTimeout),
96241b0480SAxel Dörfler 	fAddr(endpoint.fAddr),
97241b0480SAxel Dörfler 	fPeer(endpoint.fPeer)
9849a22456SOliver Tappe 
996fdccb80SAxel Dörfler {
100241b0480SAxel Dörfler 	if (endpoint.fSocket >= 0) {
101241b0480SAxel Dörfler 		fSocket = dup(endpoint.fSocket);
10249a22456SOliver Tappe 		if (fSocket < 0)
10349a22456SOliver Tappe 			fStatus = errno;
104241b0480SAxel Dörfler 	}
1056fdccb80SAxel Dörfler }
1066fdccb80SAxel Dörfler 
1076fdccb80SAxel Dörfler 
108dcc56bf7SMichael Lotz // Private constructor only used from BNetEndpoint::Accept().
BNetEndpoint(const BNetEndpoint & endpoint,int socket,const struct sockaddr_in & localAddress,const struct sockaddr_in & peerAddress)109dcc56bf7SMichael Lotz BNetEndpoint::BNetEndpoint(const BNetEndpoint& endpoint, int socket,
110dcc56bf7SMichael Lotz 	const struct sockaddr_in& localAddress,
111dcc56bf7SMichael Lotz 	const struct sockaddr_in& peerAddress)
112dcc56bf7SMichael Lotz 	:
113dcc56bf7SMichael Lotz 	fStatus(endpoint.fStatus),
114dcc56bf7SMichael Lotz 	fFamily(endpoint.fFamily),
115dcc56bf7SMichael Lotz 	fType(endpoint.fType),
116dcc56bf7SMichael Lotz 	fProtocol(endpoint.fProtocol),
117dcc56bf7SMichael Lotz 	fSocket(socket),
118dcc56bf7SMichael Lotz 	fTimeout(endpoint.fTimeout),
119dcc56bf7SMichael Lotz 	fAddr(localAddress),
120dcc56bf7SMichael Lotz 	fPeer(peerAddress)
121dcc56bf7SMichael Lotz {
122dcc56bf7SMichael Lotz }
123dcc56bf7SMichael Lotz 
124dcc56bf7SMichael Lotz 
125241b0480SAxel Dörfler BNetEndpoint&
operator =(const BNetEndpoint & endpoint)126241b0480SAxel Dörfler BNetEndpoint::operator=(const BNetEndpoint& endpoint)
1276fdccb80SAxel Dörfler {
12849a22456SOliver Tappe 	if (this == &endpoint)
12949a22456SOliver Tappe 		return *this;
13049a22456SOliver Tappe 
1316fdccb80SAxel Dörfler 	Close();
1326fdccb80SAxel Dörfler 
13349a22456SOliver Tappe 	fStatus = endpoint.fStatus;
13449a22456SOliver Tappe 	fFamily = endpoint.fFamily;
13549a22456SOliver Tappe 	fType = endpoint.fType;
13649a22456SOliver Tappe 	fProtocol = endpoint.fProtocol;
137241b0480SAxel Dörfler 	fTimeout = endpoint.fTimeout;
138241b0480SAxel Dörfler 	fAddr = endpoint.fAddr;
139241b0480SAxel Dörfler 	fPeer = endpoint.fPeer;
1406fdccb80SAxel Dörfler 
141241b0480SAxel Dörfler 	fSocket = -1;
142241b0480SAxel Dörfler 	if (endpoint.fSocket >= 0) {
143241b0480SAxel Dörfler 		fSocket = dup(endpoint.fSocket);
14449a22456SOliver Tappe 		if (fSocket < 0)
14549a22456SOliver Tappe 			fStatus = errno;
146241b0480SAxel Dörfler 	}
1476fdccb80SAxel Dörfler 
1486fdccb80SAxel Dörfler     return *this;
1496fdccb80SAxel Dörfler }
1506fdccb80SAxel Dörfler 
151241b0480SAxel Dörfler 
~BNetEndpoint()1526fdccb80SAxel Dörfler BNetEndpoint::~BNetEndpoint()
1536fdccb80SAxel Dörfler {
15449a22456SOliver Tappe 	if (fSocket >= 0)
1556fdccb80SAxel Dörfler 		Close();
1566fdccb80SAxel Dörfler }
1576fdccb80SAxel Dörfler 
158241b0480SAxel Dörfler 
1596fdccb80SAxel Dörfler // #pragma mark -
1606fdccb80SAxel Dörfler 
161241b0480SAxel Dörfler 
162241b0480SAxel Dörfler status_t
Archive(BMessage * into,bool deep) const163241b0480SAxel Dörfler BNetEndpoint::Archive(BMessage* into, bool deep) const
1646fdccb80SAxel Dörfler {
16549a22456SOliver Tappe 	if (!into)
1666fdccb80SAxel Dörfler 		return B_ERROR;
1676fdccb80SAxel Dörfler 
16849a22456SOliver Tappe 	status_t status = BArchivable::Archive(into, deep);
16949a22456SOliver Tappe 	if (status != B_OK)
17049a22456SOliver Tappe 		return status;
1716fdccb80SAxel Dörfler 
17249a22456SOliver Tappe 	in_addr addr, peer;
17349a22456SOliver Tappe 	unsigned short addrPort, peerPort;
1746fdccb80SAxel Dörfler 
17549a22456SOliver Tappe 	status = fAddr.GetAddr(addr, &addrPort);
17649a22456SOliver Tappe 	if (status == B_OK) {
17749a22456SOliver Tappe 		status = into->AddInt32("_BNetEndpoint_addr_addr", addr.s_addr);
17849a22456SOliver Tappe 		if (status == B_OK)
17949a22456SOliver Tappe 			status = into->AddInt16("_BNetEndpoint_addr_port", addrPort);
18049a22456SOliver Tappe 		if (status != B_OK)
18149a22456SOliver Tappe 			return status;
18249a22456SOliver Tappe 	}
18349a22456SOliver Tappe 	status = fPeer.GetAddr(peer, &peerPort);
18449a22456SOliver Tappe 	if (status == B_OK) {
18549a22456SOliver Tappe 		status = into->AddInt32("_BNetEndpoint_peer_addr", peer.s_addr);
18649a22456SOliver Tappe 		if (status == B_OK)
18749a22456SOliver Tappe 			status = into->AddInt16("_BNetEndpoint_peer_port", peerPort);
18849a22456SOliver Tappe 		if (status != B_OK)
18949a22456SOliver Tappe 			return status;
19049a22456SOliver Tappe 	}
1916fdccb80SAxel Dörfler 
19249a22456SOliver Tappe 	status = into->AddInt64("_BNetEndpoint_timeout", fTimeout);
19349a22456SOliver Tappe 	if (status == B_OK)
19449a22456SOliver Tappe 		status = into->AddInt32("_BNetEndpoint_proto", fType);
19549a22456SOliver Tappe 
19649a22456SOliver Tappe 	return status;
1976fdccb80SAxel Dörfler }
1986fdccb80SAxel Dörfler 
1996fdccb80SAxel Dörfler 
200241b0480SAxel Dörfler BArchivable*
Instantiate(BMessage * archive)201241b0480SAxel Dörfler BNetEndpoint::Instantiate(BMessage* archive)
2026fdccb80SAxel Dörfler {
2036fdccb80SAxel Dörfler 	if (!archive)
2046fdccb80SAxel Dörfler 		return NULL;
2056fdccb80SAxel Dörfler 
20649a22456SOliver Tappe 	if (!validate_instantiation(archive, "BNetEndpoint"))
2076fdccb80SAxel Dörfler 		return NULL;
2086fdccb80SAxel Dörfler 
209241b0480SAxel Dörfler 	BNetEndpoint* endpoint = new BNetEndpoint(archive);
210241b0480SAxel Dörfler 	if (endpoint && endpoint->InitCheck() == B_OK)
211241b0480SAxel Dörfler 		return endpoint;
2126fdccb80SAxel Dörfler 
213241b0480SAxel Dörfler 	delete endpoint;
2146fdccb80SAxel Dörfler 	return NULL;
2156fdccb80SAxel Dörfler }
2166fdccb80SAxel Dörfler 
217241b0480SAxel Dörfler 
2186fdccb80SAxel Dörfler // #pragma mark -
2196fdccb80SAxel Dörfler 
2206fdccb80SAxel Dörfler 
221241b0480SAxel Dörfler status_t
InitCheck() const22249a22456SOliver Tappe BNetEndpoint::InitCheck() const
2236fdccb80SAxel Dörfler {
22449a22456SOliver Tappe 	return fSocket == -1 ? B_NO_INIT : B_OK;
2256fdccb80SAxel Dörfler }
2266fdccb80SAxel Dörfler 
2276fdccb80SAxel Dörfler 
228241b0480SAxel Dörfler int
Socket() const229241b0480SAxel Dörfler BNetEndpoint::Socket() const
2306fdccb80SAxel Dörfler {
231241b0480SAxel Dörfler 	return fSocket;
2326fdccb80SAxel Dörfler }
2336fdccb80SAxel Dörfler 
2346fdccb80SAxel Dörfler 
235241b0480SAxel Dörfler const BNetAddress&
LocalAddr() const23649a22456SOliver Tappe BNetEndpoint::LocalAddr() const
2376fdccb80SAxel Dörfler {
238241b0480SAxel Dörfler 	return fAddr;
2396fdccb80SAxel Dörfler }
2406fdccb80SAxel Dörfler 
2416fdccb80SAxel Dörfler 
242241b0480SAxel Dörfler const BNetAddress&
RemoteAddr() const24349a22456SOliver Tappe BNetEndpoint::RemoteAddr() const
2446fdccb80SAxel Dörfler {
245241b0480SAxel Dörfler 	return fPeer;
2466fdccb80SAxel Dörfler }
2476fdccb80SAxel Dörfler 
2486fdccb80SAxel Dörfler 
249241b0480SAxel Dörfler status_t
SetProtocol(int protocol)250241b0480SAxel Dörfler BNetEndpoint::SetProtocol(int protocol)
2516fdccb80SAxel Dörfler {
2526fdccb80SAxel Dörfler 	Close();
25349a22456SOliver Tappe 	fType = protocol;	// sic (protocol is SOCK_DGRAM or SOCK_STREAM)
25449a22456SOliver Tappe 	return _SetupSocket();
2556fdccb80SAxel Dörfler }
2566fdccb80SAxel Dörfler 
2576fdccb80SAxel Dörfler 
258241b0480SAxel Dörfler int
SetOption(int32 option,int32 level,const void * data,unsigned int length)259241b0480SAxel Dörfler BNetEndpoint::SetOption(int32 option, int32 level,
2606fdccb80SAxel Dörfler 	const void* data, unsigned int length)
2616fdccb80SAxel Dörfler {
26249a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
26349a22456SOliver Tappe 		return fStatus;
2646fdccb80SAxel Dörfler 
265241b0480SAxel Dörfler 	if (setsockopt(fSocket, level, option, data, length) < 0) {
26649a22456SOliver Tappe 		fStatus = errno;
2676fdccb80SAxel Dörfler 		return B_ERROR;
2686fdccb80SAxel Dörfler 	}
269241b0480SAxel Dörfler 
2706fdccb80SAxel Dörfler 	return B_OK;
2716fdccb80SAxel Dörfler }
2726fdccb80SAxel Dörfler 
2736fdccb80SAxel Dörfler 
274241b0480SAxel Dörfler int
SetNonBlocking(bool enable)275241b0480SAxel Dörfler BNetEndpoint::SetNonBlocking(bool enable)
2766fdccb80SAxel Dörfler {
27749a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
27849a22456SOliver Tappe 		return fStatus;
27949a22456SOliver Tappe 
280241b0480SAxel Dörfler 	int flags = fcntl(fSocket, F_GETFL);
281241b0480SAxel Dörfler 	if (flags < 0) {
28249a22456SOliver Tappe 		fStatus = errno;
283241b0480SAxel Dörfler 		return B_ERROR;
284241b0480SAxel Dörfler 	}
2856fdccb80SAxel Dörfler 
2866fdccb80SAxel Dörfler 	if (enable)
2876fdccb80SAxel Dörfler 		flags |= O_NONBLOCK;
2886fdccb80SAxel Dörfler 	else
2896fdccb80SAxel Dörfler 		flags &= ~O_NONBLOCK;
2906fdccb80SAxel Dörfler 
291241b0480SAxel Dörfler 	if (fcntl(fSocket, F_SETFL, flags) < 0) {
29249a22456SOliver Tappe 		fStatus = errno;
2936fdccb80SAxel Dörfler 		return B_ERROR;
2946fdccb80SAxel Dörfler 	}
2956fdccb80SAxel Dörfler 
2966fdccb80SAxel Dörfler 	return B_OK;
2976fdccb80SAxel Dörfler }
2986fdccb80SAxel Dörfler 
2996fdccb80SAxel Dörfler 
300241b0480SAxel Dörfler int
SetReuseAddr(bool enable)301241b0480SAxel Dörfler BNetEndpoint::SetReuseAddr(bool enable)
3026fdccb80SAxel Dörfler {
30349a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
30449a22456SOliver Tappe 		return fStatus;
30549a22456SOliver Tappe 
3066fdccb80SAxel Dörfler 	int onoff = (int) enable;
3076fdccb80SAxel Dörfler 	return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff));
3086fdccb80SAxel Dörfler }
3096fdccb80SAxel Dörfler 
3106fdccb80SAxel Dörfler 
311241b0480SAxel Dörfler void
SetTimeout(bigtime_t timeout)312241b0480SAxel Dörfler BNetEndpoint::SetTimeout(bigtime_t timeout)
3136fdccb80SAxel Dörfler {
3142c9528d2SAdrien Destugues 	fTimeout = timeout < 0 ? B_INFINITE_TIMEOUT : timeout;
3156fdccb80SAxel Dörfler }
3166fdccb80SAxel Dörfler 
3176fdccb80SAxel Dörfler 
318241b0480SAxel Dörfler int
Error() const319241b0480SAxel Dörfler BNetEndpoint::Error() const
3206fdccb80SAxel Dörfler {
32149a22456SOliver Tappe 	return (int)fStatus;
3226fdccb80SAxel Dörfler }
3236fdccb80SAxel Dörfler 
3246fdccb80SAxel Dörfler 
325241b0480SAxel Dörfler char*
ErrorStr() const326241b0480SAxel Dörfler BNetEndpoint::ErrorStr() const
3276fdccb80SAxel Dörfler {
32849a22456SOliver Tappe 	return strerror(fStatus);
3296fdccb80SAxel Dörfler }
3306fdccb80SAxel Dörfler 
3316fdccb80SAxel Dörfler 
3326fdccb80SAxel Dörfler // #pragma mark -
3336fdccb80SAxel Dörfler 
334241b0480SAxel Dörfler 
335241b0480SAxel Dörfler void
Close()336241b0480SAxel Dörfler BNetEndpoint::Close()
3376fdccb80SAxel Dörfler {
338241b0480SAxel Dörfler 	if (fSocket >= 0)
339241b0480SAxel Dörfler 		close(fSocket);
340241b0480SAxel Dörfler 
341241b0480SAxel Dörfler 	fSocket = -1;
34249a22456SOliver Tappe 	fStatus = B_NO_INIT;
3436fdccb80SAxel Dörfler }
3446fdccb80SAxel Dörfler 
3456fdccb80SAxel Dörfler 
346241b0480SAxel Dörfler status_t
Bind(const BNetAddress & address)347241b0480SAxel Dörfler BNetEndpoint::Bind(const BNetAddress& address)
3486fdccb80SAxel Dörfler {
34949a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
35049a22456SOliver Tappe 		return fStatus;
3516cde6bebSAxel Dörfler 
3526fdccb80SAxel Dörfler 	struct sockaddr_in addr;
353241b0480SAxel Dörfler 	status_t status = address.GetAddr(addr);
3546fdccb80SAxel Dörfler 	if (status != B_OK)
3556fdccb80SAxel Dörfler 		return status;
3566fdccb80SAxel Dörfler 
357241b0480SAxel Dörfler 	if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
35849a22456SOliver Tappe 		fStatus = errno;
3596fdccb80SAxel Dörfler 		Close();
3606fdccb80SAxel Dörfler 		return B_ERROR;
3616fdccb80SAxel Dörfler 	}
3626fdccb80SAxel Dörfler 
363241b0480SAxel Dörfler 	socklen_t addrSize = sizeof(addr);
364241b0480SAxel Dörfler 	if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) {
36549a22456SOliver Tappe 		fStatus = errno;
3666fdccb80SAxel Dörfler 		Close();
3676fdccb80SAxel Dörfler 		return B_ERROR;
3686fdccb80SAxel Dörfler 	}
3696fdccb80SAxel Dörfler 
370241b0480SAxel Dörfler 	fAddr.SetTo(addr);
3716fdccb80SAxel Dörfler 	return B_OK;
3726fdccb80SAxel Dörfler }
3736fdccb80SAxel Dörfler 
3746fdccb80SAxel Dörfler 
375241b0480SAxel Dörfler status_t
Bind(int port)376241b0480SAxel Dörfler BNetEndpoint::Bind(int port)
3776fdccb80SAxel Dörfler {
3786fdccb80SAxel Dörfler 	BNetAddress addr(INADDR_ANY, port);
3796fdccb80SAxel Dörfler 	return Bind(addr);
3806fdccb80SAxel Dörfler }
3816fdccb80SAxel Dörfler 
3826fdccb80SAxel Dörfler 
383241b0480SAxel Dörfler status_t
Connect(const BNetAddress & address)384241b0480SAxel Dörfler BNetEndpoint::Connect(const BNetAddress& address)
3856fdccb80SAxel Dörfler {
38649a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
38749a22456SOliver Tappe 		return fStatus;
3886cde6bebSAxel Dörfler 
3896fdccb80SAxel Dörfler 	sockaddr_in addr;
3906fdccb80SAxel Dörfler 	if (address.GetAddr(addr) != B_OK)
3916fdccb80SAxel Dörfler 		return B_ERROR;
3926fdccb80SAxel Dörfler 
393241b0480SAxel Dörfler 	if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) {
3946fdccb80SAxel Dörfler 		Close();
39549a22456SOliver Tappe 		fStatus = errno;
3966fdccb80SAxel Dörfler 		return B_ERROR;
3976fdccb80SAxel Dörfler 	}
3986fdccb80SAxel Dörfler 
399241b0480SAxel Dörfler 	socklen_t addrSize = sizeof(addr);
400241b0480SAxel Dörfler 	if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) {
4016fdccb80SAxel Dörfler 		Close();
40249a22456SOliver Tappe 		fStatus = errno;
4036fdccb80SAxel Dörfler 		return B_ERROR;
4046fdccb80SAxel Dörfler 	}
405241b0480SAxel Dörfler 	fPeer.SetTo(addr);
4066fdccb80SAxel Dörfler 	return B_OK;
4076fdccb80SAxel Dörfler }
4086fdccb80SAxel Dörfler 
4096fdccb80SAxel Dörfler 
410241b0480SAxel Dörfler status_t
Connect(const char * hostname,int port)411241b0480SAxel Dörfler BNetEndpoint::Connect(const char *hostname, int port)
4126fdccb80SAxel Dörfler {
4136fdccb80SAxel Dörfler 	BNetAddress addr(hostname, port);
4146fdccb80SAxel Dörfler 	return Connect(addr);
4156fdccb80SAxel Dörfler }
4166fdccb80SAxel Dörfler 
4176fdccb80SAxel Dörfler 
418241b0480SAxel Dörfler status_t
Listen(int backlog)419241b0480SAxel Dörfler BNetEndpoint::Listen(int backlog)
4206fdccb80SAxel Dörfler {
42149a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
42249a22456SOliver Tappe 		return fStatus;
4236cde6bebSAxel Dörfler 
424241b0480SAxel Dörfler 	if (listen(fSocket, backlog) < 0) {
4256fdccb80SAxel Dörfler 		Close();
42649a22456SOliver Tappe 		fStatus = errno;
4276fdccb80SAxel Dörfler 		return B_ERROR;
4286fdccb80SAxel Dörfler 	}
4296fdccb80SAxel Dörfler 	return B_OK;
4306fdccb80SAxel Dörfler }
4316fdccb80SAxel Dörfler 
4326fdccb80SAxel Dörfler 
433241b0480SAxel Dörfler BNetEndpoint*
Accept(int32 timeout)434241b0480SAxel Dörfler BNetEndpoint::Accept(int32 timeout)
4356fdccb80SAxel Dörfler {
4366fdccb80SAxel Dörfler 	if (!IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout))
4376fdccb80SAxel Dörfler 		return NULL;
4386fdccb80SAxel Dörfler 
439dcc56bf7SMichael Lotz 	struct sockaddr_in peerAddress;
440dcc56bf7SMichael Lotz 	socklen_t peerAddressSize = sizeof(peerAddress);
4416fdccb80SAxel Dörfler 
442dcc56bf7SMichael Lotz 	int socket
443dcc56bf7SMichael Lotz 		= accept(fSocket, (struct sockaddr *)&peerAddress, &peerAddressSize);
444241b0480SAxel Dörfler 	if (socket < 0) {
4456fdccb80SAxel Dörfler 		Close();
44649a22456SOliver Tappe 		fStatus = errno;
4476fdccb80SAxel Dörfler 		return NULL;
4486fdccb80SAxel Dörfler 	}
4496fdccb80SAxel Dörfler 
450dcc56bf7SMichael Lotz 	struct sockaddr_in localAddress;
451dcc56bf7SMichael Lotz 	socklen_t localAddressSize = sizeof(localAddress);
452dcc56bf7SMichael Lotz 	if (getsockname(socket, (struct sockaddr *)&localAddress,
453dcc56bf7SMichael Lotz 			&localAddressSize) < 0) {
454840aeab5SStephan Aßmus 		close(socket);
455dcc56bf7SMichael Lotz 		fStatus = errno;
456dcc56bf7SMichael Lotz 		return NULL;
457dcc56bf7SMichael Lotz 	}
458dcc56bf7SMichael Lotz 
459dcc56bf7SMichael Lotz 	BNetEndpoint* endpoint = new (std::nothrow) BNetEndpoint(*this, socket,
460dcc56bf7SMichael Lotz 		localAddress, peerAddress);
461241b0480SAxel Dörfler 	if (endpoint == NULL) {
462241b0480SAxel Dörfler 		close(socket);
46349a22456SOliver Tappe 		fStatus = B_NO_MEMORY;
4646fdccb80SAxel Dörfler 		return NULL;
4656fdccb80SAxel Dörfler 	}
4666fdccb80SAxel Dörfler 
467241b0480SAxel Dörfler 	return endpoint;
4686fdccb80SAxel Dörfler }
4696fdccb80SAxel Dörfler 
470241b0480SAxel Dörfler 
4716fdccb80SAxel Dörfler // #pragma mark -
4726fdccb80SAxel Dörfler 
473241b0480SAxel Dörfler 
474241b0480SAxel Dörfler bool
IsDataPending(bigtime_t timeout)475241b0480SAxel Dörfler BNetEndpoint::IsDataPending(bigtime_t timeout)
4766fdccb80SAxel Dörfler {
477241b0480SAxel Dörfler 	struct timeval tv;
4786fdccb80SAxel Dörfler 	fd_set fds;
4796fdccb80SAxel Dörfler 
4806fdccb80SAxel Dörfler 	FD_ZERO(&fds);
481241b0480SAxel Dörfler 	FD_SET(fSocket, &fds);
4826fdccb80SAxel Dörfler 
4832c9528d2SAdrien Destugues 	// Make sure the timeout does not overflow. If it does, have an infinite
4842c9528d2SAdrien Destugues 	// timeout instead. Note that this conveniently includes B_INFINITE_TIMEOUT.
4852c9528d2SAdrien Destugues 	if (timeout > INT32_MAX * 1000000ll)
4862c9528d2SAdrien Destugues 		timeout = -1;
4872c9528d2SAdrien Destugues 
4882c9528d2SAdrien Destugues 	if (timeout >= 0) {
4896fdccb80SAxel Dörfler 		tv.tv_sec = timeout / 1000000;
4906fdccb80SAxel Dörfler 		tv.tv_usec = (timeout % 1000000);
4916fdccb80SAxel Dörfler 	}
4926fdccb80SAxel Dörfler 
493*0ce3a760SJérôme Duval 	int status;
494*0ce3a760SJérôme Duval 	do {
495*0ce3a760SJérôme Duval 		status = select(fSocket + 1, &fds, NULL, NULL,
496*0ce3a760SJérôme Duval 			timeout >= 0 ? &tv : NULL);
497*0ce3a760SJérôme Duval 	} while (status == -1 && errno == EINTR);
498*0ce3a760SJérôme Duval 
499*0ce3a760SJérôme Duval 	if (status < 0) {
50049a22456SOliver Tappe 		fStatus = errno;
5016fdccb80SAxel Dörfler 		return false;
5026fdccb80SAxel Dörfler 	}
5036fdccb80SAxel Dörfler 
504241b0480SAxel Dörfler 	return FD_ISSET(fSocket, &fds);
5056fdccb80SAxel Dörfler }
5066fdccb80SAxel Dörfler 
5076fdccb80SAxel Dörfler 
508241b0480SAxel Dörfler int32
Receive(void * buffer,size_t length,int flags)509241b0480SAxel Dörfler BNetEndpoint::Receive(void* buffer, size_t length, int flags)
5106fdccb80SAxel Dörfler {
51149a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
51249a22456SOliver Tappe 		return fStatus;
51349a22456SOliver Tappe 
514241b0480SAxel Dörfler 	if (fTimeout >= 0 && IsDataPending(fTimeout) == false)
5156fdccb80SAxel Dörfler 		return 0;
5166fdccb80SAxel Dörfler 
517241b0480SAxel Dörfler 	ssize_t bytesReceived = recv(fSocket, buffer, length, flags);
518241b0480SAxel Dörfler 	if (bytesReceived < 0)
51949a22456SOliver Tappe 		fStatus = errno;
520241b0480SAxel Dörfler 
521241b0480SAxel Dörfler 	return bytesReceived;
5226fdccb80SAxel Dörfler }
5236fdccb80SAxel Dörfler 
5246fdccb80SAxel Dörfler 
525241b0480SAxel Dörfler int32
Receive(BNetBuffer & buffer,size_t length,int flags)526241b0480SAxel Dörfler BNetEndpoint::Receive(BNetBuffer& buffer, size_t length, int flags)
5276fdccb80SAxel Dörfler {
5286fdccb80SAxel Dörfler 	BNetBuffer chunk(length);
52941a9299bSJessica Hamilton 	ssize_t bytesReceived = Receive(chunk.Data(), length, flags);
53041a9299bSJessica Hamilton 	if (bytesReceived > 0)
53141a9299bSJessica Hamilton 		buffer.AppendData(chunk.Data(), bytesReceived);
53241a9299bSJessica Hamilton 	return bytesReceived;
5336fdccb80SAxel Dörfler }
5346fdccb80SAxel Dörfler 
5356fdccb80SAxel Dörfler 
536241b0480SAxel Dörfler int32
ReceiveFrom(void * buffer,size_t length,BNetAddress & address,int flags)537241b0480SAxel Dörfler BNetEndpoint::ReceiveFrom(void* buffer, size_t length,
5386fdccb80SAxel Dörfler 	BNetAddress& address, int flags)
5396fdccb80SAxel Dörfler {
54049a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
54149a22456SOliver Tappe 		return fStatus;
54249a22456SOliver Tappe 
543241b0480SAxel Dörfler 	if (fTimeout >= 0 && IsDataPending(fTimeout) == false)
5446fdccb80SAxel Dörfler 		return 0;
5456fdccb80SAxel Dörfler 
5466fdccb80SAxel Dörfler 	struct sockaddr_in addr;
547241b0480SAxel Dörfler 	socklen_t addrSize = sizeof(addr);
5486fdccb80SAxel Dörfler 
54941a9299bSJessica Hamilton 	ssize_t bytesReceived = recvfrom(fSocket, buffer, length, flags,
550241b0480SAxel Dörfler 		(struct sockaddr *)&addr, &addrSize);
55141a9299bSJessica Hamilton 	if (bytesReceived < 0)
55249a22456SOliver Tappe 		fStatus = errno;
5536fdccb80SAxel Dörfler 	else
5546fdccb80SAxel Dörfler 		address.SetTo(addr);
555241b0480SAxel Dörfler 
55641a9299bSJessica Hamilton 	return bytesReceived;
5576fdccb80SAxel Dörfler }
5586fdccb80SAxel Dörfler 
5596fdccb80SAxel Dörfler 
560241b0480SAxel Dörfler int32
ReceiveFrom(BNetBuffer & buffer,size_t length,BNetAddress & address,int flags)561241b0480SAxel Dörfler BNetEndpoint::ReceiveFrom(BNetBuffer& buffer, size_t length,
5626fdccb80SAxel Dörfler 	BNetAddress& address, int flags)
5636fdccb80SAxel Dörfler {
5646fdccb80SAxel Dörfler 	BNetBuffer chunk(length);
56541a9299bSJessica Hamilton 	ssize_t bytesReceived = ReceiveFrom(chunk.Data(), length, address, flags);
56641a9299bSJessica Hamilton 	if (bytesReceived > 0)
56741a9299bSJessica Hamilton 		buffer.AppendData(chunk.Data(), bytesReceived);
56841a9299bSJessica Hamilton 	return bytesReceived;
5696fdccb80SAxel Dörfler }
5706fdccb80SAxel Dörfler 
5716fdccb80SAxel Dörfler 
572241b0480SAxel Dörfler int32
Send(const void * buffer,size_t length,int flags)573241b0480SAxel Dörfler BNetEndpoint::Send(const void* buffer, size_t length, int flags)
5746fdccb80SAxel Dörfler {
57549a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
57649a22456SOliver Tappe 		return fStatus;
57749a22456SOliver Tappe 
578241b0480SAxel Dörfler 	ssize_t bytesSent = send(fSocket, (const char *) buffer, length, flags);
579241b0480SAxel Dörfler 	if (bytesSent < 0)
58049a22456SOliver Tappe 		fStatus = errno;
5816fdccb80SAxel Dörfler 
582241b0480SAxel Dörfler 	return bytesSent;
5836fdccb80SAxel Dörfler }
5846fdccb80SAxel Dörfler 
5856fdccb80SAxel Dörfler 
586241b0480SAxel Dörfler int32
Send(BNetBuffer & buffer,int flags)587241b0480SAxel Dörfler BNetEndpoint::Send(BNetBuffer& buffer, int flags)
5886fdccb80SAxel Dörfler {
589b37fa18bSPhilippe Houdoin 	return Send(buffer.Data(), buffer.Size(), flags);
5906fdccb80SAxel Dörfler }
5916fdccb80SAxel Dörfler 
5926fdccb80SAxel Dörfler 
593241b0480SAxel Dörfler int32
SendTo(const void * buffer,size_t length,const BNetAddress & address,int flags)594241b0480SAxel Dörfler BNetEndpoint::SendTo(const void* buffer, size_t length,
5956fdccb80SAxel Dörfler 	const BNetAddress& address, int flags)
5966fdccb80SAxel Dörfler {
59749a22456SOliver Tappe 	if (fSocket < 0 && _SetupSocket() != B_OK)
59849a22456SOliver Tappe 		return fStatus;
59949a22456SOliver Tappe 
6006fdccb80SAxel Dörfler 	struct sockaddr_in addr;
6016fdccb80SAxel Dörfler 	if (address.GetAddr(addr) != B_OK)
6026fdccb80SAxel Dörfler 		return B_ERROR;
6036fdccb80SAxel Dörfler 
604241b0480SAxel Dörfler 	ssize_t	bytesSent = sendto(fSocket, buffer, length, flags,
6056fdccb80SAxel Dörfler 		(struct sockaddr *) &addr, sizeof(addr));
606241b0480SAxel Dörfler 	if (bytesSent < 0)
60749a22456SOliver Tappe 		fStatus = errno;
608241b0480SAxel Dörfler 
609241b0480SAxel Dörfler 	return bytesSent;
6106fdccb80SAxel Dörfler }
6116fdccb80SAxel Dörfler 
612241b0480SAxel Dörfler 
613241b0480SAxel Dörfler int32
SendTo(BNetBuffer & buffer,const BNetAddress & address,int flags)614241b0480SAxel Dörfler BNetEndpoint::SendTo(BNetBuffer& buffer,
6156fdccb80SAxel Dörfler 	const BNetAddress& address, int flags)
6166fdccb80SAxel Dörfler {
617b37fa18bSPhilippe Houdoin 	return SendTo(buffer.Data(), buffer.Size(), address, flags);
6186fdccb80SAxel Dörfler }
6196fdccb80SAxel Dörfler 
620241b0480SAxel Dörfler 
6216fdccb80SAxel Dörfler // #pragma mark -
6226fdccb80SAxel Dörfler 
623241b0480SAxel Dörfler 
62449a22456SOliver Tappe status_t
_SetupSocket()62549a22456SOliver Tappe BNetEndpoint::_SetupSocket()
62649a22456SOliver Tappe {
62749a22456SOliver Tappe 	if ((fSocket = socket(fFamily, fType, fProtocol)) < 0)
62849a22456SOliver Tappe 		fStatus = errno;
62949a22456SOliver Tappe 	else
63049a22456SOliver Tappe 		fStatus = B_OK;
63149a22456SOliver Tappe 	return fStatus;
63249a22456SOliver Tappe }
63349a22456SOliver Tappe 
63449a22456SOliver Tappe 
63549a22456SOliver Tappe // #pragma mark -
63649a22456SOliver Tappe 
InitCheck()63749a22456SOliver Tappe status_t BNetEndpoint::InitCheck()
63849a22456SOliver Tappe {
63949a22456SOliver Tappe 	return const_cast<const BNetEndpoint*>(this)->InitCheck();
64049a22456SOliver Tappe }
64149a22456SOliver Tappe 
64249a22456SOliver Tappe 
LocalAddr()64349a22456SOliver Tappe const BNetAddress& BNetEndpoint::LocalAddr()
64449a22456SOliver Tappe {
64549a22456SOliver Tappe 	return const_cast<const BNetEndpoint*>(this)->LocalAddr();
64649a22456SOliver Tappe }
64749a22456SOliver Tappe 
64849a22456SOliver Tappe 
RemoteAddr()64949a22456SOliver Tappe const BNetAddress& BNetEndpoint::RemoteAddr()
65049a22456SOliver Tappe {
65149a22456SOliver Tappe 	return const_cast<const BNetEndpoint*>(this)->RemoteAddr();
65249a22456SOliver Tappe }
65349a22456SOliver Tappe 
65449a22456SOliver Tappe 
65549a22456SOliver Tappe // #pragma mark -
65649a22456SOliver Tappe 
65749a22456SOliver Tappe 
6586fdccb80SAxel Dörfler // These are virtuals, implemented for binary compatibility purpose
_ReservedBNetEndpointFBCCruft1()659241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {}
_ReservedBNetEndpointFBCCruft2()660241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {}
_ReservedBNetEndpointFBCCruft3()661241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft3() {}
_ReservedBNetEndpointFBCCruft4()662241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft4() {}
_ReservedBNetEndpointFBCCruft5()663241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft5() {}
_ReservedBNetEndpointFBCCruft6()664241b0480SAxel Dörfler void BNetEndpoint::_ReservedBNetEndpointFBCCruft6() {}
6656fdccb80SAxel Dörfler 
666