2 * Copyright 2012-2013 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Paweł Dziepak, pdziepak@quarnos.org
10 #include "Connection.h"
12 #include <arpa/inet.h>
18 #include <AutoDeleter.h>
19 #include <net/dns_resolver.h>
20 #include <util/kernel_cpp.h>
21 #include <util/Random.h>
24 #define NFS4_PORT 2049
26 #define LAST_FRAGMENT 0x80000000
27 #define MAX_PACKET_SIZE 65535
29 #define NFS_MIN_PORT 665
33 PeerAddress::operator==(const PeerAddress
& address
)
35 return memcmp(&fAddress
, &address
.fAddress
, sizeof(fAddress
)) == 0
36 && fProtocol
== address
.fProtocol
;
41 PeerAddress::operator<(const PeerAddress
& address
)
43 int compare
= memcmp(&fAddress
, &address
.fAddress
, sizeof(fAddress
));
44 return compare
< 0 || (compare
== 0 && fProtocol
< address
.fProtocol
);
49 PeerAddress::operator=(const PeerAddress
& address
)
51 fAddress
= address
.fAddress
;
52 fProtocol
= address
.fProtocol
;
57 PeerAddress::PeerAddress()
61 memset(&fAddress
, 0, sizeof(fAddress
));
65 PeerAddress::PeerAddress(int networkFamily
)
69 ASSERT(networkFamily
== AF_INET
|| networkFamily
== AF_INET6
);
71 memset(&fAddress
, 0, sizeof(fAddress
));
73 fAddress
.ss_family
= networkFamily
;
74 switch (networkFamily
) {
76 fAddress
.ss_len
= sizeof(sockaddr_in
);
79 fAddress
.ss_len
= sizeof(sockaddr_in6
);
86 PeerAddress::ProtocolString() const
88 static const char* tcpName
= "tcp";
89 static const char* udpName
= "udp";
90 static const char* unknown
= "";
104 PeerAddress::SetProtocol(const char* protocol
)
106 ASSERT(protocol
!= NULL
);
108 if (strcmp(protocol
, "tcp") == 0)
109 fProtocol
= IPPROTO_TCP
;
110 else if (strcmp(protocol
, "udp") == 0)
111 fProtocol
= IPPROTO_UDP
;
116 PeerAddress::UniversalAddress() const
118 char* uAddr
= reinterpret_cast<char*>(malloc(INET6_ADDRSTRLEN
+ 16));
122 if (inet_ntop(fAddress
.ss_family
, InAddr(), uAddr
, AddressSize()) == NULL
)
126 sprintf(port
, ".%d.%d", Port() >> 8, Port() & 0xff);
134 PeerAddress::AddressSize() const
138 return sizeof(sockaddr_in
);
140 return sizeof(sockaddr_in6
);
148 PeerAddress::Port() const
154 port
= reinterpret_cast<const sockaddr_in
*>(&fAddress
)->sin_port
;
157 port
= reinterpret_cast<const sockaddr_in6
*>(&fAddress
)->sin6_port
;
168 PeerAddress::SetPort(uint16 port
)
174 reinterpret_cast<sockaddr_in
*>(&fAddress
)->sin_port
= port
;
177 reinterpret_cast<sockaddr_in6
*>(&fAddress
)->sin6_port
= port
;
183 PeerAddress::InAddr() const
187 return &reinterpret_cast<const sockaddr_in
*>(&fAddress
)->sin_addr
;
189 return &reinterpret_cast<const sockaddr_in6
*>(&fAddress
)->sin6_addr
;
197 PeerAddress::InAddrSize() const
201 return sizeof(in_addr
);
203 return sizeof(in6_addr
);
210 AddressResolver::AddressResolver(const char* name
)
214 fForcedPort(htons(NFS4_PORT
)),
215 fForcedProtocol(IPPROTO_TCP
)
217 fStatus
= ResolveAddress(name
);
221 AddressResolver::~AddressResolver()
228 AddressResolver::ResolveAddress(const char* name
)
230 ASSERT(name
!= NULL
);
238 // getaddrinfo() is very expensive when called from kernel, so we do not
239 // want to call it unless there is no other choice.
240 struct sockaddr_in addr
;
241 memset(&addr
, 0, sizeof(addr
));
242 if (inet_aton(name
, &addr
.sin_addr
) == 1) {
243 addr
.sin_len
= sizeof(addr
);
244 addr
.sin_family
= AF_INET
;
245 addr
.sin_port
= htons(NFS4_PORT
);
247 memcpy(&fAddress
.fAddress
, &addr
, sizeof(addr
));
248 fAddress
.fProtocol
= IPPROTO_TCP
;
252 status_t result
= getaddrinfo(name
, NULL
, NULL
, &fHead
);
260 AddressResolver::ForceProtocol(const char* protocol
)
262 ASSERT(protocol
!= NULL
);
264 if (strcmp(protocol
, "tcp") == 0)
265 fForcedProtocol
= IPPROTO_TCP
;
266 else if (strcmp(protocol
, "udp") == 0)
267 fForcedProtocol
= IPPROTO_UDP
;
269 fAddress
.SetProtocol(protocol
);
274 AddressResolver::ForcePort(uint16 port
)
276 fForcedPort
= htons(port
);
277 fAddress
.SetPort(port
);
282 AddressResolver::GetNextAddress(PeerAddress
* address
)
284 ASSERT(address
!= NULL
);
291 fStatus
= B_NAME_NOT_FOUND
;
295 address
->fProtocol
= fForcedProtocol
;
297 while (fCurrent
!= NULL
) {
298 if (fCurrent
->ai_family
== AF_INET
) {
299 memcpy(&address
->fAddress
, fCurrent
->ai_addr
, sizeof(sockaddr_in
));
300 reinterpret_cast<sockaddr_in
*>(&address
->fAddress
)->sin_port
302 } else if (fCurrent
->ai_family
== AF_INET6
) {
303 memcpy(&address
->fAddress
, fCurrent
->ai_addr
, sizeof(sockaddr_in6
));
304 reinterpret_cast<sockaddr_in6
*>(&address
->fAddress
)->sin6_port
307 fCurrent
= fCurrent
->ai_next
;
311 fCurrent
= fCurrent
->ai_next
;
315 return B_NAME_NOT_FOUND
;
319 Connection::Connection(const PeerAddress
& address
)
321 ConnectionBase(address
)
326 ConnectionListener::ConnectionListener(const PeerAddress
& address
)
328 ConnectionBase(address
)
333 ConnectionBase::ConnectionBase(const PeerAddress
& address
)
335 fWaitCancel(create_sem(0, NULL
)),
337 fPeerAddress(address
)
339 mutex_init(&fSocketLock
, NULL
);
343 ConnectionStream::ConnectionStream(const PeerAddress
& address
)
350 ConnectionPacket::ConnectionPacket(const PeerAddress
& address
)
357 ConnectionBase::~ConnectionBase()
361 mutex_destroy(&fSocketLock
);
362 delete_sem(fWaitCancel
);
367 ConnectionBase::GetLocalAddress(PeerAddress
* address
)
369 ASSERT(address
!= NULL
);
371 address
->fProtocol
= fPeerAddress
.fProtocol
;
373 socklen_t addressSize
= sizeof(address
->fAddress
);
374 return getsockname(fSocket
, (struct sockaddr
*)&address
->fAddress
,
380 ConnectionStream::Send(const void* buffer
, uint32 size
)
382 ASSERT(buffer
!= NULL
);
386 uint32
* buf
= reinterpret_cast<uint32
*>(malloc(size
+ sizeof(uint32
)));
389 MemoryDeleter
_(buf
);
391 buf
[0] = htonl(size
| LAST_FRAGMENT
);
392 memcpy(buf
+ 1, buffer
, size
);
394 // More than one threads may send data and ksend is allowed to send partial
395 // data. Need a lock here.
397 mutex_lock(&fSocketLock
);
399 result
= send(fSocket
, buf
+ sent
, size
+ sizeof(uint32
) - sent
, 0);
401 } while (result
> 0 && sent
< size
+ sizeof(uint32
));
402 mutex_unlock(&fSocketLock
);
406 } else if (result
== 0)
414 ConnectionPacket::Send(const void* buffer
, uint32 size
)
416 ASSERT(buffer
!= NULL
);
417 ASSERT(size
< 65535);
419 // send on DGRAM sockets is atomic. No need to lock.
420 status_t result
= send(fSocket
, buffer
, size
, 0);
428 ConnectionStream::Receive(void** _buffer
, uint32
* _size
)
430 ASSERT(_buffer
!= NULL
);
431 ASSERT(_size
!= NULL
);
439 bool last_one
= false;
441 object_wait_info object
[2];
442 object
[0].object
= fWaitCancel
;
443 object
[0].type
= B_OBJECT_TYPE_SEMAPHORE
;
444 object
[0].events
= B_EVENT_ACQUIRE_SEMAPHORE
;
446 object
[1].object
= fSocket
;
447 object
[1].type
= B_OBJECT_TYPE_FD
;
448 object
[1].events
= B_EVENT_READ
;
451 object
[0].events
= B_EVENT_ACQUIRE_SEMAPHORE
;
452 object
[1].events
= B_EVENT_READ
;
454 result
= wait_for_objects(object
, 2);
456 || (object
[0].events
& B_EVENT_ACQUIRE_SEMAPHORE
) != 0) {
459 } else if ((object
[1].events
& B_EVENT_READ
) == 0)
462 // There is only one listener thread per connection. No need to lock.
465 result
= recv(fSocket
, ((uint8
*)&record_size
) + received
,
466 sizeof(record_size
) - received
, 0);
468 } while (result
> 0 && received
< sizeof(record_size
));
473 } else if (result
== 0) {
478 record_size
= ntohl(record_size
);
479 ASSERT(record_size
> 0);
481 last_one
= (record_size
& LAST_FRAGMENT
) != 0;
482 record_size
&= LAST_FRAGMENT
- 1;
484 void* ptr
= realloc(buffer
, size
+ record_size
);
490 MemoryDeleter
bufferDeleter(buffer
);
494 result
= recv(fSocket
, (uint8
*)buffer
+ size
+ received
,
495 record_size
- received
, 0);
497 } while (result
> 0 && received
< record_size
);
500 else if (result
== 0)
503 bufferDeleter
.Detach();
516 ConnectionPacket::Receive(void** _buffer
, uint32
* _size
)
518 ASSERT(_buffer
!= NULL
);
519 ASSERT(_size
!= NULL
);
522 int32 size
= MAX_PACKET_SIZE
;
523 void* buffer
= malloc(size
);
528 object_wait_info object
[2];
529 object
[0].object
= fWaitCancel
;
530 object
[0].type
= B_OBJECT_TYPE_SEMAPHORE
;
531 object
[0].events
= B_EVENT_ACQUIRE_SEMAPHORE
;
533 object
[1].object
= fSocket
;
534 object
[1].type
= B_OBJECT_TYPE_FD
;
535 object
[1].events
= B_EVENT_READ
;
538 object
[0].events
= B_EVENT_ACQUIRE_SEMAPHORE
;
539 object
[1].events
= B_EVENT_READ
;
541 result
= wait_for_objects(object
, 2);
543 || (object
[0].events
& B_EVENT_ACQUIRE_SEMAPHORE
) != 0) {
546 } else if ((object
[1].events
& B_EVENT_READ
) == 0)
551 // There is only one listener thread per connection. No need to lock.
552 size
= recv(fSocket
, buffer
, size
, 0);
557 } else if (size
== 0) {
570 Connection::CreateObject(const PeerAddress
& address
)
572 switch (address
.fProtocol
) {
574 return new(std::nothrow
) ConnectionStream(address
);
576 return new(std::nothrow
) ConnectionPacket(address
);
584 Connection::Connect(Connection
**_connection
, const PeerAddress
& address
)
586 ASSERT(_connection
!= NULL
);
588 Connection
* conn
= CreateObject(address
);
593 if (conn
->fWaitCancel
< B_OK
) {
594 result
= conn
->fWaitCancel
;
599 result
= conn
->Connect();
600 if (result
!= B_OK
) {
612 Connection::SetTo(Connection
**_connection
, int socket
,
613 const PeerAddress
& address
)
615 ASSERT(_connection
!= NULL
);
616 ASSERT(socket
!= -1);
618 Connection
* conn
= CreateObject(address
);
623 if (conn
->fWaitCancel
< B_OK
) {
624 result
= conn
->fWaitCancel
;
629 conn
->fSocket
= socket
;
638 Connection::Connect()
640 switch (fPeerAddress
.fProtocol
) {
642 fSocket
= socket(fPeerAddress
.Family(), SOCK_STREAM
, IPPROTO_TCP
);
645 fSocket
= socket(fPeerAddress
.Family(), SOCK_DGRAM
, IPPROTO_UDP
);
654 uint16 port
, attempt
= 0;
656 PeerAddress
address(fPeerAddress
.Family());
659 port
= get_random
<uint16
>() % (IPPORT_RESERVED
- NFS_MIN_PORT
);
660 port
+= NFS_MIN_PORT
;
666 address
.SetPort(port
);
667 result
= bind(fSocket
, (sockaddr
*)&address
.fAddress
,
668 address
.AddressSize());
669 } while (attempt
<= 10 && result
!= B_OK
);
676 result
= connect(fSocket
, (sockaddr
*)&fPeerAddress
.fAddress
,
677 fPeerAddress
.AddressSize());
689 Connection::Reconnect()
691 release_sem(fWaitCancel
);
693 acquire_sem(fWaitCancel
);
699 ConnectionBase::Disconnect()
701 release_sem(fWaitCancel
);
709 ConnectionListener::Listen(ConnectionListener
** listener
, int networkFamily
,
712 ASSERT(listener
!= NULL
);
713 ASSERT(networkFamily
== AF_INET
|| networkFamily
== AF_INET6
);
715 int sock
= socket(networkFamily
, SOCK_STREAM
, IPPROTO_TCP
);
719 PeerAddress
address(networkFamily
);
720 address
.SetPort(port
);
721 address
.fProtocol
= IPPROTO_TCP
;
723 status_t result
= bind(sock
, (sockaddr
*)&address
.fAddress
,
724 address
.AddressSize());
725 if (result
!= B_OK
) {
730 if (listen(sock
, 5) != B_OK
) {
735 *listener
= new(std::nothrow
) ConnectionListener(address
);
736 if (*listener
== NULL
) {
741 if ((*listener
)->fWaitCancel
< B_OK
) {
742 result
= (*listener
)->fWaitCancel
;
748 (*listener
)->fSocket
= sock
;
755 ConnectionListener::AcceptConnection(Connection
** connection
)
757 ASSERT(connection
!= NULL
);
759 object_wait_info object
[2];
760 object
[0].object
= fWaitCancel
;
761 object
[0].type
= B_OBJECT_TYPE_SEMAPHORE
;
762 object
[0].events
= B_EVENT_ACQUIRE_SEMAPHORE
;
764 object
[1].object
= fSocket
;
765 object
[1].type
= B_OBJECT_TYPE_FD
;
766 object
[1].events
= B_EVENT_READ
;
769 object
[0].events
= B_EVENT_ACQUIRE_SEMAPHORE
;
770 object
[1].events
= B_EVENT_READ
;
772 status_t result
= wait_for_objects(object
, 2);
774 || (object
[0].events
& B_EVENT_ACQUIRE_SEMAPHORE
) != 0) {
776 } else if ((object
[1].events
& B_EVENT_READ
) == 0)
781 sockaddr_storage addr
;
782 socklen_t length
= sizeof(addr
);
783 int sock
= accept(fSocket
, reinterpret_cast<sockaddr
*>(&addr
), &length
);
788 address
.fProtocol
= IPPROTO_TCP
;
789 address
.fAddress
= addr
;
791 status_t result
= Connection::SetTo(connection
, sock
, address
);
792 if (result
!= B_OK
) {