sources/network/udp.cpp

changeset 5
146825d63b9a
equal deleted inserted replaced
4:ec5387e121fa 5:146825d63b9a
1 #include <sys/socket.h>
2 #include <sys/types.h>
3 #include <sys/time.h>
4 #include <netinet/in.h>
5 #include <string.h>
6 #include <fcntl.h>
7 #include "udp.h"
8
9 // -----------------------------------------------------------------------------
10 //
11 UDPSocket::UDPSocket() :
12 m_socket (socket (AF_INET, SOCK_DGRAM, 0)) {}
13
14 // -----------------------------------------------------------------------------
15 //
16 UDPSocket::~UDPSocket() {}
17
18 // -------------------------------------------------------------------------------------------------
19 //
20 METHOD
21 UDPSocket::set_blocking (bool a) -> bool
22 {
23 int flags = fcntl (m_socket, F_GETFL, 0);
24 int newflags = (a ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK));
25
26 if (flags < 0 || fcntl (m_socket, F_SETFL, newflags) != 0)
27 {
28 m_error = "Unable to set socket as non-blocking";
29 return false;
30 }
31
32 return true;
33 }
34
35 // -------------------------------------------------------------------------------------------------
36 //
37 METHOD
38 UDPSocket::bind (unsigned short port) -> bool
39 {
40 struct sockaddr_in svaddr;
41 memset (&svaddr, 0, sizeof svaddr);
42 svaddr.sin_family = AF_INET;
43 svaddr.sin_port = htons (port);
44 svaddr.sin_addr.s_addr = htonl (INADDR_ANY);
45
46 if (::bind (m_socket, reinterpret_cast<struct sockaddr*> (&svaddr), sizeof svaddr) == -1)
47 {
48 m_error = String ("Couldn't bind to port ") + String::from_number (port);
49 return false;
50 }
51
52 return true;
53 }
54
55 // -------------------------------------------------------------------------------------------------
56 //
57 METHOD
58 UDPSocket::read (Datagram& datagram) -> bool
59 {
60 sockaddr_in claddr;
61 socklen_t socklen = sizeof claddr;
62 static unsigned char packet[MAX_DATAGRAM_LENGTH];
63 int length = ::recvfrom (m_socket, packet, sizeof packet, 0,
64 reinterpret_cast<struct sockaddr*> (&claddr), &socklen);
65
66 if (length == -1)
67 {
68 // We got an error, though EWOULDBLOCK is silent as it means no packets recieved.
69 if (errno != EWOULDBLOCK)
70 m_error.sprintf ("recvfrom error: %s", strerror (errno));;
71
72 return false;
73 }
74
75 datagram.from.host = ntohl (claddr.sin_addr.s_addr);
76 datagram.from.port = ntohs (claddr.sin_port);
77 datagram.data = Bytestream (packet, length);
78 return true;
79 }
80
81 // -------------------------------------------------------------------------------------------------
82 //
83 METHOD
84 UDPSocket::send (const Bytestream& data, const IPAddress& addr) -> bool
85 {
86 struct sockaddr_in claddr = addr.to_sockaddr_in();
87
88 int res = ::sendto (m_socket, data.data(), data.written_length(), 0,
89 reinterpret_cast<struct sockaddr*> (&claddr), sizeof claddr);
90
91 if (res == -1)
92 {
93 m_error = String ("Unable to launch packet: ") + strerror (errno);
94 return false;
95 }
96
97 return true;
98 }

mercurial