diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index edd82183d..b409177f4 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -99,7 +99,6 @@ void packet_receive(struct Packet* p) { if (gNetworkServerAddr != NULL && gNetworkType == NT_CLIENT) { bool fromServer = (p->localIndex == UNKNOWN_LOCAL_INDEX); if (gNetworkPlayerServer != NULL) { fromServer = fromServer || p->localIndex == gNetworkPlayerServer->localIndex; } - LOG_INFO("matching? %d, %d", fromServer, gNetworkSystem->match_addr(gNetworkServerAddr, p->addr)); if (fromServer && !gNetworkSystem->match_addr(gNetworkServerAddr, p->addr)) { LOG_INFO("refusing packet from unknown server"); return; diff --git a/src/pc/network/packets/packet_download.c b/src/pc/network/packets/packet_download.c index 265cdb380..711a5fef3 100644 --- a/src/pc/network/packets/packet_download.c +++ b/src/pc/network/packets/packet_download.c @@ -3,6 +3,12 @@ #include "pc/mod_list.h" #include "pc/debuglog.h" +#define CHUNK_SIZE 400 +#define OFFSET_COUNT 5 + +static u64 sOffset[OFFSET_COUNT] = { 0 }; +static bool sWaitingForOffset[OFFSET_COUNT] = { 0 }; + static void network_send_next_download_request(void) { SOFT_ASSERT(gNetworkType == NT_CLIENT); for (int i = 0; i < sModEntryCount; i++) { @@ -23,21 +29,34 @@ void network_send_download_request(u16 index, u64 offset) { packet_write(&p, &index, sizeof(u16)); packet_write(&p, &offset, sizeof(u64)); + struct ModListEntry* entry = &gModEntries[index]; + for (int i = 0; i < OFFSET_COUNT; i++) { + sOffset[i] = offset + CHUNK_SIZE * i; + sWaitingForOffset[i] = (sOffset[i] < entry->size); + } + network_send_to((gNetworkPlayerServer != NULL) ? gNetworkPlayerServer->localIndex : 0, &p); - //LOG_INFO("sending download request packet"); } void network_receive_download_request(struct Packet* p) { SOFT_ASSERT(gNetworkType == NT_SERVER); - //LOG_INFO("received download request packet"); - u16 index; u64 offset; packet_read(p, &index, sizeof(u16)); packet_read(p, &offset, sizeof(u64)); - network_send_download(index, offset); + struct ModListEntry* entry = &gModEntries[index]; + if (index >= sModEntryCount) { + LOG_ERROR("Requested download of invalid index %u:%llu", index, offset); + return; + } + + for (int i = 0; i < OFFSET_COUNT; i++) { + u64 o = offset + CHUNK_SIZE * i; + if (o >= entry->size) { break; } + network_send_download(index, o); + } } void network_send_download(u16 index, u64 offset) { @@ -77,7 +96,6 @@ void network_send_download(u16 index, u64 offset) { packet_write(&p, chunk, chunkSize * sizeof(u8)); network_send_to(0, &p); - //LOG_INFO("sending download packet: %u:%llu", index, offset); } void network_receive_download(struct Packet* p) { @@ -118,32 +136,36 @@ void network_receive_download(struct Packet* p) { return; } - if (entry->curOffset != offset) { + // check if we're still waiting for chunks + bool found = false; + bool waiting = false; + for (int i = 0; i < OFFSET_COUNT; i++) { + if (sOffset[i] == offset) { + found = sWaitingForOffset[i]; + sWaitingForOffset[i] = false; + } + waiting = waiting || sWaitingForOffset[i]; + } + + if (!found) { LOG_ERROR("Received download of unexpected offset %llu != %llu", entry->curOffset, offset); return; } - entry->curOffset += chunkSize; - - //u64 told = ftell(entry->fp); - //if (offset == 0) { - fseek(entry->fp, offset, SEEK_SET); - //} + // write to the file + fseek(entry->fp, offset, SEEK_SET); fwrite(chunk, sizeof(u8) * chunkSize, 1, entry->fp); - /*u64 told2 = ftell(entry->fp); + if (!waiting) { + // check if we're finished with this file + if (sOffset[OFFSET_COUNT - 1] >= entry->size) { + LOG_INFO("Finished download of '%s'", entry->name); + fclose(entry->fp); + entry->fp = NULL; + entry->complete = true; + } - printf("#################################################\n"); - printf("%llu -> %llu -> %llu - %u\n", told, offset, told2, chunkSize); - printf("%s\n", chunk); - printf("#################################################\n");*/ - - if ((offset + chunkSize) == entry->size) { - LOG_INFO("Finished download of '%s'", entry->name); - fclose(entry->fp); - entry->fp = NULL; - entry->complete = true; + entry->curOffset += CHUNK_SIZE * OFFSET_COUNT; + network_send_next_download_request(); } - - network_send_next_download_request(); } diff --git a/src/pc/network/packets/packet_mod_list.c b/src/pc/network/packets/packet_mod_list.c index 32c6dce86..5b9b18aa2 100644 --- a/src/pc/network/packets/packet_mod_list.c +++ b/src/pc/network/packets/packet_mod_list.c @@ -5,6 +5,7 @@ void network_send_mod_list_request(void) { SOFT_ASSERT(gNetworkType == NT_CLIENT); + mod_list_shutdown(); struct Packet p = { 0 }; packet_init(&p, PACKET_MOD_LIST_REQUEST, true, PLMT_NONE); @@ -59,6 +60,10 @@ void network_send_mod_list(void) { void network_receive_mod_list(struct Packet* p) { SOFT_ASSERT(gNetworkType == NT_CLIENT); SOFT_ASSERT(p->localIndex == UNKNOWN_LOCAL_INDEX); + if (gModEntries != NULL) { + LOG_INFO("received mod list after allocating"); + return; + } if (gNetworkServerAddr == NULL) { gNetworkServerAddr = network_duplicate_address(0); diff --git a/src/pc/network/packets/packet_reliable.c b/src/pc/network/packets/packet_reliable.c index d44da3128..3e433f342 100644 --- a/src/pc/network/packets/packet_reliable.c +++ b/src/pc/network/packets/packet_reliable.c @@ -111,11 +111,24 @@ void network_remember_reliable(struct Packet* p) { tail = node; } +static float network_adjust_max_elapsed(enum PacketType packetType, float maxElapsed) { + switch (packetType) { + case PACKET_DOWNLOAD_REQUEST: + case PACKET_DOWNLOAD: + case PACKET_MOD_LIST_REQUEST: + case PACKET_MOD_LIST: + return 0.2f + maxElapsed * 2.0f; + default: + return maxElapsed; + } +} + void network_update_reliable(void) { struct PacketLinkedList* node = head; while (node != NULL) { float elapsed = (clock_elapsed() - node->lastSend); float maxElapsed = (node->sendAttempts * node->sendAttempts * RELIABLE_RESEND_RATE) / ((float)MAX_RESEND_ATTEMPTS); + maxElapsed = network_adjust_max_elapsed(node->p.packetType, maxElapsed); if (elapsed > maxElapsed) { if (node->p.packetType == PACKET_JOIN_REQUEST && gNetworkPlayerServer != NULL) { node->p.localIndex = gNetworkPlayerServer->localIndex;