mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-03-12 05:25:23 -07:00
Non-blocking connect
This commit is contained in:
parent
e2fc84e0e6
commit
042e698749
@ -2,6 +2,7 @@
|
||||
set(HEADER_FILES
|
||||
include/chiaki/session.h
|
||||
include/chiaki/common.h
|
||||
include/chiaki/sock.h
|
||||
include/chiaki/thread.h
|
||||
include/chiaki/base64.h
|
||||
include/chiaki/http.h
|
||||
@ -37,6 +38,7 @@ set(HEADER_FILES
|
||||
|
||||
set(SOURCE_FILES
|
||||
src/common.c
|
||||
src/sock.c
|
||||
src/session.c
|
||||
src/thread.c
|
||||
src/base64.c
|
||||
|
@ -18,27 +18,14 @@
|
||||
#ifndef CHIAKI_COMMON_H
|
||||
#define CHIAKI_COMMON_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#ifdef _WIN32
|
||||
#define chiaki_socket_t SOCKET
|
||||
#define CHIAKI_SOCKET_IS_INVALID(s) ((s) == INVALID_SOCKET)
|
||||
#define CHIAKI_INVALID_SOCKET INVALID_SOCKET
|
||||
#define CHIAKI_SOCKET_CLOSE(s) closesocket(s)
|
||||
#define CHIAKI_SOCKET_ERROR_FMT "%d"
|
||||
#define CHIAKI_SOCKET_ERROR_VALUE (WSAGetLastError())
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#define chiaki_socket_t int
|
||||
#define CHIAKI_SOCKET_IS_INVALID(s) ((s) < 0)
|
||||
#define CHIAKI_INVALID_SOCKET (-1)
|
||||
#define CHIAKI_SOCKET_CLOSE(s) close(s)
|
||||
#define CHIAKI_SOCKET_ERROR_FMT "%s"
|
||||
#define CHIAKI_SOCKET_ERROR_VALUE (strerror(errno))
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -56,6 +43,9 @@ typedef enum
|
||||
CHIAKI_ERR_MEMORY,
|
||||
CHIAKI_ERR_OVERFLOW,
|
||||
CHIAKI_ERR_NETWORK,
|
||||
CHIAKI_ERR_CONNECTION_REFUSED,
|
||||
CHIAKI_ERR_HOST_DOWN,
|
||||
CHIAKI_ERR_HOST_UNREACH,
|
||||
CHIAKI_ERR_DISCONNECTED,
|
||||
CHIAKI_ERR_INVALID_DATA,
|
||||
CHIAKI_ERR_BUF_TOO_SMALL,
|
||||
|
56
lib/include/chiaki/sock.h
Normal file
56
lib/include/chiaki/sock.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of Chiaki.
|
||||
*
|
||||
* Chiaki is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Chiaki is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Chiaki. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CHIAKI_SOCK_H
|
||||
#define CHIAKI_SOCK_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
typedef SOCKET chiaki_socket_t;
|
||||
#define CHIAKI_SOCKET_IS_INVALID(s) ((s) == INVALID_SOCKET)
|
||||
#define CHIAKI_INVALID_SOCKET INVALID_SOCKET
|
||||
#define CHIAKI_SOCKET_CLOSE(s) closesocket(s)
|
||||
#define CHIAKI_SOCKET_ERROR_FMT "%d"
|
||||
#define CHIAKI_SOCKET_ERROR_VALUE (WSAGetLastError())
|
||||
#define CHIAKI_SOCKET_EINPROGRESS (WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
typedef int chiaki_socket_t;
|
||||
#define CHIAKI_SOCKET_IS_INVALID(s) ((s) < 0)
|
||||
#define CHIAKI_INVALID_SOCKET (-1)
|
||||
#define CHIAKI_SOCKET_CLOSE(s) close(s)
|
||||
#define CHIAKI_SOCKET_ERROR_FMT "%s"
|
||||
#define CHIAKI_SOCKET_ERROR_VALUE (strerror(errno))
|
||||
#define CHIAKI_SOCKET_EINPROGRESS (errno == EINPROGRESS)
|
||||
#endif
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_socket_set_nonblock(chiaki_socket_t sock, bool nonblock);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //CHIAKI_SOCK_H
|
@ -18,10 +18,11 @@
|
||||
#ifndef CHIAKI_STOPPIPE_H
|
||||
#define CHIAKI_STOPPIPE_H
|
||||
|
||||
#include "common.h"
|
||||
#include "sock.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
@ -40,11 +41,17 @@ typedef struct chiaki_stop_pipe_t
|
||||
#endif
|
||||
} ChiakiStopPipe;
|
||||
|
||||
struct sockaddr;
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_init(ChiakiStopPipe *stop_pipe);
|
||||
CHIAKI_EXPORT void chiaki_stop_pipe_fini(ChiakiStopPipe *stop_pipe);
|
||||
CHIAKI_EXPORT void chiaki_stop_pipe_stop(ChiakiStopPipe *stop_pipe);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, uint64_t timeout_ms);
|
||||
static inline ChiakiErrorCode chiaki_stop_pipe_sleep(ChiakiStopPipe *stop_pipe, uint64_t timeout_ms) { return chiaki_stop_pipe_select_single(stop_pipe, CHIAKI_INVALID_SOCKET, timeout_ms); }
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, bool write, uint64_t timeout_ms);
|
||||
/**
|
||||
* Like connect(), but can be canceled by the stop pipe. Only makes sense with a non-blocking socket.
|
||||
*/
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_connect(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, struct sockaddr *addr, size_t addrlen);
|
||||
static inline ChiakiErrorCode chiaki_stop_pipe_sleep(ChiakiStopPipe *stop_pipe, uint64_t timeout_ms) { return chiaki_stop_pipe_select_single(stop_pipe, CHIAKI_INVALID_SOCKET, false, timeout_ms); }
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_reset(ChiakiStopPipe *stop_pipe);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -213,7 +213,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send(ChiakiTakion *takion, uint8_t *
|
||||
/**
|
||||
* Thread-safe while Takion is running.
|
||||
*
|
||||
* @param optional pointer to write the sequence number of the sent package to
|
||||
* @param optional pointer to write the sequence number of the sent packet to
|
||||
*/
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_message_data(ChiakiTakion *takion, uint8_t chunk_flags, uint16_t channel, uint8_t *buf, size_t buf_size, ChiakiSeqNum32 *seq_num);
|
||||
|
||||
|
@ -43,6 +43,12 @@ CHIAKI_EXPORT const char *chiaki_error_string(ChiakiErrorCode code)
|
||||
return "Memory error";
|
||||
case CHIAKI_ERR_NETWORK:
|
||||
return "Network error";
|
||||
case CHIAKI_ERR_CONNECTION_REFUSED:
|
||||
return "Connection Refused";
|
||||
case CHIAKI_ERR_HOST_DOWN:
|
||||
return "Host is down";
|
||||
case CHIAKI_ERR_HOST_UNREACH:
|
||||
return "No route to host";
|
||||
case CHIAKI_ERR_DISCONNECTED:
|
||||
return "Disconnected";
|
||||
case CHIAKI_ERR_INVALID_DATA:
|
||||
|
@ -151,18 +151,19 @@ static void *ctrl_thread_func(void *user)
|
||||
{
|
||||
ChiakiCtrl *ctrl = user;
|
||||
|
||||
ChiakiErrorCode err = ctrl_connect(ctrl);
|
||||
ChiakiErrorCode err = chiaki_mutex_lock(&ctrl->notif_mutex);
|
||||
assert(err == CHIAKI_ERR_SUCCESS);
|
||||
|
||||
err = ctrl_connect(ctrl);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
ctrl_failed(ctrl, CHIAKI_QUIT_REASON_CTRL_CONNECT_FAILED);
|
||||
chiaki_mutex_unlock(&ctrl->notif_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CHIAKI_LOGI(ctrl->session->log, "Ctrl connected");
|
||||
|
||||
err = chiaki_mutex_lock(&ctrl->notif_mutex);
|
||||
assert(err == CHIAKI_ERR_SUCCESS);
|
||||
|
||||
while(true)
|
||||
{
|
||||
bool overflow = false;
|
||||
@ -197,7 +198,7 @@ static void *ctrl_thread_func(void *user)
|
||||
}
|
||||
|
||||
chiaki_mutex_unlock(&ctrl->notif_mutex);
|
||||
err = chiaki_stop_pipe_select_single(&ctrl->notif_pipe, ctrl->sock, UINT64_MAX);
|
||||
err = chiaki_stop_pipe_select_single(&ctrl->notif_pipe, ctrl->sock, false, UINT64_MAX);
|
||||
chiaki_mutex_lock(&ctrl->notif_mutex);
|
||||
if(err == CHIAKI_ERR_CANCELED)
|
||||
{
|
||||
@ -511,29 +512,38 @@ static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl)
|
||||
return CHIAKI_ERR_NETWORK;
|
||||
}
|
||||
|
||||
int r = connect(sock, sa, addr->ai_addrlen);
|
||||
ChiakiErrorCode err = chiaki_socket_set_nonblock(sock, true);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
CHIAKI_LOGE(session->log, "Failed to set ctrl socket to non-blocking: %s", chiaki_error_string(err));
|
||||
|
||||
|
||||
chiaki_mutex_unlock(&ctrl->notif_mutex);
|
||||
err = chiaki_stop_pipe_connect(&ctrl->notif_pipe, sock, sa, addr->ai_addrlen);
|
||||
chiaki_mutex_lock(&ctrl->notif_mutex);
|
||||
free(sa);
|
||||
if(r < 0)
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int errsv = WSAGetLastError();
|
||||
CHIAKI_LOGE(session->log, "Ctrl connect failed: %d", errsv);
|
||||
ChiakiQuitReason quit_reason = errsv == WSAECONNREFUSED ? CHIAKI_QUIT_REASON_CTRL_CONNECTION_REFUSED : CHIAKI_QUIT_REASON_CTRL_UNKNOWN;
|
||||
#else
|
||||
int errsv = errno;
|
||||
CHIAKI_LOGE(session->log, "Ctrl connect failed: %s", strerror(errsv));
|
||||
ChiakiQuitReason quit_reason = errsv == ECONNREFUSED ? CHIAKI_QUIT_REASON_CTRL_CONNECTION_REFUSED : CHIAKI_QUIT_REASON_CTRL_UNKNOWN;
|
||||
#endif
|
||||
ctrl_failed(ctrl, quit_reason);
|
||||
CHIAKI_SOCKET_CLOSE(sock);
|
||||
return CHIAKI_ERR_NETWORK;
|
||||
if(err == CHIAKI_ERR_CANCELED)
|
||||
{
|
||||
if(ctrl->should_stop)
|
||||
CHIAKI_LOGI(session->log, "Ctrl requested to stop while connecting");
|
||||
else
|
||||
CHIAKI_LOGE(session->log, "Ctrl notif pipe signaled without should_stop during connect");
|
||||
CHIAKI_SOCKET_CLOSE(sock);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHIAKI_LOGE(session->log, "Ctrl connect failed: %s", chiaki_error_string(err));
|
||||
ChiakiQuitReason quit_reason = err == CHIAKI_ERR_CONNECTION_REFUSED ? CHIAKI_QUIT_REASON_CTRL_CONNECTION_REFUSED : CHIAKI_QUIT_REASON_CTRL_UNKNOWN;
|
||||
ctrl_failed(ctrl, quit_reason);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
CHIAKI_LOGI(session->log, "Connected to %s:%d", session->connect_info.hostname, SESSION_CTRL_PORT);
|
||||
|
||||
CHIAKI_LOGI(session->log, "Ctrl connected to %s:%d", session->connect_info.hostname, SESSION_CTRL_PORT);
|
||||
|
||||
uint8_t auth_enc[CHIAKI_RPCRYPT_KEY_SIZE];
|
||||
ChiakiErrorCode err = chiaki_rpcrypt_encrypt(&session->rpcrypt, ctrl->crypt_counter_local++, (const uint8_t *)session->connect_info.regist_key, auth_enc, CHIAKI_RPCRYPT_KEY_SIZE);
|
||||
err = chiaki_rpcrypt_encrypt(&session->rpcrypt, ctrl->crypt_counter_local++, (const uint8_t *)session->connect_info.regist_key, auth_enc, CHIAKI_RPCRYPT_KEY_SIZE);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
goto error;
|
||||
char auth_b64[CHIAKI_RPCRYPT_KEY_SIZE*2];
|
||||
|
@ -245,7 +245,7 @@ static void *discovery_thread_func(void *user)
|
||||
|
||||
while(1)
|
||||
{
|
||||
ChiakiErrorCode err = chiaki_stop_pipe_select_single(&thread->stop_pipe, discovery->socket, UINT64_MAX);
|
||||
ChiakiErrorCode err = chiaki_stop_pipe_select_single(&thread->stop_pipe, discovery->socket, false, UINT64_MAX);
|
||||
if(err == CHIAKI_ERR_CANCELED)
|
||||
break;
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
|
@ -157,7 +157,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_recv_http_header(int sock, char *buf, size_
|
||||
{
|
||||
if(stop_pipe)
|
||||
{
|
||||
ChiakiErrorCode err = chiaki_stop_pipe_select_single(stop_pipe, sock, timeout_ms);
|
||||
ChiakiErrorCode err = chiaki_stop_pipe_select_single(stop_pipe, sock, false, timeout_ms);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
return err;
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ static ChiakiErrorCode regist_search(ChiakiRegist *regist, struct addrinfo *addr
|
||||
if(now_ms > timeout_abs_ms)
|
||||
err = CHIAKI_ERR_TIMEOUT;
|
||||
else
|
||||
err = chiaki_stop_pipe_select_single(®ist->stop_pipe, sock, timeout_abs_ms - now_ms);
|
||||
err = chiaki_stop_pipe_select_single(®ist->stop_pipe, sock, false, timeout_abs_ms - now_ms);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
if(err == CHIAKI_ERR_TIMEOUT)
|
||||
@ -551,7 +551,7 @@ static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, ChiakiRegister
|
||||
|
||||
while(buf_filled_size < content_size + header_size)
|
||||
{
|
||||
err = chiaki_stop_pipe_select_single(®ist->stop_pipe, sock, REGIST_REPONSE_TIMEOUT_MS);
|
||||
err = chiaki_stop_pipe_select_single(®ist->stop_pipe, sock, false, REGIST_REPONSE_TIMEOUT_MS);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
if(err == CHIAKI_ERR_TIMEOUT)
|
||||
|
@ -628,29 +628,36 @@ static bool session_thread_request_session(ChiakiSession *session, ChiakiRpVersi
|
||||
free(sa);
|
||||
continue;
|
||||
}
|
||||
r = connect(session_sock, sa, ai->ai_addrlen);
|
||||
if(r < 0)
|
||||
|
||||
ChiakiErrorCode err = chiaki_socket_set_nonblock(session_sock, true);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
CHIAKI_LOGE(session->log, "Failed to set session socket to non-blocking: %s", chiaki_error_string(err));
|
||||
|
||||
chiaki_mutex_unlock(&session->state_mutex);
|
||||
err = chiaki_stop_pipe_connect(&session->stop_pipe, session_sock, sa, ai->ai_addrlen);
|
||||
chiaki_mutex_lock(&session->state_mutex);
|
||||
if(err == CHIAKI_ERR_CANCELED)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int err = WSAGetLastError();
|
||||
CHIAKI_LOGE(session->log, "Session request connect failed: %u", err);
|
||||
if(err == WSAECONNREFUSED)
|
||||
CHIAKI_LOGI(session->log, "Session stopped while connecting for session request");
|
||||
session->quit_reason = CHIAKI_QUIT_REASON_STOPPED;
|
||||
CHIAKI_SOCKET_CLOSE(session_sock);
|
||||
session_sock = -1;
|
||||
free(sa);
|
||||
break;
|
||||
}
|
||||
else if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
CHIAKI_LOGE(session->log, "Session request connect failed: %s", chiaki_error_string(err));
|
||||
if(err == CHIAKI_ERR_CONNECTION_REFUSED)
|
||||
session->quit_reason = CHIAKI_QUIT_REASON_SESSION_REQUEST_CONNECTION_REFUSED;
|
||||
else
|
||||
session->quit_reason = CHIAKI_QUIT_REASON_NONE;
|
||||
#else
|
||||
int errsv = errno;
|
||||
CHIAKI_LOGE(session->log, "Session request connect failed: %s", strerror(errsv));
|
||||
if(errsv == ECONNREFUSED)
|
||||
session->quit_reason = CHIAKI_QUIT_REASON_SESSION_REQUEST_CONNECTION_REFUSED;
|
||||
else
|
||||
session->quit_reason = CHIAKI_QUIT_REASON_NONE;
|
||||
#endif
|
||||
CHIAKI_SOCKET_CLOSE(session_sock);
|
||||
session_sock = -1;
|
||||
free(sa);
|
||||
continue;
|
||||
}
|
||||
|
||||
free(sa);
|
||||
|
||||
session->connect_info.host_addrinfo_selected = ai;
|
||||
|
36
lib/src/sock.c
Normal file
36
lib/src/sock.c
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of Chiaki.
|
||||
*
|
||||
* Chiaki is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Chiaki is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Chiaki. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <chiaki/sock.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_socket_set_nonblock(chiaki_socket_t sock, bool nonblock)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
u_long nbio = nonblock ? 1 : 0;
|
||||
if(ioctlsocket(sock, FIONBIO, &nbio) != NO_ERROR)
|
||||
return CHIAKI_ERR_UNKNOWN;
|
||||
#else
|
||||
int flags = fcntl(sock, F_GETFL, 0);
|
||||
if(flags == -1)
|
||||
return CHIAKI_ERR_UNKNOWN;
|
||||
flags = nonblock ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK);
|
||||
if(fcntl(sock, F_SETFL, flags) == -1)
|
||||
return CHIAKI_ERR_UNKNOWN;
|
||||
#endif
|
||||
return CHIAKI_ERR_SUCCESS;
|
||||
}
|
@ -16,11 +16,12 @@
|
||||
*/
|
||||
|
||||
#include <chiaki/stoppipe.h>
|
||||
#include <chiaki/sock.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
@ -69,7 +70,7 @@ CHIAKI_EXPORT void chiaki_stop_pipe_stop(ChiakiStopPipe *stop_pipe)
|
||||
#endif
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, uint64_t timeout_ms)
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, bool write, uint64_t timeout_ms)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSAEVENT events[2];
|
||||
@ -82,7 +83,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto
|
||||
events[1] = WSACreateEvent();
|
||||
if(events[1] == WSA_INVALID_EVENT)
|
||||
return CHIAKI_ERR_UNKNOWN;
|
||||
WSAEventSelect(fd, events[1], FD_READ);
|
||||
WSAEventSelect(fd, events[1], write ? FD_WRITE : FD_READ);
|
||||
}
|
||||
|
||||
DWORD r = WSAWaitForMultipleEvents(events_count, events, FALSE, timeout_ms == UINT64_MAX ? WSA_INFINITE : (DWORD)timeout_ms, FALSE);
|
||||
@ -102,14 +103,17 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto
|
||||
return CHIAKI_ERR_UNKNOWN;
|
||||
}
|
||||
#else
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(stop_pipe->fds[0], &fds);
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(stop_pipe->fds[0], &rfds);
|
||||
|
||||
fd_set wfds;
|
||||
FD_ZERO(&wfds);
|
||||
|
||||
int nfds = stop_pipe->fds[0];
|
||||
if(fd >= 0)
|
||||
if(!CHIAKI_SOCKET_IS_INVALID(fd))
|
||||
{
|
||||
FD_SET(fd, &fds);
|
||||
FD_SET(fd, write ? &wfds : &rfds);
|
||||
if(fd > nfds)
|
||||
nfds = fd;
|
||||
}
|
||||
@ -124,20 +128,96 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto
|
||||
timeout = &timeout_s;
|
||||
}
|
||||
|
||||
int r = select(nfds, &fds, NULL, NULL, timeout);
|
||||
int r = select(nfds, &rfds, write ? &wfds : NULL, NULL, timeout);
|
||||
if(r < 0)
|
||||
return CHIAKI_ERR_UNKNOWN;
|
||||
|
||||
if(FD_ISSET(stop_pipe->fds[0], &fds))
|
||||
if(FD_ISSET(stop_pipe->fds[0], &rfds))
|
||||
return CHIAKI_ERR_CANCELED;
|
||||
|
||||
if(fd >= 0 && FD_ISSET(fd, &fds))
|
||||
if(!CHIAKI_SOCKET_IS_INVALID(fd) && FD_ISSET(fd, write ? &wfds : &rfds))
|
||||
return CHIAKI_ERR_SUCCESS;
|
||||
|
||||
return CHIAKI_ERR_TIMEOUT;
|
||||
#endif
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_connect(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, struct sockaddr *addr, size_t addrlen)
|
||||
{
|
||||
int r = connect(fd, addr, (socklen_t)addrlen);
|
||||
if(r >= 0)
|
||||
return CHIAKI_ERR_SUCCESS;
|
||||
|
||||
if(CHIAKI_SOCKET_EINPROGRESS)
|
||||
{
|
||||
ChiakiErrorCode err = chiaki_stop_pipe_select_single(stop_pipe, fd, true, UINT64_MAX);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
return err;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int err = WSAGetLastError();
|
||||
if(err == WSAECONNREFUSED)
|
||||
return CHIAKI_ERR_CONNECTION_REFUSED;
|
||||
else
|
||||
return CHIAKI_ERR_NETWORK;
|
||||
#else
|
||||
if(errno == ECONNREFUSED)
|
||||
return CHIAKI_ERR_CONNECTION_REFUSED;
|
||||
else
|
||||
return CHIAKI_ERR_NETWORK;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct sockaddr peer;
|
||||
socklen_t peerlen = sizeof(peer);
|
||||
if(getpeername(fd, &peer, &peerlen) == 0)
|
||||
return CHIAKI_ERR_SUCCESS;
|
||||
|
||||
if(errno != ENOTCONN)
|
||||
return CHIAKI_ERR_UNKNOWN;
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD sockerr;
|
||||
#else
|
||||
int sockerr;
|
||||
#endif
|
||||
socklen_t sockerr_sz = sizeof(sockerr);
|
||||
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &sockerr_sz) < 0)
|
||||
return CHIAKI_ERR_UNKNOWN;
|
||||
|
||||
#ifdef _WIN32
|
||||
switch(sockerr)
|
||||
{
|
||||
case WSAETIMEDOUT:
|
||||
return CHIAKI_ERR_TIMEOUT;
|
||||
case WSAECONNREFUSED:
|
||||
return CHIAKI_ERR_CONNECTION_REFUSED;
|
||||
case WSAEHOSTDOWN:
|
||||
return CHIAKI_ERR_HOST_DOWN;
|
||||
case WSAEHOSTUNREACH:
|
||||
return CHIAKI_ERR_HOST_UNREACH;
|
||||
default:
|
||||
return CHIAKI_ERR_UNKNOWN;
|
||||
}
|
||||
#else
|
||||
switch(sockerr)
|
||||
{
|
||||
case ETIMEDOUT:
|
||||
return CHIAKI_ERR_TIMEOUT;
|
||||
case ECONNREFUSED:
|
||||
return CHIAKI_ERR_CONNECTION_REFUSED;
|
||||
case EHOSTDOWN:
|
||||
return CHIAKI_ERR_HOST_DOWN;
|
||||
case EHOSTUNREACH:
|
||||
return CHIAKI_ERR_HOST_UNREACH;
|
||||
default:
|
||||
return CHIAKI_ERR_UNKNOWN;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_reset(ChiakiStopPipe *stop_pipe)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -757,7 +757,7 @@ beach:
|
||||
|
||||
static ChiakiErrorCode takion_recv(ChiakiTakion *takion, uint8_t *buf, size_t *buf_size, uint64_t timeout_ms)
|
||||
{
|
||||
ChiakiErrorCode err = chiaki_stop_pipe_select_single(&takion->stop_pipe, takion->sock, timeout_ms);
|
||||
ChiakiErrorCode err = chiaki_stop_pipe_select_single(&takion->stop_pipe, takion->sock, false, timeout_ms);
|
||||
if(err == CHIAKI_ERR_TIMEOUT || err == CHIAKI_ERR_CANCELED)
|
||||
return err;
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
|
@ -18,7 +18,7 @@
|
||||
#ifndef CHIAKI_UTILS_H
|
||||
#define CHIAKI_UTILS_H
|
||||
|
||||
#include <chiaki/common.h>
|
||||
#include <chiaki/sock.h>
|
||||
#include <chiaki/log.h>
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
|
Loading…
x
Reference in New Issue
Block a user