| 553 | } |
| 554 | |
| 555 | bool Transfer::startReceiver(std::string& outError) |
| 556 | { |
| 557 | { |
| 558 | std::lock_guard<std::mutex> lock(g_receiverMutex); |
| 559 | if (g_receiverRunning) { |
| 560 | return true; |
| 561 | } |
| 562 | } |
| 563 | if (Server::getAddress().empty()) { |
| 564 | outError = "HTTP server not available."; |
| 565 | return false; |
| 566 | } |
| 567 | |
| 568 | g_failedAuthAttempts.store(0); |
| 569 | // A 4-digit PIN from srand(time) is trivially predictable; seed from the |
| 570 | // system CSPRNG so a LAN peer can't reconstruct it from the clock. |
| 571 | int pin = 1000 + (int)(randomGet64() % 9000); |
| 572 | std::string token = StringUtils::format("%04d", pin); |
| 573 | std::string ip = Server::getAddress(); |
| 574 | setReceiverNotice(""); |
| 575 | setReceiverCompletedName(""); |
| 576 | g_receiverCompleted.store(false); |
| 577 | g_completedTitleId.store(0); |
| 578 | size_t pos = ip.find("://"); |
| 579 | if (pos != std::string::npos) { |
| 580 | ip = ip.substr(pos + 3); |
| 581 | } |
| 582 | pos = ip.find(":"); |
| 583 | if (pos != std::string::npos) { |
| 584 | ip = ip.substr(0, pos); |
| 585 | } |
| 586 | |
| 587 | // Publish token/ip/port before the handler is reachable, so an upload that |
| 588 | // arrives the instant it registers validates against the real token. |
| 589 | { |
| 590 | std::lock_guard<std::mutex> lock(g_receiverMutex); |
| 591 | g_token = token; |
| 592 | g_receiverIp = ip; |
| 593 | g_receiverPort = TRANSFER_PORT; |
| 594 | } |
| 595 | |
| 596 | Server::registerHandler("/transfer/info", handleInfo); |
| 597 | Server::registerUploadHandler("/transfer/upload", TEMP_UPLOAD, handleUpload); |
| 598 | |
| 599 | { |
| 600 | std::lock_guard<std::mutex> lock(g_receiverMutex); |
| 601 | g_receiverRunning = true; |
| 602 | } |
| 603 | |
| 604 | return true; |
| 605 | } |
| 606 | |
| 607 | void Transfer::stopReceiver(void) |
| 608 | { |
nothing calls this directly
no test coverage detected