15 #include "visiontransfer/networking.h"
16 #include "visiontransfer/exceptions.h"
21 using namespace visiontransfer;
22 using namespace visiontransfer::internal;
24 namespace visiontransfer {
29 error_int_type Networking::getErrno() {
30 return WSAGetLastError();
33 std::string Networking::getErrorString(error_int_type error) {
35 if(FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
36 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
37 nullptr, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
38 (LPSTR)&str, 0,
nullptr) == 0 || str ==
nullptr) {
39 return "Unknown error";
42 snprintf(buffer,
sizeof(buffer),
"%s (%lu)", str, error);
44 return std::string(buffer);
48 error_int_type Networking::getErrno() {
51 std::string Networking::getErrorString(error_int_type error) {
52 return std::string(strerror(error));
56 std::string Networking::getLastErrorString() {
57 return getErrorString(getErrno());
60 void Networking::initNetworking() {
64 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
70 addrinfo* Networking::resolveAddress(
const char* address,
const char* service) {
72 memset(&hints, 0,
sizeof(hints));
73 hints.ai_family = AF_INET;
74 hints.ai_socktype = SOCK_STREAM;
76 hints.ai_protocol = 0;
78 addrinfo* addressInfo =
nullptr;
80 if(getaddrinfo(address, service, &hints, &addressInfo) != 0 || addressInfo ==
nullptr) {
85 if(addressInfo->ai_addrlen !=
sizeof(sockaddr_in)) {
92 SOCKET Networking::connectTcpSocket(
const addrinfo* address) {
93 SOCKET sock = ::socket(address->ai_family, address->ai_socktype,
94 address->ai_protocol);
95 if(sock == INVALID_SOCKET) {
100 if(connect(sock, address->ai_addr,
static_cast<int>(address->ai_addrlen)) < 0) {
101 TransferException ex(
"Error connection to destination address: " + getLastErrorString());
108 void Networking::setSocketTimeout(SOCKET socket,
int timeoutMillisec) {
110 unsigned int timeout = timeoutMillisec;
112 struct timeval timeout;
113 timeout.tv_sec = timeoutMillisec/1000;
114 timeout.tv_usec = timeoutMillisec*1000;
117 setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO,
reinterpret_cast<char*
>(&timeout),
sizeof(timeout));
118 setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO,
reinterpret_cast<char*
>(&timeout),
sizeof(timeout));
121 void Networking::closeSocket(SOCKET& socket) {
122 setSocketBlocking(socket,
false);
123 shutdown(socket, SHUT_WR);
127 for(
int i=0; i<3; i++) {
128 int received = recv(socket, buffer,
sizeof(buffer), 0);
135 socket = INVALID_SOCKET;
138 void Networking::setSocketBlocking(SOCKET socket,
bool blocking) {
140 unsigned long on = (blocking ? 0 : 1);
141 ioctlsocket(socket, FIONBIO, &on);
143 int flags = fcntl(socket, F_GETFL, 0);
146 flags &= ~O_NONBLOCK;
150 fcntl(socket, F_SETFL, flags);
155 void Networking::enableReuseAddress(SOCKET socket,
bool reuse) {
156 int enable = reuse ? 1 : 0;
157 setsockopt(socket, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<char*
>(&enable),
sizeof(
int));
160 void Networking::bindSocket(SOCKET socket,
const addrinfo* addressInfo) {
161 if (::bind(socket, addressInfo->ai_addr,
static_cast<int>(addressInfo->ai_addrlen)) < 0) {
167 SOCKET Networking::acceptConnection(SOCKET socket, sockaddr_in& remoteAddress) {
168 socklen_t clientAddressLength =
sizeof(sockaddr_in);
170 SOCKET newSocket = accept(socket,
reinterpret_cast<sockaddr *
>(&remoteAddress),
171 &clientAddressLength);
173 if(clientAddressLength !=
sizeof(sockaddr_in)) {
177 if(newSocket == INVALID_SOCKET) {
178 if(getErrno() == EWOULDBLOCK || getErrno() == ETIMEDOUT) {
180 return INVALID_SOCKET;