增加文件传输功能
This commit is contained in:
@@ -19,6 +19,9 @@ set(SOURCES
|
||||
NetworkSender.h
|
||||
IddBridge.cpp
|
||||
IddBridge.h
|
||||
TcpServer.cpp
|
||||
TcpServer.h
|
||||
FileTransferProtocol.h
|
||||
)
|
||||
|
||||
add_executable(WindowsSenderDemo ${SOURCES})
|
||||
|
||||
46
demo/windows_sender/FileTransferProtocol.h
Normal file
46
demo/windows_sender/FileTransferProtocol.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Port for TCP Control & File Transfer
|
||||
constexpr int FILE_TRANSFER_PORT = 8889;
|
||||
|
||||
enum class PacketType : uint8_t {
|
||||
// Control Events
|
||||
Handshake = 0x01,
|
||||
MouseEvent = 0x02,
|
||||
KeyboardEvent = 0x03,
|
||||
|
||||
// File Transfer
|
||||
FileHeader = 0x10, // Metadata: Name, Size
|
||||
FileData = 0x11, // Chunk of data
|
||||
FileEnd = 0x12, // End of transfer
|
||||
FileAck = 0x13, // Acknowledge receipt
|
||||
FileError = 0x14 // Error during transfer
|
||||
|
||||
,
|
||||
FolderHeader = 0x20,
|
||||
DirEntry = 0x21,
|
||||
FileHeaderV2 = 0x22,
|
||||
FolderEnd = 0x23
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct CommonHeader {
|
||||
uint8_t type;
|
||||
uint32_t payloadSize;
|
||||
};
|
||||
|
||||
// Payload for FileHeader (Type 0x10)
|
||||
struct FileMetadata {
|
||||
uint64_t fileSize;
|
||||
char fileName[256]; // UTF-8 encoded
|
||||
};
|
||||
|
||||
// Payload for FileAck (Type 0x13)
|
||||
struct FileAckPayload {
|
||||
uint8_t status; // 0 = OK, 1 = Error
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
418
demo/windows_sender/TcpServer.cpp
Normal file
418
demo/windows_sender/TcpServer.cpp
Normal file
@@ -0,0 +1,418 @@
|
||||
#include "TcpServer.h"
|
||||
#include "FileTransferProtocol.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
TcpServer::TcpServer() = default;
|
||||
|
||||
TcpServer::~TcpServer() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
bool TcpServer::Start(int port) {
|
||||
if (running_) return true;
|
||||
|
||||
// Initialize Winsock
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
std::cerr << "WSAStartup failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
listenSocket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (listenSocket_ == INVALID_SOCKET) {
|
||||
std::cerr << "Socket creation failed" << std::endl;
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
sockaddr_in serverAddr;
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_addr.s_addr = INADDR_ANY;
|
||||
serverAddr.sin_port = htons(port);
|
||||
|
||||
if (bind(listenSocket_, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
|
||||
std::cerr << "Bind failed" << std::endl;
|
||||
closesocket(listenSocket_);
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (listen(listenSocket_, 1) == SOCKET_ERROR) {
|
||||
std::cerr << "Listen failed" << std::endl;
|
||||
closesocket(listenSocket_);
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
running_ = true;
|
||||
acceptThread_ = std::thread(&TcpServer::AcceptLoop, this);
|
||||
|
||||
std::cout << "TCP Server started on port " << port << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TcpServer::Stop() {
|
||||
running_ = false;
|
||||
if (listenSocket_ != INVALID_SOCKET) {
|
||||
closesocket(listenSocket_);
|
||||
listenSocket_ = INVALID_SOCKET;
|
||||
}
|
||||
if (clientSocket_ != INVALID_SOCKET) {
|
||||
closesocket(clientSocket_);
|
||||
clientSocket_ = INVALID_SOCKET;
|
||||
}
|
||||
if (acceptThread_.joinable()) acceptThread_.join();
|
||||
if (clientThread_.joinable()) clientThread_.join();
|
||||
|
||||
// Close any open file stream
|
||||
if (currentFileStream_) {
|
||||
currentFileStream_->close();
|
||||
delete currentFileStream_;
|
||||
currentFileStream_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TcpServer::AcceptLoop() {
|
||||
while (running_) {
|
||||
sockaddr_in clientAddr;
|
||||
int clientAddrLen = sizeof(clientAddr);
|
||||
SOCKET client = accept(listenSocket_, (sockaddr*)&clientAddr, &clientAddrLen);
|
||||
|
||||
if (client == INVALID_SOCKET) {
|
||||
if (running_) std::cerr << "Accept failed" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << "Client connected for File Transfer" << std::endl;
|
||||
|
||||
// Close previous client if any
|
||||
if (clientSocket_ != INVALID_SOCKET) {
|
||||
closesocket(clientSocket_);
|
||||
if (clientThread_.joinable()) clientThread_.join();
|
||||
}
|
||||
|
||||
clientSocket_ = client;
|
||||
clientThread_ = std::thread(&TcpServer::ClientHandler, this, clientSocket_);
|
||||
}
|
||||
}
|
||||
|
||||
void TcpServer::ClientHandler(SOCKET clientSocket) {
|
||||
while (running_) {
|
||||
CommonHeader header;
|
||||
if (!ReceiveBytes(clientSocket, &header, sizeof(header))) {
|
||||
std::cout << "Client disconnected" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> payload(header.payloadSize);
|
||||
if (header.payloadSize > 0) {
|
||||
if (!ReceiveBytes(clientSocket, payload.data(), header.payloadSize)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PacketType type = static_cast<PacketType>(header.type);
|
||||
switch (type) {
|
||||
case PacketType::FileHeader:
|
||||
HandleFileHeader(clientSocket, payload);
|
||||
break;
|
||||
case PacketType::FileData:
|
||||
HandleFileData(payload);
|
||||
break;
|
||||
case PacketType::FileEnd:
|
||||
HandleFileEnd();
|
||||
break;
|
||||
case PacketType::FolderHeader:
|
||||
HandleFolderHeader(payload);
|
||||
break;
|
||||
case PacketType::DirEntry:
|
||||
HandleDirEntry(payload);
|
||||
break;
|
||||
case PacketType::FileHeaderV2:
|
||||
HandleFileHeaderV2(payload);
|
||||
break;
|
||||
case PacketType::FolderEnd:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
closesocket(clientSocket);
|
||||
clientSocket_ = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
bool TcpServer::ReceiveBytes(SOCKET sock, void* buffer, int size) {
|
||||
char* ptr = (char*)buffer;
|
||||
int remaining = size;
|
||||
while (remaining > 0) {
|
||||
int received = recv(sock, ptr, remaining, 0);
|
||||
if (received <= 0) return false;
|
||||
ptr += received;
|
||||
remaining -= received;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TcpServer::SendBytes(SOCKET sock, const void* buffer, int size) {
|
||||
const char* ptr = (const char*)buffer;
|
||||
int remaining = size;
|
||||
while (remaining > 0) {
|
||||
int sent = send(sock, ptr, remaining, 0);
|
||||
if (sent <= 0) return false;
|
||||
ptr += sent;
|
||||
remaining -= sent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TcpServer::HandleFileHeader(SOCKET sock, const std::vector<uint8_t>& payload) {
|
||||
if (payload.size() < sizeof(FileMetadata)) return;
|
||||
const FileMetadata* meta = reinterpret_cast<const FileMetadata*>(payload.data());
|
||||
|
||||
std::lock_guard<std::mutex> lock(fileMutex_);
|
||||
|
||||
// Save to Desktop by default
|
||||
std::string desktopPath = getenv("USERPROFILE");
|
||||
desktopPath += "\\Desktop\\";
|
||||
|
||||
currentFileName_ = desktopPath + std::string(meta->fileName);
|
||||
currentFileSize_ = meta->fileSize;
|
||||
receivedBytes_ = 0;
|
||||
|
||||
if (currentFileStream_) {
|
||||
delete currentFileStream_;
|
||||
}
|
||||
currentFileStream_ = new std::ofstream(currentFileName_, std::ios::binary);
|
||||
|
||||
std::cout << "Receiving file: " << currentFileName_ << " (" << currentFileSize_ << " bytes)" << std::endl;
|
||||
}
|
||||
|
||||
void TcpServer::HandleFileData(const std::vector<uint8_t>& payload) {
|
||||
std::lock_guard<std::mutex> lock(fileMutex_);
|
||||
if (currentFileStream_ && currentFileStream_->is_open()) {
|
||||
currentFileStream_->write((const char*)payload.data(), payload.size());
|
||||
receivedBytes_ += payload.size();
|
||||
|
||||
// Optional: Progress log
|
||||
// std::cout << "\rProgress: " << (receivedBytes_ * 100 / currentFileSize_) << "%" << std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
void TcpServer::HandleFileEnd() {
|
||||
std::lock_guard<std::mutex> lock(fileMutex_);
|
||||
if (currentFileStream_) {
|
||||
currentFileStream_->close();
|
||||
delete currentFileStream_;
|
||||
currentFileStream_ = nullptr;
|
||||
std::cout << "\nFile received successfully!" << std::endl;
|
||||
|
||||
if (fileReceivedCallback_) {
|
||||
fileReceivedCallback_(currentFileName_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TcpServer::SendFile(const std::string& filePath) {
|
||||
if (clientSocket_ == INVALID_SOCKET) {
|
||||
std::cerr << "No client connected" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ifstream file(filePath, std::ios::binary | std::ios::ate);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "Cannot open file: " << filePath << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t fileSize = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
fs::path p(filePath);
|
||||
std::string filename = p.filename().string();
|
||||
|
||||
// 1. Send Header
|
||||
CommonHeader header;
|
||||
header.type = (uint8_t)PacketType::FileHeader;
|
||||
header.payloadSize = sizeof(FileMetadata);
|
||||
|
||||
FileMetadata meta;
|
||||
meta.fileSize = fileSize;
|
||||
strncpy_s(meta.fileName, filename.c_str(), sizeof(meta.fileName) - 1);
|
||||
|
||||
if (!SendBytes(clientSocket_, &header, sizeof(header))) return false;
|
||||
if (!SendBytes(clientSocket_, &meta, sizeof(meta))) return false;
|
||||
|
||||
// 2. Send Data
|
||||
const int CHUNK_SIZE = 64 * 1024; // 64KB
|
||||
std::vector<char> buffer(CHUNK_SIZE);
|
||||
|
||||
uint64_t sent = 0;
|
||||
while (sent < fileSize) {
|
||||
file.read(buffer.data(), CHUNK_SIZE);
|
||||
int bytesRead = (int)file.gcount();
|
||||
|
||||
CommonHeader dataHeader;
|
||||
dataHeader.type = (uint8_t)PacketType::FileData;
|
||||
dataHeader.payloadSize = bytesRead;
|
||||
|
||||
if (!SendBytes(clientSocket_, &dataHeader, sizeof(dataHeader))) return false;
|
||||
if (!SendBytes(clientSocket_, buffer.data(), bytesRead)) return false;
|
||||
|
||||
sent += bytesRead;
|
||||
std::cout << "\rSending: " << (sent * 100 / fileSize) << "%" << std::flush;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
// 3. Send End
|
||||
CommonHeader endHeader;
|
||||
endHeader.type = (uint8_t)PacketType::FileEnd;
|
||||
endHeader.payloadSize = 0;
|
||||
SendBytes(clientSocket_, &endHeader, sizeof(endHeader));
|
||||
|
||||
std::cout << "File sent successfully" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TcpServer::SetFileReceivedCallback(FileReceivedCallback cb) {
|
||||
fileReceivedCallback_ = cb;
|
||||
}
|
||||
bool TcpServer::SendFolder(const std::string& folderPath) {
|
||||
if (clientSocket_ == INVALID_SOCKET) {
|
||||
std::cerr << "No client connected" << std::endl;
|
||||
return false;
|
||||
}
|
||||
fs::path root(folderPath);
|
||||
if (!fs::exists(root) || !fs::is_directory(root)) {
|
||||
std::cerr << "Invalid folder: " << folderPath << std::endl;
|
||||
return false;
|
||||
}
|
||||
std::string rootName = root.filename().string();
|
||||
{
|
||||
CommonHeader hdr;
|
||||
hdr.type = (uint8_t)PacketType::FolderHeader;
|
||||
hdr.payloadSize = (uint32_t)rootName.size();
|
||||
if (!SendBytes(clientSocket_, &hdr, sizeof(hdr))) return false;
|
||||
if (hdr.payloadSize > 0) {
|
||||
if (!SendBytes(clientSocket_, rootName.data(), (int)rootName.size())) return false;
|
||||
}
|
||||
}
|
||||
auto norm = [](std::string s) {
|
||||
for (auto& c : s) if (c == '\\') c = '/';
|
||||
return s;
|
||||
};
|
||||
for (auto it = fs::recursive_directory_iterator(root); it != fs::recursive_directory_iterator(); ++it) {
|
||||
const fs::path p = it->path();
|
||||
fs::path rel = fs::relative(p, root);
|
||||
std::string relStr = norm(rel.string());
|
||||
if (it->is_directory()) {
|
||||
CommonHeader hdr;
|
||||
hdr.type = (uint8_t)PacketType::DirEntry;
|
||||
hdr.payloadSize = (uint32_t)relStr.size();
|
||||
if (!SendBytes(clientSocket_, &hdr, sizeof(hdr))) return false;
|
||||
if (hdr.payloadSize > 0) {
|
||||
if (!SendBytes(clientSocket_, relStr.data(), (int)relStr.size())) return false;
|
||||
}
|
||||
} else if (it->is_regular_file()) {
|
||||
uint64_t fileSize = (uint64_t)fs::file_size(p);
|
||||
std::vector<uint8_t> header;
|
||||
uint16_t pathLen = (uint16_t)std::min<size_t>(relStr.size(), 65535);
|
||||
header.resize(8 + 2 + pathLen);
|
||||
std::memcpy(header.data(), &fileSize, 8);
|
||||
std::memcpy(header.data() + 8, &pathLen, 2);
|
||||
std::memcpy(header.data() + 10, relStr.data(), pathLen);
|
||||
CommonHeader hdr;
|
||||
hdr.type = (uint8_t)PacketType::FileHeaderV2;
|
||||
hdr.payloadSize = (uint32_t)header.size();
|
||||
if (!SendBytes(clientSocket_, &hdr, sizeof(hdr))) return false;
|
||||
if (!SendBytes(clientSocket_, header.data(), (int)header.size())) return false;
|
||||
std::ifstream file(p, std::ios::binary);
|
||||
if (!file.is_open()) continue;
|
||||
const int CHUNK_SIZE = 64 * 1024;
|
||||
std::vector<char> buffer(CHUNK_SIZE);
|
||||
while (file) {
|
||||
file.read(buffer.data(), CHUNK_SIZE);
|
||||
int bytesRead = (int)file.gcount();
|
||||
if (bytesRead <= 0) break;
|
||||
CommonHeader dh;
|
||||
dh.type = (uint8_t)PacketType::FileData;
|
||||
dh.payloadSize = bytesRead;
|
||||
if (!SendBytes(clientSocket_, &dh, sizeof(dh))) { file.close(); return false; }
|
||||
if (!SendBytes(clientSocket_, buffer.data(), bytesRead)) { file.close(); return false; }
|
||||
}
|
||||
file.close();
|
||||
CommonHeader endH;
|
||||
endH.type = (uint8_t)PacketType::FileEnd;
|
||||
endH.payloadSize = 0;
|
||||
if (!SendBytes(clientSocket_, &endH, sizeof(endH))) return false;
|
||||
}
|
||||
}
|
||||
CommonHeader fin;
|
||||
fin.type = (uint8_t)PacketType::FolderEnd;
|
||||
fin.payloadSize = 0;
|
||||
if (!SendBytes(clientSocket_, &fin, sizeof(fin))) return false;
|
||||
std::cout << "Folder sent successfully" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TcpServer::HandleFolderHeader(const std::vector<uint8_t>& payload) {
|
||||
std::string desktopPath = getenv("USERPROFILE");
|
||||
desktopPath += "\\Desktop\\";
|
||||
std::string rootName;
|
||||
if (!payload.empty()) {
|
||||
rootName.assign(reinterpret_cast<const char*>(payload.data()), payload.size());
|
||||
size_t pos = rootName.find('\0');
|
||||
if (pos != std::string::npos) rootName = rootName.substr(0, pos);
|
||||
} else {
|
||||
rootName = "AndroidFolder";
|
||||
}
|
||||
baseFolderRoot_ = desktopPath + rootName;
|
||||
try {
|
||||
fs::create_directories(baseFolderRoot_);
|
||||
} catch (...) {}
|
||||
std::cout << "Receiving folder: " << baseFolderRoot_ << std::endl;
|
||||
}
|
||||
|
||||
void TcpServer::HandleDirEntry(const std::vector<uint8_t>& payload) {
|
||||
if (baseFolderRoot_.empty()) return;
|
||||
std::string rel;
|
||||
rel.assign(reinterpret_cast<const char*>(payload.data()), payload.size());
|
||||
size_t pos = rel.find('\0');
|
||||
if (pos != std::string::npos) rel = rel.substr(0, pos);
|
||||
std::string path = baseFolderRoot_ + "\\" + rel;
|
||||
try {
|
||||
fs::create_directories(path);
|
||||
} catch (...) {}
|
||||
std::cout << "Create dir: " << path << std::endl;
|
||||
}
|
||||
|
||||
void TcpServer::HandleFileHeaderV2(const std::vector<uint8_t>& payload) {
|
||||
if (payload.size() < sizeof(uint64_t) + sizeof(uint16_t)) return;
|
||||
const uint8_t* p = payload.data();
|
||||
uint64_t sz = *reinterpret_cast<const uint64_t*>(p);
|
||||
p += sizeof(uint64_t);
|
||||
uint16_t pathLen = *reinterpret_cast<const uint16_t*>(p);
|
||||
p += sizeof(uint16_t);
|
||||
if (payload.size() < sizeof(uint64_t) + sizeof(uint16_t) + pathLen) return;
|
||||
std::string rel(reinterpret_cast<const char*>(p), pathLen);
|
||||
std::string full = baseFolderRoot_.empty() ? rel : (baseFolderRoot_ + "\\" + rel);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fileMutex_);
|
||||
if (currentFileStream_) {
|
||||
delete currentFileStream_;
|
||||
currentFileStream_ = nullptr;
|
||||
}
|
||||
currentFileName_ = full;
|
||||
currentFileSize_ = sz;
|
||||
receivedBytes_ = 0;
|
||||
fs::create_directories(fs::path(full).parent_path());
|
||||
currentFileStream_ = new std::ofstream(full, std::ios::binary);
|
||||
}
|
||||
std::cout << "Receiving file: " << full << " (" << sz << " bytes)" << std::endl;
|
||||
}
|
||||
59
demo/windows_sender/TcpServer.h
Normal file
59
demo/windows_sender/TcpServer.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <winsock2.h>
|
||||
|
||||
class TcpServer {
|
||||
public:
|
||||
TcpServer();
|
||||
~TcpServer();
|
||||
|
||||
bool Start(int port);
|
||||
void Stop();
|
||||
|
||||
// Send a file to the connected client
|
||||
bool SendFile(const std::string& filePath);
|
||||
bool SendFolder(const std::string& folderPath);
|
||||
|
||||
// Set callback for received files
|
||||
// Callback signature: (filename, data) -> void
|
||||
// Note: For large files, we should probably stream to disk directly,
|
||||
// but for simplicity in this demo, we might just notify path.
|
||||
using FileReceivedCallback = std::function<void(const std::string& filename)>;
|
||||
void SetFileReceivedCallback(FileReceivedCallback cb);
|
||||
|
||||
private:
|
||||
void AcceptLoop();
|
||||
void ClientHandler(SOCKET clientSocket);
|
||||
bool ReceiveBytes(SOCKET sock, void* buffer, int size);
|
||||
bool SendBytes(SOCKET sock, const void* buffer, int size);
|
||||
|
||||
// File receiving logic
|
||||
void HandleFileHeader(SOCKET sock, const std::vector<uint8_t>& payload);
|
||||
void HandleFileData(const std::vector<uint8_t>& payload);
|
||||
void HandleFileEnd();
|
||||
void HandleFolderHeader(const std::vector<uint8_t>& payload);
|
||||
void HandleDirEntry(const std::vector<uint8_t>& payload);
|
||||
void HandleFileHeaderV2(const std::vector<uint8_t>& payload);
|
||||
|
||||
SOCKET listenSocket_ = INVALID_SOCKET;
|
||||
SOCKET clientSocket_ = INVALID_SOCKET; // Only support 1 client for now
|
||||
std::thread acceptThread_;
|
||||
std::thread clientThread_;
|
||||
std::atomic<bool> running_ = false;
|
||||
|
||||
FileReceivedCallback fileReceivedCallback_;
|
||||
|
||||
// Current receiving state
|
||||
std::string currentFileName_;
|
||||
uint64_t currentFileSize_ = 0;
|
||||
uint64_t receivedBytes_ = 0;
|
||||
std::ofstream* currentFileStream_ = nullptr;
|
||||
std::mutex fileMutex_;
|
||||
std::string baseFolderRoot_;
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "ScreenCapture.h"
|
||||
#include "IddBridge.h"
|
||||
#include "VideoEncoder.h"
|
||||
#include "TcpServer.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
@@ -18,6 +19,8 @@ int main(int argc, char* argv[]) {
|
||||
int outputIndex = -1;
|
||||
bool iddProducer = false;
|
||||
int producerOutputIndex = -1;
|
||||
std::string fileToSend = "";
|
||||
std::string folderToSend = "";
|
||||
|
||||
if (argc > 1) ipStr = argv[1];
|
||||
if (argc > 2) port = std::stoi(argv[2]);
|
||||
@@ -36,6 +39,10 @@ int main(int argc, char* argv[]) {
|
||||
try {
|
||||
producerOutputIndex = std::stoi(arg.substr(std::string("--producer-output=").size()));
|
||||
} catch (...) {}
|
||||
} else if (arg.rfind("--send-file=", 0) == 0) {
|
||||
fileToSend = arg.substr(std::string("--send-file=").size());
|
||||
} else if (arg.rfind("--send-folder=", 0) == 0) {
|
||||
folderToSend = arg.substr(std::string("--send-folder=").size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +76,39 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
// Start TCP Server
|
||||
TcpServer tcpServer;
|
||||
if (tcpServer.Start(8889)) {
|
||||
// Wait for client to connect if we need to send a file immediately
|
||||
if (!fileToSend.empty()) {
|
||||
std::cout << "Waiting for client to connect to send file: " << fileToSend << "..." << std::endl;
|
||||
// Simple polling wait (in a real app, use events/condition variables)
|
||||
// But TcpServer::SendFile checks if client is connected.
|
||||
// We'll try to send in a loop or thread.
|
||||
std::thread([&tcpServer, fileToSend]() {
|
||||
// Wait for up to 30 seconds for a client
|
||||
for (int i = 0; i < 300; ++i) {
|
||||
if (tcpServer.SendFile(fileToSend)) {
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}).detach();
|
||||
} else if (!folderToSend.empty()) {
|
||||
std::cout << "Waiting for client to connect to send folder: " << folderToSend << "..." << std::endl;
|
||||
std::thread([&tcpServer, folderToSend]() {
|
||||
for (int i = 0; i < 300; ++i) {
|
||||
if (tcpServer.SendFolder(folderToSend)) {
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Failed to start TCP Server on port 8889" << std::endl;
|
||||
}
|
||||
|
||||
// Debug: Open file to save H.264 stream if filename is provided
|
||||
std::ofstream outFile;
|
||||
if (!outputFileName.empty()) {
|
||||
|
||||
Reference in New Issue
Block a user