]> git.llucax.com Git - software/posixx.git/blob - src/socket/basic_socket.hpp
Add Boost License
[software/posixx.git] / src / socket / basic_socket.hpp
1 // Copyright Leandro Lucarella 2008 - 2010.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file COPYING or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6
7 #ifndef POSIXX_SOCKET_BASIC_SOCKET_HPP_
8 #define POSIXX_SOCKET_BASIC_SOCKET_HPP_
9
10 #include "../error.hpp" // posixx::error
11 #include "../static_assert.hpp" // static_assert
12
13 #include <string> // std::string
14 #include <utility> // std::pair
15 #include <sys/socket.h> // socket, send, recv, etc.
16
17 /// @file
18
19 /// POSIX thin wrapper
20 namespace posixx {
21
22 /// BSD socket API
23 namespace socket {
24
25 /**
26  * Socket type.
27  *
28  * @see socket().
29  * @see socket(7).
30  */
31 enum type
32 {
33         /**
34          * Connectionless, unreliable messages of a fixed maximum
35          * length.
36          */
37         DGRAM = SOCK_DGRAM,
38         /**
39          * Reliable datagram layer that does not guarantee ordering.
40          */
41         RDM = SOCK_RDM,
42         /**
43          * Sequenced, reliable, two-way connection-based datagram
44          * transmission.
45          *
46          * Sequenced, reliable, two-way connection-based data
47          * transmission path for datagrams of fixed maximum length;
48          * a consumer is required to read an entire packet with each
49          * read system call.
50          */
51         SEQPACKET = SOCK_SEQPACKET,
52         /**
53          * Sequenced, reliable, two-way, connection-based byte streams.
54          *
55          * An out-of-band data transmission mechanism may be supported.
56          */
57         STREAM = SOCK_STREAM,
58         /**
59          * Raw network protocol access.
60          */
61         RAW = SOCK_RAW
62 };
63
64 /**
65  * Shutdown mode.
66  *
67  * @see socket::shutdown().
68  * @see shutdown(2).
69  */
70 enum shutdown_mode
71 {
72         RD = SHUT_RD,    ///< Further receptions will be disallowed.
73         WR = SHUT_WR,    ///< Further transmissions will be disallowed.
74         RDWR = SHUT_RDWR ///< Both will be disallowed.
75 };
76
77 /**
78  * Generic socket interface.
79  *
80  * This class is thread-safe as it just stores a file descriptor for the socket.
81  *
82  * @see socket(7)
83  */
84 template < typename TSockTraits >
85 struct basic_socket
86 {
87
88         /// Traits used by this socket
89         typedef TSockTraits traits;
90
91         /**
92          * Create an endpoint for communication.
93          *
94          * @param type Type of socket.
95          * @param protocol Protocol number.
96          *
97          * @see socket(2), socket(7)
98          */
99         basic_socket(type type, int protocol = 0) throw (error);
100
101         /**
102          * Create a socket instance from a file descriptor.
103          *
104          * This is mainly used by the accept() method and pair() function and
105          * should be used with care because it takes "ownership" of the file
106          * descriptor (it's closed by the destructor).
107          *
108          * Use with care.
109          *
110          * @param fd Socket file descriptor.
111          */
112         explicit basic_socket(int fd) throw ();
113
114         /**
115          * Bind a name to the socket.
116          *
117          * @param addr Protocol-dependant name to bind on.
118          *
119          * @see bind(2)
120          */
121         void bind(const typename TSockTraits::sockaddr& addr) throw (error);
122
123         /**
124          * Initiate a connection on the socket.
125          *
126          * @param addr Protocol-dependant name to connect to.
127          *
128          * @see connect(2)
129          */
130         void connect(const typename TSockTraits::sockaddr& addr) throw (error);
131
132         /**
133          * Get the socket name.
134          *
135          * @return Protocol-dependant name binded.
136          *
137          * @see getsockname(2)
138          */
139         typename TSockTraits::sockaddr name() const throw (error);
140
141         /**
142          * Get the name of connected peer socket.
143          *
144          * @return Protocol-dependant name of the peer.
145          *
146          * @see getpeername(2)
147          */
148         typename TSockTraits::sockaddr peer_name() const throw (error);
149
150         /**
151          * Send a message on the socket.
152          *
153          * @param buf Message buffer.
154          * @param n Message length.
155          * @param flags Sending options.
156          *
157          * @return The number of characters sent.
158          *
159          * @see send(2), connect()
160          *
161          * @todo make an enum for the flags (are they protocol-dependant?)
162          */
163         ssize_t send(const void* buf, size_t n, int flags = 0) throw (error);
164
165         /**
166          * Receive a message on the socket.
167          *
168          * @param buf Message buffer.
169          * @param n Maximum message length.
170          * @param flags Receiving options.
171          *
172          * @return The number of characters received.
173          *
174          * @see recv(2), connect()
175          *
176          * @todo make an enum for the flags (are they protocol-dependant?)
177          */
178         ssize_t recv(void* buf, size_t n, int flags = 0) throw (error);
179
180         /**
181          * Send a message on the socket to a specific name.
182          *
183          * @param buf Message buffer.
184          * @param n Message length.
185          * @param to Name to send the message to.
186          * @param flags Sending options.
187          *
188          * @return The number of characters sent.
189          *
190          * @see sendto(2)
191          *
192          * @todo make an enum for the flags (are they protocol-dependant?)
193          */
194         ssize_t send(const void* buf, size_t n,
195                         const typename TSockTraits::sockaddr& to,
196                         int flags = 0) throw (error);
197
198         /**
199          * Receive a message on the socket from a specific name.
200          *
201          * @param buf Message buffer.
202          * @param n Maximum message length.
203          * @param from Name to receive the message from.
204          * @param flags Receiving options.
205          *
206          * @return The number of characters received.
207          *
208          * @see recvfrom(2)
209          *
210          * @todo make an enum for the flags (are they protocol-dependant?)
211          */
212         ssize_t recv(void* buf, size_t n, typename TSockTraits::sockaddr& from,
213                         int flags = 0) throw (error);
214
215         /**
216          * Get options on the socket.
217          *
218          * @param level Level at which the option reside.
219          * @param optname Name of the option.
220          * @param opt Where to store the option value.
221          *
222          * @see getsockopt(2)
223          */
224         template< typename TSockOpt >
225         void getsockopt(int level, int optname, TSockOpt& opt) const
226                         throw (error);
227
228         /**
229          * Set options on the socket.
230          *
231          * @param level Level at which the option reside.
232          * @param optname Name of the option.
233          * @param opt New option value.
234          *
235          * @see setsockopt(2)
236          */
237         template< typename TSockOpt >
238         void setsockopt(int level, int optname, const TSockOpt& opt)
239                         throw (error);
240
241         /**
242          * Get option on the socket (type-safe).
243          *
244          * Note that template argument must be specified explicitly, and the
245          * template argument must be a valid socket option, which is a struct
246          * with 5 members: level, optname, read, write and type. level and
247          * optname must be the corresponding SOL_* and SO_* constants. read and
248          * write must be boolean constants indicating if the options can be
249          * read or written. type should be the type of the option's argument.
250          *
251          * See sockopt namespaces for available options.
252          *
253          * @return Option value
254          *
255          * @see getsockopt()
256          */
257         template< typename TSockOpt >
258         typename TSockOpt::type opt() const throw (error);
259
260         /**
261          * Set option on the socket (type-safe).
262          *
263          * See getsockopt() for details on how options can be constructed.
264          *
265          * @param opt Option value
266          *
267          * @see setsockopt()
268          */
269         template< typename TSockOpt >
270         void opt(const typename TSockOpt::type& opt) throw (error);
271
272         /**
273          * Listen for connections on the socket.
274          *
275          * @param backlog Maximum length the queue of pending
276          *                        connections may grow to.
277          *
278          * @see accept(), listen(2)
279          */
280         void listen(int backlog = 5) throw (error);
281
282         /**
283          * Accept a connection on the socket.
284          *
285          * @see listen(), accept(2)
286          */
287         basic_socket* accept() throw (error);
288
289         /**
290          * Accept a connection on the socket.
291          *
292          * @param addr Address of the peer socket, as known to the
293          *             communications layer.
294          *
295          * @see listen(), accept(2)
296          */
297         basic_socket* accept(typename TSockTraits::sockaddr& addr)
298                         throw (error);
299
300         /**
301          * Shut down part of a full-duplex connection.
302          *
303          * @param how How the connection is shutted down.
304          *
305          * @see shutdown(2)
306          */
307         void shutdown(shutdown_mode how = RDWR) throw (error);
308
309         /**
310          * Close the socket file descriptor.
311          *
312          * @see close(2)
313          */
314         void close() throw (error);
315
316         /**
317          * Destructor.
318          *
319          * Closes the socket.
320          *
321          * @see shutdown(), close()
322          */
323         ~basic_socket() throw ();
324
325         // Higher level API
326
327         /**
328          * Send a message on the socket.
329          *
330          * The message could be any struct and is sent as binary data without
331          * any concerns about the byte-order.
332          *
333          * This is a shortcut for the low-level send() method, where the
334          * message length is calculated as sizeof(TPacket).
335          *
336          * Of course, TPacket should be a POD type, without pointers or
337          * references.
338          *
339          * This method loops on the low-level send() until all the data is
340          * sent, or throws an exception if the send() can't be completed.
341          *
342          * @param packet Message struct to send.
343          * @param flags Sending options.
344          *
345          * @see send()
346          *
347          * @todo make an enum for the flags (are they protocol-dependant?)
348          */
349         template< typename TPacket >
350         void send_struct(const TPacket& packet, int flags = MSG_NOSIGNAL)
351                         throw (error);
352
353         /**
354          * Receive a message on the socket.
355          *
356          * The message could be any struct and is received as binary data
357          * without any concerns about the byte-order.
358          *
359          * This is a shortcut for the low-level recv() method, where the
360          * message length is calculated as sizeof(TPacket).
361          *
362          * Of course, TPacket should be a POD type, without pointers or
363          * references.
364          *
365          * This method loops on the low-level recv() until all the data is
366          * received, or throws an exception if the recv() can't be completed.
367          *
368          * @param packet Message struct to receive on.
369          * @param flags Sending options.
370          *
371          * @see recv()
372          *
373          * @todo make an enum for the flags (are they protocol-dependant?)
374          */
375         template< typename TPacket >
376         void recv_struct(TPacket& packet,
377                         int flags = MSG_NOSIGNAL | MSG_WAITALL) throw (error);
378
379         /**
380          * Send a message on the socket to a specific name.
381          *
382          * This method behaves the same as send(const TPacket& packet, int
383          * flags) but sending to a specific name.
384          *
385          * @param packet Message struct to send.
386          * @param to Name to send the message to.
387          * @param flags Sending options.
388          *
389          * @see send()
390          *
391          * @todo make an enum for the flags (are they protocol-dependant?)
392          */
393         template< typename TPacket >
394         void send_struct(const TPacket& packet,
395                         const typename TSockTraits::sockaddr& to,
396                         int flags = MSG_NOSIGNAL) throw (error);
397
398         /**
399          * Receive a message on the socket from a specific name.
400          *
401          * This method behaves the same as recv(TPacket& packet, int flags) but
402          * receiving from a specific name.
403          *
404          * @param packet Message struct to receive to.
405          * @param from Name to receive the message from.
406          * @param flags Receiving options.
407          *
408          * @see recv()
409          *
410          * @todo make an enum for the flags (are they protocol-dependant?)
411          */
412         template< typename TPacket >
413         void recv_struct(TPacket& packet, typename TSockTraits::sockaddr& from,
414                         int flags = MSG_NOSIGNAL | MSG_WAITALL) throw (error);
415
416         /**
417          * Get the socket file descriptor.
418          *
419          * You should be careful when using the socket file descriptor, and you
420          * should not close it since it's closed by the destructor.
421          *
422          * @return Socket file descriptor.
423          */
424         int fd() const throw ();
425
426         /**
427          * Convert the socket to a file descriptor.
428          *
429          * This is really a shortcut to fd(), useful to pass a socket to a low
430          * level C function.
431          *
432          * @return Socket file descriptor.
433          */
434         operator int () const throw ();
435
436 private:
437
438         /// Hidden copy constructor (it has non-copiable behavior).
439         basic_socket(const basic_socket& s);
440
441         /// Hidden assign operator (it has non-assignable behavior).
442         basic_socket& operator=(const basic_socket& s);
443
444         /// Socket file descriptor.
445         int _fd;
446
447 };
448
449 /**
450  * Create a pair of connected sockets.
451  *
452  * @param type Type of socket.
453  * @param protocol Protocol number.
454  *
455  * @return The new connected pair of sockets.
456  *
457  * @see socketpair(2)
458  */
459 template < typename TSock >
460 inline
461 std::pair< TSock*, TSock* > pair(type type, int protocol = 0) throw (error);
462
463 } } // namespace posixx::socket
464
465
466
467
468 template < typename TSock >
469 std::pair< TSock*, TSock* > posixx::socket::pair(type type, int protocol)
470                 throw (posixx::error)
471 {
472         int fds[2];
473         if (::socketpair(TSock::traits::PF, type, protocol, fds) == -1)
474                 throw error("socketpair");
475         return std::make_pair(new TSock(fds[0]), new TSock(fds[1]));
476 }
477
478
479 template< typename TSockTraits >
480 inline
481 posixx::socket::basic_socket< TSockTraits >::basic_socket(int fd) throw ():
482                 _fd(fd)
483 {
484 }
485
486 template< typename TSockTraits >
487 inline
488 posixx::socket::basic_socket< TSockTraits >::basic_socket(type type,
489                 int protocol) throw (posixx::error)
490 {
491         _fd = ::socket(TSockTraits::PF, type, protocol);
492         if (_fd == -1)
493                 throw error("socket");
494 }
495
496 template< typename TSockTraits >
497 inline
498 void posixx::socket::basic_socket< TSockTraits >::bind(
499                 const typename TSockTraits::sockaddr& addr)
500                 throw (posixx::error)
501 {
502         if (::bind(_fd, reinterpret_cast< const ::sockaddr* >(&addr),
503                                 addr.length()) == -1)
504                 throw error("bind");
505 }
506
507 template< typename TSockTraits >
508 inline
509 void posixx::socket::basic_socket< TSockTraits >::connect(
510                 const typename TSockTraits::sockaddr& addr)
511                 throw (posixx::error)
512 {
513         if (::connect(_fd, reinterpret_cast< const ::sockaddr* >(&addr),
514                                 addr.length()) == -1)
515                 throw error("connect");
516 }
517
518 template< typename TSockTraits >
519 inline
520 typename TSockTraits::sockaddr posixx::socket::basic_socket< TSockTraits >::name()
521                 const throw (posixx::error)
522 {
523         typename TSockTraits::sockaddr addr;
524         socklen_t len = sizeof(typename TSockTraits::sockaddr);
525         // TODO assert len == sizeof(typename TSockTraits::sockaddr)
526         if (::getsockname(_fd, reinterpret_cast< ::sockaddr* >(&addr), &len) == -1)
527                 throw error("getsockname");
528         return addr;
529 }
530
531 template< typename TSockTraits >
532 inline
533 typename TSockTraits::sockaddr
534 posixx::socket::basic_socket< TSockTraits >::peer_name() const throw (posixx::error)
535 {
536         typename TSockTraits::sockaddr addr;
537         socklen_t len = sizeof(typename TSockTraits::sockaddr);
538         // TODO assert len == sizeof(typename TSockTraits::sockaddr)
539         if (::getpeername(_fd, reinterpret_cast< ::sockaddr* >(&addr), &len) == -1)
540                 throw error("getpeername");
541         return addr;
542 }
543
544 template< typename TSockTraits >
545 inline
546 ssize_t posixx::socket::basic_socket< TSockTraits >::send(const void* buf,
547                 size_t n, int flags) throw (posixx::error)
548 {
549         ssize_t s = ::send(_fd, buf, n, flags);
550         if (s == -1)
551                 throw error("send");
552         if (s == 0)
553                 throw error("send connection shutdown"); // XXX
554         return s;
555 }
556
557 template< typename TSockTraits >
558 inline
559 ssize_t posixx::socket::basic_socket< TSockTraits >::recv(void* buf, size_t n, int flags)
560                 throw (posixx::error)
561 {
562         ssize_t s = ::recv(_fd, buf, n, flags);
563         if (s == -1)
564                 throw error("recv");
565         if (s == 0)
566                 throw error("recv connection shutdown"); // XXX
567         return s;
568 }
569
570 template< typename TSockTraits >
571 inline
572 ssize_t posixx::socket::basic_socket< TSockTraits >::send(const void* buf,
573                 size_t n, const typename TSockTraits::sockaddr& to, int flags)
574                 throw (posixx::error)
575 {
576         ssize_t s = ::sendto(_fd, buf, n, flags,
577                         reinterpret_cast< const ::sockaddr* >(&to),
578                         to.length());
579         if (s == -1)
580                 throw error("sendto");
581         if (s == 0) {
582                 error e("sendto client shutdown"); // XXX
583                 e.no = 0;
584                 throw e;
585         }
586         return s;
587 }
588
589 template< typename TSockTraits >
590 inline
591 ssize_t posixx::socket::basic_socket< TSockTraits >::recv(void* buf, size_t n,
592                 typename TSockTraits::sockaddr& from, int flags)
593                 throw (posixx::error)
594 {
595         socklen_t len = sizeof(typename TSockTraits::sockaddr);
596         ssize_t s = ::recvfrom(_fd, buf, n, flags,
597                         reinterpret_cast< ::sockaddr* >(&from), &len);
598         if (s == -1)
599                 throw error("recvfrom");
600         if (s == 0) {
601                 error e("recvfrom client shutdown"); // XXX
602                 e.no = 0;
603                 throw e;
604         }
605         return s;
606 }
607
608 /*
609 template< typename TSockTraits >
610 inline
611 ssize_t posixx::socket::basic_socket< TSockTraits >::send(const msghdr* msg, int flags)
612 {
613         ssize_t s = ::sendmsg(_fd, msg, flags);
614         if (s == -1)
615                 throw error("sendmsg");
616         if (s == 0)
617                 throw error("send");
618         return s;
619 }
620
621 template< typename TSockTraits >
622 inline
623 ssize_t posixx::socket::basic_socket< TSockTraits >::recv(struct msghdr* msg, int flags)
624 {
625         ssize_t s = ::recvmsg(_fd, msg, flags);
626         if (s == -1)
627                 throw error("recvmsg");
628         if (s == 0)
629                 throw error("send");
630         return s;
631 }
632 */
633
634 template< typename TSockTraits >
635 template< typename TSockOpt >
636 inline
637 void posixx::socket::basic_socket< TSockTraits >::getsockopt(int level, int optname,
638                 TSockOpt& opt) const throw (posixx::error)
639 {
640         socklen_t len = sizeof(TSockOpt);
641         if (::getsockopt(_fd, level, optname, &opt, &len) == -1) // TODO assert len == sizeof(TSockOpt)
642                 throw error("getsockopt");
643 }
644
645 template< typename TSockTraits >
646 template< typename TSockOpt >
647 inline
648 void posixx::socket::basic_socket< TSockTraits >::setsockopt(int level, int optname,
649                 const TSockOpt& opt) throw (posixx::error)
650 {
651         if (::setsockopt(_fd, level, optname, &opt, sizeof(TSockOpt)) == -1)
652                 throw error("setsockopt");
653 }
654
655 template< typename TSockTraits >
656 template< typename TSockOpt >
657 inline
658 typename TSockOpt::type posixx::socket::basic_socket< TSockTraits >::opt() const
659                 throw (posixx::error)
660 {
661         static_assert(TSockOpt::read, "Option is not readable");
662         typename TSockOpt::type opt;
663         socklen_t len = sizeof(opt);
664         // TODO assert len == sizeof(TSockOpt)
665         if (::getsockopt(_fd, TSockOpt::level, TSockOpt::optname, &opt, &len) == -1)
666                 throw error("getsockopt");
667         return opt;
668 }
669
670 template< typename TSockTraits >
671 template< typename TSockOpt >
672 inline
673 void posixx::socket::basic_socket< TSockTraits >::opt(
674                 const typename TSockOpt::type& opt) throw (posixx::error)
675 {
676         static_assert(TSockOpt::write, "Option is not writable");
677         if (::setsockopt(_fd, TSockOpt::level, TSockOpt::optname, &opt,
678                                 sizeof(typename TSockOpt::type)) == -1)
679                 throw error("setsockopt");
680 }
681
682 template< typename TSockTraits >
683 inline
684 void posixx::socket::basic_socket< TSockTraits >::listen(int backlog) throw (posixx::error)
685 {
686         if (::listen(_fd, backlog) == -1)
687                 throw error("listen");
688 }
689
690 template< typename TSockTraits >
691 inline
692 posixx::socket::basic_socket< TSockTraits >* posixx::socket::basic_socket< TSockTraits >::accept()
693                 throw (posixx::error)
694 {
695         int fd = ::accept(_fd, 0, 0);
696         if (fd == -1)
697                 throw error("accept");
698         return new basic_socket(fd);
699 }
700
701 template< typename TSockTraits >
702 inline
703 posixx::socket::basic_socket< TSockTraits >*
704 posixx::socket::basic_socket< TSockTraits >::accept(typename TSockTraits::sockaddr& addr)
705                 throw (posixx::error)
706 {
707         socklen_t len = sizeof(typename TSockTraits::sockaddr);
708         // TODO assert len = sizeof(typename TSockTraits::sockaddr)
709         int fd = ::accept(_fd, reinterpret_cast< ::sockaddr* >(&addr), &len);
710         if (fd == -1)
711                 throw error("accept");
712         return new basic_socket(fd);
713 }
714
715 template< typename TSockTraits >
716 inline
717 void posixx::socket::basic_socket< TSockTraits >::shutdown(shutdown_mode how)
718                 throw (posixx::error)
719 {
720         if (::shutdown(_fd, how) == -1)
721                 throw error("shutdown");
722 }
723
724 template< typename TSockTraits >
725 inline
726 void posixx::socket::basic_socket< TSockTraits >::close() throw (posixx::error)
727 {
728         if (::close(_fd) == -1)
729                 throw error("close");
730         _fd = -1;
731 }
732
733 template< typename TSockTraits >
734 inline
735 posixx::socket::basic_socket< TSockTraits >::~basic_socket() throw ()
736 {
737         if (_fd != -1)
738                 close();
739 }
740
741 template< typename TSockTraits >
742 template< typename TPacket >
743 void posixx::socket::basic_socket< TSockTraits >::send_struct(
744                 const TPacket& packet, int flags) throw (posixx::error)
745 {
746         ssize_t s = 0;
747         while (static_cast< unsigned >(s) < sizeof(TPacket))
748         {
749                 try
750                 {
751                         s += send(&packet + s, sizeof(TPacket) - s, flags);
752                 }
753                 catch (const error& e)
754                 {
755                         if (e.no != EINTR && e.no != EAGAIN)
756                                 throw;
757                 }
758         }
759         if (static_cast< unsigned >(s) != sizeof(TPacket))
760                 throw error("send size not match");
761 }
762
763 template< typename TSockTraits >
764 template< typename TPacket >
765 inline
766 void posixx::socket::basic_socket< TSockTraits >::recv_struct(TPacket& packet, int flags)
767                 throw (posixx::error)
768 {
769         ssize_t s = 0;
770         while (static_cast< unsigned >(s) < sizeof(TPacket))
771         {
772                 try
773                 {
774                         s += recv(&packet + s, sizeof(TPacket) - s, flags);
775                 }
776                 catch (const error& e)
777                 {
778                         if (e.no != EINTR && e.no != EAGAIN && e.no != EWOULDBLOCK)
779                                 throw;
780                 }
781         }
782         if (static_cast< unsigned >(s) != sizeof(TPacket))
783                 throw error("recv size not match");
784 }
785
786 template< typename TSockTraits >
787 template< typename TPacket >
788 inline
789 void posixx::socket::basic_socket< TSockTraits >::send_struct(
790                 const TPacket& packet,
791                 const typename TSockTraits::sockaddr& to,
792                 int flags) throw (posixx::error)
793 {
794         ssize_t s = 0;
795         while (static_cast< unsigned >(s) < sizeof(TPacket))
796         {
797                 try
798                 {
799                         s += send(&packet + s, sizeof(TPacket) - s, to, flags);
800                 }
801                 catch (const error& e)
802                 {
803                         if (e.no != EINTR && e.no != EAGAIN)
804                                 throw;
805                 }
806         }
807         if (static_cast< unsigned >(s) != sizeof(TPacket))
808                 throw error("send size not match");
809 }
810
811 template< typename TSockTraits >
812 template< typename TPacket >
813 inline
814 void posixx::socket::basic_socket< TSockTraits >::recv_struct(TPacket& packet,
815                 typename TSockTraits::sockaddr& from, int flags)
816                 throw (posixx::error)
817 {
818         ssize_t s = 0;
819         while (static_cast< unsigned >(s) < sizeof(TPacket))
820         {
821                 try
822                 {
823                         s += recv(&packet + s, sizeof(TPacket) - s, from, flags);
824                 }
825                 catch (const error& e)
826                 {
827                         if (e.no != EINTR && e.no != EAGAIN && e.no != EWOULDBLOCK)
828                                 throw;
829                 }
830         }
831         if (static_cast< unsigned >(s) != sizeof(TPacket))
832                 throw error("recv size not match");
833 }
834
835 template< typename TSockTraits >
836 inline
837 int posixx::socket::basic_socket< TSockTraits >::fd() const throw ()
838 {
839         return _fd;
840 }
841
842 template< typename TSockTraits >
843 inline
844 posixx::socket::basic_socket< TSockTraits >::operator int () const throw ()
845 {
846         return _fd;
847 }
848
849 #if 0
850
851 template< typename TSockTraits >
852 template< typename TPacket >
853 inline
854 void send(const TPacket& packet) // TODO specialize with std::string
855 {
856 }
857
858 template< typename TSockTraits >
859 template< typename TPacket >
860 inline
861 void recv(TPacket& packet) // TODO specialize with std::string
862 {
863 }
864
865 template< typename TSockTraits >
866 inline
867 void recv(std::string& buf, size_t n)
868 {
869 }
870 #endif
871
872 #endif // _POSIXX_SOCKET_BASIC_SOCKET_HPP_