Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/File/FileDescriptor.cpp
5656 views
1
#include "ppsspp_config.h"
2
3
#include <errno.h>
4
#include <cmath>
5
#include <cstdio>
6
7
#include "Common/CommonTypes.h"
8
#include "Common/Net/SocketCompat.h"
9
#include "Common/Data/Encoding/Utf8.h"
10
#include "Common/File/FileDescriptor.h"
11
#include "Common/Log.h"
12
13
namespace fd_util {
14
15
bool WaitUntilReady(int fd, double timeout, bool for_write) {
16
struct timeval tv;
17
tv.tv_sec = (long)floor(timeout);
18
tv.tv_usec = (long)((timeout - floor(timeout)) * 1000000.0);
19
20
fd_set fds;
21
FD_ZERO(&fds);
22
FD_SET(fd, &fds);
23
// First argument to select is the highest socket in the set + 1.
24
int rval;
25
if (for_write) {
26
rval = select(fd + 1, nullptr, &fds, nullptr, &tv);
27
} else {
28
rval = select(fd + 1, &fds, nullptr, nullptr, &tv);
29
}
30
31
if (rval < 0) {
32
// Error calling select.
33
return false;
34
} else if (rval == 0) {
35
// Timeout.
36
return false;
37
} else {
38
// Socket is ready.
39
return true;
40
}
41
}
42
43
void SetNonBlocking(int sock, bool non_blocking) {
44
#ifndef _WIN32
45
int opts = fcntl(sock, F_GETFL);
46
if (opts < 0) {
47
perror("fcntl(F_GETFL)");
48
ERROR_LOG(Log::IO, "Error getting socket status while changing nonblocking status");
49
}
50
if (non_blocking) {
51
opts = (opts | O_NONBLOCK);
52
} else {
53
opts = (opts & ~O_NONBLOCK);
54
}
55
56
if (fcntl(sock, F_SETFL, opts) < 0) {
57
perror("fcntl(F_SETFL)");
58
ERROR_LOG(Log::IO, "Error setting socket nonblocking status");
59
}
60
#else
61
u_long val = non_blocking ? 1 : 0;
62
if (ioctlsocket(sock, FIONBIO, &val) != 0) {
63
ERROR_LOG(Log::IO, "Error setting socket nonblocking status");
64
}
65
#endif
66
}
67
68
std::string GetLocalIP(int sock) {
69
union {
70
struct sockaddr sa;
71
struct sockaddr_in ipv4;
72
#if !PPSSPP_PLATFORM(SWITCH)
73
struct sockaddr_in6 ipv6;
74
#endif
75
} server_addr;
76
memset(&server_addr, 0, sizeof(server_addr));
77
socklen_t len = sizeof(server_addr);
78
int retval = getsockname(sock, (struct sockaddr *)&server_addr, &len);
79
if (retval == 0) {
80
char temp[64]{};
81
82
// We clear the port below for WSAAddressToStringA.
83
void *addr = nullptr;
84
#if !PPSSPP_PLATFORM(SWITCH)
85
if (server_addr.sa.sa_family == AF_INET6) {
86
server_addr.ipv6.sin6_port = 0;
87
addr = &server_addr.ipv6.sin6_addr;
88
}
89
#endif
90
if (addr == nullptr) {
91
server_addr.ipv4.sin_port = 0;
92
addr = &server_addr.ipv4.sin_addr;
93
}
94
#ifdef _WIN32
95
wchar_t wtemp[sizeof(temp)];
96
DWORD len = (DWORD)sizeof(temp);
97
// Windows XP doesn't support inet_ntop.
98
HRESULT result = WSAAddressToStringW((struct sockaddr *)&server_addr, sizeof(server_addr), nullptr, wtemp, &len);
99
if (result == 0) {
100
return ConvertWStringToUTF8(wtemp);
101
} else {
102
return "";
103
}
104
#else
105
const char *result = inet_ntop(server_addr.sa.sa_family, addr, temp, sizeof(temp));
106
if (result) {
107
return result;
108
} else {
109
return "";
110
}
111
#endif
112
} else {
113
WARN_LOG(Log::IO, "GetLocalIP: getsockname failed with error %d (%s)", retval, strerror(retval));
114
return "";
115
}
116
}
117
118
} // fd_util
119
120