]>
Dogcows Code - chaz/yoink/blob - src/moof/socket.hh
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
10 **************************************************************************/
12 #ifndef _MOOF_SOCKET_HH_
13 #define _MOOF_SOCKET_HH_
28 #define SHUT_RD SD_RECEIVE
29 #define SHUT_WR SD_SEND
30 #define SHUT_RDWR SD_BOTH
32 #include <arpa/inet.h>
34 #include <sys/socket.h>
35 #include <sys/types.h>
38 #include <moof/debug.hh>
39 #include <moof/packet.hh>
40 #include <moof/thread.hh>
43 #define AI_ADDRCONFIG 0
53 * Network-related classes, including a reinterpreted sockets API.
60 * The socket class represents a connection or between this node and a
68 * A class to represent the address of a remote host, including the
69 * type of service and socket communication.
76 * Construct an unspecified address.
82 addr_
.sa
.sa_family
= AF_UNSPEC
;
83 addr_
.in
.sin_port
= 0;
87 * Construct an address with a specified host. The address can be
88 * used to connect to a host.
89 * \param service The service name or port number.
90 * \param name The numeric IP address of the host.
91 * \param type The type of socket; either SOCK_STREAM or
93 * \param family The family; can be AF_INET or AF_INET6.
95 address(const std::string
& service
,
96 const std::string
& name
,
97 int type
= SOCK_STREAM
,
98 int family
= AF_UNSPEC
)
100 init(service
, name
, type
, family
);
104 * Construct an address without a specified host. The address can
105 * be used to accept on a local port.
106 * \param service The service name or port number.
107 * \param type The type of socket; either SOCK_STREAM or
109 * \param family The family; can be AF_INET or AF_INET6.
111 explicit address(const std::string
& service
,
112 int type
= SOCK_STREAM
,
113 int family
= AF_UNSPEC
)
115 init(service
, type
, family
);
119 * Construct an address from the information in an addrinfo
121 * \param addr The addrinfo structure.
123 address(const struct addrinfo
* addr
) :
124 size_(addr
->ai_addrlen
),
125 type_(addr
->ai_socktype
)
127 memcpy(&addr_
.sa
, addr
->ai_addr
, addr
->ai_addrlen
);
128 get_name_and_service(name_
, service_
);
132 * Construct an address from a sockaddr structure.
133 * \param addr The sockaddr structure.
134 * \param size The size of the sockaddr structure.
135 * \param type The type of socket; either SOCK_STREAM or
138 address(const struct sockaddr
* addr
,
140 int type
= SOCK_STREAM
) :
144 memcpy(&addr_
.sa
, addr
, size
);
145 get_name_and_service(name_
, service_
);
150 * Get an IPv4 broadcast address.
151 * \param service The service name or port number.
152 * \return The socket address.
154 static address
broadcast(const std::string
& service
)
156 std::istringstream
stream(service
);
160 struct sockaddr_in addr
;
161 addr
.sin_family
= AF_INET
;
162 addr
.sin_port
= htons(port
);
163 addr
.sin_addr
.s_addr
= INADDR_BROADCAST
;
164 memset(&addr
.sin_zero
, 0, sizeof(addr
.sin_zero
));
165 return address((struct sockaddr
*)&addr
, sizeof(addr
),
171 * Initialize the address with a specified host. The address can
172 * be used to connect to a host.
173 * \param service The service name or port number.
174 * \param name The numeric IP address of the host.
175 * \param type The type of socket; either SOCK_STREAM or
177 * \param family The family; can be AF_INET or AF_INET6.
179 void init(const std::string
& service
,
180 const std::string
& name
,
181 int type
= SOCK_STREAM
,
182 int family
= AF_UNSPEC
)
184 const int flags
= AI_ADDRCONFIG
| AI_NUMERICHOST
| AI_V4MAPPED
;
185 struct addrinfo
* addr
= resolve(service
.c_str(), name
.c_str(),
190 size_
= addr
->ai_addrlen
;
191 type_
= addr
->ai_socktype
;
192 memcpy(&addr_
.sa
, addr
->ai_addr
, addr
->ai_addrlen
);
203 addr_
.sa
.sa_family
= AF_UNSPEC
;
204 addr_
.in
.sin_port
= 0;
209 * Initialize the address without a specified host. The address
210 * can be used to accept on a local port.
211 * \param service The service name or port number.
212 * \param type The type of socket; either SOCK_STREAM or
214 * \param family The family; can be AF_INET or AF_INET6.
216 void init(const std::string
& service
,
217 int type
= SOCK_STREAM
,
218 int family
= AF_UNSPEC
)
220 struct addrinfo
* addr
= resolve(service
.c_str(), 0,
225 size_
= addr
->ai_addrlen
;
226 type_
= addr
->ai_socktype
;
227 memcpy(&addr_
.sa
, addr
->ai_addr
, addr
->ai_addrlen
);
238 addr_
.sa
.sa_family
= AF_UNSPEC
;
239 addr_
.in
.sin_port
= 0;
245 * Get the name of the service. This could also be a port number
246 * if there is no service name associated with the number.
247 * \return The service.
249 const std::string
& service() const
255 * Get the name of the host. This may be the host used to
256 * construct the address, or a resolved numeric host if none was
260 const std::string
& name() const
266 * Get the port number of the address service.
267 * \return Port number.
269 unsigned short port() const
271 return ntohs(addr_
.in
.sin_port
);
275 * Get the type of socket associated with the service of this
277 * \return Socket type; either SOCK_STREAM or SOCK_DGRAM.
285 * Get the family of the protocol associated with the address.
286 * \return Protocol family; either AF_INET, AF_INET6, or AF_UNSPEC.
290 return addr_
.sa
.sa_family
;
295 * Get the sockaddr structure of the address.
296 * \return The sockaddr structure.
298 const struct sockaddr
* sockaddr() const
300 return size_
!= 0 ? &addr_
.sa
: 0;
304 * Get the size of the sockaddr structure of the address.
305 * \return The size of the sockaddr structure.
314 * Get a list of addresses resolved to by the given search
315 * criteria. This can be used to perform lookups for name
316 * resolution, so this method may take some time to return. Use
317 * the ResolveTask class to resolve addresses asynchronously.
318 * \param service The service name or port number.
319 * \param name The name of the local or remote host.
320 * \param type The type of socket; either SOCK_STREAM or
322 * \param family The family; can be AF_INET or AF_INET6.
323 * \param resolved The list to be filled with addresses.
324 * \return 0 on success, -1 on error.
326 static int resolve(const std::string
& service
,
327 const std::string
& name
,
330 std::vector
<address
>& resolved
)
332 struct addrinfo
* list
= resolve(service
.c_str(), name
.c_str(),
334 AI_ADDRCONFIG
| AI_V4MAPPED
);
335 int result
= collect_addresses(list
, resolved
);
341 * Get a list of addresses resolved to by the given search
342 * criteria. The addresses will be suitable for accepting on a
343 * local port. \param service The service name or port number.
344 * \param type The type of socket; either SOCK_STREAM or
346 * \param family The family; can be AF_INET or AF_INET6.
347 * \param resolved The list to be filled with addresses.
348 * \return 0 on success, -1 on error.
350 static int resolve(const std::string
& service
,
353 std::vector
<address
>& resolved
)
355 struct addrinfo
* list
= resolve(service
.c_str(), 0,
358 int result
= collect_addresses(list
, resolved
);
365 * Resolve the hostname of the address. The default behavior is to
366 * avoid a reverse lookup by giving the numeric address. You can
367 * change that behavior with the getnameinfo flags.
368 * \param name The place to store the hostname or IP address.
369 * \param flags The getnameinfo flags.
371 void get_name(std::string
& name
, int flags
= NI_NUMERICHOST
)
373 char node
[256] = {'\0'};
374 int result
= getnameinfo(&addr_
.sa
, size_
,
378 if (result
== 0) name
.assign(node
);
382 * Resolve the service name of the address.
383 * \param service The place to store the service name or port
385 * \param flags The getnameinfo flags.
387 void get_service(std::string
& service
, int flags
)
389 flags
|= type_
== SOCK_DGRAM
? NI_DGRAM
: 0;
391 char serv
[64] = {'\0'};
392 int result
= getnameinfo(&addr_
.sa
, size_
,
396 if (result
== 0) service
.assign(serv
);
400 * Resolve the service and hostname of the address. The default
401 * behavior is to avoid a reverse lookup by giving the numeric
402 * address. You can change that behavior with the getnameinfo
404 * \param name The place to store the hostname or IP address.
405 * \param service The place to store the service name or port
407 * \param flags The getnameinfo flags.
409 void get_name_and_service(std::string
& name
,
410 std::string
& service
,
411 int flags
= NI_NUMERICHOST
)
413 flags
|= type_
== SOCK_DGRAM
? NI_DGRAM
: 0;
415 char serv
[64] = {'\0'};
416 char node
[256] = {'\0'};
417 int result
= getnameinfo(&addr_
.sa
, size_
,
423 service
.assign(serv
);
431 static struct addrinfo
* resolve(const char* service
,
437 ASSERT(type
== SOCK_STREAM
|| type
== SOCK_DGRAM
);
438 ASSERT(family
== AF_INET
|| family
== AF_INET6
|| family
== AF_UNSPEC
);
440 struct addrinfo hints
;
441 memset(&hints
, 0, sizeof(hints
));
442 hints
.ai_family
= family
;
443 hints
.ai_socktype
= type
;
444 hints
.ai_flags
= flags
;
446 struct addrinfo
* addr
;
447 int status
= getaddrinfo(node
, service
, &hints
, &addr
);
455 log_warning(gai_strerror(status
));
460 static int collect_addresses(struct addrinfo
* addresses
,
461 std::vector
<address
>& resolved
)
467 for (struct addrinfo
* addr
= addresses
;
469 addr
= addr
->ai_next
)
471 resolved
.push_back(address(addr
));
483 struct sockaddr_in in
;
484 struct sockaddr_storage storage
;
490 std::string service_
;
498 socket::address address
;
504 is_connected(false) {}
506 impl(const socket::address
& address
, int flags
= 0) :
508 fd(::socket(address
.family(), address
.type(), flags
)),
509 is_connected(false) {}
516 * Construct a socket with no associated peer.
521 * Construct a socket with an address.
522 * \param address The address.
523 * \param flags The socket options.
525 socket(const address
& address
, int flags
= 0) :
526 impl_(address
, flags
) {}
529 * Construct a socket with a specified host. The socket can be used to
531 * \param service The service name or port number.
532 * \param name The numeric IP address of the host.
533 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
534 * \param family The family; can be AF_INET or AF_INET6.
535 * \param flags The socket options.
537 socket(const std::string
& service
,
538 const std::string
& name
,
539 int type
= SOCK_STREAM
,
540 int family
= AF_UNSPEC
,
542 impl_(address(service
, name
, type
, family
), flags
) {}
545 * Construct a socket without a specified host. The socket can be used
546 * to accept sockets on a local port.
547 * \param service The service name or port number.
548 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
549 * \param family The family; can be AF_INET or AF_INET6.
550 * \param flags The socket options.
552 explicit socket(const std::string
& service
,
553 int type
= SOCK_STREAM
,
554 int family
= AF_UNSPEC
,
556 impl_(address(service
, type
, family
), flags
) {}
560 * Deconstruct the socket, closing it.
569 * Get whether or not the socket is connected.
570 * \return True if the socket is connected, false otherwise.
572 bool is_connected() const
574 return impl_
.is_connected
;
578 * Get the address associated with the socket.
580 const address
& peer_address() const
582 return impl_
.address
;
587 * Connect the socket to its peer.
588 * \return 0 on success, -1 on failure.
592 int result
= ::connect(impl_
.fd
,
593 impl_
.address
.sockaddr(),
594 impl_
.address
.size());
595 impl_
.is_connected
= result
!= -1;
600 * Disconnect a connected socket from its peer.
601 * \param flags Specify the socket directions to close.
602 * \return 0 on success, -1 on failure.
604 int disconnect(int flags
= SHUT_RDWR
)
606 return shutdown(impl_
.fd
, flags
);
611 * Bind the socket to interface and port number specified in the
613 * \return 0 on success, -1 on failure.
617 return ::bind(impl_
.fd
,
618 impl_
.address
.sockaddr(),
619 impl_
.address
.size());
623 * Listen on the socket for incoming connections. This is only useful
624 * for sockets of type SOCK_STREAM.
625 * \param backlog The number of unaccepted connections to queue.
626 * \return 0 on success, -1 on failure.
628 int listen(int backlog
= SOMAXCONN
)
630 return ::listen(impl_
.fd
, backlog
> 0 ? backlog
: SOMAXCONN
);
634 * Accept a new connection on the socket. This is only useful for
635 * sockets of type SOCK_STREAM.
636 * \param socket Set to the new socket on return.
637 * \return 0 on success, -1 on failure.
639 int accept(socket
& socket
)
641 moof::socket temp
= moof::socket(impl_
.fd
);
642 if (temp
.impl_
.fd
!= -1)
645 return socket
.impl_
.fd
;
652 * Set an integer socket option.
653 * \param option The option to set.
654 * \param value The new value.
655 * \param level The layer to handle the option.
656 * \return 0 on success, -1 on failure.
659 int set(int option
, const T
& value
, int level
= SOL_SOCKET
)
662 return setsockopt(impl_
.fd
,
665 reinterpret_cast<const char*>(&value
),
668 return setsockopt(impl_
.fd
, level
, option
, &value
, sizeof(value
));
673 * Set a string socket option.
674 * \param option The option to set.
675 * \param value The new value.
676 * \param level The layer to handle the option.
677 * \return 0 on success, -1 on failure.
679 int set(int option
, const std::string
& value
, int level
= SOL_SOCKET
)
681 return setsockopt(impl_
.fd
, level
, option
,
682 value
.data(), value
.length());
686 * Get an integer socket option.
687 * \param option The option to set.
688 * \param value The new value.
689 * \param level The layer to handle the option.
690 * \return 0 on success, -1 on failure.
693 int get(int option
, T
& value
, int level
= SOL_SOCKET
) const
695 int size
= sizeof(value
);
696 return getsockopt(impl_
.fd
, level
, option
, &value
, &size
);
700 * Get a string socket option.
701 * \param option The option to set.
702 * \param value The new value.
703 * \param level The layer to handle the option.
704 * \return 0 on success, -1 on failure.
706 int get(int option
, std::string
& value
, int level
= SOL_SOCKET
) const
708 char str
[256] = {'\0'};
709 socklen_t size
= sizeof(str
);
712 int result
= getsockopt(impl_
.fd
,
715 reinterpret_cast<char*>(&str
),
718 int result
= getsockopt(impl_
.fd
, level
, option
, &str
, &size
);
720 value
.assign(str
, size
);
726 * Set the socket IO mode to either blocking or non-blocking.
727 * \param is_blocking True if the socket should block, false otherwise.
729 void is_blocking(bool is_blocking
)
732 u_long value
= is_blocking
;
733 ioctlsocket(impl_
.fd
, FIONBIO
, &value
);
735 int flags
= fcntl(impl_
.fd
, F_GETFL
);
736 flags
= is_blocking
? (flags
& ~O_NONBLOCK
) : (flags
| O_NONBLOCK
);
737 fcntl(impl_
.fd
, F_SETFL
, flags
);
742 * Get whether or not the socket is blocking or non-blocking. If the
743 * IO mode can't be determined, this method will assume the socket is
745 * \return True if the socket blocks, false otherwise.
747 bool is_blocking() const
752 int flags
= fcntl(impl_
.fd
, F_GETFL
);
753 return !(flags
& O_NONBLOCK
);
759 * Write some bytes to the socket. Use this for connected sockets.
760 * \param bytes The bytes.
761 * \param size The number of bytes.
762 * \param flags The send options.
763 * \return The number of bytes written.
765 ssize_t
write(const void* bytes
, size_t size
, int flags
= 0)
768 return send(impl_
.fd
,
769 reinterpret_cast<const char *>(bytes
), size
,
772 return send(impl_
.fd
, bytes
, size
, flags
);
777 * Write some bytes to the socket using the given address. Use this
778 * for unconnected sockets.
779 * \param bytes The bytes.
780 * \param size The number of bytes.
781 * \param address The address to send to.
782 * \param flags The send options.
783 * \return The number of bytes written.
785 ssize_t
write(const void* bytes
,
787 const address
& address
,
791 return sendto(impl_
.fd
,
792 reinterpret_cast<const char*>(bytes
), size
,
794 address
.sockaddr(), address
.size());
796 return sendto(impl_
.fd
, bytes
, size
, flags
,
797 address
.sockaddr(), address
.size());
802 * Write a packet to the socket. Use this for connected sockets.
803 * \param packet The packet.
804 * \param flags The send options.
805 * \return The number of bytes written.
807 ssize_t
write(const packet
& packet
, int flags
= 0)
809 return write(packet
.bytes(), packet
.size(), flags
);
813 * Write a packet to the socket using the given address. Use this for
814 * unconnected sockets.
815 * \param packet The packet.
816 * \param address The address to send to.
817 * \param flags The send options.
818 * \return The number of bytes written.
820 ssize_t
write(const packet
& packet
,
821 const address
& address
,
824 return write(packet
.bytes(), packet
.size(), address
, flags
);
829 * Read some bytes from the socket. Use this for connected sockets.
830 * \param bytes The buffer to store the bytes.
831 * \param size The size of the buffer.
832 * \param flags The recv options.
833 * \return The number of bytes read.
835 ssize_t
read(void* bytes
, size_t size
, int flags
= 0)
838 ssize_t result
= recv(impl_
.fd
,
839 reinterpret_cast<char*>(bytes
), size
,
842 ssize_t result
= recv(impl_
.fd
, bytes
, size
, flags
);
844 if (result
== 0) impl_
.is_connected
= false;
849 * Read some bytes from the socket using the given address. Use this
850 * for unconnected sockets.
851 * \param bytes The buffer to store the bytes.
852 * \param size The size of the buffer.
853 * \param address The address to read from.
854 * \param flags The recv options.
855 * \return The number of bytes read.
857 ssize_t
read(void* bytes
,
859 socket::address
& address
,
865 struct sockaddr_storage storage
;
867 socklen_t length
= sizeof(addr
);
870 ssize_t result
= recvfrom(impl_
.fd
,
871 reinterpret_cast<char*>(bytes
), size
,
875 ssize_t result
= recvfrom(impl_
.fd
, bytes
, size
, flags
,
880 address
= socket::address(&addr
.sa
, length
,
881 impl_
.address
.type());
883 else if (result
== 0)
885 impl_
.is_connected
= false;
891 * Read a packet from the socket. Use this for connected sockets.
892 * \param packet Set to the packet read on return.
893 * \param flags The recv options.
894 * \return The number of bytes read.
896 ssize_t
read(packet
& packet
, int flags
= 0)
899 ssize_t result
= read(buffer
, sizeof(buffer
), flags
);
900 if (result
!= -1) packet
= moof::packet(buffer
, result
);
905 * Read a packet from the socket using the given address. Use this for
906 * unconnected sockets.
907 * \param packet Set to the packet read on return.
908 * \param address The address to read from.
909 * \param flags The recv options.
910 * \return The number of bytes read.
912 ssize_t
read(packet
& packet
, address
& address
, int flags
= 0)
915 ssize_t result
= read(buffer
, sizeof(buffer
), address
, flags
);
916 if (result
!= -1) packet
= moof::packet(buffer
, result
);
921 // The rest of this junk is used to implement the "move" semantics
922 // correctly, since it makes no sense for socket objects to be copied.
924 socket(socket
& move
) :
928 move
.impl_
.is_connected
= false;
934 socket
& operator=(socket
& move
)
939 move
.impl_
.is_connected
= false;
943 socket
& operator=(impl move
)
954 impl_
.is_connected
= false;
963 // for accepting a socket from fd
967 struct sockaddr_storage storage
;
969 socklen_t length
= sizeof(addr
);
971 impl_
.fd
= ::accept(fd
, &addr
.sa
, &length
);
974 impl_
.is_connected
= true;
975 impl_
.address
= address(&addr
.sa
, length
);
982 if (impl_
.fd
!= -1) closesocket(impl_
.fd
);
984 if (impl_
.fd
!= -1) ::close(impl_
.fd
);
990 class socket_multiplexer
994 typedef boost::function
<int(socket_multiplexer
&,
996 const socket::address
&)> function
;
998 explicit socket_multiplexer(moof::socket sock
) :
1002 void socket(moof::socket sock
)
1004 MOOF_MUTEX_LOCK(mutex_
);
1008 moof::socket
& socket()
1014 std::vector
<function
>& protocols()
1020 void update(scalar t
, scalar dt
)
1022 socket::address address
;
1024 ssize_t bytes
= socket_
.read(packet
, address
);
1028 std::vector
<function
>::iterator it
;
1029 for (it
= protocols_
.begin(); it
< protocols_
.end(); ++it
)
1032 if ((*it
)(*this, packet
, address
)) break;
1046 moof::socket socket_
;
1047 std::vector
<function
> protocols_
;
1049 MOOF_DECLARE_MUTEX(mutex_
);
1054 * An asynchronous task to resolve addresses.
1056 class resolver_task
: public threaded_task
1061 * Construct a resolver task from a service and hostname.
1062 * \param service Server name or port number.
1063 * \param name The hostname or numeric address.
1064 * \param type The type of communication.
1065 * \param family The requested protocol family.
1067 resolver_task(const std::string
& service
,
1068 const std::string
& name
,
1069 int type
= SOCK_STREAM
,
1070 int family
= AF_UNSPEC
) :
1073 function_
= boost::bind(&resolver_task::resolve
,
1074 this, service
, name
, type
, family
);
1079 * Get whether or not the task is done.
1080 * \return True if the task has finished, false otherwise.
1082 bool is_done() const
1088 * Start the task. This does nothing if the task was already run or is
1089 * currently running.
1093 if (!is_done() && !thread_
.is_valid())
1095 thread_
= thread::detach(function_
);
1101 * Get the addresses resolved. This is filled and safe to access after
1102 * the task finishes.
1103 * \return List of addresses.
1106 const std::vector
<socket::address
>& addresses() const
1108 return address_list_
;
1114 int resolve(const std::string
& service
,
1115 const std::string
& name
,
1119 int status
= socket::address::resolve(service
, name
,
1127 std::vector
<socket::address
> address_list_
;
1129 thread::function function_
;
1134 * Insert a string representation of a socket address into a stream.
1135 * \param stream The output stream.
1136 * \param addr The socket address.
1137 * \return The stream.
1139 std::ostream
& operator << (std::ostream
& stream
, const socket::address
& addr
)
1141 stream
<< addr
.name() << ":" << addr
.service();
1146 * Insert a string representation of a socket into a stream.
1147 * \param stream The output stream.
1148 * \param addr The socket.
1149 * \return The stream.
1151 std::ostream
& operator << (std::ostream
& stream
, const socket
& sock
)
1153 stream
<< sock
.peer_address();
1160 #endif // _MOOF_SOCKET_HH_
This page took 0.080709 seconds and 4 git commands to generate.