Static Webview - RTC - UDP - TCP - WSS

This commit is contained in:
2026-10-03 01:22:41 -07:00
parent 058104d93f
commit 75224df058
19 changed files with 1994 additions and 284 deletions

View File

@ -44,6 +44,7 @@ public:
bool isConnected;
bool isBound;
bool isListening;
bool connectInProgress;
std::string lastError;
#ifdef _WIN32
@ -58,7 +59,8 @@ public:
void* ssl_cred_handle_;
void* ssl_context_handle_;
bool ssl_context_initialized_;
std::vector<char> ssl_buffer_;
std::vector<char> ssl_buffer_;
std::vector<char> ssl_send_buffer_;
#else
SSL* ssl;
SSL_CTX* ssl_ctx;
@ -67,7 +69,7 @@ public:
#endif
RunTSocket(int socket_id) : id(socket_id), isBlocking(true), isConnected(false),
isBound(false), isListening(false) {
isBound(false), isListening(false), connectInProgress(false) {
#ifdef _WIN32
socket_fd = INVALID_SOCKET;
#else
@ -245,6 +247,14 @@ extern "C" int runt_socket_create() {
int no_sigpipe = 1;
setsockopt(socket->socket_fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&no_sigpipe, sizeof(no_sigpipe));
#endif
#ifdef _WIN32
u_long mode = 1;
ioctlsocket(socket->socket_fd, FIONBIO, &mode);
#else
int flags = fcntl(socket->socket_fd, F_GETFL, 0);
fcntl(socket->socket_fd, F_SETFL, flags | O_NONBLOCK);
#endif
socket->isBlocking = false;
g_sockets[socket_id] = std::move(socket);
#ifdef DEBUG_NETWORK
@ -399,6 +409,20 @@ extern "C" bool runt_socket_connect(int socket_id, const char* hostname, int por
connected = true;
break;
}
#ifdef _WIN32
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK || err == WSAEINPROGRESS) {
connected = true;
socket->connectInProgress = true;
break;
}
#else
if (errno == EINPROGRESS || errno == EWOULDBLOCK) {
connected = true;
socket->connectInProgress = true;
break;
}
#endif
}
freeaddrinfo(result);
@ -413,7 +437,7 @@ extern "C" bool runt_socket_connect(int socket_id, const char* hostname, int por
return false;
}
socket->isConnected = true;
socket->isConnected = !socket->connectInProgress;
#ifdef DEBUG_NETWORK
kinc_log(KINC_LOG_LEVEL_INFO, "Connected successfully to %s:%d", hostname, port);
#endif
@ -447,7 +471,8 @@ extern "C" int runt_socket_send(int socket_id, const char* data, int length) {
}
int total_size = stream_sizes.cbHeader + length + stream_sizes.cbTrailer;
char* encrypt_buffer = new char[total_size];
socket->ssl_send_buffer_.resize(total_size);
char* encrypt_buffer = socket->ssl_send_buffer_.data();
SecBufferDesc message_desc;
SecBuffer message_buffers[4];
@ -479,15 +504,12 @@ extern "C" int runt_socket_send(int socket_id, const char* data, int length) {
if (status != SEC_E_OK) {
kinc_log(KINC_LOG_LEVEL_ERROR, "SChannel encrypt failed: 0x%x", status);
delete[] encrypt_buffer;
return -1;
}
int total_encrypted = message_buffers[0].cbBuffer + message_buffers[1].cbBuffer + message_buffers[2].cbBuffer;
int sent = send(socket->socket_fd, encrypt_buffer, total_encrypted, 0);
delete[] encrypt_buffer;
if (sent != total_encrypted) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to send encrypted SSL data");
return -1;
@ -644,11 +666,13 @@ extern "C" int runt_socket_recv(int socket_id, int max_length, char** out_data)
int received = recv(socket->socket_fd, recv_buffer, sizeof(recv_buffer), 0);
if (received <= 0) {
delete[] buffer;
if (received < 0 && WSAGetLastError() == WSAEWOULDBLOCK) return 0;
if (received == 0) {
#ifdef DEBUG_NETWORK
kinc_log(KINC_LOG_LEVEL_INFO, "SSL connection closed by server");
#endif
return 0;
socket->isConnected = false;
return -2;
} else {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to receive encrypted data for SSL read");
return -1;
@ -669,11 +693,13 @@ extern "C" int runt_socket_recv(int socket_id, int max_length, char** out_data)
int received = recv(socket->socket_fd, recv_buffer, sizeof(recv_buffer), 0);
if (received <= 0) {
delete[] buffer;
if (received < 0 && WSAGetLastError() == WSAEWOULDBLOCK) return 0;
if (received == 0) {
#ifdef DEBUG_NETWORK
kinc_log(KINC_LOG_LEVEL_INFO, "SSL connection closed by server (no buffered data)");
#endif
return 0;
socket->isConnected = false;
return -2;
} else {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to receive encrypted data");
return -1;
@ -691,6 +717,10 @@ extern "C" int runt_socket_recv(int socket_id, int max_length, char** out_data)
if (ssl_error == SSL_ERROR_WANT_READ || ssl_error == SSL_ERROR_WANT_WRITE) {
return 0;
}
if (ssl_error == SSL_ERROR_ZERO_RETURN) {
socket->isConnected = false;
return -2;
}
kinc_log(KINC_LOG_LEVEL_ERROR, "SSL_read failed: %d", ssl_error);
return -1;
}
@ -755,6 +785,143 @@ extern "C" int runt_socket_recv(int socket_id, int max_length, char** out_data)
return received;
}
extern "C" int runt_udp_create() {
if (!initialize_networking()) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to initialize networking");
return -1;
}
int socket_id = g_next_socket_id++;
auto socket = std::make_unique<RunTSocket>(socket_id);
#ifdef _WIN32
socket->socket_fd = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (socket->socket_fd == INVALID_SOCKET) {
kinc_log(KINC_LOG_LEVEL_ERROR, "UDP socket creation failed: %d",
WSAGetLastError());
return -1;
}
#else
socket->socket_fd = ::socket(AF_INET, SOCK_DGRAM, 0);
if (socket->socket_fd < 0) {
kinc_log(KINC_LOG_LEVEL_ERROR, "UDP socket creation failed: %s",
strerror(errno));
return -1;
}
#endif
int reuse = 1;
setsockopt(socket->socket_fd, SOL_SOCKET, SO_REUSEADDR,
(const char*)&reuse, sizeof(reuse));
int sndbuf = 256 * 1024;
int rcvbuf = 256 * 1024;
setsockopt(socket->socket_fd, SOL_SOCKET, SO_SNDBUF,
(const char*)&sndbuf, sizeof(sndbuf));
setsockopt(socket->socket_fd, SOL_SOCKET, SO_RCVBUF,
(const char*)&rcvbuf, sizeof(rcvbuf));
#ifdef _WIN32
u_long mode = 1;
ioctlsocket(socket->socket_fd, FIONBIO, &mode);
#else
int flags = fcntl(socket->socket_fd, F_GETFL, 0);
fcntl(socket->socket_fd, F_SETFL, flags | O_NONBLOCK);
#endif
socket->isBlocking = false;
g_sockets[socket_id] = std::move(socket);
#ifdef DEBUG_NETWORK
kinc_log(KINC_LOG_LEVEL_INFO, "UDP socket created: ID %d", socket_id);
#endif
return socket_id;
}
extern "C" bool runt_udp_bind(int socket_id, const char* address,
int port) {
return runt_socket_bind(socket_id, address, port);
}
extern "C" int runt_udp_sendto(int socket_id, const char* host, int port,
const char* data, int length) {
auto it = g_sockets.find(socket_id);
if (it == g_sockets.end()) return -1;
auto& socket = it->second;
if (!socket->isValid()) return -1;
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (inet_pton(AF_INET, host, &addr.sin_addr) <= 0) {
struct addrinfo hints, *result;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
if (getaddrinfo(host, nullptr, &hints, &result) != 0) {
kinc_log(KINC_LOG_LEVEL_ERROR,
"UDP resolve failed: %s", host);
return -1;
}
addr.sin_addr = ((sockaddr_in*)result->ai_addr)->sin_addr;
freeaddrinfo(result);
}
#ifdef _WIN32
int sent = sendto(socket->socket_fd, data, length, 0,
(sockaddr*)&addr, sizeof(addr));
if (sent < 0) {
int error = WSAGetLastError();
if (error == WSAEWOULDBLOCK) return 0;
kinc_log(KINC_LOG_LEVEL_ERROR, "UDP sendto failed: %d", error);
return -1;
}
#else
int sent = sendto(socket->socket_fd, data, length, MSG_NOSIGNAL,
(sockaddr*)&addr, sizeof(addr));
if (sent < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) return 0;
kinc_log(KINC_LOG_LEVEL_ERROR, "UDP sendto failed: %s",
strerror(errno));
return -1;
}
#endif
return sent;
}
extern "C" int runt_udp_recvfrom(int socket_id, int max_length,
char** out_data, char* out_host, int out_host_len,
int* out_port) {
auto it = g_sockets.find(socket_id);
if (it == g_sockets.end()) return -1;
auto& socket = it->second;
if (!socket->isValid()) return -1;
char* buffer = new char[max_length];
sockaddr_in from;
socklen_t fromlen = sizeof(from);
int received = recvfrom(socket->socket_fd, buffer, max_length, 0,
(sockaddr*)&from, &fromlen);
if (received < 0) {
delete[] buffer;
#ifdef _WIN32
if (WSAGetLastError() == WSAEWOULDBLOCK) return 0;
#else
if (errno == EAGAIN || errno == EWOULDBLOCK) return 0;
#endif
return -1;
}
inet_ntop(AF_INET, &from.sin_addr, out_host, out_host_len);
*out_port = ntohs(from.sin_port);
*out_data = buffer;
return received;
}
extern "C" void runt_socket_close(int socket_id) {
auto it = g_sockets.find(socket_id);
if (it == g_sockets.end()) return;
@ -767,11 +934,45 @@ extern "C" void runt_socket_close(int socket_id) {
}
extern "C" bool runt_socket_is_connected(int socket_id) {
auto it = g_sockets.find(socket_id);
if (it == g_sockets.end()) return false;
auto& socket = it->second;
return socket->isValid() && socket->isConnected;
auto it = g_sockets.find(socket_id);
if (it == g_sockets.end()) return false;
auto& socket = it->second;
if (!socket->isValid()) return false;
if (socket->isConnected) return true;
if (!socket->connectInProgress) return false;
fd_set wfds, efds;
FD_ZERO(&wfds);
FD_ZERO(&efds);
FD_SET(socket->socket_fd, &wfds);
FD_SET(socket->socket_fd, &efds);
struct timeval tv = {0, 0};
int sel;
#ifdef _WIN32
sel = ::select(0, nullptr, &wfds, &efds, &tv);
#else
sel = ::select(socket->socket_fd + 1, nullptr, &wfds, &efds, &tv);
#endif
if (sel <= 0 || (!FD_ISSET(socket->socket_fd, &wfds) &&
!FD_ISSET(socket->socket_fd, &efds))) {
return false;
}
int err = 0;
socklen_t errlen = sizeof(err);
if (getsockopt(socket->socket_fd, SOL_SOCKET, SO_ERROR, (char*)&err, &errlen) != 0) {
socket->connectInProgress = false;
return false;
}
socket->connectInProgress = false;
if (err == 0) {
socket->isConnected = true;
return true;
}
return false;
}
extern "C" void runt_socket_set_blocking(int socket_id, bool blocking) {
@ -925,7 +1126,10 @@ extern "C" bool runt_socket_enable_ssl(int socket_id) {
SSL_set_fd(socket->ssl, socket->socket_fd);
int flags = fcntl(socket->socket_fd, F_GETFL, 0);
fcntl(socket->socket_fd, F_SETFL, flags & ~O_NONBLOCK);
int ret = SSL_connect(socket->ssl);
fcntl(socket->socket_fd, F_SETFL, flags);
if (ret <= 0) {
int ssl_error = SSL_get_error(socket->ssl, ret);
kinc_log(KINC_LOG_LEVEL_ERROR, "SSL_connect failed: %d", ssl_error);