udp/tcp 비동기 통신은 현재 가능
This commit is contained in:
@@ -40,7 +40,7 @@ void IOCP::destruct() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void IOCP::registerSocket(IOCPPASSINDATA* data) {
|
||||
void IOCP::registerTCPSocket(IOCPPASSINDATA* data) {
|
||||
#ifdef _WIN32
|
||||
HANDLE returnData = ::CreateIoCompletionPort(
|
||||
(HANDLE)data->socket->sock, completionPort_, data->socket->sock, 0);
|
||||
@@ -50,20 +50,51 @@ void IOCP::registerSocket(IOCPPASSINDATA* data) {
|
||||
recv_data->event = IOCPEVENT::READ;
|
||||
recv_data->socket = data->socket;
|
||||
DWORD recvbytes = 0, flags = 0;
|
||||
int result = ::WSARecv(recv_data->socket->sock, &recv_data->wsabuf, 1,
|
||||
&recvbytes, &flags, &recv_data->overlapped, NULL);
|
||||
|
||||
int result = SOCKET_ERROR;
|
||||
|
||||
::WSARecv(recv_data->socket->sock, &recv_data->wsabuf, 1, &recvbytes, &flags,
|
||||
&recv_data->overlapped, NULL);
|
||||
if (result == SOCKET_ERROR) {
|
||||
int err = ::WSAGetLastError();
|
||||
if (err != WSA_IO_PENDING) {
|
||||
spdlog::error("WSARecv failed: {}", err);
|
||||
// 반드시 여기서 리턴하거나 처리해야 합니다.
|
||||
auto err_msg = std::format("WSARecv failed: {}", err);
|
||||
throw std::runtime_error(err_msg);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int IOCP::recv(IOCPPASSINDATA* data) { //읽은 바이트수가 무조건 100임? 왜..?
|
||||
void IOCP::registerUDPSocket(IOCPPASSINDATA* data, Address recv_addr) {
|
||||
#ifdef _WIN32
|
||||
HANDLE returnData = ::CreateIoCompletionPort(
|
||||
(HANDLE)data->socket->sock, completionPort_, data->socket->sock, 0);
|
||||
if (returnData == 0) completionPort_ = returnData;
|
||||
|
||||
IOCPPASSINDATA* recv_data = new IOCPPASSINDATA(data->bufsize);
|
||||
recv_data->event = IOCPEVENT::READ;
|
||||
recv_data->socket = data->socket;
|
||||
DWORD recvbytes = 0, flags = 0;
|
||||
|
||||
int result = SOCKET_ERROR;
|
||||
|
||||
::WSARecvFrom(recv_data->socket->sock, &recv_data->wsabuf, 1, &recvbytes,
|
||||
&flags, &recv_addr.addr, &recv_addr.length,
|
||||
&recv_data->overlapped, NULL);
|
||||
|
||||
if (result == SOCKET_ERROR) {
|
||||
int err = ::WSAGetLastError();
|
||||
if (err != WSA_IO_PENDING) {
|
||||
auto err_msg = std::format("WSARecv failed: {}", err);
|
||||
throw std::runtime_error(err_msg);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int IOCP::recv(IOCPPASSINDATA* data) { // 읽은 바이트수가 무조건 100임? 왜..?
|
||||
SOCKET sock = data->socket->sock;
|
||||
std::lock_guard lock(*GetRecvQueueMutex_(sock));
|
||||
auto queue = GetRecvQueue_(sock);
|
||||
@@ -148,14 +179,49 @@ void IOCP::iocpWatcher_(utils::ThreadPool* IOCPThread) {
|
||||
auto queue_list = GetRecvQueue_(data->socket->sock);
|
||||
if (data->event == IOCPEVENT::READ) {
|
||||
if (proto_ == SessionProtocol::TLS || proto_ == SessionProtocol::QUIC) {
|
||||
// DEBUG: BIO_write 전 OpenSSL 에러 스택 확인 (혹시 모를 이전 에러)
|
||||
ERR_print_errors_fp(stderr); // 이미 오류 스택에 뭔가 있는지 확인용
|
||||
fprintf(stderr, "--- Before BIO_write ---\n");
|
||||
|
||||
::BIO_write(::SSL_get_rbio(data->ssl.get()), data->wsabuf.buf,
|
||||
cbTransfrred);
|
||||
|
||||
// DEBUG: BIO_write 후 OpenSSL 에러 스택 확인 (BIO_write에서 에러 발생 시)
|
||||
ERR_print_errors_fp(stderr); // BIO_write에서도 에러가 발생할 수 있음
|
||||
fprintf(stderr, "--- After BIO_write, cbTransfrred: %lu ---\n",
|
||||
cbTransfrred);
|
||||
|
||||
while ((red_data = ::SSL_read(data->ssl.get(), buf.data(), buf.size())) >
|
||||
0) {
|
||||
queue_list->emplace_back(std::make_pair(
|
||||
std::vector<char>(buf.begin(), buf.begin() + red_data), 0));
|
||||
}
|
||||
if (red_data == -1) {
|
||||
auto ssl_error_code = SSL_get_error(
|
||||
data->ssl.get(), red_data); // 여기서 SSL_get_error 결과 저장
|
||||
auto err_msg = std::format("SSL_read failed with SSL_get_error: {}",
|
||||
ssl_error_code);
|
||||
fprintf(stderr, "%s\n", err_msg.c_str());
|
||||
|
||||
// *** 가장 중요한 부분: SSL_ERROR_SSL일 때 상세 에러를 강제로 출력 시도
|
||||
// ***
|
||||
if (ssl_error_code == SSL_ERROR_SSL) {
|
||||
fprintf(stderr, "Detailed SSL_ERROR_SSL trace:\n");
|
||||
unsigned long err_peek;
|
||||
// ERR_get_error()를 사용하여 스택의 모든 오류를 팝하고 출력
|
||||
while ((err_peek = ERR_get_error()) != 0) {
|
||||
char err_str[256];
|
||||
ERR_error_string_n(err_peek, err_str, sizeof(err_str));
|
||||
fprintf(stderr, "OpenSSL stack error: %s\n", err_str);
|
||||
}
|
||||
} else {
|
||||
// SSL_ERROR_SSL이 아닌 다른 오류 (SYSCALL, WANT_READ 등)일 경우
|
||||
// ERR_print_errors_fp는 여전히 유용할 수 있음
|
||||
ERR_print_errors_fp(stderr);
|
||||
}
|
||||
|
||||
throw std::runtime_error(err_msg); // 예외 발생
|
||||
}
|
||||
} else {
|
||||
::memcpy(buf.data(), data->wsabuf.buf, data->transferredbytes);
|
||||
queue_list->emplace_back(std::make_pair(
|
||||
@@ -230,7 +296,8 @@ void IOCP::packet_sender_(SOCKET sock) {
|
||||
int data_len = 0;
|
||||
|
||||
if (proto_ == SessionProtocol::TLS || proto_ == SessionProtocol::QUIC) {
|
||||
int ret = ::SSL_write(front->ssl.get(), front->wsabuf.buf, front->wsabuf.len);
|
||||
int ret =
|
||||
::SSL_write(front->ssl.get(), front->wsabuf.buf, front->wsabuf.len);
|
||||
if (ret <= 0) {
|
||||
int err = ::SSL_get_error(front->ssl.get(), ret);
|
||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
|
||||
@@ -242,7 +309,8 @@ void IOCP::packet_sender_(SOCKET sock) {
|
||||
break;
|
||||
}
|
||||
|
||||
while ((data_len = ::BIO_read(::SSL_get_wbio(front->ssl.get()), buf.data(), buf.size())) > 0) {
|
||||
while ((data_len = ::BIO_read(::SSL_get_wbio(front->ssl.get()),
|
||||
buf.data(), buf.size())) > 0) {
|
||||
wsabuf.buf = buf.data();
|
||||
wsabuf.len = data_len;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ int Socket::init(int domain, int type, int protocol) {
|
||||
this->domain = domain;
|
||||
|
||||
sock = ::socket(domain, type, protocol);
|
||||
// sock = ::WSASocket(domain, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
|
||||
if (sock == INVALID_SOCKET) spdlog::critical("socket()");
|
||||
|
||||
valid_ = true;
|
||||
@@ -65,6 +66,26 @@ int Socket::bind(Address __addr) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int Socket::connect(Address& serveraddr) {
|
||||
std::string addr_string = serveraddr;
|
||||
int retVal = -1;
|
||||
if (serveraddr.family == AF_INET)
|
||||
retVal = ::connect(sock, (const sockaddr*)&serveraddr.addr_in,
|
||||
serveraddr.length);
|
||||
else
|
||||
retVal = ::connect(sock, (const sockaddr*)&serveraddr.addr_in6,
|
||||
serveraddr.length);
|
||||
memcpy(&remoteAddr, &serveraddr, sizeof(Address));
|
||||
if (retVal == INVALID_SOCKET) {
|
||||
#ifdef _WIN32
|
||||
int err = WSAGetLastError();
|
||||
spdlog::error("connect() failed: WSA error {} (0x{:X})", err, err);
|
||||
#endif
|
||||
spdlog::error("connect()");
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int Socket::recvfrom(void* __restrict __buf, size_t __n, int __flags,
|
||||
struct Address& __addr) {
|
||||
std::lock_guard<std::mutex> lock(readMutex);
|
||||
|
||||
@@ -4,4 +4,24 @@ namespace Network {
|
||||
|
||||
int UDPSocket::init(int domain) { return init(domain, SOCK_DGRAM, 0); }
|
||||
|
||||
int UDPSocket::connect(Address &serveraddr) {
|
||||
std::string addr_string = serveraddr;
|
||||
int retVal = -1;
|
||||
if (serveraddr.family == AF_INET)
|
||||
retVal = ::connect(sock, (const sockaddr *)&serveraddr.addr_in,
|
||||
serveraddr.length);
|
||||
else
|
||||
retVal = ::connect(sock, (const sockaddr *)&serveraddr.addr_in6,
|
||||
serveraddr.length);
|
||||
memcpy(&remoteAddr, &serveraddr, sizeof(Address));
|
||||
if (retVal == INVALID_SOCKET) {
|
||||
#ifdef _WIN32
|
||||
int err = WSAGetLastError();
|
||||
spdlog::error("connect() failed: WSA error {} (0x{:X})", err, err);
|
||||
#endif
|
||||
spdlog::error("connect()");
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
} // namespace Network
|
||||
|
||||
Reference in New Issue
Block a user