759 lines
25 KiB
C
759 lines
25 KiB
C
#include "pcpt.h"
|
|
|
|
e_pcpt_t _pcptGetErrorFromWin(int err) {
|
|
switch (err) {
|
|
case WSAEBADF:
|
|
case WSAEINVAL:
|
|
case WSAENOTSOCK:
|
|
case WSAEISCONN:
|
|
return e_pcpt_wsa2_generic;
|
|
case WSAEMFILE:
|
|
return e_pcpt_cannot_open;
|
|
case WSAEWOULDBLOCK:
|
|
case WSAETIMEDOUT:
|
|
return e_pcpt_to;
|
|
case WSAEADDRNOTAVAIL:
|
|
return e_pcpt_inval_addr;
|
|
case WSAECONNABORTED:
|
|
case WSAECONNRESET:
|
|
return e_pcpt_closed;
|
|
case WSAENOBUFS:
|
|
return e_pcpt_nobufs;
|
|
case WSANOTINITIALISED:
|
|
return e_pcpt_wsa_noinit;
|
|
default:
|
|
return e_pcpt_unknown;
|
|
}
|
|
}
|
|
|
|
e_pcpt_t pcptInitStream(pcpt_t *sock) {
|
|
SOCKET s;
|
|
|
|
if (sock == NULL) {
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
|
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (s == SOCKET_INVAL) return _errW2T(WSAGetLastError());
|
|
closesocket(s);
|
|
|
|
sock->client_open = 0;
|
|
sock->open = PCPT_CLOSED;
|
|
sock->client_event = NULL;
|
|
sock->server_event = NULL;
|
|
sock->send_buf = NULL;
|
|
sock->send_buf_count = NULL;
|
|
sock->recv_buf_count = NULL;
|
|
sock->recv_buf = NULL;
|
|
sock->server_sock = SOCKET_INVAL;
|
|
sock->client_sock = SOCKET_INVAL;
|
|
sock->err = e_pcpt_unknown;
|
|
memset(&sock->client_addr, 0, sizeof sock->client_addr);
|
|
sock->field_0x58 = 0;
|
|
sock->tcp_nodelay = 0;
|
|
sock->config_0 = 12000;
|
|
sock->config_1 = 5;
|
|
sock->so_linger = 1;
|
|
|
|
return e_pcpt_ok;
|
|
}
|
|
|
|
void pcptClose(pcpt_t *sock) {
|
|
if (sock == NULL) {
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return;
|
|
}
|
|
|
|
if (sock->server_sock != SOCKET_INVAL) {
|
|
WSAEventSelect(sock->server_sock, 0, 0);
|
|
WSACloseEvent(sock->server_event);
|
|
sock->server_event = NULL;
|
|
closesocket(sock->server_sock);
|
|
sock->server_sock = SOCKET_INVAL;
|
|
}
|
|
if (sock->client_sock != SOCKET_INVAL) {
|
|
WSAEventSelect(sock->client_sock, 0, 0);
|
|
WSACloseEvent(sock->client_event);
|
|
sock->client_event = NULL;
|
|
closesocket(sock->client_sock);
|
|
sock->client_sock = SOCKET_INVAL;
|
|
}
|
|
sock->client_open = 0;
|
|
sock->open = PCPT_CLOSED;
|
|
sock->err = e_pcpt_unknown;
|
|
if (sock->client_event != NULL) {
|
|
WSACloseEvent(sock->client_event);
|
|
sock->client_event = NULL;
|
|
}
|
|
if (sock->server_event != NULL) {
|
|
WSACloseEvent(sock->server_event);
|
|
sock->server_event = NULL;
|
|
}
|
|
sock->send_buf = NULL;
|
|
sock->send_buf_count = NULL;
|
|
sock->recv_buf_count = NULL;
|
|
sock->recv_buf = NULL;
|
|
memset(&sock->client_addr, 0, sizeof sock->client_addr);
|
|
sock->field_0x58 = 0;
|
|
}
|
|
|
|
void pcptCloseDataSock(pcpt_t *sock) {
|
|
if (sock == NULL) {
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return;
|
|
}
|
|
if (sock->field_0x58 != 0) {
|
|
sock->open = PCPT_LISTENING;
|
|
}
|
|
sock->client_open = 0;
|
|
if (sock->client_sock != SOCKET_INVAL) {
|
|
WSAEventSelect(sock->client_sock, 0, 0);
|
|
WSACloseEvent(sock->client_event);
|
|
sock->client_event = NULL;
|
|
closesocket(sock->client_sock);
|
|
sock->client_sock = SOCKET_INVAL;
|
|
}
|
|
}
|
|
|
|
e_pcpt_t pcptAcceptServer(pcpt_t *stream, timeout_t timeout_ms) {
|
|
if (stream == NULL) {
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
|
|
e_pcpt_t err = pcptCheckEvent(stream->server_event, timeout_ms, stream->server_sock, FD_ACCEPT);
|
|
if (err != e_pcpt_ok) return err;
|
|
|
|
int addrlen = 16;
|
|
SOCKET client = accept(stream->server_sock, &stream->client_addr, &addrlen);
|
|
stream->client_sock = client;
|
|
if (client == SOCKET_INVAL) return _errW2T(GetLastError());
|
|
|
|
WSAEVENT event = WSACreateEvent();
|
|
stream->client_event = event;
|
|
if (event == NULL) {
|
|
closesocket(stream->client_sock);
|
|
stream->client_sock = SOCKET_INVAL;
|
|
return e_pcpt_unknown;
|
|
}
|
|
WSAEventSelect(stream->client_sock, event, FD_READ | FD_WRITE | FD_CLOSE);
|
|
|
|
uint so_linger = (uint)(!!stream->so_linger);
|
|
setsockopt(stream->client_sock, SOL_SOCKET, SO_LINGER, (void *)&so_linger, sizeof so_linger);
|
|
|
|
uint nodelay = (uint)(!stream->tcp_nodelay);
|
|
setsockopt(stream->client_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay, sizeof nodelay);
|
|
return e_pcpt_ok;
|
|
}
|
|
|
|
e_pcpt_t pcptCheckConnectAble(pcpt_t *stream, timeout_t timeout_ms) {
|
|
DWORD DVar1;
|
|
uint uVar3;
|
|
HANDLE event;
|
|
bool bVar5;
|
|
e_pcpt_t local_44;
|
|
u_long local_40;
|
|
amtime_t now;
|
|
amtime_t start;
|
|
|
|
if (stream == NULL) {
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
amiTimerGet(&start);
|
|
DVar1 = timeout_ms;
|
|
|
|
if (timeout_ms == TIMEOUT_NONE) DVar1 = TIMEOUT_NONE;
|
|
|
|
while (DVar1 = WaitForSingleObject(stream->client_event, DVar1), DVar1 == WAIT_TIMEOUT) {
|
|
LAB_004589c8:
|
|
amiTimerGet(&now);
|
|
uVar3 = _amTimeDelta(now, start);
|
|
if (timeout_ms <= uVar3) return e_pcpt_to;
|
|
|
|
DVar1 = timeout_ms - uVar3;
|
|
}
|
|
|
|
if (DVar1 == 0) {
|
|
WSANETWORKEVENTS net_events;
|
|
|
|
if (FAILED(WSAEnumNetworkEvents(stream->client_sock, stream->client_event, &net_events))) {
|
|
bVar5 = WSAGetLastError() == WSAEWOULDBLOCK;
|
|
} else {
|
|
if ((net_events.lNetworkEvents & 0x10) != 0 &&
|
|
net_events.iErrorCode[FD_CONNECT_BIT] == 0) {
|
|
local_44 = e_pcpt_ok;
|
|
goto LAB_00458a1e;
|
|
}
|
|
if (WSAGetLastError() == WSAEWOULDBLOCK) goto LAB_004589c8;
|
|
bVar5 = net_events.iErrorCode[FD_CONNECT_BIT] == WSAECONNREFUSED;
|
|
}
|
|
if (bVar5) goto LAB_004589c8;
|
|
}
|
|
local_44 = e_pcpt_wsa2_generic;
|
|
|
|
LAB_00458a1e:
|
|
local_40 = 0;
|
|
WSAEventSelect(stream->client_sock, 0, 0);
|
|
WSACloseEvent(stream->client_event);
|
|
stream->client_event = NULL;
|
|
if (local_44 != e_pcpt_ok) {
|
|
closesocket(stream->client_sock);
|
|
stream->client_sock = SOCKET_INVAL;
|
|
return local_44;
|
|
}
|
|
ioctlsocket(stream->client_sock, FIONBIO, &local_40);
|
|
|
|
event = WSACreateEvent();
|
|
stream->client_event = event;
|
|
if (event != NULL) {
|
|
WSAEventSelect(stream->client_sock, event, FD_READ | FD_WRITE | FD_CLOSE);
|
|
return e_pcpt_ok;
|
|
}
|
|
closesocket(stream->client_sock);
|
|
stream->client_sock = SOCKET_INVAL;
|
|
return e_pcpt_unknown;
|
|
}
|
|
|
|
e_pcpt_t pcptCheckEvent(HANDLE event, timeout_t timeout_ms, SOCKET socket, uint event_mask) {
|
|
amtime_t now;
|
|
amtime_t start;
|
|
WSANETWORKEVENTS networkEvents;
|
|
|
|
amiTimerGet(&start);
|
|
now.seconds = start.seconds;
|
|
now.microseconds = start.microseconds;
|
|
DWORD wait_timeout = timeout_ms;
|
|
if (timeout_ms == TIMEOUT_NONE) wait_timeout = TIMEOUT_NONE;
|
|
|
|
if (event == NULL) {
|
|
PCP_LOG("Error : EVENT HANDLE error\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
|
|
event_mask &= 0xffffffdf;
|
|
|
|
while (1) {
|
|
DWORD err = WaitForSingleObject(event, wait_timeout);
|
|
if ((err != WAIT_TIMEOUT && err != 0) || FAILED(err)) {
|
|
return e_pcpt_wsa2_generic;
|
|
}
|
|
|
|
if (err != WAIT_TIMEOUT) {
|
|
if (FAILED(WSAEnumNetworkEvents(socket, event, &networkEvents)))
|
|
return e_pcpt_wsa2_generic;
|
|
|
|
if ((networkEvents.lNetworkEvents & 0x20) != 0) return e_pcpt_closed;
|
|
|
|
if ((event_mask & networkEvents.lNetworkEvents) != 0) return e_pcpt_ok;
|
|
}
|
|
|
|
if (timeout_ms != TIMEOUT_NONE) {
|
|
amiTimerGet(&now);
|
|
uint elapsed = _amTimeDelta(now, start);
|
|
if ((uint)timeout_ms <= elapsed) return e_pcpt_to;
|
|
|
|
wait_timeout = timeout_ms - elapsed;
|
|
}
|
|
}
|
|
}
|
|
|
|
e_pcpt_t pcptOpenDataSockServer(pcpt_t *sock, timeout_t timeout_ms) {
|
|
if (sock == NULL) {
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
if (sock->open == PCPT_CONNECTED) return e_pcpt_already_open;
|
|
if (sock->open == PCPT_CLOSED) return e_pcpt_not_open;
|
|
|
|
if ((sock->client_sock == SOCKET_INVAL)) {
|
|
e_pcpt_t err = pcptAcceptServer(sock, timeout_ms);
|
|
if (err != e_pcpt_ok) return err;
|
|
}
|
|
|
|
sock->open = PCPT_CONNECTED;
|
|
return e_pcpt_ok;
|
|
}
|
|
|
|
e_pcpt_t pcptOpenServer(pcpt_t *stream, int open_mode, ushort port) {
|
|
e_pcpt_t err;
|
|
|
|
if (stream == NULL) {
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
|
|
if (stream->server_sock != SOCKET_INVAL || stream->client_sock != SOCKET_INVAL)
|
|
return stream->err = e_pcpt_already_open;
|
|
|
|
amtime_t start;
|
|
amiTimerGet(&start);
|
|
stream->field_0x58 = 1;
|
|
stream->open = PCPT_CLOSED;
|
|
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
|
|
stream->server_sock = s;
|
|
|
|
if (s == SOCKET_INVAL) return stream->err = _errW2T(GetLastError());
|
|
|
|
uint reuseaddr = 1;
|
|
if (FAILED(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&reuseaddr, 4))) {
|
|
err = _errW2T(GetLastError());
|
|
closesocket(stream->server_sock);
|
|
stream->server_sock = SOCKET_INVAL;
|
|
return stream->err = err;
|
|
}
|
|
|
|
SOCKADDR_IN addr = { .sin_family = AF_INET,
|
|
.sin_port = ntohs(port),
|
|
.sin_addr.s_addr = ntohl(0) };
|
|
if (open_mode != OPEN_MODE_GLOBAL) {
|
|
INT len = sizeof &addr.sin_addr.s_addr;
|
|
|
|
WSAStringToAddressW(L"127.0.0.1", AF_INET, NULL, (LPSOCKADDR)&addr.sin_addr.s_addr, &len);
|
|
}
|
|
|
|
if (FAILED(bind(stream->server_sock, (SOCKADDR *)&addr, sizeof addr))) {
|
|
err = _errW2T(GetLastError());
|
|
closesocket(stream->server_sock);
|
|
stream->server_sock = SOCKET_INVAL;
|
|
return stream->err = err;
|
|
}
|
|
if (FAILED(listen(stream->server_sock, 128))) {
|
|
err = _errW2T(GetLastError());
|
|
closesocket(stream->server_sock);
|
|
stream->server_sock = SOCKET_INVAL;
|
|
return stream->err = err;
|
|
}
|
|
|
|
WSAEVENT event = WSACreateEvent();
|
|
stream->server_event = event;
|
|
if (event != NULL) {
|
|
WSAEventSelect(stream->server_sock, event, FD_CLOSE | FD_ACCEPT);
|
|
stream->open = PCPT_LISTENING;
|
|
stream->client_open = 0;
|
|
return stream->err = e_pcpt_ok;
|
|
}
|
|
closesocket(stream->server_sock);
|
|
stream->server_sock = SOCKET_INVAL;
|
|
|
|
return stream->err = e_pcpt_unknown;
|
|
}
|
|
|
|
e_pcpt_t pcptRecv(pcpt_t *sock, unsigned char *recv_buf, size_t *recv_buf_len,
|
|
timeout_t timeout_ms) {
|
|
e_pcpt_t err;
|
|
amtime_t now;
|
|
amtime_t start;
|
|
|
|
if (sock == NULL || recv_buf == NULL || recv_buf_len == NULL) {
|
|
printf("%p %p %p\n", sock, recv_buf, recv_buf_len);
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
|
|
if (sock->open == PCPT_CLOSED) return sock->err = e_pcpt_not_open;
|
|
if (sock->client_open != 0) return sock->err = e_pcpt_already_connected;
|
|
|
|
sock->recv_buf = recv_buf;
|
|
sock->recv_buf_count = recv_buf_len;
|
|
sock->client_open = 3;
|
|
|
|
if (sock->open == PCPT_LISTENING && sock->field_0x58 != 0) {
|
|
amiTimerGet(&start);
|
|
sock->err = err = pcptOpenDataSockServer(sock, timeout_ms);
|
|
if (err == e_pcpt_to) return e_pcpt_to;
|
|
|
|
if (err != e_pcpt_ok) {
|
|
pcptCloseDataSock(sock);
|
|
return sock->err;
|
|
}
|
|
|
|
if (timeout_ms != TIMEOUT_NONE) {
|
|
amiTimerGet(&now);
|
|
uint elapsed = _amTimeDelta(now, start);
|
|
|
|
if (elapsed < timeout_ms)
|
|
timeout_ms = timeout_ms - elapsed;
|
|
else
|
|
timeout_ms = 0;
|
|
}
|
|
}
|
|
sock->err = err = pcptCheckEvent(sock->client_event, timeout_ms, sock->client_sock, FD_READ);
|
|
if (err == e_pcpt_to) return e_pcpt_to;
|
|
|
|
sock->client_open = 0;
|
|
if (err == e_pcpt_ok) {
|
|
size_t recv_count =
|
|
recv(sock->client_sock, (char *)sock->recv_buf, *sock->recv_buf_count, 0);
|
|
if (0 < (int)recv_count) {
|
|
*recv_buf_len = recv_count;
|
|
sock->err = e_pcpt_ok;
|
|
return e_pcpt_ok;
|
|
}
|
|
|
|
if (recv_count == 0) {
|
|
pcptCloseDataSock(sock);
|
|
return sock->err = e_pcpt_closed;
|
|
}
|
|
sock->err = _errW2T(GetLastError());
|
|
}
|
|
|
|
pcptCloseDataSock(sock);
|
|
return sock->err;
|
|
}
|
|
|
|
e_pcpt_t pcptSend(pcpt_t *sock, unsigned char *send_buf, size_t *send_len, uint param_4,
|
|
timeout_t timeout_ms) {
|
|
e_pcpt_t err;
|
|
amtime_t now;
|
|
amtime_t start_time;
|
|
|
|
if (sock == NULL || send_buf == NULL || send_len == NULL) {
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
|
|
if (sock->open == PCPT_CLOSED) return sock->err = e_pcpt_not_open;
|
|
if (sock->client_open != 0) return sock->err = e_pcpt_already_connected;
|
|
|
|
sock->send_buf_count = send_len;
|
|
sock->send_buf = send_buf;
|
|
sock->client_open = 2;
|
|
sock->field_0x14 = param_4;
|
|
sock->field_0x54 = 0;
|
|
|
|
if (sock->open == PCPT_LISTENING && sock->field_0x58 != 0) {
|
|
amiTimerGet(&start_time);
|
|
err = pcptOpenDataSockServer(sock, timeout_ms);
|
|
sock->err = err;
|
|
if (err == e_pcpt_to) return e_pcpt_to;
|
|
|
|
if (err == e_pcpt_ok) {
|
|
amiTimerGet(&now);
|
|
uint elapsed = _amTimeDelta(now, start_time);
|
|
if (timeout_ms != TIMEOUT_NONE) {
|
|
if (elapsed < timeout_ms)
|
|
timeout_ms = timeout_ms - elapsed;
|
|
else
|
|
timeout_ms = 0;
|
|
}
|
|
goto LAB_0045930e;
|
|
}
|
|
} else {
|
|
LAB_0045930e:
|
|
err = pcptSendAllMsg(sock, timeout_ms);
|
|
sock->err = err;
|
|
if (err == e_pcpt_to) {
|
|
return e_pcpt_to;
|
|
}
|
|
sock->client_open = 0;
|
|
if (err == e_pcpt_ok) return err;
|
|
}
|
|
pcptCloseDataSock(sock);
|
|
|
|
return sock->err;
|
|
}
|
|
|
|
e_pcpt_t pcptSendAllMsg(pcpt_t *sock, timeout_t timeout_ms) {
|
|
size_t sVar1;
|
|
bool bVar2;
|
|
e_pcpt_t err;
|
|
bool bVar3;
|
|
amtime_t now;
|
|
amtime_t start;
|
|
|
|
if (sock == NULL) {
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
|
|
if (sock->send_buf == NULL || sock->send_buf_count == NULL) {
|
|
PCP_LOG("error send buffer isn\'t set\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
|
|
bVar3 = sock->field_0x54 == 0;
|
|
amiTimerGet(&start);
|
|
sVar1 = *sock->send_buf_count;
|
|
while (1) {
|
|
if (sVar1 == 0) {
|
|
sock->field_0x54 = 0;
|
|
return e_pcpt_ok;
|
|
}
|
|
|
|
bVar2 = false;
|
|
amiTimerGet(&now);
|
|
uint elapsed = _amTimeDelta(now, start);
|
|
if (timeout_ms != TIMEOUT_NONE && timeout_ms < elapsed) return e_pcpt_to;
|
|
|
|
uint wait_time;
|
|
if (bVar3) {
|
|
wait_time = timeout_ms;
|
|
if (timeout_ms != TIMEOUT_NONE) wait_time = timeout_ms - elapsed;
|
|
} else {
|
|
if ((timeout_ms == TIMEOUT_NONE) ||
|
|
(wait_time = timeout_ms - elapsed,
|
|
sock->field_0x14 <= wait_time && wait_time != sock->field_0x14)) {
|
|
wait_time = sock->field_0x14;
|
|
bVar2 = true;
|
|
}
|
|
}
|
|
int sent = send(sock->client_sock, (char *)sock->send_buf, *sock->send_buf_count, 0);
|
|
if (sent == -1) {
|
|
err = _errW2T(GetLastError());
|
|
if (err != e_pcpt_to) return err;
|
|
|
|
err = pcptCheckEvent(sock->client_event, wait_time, sock->client_sock, FD_WRITE);
|
|
if (err == e_pcpt_to) {
|
|
if (!bVar2) return e_pcpt_to;
|
|
|
|
sock->field_0x54 = 0;
|
|
return e_pcpt_NO_IDEA_WHAT_THIS_IS;
|
|
}
|
|
|
|
if (err != e_pcpt_ok) return err;
|
|
} else {
|
|
sock->send_buf = sock->send_buf + sent;
|
|
sock->field_0x54 = 1;
|
|
*sock->send_buf_count = *sock->send_buf_count - sent;
|
|
}
|
|
|
|
bVar3 = false;
|
|
sVar1 = *sock->send_buf_count;
|
|
}
|
|
}
|
|
|
|
void pcptSetConfig(pcpt_t *stream, uint config, uint value) {
|
|
if (stream == NULL) {
|
|
PCP_LOG("error don\'t set stream\n");
|
|
return;
|
|
}
|
|
|
|
switch (config) {
|
|
case PCPT_CONFIG_0:
|
|
stream->config_0 = value;
|
|
break;
|
|
case PCPT_CONFIG_1:
|
|
stream->config_1 = value;
|
|
break;
|
|
case PCPT_SO_LINGER:
|
|
stream->so_linger = value;
|
|
break;
|
|
case PCPT_TCP_NODELAY:
|
|
stream->tcp_nodelay = value;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// TODO: TIDY
|
|
|
|
e_pcpt_t pcptIsBusy(pcpt_t *sock, timeout_t timeout_ms) {
|
|
bool bVar1;
|
|
bool bVar2;
|
|
uint uVar3;
|
|
uint uVar4;
|
|
SOCKET SVar5;
|
|
WSAEVENT event;
|
|
int iVar7;
|
|
e_pcpt_t eVar8;
|
|
u_long timeout_ms_00;
|
|
uint uVar10;
|
|
amtime_t local_18;
|
|
amtime_t local_10;
|
|
amtime_t local_8;
|
|
|
|
timeout_ms_00 = timeout_ms;
|
|
if (sock == NULL) {
|
|
PCP_LOG("error PCP stream isn\'t set\n");
|
|
return e_pcpt_pointer_unset;
|
|
}
|
|
switch (sock->client_open) {
|
|
case 0:
|
|
sock->err = e_pcpt_no_client;
|
|
return sock->err;
|
|
case 1:
|
|
if (sock->open != PCPT_CLOSED) {
|
|
sock->err = e_pcpt_cannot_open;
|
|
sock->client_open = 0;
|
|
return sock->err;
|
|
}
|
|
amiTimerGet(&local_10);
|
|
uVar10 = timeout_ms_00;
|
|
do {
|
|
bVar1 = false;
|
|
bVar2 = false;
|
|
amiTimerGet(&local_18);
|
|
if (uVar10 != TIMEOUT_NONE) {
|
|
uVar3 = _amTimeDelta(local_18, local_10);
|
|
if (uVar3 < uVar10) {
|
|
timeout_ms_00 = uVar10 - uVar3;
|
|
} else {
|
|
bVar2 = true;
|
|
timeout_ms_00 = 0;
|
|
}
|
|
}
|
|
amiTimerGet(&local_18);
|
|
uVar4 = _amTimeMs(local_18) - sock->field_0x40;
|
|
uVar3 = sock->config_0;
|
|
if (uVar3 < uVar4) {
|
|
timeout_ms_00 = 0;
|
|
LAB_00459626:
|
|
bVar1 = true;
|
|
} else {
|
|
if ((uVar10 == TIMEOUT_NONE) || (uVar3 < timeout_ms_00)) {
|
|
timeout_ms_00 = uVar3 - uVar4;
|
|
goto LAB_00459626;
|
|
}
|
|
}
|
|
eVar8 = pcptCheckConnectAble(sock, timeout_ms_00);
|
|
sock->err = eVar8;
|
|
if (eVar8 != e_pcpt_to) {
|
|
sock->client_open = 0;
|
|
if (eVar8 == e_pcpt_ok) {
|
|
sock->open = PCPT_CONNECTED;
|
|
return sock->err;
|
|
}
|
|
break;
|
|
}
|
|
if (bVar1) {
|
|
WSAEventSelect(sock->client_sock, 0, 0);
|
|
WSACloseEvent(sock->client_event);
|
|
sock->client_event = NULL;
|
|
closesocket(sock->client_sock);
|
|
sock->client_sock = SOCKET_INVAL;
|
|
SVar5 = socket(2, 1, 0);
|
|
sock->client_sock = SVar5;
|
|
if (SVar5 == SOCKET_INVAL) goto LAB_004599cf;
|
|
event = WSACreateEvent();
|
|
sock->client_event = event;
|
|
if (event == NULL) {
|
|
closesocket(sock->client_sock);
|
|
sock->err = e_pcpt_unknown;
|
|
sock->client_sock = SOCKET_INVAL;
|
|
return sock->err;
|
|
}
|
|
WSAEventSelect(sock->client_sock, event, FD_CONNECT | FD_CLOSE);
|
|
iVar7 = connect(sock->client_sock, &sock->client_addr, 16);
|
|
if (iVar7 != -1) {
|
|
WSAEventSelect(sock->client_sock, 0, 0);
|
|
WSACloseEvent(sock->client_event);
|
|
sock->client_event = NULL;
|
|
timeout_ms = 0;
|
|
ioctlsocket(sock->client_sock, FIONBIO, (u_long *)&timeout_ms);
|
|
event = WSACreateEvent();
|
|
sock->client_event = event;
|
|
if (event != NULL) {
|
|
WSAEventSelect(sock->client_sock, event, FD_READ | FD_WRITE | FD_CLOSE);
|
|
sock->err = e_pcpt_ok;
|
|
sock->client_open = 0;
|
|
sock->open = PCPT_CONNECTED;
|
|
return e_pcpt_ok;
|
|
}
|
|
closesocket(sock->client_sock);
|
|
sock->err = e_pcpt_unknown;
|
|
sock->client_sock = SOCKET_INVAL;
|
|
return sock->err;
|
|
}
|
|
amiTimerGet(&local_8);
|
|
sock->field_0x40 = _amTimeMs(local_8);
|
|
} else {
|
|
if (bVar2) {
|
|
sock->err = e_pcpt_to;
|
|
return e_pcpt_to;
|
|
}
|
|
}
|
|
uVar10 = timeout_ms;
|
|
} while (sock->err == e_pcpt_to);
|
|
break;
|
|
case 2:
|
|
if (sock->open == PCPT_CLOSED) {
|
|
sock->err = e_pcpt_not_open;
|
|
return e_pcpt_not_open;
|
|
}
|
|
if ((sock->open == PCPT_LISTENING) && (sock->field_0x58 != 0)) {
|
|
amiTimerGet(&local_10);
|
|
eVar8 = pcptOpenDataSockServer(sock, timeout_ms_00);
|
|
sock->err = eVar8;
|
|
if (eVar8 == e_pcpt_to) {
|
|
return e_pcpt_to;
|
|
}
|
|
if (eVar8 != e_pcpt_ok) {
|
|
LAB_0045997d:
|
|
pcptCloseDataSock(sock);
|
|
return sock->err;
|
|
}
|
|
amiTimerGet(&local_18);
|
|
if (timeout_ms_00 != TIMEOUT_NONE) {
|
|
iVar7 = (local_18.microseconds - local_10.microseconds) / 1000;
|
|
if (timeout_ms_00 <
|
|
(uint)((local_18.seconds - local_10.seconds) * 1000 + iVar7)) {
|
|
timeout_ms_00 =
|
|
((local_10.seconds - local_18.seconds) * 1000 - iVar7) + timeout_ms_00;
|
|
} else {
|
|
timeout_ms_00 = 0;
|
|
}
|
|
}
|
|
}
|
|
eVar8 = pcptSendAllMsg(sock, timeout_ms_00);
|
|
sock->err = eVar8;
|
|
if (eVar8 != e_pcpt_to) {
|
|
if (eVar8 != e_pcpt_ok) {
|
|
pcptCloseDataSock(sock);
|
|
}
|
|
sock->client_open = 0;
|
|
return sock->err;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (sock->open == PCPT_CLOSED) {
|
|
sock->err = e_pcpt_not_open;
|
|
return sock->err;
|
|
}
|
|
if ((sock->open == PCPT_LISTENING) && (sock->field_0x58 != 0)) {
|
|
amiTimerGet(&local_10);
|
|
eVar8 = pcptOpenDataSockServer(sock, timeout_ms_00);
|
|
sock->err = eVar8;
|
|
if (eVar8 == e_pcpt_to) {
|
|
return e_pcpt_to;
|
|
}
|
|
if (eVar8 != e_pcpt_ok) goto LAB_0045997d;
|
|
amiTimerGet(&local_18);
|
|
if (timeout_ms_00 != TIMEOUT_NONE) {
|
|
iVar7 = (local_18.microseconds - local_10.microseconds) / 1000;
|
|
if (timeout_ms_00 <
|
|
(uint)((local_18.seconds - local_10.seconds) * 1000 + iVar7)) {
|
|
timeout_ms_00 =
|
|
((local_10.seconds - local_18.seconds) * 1000 - iVar7) + timeout_ms_00;
|
|
} else {
|
|
timeout_ms_00 = 0;
|
|
}
|
|
}
|
|
}
|
|
eVar8 = pcptCheckEvent(sock->client_event, timeout_ms_00, sock->client_sock, 1);
|
|
sock->err = eVar8;
|
|
if (eVar8 == e_pcpt_to) break;
|
|
sock->client_open = 0;
|
|
if (eVar8 != e_pcpt_ok) goto LAB_0045997d;
|
|
if (sock->recv_buf == NULL || sock->recv_buf_count == NULL) {
|
|
PCP_LOG("error Recv buffer isn\'t set\n");
|
|
return sock->err = e_pcpt_recv_unset;
|
|
}
|
|
size_t received =
|
|
recv(sock->client_sock, (char *)sock->recv_buf, *sock->recv_buf_count, 0);
|
|
if (received < 1) {
|
|
pcptCloseDataSock(sock);
|
|
if (received == 0) {
|
|
sock->err = e_pcpt_closed;
|
|
return e_pcpt_closed;
|
|
}
|
|
LAB_004599cf:
|
|
return sock->err = _errW2T(GetLastError());
|
|
}
|
|
*sock->recv_buf_count = received;
|
|
default:
|
|
sock->err = e_pcpt_ok;
|
|
}
|
|
return sock->err;
|
|
}
|