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