|
15 | 15 | #include "TraceEvent.hpp"
|
16 | 16 | #include "Util.hpp"
|
17 | 17 |
|
| 18 | +#include <cerrno> |
18 | 19 | #include <chrono>
|
19 | 20 | #include <cstring>
|
20 | 21 | #include <cctype>
|
|
26 | 27 | #include <cstdio>
|
27 | 28 | #include <string>
|
28 | 29 | #include <unistd.h>
|
| 30 | +#include <sysexits.h> |
29 | 31 | #include <sys/stat.h>
|
30 | 32 | #include <sys/types.h>
|
31 | 33 | #include <sys/un.h>
|
@@ -1161,50 +1163,66 @@ std::shared_ptr<Socket> ServerSocket::accept()
|
1161 | 1163 | #else
|
1162 | 1164 | const int rc = fakeSocketAccept4(getFD());
|
1163 | 1165 | #endif
|
1164 |
| - LOG_TRC("Accepted socket #" << rc << ", creating socket object."); |
1165 |
| - try |
| 1166 | + if (rc < 0) |
1166 | 1167 | {
|
1167 |
| - // Create a socket object using the factory. |
1168 |
| - if (rc != -1) |
| 1168 | + const int cause = errno; |
| 1169 | + if( cause != EINTR && cause != EAGAIN && cause != EWOULDBLOCK ) |
1169 | 1170 | {
|
1170 |
| -#if !MOBILEAPP |
1171 |
| - char addrstr[INET6_ADDRSTRLEN]; |
| 1171 | + // Unrecoverable error, throw, which will close `ServerSocket` and discard it from `AcceptPoll` during `SocketPoll::poll` |
| 1172 | + constexpr const char * messagePrefix = "Failed to accept. (errno: "; |
| 1173 | + LOG_FTL(messagePrefix << std::to_string(cause) << ", " << std::strerror(cause) << ')'); |
| 1174 | + Util::forcedExit(EX_SOFTWARE); |
| 1175 | + } |
| 1176 | + return nullptr; |
| 1177 | + } |
| 1178 | + LOG_TRC("Accepted socket #" << rc << ", creating socket object."); |
1172 | 1179 |
|
1173 |
| - Socket::Type type; |
1174 |
| - const void *inAddr; |
1175 |
| - if (clientInfo.sin6_family == AF_INET) |
1176 |
| - { |
1177 |
| - struct sockaddr_in *ipv4 = (struct sockaddr_in *)&clientInfo; |
1178 |
| - inAddr = &(ipv4->sin_addr); |
1179 |
| - type = Socket::Type::IPv4; |
1180 |
| - } |
1181 |
| - else |
1182 |
| - { |
1183 |
| - struct sockaddr_in6 *ipv6 = &clientInfo; |
1184 |
| - inAddr = &(ipv6->sin6_addr); |
1185 |
| - type = Socket::Type::IPv6; |
1186 |
| - } |
| 1180 | +#if !MOBILEAPP |
| 1181 | + char addrstr[INET6_ADDRSTRLEN]; |
1187 | 1182 |
|
1188 |
| - std::shared_ptr<Socket> _socket = createSocketFromAccept(rc, type); |
| 1183 | + Socket::Type type; |
| 1184 | + const void *inAddr; |
| 1185 | + if (clientInfo.sin6_family == AF_INET) |
| 1186 | + { |
| 1187 | + struct sockaddr_in *ipv4 = (struct sockaddr_in *)&clientInfo; |
| 1188 | + inAddr = &(ipv4->sin_addr); |
| 1189 | + type = Socket::Type::IPv4; |
| 1190 | + } |
| 1191 | + else |
| 1192 | + { |
| 1193 | + struct sockaddr_in6 *ipv6 = &clientInfo; |
| 1194 | + inAddr = &(ipv6->sin6_addr); |
| 1195 | + type = Socket::Type::IPv6; |
| 1196 | + } |
| 1197 | + ::inet_ntop(clientInfo.sin6_family, inAddr, addrstr, sizeof(addrstr)); |
1189 | 1198 |
|
1190 |
| - ::inet_ntop(clientInfo.sin6_family, inAddr, addrstr, sizeof(addrstr)); |
1191 |
| - _socket->setClientAddress(addrstr, clientInfo.sin6_port); |
| 1199 | + const size_t extConnCount = StreamSocket::getExternalConnectionCount(); |
| 1200 | + if( 0 < net::Defaults.maxExtConnections && extConnCount >= net::Defaults.maxExtConnections ) |
| 1201 | + { |
| 1202 | + LOG_WRN("Limiter rejected extConn[" << extConnCount << "/" << net::Defaults.maxExtConnections << "]: #" |
| 1203 | + << rc << " has family " |
| 1204 | + << clientInfo.sin6_family << ", address " << addrstr << ":" << clientInfo.sin6_port); |
| 1205 | + ::close(rc); |
| 1206 | + return nullptr; |
| 1207 | + } |
| 1208 | + try |
| 1209 | + { |
| 1210 | + // Create a socket object using the factory. |
| 1211 | + std::shared_ptr<Socket> _socket = createSocketFromAccept(rc, type); |
| 1212 | + _socket->setClientAddress(addrstr, clientInfo.sin6_port); |
1192 | 1213 |
|
1193 |
| - LOG_TRC("Accepted socket #" << _socket->getFD() << " has family " |
1194 |
| - << clientInfo.sin6_family << ", " << *_socket); |
1195 |
| -#else |
1196 |
| - std::shared_ptr<Socket> _socket = createSocketFromAccept(rc, Socket::Type::Unix); |
1197 |
| -#endif |
1198 |
| - return _socket; |
1199 |
| - } |
1200 |
| - return std::shared_ptr<Socket>(nullptr); |
| 1214 | + LOG_TRC("Accepted socket #" << _socket->getFD() << " has family " |
| 1215 | + << clientInfo.sin6_family << ", " << *_socket); |
| 1216 | + return _socket; |
1201 | 1217 | }
|
1202 | 1218 | catch (const std::exception& ex)
|
1203 | 1219 | {
|
1204 | 1220 | LOG_ERR("Failed to create client socket #" << rc << ". Error: " << ex.what());
|
1205 | 1221 | }
|
1206 |
| - |
1207 | 1222 | return nullptr;
|
| 1223 | +#else |
| 1224 | + return createSocketFromAccept(rc, Socket::Type::Unix); |
| 1225 | +#endif |
1208 | 1226 | }
|
1209 | 1227 |
|
1210 | 1228 | #if !MOBILEAPP
|
@@ -1250,11 +1268,21 @@ bool Socket::isLocal() const
|
1250 | 1268 | std::shared_ptr<Socket> LocalServerSocket::accept()
|
1251 | 1269 | {
|
1252 | 1270 | const int rc = ::accept4(getFD(), nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
| 1271 | + if (rc < 0) |
| 1272 | + { |
| 1273 | + const int cause = errno; |
| 1274 | + if( cause != EINTR && cause != EAGAIN && cause != EWOULDBLOCK ) |
| 1275 | + { |
| 1276 | + // Unrecoverable error, throw, which will close `ServerSocket` and discard it from `AcceptPoll` during `SocketPoll::poll` |
| 1277 | + constexpr const char * messagePrefix = "Failed to accept. (errno: "; |
| 1278 | + LOG_FTL(messagePrefix << std::to_string(cause) << ", " << std::strerror(cause) << ')'); |
| 1279 | + Util::forcedExit(EX_SOFTWARE); |
| 1280 | + } |
| 1281 | + return nullptr; |
| 1282 | + } |
1253 | 1283 | try
|
1254 | 1284 | {
|
1255 | 1285 | LOG_DBG("Accepted prisoner socket #" << rc << ", creating socket object.");
|
1256 |
| - if (rc < 0) |
1257 |
| - return std::shared_ptr<Socket>(nullptr); |
1258 | 1286 |
|
1259 | 1287 | std::shared_ptr<Socket> _socket = createSocketFromAccept(rc, Socket::Type::Unix);
|
1260 | 1288 | // Sanity check this incoming socket
|
@@ -1304,8 +1332,8 @@ std::shared_ptr<Socket> LocalServerSocket::accept()
|
1304 | 1332 | catch (const std::exception& ex)
|
1305 | 1333 | {
|
1306 | 1334 | LOG_ERR("Failed to create client socket #" << rc << ". Error: " << ex.what());
|
1307 |
| - return std::shared_ptr<Socket>(nullptr); |
1308 | 1335 | }
|
| 1336 | + return nullptr; |
1309 | 1337 | }
|
1310 | 1338 |
|
1311 | 1339 | /// Returns true on success only.
|
|
0 commit comments