]> git.tdb.fi Git - libs/net.git/blob - source/net/datagramsocket.cpp
Implement an asynchronous name resolver class
[libs/net.git] / source / net / datagramsocket.cpp
1 #ifdef WIN32
2 #include <winsock2.h>
3 #endif
4 #include <cerrno>
5 #include <msp/core/systemerror.h>
6 #include <msp/io/handle_private.h>
7 #include <msp/strings/format.h>
8 #include "datagramsocket.h"
9 #include "sockaddr_private.h"
10 #include "socket_private.h"
11
12 namespace Msp {
13 namespace Net {
14
15 DatagramSocket::DatagramSocket(Family f, int p):
16         ClientSocket(f, SOCK_DGRAM, p)
17 {
18 #ifdef WIN32
19         WSAEventSelect(priv->handle, *priv->event, FD_READ|FD_CLOSE);
20 #endif
21         set_events(IO::P_INPUT);
22 }
23
24 bool DatagramSocket::connect(const SockAddr &addr)
25 {
26         SockAddr::SysAddr sa = addr.to_sys();
27
28         int err = ::connect(priv->handle, reinterpret_cast<sockaddr *>(&sa.addr), sa.size);
29         if(err==-1)
30         {
31 #ifdef WIN32
32                 throw system_error("connect", WSAGetLastError());
33 #else
34                 throw system_error("connect");
35 #endif
36         }
37
38         delete peer_addr;
39         peer_addr = addr.copy();
40
41         delete local_addr;
42         SockAddr::SysAddr lsa;
43         getsockname(priv->handle, reinterpret_cast<sockaddr *>(&lsa.addr), &lsa.size);
44         local_addr = SockAddr::new_from_sys(lsa);
45
46         connected = true;
47
48         return true;
49 }
50
51 unsigned DatagramSocket::sendto(const char *buf, unsigned size, const SockAddr &addr)
52 {
53         if(size==0)
54                 return 0;
55
56         SockAddr::SysAddr sa = addr.to_sys();
57
58         int ret = ::sendto(priv->handle, buf, size, 0, reinterpret_cast<sockaddr *>(&sa.addr), sa.size);
59         if(ret<0)
60         {
61                 if(errno==EAGAIN)
62                         return 0;
63                 else
64                 {
65 #ifdef WIN32
66                         throw system_error("sendto", WSAGetLastError());
67 #else
68                         throw system_error("sendto");
69 #endif
70                 }
71         }
72
73         return ret;
74 }
75
76 unsigned DatagramSocket::recvfrom(char *buf, unsigned size, SockAddr *&from_addr)
77 {
78         if(size==0)
79                 return 0;
80
81         SockAddr::SysAddr sa;
82         int ret = ::recvfrom(priv->handle, buf, size, 0, reinterpret_cast<sockaddr *>(&sa.addr), &sa.size);
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         from_addr = SockAddr::new_from_sys(sa);
98
99         return ret;
100 }
101
102 } // namespace Net
103 } // namespace Msp