mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-19 21:13:12 -07:00
Non-blocking connect
This commit is contained in:
parent
e2fc84e0e6
commit
042e698749
15 changed files with 266 additions and 72 deletions
|
@ -2,6 +2,7 @@
|
||||||
set(HEADER_FILES
|
set(HEADER_FILES
|
||||||
include/chiaki/session.h
|
include/chiaki/session.h
|
||||||
include/chiaki/common.h
|
include/chiaki/common.h
|
||||||
|
include/chiaki/sock.h
|
||||||
include/chiaki/thread.h
|
include/chiaki/thread.h
|
||||||
include/chiaki/base64.h
|
include/chiaki/base64.h
|
||||||
include/chiaki/http.h
|
include/chiaki/http.h
|
||||||
|
@ -37,6 +38,7 @@ set(HEADER_FILES
|
||||||
|
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
src/common.c
|
src/common.c
|
||||||
|
src/sock.c
|
||||||
src/session.c
|
src/session.c
|
||||||
src/thread.c
|
src/thread.c
|
||||||
src/base64.c
|
src/base64.c
|
||||||
|
|
|
@ -18,27 +18,14 @@
|
||||||
#ifndef CHIAKI_COMMON_H
|
#ifndef CHIAKI_COMMON_H
|
||||||
#define CHIAKI_COMMON_H
|
#define CHIAKI_COMMON_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#ifdef _WIN32
|
#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
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#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
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,6 +43,9 @@ typedef enum
|
||||||
CHIAKI_ERR_MEMORY,
|
CHIAKI_ERR_MEMORY,
|
||||||
CHIAKI_ERR_OVERFLOW,
|
CHIAKI_ERR_OVERFLOW,
|
||||||
CHIAKI_ERR_NETWORK,
|
CHIAKI_ERR_NETWORK,
|
||||||
|
CHIAKI_ERR_CONNECTION_REFUSED,
|
||||||
|
CHIAKI_ERR_HOST_DOWN,
|
||||||
|
CHIAKI_ERR_HOST_UNREACH,
|
||||||
CHIAKI_ERR_DISCONNECTED,
|
CHIAKI_ERR_DISCONNECTED,
|
||||||
CHIAKI_ERR_INVALID_DATA,
|
CHIAKI_ERR_INVALID_DATA,
|
||||||
CHIAKI_ERR_BUF_TOO_SMALL,
|
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
|
#ifndef CHIAKI_STOPPIPE_H
|
||||||
#define CHIAKI_STOPPIPE_H
|
#define CHIAKI_STOPPIPE_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "sock.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
@ -40,11 +41,17 @@ typedef struct chiaki_stop_pipe_t
|
||||||
#endif
|
#endif
|
||||||
} ChiakiStopPipe;
|
} ChiakiStopPipe;
|
||||||
|
|
||||||
|
struct sockaddr;
|
||||||
|
|
||||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_init(ChiakiStopPipe *stop_pipe);
|
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_fini(ChiakiStopPipe *stop_pipe);
|
||||||
CHIAKI_EXPORT void chiaki_stop_pipe_stop(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);
|
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *stop_pipe, chiaki_socket_t fd, bool write, 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); }
|
/**
|
||||||
|
* 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);
|
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_reset(ChiakiStopPipe *stop_pipe);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -213,7 +213,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send(ChiakiTakion *takion, uint8_t *
|
||||||
/**
|
/**
|
||||||
* Thread-safe while Takion is running.
|
* 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);
|
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";
|
return "Memory error";
|
||||||
case CHIAKI_ERR_NETWORK:
|
case CHIAKI_ERR_NETWORK:
|
||||||
return "Network error";
|
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:
|
case CHIAKI_ERR_DISCONNECTED:
|
||||||
return "Disconnected";
|
return "Disconnected";
|
||||||
case CHIAKI_ERR_INVALID_DATA:
|
case CHIAKI_ERR_INVALID_DATA:
|
||||||
|
|
|
@ -151,18 +151,19 @@ static void *ctrl_thread_func(void *user)
|
||||||
{
|
{
|
||||||
ChiakiCtrl *ctrl = 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)
|
if(err != CHIAKI_ERR_SUCCESS)
|
||||||
{
|
{
|
||||||
ctrl_failed(ctrl, CHIAKI_QUIT_REASON_CTRL_CONNECT_FAILED);
|
ctrl_failed(ctrl, CHIAKI_QUIT_REASON_CTRL_CONNECT_FAILED);
|
||||||
|
chiaki_mutex_unlock(&ctrl->notif_mutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHIAKI_LOGI(ctrl->session->log, "Ctrl connected");
|
CHIAKI_LOGI(ctrl->session->log, "Ctrl connected");
|
||||||
|
|
||||||
err = chiaki_mutex_lock(&ctrl->notif_mutex);
|
|
||||||
assert(err == CHIAKI_ERR_SUCCESS);
|
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
bool overflow = false;
|
bool overflow = false;
|
||||||
|
@ -197,7 +198,7 @@ static void *ctrl_thread_func(void *user)
|
||||||
}
|
}
|
||||||
|
|
||||||
chiaki_mutex_unlock(&ctrl->notif_mutex);
|
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);
|
chiaki_mutex_lock(&ctrl->notif_mutex);
|
||||||
if(err == CHIAKI_ERR_CANCELED)
|
if(err == CHIAKI_ERR_CANCELED)
|
||||||
{
|
{
|
||||||
|
@ -511,29 +512,38 @@ static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl)
|
||||||
return CHIAKI_ERR_NETWORK;
|
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);
|
free(sa);
|
||||||
if(r < 0)
|
if(err != CHIAKI_ERR_SUCCESS)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
if(err == CHIAKI_ERR_CANCELED)
|
||||||
int errsv = WSAGetLastError();
|
{
|
||||||
CHIAKI_LOGE(session->log, "Ctrl connect failed: %d", errsv);
|
if(ctrl->should_stop)
|
||||||
ChiakiQuitReason quit_reason = errsv == WSAECONNREFUSED ? CHIAKI_QUIT_REASON_CTRL_CONNECTION_REFUSED : CHIAKI_QUIT_REASON_CTRL_UNKNOWN;
|
CHIAKI_LOGI(session->log, "Ctrl requested to stop while connecting");
|
||||||
#else
|
else
|
||||||
int errsv = errno;
|
CHIAKI_LOGE(session->log, "Ctrl notif pipe signaled without should_stop during connect");
|
||||||
CHIAKI_LOGE(session->log, "Ctrl connect failed: %s", strerror(errsv));
|
CHIAKI_SOCKET_CLOSE(sock);
|
||||||
ChiakiQuitReason quit_reason = errsv == ECONNREFUSED ? CHIAKI_QUIT_REASON_CTRL_CONNECTION_REFUSED : CHIAKI_QUIT_REASON_CTRL_UNKNOWN;
|
}
|
||||||
#endif
|
else
|
||||||
ctrl_failed(ctrl, quit_reason);
|
{
|
||||||
CHIAKI_SOCKET_CLOSE(sock);
|
CHIAKI_LOGE(session->log, "Ctrl connect failed: %s", chiaki_error_string(err));
|
||||||
return CHIAKI_ERR_NETWORK;
|
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];
|
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)
|
if(err != CHIAKI_ERR_SUCCESS)
|
||||||
goto error;
|
goto error;
|
||||||
char auth_b64[CHIAKI_RPCRYPT_KEY_SIZE*2];
|
char auth_b64[CHIAKI_RPCRYPT_KEY_SIZE*2];
|
||||||
|
|
|
@ -245,7 +245,7 @@ static void *discovery_thread_func(void *user)
|
||||||
|
|
||||||
while(1)
|
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)
|
if(err == CHIAKI_ERR_CANCELED)
|
||||||
break;
|
break;
|
||||||
if(err != CHIAKI_ERR_SUCCESS)
|
if(err != CHIAKI_ERR_SUCCESS)
|
||||||
|
|
|
@ -157,7 +157,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_recv_http_header(int sock, char *buf, size_
|
||||||
{
|
{
|
||||||
if(stop_pipe)
|
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)
|
if(err != CHIAKI_ERR_SUCCESS)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,7 +349,7 @@ static ChiakiErrorCode regist_search(ChiakiRegist *regist, struct addrinfo *addr
|
||||||
if(now_ms > timeout_abs_ms)
|
if(now_ms > timeout_abs_ms)
|
||||||
err = CHIAKI_ERR_TIMEOUT;
|
err = CHIAKI_ERR_TIMEOUT;
|
||||||
else
|
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_SUCCESS)
|
||||||
{
|
{
|
||||||
if(err == CHIAKI_ERR_TIMEOUT)
|
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)
|
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_SUCCESS)
|
||||||
{
|
{
|
||||||
if(err == CHIAKI_ERR_TIMEOUT)
|
if(err == CHIAKI_ERR_TIMEOUT)
|
||||||
|
|
|
@ -628,29 +628,36 @@ static bool session_thread_request_session(ChiakiSession *session, ChiakiRpVersi
|
||||||
free(sa);
|
free(sa);
|
||||||
continue;
|
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
|
CHIAKI_LOGI(session->log, "Session stopped while connecting for session request");
|
||||||
int err = WSAGetLastError();
|
session->quit_reason = CHIAKI_QUIT_REASON_STOPPED;
|
||||||
CHIAKI_LOGE(session->log, "Session request connect failed: %u", err);
|
CHIAKI_SOCKET_CLOSE(session_sock);
|
||||||
if(err == WSAECONNREFUSED)
|
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;
|
session->quit_reason = CHIAKI_QUIT_REASON_SESSION_REQUEST_CONNECTION_REFUSED;
|
||||||
else
|
else
|
||||||
session->quit_reason = CHIAKI_QUIT_REASON_NONE;
|
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);
|
CHIAKI_SOCKET_CLOSE(session_sock);
|
||||||
session_sock = -1;
|
session_sock = -1;
|
||||||
free(sa);
|
free(sa);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(sa);
|
free(sa);
|
||||||
|
|
||||||
session->connect_info.host_addrinfo_selected = ai;
|
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/stoppipe.h>
|
||||||
|
#include <chiaki/sock.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <winsock2.h>
|
#include <ws2tcpip.h>
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -69,7 +70,7 @@ CHIAKI_EXPORT void chiaki_stop_pipe_stop(ChiakiStopPipe *stop_pipe)
|
||||||
#endif
|
#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
|
#ifdef _WIN32
|
||||||
WSAEVENT events[2];
|
WSAEVENT events[2];
|
||||||
|
@ -82,7 +83,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto
|
||||||
events[1] = WSACreateEvent();
|
events[1] = WSACreateEvent();
|
||||||
if(events[1] == WSA_INVALID_EVENT)
|
if(events[1] == WSA_INVALID_EVENT)
|
||||||
return CHIAKI_ERR_UNKNOWN;
|
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);
|
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;
|
return CHIAKI_ERR_UNKNOWN;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
fd_set fds;
|
fd_set rfds;
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&rfds);
|
||||||
FD_SET(stop_pipe->fds[0], &fds);
|
FD_SET(stop_pipe->fds[0], &rfds);
|
||||||
|
|
||||||
|
fd_set wfds;
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
|
||||||
int nfds = stop_pipe->fds[0];
|
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)
|
if(fd > nfds)
|
||||||
nfds = fd;
|
nfds = fd;
|
||||||
}
|
}
|
||||||
|
@ -124,20 +128,96 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto
|
||||||
timeout = &timeout_s;
|
timeout = &timeout_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int r = select(nfds, &fds, NULL, NULL, timeout);
|
int r = select(nfds, &rfds, write ? &wfds : NULL, NULL, timeout);
|
||||||
if(r < 0)
|
if(r < 0)
|
||||||
return CHIAKI_ERR_UNKNOWN;
|
return CHIAKI_ERR_UNKNOWN;
|
||||||
|
|
||||||
if(FD_ISSET(stop_pipe->fds[0], &fds))
|
if(FD_ISSET(stop_pipe->fds[0], &rfds))
|
||||||
return CHIAKI_ERR_CANCELED;
|
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_SUCCESS;
|
||||||
|
|
||||||
return CHIAKI_ERR_TIMEOUT;
|
return CHIAKI_ERR_TIMEOUT;
|
||||||
#endif
|
#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)
|
CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_reset(ChiakiStopPipe *stop_pipe)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
|
@ -757,7 +757,7 @@ beach:
|
||||||
|
|
||||||
static ChiakiErrorCode takion_recv(ChiakiTakion *takion, uint8_t *buf, size_t *buf_size, uint64_t timeout_ms)
|
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)
|
if(err == CHIAKI_ERR_TIMEOUT || err == CHIAKI_ERR_CANCELED)
|
||||||
return err;
|
return err;
|
||||||
if(err != CHIAKI_ERR_SUCCESS)
|
if(err != CHIAKI_ERR_SUCCESS)
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#ifndef CHIAKI_UTILS_H
|
#ifndef CHIAKI_UTILS_H
|
||||||
#define CHIAKI_UTILS_H
|
#define CHIAKI_UTILS_H
|
||||||
|
|
||||||
#include <chiaki/common.h>
|
#include <chiaki/sock.h>
|
||||||
#include <chiaki/log.h>
|
#include <chiaki/log.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue