Merge pull request #13392 from ANR2ME/adhoc_socket

Ignore SIGPIPE error on certain system (ie. Linux)
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2020-09-06 22:09:11 +02:00
commit 901239c05e
4 files changed
+71 -31

No files matched your search

+18 -4
View File
@@ -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);
+5
View File
@@ -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)
*/
+14 -9
View File
@@ -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
View File
@@ -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);