]> git.tdb.fi Git - libs/net.git/blob - source/datagramsocket.cpp
Hide platform details of Socket behind pimpl
[libs/net.git] / source / datagramsocket.cpp
1 #include <cerrno>
2 #include <msp/core/systemerror.h>
3 #include <msp/io/handle_private.h>
4 #include <msp/strings/format.h>
5 #include "datagramsocket.h"
6 #include "socket_private.h"
7
8 namespace Msp {
9 namespace Net {
10
11 DatagramSocket::DatagramSocket(Family f, int p):
12         Socket(f, SOCK_DGRAM, p)
13 {
14 #ifdef WIN32
15         WSAEventSelect(priv->handle, *priv->event, FD_READ|FD_CLOSE);
16 #endif
17         set_events(IO::P_INPUT);
18 }
19
20 int DatagramSocket::connect(const SockAddr &addr)
21 {
22         sockaddr_storage sa;
23         socklen_t size = addr.fill_sockaddr(sa);
24
25         int err = ::connect(priv->handle, reinterpret_cast<sockaddr *>(&sa), size);
26         if(err==-1)
27         {
28 #ifdef WIN32
29                 throw system_error("connect", WSAGetLastError());
30 #else
31                 throw system_error("connect");
32 #endif
33         }
34
35         delete peer_addr;
36         peer_addr = addr.copy();
37
38         delete local_addr;
39         size = sizeof(sockaddr_storage);
40         getsockname(priv->handle, reinterpret_cast<sockaddr *>(&sa), &size);
41         local_addr = SockAddr::create(sa);
42
43         connected = true;
44
45         return (err==0)?0:1;
46 }
47
48 unsigned DatagramSocket::sendto(const char *buf, unsigned size, const SockAddr &addr_)
49 {
50         if(size==0)
51                 return 0;
52
53         sockaddr_storage addr;
54         socklen_t addr_len = addr_.fill_sockaddr(addr);
55
56         int ret = ::sendto(priv->handle, buf, size, 0, reinterpret_cast<sockaddr *>(&addr), addr_len);
57         if(ret<0)
58         {
59                 if(errno==EAGAIN)
60                         return 0;
61                 else
62                 {
63 #ifdef WIN32
64                         throw system_error("sendto", WSAGetLastError());
65 #else
66                         throw system_error("sendto");
67 #endif
68                 }
69         }
70
71         return ret;
72 }
73
74 unsigned DatagramSocket::recvfrom(char *buf, unsigned size, SockAddr *&addr_)
75 {
76         if(size==0)
77                 return 0;
78
79         sockaddr_storage addr;
80         socklen_t addr_len = sizeof(sockaddr_storage);
81
82         int ret = ::recvfrom(priv->handle, buf, size, 0, reinterpret_cast<sockaddr *>(&addr), &addr_len);
83         if(ret<0)
84         {
85                 if(errno==EAGAIN)
86                         return 0;
87                 else
88                 {
89 #ifdef WIN32
90                         throw system_error("recvfrom", WSAGetLastError());
91 #else
92                         throw system_error("recvfrom");
93 #endif
94                 }
95         }
96
97         addr_ = SockAddr::create(addr);
98
99         return ret;
100 }
101
102 } // namespace Net
103 } // namespace Msp