2411cc2e90a0c4c28c16ebf5bbe103fa255cf049
[chaz/yoink] / src / Moof / Socket.hh
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
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.
9 *
10 **************************************************************************/
11
12 #ifndef _MOOF_SOCKET_HH_
13 #define _MOOF_SOCKET_HH_
14
15 #include <algorithm>
16 #include <cstring>
17 #include <sstream>
18 #include <string>
19 #include <vector>
20
21 #if defined(_WIN32)
22 #include <winsock2.h>
23 #include <ws2tcpip.h>
24 #include <wspiapi.h>
25 #else
26 #include <arpa/inet.h>
27 #include <netdb.h>
28 #include <sys/socket.h>
29 #include <sys/types.h>
30 #if HAVE_FCNTL_H
31 #include <fcntl.h>
32 #else
33 #include <sys/ioctl.h>
34 #endif
35 #endif
36
37 #include <Moof/Log.hh>
38 #include <Moof/Packet.hh>
39 #include <Moof/Thread.hh>
40
41
42 #ifndef SO_NONBLOCK
43 #define SO_NONBLOCK 1024
44 #endif
45
46
47 namespace Mf {
48
49
50 /**
51 * A class to represent the address of a remote host, including the type of
52 * service and socket communication.
53 */
54 class SocketAddress
55 {
56 public:
57
58 /**
59 * Construct an unspecified address.
60 */
61 SocketAddress() :
62 mSize(0),
63 mType(0)
64 {
65 mAddr.sa.sa_family = AF_UNSPEC;
66 mAddr.in.sin_port = 0;
67 }
68
69 /**
70 * Construct an address with a specified host. The address can be used
71 * to connect to a host.
72 * \param service The service name or port number.
73 * \param host The numeric IP address of the host.
74 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
75 * \param family The family; can be AF_INET or AF_INET6.
76 */
77 SocketAddress(const std::string& service,
78 const std::string& host,
79 int type = SOCK_STREAM,
80 int family = AF_UNSPEC)
81 {
82 init(service, host, type, family);
83 }
84
85 /**
86 * Construct an address without a specified host. The address can be
87 * used to accept on a local port.
88 * \param service The service name or port number.
89 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
90 * \param family The family; can be AF_INET or AF_INET6.
91 */
92 SocketAddress(const std::string& service,
93 int type = SOCK_STREAM,
94 int family = AF_UNSPEC)
95 {
96 init(service, type, family);
97 }
98
99 /**
100 * Construct an address from the information in an addrinfo structure.
101 * \param addr The addrinfo structure.
102 */
103 SocketAddress(const struct addrinfo* addr) :
104 mSize(addr->ai_addrlen),
105 mType(addr->ai_socktype)
106 {
107 memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
108 getServiceAndHostName(mService, mHost);
109 }
110
111 /**
112 * Construct an address from a sockaddr structure.
113 * \param addr The sockaddr structure.
114 * \param size The size of the sockaddr structure.
115 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
116 */
117 SocketAddress(const struct sockaddr* addr,
118 size_t size,
119 int type = SOCK_STREAM) :
120 mSize(size),
121 mType(type)
122 {
123 memcpy(&mAddr.sa, addr, size);
124 getServiceAndHostName(mService, mHost);
125 }
126
127
128 /**
129 * Get an IPv4 broadcast address.
130 * \param service The service name or port number.
131 * \return The socket address.
132 */
133 static SocketAddress broadcast(const std::string& service)
134 {
135 std::istringstream stream(service);
136 unsigned short port;
137 stream >> port;
138
139 struct sockaddr_in addr;
140 addr.sin_family = AF_INET;
141 addr.sin_port = htons(port);
142 addr.sin_addr.s_addr = INADDR_BROADCAST;
143 memset(&addr.sin_zero, 0, sizeof(addr.sin_zero));
144 return SocketAddress((sockaddr*)&addr, sizeof(addr), SOCK_DGRAM);
145 }
146
147
148 /**
149 * Initialize the address with a specified host. The address can be
150 * used to connect to a host.
151 * \param service The service name or port number.
152 * \param host The numeric IP address of the host.
153 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
154 * \param family The family; can be AF_INET or AF_INET6.
155 */
156 void init(const std::string& service,
157 const std::string& host,
158 int type = SOCK_STREAM,
159 int family = AF_UNSPEC)
160 {
161 struct addrinfo* addr = resolve(service.c_str(), host.c_str(),
162 type, family,
163 AI_ADDRCONFIG | AI_NUMERICHOST | AI_V4MAPPED);
164 if (addr)
165 {
166 mSize = addr->ai_addrlen;
167 mType = addr->ai_socktype;
168 memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
169
170 mService = service;
171 mHost = host;
172
173 freeaddrinfo(addr);
174 }
175 else
176 {
177 mType = 0;
178 mSize = 0;
179 mAddr.sa.sa_family = AF_UNSPEC;
180 mAddr.in.sin_port = 0;
181 }
182 }
183
184 /**
185 * Initialize the address without a specified host. The address can be
186 * used to accept on a local port.
187 * \param service The service name or port number.
188 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
189 * \param family The family; can be AF_INET or AF_INET6.
190 */
191 void init(const std::string& service,
192 int type = SOCK_STREAM,
193 int family = AF_UNSPEC)
194 {
195 struct addrinfo* addr = resolve(service.c_str(), 0,
196 type, family,
197 AI_PASSIVE);
198 if (addr)
199 {
200 mSize = addr->ai_addrlen;
201 mType = addr->ai_socktype;
202 memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
203
204 mService = service;
205 getHost(mHost);
206
207 freeaddrinfo(addr);
208 }
209 else
210 {
211 mType = 0;
212 mSize = 0;
213 mAddr.sa.sa_family = AF_UNSPEC;
214 mAddr.in.sin_port = 0;
215 }
216 }
217
218
219 /**
220 * Get the name of the service. This could also be a port number if
221 * there is no service name associated with the number.
222 * \return The service.
223 */
224 const std::string& service() const
225 {
226 return mService;
227 }
228
229 /**
230 * Get the name of the host. This may be the host used to construct
231 * the address, or a resolved numeric host if none was used.
232 * \return The host.
233 */
234 const std::string& host() const
235 {
236 return mHost;
237 }
238
239 /**
240 * Get the port number of the address service.
241 * \return Port number.
242 */
243 unsigned short port() const
244 {
245 return ntohs(mAddr.in.sin_port);
246 }
247
248 /**
249 * Get the type of socket associated with the service of this address.
250 * \return Socket type; either SOCK_STREAM or SOCK_DGRAM.
251 */
252 int type() const
253 {
254 return mType;
255 }
256
257 /**
258 * Get the family of the protocol associated with the address.
259 * \return Protocol family; either AF_INET, AF_INET6, or AF_UNSPEC.
260 */
261 int family() const
262 {
263 return mAddr.sa.sa_family;
264 }
265
266
267 /**
268 * Get the sockaddr structure of the address.
269 * \return The sockaddr structure.
270 */
271 const struct sockaddr* address() const
272 {
273 return mSize != 0 ? &mAddr.sa : 0;
274 }
275
276 /**
277 * Get the size of the sockaddr structure of the address.
278 * \return The size of the sockaddr structure.
279 */
280 size_t size() const
281 {
282 return mSize;
283 }
284
285
286 /**
287 * Get a list of addresses resolved to by the given search criteria.
288 * This can be used to perform lookups for name resolution, so this
289 * method may take some time to return. Use the ResolveTask class to
290 * resolve addresses asynchronously.
291 * \param service The service name or port number.
292 * \param host The name of the local or remote host.
293 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
294 * \param family The family; can be AF_INET or AF_INET6.
295 * \param resolved The list to be filled with addresses.
296 * \return 0 on success, -1 on error.
297 */
298 static int resolve(const std::string& service,
299 const std::string& host,
300 int type,
301 int family,
302 std::vector<SocketAddress>& resolved)
303 {
304 struct addrinfo* list = resolve(service.c_str(), host.c_str(),
305 type, family,
306 AI_ADDRCONFIG | AI_V4MAPPED);
307 int result = collectAddresses(list, resolved);
308 freeaddrinfo(list);
309 return result;
310 }
311
312 /**
313 * Get a list of addresses resolved to by the given search criteria.
314 * The addresses will be suitable for accepting on a local port.
315 * \param service The service name or port number.
316 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
317 * \param family The family; can be AF_INET or AF_INET6.
318 * \param resolved The list to be filled with addresses.
319 * \return 0 on success, -1 on error.
320 */
321 static int resolve(const std::string& service,
322 int type,
323 int family,
324 std::vector<SocketAddress>& resolved)
325 {
326 struct addrinfo* list = resolve(service.c_str(), 0,
327 type, family,
328 AI_PASSIVE);
329 int result = collectAddresses(list, resolved);
330 freeaddrinfo(list);
331 return result;
332 }
333
334
335 private:
336
337 static struct addrinfo* resolve(const char* service,
338 const char* node,
339 int type,
340 int family,
341 int flags)
342 {
343 ASSERT(type == SOCK_STREAM || type == SOCK_DGRAM);
344 ASSERT(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
345
346 struct addrinfo hints;
347 memset(&hints, 0, sizeof(hints));
348 hints.ai_family = family;
349 hints.ai_socktype = type;
350 hints.ai_flags = flags;
351
352 struct addrinfo* addr;
353 int status = getaddrinfo(node, service, &hints, &addr);
354
355 if (status == 0)
356 {
357 return addr;
358 }
359 else
360 {
361 Mf::logWarning(gai_strerror(status));
362 return 0;
363 }
364 }
365
366 static int collectAddresses(struct addrinfo* addresses,
367 std::vector<SocketAddress>& resolved)
368 {
369 if (addresses)
370 {
371 resolved.clear();
372
373 for (struct addrinfo* addr = addresses;
374 addr != 0;
375 addr = addr->ai_next)
376 {
377 resolved.push_back(SocketAddress(addr));
378 }
379
380 return 0;
381 }
382 else return -1;
383 }
384
385
386 void getService(std::string& service)
387 {
388 char value[64] = {'\0'};
389 int result = getnameinfo(&mAddr.sa, mSize,
390 0, 0,
391 value, sizeof(value),
392 (mType == SOCK_DGRAM) ? NI_DGRAM : 0);
393 if (result == 0) service.assign(value);
394 }
395
396 void getHost(std::string& host)
397 {
398 char value[256] = {'\0'};
399 int result = getnameinfo(&mAddr.sa, mSize,
400 value, sizeof(value),
401 0, 0,
402 NI_NUMERICHOST);
403 if (result == 0) host.assign(value);
404 }
405
406 void getServiceAndHostName(std::string& service, std::string& host)
407 {
408 char serv[64] = {'\0'};
409 char node[256] = {'\0'};
410 int result = getnameinfo(&mAddr.sa, mSize,
411 node, sizeof(node),
412 serv, sizeof(serv),
413 NI_NUMERICHOST |
414 ((mType == SOCK_DGRAM) ? NI_DGRAM : 0));
415 if (result == 0)
416 {
417 service.assign(serv);
418 host.assign(node);
419 }
420 }
421
422
423 union
424 {
425 sockaddr sa;
426 sockaddr_in in;
427 sockaddr_storage storage;
428 } mAddr;
429 size_t mSize;
430 int mType;
431
432 std::string mHost;
433 std::string mService;
434 };
435
436
437 /**
438 * The socket class represents a connection or between this node and a
439 * remote node.
440 */
441 class Socket
442 {
443 struct Impl
444 {
445 SocketAddress address;
446 int fd;
447 bool isConnected;
448
449 Impl() :
450 fd(-1),
451 isConnected(false) {}
452
453 Impl(const SocketAddress& address, int flags = 0) :
454 address(address),
455 fd(::socket(address.family(), address.type(), flags)),
456 isConnected(false) {}
457 } mImpl;
458
459
460 public:
461
462 /**
463 * Construct a socket with no associated peer.
464 */
465 Socket() {}
466
467 /**
468 * Construct a socket with an address.
469 * \param address The address.
470 * \param flags The socket options.
471 */
472 Socket(const SocketAddress& address, int flags = 0) :
473 mImpl(address, flags) {}
474
475 /**
476 * Construct a socket with a specified host. The socket can be used to
477 * connect to a host.
478 * \param service The service name or port number.
479 * \param host The numeric IP address of the host.
480 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
481 * \param family The family; can be AF_INET or AF_INET6.
482 * \param flags The socket options.
483 */
484 Socket(const std::string& service, const std::string& name,
485 int type = SOCK_STREAM, int family = AF_UNSPEC,
486 int flags = 0) :
487 mImpl(SocketAddress(service, name, type, family), flags) {}
488
489 /**
490 * Construct a socket without a specified host. The socket can be used
491 * to accept sockets on a local port.
492 * \param service The service name or port number.
493 * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
494 * \param family The family; can be AF_INET or AF_INET6.
495 * \param flags The socket options.
496 */
497 Socket(const std::string& service, int type = SOCK_STREAM,
498 int family = AF_UNSPEC, int flags = 0) :
499 mImpl(SocketAddress(service, type, family), flags) {}
500
501
502 /**
503 * Deconstruct the socket, closing it.
504 */
505 ~Socket()
506 {
507 close();
508 }
509
510
511 /**
512 * Get whether or not the socket is connected.
513 * \return True if the socket is connected, false otherwise.
514 */
515 bool isConnected() const
516 {
517 return mImpl.isConnected;
518 }
519
520 /**
521 * Get the address associated with the socket.
522 */
523 const SocketAddress& address() const
524 {
525 return mImpl.address;
526 }
527
528
529 /**
530 * Connect the socket to its peer.
531 * \return 0 on success, -1 on failure.
532 */
533 int connect()
534 {
535 int result = ::connect(mImpl.fd,
536 mImpl.address.address(),
537 mImpl.address.size());
538 mImpl.isConnected = result != -1;
539 return result;
540 }
541
542 /**
543 * Disconnect a connected socket from its peer.
544 * \param flags Specify the socket directions to close.
545 * \return 0 on success, -1 on failure.
546 */
547 int disconnect(int flags = SHUT_RDWR)
548 {
549 return shutdown(mImpl.fd, flags);
550 }
551
552
553 /**
554 * Bind the socket to interface and port number specified in the
555 * address.
556 * \return 0 on success, -1 on failure.
557 */
558 int bind()
559 {
560 return ::bind(mImpl.fd,
561 mImpl.address.address(),
562 mImpl.address.size());
563 }
564
565 /**
566 * Listen on the socket for incoming connections. This is only useful
567 * for sockets of type SOCK_STREAM.
568 * \param backlog The number of unaccepted connections to queue.
569 * \return 0 on success, -1 on failure.
570 */
571 int listen(int backlog = SOMAXCONN)
572 {
573 return ::listen(mImpl.fd, backlog > 0 ? backlog : SOMAXCONN);
574 }
575
576 /**
577 * Accept a new connection on the socket. This is only useful for
578 * sockets of type SOCK_STREAM.
579 * \param socket Set to the new socket on return.
580 * \return 0 on success, -1 on failure.
581 */
582 int accept(Socket& socket)
583 {
584 Socket temp = Socket(mImpl.fd);
585 if (temp.mImpl.fd != -1)
586 {
587 socket = temp;
588 return socket.mImpl.fd;
589 }
590 return -1;
591 }
592
593
594 /**
595 * Set an integer socket option.
596 * \param option The option to set.
597 * \param value The new value.
598 * \return 0 on success, -1 on failure.
599 */
600 int set(int option, int value = 0)
601 {
602 if (option == SO_NONBLOCK)
603 {
604 #ifdef HAVE_FCNTL
605 int flags = fcntl(mImpl.fd, F_GETFL);
606 return fcntl(mImpl.fd,
607 F_SETFL,
608 flags | (value ? O_NONBLOCK : 0));
609 #else
610 return ioctl(mImpl.fd, FIONBIO, value);
611 #endif
612 }
613 return setsockopt(mImpl.fd, SOL_SOCKET, option,
614 &value, sizeof(value));
615 }
616
617 /**
618 * Set a string socket option.
619 * \param option The option to set.
620 * \param value The new value.
621 * \return 0 on success, -1 on failure.
622 */
623 int set(int option, const std::string& value)
624 {
625 return setsockopt(mImpl.fd, SOL_SOCKET, option,
626 value.data(), value.length());
627 }
628
629 /**
630 * Get an integer socket option.
631 * \param option The option to set.
632 * \param value The new value.
633 * \return 0 on success, -1 on failure.
634 */
635 int get(int option, int& value)
636 {
637 if (option == SO_NONBLOCK)
638 {
639 #ifdef HAVE_FCNTL
640 int flags = fcntl(mImpl.fd, F_GETFL);
641 return flags & O_NONBLOCK;
642 #else
643 return ioctl(mImpl.fd, FIONBIO, &value);
644 #endif
645 }
646 socklen_t optlen = sizeof(value);
647 return getsockopt(mImpl.fd, SOL_SOCKET, option, &value, &optlen);
648 }
649
650 /**
651 * Get a string socket option.
652 * \param option The option to set.
653 * \param value The new value.
654 * \return 0 on success, -1 on failure.
655 */
656 int get(int option, std::string& value)
657 {
658 char str[256] = {'\0'};
659 socklen_t optlen = sizeof(str);
660 int result = getsockopt(mImpl.fd, SOL_SOCKET, option,
661 &str, &optlen);
662 value = str;
663 return result;
664 }
665
666
667 /**
668 * Write some bytes to the socket. Use this for connected sockets.
669 * \param bytes The bytes.
670 * \param size The number of bytes.
671 * \param flags The send options.
672 * \return The number of bytes written.
673 */
674 ssize_t write(const void* bytes, size_t size, int flags = 0)
675 {
676 return send(mImpl.fd, bytes, size, flags);
677 }
678
679 /**
680 * Write some bytes to the socket using the given address. Use this
681 * for unconnected sockets.
682 * \param bytes The bytes.
683 * \param size The number of bytes.
684 * \param address The address to send to.
685 * \param flags The send options.
686 * \return The number of bytes written.
687 */
688 ssize_t write(const void* bytes, size_t size,
689 const SocketAddress& address, int flags = 0)
690 {
691 return sendto(mImpl.fd, bytes, size, flags,
692 address.address(), address.size());
693 }
694
695 /**
696 * Write a packet to the socket. Use this for connected sockets.
697 * \param packet The packet.
698 * \param flags The send options.
699 * \return The number of bytes written.
700 */
701 ssize_t write(const Packet& packet, int flags = 0)
702 {
703 return write(packet.bytes(), packet.size(), flags);
704 }
705
706 /**
707 * Write a packet to the socket using the given address. Use this for
708 * unconnected sockets.
709 * \param packet The packet.
710 * \param address The address to send to.
711 * \param flags The send options.
712 * \return The number of bytes written.
713 */
714 ssize_t write(const Packet& packet, const SocketAddress& address,
715 int flags = 0)
716 {
717 return write(packet.bytes(), packet.size(), address, flags);
718 }
719
720
721 /**
722 * Read some bytes from the socket. Use this for connected sockets.
723 * \param bytes The buffer to store the bytes.
724 * \param size The size of the buffer.
725 * \param flags The recv options.
726 * \return The number of bytes read.
727 */
728 ssize_t read(void* bytes, size_t size, int flags = 0)
729 {
730 return recv(mImpl.fd, bytes, size, flags);
731 }
732
733 /**
734 * Read some bytes from the socket using the given address. Use this
735 * for unconnected sockets.
736 * \param bytes The buffer to store the bytes.
737 * \param size The size of the buffer.
738 * \param address The address to read from.
739 * \param flags The recv options.
740 * \return The number of bytes read.
741 */
742 ssize_t read(void* bytes, size_t size, SocketAddress& address,
743 int flags = 0)
744 {
745 union
746 {
747 sockaddr sa;
748 sockaddr_storage storage;
749 } addr;
750 socklen_t length = sizeof(addr);
751
752 ssize_t result = recvfrom(mImpl.fd, bytes, size, flags,
753 &addr.sa, &length);
754 if (result != -1)
755 {
756 address = SocketAddress(&addr.sa, length, mImpl.address.type());
757 }
758 return result;
759 }
760
761 /**
762 * Read a packet from the socket. Use this for connected sockets.
763 * \param packet Set to the packet read on return.
764 * \param flags The recv options.
765 * \return The number of bytes read.
766 */
767 ssize_t read(Packet& packet, int flags = 0)
768 {
769 char buffer[65536];
770 ssize_t result = read(buffer, sizeof(buffer), flags);
771 if (result != -1) packet = Packet(buffer, result);
772 return result;
773 }
774
775 /**
776 * Read a packet from the socket using the given address. Use this for
777 * unconnected sockets.
778 * \param packet Set to the packet read on return.
779 * \param address The address to read from.
780 * \param flags The recv options.
781 * \return The number of bytes read.
782 */
783 ssize_t read(Packet& packet, SocketAddress& address, int flags = 0)
784 {
785 char buffer[65536];
786 ssize_t result = read(buffer, sizeof(buffer), address, flags);
787 if (result != -1) packet = Packet(buffer, result);
788 return result;
789 }
790
791
792 // The rest of this junk is used to implement the "move" semantics
793 // correctly, since it makes no sense for socket objects to be copied.
794
795 Socket(Socket& move) :
796 mImpl(move.mImpl)
797 {
798 move.mImpl.fd = -1;
799 move.mImpl.isConnected = false;
800 }
801
802 Socket(Impl move) :
803 mImpl(move) {}
804
805 Socket& operator=(Socket& move)
806 {
807 close();
808 mImpl = move.mImpl;
809 move.mImpl.fd = -1;
810 move.mImpl.isConnected = false;
811 return *this;
812 }
813
814 Socket& operator=(Impl move)
815 {
816 close();
817 mImpl = move;
818 return *this;
819 }
820
821 operator Impl()
822 {
823 Impl impl(mImpl);
824 mImpl.fd = -1;
825 mImpl.isConnected = false;
826 return impl;
827 }
828
829
830 private:
831
832 Socket(int fd)
833 {
834 // for accepting a socket from fd
835 union
836 {
837 sockaddr sa;
838 sockaddr_storage storage;
839 } addr;
840 socklen_t length = sizeof(addr);
841
842 mImpl.fd = ::accept(fd, &addr.sa, &length);
843 if (mImpl.fd != -1)
844 {
845 mImpl.isConnected = true;
846 mImpl.address = SocketAddress(&addr.sa, length);
847 }
848 }
849
850 void close()
851 {
852 #if defined(_WIN32)
853 if (mImpl.fd != -1) closesocket(mImpl.fd);
854 #else
855 if (mImpl.fd != -1) ::close(mImpl.fd);
856 #endif
857 }
858 };
859
860
861 /**
862 * An asynchronous task to resolve addresses.
863 */
864 class ResolverTask : public ThreadedTask
865 {
866 public:
867
868 /**
869 * Construct a resolver task from a service and hostname.
870 * \param service Server name or port number.
871 * \param host The hostname or numeric address.
872 * \param type The type of communication.
873 * \param family The requested protocol family.
874 */
875 ResolverTask(const std::string& service,
876 const std::string& host,
877 int type = SOCK_STREAM,
878 int family = AF_UNSPEC) :
879 mIsDone(false)
880 {
881 mFunction = boost::bind(&ResolverTask::resolve,
882 this, service, host, type, family);
883 }
884
885
886 /**
887 * Get whether or not the task is done.
888 * \return True if the task has finished, false otherwise.
889 */
890 bool isDone() const
891 {
892 return mIsDone;
893 }
894
895 /**
896 * Start the task. This does nothing if the task was already run or is
897 * currently running.
898 */
899 void run()
900 {
901 if (!isDone() && !mThread.isValid())
902 {
903 mThread = Thread::detach(mFunction);
904 }
905 }
906
907
908 /**
909 * Get the addresses resolved. This is filled and safe to access after
910 * the task finishes.
911 * \return List of addresses.
912 * \see isDone()
913 */
914 const std::vector<SocketAddress>& addresses() const
915 {
916 return mAddressList;
917 }
918
919
920 private:
921
922 int resolve(const std::string& service,
923 const std::string& host,
924 int type,
925 int family)
926 {
927 int status = SocketAddress::resolve(service, host,
928 type, family,
929 mAddressList);
930 mIsDone = true;
931 return status;
932 }
933
934
935 std::vector<SocketAddress> mAddressList;
936 bool mIsDone;
937 Thread::Function mFunction;
938 };
939
940
941 } // namespace Mf
942
943 #endif // _MOOF_SOCKET_HH_
944
This page took 0.067928 seconds and 3 git commands to generate.