Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/File/FileDescriptor.cpp
3186 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
// Slow as hell and should only be used for prototyping.
16
// Reads from a socket, up to an '\n'. This means that if the line ends
17
// with '\r', the '\r' will be returned.
18
size_t ReadLine(int fd, char *vptr, size_t buf_size) {
19
char *buffer = vptr;
20
size_t n;
21
for (n = 1; n < buf_size; n++) {
22
char c;
23
size_t rc;
24
if ((rc = read(fd, &c, 1)) == 1) {
25
*buffer++ = c;
26
if (c == '\n')
27
break;
28
} else if (rc == 0) {
29
if (n == 1)
30
return 0;
31
else
32
break;
33
} else {
34
if (errno == EINTR)
35
continue;
36
_assert_msg_(false, "Error in Readline()");
37
}
38
}
39
40
*buffer = 0;
41
return n;
42
}
43
44
// Misnamed, it just writes raw data in a retry loop.
45
size_t WriteLine(int fd, const char *vptr, size_t n) {
46
const char *buffer = vptr;
47
size_t nleft = n;
48
49
while (nleft > 0) {
50
int nwritten;
51
if ((nwritten = (int)write(fd, buffer, (unsigned int)nleft)) <= 0) {
52
if (errno == EINTR)
53
nwritten = 0;
54
else
55
_assert_msg_(false, "Error in Writeline()");
56
}
57
nleft -= nwritten;
58
buffer += nwritten;
59
}
60
61
return n;
62
}
63
64
size_t WriteLine(int fd, const char *buffer) {
65
return WriteLine(fd, buffer, strlen(buffer));
66
}
67
68
size_t Write(int fd, const std::string &str) {
69
return WriteLine(fd, str.c_str(), str.size());
70
}
71
72
bool WaitUntilReady(int fd, double timeout, bool for_write) {
73
struct timeval tv;
74
tv.tv_sec = (long)floor(timeout);
75
tv.tv_usec = (long)((timeout - floor(timeout)) * 1000000.0);
76
77
fd_set fds;
78
FD_ZERO(&fds);
79
FD_SET(fd, &fds);
80
// First argument to select is the highest socket in the set + 1.
81
int rval;
82
if (for_write) {
83
rval = select(fd + 1, nullptr, &fds, nullptr, &tv);
84
} else {
85
rval = select(fd + 1, &fds, nullptr, nullptr, &tv);
86
}
87
88
if (rval < 0) {
89
// Error calling select.
90
return false;
91
} else if (rval == 0) {
92
// Timeout.
93
return false;
94
} else {
95
// Socket is ready.
96
return true;
97
}
98
}
99
100
void SetNonBlocking(int sock, bool non_blocking) {
101
#ifndef _WIN32
102
int opts = fcntl(sock, F_GETFL);
103
if (opts < 0) {
104
perror("fcntl(F_GETFL)");
105
ERROR_LOG(Log::IO, "Error getting socket status while changing nonblocking status");
106
}
107
if (non_blocking) {
108
opts = (opts | O_NONBLOCK);
109
} else {
110
opts = (opts & ~O_NONBLOCK);
111
}
112
113
if (fcntl(sock, F_SETFL, opts) < 0) {
114
perror("fcntl(F_SETFL)");
115
ERROR_LOG(Log::IO, "Error setting socket nonblocking status");
116
}
117
#else
118
u_long val = non_blocking ? 1 : 0;
119
if (ioctlsocket(sock, FIONBIO, &val) != 0) {
120
ERROR_LOG(Log::IO, "Error setting socket nonblocking status");
121
}
122
#endif
123
}
124
125
std::string GetLocalIP(int sock) {
126
union {
127
struct sockaddr sa;
128
struct sockaddr_in ipv4;
129
#if !PPSSPP_PLATFORM(SWITCH)
130
struct sockaddr_in6 ipv6;
131
#endif
132
} server_addr;
133
memset(&server_addr, 0, sizeof(server_addr));
134
socklen_t len = sizeof(server_addr);
135
if (getsockname(sock, (struct sockaddr *)&server_addr, &len) == 0) {
136
char temp[64]{};
137
138
// We clear the port below for WSAAddressToStringA.
139
void *addr = nullptr;
140
#if !PPSSPP_PLATFORM(SWITCH)
141
if (server_addr.sa.sa_family == AF_INET6) {
142
server_addr.ipv6.sin6_port = 0;
143
addr = &server_addr.ipv6.sin6_addr;
144
}
145
#endif
146
if (addr == nullptr) {
147
server_addr.ipv4.sin_port = 0;
148
addr = &server_addr.ipv4.sin_addr;
149
}
150
#ifdef _WIN32
151
wchar_t wtemp[sizeof(temp)];
152
DWORD len = (DWORD)sizeof(temp);
153
// Windows XP doesn't support inet_ntop.
154
if (WSAAddressToStringW((struct sockaddr *)&server_addr, sizeof(server_addr), nullptr, wtemp, &len) == 0) {
155
return ConvertWStringToUTF8(wtemp);
156
}
157
#else
158
const char *result = inet_ntop(server_addr.sa.sa_family, addr, temp, sizeof(temp));
159
if (result) {
160
return result;
161
}
162
#endif
163
}
164
return "";
165
}
166
167
} // fd_util
168
169