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