mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-28 02:11:43 +00:00
Add win32 tcpsockets implementation.
This commit is contained in:
@@ -12,6 +12,9 @@ include_directories(include src)
|
||||
add_library(ntcore SHARED ${SRC_FILES})
|
||||
set_target_properties(ntcore PROPERTIES VERSION 1.0.0 SOVERSION 1)
|
||||
#target_link_libraries(ntcore)
|
||||
if (WIN32)
|
||||
target_link_libraries(ntcore ws2_32)
|
||||
endif()
|
||||
INSTALL(TARGETS ntcore
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
|
||||
@@ -25,10 +25,15 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#ifdef _WIN32
|
||||
#include <WinSock2.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "llvm/SmallString.h"
|
||||
#include "Log.h"
|
||||
|
||||
TCPAcceptor::TCPAcceptor(int port, const char* address)
|
||||
@@ -36,13 +41,26 @@ TCPAcceptor::TCPAcceptor(int port, const char* address)
|
||||
m_port(port),
|
||||
m_address(address),
|
||||
m_listening(false),
|
||||
m_shutdown(false) {}
|
||||
m_shutdown(false) {
|
||||
#ifdef _WIN32
|
||||
WSAData wsaData;
|
||||
WORD wVersionRequested = MAKEWORD(2, 2);
|
||||
WSAStartup(wVersionRequested, &wsaData);
|
||||
#endif
|
||||
}
|
||||
|
||||
TCPAcceptor::~TCPAcceptor() {
|
||||
if (m_lsd > 0) {
|
||||
shutdown();
|
||||
#ifdef _WIN32
|
||||
closesocket(m_lsd);
|
||||
#else
|
||||
close(m_lsd);
|
||||
#endif
|
||||
}
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
int TCPAcceptor::start() {
|
||||
@@ -53,15 +71,22 @@ int TCPAcceptor::start() {
|
||||
|
||||
std::memset(&address, 0, sizeof(address));
|
||||
address.sin_family = PF_INET;
|
||||
address.sin_port = htons(m_port);
|
||||
if (m_address.size() > 0) {
|
||||
#ifdef _WIN32
|
||||
llvm::SmallString<128> addr_copy(m_address);
|
||||
addr_copy.append('\0');
|
||||
int size = sizeof(address);
|
||||
WSAStringToAddress(addr_copy.data(), PF_INET, nullptr, (struct sockaddr*)&address, &size);
|
||||
#else
|
||||
inet_pton(PF_INET, m_address.c_str(), &(address.sin_addr));
|
||||
#endif
|
||||
} else {
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
address.sin_port = htons(m_port);
|
||||
|
||||
int optval = 1;
|
||||
setsockopt(m_lsd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
|
||||
setsockopt(m_lsd, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof optval);
|
||||
|
||||
int result = bind(m_lsd, (struct sockaddr*)&address, sizeof(address));
|
||||
if (result != 0) {
|
||||
@@ -80,14 +105,22 @@ int TCPAcceptor::start() {
|
||||
|
||||
void TCPAcceptor::shutdown() {
|
||||
m_shutdown = true;
|
||||
#ifdef _WIN32
|
||||
::shutdown(m_lsd, SD_BOTH);
|
||||
#else
|
||||
::shutdown(m_lsd, SHUT_RDWR);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr<NetworkStream> TCPAcceptor::accept() {
|
||||
if (!m_listening) return nullptr;
|
||||
|
||||
struct sockaddr_in address;
|
||||
#ifdef _WIN32
|
||||
int len = sizeof(address);
|
||||
#else
|
||||
socklen_t len = sizeof(address);
|
||||
#endif
|
||||
std::memset(&address, 0, sizeof(address));
|
||||
int sd = ::accept(m_lsd, (struct sockaddr*)&address, &len);
|
||||
if (sd < 0) {
|
||||
|
||||
@@ -27,12 +27,18 @@
|
||||
#include <fcntl.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#ifdef _WIN32
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "TCPStream.h"
|
||||
|
||||
#include "llvm/SmallString.h"
|
||||
#include "Log.h"
|
||||
|
||||
static int ResolveHostName(const char* hostname, struct in_addr* addr) {
|
||||
@@ -49,14 +55,32 @@ static int ResolveHostName(const char* hostname, struct in_addr* addr) {
|
||||
|
||||
std::unique_ptr<NetworkStream> TCPConnector::connect(const char* server,
|
||||
int port, int timeout) {
|
||||
#ifdef _WIN32
|
||||
struct WSAHelper {
|
||||
WSAHelper() {
|
||||
WSAData wsaData;
|
||||
WORD wVersionRequested = MAKEWORD(2, 2);
|
||||
WSAStartup(wVersionRequested, &wsaData);
|
||||
}
|
||||
~WSAHelper() { WSACleanup(); }
|
||||
};
|
||||
static WSAHelper helper;
|
||||
#endif
|
||||
struct sockaddr_in address;
|
||||
|
||||
std::memset(&address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(port);
|
||||
if (ResolveHostName(server, &(address.sin_addr)) != 0) {
|
||||
#ifdef _WIN32
|
||||
llvm::SmallString<128> addr_copy(server);
|
||||
addr_copy.append('\0');
|
||||
int size = sizeof(address);
|
||||
WSAStringToAddress(addr_copy.data(), PF_INET, nullptr, (struct sockaddr*)&address, &size);
|
||||
#else
|
||||
inet_pton(PF_INET, server, &(address.sin_addr));
|
||||
#endif
|
||||
}
|
||||
address.sin_port = htons(port);
|
||||
|
||||
if (timeout == 0) {
|
||||
int sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
@@ -74,9 +98,14 @@ std::unique_ptr<NetworkStream> TCPConnector::connect(const char* server,
|
||||
int result = -1, valopt, sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
// Set socket to non-blocking
|
||||
#ifdef _WIN32
|
||||
u_long mode = 1;
|
||||
ioctlsocket(sd, FIONBIO, &mode);
|
||||
#else
|
||||
arg = fcntl(sd, F_GETFL, nullptr);
|
||||
arg |= O_NONBLOCK;
|
||||
fcntl(sd, F_SETFL, arg);
|
||||
#endif
|
||||
|
||||
// Connect with time limit
|
||||
std::string message;
|
||||
@@ -89,7 +118,7 @@ std::unique_ptr<NetworkStream> TCPConnector::connect(const char* server,
|
||||
FD_SET(sd, &sdset);
|
||||
if (select(sd + 1, nullptr, &sdset, nullptr, &tv) > 0) {
|
||||
len = sizeof(int);
|
||||
getsockopt(sd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &len);
|
||||
getsockopt(sd, SOL_SOCKET, SO_ERROR, (char*)(&valopt), &len);
|
||||
if (valopt) {
|
||||
DEBUG("connect() error " << valopt << " - " << strerror(valopt));
|
||||
}
|
||||
@@ -103,9 +132,14 @@ std::unique_ptr<NetworkStream> TCPConnector::connect(const char* server,
|
||||
}
|
||||
|
||||
// Return socket to blocking mode
|
||||
#ifdef _WIN32
|
||||
mode = 0;
|
||||
ioctlsocket(sd, FIONBIO, &mode);
|
||||
#else
|
||||
arg = fcntl(sd, F_GETFL, nullptr);
|
||||
arg &= (~O_NONBLOCK);
|
||||
fcntl(sd, F_SETFL, arg);
|
||||
#endif
|
||||
|
||||
// Create stream object if connected
|
||||
if (result == -1) return nullptr;
|
||||
|
||||
@@ -23,13 +23,22 @@
|
||||
|
||||
#include "TCPStream.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <WinSock2.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
TCPStream::TCPStream(int sd, struct sockaddr_in* address) : m_sd(sd) {
|
||||
char ip[50];
|
||||
#ifdef _WIN32
|
||||
unsigned long size = sizeof(ip) - 1;
|
||||
WSAAddressToString((struct sockaddr*)address, sizeof sockaddr_in, nullptr, ip, &size);
|
||||
#else
|
||||
inet_ntop(PF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip,
|
||||
sizeof(ip) - 1);
|
||||
#endif
|
||||
m_peerIP = ip;
|
||||
m_peerPort = ntohs(address->sin_port);
|
||||
}
|
||||
@@ -41,11 +50,33 @@ std::size_t TCPStream::send(const char* buffer, std::size_t len, Error* err) {
|
||||
*err = kConnectionClosed;
|
||||
return 0;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
WSABUF wsaBuf;
|
||||
wsaBuf.buf = const_cast<char*>(buffer);
|
||||
wsaBuf.len = (ULONG)len;
|
||||
DWORD rv;
|
||||
bool result = true;
|
||||
while (WSASend(m_sd, &wsaBuf, 1, &rv, 0, nullptr, nullptr) == SOCKET_ERROR) {
|
||||
if (WSAGetLastError() != WSAEWOULDBLOCK) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
if (!result) {
|
||||
char Buffer[128];
|
||||
sprintf(Buffer, "Send() failed: WSA error=%d\n", WSAGetLastError());
|
||||
OutputDebugStringA(Buffer);
|
||||
*err = kConnectionReset;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
ssize_t rv = write(m_sd, buffer, len);
|
||||
if (rv < 0) {
|
||||
*err = kConnectionReset;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return static_cast<std::size_t>(rv);
|
||||
}
|
||||
|
||||
@@ -55,12 +86,25 @@ std::size_t TCPStream::receive(char* buffer, std::size_t len, Error* err,
|
||||
*err = kConnectionClosed;
|
||||
return 0;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
int rv;
|
||||
#else
|
||||
ssize_t rv;
|
||||
if (timeout <= 0)
|
||||
#endif
|
||||
if (timeout <= 0) {
|
||||
#ifdef _WIN32
|
||||
rv = recv(m_sd, buffer, len, 0);
|
||||
#else
|
||||
rv = read(m_sd, buffer, len);
|
||||
else if (WaitForReadEvent(timeout))
|
||||
#endif
|
||||
}
|
||||
else if (WaitForReadEvent(timeout)) {
|
||||
#ifdef _WIN32
|
||||
rv = recv(m_sd, buffer, len, 0);
|
||||
#else
|
||||
rv = read(m_sd, buffer, len);
|
||||
else {
|
||||
#endif
|
||||
} else {
|
||||
*err = kConnectionTimedOut;
|
||||
return 0;
|
||||
}
|
||||
@@ -73,8 +117,13 @@ std::size_t TCPStream::receive(char* buffer, std::size_t len, Error* err,
|
||||
|
||||
void TCPStream::close() {
|
||||
if (m_sd >= 0) {
|
||||
#ifdef _WIN32
|
||||
::shutdown(m_sd, SD_BOTH);
|
||||
closesocket(m_sd);
|
||||
#else
|
||||
::shutdown(m_sd, SHUT_RDWR);
|
||||
::close(m_sd);
|
||||
#endif
|
||||
}
|
||||
m_sd = -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user