mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-24 11:49:05 +02:00
Merge pull request #13392 from ANR2ME/adhoc_socket
Ignore SIGPIPE error on certain system (ie. Linux)
This commit is contained in:
4 files changed
+71
-31
No files matched your search
+18
-4
@@ -30,6 +30,11 @@
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
// Default value to 0x00 (do nothing) in systems where it's not supported.
|
||||
#define MSG_NOSIGNAL 0x00
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "i18n/i18n.h"
|
||||
@@ -1203,7 +1208,7 @@ void sendChat(std::string chatString) {
|
||||
strcpy(chat.message, message.c_str());
|
||||
//Send Chat Messages
|
||||
if (IsSocketReady(metasocket, false, true) > 0) {
|
||||
int chatResult = send(metasocket, (const char*)&chat, sizeof(chat), 0);
|
||||
int chatResult = send(metasocket, (const char*)&chat, sizeof(chat), MSG_NOSIGNAL);
|
||||
NOTICE_LOG(SCENET, "Send Chat %s to Adhoc Server", chat.message);
|
||||
name = g_Config.sNickName.c_str();
|
||||
chatLog.push_back(name.substr(0, 8) + ": " + chat.message);
|
||||
@@ -1283,7 +1288,7 @@ int friendFinder(){
|
||||
|
||||
// Send Ping to Server, may failed with socket error 10054/10053 if someone else with the same IP already connected to AdHoc Server (the server might need to be modified to differentiate MAC instead of IP)
|
||||
if (IsSocketReady(metasocket, false, true) > 0) {
|
||||
int iResult = send(metasocket, (const char*)&opcode, 1, 0);
|
||||
int iResult = send(metasocket, (const char*)&opcode, 1, MSG_NOSIGNAL);
|
||||
int error = errno;
|
||||
// KHBBS seems to be getting error 10053 often
|
||||
if (iResult == SOCKET_ERROR) {
|
||||
@@ -1306,7 +1311,7 @@ int friendFinder(){
|
||||
|
||||
// Check for Incoming Data
|
||||
if (IsSocketReady(metasocket, true, false) > 0) {
|
||||
int received = recv(metasocket, (char*)(rx + rxpos), sizeof(rx) - rxpos, 0);
|
||||
int received = recv(metasocket, (char*)(rx + rxpos), sizeof(rx) - rxpos, MSG_NOSIGNAL);
|
||||
|
||||
// Free Network Lock
|
||||
//_freeNetworkLock();
|
||||
@@ -1807,6 +1812,15 @@ int setSockNoDelay(int tcpsock, int flag) {
|
||||
return setsockopt(tcpsock, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt));
|
||||
}
|
||||
|
||||
int setSockNoSIGPIPE(int sock, int flag) {
|
||||
// Set SIGPIPE when supported (ie. BSD/MacOS X)
|
||||
int opt = flag;
|
||||
#if defined(SO_NOSIGPIPE)
|
||||
return setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&opt, sizeof(opt));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if !defined(TCP_KEEPIDLE)
|
||||
#define TCP_KEEPIDLE TCP_KEEPALIVE //TCP_KEEPIDLE on Linux is equivalent to TCP_KEEPALIVE on macOS
|
||||
#endif
|
||||
@@ -1978,7 +1992,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
|
||||
memcpy(packet.game.data, adhoc_id->data, ADHOCCTL_ADHOCID_LEN);
|
||||
|
||||
IsSocketReady(metasocket, false, true, nullptr, adhocDefaultTimeout * 1000);
|
||||
int sent = send(metasocket, (char*)&packet, sizeof(packet), 0);
|
||||
int sent = send(metasocket, (char*)&packet, sizeof(packet), MSG_NOSIGNAL);
|
||||
if (sent > 0) {
|
||||
socklen_t addrLen = sizeof(LocalIP);
|
||||
memset(&LocalIP, 0, addrLen);
|
||||
|
||||
@@ -1240,6 +1240,11 @@ int getSockNoDelay(int tcpsock);
|
||||
*/
|
||||
int setSockNoDelay(int tcpsock, int flag);
|
||||
|
||||
/*
|
||||
* Set Socket SO_NOSIGPIPE when supported
|
||||
*/
|
||||
int setSockNoSIGPIPE(int sock, int flag);
|
||||
|
||||
/*
|
||||
* Set Socket KeepAlive (opt = SO_KEEPALIVE)
|
||||
*/
|
||||
|
||||
@@ -44,6 +44,11 @@
|
||||
#include <errno.h>
|
||||
//#include <sqlite3.h>
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
// Default value to 0x00 (do nothing) in systems where it's not supported.
|
||||
#define MSG_NOSIGNAL 0x00
|
||||
#endif
|
||||
|
||||
#include "i18n/i18n.h"
|
||||
#include "thread/threadutil.h"
|
||||
|
||||
@@ -848,7 +853,7 @@ void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group
|
||||
packet.ip = user->resolver.ip;
|
||||
|
||||
// Send Data
|
||||
int iResult = send(peer->stream, (const char*)&packet, sizeof(packet), 0);
|
||||
int iResult = send(peer->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
|
||||
if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: connect_user[send peer] (Socket error %d)", errno);
|
||||
|
||||
// Set Player Name
|
||||
@@ -861,7 +866,7 @@ void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group
|
||||
packet.ip = peer->resolver.ip;
|
||||
|
||||
// Send Data
|
||||
iResult = send(user->stream, (const char*)&packet, sizeof(packet), 0);
|
||||
iResult = send(user->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
|
||||
if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: connect_user[send user] (Socket error %d)", errno);
|
||||
|
||||
// Set BSSID
|
||||
@@ -883,7 +888,7 @@ void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group
|
||||
g->playercount++;
|
||||
|
||||
// Send Network BSSID to User
|
||||
int iResult = send(user->stream, (const char*)&bssid, sizeof(bssid), 0);
|
||||
int iResult = send(user->stream, (const char*)&bssid, sizeof(bssid), MSG_NOSIGNAL);
|
||||
if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: connect_user[send user bssid] (Socket error %d)", errno);
|
||||
|
||||
// Notify User
|
||||
@@ -975,7 +980,7 @@ void disconnect_user(SceNetAdhocctlUserNode * user)
|
||||
packet.ip = user->resolver.ip;
|
||||
|
||||
// Send Data
|
||||
int iResult = send(peer->stream, (const char*)&packet, sizeof(packet), 0);
|
||||
int iResult = send(peer->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
|
||||
if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: disconnect_user[send peer] (Socket error %d)", errno);
|
||||
|
||||
// Move Pointer
|
||||
@@ -1074,13 +1079,13 @@ void send_scan_results(SceNetAdhocctlUserNode * user)
|
||||
}
|
||||
|
||||
// Send Group Packet
|
||||
int iResult = send(user->stream, (const char*)&packet, sizeof(packet), 0);
|
||||
int iResult = send(user->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
|
||||
if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: send_scan_result[send user] (Socket error %d)", errno);
|
||||
}
|
||||
|
||||
// Notify Player of End of Scan
|
||||
uint8_t opcode = OPCODE_SCAN_COMPLETE;
|
||||
int iResult = send(user->stream, (const char*)&opcode, 1, 0);
|
||||
int iResult = send(user->stream, (const char*)&opcode, 1, MSG_NOSIGNAL);
|
||||
if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: send_scan_result[send peer complete] (Socket error %d)", errno);
|
||||
|
||||
// Notify User
|
||||
@@ -1139,7 +1144,7 @@ void spread_message(SceNetAdhocctlUserNode *user, const char *message)
|
||||
strcpy(packet.base.message, message);
|
||||
|
||||
// Send Data
|
||||
int iResult = send(user->stream, (const char*)&packet, sizeof(packet), 0);
|
||||
int iResult = send(user->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
|
||||
if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: spread_message[send user chat] (Socket error %d)", errno);
|
||||
}
|
||||
}
|
||||
@@ -1181,7 +1186,7 @@ void spread_message(SceNetAdhocctlUserNode *user, const char *message)
|
||||
packet.name = user->resolver.name;
|
||||
|
||||
// Send Data
|
||||
int iResult = send(peer->stream, (const char*)&packet, sizeof(packet), 0);
|
||||
int iResult = send(peer->stream, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
|
||||
if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: spread_message[send peer chat] (Socket error %d)", errno);
|
||||
|
||||
// Move Pointer
|
||||
@@ -1930,7 +1935,7 @@ int server_loop(int server)
|
||||
SceNetAdhocctlUserNode * next = user->next;
|
||||
|
||||
// Receive Data from User
|
||||
int recvresult = recv(user->stream, (char*)user->rx + user->rxpos, sizeof(user->rx) - user->rxpos, 0);
|
||||
int recvresult = recv(user->stream, (char*)user->rx + user->rxpos, sizeof(user->rx) - user->rxpos, MSG_NOSIGNAL);
|
||||
|
||||
// Connection Closed or Timed Out
|
||||
if(recvresult == 0 || (recvresult == -1 && errno != EAGAIN && errno != EWOULDBLOCK) || get_user_state(user) == USER_STATE_TIMED_OUT)
|
||||
|
||||
+34
-18
@@ -23,6 +23,11 @@
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
// Default value to 0x00 (do nothing) in systems where it's not supported.
|
||||
#define MSG_NOSIGNAL 0x00
|
||||
#endif
|
||||
|
||||
#include <mutex>
|
||||
#include "thread/threadutil.h"
|
||||
// sceNetAdhoc
|
||||
@@ -160,7 +165,7 @@ static void __AdhocctlNotify(u64 userdata, int cyclesLate) {
|
||||
// Send Packet if it wasn't succesfully sent before
|
||||
if (len > 0) {
|
||||
if (IsSocketReady(metasocket, false, true) > 0) {
|
||||
int ret = send(metasocket, (const char*)&packet, len, 0);
|
||||
int ret = send(metasocket, (const char*)&packet, len, MSG_NOSIGNAL);
|
||||
int sockerr = errno;
|
||||
|
||||
if (ret > 0 || (ret == SOCKET_ERROR && sockerr != EAGAIN && sockerr != EWOULDBLOCK)) {
|
||||
@@ -223,12 +228,12 @@ int DoBlockingPdpRecv(int uid, AdhocSocketRequest& req, s64& result) {
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
socklen_t sinlen = sizeof(sin);
|
||||
|
||||
int ret = recvfrom(uid, (char*)req.buffer, *req.length, MSG_PEEK, (sockaddr*)&sin, &sinlen);
|
||||
int ret = recvfrom(uid, (char*)req.buffer, *req.length, MSG_PEEK | MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen);
|
||||
int sockerr = errno;
|
||||
|
||||
// Note: UDP must not be received partially, otherwise leftover data in socket's buffer will be discarded
|
||||
if (ret >= 0 && ret <= *req.length) {
|
||||
ret = recvfrom(uid, (char*)req.buffer, *req.length, 0, (sockaddr*)&sin, &sinlen);
|
||||
ret = recvfrom(uid, (char*)req.buffer, *req.length, MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen);
|
||||
// UDP can also receives 0 data, while on TCP receiving 0 data = connection gracefully closed, but not sure whether PDP can send/recv 0 data or not tho
|
||||
if (ret > 0) {
|
||||
DEBUG_LOG(SCENET, "sceNetAdhocPdpRecv[%i:%u]: Received %u bytes from %s:%u\n", req.id, getLocalPort(uid), ret, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
|
||||
@@ -292,7 +297,7 @@ int DoBlockingPdpSend(int uid, AdhocSocketRequest& req, s64& result, AdhocSendTa
|
||||
target.sin_addr.s_addr = peer->ip;
|
||||
target.sin_port = htons(peer->port + ((isOriPort && !isPrivateIP(peer->ip)) ? 0 : portOffset));
|
||||
|
||||
int ret = sendto(pdpsocket->id, (const char*)req.buffer, targetPeers.length, 0, (sockaddr*)&target, sizeof(target));
|
||||
int ret = sendto(pdpsocket->id, (const char*)req.buffer, targetPeers.length, MSG_NOSIGNAL, (sockaddr*)&target, sizeof(target));
|
||||
int sockerr = errno;
|
||||
|
||||
if (ret >= 0) {
|
||||
@@ -327,7 +332,7 @@ int DoBlockingPtpSend(int uid, AdhocSocketRequest& req, s64& result) {
|
||||
auto ptpsocket = ptp[req.id - 1];
|
||||
|
||||
// Send Data
|
||||
int ret = send(uid, (const char*)req.buffer, *req.length, 0);
|
||||
int ret = send(uid, (const char*)req.buffer, *req.length, MSG_NOSIGNAL);
|
||||
int sockerr = errno;
|
||||
|
||||
// Success
|
||||
@@ -367,7 +372,7 @@ int DoBlockingPtpSend(int uid, AdhocSocketRequest& req, s64& result) {
|
||||
int DoBlockingPtpRecv(int uid, AdhocSocketRequest& req, s64& result) {
|
||||
auto ptpsocket = ptp[req.id - 1];
|
||||
|
||||
int ret = recv(uid, (char*)req.buffer, *req.length, 0);
|
||||
int ret = recv(uid, (char*)req.buffer, *req.length, MSG_NOSIGNAL);
|
||||
int sockerr = errno;
|
||||
|
||||
// Received Data
|
||||
@@ -869,9 +874,11 @@ static int sceNetAdhocPdpCreate(const char *mac, int port, int bufferSize, u32 u
|
||||
// Enable KeepAlive
|
||||
setSockKeepAlive(usocket, true);
|
||||
|
||||
// Ignore SIGPIPE when supported (ie. BSD/MacOS)
|
||||
setSockNoSIGPIPE(usocket, 1);
|
||||
|
||||
// Enable Port Re-use, this will allow binding to an already used port, but only one of them can read the data (shared receive buffer?)
|
||||
int one = 1;
|
||||
setsockopt(usocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one)); // NO idea if we need this
|
||||
setsockopt(usocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one));
|
||||
|
||||
// Binding Information for local Port
|
||||
sockaddr_in addr;
|
||||
@@ -1062,7 +1069,7 @@ static int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int
|
||||
//_acquireNetworkLock();
|
||||
|
||||
// Send Data. UDP are guaranteed to be sent as a whole or nothing(failed if len > SO_MAX_MSG_SIZE), and never be partially sent/recv
|
||||
int sent = sendto(socket->id, (const char *)data, len, 0, (sockaddr *)&target, sizeof(target));
|
||||
int sent = sendto(socket->id, (const char *)data, len, MSG_NOSIGNAL, (sockaddr *)&target, sizeof(target));
|
||||
int error = errno;
|
||||
|
||||
if (sent == SOCKET_ERROR) {
|
||||
@@ -1159,7 +1166,7 @@ static int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int
|
||||
target.sin_addr.s_addr = peer.ip;
|
||||
target.sin_port = htons(dport + ((isOriPort && !isPrivateIP(peer.ip)) ? 0 : portOffset));
|
||||
|
||||
int sent = sendto(socket->id, (const char*)data, len, 0, (sockaddr*)&target, sizeof(target));
|
||||
int sent = sendto(socket->id, (const char*)data, len, MSG_NOSIGNAL, (sockaddr*)&target, sizeof(target));
|
||||
int error = errno;
|
||||
if (sent == SOCKET_ERROR) {
|
||||
DEBUG_LOG(SCENET, "Socket Error (%i) on sceNetAdhocPdpSend[%i:%u->%u](BC) [size=%i]", error, id, getLocalPort(socket->id), ntohs(target.sin_port), len);
|
||||
@@ -1283,7 +1290,7 @@ static int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *
|
||||
|
||||
// Receive Data. PDP always sent in full size or nothing(failed), recvfrom will always receive in full size as requested (blocking) or failed (non-blocking). If available UDP data is larger than buffer, excess data is lost.
|
||||
// Should peek first for the available data size if it's more than len return ERROR_NET_ADHOC_NOT_ENOUGH_SPACE along with required size in len to prevent losing excess data
|
||||
received = recvfrom(socket->id, (char*)buf, *len, MSG_PEEK, (sockaddr*)&sin, &sinlen);
|
||||
received = recvfrom(socket->id, (char*)buf, *len, MSG_PEEK | MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen);
|
||||
if (received != SOCKET_ERROR && *len < received) {
|
||||
WARN_LOG(SCENET, "sceNetAdhocPdpRecv[%i:%u]: Peeked %u/%u bytes from %s:%u\n", id, getLocalPort(socket->id), received, *len, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
|
||||
*len = received;
|
||||
@@ -1309,7 +1316,7 @@ static int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *
|
||||
|
||||
return ERROR_NET_ADHOC_NOT_ENOUGH_SPACE; //received;
|
||||
}
|
||||
received = recvfrom(socket->id, (char*)buf, *len, 0, (sockaddr*)&sin, &sinlen);
|
||||
received = recvfrom(socket->id, (char*)buf, *len, MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen);
|
||||
error = errno;
|
||||
|
||||
if (received == SOCKET_ERROR) {
|
||||
@@ -1645,7 +1652,7 @@ int sceNetAdhocctlScan() {
|
||||
uint8_t opcode = OPCODE_SCAN;
|
||||
|
||||
// Send Scan Request Packet, may failed with socket error 10054/10053 if someone else with the same IP already connected to AdHoc Server (the server might need to be modified to differentiate MAC instead of IP)
|
||||
int iResult = send(metasocket, (char *)&opcode, 1, 0);
|
||||
int iResult = send(metasocket, (char *)&opcode, 1, MSG_NOSIGNAL);
|
||||
int error = errno;
|
||||
|
||||
if (iResult == SOCKET_ERROR) {
|
||||
@@ -1833,7 +1840,7 @@ u32 NetAdhocctl_Disconnect() {
|
||||
//_acquireNetworkLock();
|
||||
|
||||
// Send Disconnect Request Packet
|
||||
iResult = send(metasocket, (const char*)&opcode, 1, 0);
|
||||
iResult = send(metasocket, (const char*)&opcode, 1, MSG_NOSIGNAL);
|
||||
error = errno;
|
||||
|
||||
// Sending may get socket error 10053 if the AdhocServer is already shutted down
|
||||
@@ -2114,7 +2121,7 @@ int NetAdhocctl_Create(const char* groupName) {
|
||||
// Acquire Network Lock
|
||||
|
||||
// Send Packet
|
||||
int iResult = send(metasocket, (const char*)&packet, sizeof(packet), 0);
|
||||
int iResult = send(metasocket, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL);
|
||||
int error = errno;
|
||||
|
||||
if (iResult == SOCKET_ERROR && error != EAGAIN && error != EWOULDBLOCK) {
|
||||
@@ -2512,6 +2519,9 @@ static int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac,
|
||||
// Enable KeepAlive
|
||||
setSockKeepAlive(tcpsocket, true, rexmt_int / 1000000L, rexmt_cnt);
|
||||
|
||||
// Ignore SIGPIPE when supported (ie. BSD/MacOS)
|
||||
setSockNoSIGPIPE(tcpsocket, 1);
|
||||
|
||||
// Enable Port Re-use
|
||||
setsockopt(tcpsocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one));
|
||||
|
||||
@@ -2618,6 +2628,9 @@ int AcceptPtpSocket(int ptpId, int newsocket, sockaddr_in& peeraddr, SceNetEther
|
||||
// Cast Socket
|
||||
auto socket = ptp[ptpId - 1];
|
||||
|
||||
// Ignore SIGPIPE when supported (ie. BSD/MacOS)
|
||||
setSockNoSIGPIPE(newsocket, 1);
|
||||
|
||||
// Enable Port Re-use
|
||||
setsockopt(newsocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one));
|
||||
|
||||
@@ -2996,6 +3009,9 @@ static int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int
|
||||
// Enable KeepAlive
|
||||
setSockKeepAlive(tcpsocket, true, rexmt_int / 1000000L, rexmt_cnt);
|
||||
|
||||
// Ignore SIGPIPE when supported (ie. BSD/MacOS)
|
||||
setSockNoSIGPIPE(tcpsocket, 1);
|
||||
|
||||
// Enable Port Re-use
|
||||
setsockopt(tcpsocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one));
|
||||
|
||||
@@ -3146,7 +3162,7 @@ static int sceNetAdhocPtpSend(int id, u32 dataAddr, u32 dataSizeAddr, int timeou
|
||||
// _acquireNetworkLock();
|
||||
|
||||
// Send Data
|
||||
int sent = send(socket->id, data, *len, 0);
|
||||
int sent = send(socket->id, data, *len, MSG_NOSIGNAL);
|
||||
int error = errno;
|
||||
|
||||
// Free Network Lock
|
||||
@@ -3236,7 +3252,7 @@ static int sceNetAdhocPtpRecv(int id, u32 dataAddr, u32 dataSizeAddr, int timeou
|
||||
int error = 0;
|
||||
|
||||
// Receive Data
|
||||
received = recv(socket->id, (char*)buf, *len, 0);
|
||||
received = recv(socket->id, (char*)buf, *len, MSG_NOSIGNAL);
|
||||
error = errno;
|
||||
|
||||
if (received == SOCKET_ERROR) {
|
||||
@@ -3331,7 +3347,7 @@ static int sceNetAdhocPtpFlush(int id, int timeout, int nonblock) {
|
||||
|
||||
// Send Empty Data just to trigger Nagle on/off effect to flush the send buffer, Do we need to trigger this at all or is it automatically flushed?
|
||||
//changeBlockingMode(socket->id, nonblock);
|
||||
int sent = send(socket->id, 0, 0, 0);
|
||||
int sent = send(socket->id, 0, 0, MSG_NOSIGNAL);
|
||||
int error = errno;
|
||||
//changeBlockingMode(socket->id, 1);
|
||||
|
||||
|
||||
Reference in new issue
Block a user