mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-10-15 22:08:53 -05:00
NetPlay: Implement chunked data transfer
This sends arbitrary packets in chunks to be reassembled at the other end, allowing large data transfers to be speed-limited and interleaved with other packets being sent. It also enables tracking the progress of large data transfers.
This commit is contained in:
@@ -112,7 +112,7 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay
|
||||
if (!traversal_config.use_traversal)
|
||||
{
|
||||
// Direct Connection
|
||||
m_client = enet_host_create(nullptr, 1, 3, 0, 0);
|
||||
m_client = enet_host_create(nullptr, 1, CHANNEL_COUNT, 0, 0);
|
||||
|
||||
if (m_client == nullptr)
|
||||
{
|
||||
@@ -124,7 +124,7 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay
|
||||
enet_address_set_host(&addr, address.c_str());
|
||||
addr.port = port;
|
||||
|
||||
m_server = enet_host_connect(m_client, &addr, 3, 0);
|
||||
m_server = enet_host_connect(m_client, &addr, CHANNEL_COUNT, 0);
|
||||
|
||||
if (m_server == nullptr)
|
||||
{
|
||||
@@ -338,6 +338,61 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_CHUNKED_DATA_START:
|
||||
{
|
||||
u32 cid;
|
||||
packet >> cid;
|
||||
std::string title;
|
||||
packet >> title;
|
||||
u64 data_size = Common::PacketReadU64(packet);
|
||||
|
||||
m_chunked_data_receive_queue.emplace(cid, sf::Packet{});
|
||||
|
||||
std::vector<int> players;
|
||||
players.push_back(m_local_player->pid);
|
||||
m_dialog->ShowChunkedProgressDialog(title, data_size, players);
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_CHUNKED_DATA_END:
|
||||
{
|
||||
u32 cid;
|
||||
packet >> cid;
|
||||
|
||||
OnData(m_chunked_data_receive_queue[cid]);
|
||||
m_chunked_data_receive_queue.erase(m_chunked_data_receive_queue.find(cid));
|
||||
m_dialog->HideChunkedProgressDialog();
|
||||
|
||||
sf::Packet complete_packet;
|
||||
complete_packet << static_cast<MessageId>(NP_MSG_CHUNKED_DATA_COMPLETE);
|
||||
complete_packet << cid;
|
||||
Send(complete_packet, CHUNKED_DATA_CHANNEL);
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_CHUNKED_DATA_PAYLOAD:
|
||||
{
|
||||
u32 cid;
|
||||
packet >> cid;
|
||||
|
||||
while (!packet.endOfPacket())
|
||||
{
|
||||
u8 byte;
|
||||
packet >> byte;
|
||||
m_chunked_data_receive_queue[cid] << byte;
|
||||
}
|
||||
|
||||
m_dialog->SetChunkedProgress(m_local_player->pid,
|
||||
m_chunked_data_receive_queue[cid].getDataSize());
|
||||
|
||||
sf::Packet progress_packet;
|
||||
progress_packet << static_cast<MessageId>(NP_MSG_CHUNKED_DATA_PROGRESS);
|
||||
progress_packet << cid;
|
||||
progress_packet << sf::Uint64{m_chunked_data_receive_queue[cid].getDataSize()};
|
||||
Send(progress_packet, CHUNKED_DATA_CHANNEL);
|
||||
}
|
||||
break;
|
||||
|
||||
case NP_MSG_PAD_MAPPING:
|
||||
{
|
||||
for (PadMapping& mapping : m_pad_map)
|
||||
@@ -1050,11 +1105,11 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NetPlayClient::Send(const sf::Packet& packet)
|
||||
void NetPlayClient::Send(const sf::Packet& packet, const u8 channel_id)
|
||||
{
|
||||
ENetPacket* epac =
|
||||
enet_packet_create(packet.getData(), packet.getDataSize(), ENET_PACKET_FLAG_RELIABLE);
|
||||
enet_peer_send(m_server, 0, epac);
|
||||
enet_peer_send(m_server, channel_id, epac);
|
||||
}
|
||||
|
||||
void NetPlayClient::DisplayPlayersPing()
|
||||
@@ -1104,11 +1159,11 @@ void NetPlayClient::Disconnect()
|
||||
m_server = nullptr;
|
||||
}
|
||||
|
||||
void NetPlayClient::SendAsync(sf::Packet&& packet)
|
||||
void NetPlayClient::SendAsync(sf::Packet&& packet, const u8 channel_id)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lkq(m_crit.async_queue_write);
|
||||
m_async_queue.Push(std::move(packet));
|
||||
m_async_queue.Push(AsyncQueueEntry{std::move(packet), channel_id});
|
||||
}
|
||||
ENetUtil::WakeupThread(m_client);
|
||||
}
|
||||
@@ -1136,7 +1191,10 @@ void NetPlayClient::ThreadFunc()
|
||||
net = enet_host_service(m_client, &netEvent, 250);
|
||||
while (!m_async_queue.Empty())
|
||||
{
|
||||
Send(m_async_queue.Front());
|
||||
{
|
||||
auto& e = m_async_queue.Front();
|
||||
Send(e.packet, e.channel_id);
|
||||
}
|
||||
m_async_queue.Pop();
|
||||
}
|
||||
if (net > 0)
|
||||
@@ -1557,7 +1615,7 @@ void NetPlayClient::OnConnectReady(ENetAddress addr)
|
||||
if (m_connection_state == ConnectionState::WaitingForTraversalClientConnectReady)
|
||||
{
|
||||
m_connection_state = ConnectionState::Connecting;
|
||||
enet_host_connect(m_client, &addr, 0, 0);
|
||||
enet_host_connect(m_client, &addr, CHANNEL_COUNT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user