diff options
| author | 2023-07-16 16:56:47 -0400 | |
|---|---|---|
| committer | 2023-07-16 16:56:47 -0400 | |
| commit | 2461c78e3f9368e4a03b4c27fae207cbb1d9cfff (patch) | |
| tree | 50812311958a38d27d9ebcd1cfa443b77ff1c40c /src/core/internal_network | |
| parent | file_sys/content_archive: Detect compressed NCAs (#11047) (diff) | |
| parent | Rename variables to avoid -Wshadow warnings under GCC (diff) | |
| download | yuzu-2461c78e3f9368e4a03b4c27fae207cbb1d9cfff.tar.gz yuzu-2461c78e3f9368e4a03b4c27fae207cbb1d9cfff.tar.xz yuzu-2461c78e3f9368e4a03b4c27fae207cbb1d9cfff.zip | |
Merge pull request #10912 from comex/ssl
Implement SSL service
Diffstat (limited to 'src/core/internal_network')
| -rw-r--r-- | src/core/internal_network/network.cpp | 286 | ||||
| -rw-r--r-- | src/core/internal_network/network.h | 36 | ||||
| -rw-r--r-- | src/core/internal_network/socket_proxy.cpp | 22 | ||||
| -rw-r--r-- | src/core/internal_network/socket_proxy.h | 8 | ||||
| -rw-r--r-- | src/core/internal_network/sockets.h | 16 |
5 files changed, 292 insertions, 76 deletions
diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index 75ac10a9c..28f89c599 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | 27 | ||
| 28 | #include "common/assert.h" | 28 | #include "common/assert.h" |
| 29 | #include "common/common_types.h" | 29 | #include "common/common_types.h" |
| 30 | #include "common/expected.h" | ||
| 30 | #include "common/logging/log.h" | 31 | #include "common/logging/log.h" |
| 31 | #include "common/settings.h" | 32 | #include "common/settings.h" |
| 32 | #include "core/internal_network/network.h" | 33 | #include "core/internal_network/network.h" |
| @@ -97,6 +98,8 @@ bool EnableNonBlock(SOCKET fd, bool enable) { | |||
| 97 | 98 | ||
| 98 | Errno TranslateNativeError(int e) { | 99 | Errno TranslateNativeError(int e) { |
| 99 | switch (e) { | 100 | switch (e) { |
| 101 | case 0: | ||
| 102 | return Errno::SUCCESS; | ||
| 100 | case WSAEBADF: | 103 | case WSAEBADF: |
| 101 | return Errno::BADF; | 104 | return Errno::BADF; |
| 102 | case WSAEINVAL: | 105 | case WSAEINVAL: |
| @@ -121,6 +124,8 @@ Errno TranslateNativeError(int e) { | |||
| 121 | return Errno::MSGSIZE; | 124 | return Errno::MSGSIZE; |
| 122 | case WSAETIMEDOUT: | 125 | case WSAETIMEDOUT: |
| 123 | return Errno::TIMEDOUT; | 126 | return Errno::TIMEDOUT; |
| 127 | case WSAEINPROGRESS: | ||
| 128 | return Errno::INPROGRESS; | ||
| 124 | default: | 129 | default: |
| 125 | UNIMPLEMENTED_MSG("Unimplemented errno={}", e); | 130 | UNIMPLEMENTED_MSG("Unimplemented errno={}", e); |
| 126 | return Errno::OTHER; | 131 | return Errno::OTHER; |
| @@ -195,6 +200,8 @@ bool EnableNonBlock(int fd, bool enable) { | |||
| 195 | 200 | ||
| 196 | Errno TranslateNativeError(int e) { | 201 | Errno TranslateNativeError(int e) { |
| 197 | switch (e) { | 202 | switch (e) { |
| 203 | case 0: | ||
| 204 | return Errno::SUCCESS; | ||
| 198 | case EBADF: | 205 | case EBADF: |
| 199 | return Errno::BADF; | 206 | return Errno::BADF; |
| 200 | case EINVAL: | 207 | case EINVAL: |
| @@ -219,8 +226,10 @@ Errno TranslateNativeError(int e) { | |||
| 219 | return Errno::MSGSIZE; | 226 | return Errno::MSGSIZE; |
| 220 | case ETIMEDOUT: | 227 | case ETIMEDOUT: |
| 221 | return Errno::TIMEDOUT; | 228 | return Errno::TIMEDOUT; |
| 229 | case EINPROGRESS: | ||
| 230 | return Errno::INPROGRESS; | ||
| 222 | default: | 231 | default: |
| 223 | UNIMPLEMENTED_MSG("Unimplemented errno={}", e); | 232 | UNIMPLEMENTED_MSG("Unimplemented errno={} ({})", e, strerror(e)); |
| 224 | return Errno::OTHER; | 233 | return Errno::OTHER; |
| 225 | } | 234 | } |
| 226 | } | 235 | } |
| @@ -234,15 +243,84 @@ Errno GetAndLogLastError() { | |||
| 234 | int e = errno; | 243 | int e = errno; |
| 235 | #endif | 244 | #endif |
| 236 | const Errno err = TranslateNativeError(e); | 245 | const Errno err = TranslateNativeError(e); |
| 237 | if (err == Errno::AGAIN || err == Errno::TIMEDOUT) { | 246 | if (err == Errno::AGAIN || err == Errno::TIMEDOUT || err == Errno::INPROGRESS) { |
| 247 | // These happen during normal operation, so only log them at debug level. | ||
| 248 | LOG_DEBUG(Network, "Socket operation error: {}", Common::NativeErrorToString(e)); | ||
| 238 | return err; | 249 | return err; |
| 239 | } | 250 | } |
| 240 | LOG_ERROR(Network, "Socket operation error: {}", Common::NativeErrorToString(e)); | 251 | LOG_ERROR(Network, "Socket operation error: {}", Common::NativeErrorToString(e)); |
| 241 | return err; | 252 | return err; |
| 242 | } | 253 | } |
| 243 | 254 | ||
| 244 | int TranslateDomain(Domain domain) { | 255 | GetAddrInfoError TranslateGetAddrInfoErrorFromNative(int gai_err) { |
| 256 | switch (gai_err) { | ||
| 257 | case 0: | ||
| 258 | return GetAddrInfoError::SUCCESS; | ||
| 259 | #ifdef EAI_ADDRFAMILY | ||
| 260 | case EAI_ADDRFAMILY: | ||
| 261 | return GetAddrInfoError::ADDRFAMILY; | ||
| 262 | #endif | ||
| 263 | case EAI_AGAIN: | ||
| 264 | return GetAddrInfoError::AGAIN; | ||
| 265 | case EAI_BADFLAGS: | ||
| 266 | return GetAddrInfoError::BADFLAGS; | ||
| 267 | case EAI_FAIL: | ||
| 268 | return GetAddrInfoError::FAIL; | ||
| 269 | case EAI_FAMILY: | ||
| 270 | return GetAddrInfoError::FAMILY; | ||
| 271 | case EAI_MEMORY: | ||
| 272 | return GetAddrInfoError::MEMORY; | ||
| 273 | case EAI_NONAME: | ||
| 274 | return GetAddrInfoError::NONAME; | ||
| 275 | case EAI_SERVICE: | ||
| 276 | return GetAddrInfoError::SERVICE; | ||
| 277 | case EAI_SOCKTYPE: | ||
| 278 | return GetAddrInfoError::SOCKTYPE; | ||
| 279 | // These codes may not be defined on all systems: | ||
| 280 | #ifdef EAI_SYSTEM | ||
| 281 | case EAI_SYSTEM: | ||
| 282 | return GetAddrInfoError::SYSTEM; | ||
| 283 | #endif | ||
| 284 | #ifdef EAI_BADHINTS | ||
| 285 | case EAI_BADHINTS: | ||
| 286 | return GetAddrInfoError::BADHINTS; | ||
| 287 | #endif | ||
| 288 | #ifdef EAI_PROTOCOL | ||
| 289 | case EAI_PROTOCOL: | ||
| 290 | return GetAddrInfoError::PROTOCOL; | ||
| 291 | #endif | ||
| 292 | #ifdef EAI_OVERFLOW | ||
| 293 | case EAI_OVERFLOW: | ||
| 294 | return GetAddrInfoError::OVERFLOW_; | ||
| 295 | #endif | ||
| 296 | default: | ||
| 297 | #ifdef EAI_NODATA | ||
| 298 | // This can't be a case statement because it would create a duplicate | ||
| 299 | // case on Windows where EAI_NODATA is an alias for EAI_NONAME. | ||
| 300 | if (gai_err == EAI_NODATA) { | ||
| 301 | return GetAddrInfoError::NODATA; | ||
| 302 | } | ||
| 303 | #endif | ||
| 304 | return GetAddrInfoError::OTHER; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | Domain TranslateDomainFromNative(int domain) { | ||
| 309 | switch (domain) { | ||
| 310 | case 0: | ||
| 311 | return Domain::Unspecified; | ||
| 312 | case AF_INET: | ||
| 313 | return Domain::INET; | ||
| 314 | default: | ||
| 315 | UNIMPLEMENTED_MSG("Unhandled domain={}", domain); | ||
| 316 | return Domain::INET; | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | int TranslateDomainToNative(Domain domain) { | ||
| 245 | switch (domain) { | 321 | switch (domain) { |
| 322 | case Domain::Unspecified: | ||
| 323 | return 0; | ||
| 246 | case Domain::INET: | 324 | case Domain::INET: |
| 247 | return AF_INET; | 325 | return AF_INET; |
| 248 | default: | 326 | default: |
| @@ -251,20 +329,58 @@ int TranslateDomain(Domain domain) { | |||
| 251 | } | 329 | } |
| 252 | } | 330 | } |
| 253 | 331 | ||
| 254 | int TranslateType(Type type) { | 332 | Type TranslateTypeFromNative(int type) { |
| 333 | switch (type) { | ||
| 334 | case 0: | ||
| 335 | return Type::Unspecified; | ||
| 336 | case SOCK_STREAM: | ||
| 337 | return Type::STREAM; | ||
| 338 | case SOCK_DGRAM: | ||
| 339 | return Type::DGRAM; | ||
| 340 | case SOCK_RAW: | ||
| 341 | return Type::RAW; | ||
| 342 | case SOCK_SEQPACKET: | ||
| 343 | return Type::SEQPACKET; | ||
| 344 | default: | ||
| 345 | UNIMPLEMENTED_MSG("Unimplemented type={}", type); | ||
| 346 | return Type::STREAM; | ||
| 347 | } | ||
| 348 | } | ||
| 349 | |||
| 350 | int TranslateTypeToNative(Type type) { | ||
| 255 | switch (type) { | 351 | switch (type) { |
| 352 | case Type::Unspecified: | ||
| 353 | return 0; | ||
| 256 | case Type::STREAM: | 354 | case Type::STREAM: |
| 257 | return SOCK_STREAM; | 355 | return SOCK_STREAM; |
| 258 | case Type::DGRAM: | 356 | case Type::DGRAM: |
| 259 | return SOCK_DGRAM; | 357 | return SOCK_DGRAM; |
| 358 | case Type::RAW: | ||
| 359 | return SOCK_RAW; | ||
| 260 | default: | 360 | default: |
| 261 | UNIMPLEMENTED_MSG("Unimplemented type={}", type); | 361 | UNIMPLEMENTED_MSG("Unimplemented type={}", type); |
| 262 | return 0; | 362 | return 0; |
| 263 | } | 363 | } |
| 264 | } | 364 | } |
| 265 | 365 | ||
| 266 | int TranslateProtocol(Protocol protocol) { | 366 | Protocol TranslateProtocolFromNative(int protocol) { |
| 367 | switch (protocol) { | ||
| 368 | case 0: | ||
| 369 | return Protocol::Unspecified; | ||
| 370 | case IPPROTO_TCP: | ||
| 371 | return Protocol::TCP; | ||
| 372 | case IPPROTO_UDP: | ||
| 373 | return Protocol::UDP; | ||
| 374 | default: | ||
| 375 | UNIMPLEMENTED_MSG("Unimplemented protocol={}", protocol); | ||
| 376 | return Protocol::Unspecified; | ||
| 377 | } | ||
| 378 | } | ||
| 379 | |||
| 380 | int TranslateProtocolToNative(Protocol protocol) { | ||
| 267 | switch (protocol) { | 381 | switch (protocol) { |
| 382 | case Protocol::Unspecified: | ||
| 383 | return 0; | ||
| 268 | case Protocol::TCP: | 384 | case Protocol::TCP: |
| 269 | return IPPROTO_TCP; | 385 | return IPPROTO_TCP; |
| 270 | case Protocol::UDP: | 386 | case Protocol::UDP: |
| @@ -275,21 +391,10 @@ int TranslateProtocol(Protocol protocol) { | |||
| 275 | } | 391 | } |
| 276 | } | 392 | } |
| 277 | 393 | ||
| 278 | SockAddrIn TranslateToSockAddrIn(sockaddr input_) { | 394 | SockAddrIn TranslateToSockAddrIn(sockaddr_in input, size_t input_len) { |
| 279 | sockaddr_in input; | ||
| 280 | std::memcpy(&input, &input_, sizeof(input)); | ||
| 281 | |||
| 282 | SockAddrIn result; | 395 | SockAddrIn result; |
| 283 | 396 | ||
| 284 | switch (input.sin_family) { | 397 | result.family = TranslateDomainFromNative(input.sin_family); |
| 285 | case AF_INET: | ||
| 286 | result.family = Domain::INET; | ||
| 287 | break; | ||
| 288 | default: | ||
| 289 | UNIMPLEMENTED_MSG("Unhandled sockaddr family={}", input.sin_family); | ||
| 290 | result.family = Domain::INET; | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | 398 | ||
| 294 | result.portno = ntohs(input.sin_port); | 399 | result.portno = ntohs(input.sin_port); |
| 295 | 400 | ||
| @@ -301,22 +406,33 @@ SockAddrIn TranslateToSockAddrIn(sockaddr input_) { | |||
| 301 | short TranslatePollEvents(PollEvents events) { | 406 | short TranslatePollEvents(PollEvents events) { |
| 302 | short result = 0; | 407 | short result = 0; |
| 303 | 408 | ||
| 304 | if (True(events & PollEvents::In)) { | 409 | const auto translate = [&result, &events](PollEvents guest, short host) { |
| 305 | events &= ~PollEvents::In; | 410 | if (True(events & guest)) { |
| 306 | result |= POLLIN; | 411 | events &= ~guest; |
| 307 | } | 412 | result |= host; |
| 308 | if (True(events & PollEvents::Pri)) { | 413 | } |
| 309 | events &= ~PollEvents::Pri; | 414 | }; |
| 415 | |||
| 416 | translate(PollEvents::In, POLLIN); | ||
| 417 | translate(PollEvents::Pri, POLLPRI); | ||
| 418 | translate(PollEvents::Out, POLLOUT); | ||
| 419 | translate(PollEvents::Err, POLLERR); | ||
| 420 | translate(PollEvents::Hup, POLLHUP); | ||
| 421 | translate(PollEvents::Nval, POLLNVAL); | ||
| 422 | translate(PollEvents::RdNorm, POLLRDNORM); | ||
| 423 | translate(PollEvents::RdBand, POLLRDBAND); | ||
| 424 | translate(PollEvents::WrBand, POLLWRBAND); | ||
| 425 | |||
| 310 | #ifdef _WIN32 | 426 | #ifdef _WIN32 |
| 311 | LOG_WARNING(Service, "Winsock doesn't support POLLPRI"); | 427 | short allowed_events = POLLRDBAND | POLLRDNORM | POLLWRNORM; |
| 312 | #else | 428 | // Unlike poll on other OSes, WSAPoll will complain if any other flags are set on input. |
| 313 | result |= POLLPRI; | 429 | if (result & ~allowed_events) { |
| 430 | LOG_DEBUG(Network, | ||
| 431 | "Removing WSAPoll input events 0x{:x} because Windows doesn't support them", | ||
| 432 | result & ~allowed_events); | ||
| 433 | } | ||
| 434 | result &= allowed_events; | ||
| 314 | #endif | 435 | #endif |
| 315 | } | ||
| 316 | if (True(events & PollEvents::Out)) { | ||
| 317 | events &= ~PollEvents::Out; | ||
| 318 | result |= POLLOUT; | ||
| 319 | } | ||
| 320 | 436 | ||
| 321 | UNIMPLEMENTED_IF_MSG((u16)events != 0, "Unhandled guest events=0x{:x}", (u16)events); | 437 | UNIMPLEMENTED_IF_MSG((u16)events != 0, "Unhandled guest events=0x{:x}", (u16)events); |
| 322 | 438 | ||
| @@ -337,6 +453,10 @@ PollEvents TranslatePollRevents(short revents) { | |||
| 337 | translate(POLLOUT, PollEvents::Out); | 453 | translate(POLLOUT, PollEvents::Out); |
| 338 | translate(POLLERR, PollEvents::Err); | 454 | translate(POLLERR, PollEvents::Err); |
| 339 | translate(POLLHUP, PollEvents::Hup); | 455 | translate(POLLHUP, PollEvents::Hup); |
| 456 | translate(POLLNVAL, PollEvents::Nval); | ||
| 457 | translate(POLLRDNORM, PollEvents::RdNorm); | ||
| 458 | translate(POLLRDBAND, PollEvents::RdBand); | ||
| 459 | translate(POLLWRBAND, PollEvents::WrBand); | ||
| 340 | 460 | ||
| 341 | UNIMPLEMENTED_IF_MSG(revents != 0, "Unhandled host revents=0x{:x}", revents); | 461 | UNIMPLEMENTED_IF_MSG(revents != 0, "Unhandled host revents=0x{:x}", revents); |
| 342 | 462 | ||
| @@ -360,12 +480,51 @@ std::optional<IPv4Address> GetHostIPv4Address() { | |||
| 360 | return {}; | 480 | return {}; |
| 361 | } | 481 | } |
| 362 | 482 | ||
| 363 | std::array<char, 16> ip_addr = {}; | ||
| 364 | ASSERT(inet_ntop(AF_INET, &network_interface->ip_address, ip_addr.data(), sizeof(ip_addr)) != | ||
| 365 | nullptr); | ||
| 366 | return TranslateIPv4(network_interface->ip_address); | 483 | return TranslateIPv4(network_interface->ip_address); |
| 367 | } | 484 | } |
| 368 | 485 | ||
| 486 | std::string IPv4AddressToString(IPv4Address ip_addr) { | ||
| 487 | std::array<char, INET_ADDRSTRLEN> buf = {}; | ||
| 488 | ASSERT(inet_ntop(AF_INET, &ip_addr, buf.data(), sizeof(buf)) == buf.data()); | ||
| 489 | return std::string(buf.data()); | ||
| 490 | } | ||
| 491 | |||
| 492 | u32 IPv4AddressToInteger(IPv4Address ip_addr) { | ||
| 493 | return static_cast<u32>(ip_addr[0]) << 24 | static_cast<u32>(ip_addr[1]) << 16 | | ||
| 494 | static_cast<u32>(ip_addr[2]) << 8 | static_cast<u32>(ip_addr[3]); | ||
| 495 | } | ||
| 496 | |||
| 497 | Common::Expected<std::vector<AddrInfo>, GetAddrInfoError> GetAddressInfo( | ||
| 498 | const std::string& host, const std::optional<std::string>& service) { | ||
| 499 | addrinfo hints{}; | ||
| 500 | hints.ai_family = AF_INET; // Switch only supports IPv4. | ||
| 501 | addrinfo* addrinfo; | ||
| 502 | s32 gai_err = getaddrinfo(host.c_str(), service.has_value() ? service->c_str() : nullptr, | ||
| 503 | &hints, &addrinfo); | ||
| 504 | if (gai_err != 0) { | ||
| 505 | return Common::Unexpected(TranslateGetAddrInfoErrorFromNative(gai_err)); | ||
| 506 | } | ||
| 507 | std::vector<AddrInfo> ret; | ||
| 508 | for (auto* current = addrinfo; current; current = current->ai_next) { | ||
| 509 | // We should only get AF_INET results due to the hints value. | ||
| 510 | ASSERT_OR_EXECUTE(addrinfo->ai_family == AF_INET && | ||
| 511 | addrinfo->ai_addrlen == sizeof(sockaddr_in), | ||
| 512 | continue;); | ||
| 513 | |||
| 514 | AddrInfo& out = ret.emplace_back(); | ||
| 515 | out.family = TranslateDomainFromNative(current->ai_family); | ||
| 516 | out.socket_type = TranslateTypeFromNative(current->ai_socktype); | ||
| 517 | out.protocol = TranslateProtocolFromNative(current->ai_protocol); | ||
| 518 | out.addr = TranslateToSockAddrIn(*reinterpret_cast<sockaddr_in*>(current->ai_addr), | ||
| 519 | current->ai_addrlen); | ||
| 520 | if (current->ai_canonname != nullptr) { | ||
| 521 | out.canon_name = current->ai_canonname; | ||
| 522 | } | ||
| 523 | } | ||
| 524 | freeaddrinfo(addrinfo); | ||
| 525 | return ret; | ||
| 526 | } | ||
| 527 | |||
| 369 | std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { | 528 | std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { |
| 370 | const size_t num = pollfds.size(); | 529 | const size_t num = pollfds.size(); |
| 371 | 530 | ||
| @@ -411,9 +570,21 @@ Socket::Socket(Socket&& rhs) noexcept { | |||
| 411 | } | 570 | } |
| 412 | 571 | ||
| 413 | template <typename T> | 572 | template <typename T> |
| 414 | Errno Socket::SetSockOpt(SOCKET fd_, int option, T value) { | 573 | std::pair<T, Errno> Socket::GetSockOpt(SOCKET fd_so, int option) { |
| 574 | T value{}; | ||
| 575 | socklen_t len = sizeof(value); | ||
| 576 | const int result = getsockopt(fd_so, SOL_SOCKET, option, reinterpret_cast<char*>(&value), &len); | ||
| 577 | if (result != SOCKET_ERROR) { | ||
| 578 | ASSERT(len == sizeof(value)); | ||
| 579 | return {value, Errno::SUCCESS}; | ||
| 580 | } | ||
| 581 | return {value, GetAndLogLastError()}; | ||
| 582 | } | ||
| 583 | |||
| 584 | template <typename T> | ||
| 585 | Errno Socket::SetSockOpt(SOCKET fd_so, int option, T value) { | ||
| 415 | const int result = | 586 | const int result = |
| 416 | setsockopt(fd_, SOL_SOCKET, option, reinterpret_cast<const char*>(&value), sizeof(value)); | 587 | setsockopt(fd_so, SOL_SOCKET, option, reinterpret_cast<const char*>(&value), sizeof(value)); |
| 417 | if (result != SOCKET_ERROR) { | 588 | if (result != SOCKET_ERROR) { |
| 418 | return Errno::SUCCESS; | 589 | return Errno::SUCCESS; |
| 419 | } | 590 | } |
| @@ -421,7 +592,8 @@ Errno Socket::SetSockOpt(SOCKET fd_, int option, T value) { | |||
| 421 | } | 592 | } |
| 422 | 593 | ||
| 423 | Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { | 594 | Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { |
| 424 | fd = socket(TranslateDomain(domain), TranslateType(type), TranslateProtocol(protocol)); | 595 | fd = socket(TranslateDomainToNative(domain), TranslateTypeToNative(type), |
| 596 | TranslateProtocolToNative(protocol)); | ||
| 425 | if (fd != INVALID_SOCKET) { | 597 | if (fd != INVALID_SOCKET) { |
| 426 | return Errno::SUCCESS; | 598 | return Errno::SUCCESS; |
| 427 | } | 599 | } |
| @@ -430,19 +602,17 @@ Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { | |||
| 430 | } | 602 | } |
| 431 | 603 | ||
| 432 | std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() { | 604 | std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() { |
| 433 | sockaddr addr; | 605 | sockaddr_in addr; |
| 434 | socklen_t addrlen = sizeof(addr); | 606 | socklen_t addrlen = sizeof(addr); |
| 435 | const SOCKET new_socket = accept(fd, &addr, &addrlen); | 607 | const SOCKET new_socket = accept(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen); |
| 436 | 608 | ||
| 437 | if (new_socket == INVALID_SOCKET) { | 609 | if (new_socket == INVALID_SOCKET) { |
| 438 | return {AcceptResult{}, GetAndLogLastError()}; | 610 | return {AcceptResult{}, GetAndLogLastError()}; |
| 439 | } | 611 | } |
| 440 | 612 | ||
| 441 | ASSERT(addrlen == sizeof(sockaddr_in)); | ||
| 442 | |||
| 443 | AcceptResult result{ | 613 | AcceptResult result{ |
| 444 | .socket = std::make_unique<Socket>(new_socket), | 614 | .socket = std::make_unique<Socket>(new_socket), |
| 445 | .sockaddr_in = TranslateToSockAddrIn(addr), | 615 | .sockaddr_in = TranslateToSockAddrIn(addr, addrlen), |
| 446 | }; | 616 | }; |
| 447 | 617 | ||
| 448 | return {std::move(result), Errno::SUCCESS}; | 618 | return {std::move(result), Errno::SUCCESS}; |
| @@ -458,25 +628,23 @@ Errno Socket::Connect(SockAddrIn addr_in) { | |||
| 458 | } | 628 | } |
| 459 | 629 | ||
| 460 | std::pair<SockAddrIn, Errno> Socket::GetPeerName() { | 630 | std::pair<SockAddrIn, Errno> Socket::GetPeerName() { |
| 461 | sockaddr addr; | 631 | sockaddr_in addr; |
| 462 | socklen_t addrlen = sizeof(addr); | 632 | socklen_t addrlen = sizeof(addr); |
| 463 | if (getpeername(fd, &addr, &addrlen) == SOCKET_ERROR) { | 633 | if (getpeername(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen) == SOCKET_ERROR) { |
| 464 | return {SockAddrIn{}, GetAndLogLastError()}; | 634 | return {SockAddrIn{}, GetAndLogLastError()}; |
| 465 | } | 635 | } |
| 466 | 636 | ||
| 467 | ASSERT(addrlen == sizeof(sockaddr_in)); | 637 | return {TranslateToSockAddrIn(addr, addrlen), Errno::SUCCESS}; |
| 468 | return {TranslateToSockAddrIn(addr), Errno::SUCCESS}; | ||
| 469 | } | 638 | } |
| 470 | 639 | ||
| 471 | std::pair<SockAddrIn, Errno> Socket::GetSockName() { | 640 | std::pair<SockAddrIn, Errno> Socket::GetSockName() { |
| 472 | sockaddr addr; | 641 | sockaddr_in addr; |
| 473 | socklen_t addrlen = sizeof(addr); | 642 | socklen_t addrlen = sizeof(addr); |
| 474 | if (getsockname(fd, &addr, &addrlen) == SOCKET_ERROR) { | 643 | if (getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen) == SOCKET_ERROR) { |
| 475 | return {SockAddrIn{}, GetAndLogLastError()}; | 644 | return {SockAddrIn{}, GetAndLogLastError()}; |
| 476 | } | 645 | } |
| 477 | 646 | ||
| 478 | ASSERT(addrlen == sizeof(sockaddr_in)); | 647 | return {TranslateToSockAddrIn(addr, addrlen), Errno::SUCCESS}; |
| 479 | return {TranslateToSockAddrIn(addr), Errno::SUCCESS}; | ||
| 480 | } | 648 | } |
| 481 | 649 | ||
| 482 | Errno Socket::Bind(SockAddrIn addr) { | 650 | Errno Socket::Bind(SockAddrIn addr) { |
| @@ -519,7 +687,7 @@ Errno Socket::Shutdown(ShutdownHow how) { | |||
| 519 | return GetAndLogLastError(); | 687 | return GetAndLogLastError(); |
| 520 | } | 688 | } |
| 521 | 689 | ||
| 522 | std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) { | 690 | std::pair<s32, Errno> Socket::Recv(int flags, std::span<u8> message) { |
| 523 | ASSERT(flags == 0); | 691 | ASSERT(flags == 0); |
| 524 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); | 692 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); |
| 525 | 693 | ||
| @@ -532,21 +700,20 @@ std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) { | |||
| 532 | return {-1, GetAndLogLastError()}; | 700 | return {-1, GetAndLogLastError()}; |
| 533 | } | 701 | } |
| 534 | 702 | ||
| 535 | std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) { | 703 | std::pair<s32, Errno> Socket::RecvFrom(int flags, std::span<u8> message, SockAddrIn* addr) { |
| 536 | ASSERT(flags == 0); | 704 | ASSERT(flags == 0); |
| 537 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); | 705 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); |
| 538 | 706 | ||
| 539 | sockaddr addr_in{}; | 707 | sockaddr_in addr_in{}; |
| 540 | socklen_t addrlen = sizeof(addr_in); | 708 | socklen_t addrlen = sizeof(addr_in); |
| 541 | socklen_t* const p_addrlen = addr ? &addrlen : nullptr; | 709 | socklen_t* const p_addrlen = addr ? &addrlen : nullptr; |
| 542 | sockaddr* const p_addr_in = addr ? &addr_in : nullptr; | 710 | sockaddr* const p_addr_in = addr ? reinterpret_cast<sockaddr*>(&addr_in) : nullptr; |
| 543 | 711 | ||
| 544 | const auto result = recvfrom(fd, reinterpret_cast<char*>(message.data()), | 712 | const auto result = recvfrom(fd, reinterpret_cast<char*>(message.data()), |
| 545 | static_cast<int>(message.size()), 0, p_addr_in, p_addrlen); | 713 | static_cast<int>(message.size()), 0, p_addr_in, p_addrlen); |
| 546 | if (result != SOCKET_ERROR) { | 714 | if (result != SOCKET_ERROR) { |
| 547 | if (addr) { | 715 | if (addr) { |
| 548 | ASSERT(addrlen == sizeof(addr_in)); | 716 | *addr = TranslateToSockAddrIn(addr_in, addrlen); |
| 549 | *addr = TranslateToSockAddrIn(addr_in); | ||
| 550 | } | 717 | } |
| 551 | return {static_cast<s32>(result), Errno::SUCCESS}; | 718 | return {static_cast<s32>(result), Errno::SUCCESS}; |
| 552 | } | 719 | } |
| @@ -597,6 +764,11 @@ Errno Socket::Close() { | |||
| 597 | return Errno::SUCCESS; | 764 | return Errno::SUCCESS; |
| 598 | } | 765 | } |
| 599 | 766 | ||
| 767 | std::pair<Errno, Errno> Socket::GetPendingError() { | ||
| 768 | auto [pending_err, getsockopt_err] = GetSockOpt<int>(fd, SO_ERROR); | ||
| 769 | return {TranslateNativeError(pending_err), getsockopt_err}; | ||
| 770 | } | ||
| 771 | |||
| 600 | Errno Socket::SetLinger(bool enable, u32 linger) { | 772 | Errno Socket::SetLinger(bool enable, u32 linger) { |
| 601 | return SetSockOpt(fd, SO_LINGER, MakeLinger(enable, linger)); | 773 | return SetSockOpt(fd, SO_LINGER, MakeLinger(enable, linger)); |
| 602 | } | 774 | } |
diff --git a/src/core/internal_network/network.h b/src/core/internal_network/network.h index 1e09a007a..badcb8369 100644 --- a/src/core/internal_network/network.h +++ b/src/core/internal_network/network.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <optional> | 7 | #include <optional> |
| 8 | #include <vector> | ||
| 8 | 9 | ||
| 9 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| @@ -16,6 +17,11 @@ | |||
| 16 | #include <netinet/in.h> | 17 | #include <netinet/in.h> |
| 17 | #endif | 18 | #endif |
| 18 | 19 | ||
| 20 | namespace Common { | ||
| 21 | template <typename T, typename E> | ||
| 22 | class Expected; | ||
| 23 | } | ||
| 24 | |||
| 19 | namespace Network { | 25 | namespace Network { |
| 20 | 26 | ||
| 21 | class SocketBase; | 27 | class SocketBase; |
| @@ -36,6 +42,26 @@ enum class Errno { | |||
| 36 | NETUNREACH, | 42 | NETUNREACH, |
| 37 | TIMEDOUT, | 43 | TIMEDOUT, |
| 38 | MSGSIZE, | 44 | MSGSIZE, |
| 45 | INPROGRESS, | ||
| 46 | OTHER, | ||
| 47 | }; | ||
| 48 | |||
| 49 | enum class GetAddrInfoError { | ||
| 50 | SUCCESS, | ||
| 51 | ADDRFAMILY, | ||
| 52 | AGAIN, | ||
| 53 | BADFLAGS, | ||
| 54 | FAIL, | ||
| 55 | FAMILY, | ||
| 56 | MEMORY, | ||
| 57 | NODATA, | ||
| 58 | NONAME, | ||
| 59 | SERVICE, | ||
| 60 | SOCKTYPE, | ||
| 61 | SYSTEM, | ||
| 62 | BADHINTS, | ||
| 63 | PROTOCOL, | ||
| 64 | OVERFLOW_, | ||
| 39 | OTHER, | 65 | OTHER, |
| 40 | }; | 66 | }; |
| 41 | 67 | ||
| @@ -49,6 +75,9 @@ enum class PollEvents : u16 { | |||
| 49 | Err = 1 << 3, | 75 | Err = 1 << 3, |
| 50 | Hup = 1 << 4, | 76 | Hup = 1 << 4, |
| 51 | Nval = 1 << 5, | 77 | Nval = 1 << 5, |
| 78 | RdNorm = 1 << 6, | ||
| 79 | RdBand = 1 << 7, | ||
| 80 | WrBand = 1 << 8, | ||
| 52 | }; | 81 | }; |
| 53 | 82 | ||
| 54 | DECLARE_ENUM_FLAG_OPERATORS(PollEvents); | 83 | DECLARE_ENUM_FLAG_OPERATORS(PollEvents); |
| @@ -82,4 +111,11 @@ constexpr IPv4Address TranslateIPv4(in_addr addr) { | |||
| 82 | /// @return human ordered IPv4 address (e.g. 192.168.0.1) as an array | 111 | /// @return human ordered IPv4 address (e.g. 192.168.0.1) as an array |
| 83 | std::optional<IPv4Address> GetHostIPv4Address(); | 112 | std::optional<IPv4Address> GetHostIPv4Address(); |
| 84 | 113 | ||
| 114 | std::string IPv4AddressToString(IPv4Address ip_addr); | ||
| 115 | u32 IPv4AddressToInteger(IPv4Address ip_addr); | ||
| 116 | |||
| 117 | // named to avoid name collision with Windows macro | ||
| 118 | Common::Expected<std::vector<AddrInfo>, GetAddrInfoError> GetAddressInfo( | ||
| 119 | const std::string& host, const std::optional<std::string>& service); | ||
| 120 | |||
| 85 | } // namespace Network | 121 | } // namespace Network |
diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp index 7a77171c2..44e9e3093 100644 --- a/src/core/internal_network/socket_proxy.cpp +++ b/src/core/internal_network/socket_proxy.cpp | |||
| @@ -98,7 +98,7 @@ Errno ProxySocket::Shutdown(ShutdownHow how) { | |||
| 98 | return Errno::SUCCESS; | 98 | return Errno::SUCCESS; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | std::pair<s32, Errno> ProxySocket::Recv(int flags, std::vector<u8>& message) { | 101 | std::pair<s32, Errno> ProxySocket::Recv(int flags, std::span<u8> message) { |
| 102 | LOG_WARNING(Network, "(STUBBED) called"); | 102 | LOG_WARNING(Network, "(STUBBED) called"); |
| 103 | ASSERT(flags == 0); | 103 | ASSERT(flags == 0); |
| 104 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); | 104 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); |
| @@ -106,7 +106,7 @@ std::pair<s32, Errno> ProxySocket::Recv(int flags, std::vector<u8>& message) { | |||
| 106 | return {static_cast<s32>(0), Errno::SUCCESS}; | 106 | return {static_cast<s32>(0), Errno::SUCCESS}; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | std::pair<s32, Errno> ProxySocket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) { | 109 | std::pair<s32, Errno> ProxySocket::RecvFrom(int flags, std::span<u8> message, SockAddrIn* addr) { |
| 110 | ASSERT(flags == 0); | 110 | ASSERT(flags == 0); |
| 111 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); | 111 | ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max())); |
| 112 | 112 | ||
| @@ -140,8 +140,8 @@ std::pair<s32, Errno> ProxySocket::RecvFrom(int flags, std::vector<u8>& message, | |||
| 140 | } | 140 | } |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::vector<u8>& message, | 143 | std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::span<u8> message, SockAddrIn* addr, |
| 144 | SockAddrIn* addr, std::size_t max_length) { | 144 | std::size_t max_length) { |
| 145 | ProxyPacket& packet = received_packets.front(); | 145 | ProxyPacket& packet = received_packets.front(); |
| 146 | if (addr) { | 146 | if (addr) { |
| 147 | addr->family = Domain::INET; | 147 | addr->family = Domain::INET; |
| @@ -153,10 +153,7 @@ std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::vector<u8>& mes | |||
| 153 | std::size_t read_bytes; | 153 | std::size_t read_bytes; |
| 154 | if (packet.data.size() > max_length) { | 154 | if (packet.data.size() > max_length) { |
| 155 | read_bytes = max_length; | 155 | read_bytes = max_length; |
| 156 | message.clear(); | 156 | memcpy(message.data(), packet.data.data(), max_length); |
| 157 | std::copy(packet.data.begin(), packet.data.begin() + read_bytes, | ||
| 158 | std::back_inserter(message)); | ||
| 159 | message.resize(max_length); | ||
| 160 | 157 | ||
| 161 | if (protocol == Protocol::UDP) { | 158 | if (protocol == Protocol::UDP) { |
| 162 | if (!peek) { | 159 | if (!peek) { |
| @@ -171,9 +168,7 @@ std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::vector<u8>& mes | |||
| 171 | } | 168 | } |
| 172 | } else { | 169 | } else { |
| 173 | read_bytes = packet.data.size(); | 170 | read_bytes = packet.data.size(); |
| 174 | message.clear(); | 171 | memcpy(message.data(), packet.data.data(), read_bytes); |
| 175 | std::copy(packet.data.begin(), packet.data.end(), std::back_inserter(message)); | ||
| 176 | message.resize(max_length); | ||
| 177 | if (!peek) { | 172 | if (!peek) { |
| 178 | received_packets.pop(); | 173 | received_packets.pop(); |
| 179 | } | 174 | } |
| @@ -293,6 +288,11 @@ Errno ProxySocket::SetNonBlock(bool enable) { | |||
| 293 | return Errno::SUCCESS; | 288 | return Errno::SUCCESS; |
| 294 | } | 289 | } |
| 295 | 290 | ||
| 291 | std::pair<Errno, Errno> ProxySocket::GetPendingError() { | ||
| 292 | LOG_DEBUG(Network, "(STUBBED) called"); | ||
| 293 | return {Errno::SUCCESS, Errno::SUCCESS}; | ||
| 294 | } | ||
| 295 | |||
| 296 | bool ProxySocket::IsOpened() const { | 296 | bool ProxySocket::IsOpened() const { |
| 297 | return fd != INVALID_SOCKET; | 297 | return fd != INVALID_SOCKET; |
| 298 | } | 298 | } |
diff --git a/src/core/internal_network/socket_proxy.h b/src/core/internal_network/socket_proxy.h index 6e991fa38..e12c413d1 100644 --- a/src/core/internal_network/socket_proxy.h +++ b/src/core/internal_network/socket_proxy.h | |||
| @@ -39,11 +39,11 @@ public: | |||
| 39 | 39 | ||
| 40 | Errno Shutdown(ShutdownHow how) override; | 40 | Errno Shutdown(ShutdownHow how) override; |
| 41 | 41 | ||
| 42 | std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message) override; | 42 | std::pair<s32, Errno> Recv(int flags, std::span<u8> message) override; |
| 43 | 43 | ||
| 44 | std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) override; | 44 | std::pair<s32, Errno> RecvFrom(int flags, std::span<u8> message, SockAddrIn* addr) override; |
| 45 | 45 | ||
| 46 | std::pair<s32, Errno> ReceivePacket(int flags, std::vector<u8>& message, SockAddrIn* addr, | 46 | std::pair<s32, Errno> ReceivePacket(int flags, std::span<u8> message, SockAddrIn* addr, |
| 47 | std::size_t max_length); | 47 | std::size_t max_length); |
| 48 | 48 | ||
| 49 | std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override; | 49 | std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override; |
| @@ -74,6 +74,8 @@ public: | |||
| 74 | template <typename T> | 74 | template <typename T> |
| 75 | Errno SetSockOpt(SOCKET fd, int option, T value); | 75 | Errno SetSockOpt(SOCKET fd, int option, T value); |
| 76 | 76 | ||
| 77 | std::pair<Errno, Errno> GetPendingError() override; | ||
| 78 | |||
| 77 | bool IsOpened() const override; | 79 | bool IsOpened() const override; |
| 78 | 80 | ||
| 79 | private: | 81 | private: |
diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h index 11e479e50..46a53ef79 100644 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h | |||
| @@ -59,10 +59,9 @@ public: | |||
| 59 | 59 | ||
| 60 | virtual Errno Shutdown(ShutdownHow how) = 0; | 60 | virtual Errno Shutdown(ShutdownHow how) = 0; |
| 61 | 61 | ||
| 62 | virtual std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message) = 0; | 62 | virtual std::pair<s32, Errno> Recv(int flags, std::span<u8> message) = 0; |
| 63 | 63 | ||
| 64 | virtual std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, | 64 | virtual std::pair<s32, Errno> RecvFrom(int flags, std::span<u8> message, SockAddrIn* addr) = 0; |
| 65 | SockAddrIn* addr) = 0; | ||
| 66 | 65 | ||
| 67 | virtual std::pair<s32, Errno> Send(std::span<const u8> message, int flags) = 0; | 66 | virtual std::pair<s32, Errno> Send(std::span<const u8> message, int flags) = 0; |
| 68 | 67 | ||
| @@ -87,6 +86,8 @@ public: | |||
| 87 | 86 | ||
| 88 | virtual Errno SetNonBlock(bool enable) = 0; | 87 | virtual Errno SetNonBlock(bool enable) = 0; |
| 89 | 88 | ||
| 89 | virtual std::pair<Errno, Errno> GetPendingError() = 0; | ||
| 90 | |||
| 90 | virtual bool IsOpened() const = 0; | 91 | virtual bool IsOpened() const = 0; |
| 91 | 92 | ||
| 92 | virtual void HandleProxyPacket(const ProxyPacket& packet) = 0; | 93 | virtual void HandleProxyPacket(const ProxyPacket& packet) = 0; |
| @@ -126,9 +127,9 @@ public: | |||
| 126 | 127 | ||
| 127 | Errno Shutdown(ShutdownHow how) override; | 128 | Errno Shutdown(ShutdownHow how) override; |
| 128 | 129 | ||
| 129 | std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message) override; | 130 | std::pair<s32, Errno> Recv(int flags, std::span<u8> message) override; |
| 130 | 131 | ||
| 131 | std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) override; | 132 | std::pair<s32, Errno> RecvFrom(int flags, std::span<u8> message, SockAddrIn* addr) override; |
| 132 | 133 | ||
| 133 | std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override; | 134 | std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override; |
| 134 | 135 | ||
| @@ -156,6 +157,11 @@ public: | |||
| 156 | template <typename T> | 157 | template <typename T> |
| 157 | Errno SetSockOpt(SOCKET fd, int option, T value); | 158 | Errno SetSockOpt(SOCKET fd, int option, T value); |
| 158 | 159 | ||
| 160 | std::pair<Errno, Errno> GetPendingError() override; | ||
| 161 | |||
| 162 | template <typename T> | ||
| 163 | std::pair<T, Errno> GetSockOpt(SOCKET fd, int option); | ||
| 164 | |||
| 159 | bool IsOpened() const override; | 165 | bool IsOpened() const override; |
| 160 | 166 | ||
| 161 | void HandleProxyPacket(const ProxyPacket& packet) override; | 167 | void HandleProxyPacket(const ProxyPacket& packet) override; |