SocketName Win32Socket::get_remote_name() const { sockaddr_in addr; memset(&addr, 0, sizeof(sockaddr_in)); int size = sizeof(sockaddr_in); int result = getpeername(handle, (sockaddr *) &addr, &size); throw_if_failed(result); SocketName name; name.from_sockaddr(AF_INET, (sockaddr *) &addr, sizeof(sockaddr_in)); return name; }
SocketName TCPConnectionImpl::remote_name() { sockaddr_in addr; memset(&addr, 0, sizeof(sockaddr_in)); int size = sizeof(sockaddr_in); int result = getpeername(handle, (sockaddr *)&addr, &size); if (result == SOCKET_ERROR) throw Exception("Error retrieving remote socket name"); SocketName name; name.from_sockaddr(AF_INET, (sockaddr *)&addr, sizeof(sockaddr_in)); return name; }
SocketName TCPConnectionImpl::local_name() { sockaddr_in addr; memset(&addr, 0, sizeof(sockaddr_in)); socklen_t size = sizeof(sockaddr_in); int result = getsockname(handle, (sockaddr *)&addr, &size); if (result == -1) throw Exception("Error retrieving local socket name"); SocketName name; name.from_sockaddr(AF_INET, (sockaddr *)&addr, sizeof(sockaddr_in)); return name; }
void UDPSocketImpl::send(const void *data, int size, const SocketName &endpoint) { sockaddr_in addr; endpoint.to_sockaddr(AF_INET, (sockaddr *)&addr, sizeof(sockaddr_in)); sendto(handle, static_cast<const char*>(data), size, 0, (const sockaddr *)&addr, sizeof(sockaddr_in)); }
TCPConnectionImpl::TCPConnectionImpl(const SocketName &endpoint) { int receive_buffer_size = 600 * 1024; int send_buffer_size = 600 * 1024; //int result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, (const char *) &receive_buffer_size, sizeof(int)); int result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, (const char *)&send_buffer_size, sizeof(int)); sockaddr_in addr; endpoint.to_sockaddr(AF_INET, (sockaddr *)&addr, sizeof(sockaddr_in)); result = ::connect(handle, (const sockaddr *)&addr, sizeof(sockaddr_in)); if (result == SOCKET_ERROR) throw Exception("Connect to server failed"); int value = 1; result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, (const char *)&value, sizeof(int)); result = WSAEventSelect(handle, wait_handle, FD_READ | FD_WRITE | FD_CLOSE); if (result == SOCKET_ERROR) throw Exception("WSAEventSelect failed"); //int receive_buffer_size = 0; //int send_buffer_size = 0; //int len = sizeof(int); //getsockopt(handle, SOL_SOCKET, SO_RCVBUF, (char *) &receive_buffer_size, &len); //getsockopt(handle, SOL_SOCKET, SO_SNDBUF, (char *) &send_buffer_size, &len); }
int UDPSocketImpl::read(void *data, int size, SocketName &endpoint) { sockaddr_in addr; int addr_len = sizeof(sockaddr_in); int result = recvfrom(handle, static_cast<char*>(data), size, 0, (sockaddr *)&addr, &addr_len); if (result == SOCKET_ERROR) { int last_error = WSAGetLastError(); // To do: maybe return different return values for sending errors if (last_error == WSAEWOULDBLOCK || last_error == WSAEMSGSIZE || last_error == WSAECONNRESET || last_error == WSAENETRESET) { endpoint = SocketName(); return -1; } else { throw Exception("Error reading from udp socket"); } } endpoint = SocketName(); endpoint.from_sockaddr(AF_INET, (sockaddr *)&addr, addr_len); return result; }
TCPConnectionImpl::TCPConnectionImpl(const SocketName &endpoint) { //int receive_buffer_size = 600*1024; int send_buffer_size = 600*1024; //int result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, (const char *) &receive_buffer_size, sizeof(int)); int result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, (const char *) &send_buffer_size, sizeof(int)); sockaddr_in addr; endpoint.to_sockaddr(AF_INET, (sockaddr *) &addr, sizeof(sockaddr_in)); result = ::connect(handle, (const sockaddr *) &addr, sizeof(sockaddr_in)); if (result == -1) throw Exception("Connect to server failed"); int value = 1; result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, (const char *) &value, sizeof(int)); //int receive_buffer_size = 0; //int send_buffer_size = 0; //int len = sizeof(int); //getsockopt(handle, SOL_SOCKET, SO_RCVBUF, (char *) &receive_buffer_size, &len); //getsockopt(handle, SOL_SOCKET, SO_SNDBUF, (char *) &send_buffer_size, &len); int nonblocking = 1; ioctl(handle, FIONBIO, &nonblocking); }
void UDPSocketImpl::bind(const SocketName &endpoint) { sockaddr_in addr; endpoint.to_sockaddr(AF_INET, (sockaddr *)&addr, sizeof(sockaddr_in)); int result = ::bind(handle, (const sockaddr *)&addr, sizeof(sockaddr_in)); if (result == SOCKET_ERROR) throw Exception("Could not bind socket to end point"); }
int Win32Socket::peek_from(void *data, int size, SocketName &out_socketname) { sockaddr_in new_addr; memset(&new_addr, 0, sizeof(sockaddr_in)); int addr_size = sizeof(sockaddr_in); int result = ::recvfrom(handle, (char *) data, size, MSG_PEEK, (sockaddr *) &new_addr, &addr_size); throw_if_failed(result); out_socketname.from_sockaddr(AF_INET, (sockaddr *) &new_addr, size); reset_receive(); return result; }
SOCKET Win32Socket::accept(SocketName &out_socketname) { sockaddr_in new_addr; memset(&new_addr, 0, sizeof(sockaddr_in)); int size = sizeof(sockaddr_in); SOCKET accepted_socket = ::accept(handle, (sockaddr *) &new_addr, &size); throw_if_invalid(accepted_socket); out_socketname.from_sockaddr(AF_INET, (sockaddr *) &new_addr, size); reset_receive(); return accepted_socket; }
void Win32Socket::connect(const SocketName &socketname) { sockaddr_in addr; socketname.to_sockaddr(AF_INET, (sockaddr *) &addr, sizeof(sockaddr_in)); int result = ::connect(handle, (const sockaddr *) &addr, sizeof(sockaddr_in)); if (result == SOCKET_ERROR) { int errorcode = WSAGetLastError(); if ( ! ( (errorcode == WSAEWOULDBLOCK) || (errorcode == WSAEINPROGRESS) ) ) throw Exception(error_to_string(errorcode)); } }
void Win32Socket::bind(const SocketName &socketname, bool reuse_address) { if (reuse_address) { int value = 1; int result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, (const char *) &value, sizeof(int)); throw_if_failed(result); } sockaddr_in addr; socketname.to_sockaddr(AF_INET, (sockaddr *) &addr, sizeof(sockaddr_in)); int result = ::bind(handle, (const sockaddr *) &addr, sizeof(sockaddr_in)); throw_if_failed(result); }
void UDPSocketImpl::send(const void *data, int size, const SocketName &endpoint) { sockaddr_in addr; endpoint.to_sockaddr(AF_INET, (sockaddr *)&addr, sizeof(sockaddr_in)); int result = sendto(handle, static_cast<const char*>(data), size, 0, (const sockaddr *)&addr, sizeof(sockaddr_in)); if (result == SOCKET_ERROR) { int last_error = WSAGetLastError(); if (last_error != WSAENOBUFS) { throw Exception("Error writing to udp socket"); } } }
TCPConnection TCPListen::accept(SocketName &out_end_point) { sockaddr_in peer_address = { 0 }; socklen_t peer_address_length = sizeof(sockaddr_in); int result = ::accept(impl->handle, reinterpret_cast<sockaddr*>(&peer_address), &peer_address_length); if (result == -1) { if (errno == EWOULDBLOCK) return TCPConnection(); else throw Exception("Error accepting from socket"); } out_end_point.from_sockaddr(AF_INET, reinterpret_cast<sockaddr*>(&peer_address), peer_address_length); return TCPConnection(std::make_shared<TCPSocket>(result)); }
TCPConnection TCPListen::accept(SocketName &out_end_point) { sockaddr_in peer_address = { 0 }; int peer_address_length = sizeof(sockaddr_in); SOCKET result = ::accept(impl->handle, reinterpret_cast<sockaddr*>(&peer_address), &peer_address_length); if (result == INVALID_SOCKET) { if (WSAGetLastError() == WSAEWOULDBLOCK) return TCPConnection(); else throw Exception("Error accepting from socket"); } out_end_point = SocketName(); out_end_point.from_sockaddr(AF_INET, reinterpret_cast<sockaddr*>(&peer_address), peer_address_length); return TCPConnection(std::make_shared<TCPSocket>(result)); }
TCPListen::TCPListen(const SocketName &endpoint, int backlog, bool reuse_address) : impl(new TCPSocket()) { if (reuse_address) { int value = 1; int result = setsockopt(impl->handle, SOL_SOCKET, SO_REUSEADDR, (const char *)&value, sizeof(int)); if (result == SOCKET_ERROR) throw Exception("Could not set reuse address socket option"); } int receive_buffer_size = 600 * 1024; int send_buffer_size = 600 * 1024; //int result = setsockopt(impl->handle, SOL_SOCKET, SO_RCVBUF, (const char *) &receive_buffer_size, sizeof(int)); //if (result == SOCKET_ERROR) // throw Exception("Could not set socket receive buffer size"); int result = setsockopt(impl->handle, SOL_SOCKET, SO_SNDBUF, (const char *)&send_buffer_size, sizeof(int)); if (result == SOCKET_ERROR) throw Exception("Could not set socket send buffer size"); int value = 1; result = setsockopt(impl->handle, IPPROTO_TCP, TCP_NODELAY, (const char *)&value, sizeof(int)); sockaddr_in addr; endpoint.to_sockaddr(AF_INET, (sockaddr *)&addr, sizeof(sockaddr_in)); result = ::bind(impl->handle, (const sockaddr *)&addr, sizeof(sockaddr_in)); if (result == SOCKET_ERROR) throw Exception("Could not bind socket to end point"); result = ::listen(impl->handle, backlog); if (result == SOCKET_ERROR) throw Exception("Unable to set socket into listen state"); result = WSAEventSelect(impl->handle, impl->wait_handle, FD_ACCEPT); if (result == SOCKET_ERROR) throw Exception("WSAEventSelect failed"); }
int UDPSocketImpl::read(void *data, int size, SocketName &endpoint) { sockaddr_in addr; socklen_t addr_len = sizeof(sockaddr_in); int result = recvfrom(handle, static_cast<char*>(data), size, 0, (sockaddr *)&addr, &addr_len); if (result == -1) { if (errno == EWOULDBLOCK || errno == EMSGSIZE || errno == ECONNRESET || errno == ENETRESET) { endpoint = SocketName(); return -1; } else { throw Exception("Error reading from udp socket"); } } endpoint.from_sockaddr(AF_INET, (sockaddr *)&addr, addr_len); return result; }
int Win32Socket::send_to(const void *data, int size, const SocketName &socketname) { sockaddr_in addr; socketname.to_sockaddr(AF_INET, (sockaddr *) &addr, sizeof(sockaddr_in)); int result = ::sendto(handle, (const char *) data, size, 0, (const sockaddr *) &addr, sizeof(sockaddr_in)); if (result == SOCKET_ERROR) { int errorcode = WSAGetLastError(); if (errorcode == WSAEWOULDBLOCK) { reset_send(); return 0; } else { throw Exception(error_to_string(errorcode)); } } else { return result; } }