diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 663ba69..cfb2c04 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -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 diff --git a/lib/include/chiaki/common.h b/lib/include/chiaki/common.h index f0cd66d..c521ecf 100644 --- a/lib/include/chiaki/common.h +++ b/lib/include/chiaki/common.h @@ -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, diff --git a/lib/include/chiaki/sock.h b/lib/include/chiaki/sock.h new file mode 100644 index 0000000..c675b8c --- /dev/null +++ b/lib/include/chiaki/sock.h @@ -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 diff --git a/lib/include/chiaki/stoppipe.h b/lib/include/chiaki/stoppipe.h index b5d93b3..229995e 100644 --- a/lib/include/chiaki/stoppipe.h +++ b/lib/include/chiaki/stoppipe.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 diff --git a/lib/include/chiaki/takion.h b/lib/include/chiaki/takion.h index 1b29bda..b242769 100644 --- a/lib/include/chiaki/takion.h +++ b/lib/include/chiaki/takion.h @@ -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); diff --git a/lib/src/common.c b/lib/src/common.c index 5808039..824ed13 100644 --- a/lib/src/common.c +++ b/lib/src/common.c @@ -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: diff --git a/lib/src/ctrl.c b/lib/src/ctrl.c index f1fdece..9c3fae7 100644 --- a/lib/src/ctrl.c +++ b/lib/src/ctrl.c @@ -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]; diff --git a/lib/src/discovery.c b/lib/src/discovery.c index 6ab20c1..e2d5205 100644 --- a/lib/src/discovery.c +++ b/lib/src/discovery.c @@ -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) diff --git a/lib/src/http.c b/lib/src/http.c index 7e9d000..50c86fe 100644 --- a/lib/src/http.c +++ b/lib/src/http.c @@ -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; } diff --git a/lib/src/regist.c b/lib/src/regist.c index 16a4f62..947b713 100644 --- a/lib/src/regist.c +++ b/lib/src/regist.c @@ -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) diff --git a/lib/src/session.c b/lib/src/session.c index d37bae0..db86c70 100644 --- a/lib/src/session.c +++ b/lib/src/session.c @@ -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; diff --git a/lib/src/sock.c b/lib/src/sock.c new file mode 100644 index 0000000..f8d224e --- /dev/null +++ b/lib/src/sock.c @@ -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; +} \ No newline at end of file diff --git a/lib/src/stoppipe.c b/lib/src/stoppipe.c index 0180751..cb90309 100644 --- a/lib/src/stoppipe.c +++ b/lib/src/stoppipe.c @@ -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 diff --git a/lib/src/takion.c b/lib/src/takion.c index bdba21a..e992cc7 100644 --- a/lib/src/takion.c +++ b/lib/src/takion.c @@ -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) diff --git a/lib/src/utils.h b/lib/src/utils.h index a88208f..0bd86a7 100644 --- a/lib/src/utils.h +++ b/lib/src/utils.h @@ -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>