sources/network/udpsocket.cpp

branch
protocol5
changeset 195
be953e1621d9
parent 171
d0fba0d7ad03
parent 191
2e6cbacafdc7
equal deleted inserted replaced
176:060a13878ca0 195:be953e1621d9
1 /* 1 /*
2 Copyright 2014 - 2016 Teemu Piippo 2 Copyright 2014 - 2021 Teemu Piippo
3 All rights reserved. 3 All rights reserved.
4 4
5 Redistribution and use in source and binary forms, with or without 5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions 6 modification, are permitted provided that the following conditions
7 are met: 7 are met:
45 #include <fcntl.h> 45 #include <fcntl.h>
46 #include "../huffman/huffman.h" 46 #include "../huffman/huffman.h"
47 47
48 BEGIN_ZFC_NAMESPACE 48 BEGIN_ZFC_NAMESPACE
49 49
50 char UDPSocket::HuffmanBuffer[131072]; 50 static char HuffmanBuffer[131072];
51 51
52 // ----------------------------------------------------------------------------- 52 net::UDPSocket::UDPSocket() :
53 // 53 file_descriptor{::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)} {}
54 UDPSocket::UDPSocket() :
55 m_socket (socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) {}
56 54
57 // ----------------------------------------------------------------------------- 55 net::UDPSocket::~UDPSocket()
58 //
59 UDPSocket::~UDPSocket()
60 { 56 {
61 #ifdef _WIN32 57 #ifdef _WIN32
62 closesocket (m_socket); 58 ::closesocket(m_socket);
63 #else 59 #else
64 close (m_socket); 60 ::close(this->file_descriptor);
65 #endif 61 #endif
66 } 62 }
67 63
68 // ------------------------------------------------------------------------------------------------- 64 bool net::UDPSocket::set_blocking(bool a, std::ostream& errors)
69 //
70 bool UDPSocket::set_blocking (bool a)
71 { 65 {
72 #ifndef _WIN32 66 #ifndef _WIN32
73 int flags = fcntl (m_socket, F_GETFL, 0); 67 int flags = ::fcntl(this->file_descriptor, F_GETFL, 0);
74 int newflags = a ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); 68 int newflags = a ?(flags & ~O_NONBLOCK) :(flags | O_NONBLOCK);
75 69 if (flags < 0 || ::fcntl(this->file_descriptor, F_SETFL, newflags) != 0)
76 if (flags < 0 || fcntl (m_socket, F_SETFL, newflags) != 0)
77 { 70 {
78 m_error = "Unable to set socket as non-blocking"; 71 errors << "Unable to set the UDP socket as non-blocking";
79 return false; 72 return false;
80 } 73 }
81 74 else
82 return true; 75 {
76 return true;
77 }
83 #else 78 #else
84 unsigned long mode = a ? 0 : 1; 79 unsigned long mode = a ? 0 : 1;
85 80
86 if (ioctlsocket (m_socket, FIONBIO, &mode) != 0) 81 if (::ioctlsocket(m_socket, FIONBIO, &mode) != 0)
87 { 82 {
88 m_error = strerror (errno); 83 errors << strerror(errno);
89 return false; 84 return false;
90 } 85 }
91 86 else
92 return true; 87 {
88 return true;
89 }
93 #endif 90 #endif
94 } 91 }
95 92
96 // ------------------------------------------------------------------------------------------------- 93 bool net::UDPSocket::bind(const net::port_t port, std::ostream& errors)
97 //
98 bool UDPSocket::bind (unsigned short port)
99 { 94 {
100 sockaddr_in svaddr; 95 sockaddr_in svaddr;
101 memset (&svaddr, 0, sizeof svaddr); 96 std::memset(&svaddr, 0, sizeof svaddr);
102 svaddr.sin_family = AF_INET; 97 svaddr.sin_family = AF_INET;
103 svaddr.sin_port = htons (port); 98 svaddr.sin_port = htons(port);
104 svaddr.sin_addr.s_addr = htonl (INADDR_ANY); 99 svaddr.sin_addr.s_addr = htonl(INADDR_ANY);
105 100 if (::bind(this->file_descriptor, reinterpret_cast<sockaddr*>(&svaddr), sizeof svaddr) == -1)
106 if (::bind (m_socket, reinterpret_cast<sockaddr*> (&svaddr), sizeof svaddr) == -1)
107 { 101 {
108 m_error = String ("Couldn't bind to port ") + String::fromNumber (port); 102 errors << "Couldn't bind to port "s + std::to_string(port);
109 return false; 103 return false;
110 } 104 }
105 else
106 {
107 return true;
108 }
109 }
111 110
111 bool net::UDPSocket::read(Datagram& datagram, std::ostream& errors)
112 {
113 sockaddr_in claddr;
114 socklen_t socklen = sizeof claddr;
115 const int length = ::recvfrom(
116 this->file_descriptor,
117 zfc::HuffmanBuffer,
118 sizeof zfc::HuffmanBuffer,
119 0,
120 reinterpret_cast<sockaddr*>(&claddr),
121 &socklen
122 );
123 if (length == -1)
124 {
125 if (errno != EWOULDBLOCK)
126 {
127 errors << std::string("recvfrom error: ") + std::strerror(errno);
128 }
129 return false;
130 }
131 unsigned char decodedPacket[MAX_DATAGRAM_LENGTH];
132 int decodedLength = sizeof decodedPacket;
133 ::HUFFMAN_Decode(reinterpret_cast<unsigned char*>(HuffmanBuffer),
134 decodedPacket, length, &decodedLength);
135 datagram.address.host = ntohl(claddr.sin_addr.s_addr);
136 datagram.address.port = ntohs(claddr.sin_port);
137 datagram.message = std::vector<unsigned char>{&decodedPacket[0], &decodedPacket[decodedLength]};
112 return true; 138 return true;
113 } 139 }
114 140
115 // ------------------------------------------------------------------------------------------------- 141 bool net::UDPSocket::send(const net::ip_address& address, const std::vector<unsigned char>& data, std::ostream& errors)
116 //
117 bool UDPSocket::read (Datagram& datagram)
118 { 142 {
119 sockaddr_in claddr; 143 int encodedlength = sizeof HuffmanBuffer;
120 socklen_t socklen = sizeof claddr; 144 ::HUFFMAN_Encode(data.data(), reinterpret_cast<unsigned char*>(HuffmanBuffer), data.size(), &encodedlength);
121 int length = ::recvfrom (m_socket, HuffmanBuffer, sizeof HuffmanBuffer, 0, 145 sockaddr_in claddr = net::ip_address_to_sockaddr_in(address);
122 reinterpret_cast<sockaddr*> (&claddr), &socklen); 146 const int send_result = ::sendto(
123 147 this->file_descriptor,
124 if (length == -1) 148 HuffmanBuffer,
149 encodedlength,
150 0,
151 reinterpret_cast<sockaddr*>(&claddr),
152 sizeof claddr
153 );
154 if (send_result == -1)
125 { 155 {
126 if (errno != EWOULDBLOCK) 156 errors << "Unable to launch packet: "s + std::strerror(errno);
127 m_error = String ("recvfrom error: ") + strerror (errno);
128
129 return false; 157 return false;
130 } 158 }
131 159 else
132 unsigned char decodedPacket[MAX_DATAGRAM_LENGTH];
133 int decodedLength = sizeof decodedPacket;
134 HUFFMAN_Decode (reinterpret_cast<unsigned char*> (HuffmanBuffer),
135 decodedPacket, length, &decodedLength);
136 datagram.address.host = ntohl (claddr.sin_addr.s_addr);
137 datagram.address.port = ntohs (claddr.sin_port);
138 datagram.message = ByteArray(decodedPacket, decodedLength);
139 return true;
140 }
141
142 // -------------------------------------------------------------------------------------------------
143 //
144 bool UDPSocket::send (const IPAddress& address, const ByteArray& data)
145 {
146 int encodedlength = sizeof HuffmanBuffer;
147 HUFFMAN_Encode (data.data(), reinterpret_cast<unsigned char*> (HuffmanBuffer), data.size(), &encodedlength);
148 sockaddr_in claddr = address.to_sockaddr_in();
149 int res = ::sendto (m_socket, HuffmanBuffer, encodedlength, 0,
150 reinterpret_cast<sockaddr*> (&claddr), sizeof claddr);
151
152 if (res == -1)
153 { 160 {
154 m_error = String ("Unable to launch packet: ") + strerror (errno); 161 return true;
155 return false;
156 } 162 }
157
158 return true;
159 } 163 }
160 164
161 END_ZFC_NAMESPACE 165 END_ZFC_NAMESPACE

mercurial