void cb_manifest(FileServer_Private& client) { START_REPLY(e_FileToCli_ManifestReply); // Trans ID client.m_buffer.write<uint32_t>(DS::RecvValue<uint32_t>(client.m_sock)); // Manifest name chr16_t mfsbuf[260]; DS::RecvBuffer(client.m_sock, mfsbuf, 260 * sizeof(chr16_t)); mfsbuf[259] = 0; DS::String mfsname = DS::String::FromUtf16(mfsbuf); // Build ID uint32_t buildId = DS::RecvValue<uint32_t>(client.m_sock); if (buildId && buildId != CLIENT_BUILD_ID) { fprintf(stderr, "[File] Wrong Build ID from %s: %d\n", DS::SockIpAddress(client.m_sock).c_str(), buildId); DS::CloseSock(client.m_sock); return; } // Manifest may not have any path characters if (mfsname.find(".") != -1 || mfsname.find("/") != -1 || mfsname.find("\\") != -1 || mfsname.find(":") != -1) { fprintf(stderr, "[File] Invalid manifest request from %s: %s\n", DS::SockIpAddress(client.m_sock).c_str(), mfsname.c_str()); client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound); client.m_buffer.write<uint32_t>(0); // Reader ID client.m_buffer.write<uint32_t>(0); // File count client.m_buffer.write<uint32_t>(0); // Data packet size SEND_REPLY(); return; } DS::FileManifest manifest; mfsname = DS::Settings::FileRoot() + mfsname + ".mfs"; DS::NetResultCode result = manifest.loadManifest(mfsname.c_str()); client.m_buffer.write<uint32_t>(result); if (result != DS::e_NetSuccess) { fprintf(stderr, "[File] %s requested invalid manifest %s\n", DS::SockIpAddress(client.m_sock).c_str(), mfsname.c_str()); client.m_buffer.write<uint32_t>(0); // Reader ID client.m_buffer.write<uint32_t>(0); // File count client.m_buffer.write<uint32_t>(0); // Data packet size } else { client.m_buffer.write<uint32_t>(++client.m_readerId); client.m_buffer.write<uint32_t>(manifest.fileCount()); uint32_t sizeLocation = client.m_buffer.tell(); client.m_buffer.write<uint32_t>(0); uint32_t dataSize = manifest.encodeToStream(&client.m_buffer); client.m_buffer.seek(sizeLocation, SEEK_SET); client.m_buffer.write<uint32_t>(dataSize); } SEND_REPLY(); }
void cb_downloadStart(FileServer_Private& client) { START_REPLY(e_FileToCli_FileDownloadReply); // Trans ID client.m_buffer.write<uint32_t>(DS::RecvValue<uint32_t>(client.m_sock)); // Download filename char16_t buffer[260]; DS::RecvBuffer(client.m_sock, buffer, sizeof(buffer)); buffer[259] = 0; DS::String filename = DS::String::FromUtf16(buffer); // Build ID uint32_t buildId = DS::RecvValue<uint32_t>(client.m_sock); if (buildId && buildId != DS::Settings::BuildId()) { fprintf(stderr, "[File] Wrong Build ID from %s: %d\n", DS::SockIpAddress(client.m_sock).c_str(), buildId); DS::CloseSock(client.m_sock); return; } // Ensure filename is jailed to our data path if (filename.find("..") != -1) { client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound); client.m_buffer.write<uint32_t>(0); // Reader ID client.m_buffer.write<uint32_t>(0); // File size client.m_buffer.write<uint32_t>(0); // Data packet size SEND_REPLY(); return; } filename.replace("\\", "/"); filename = DS::Settings::FileRoot() + filename; int fd = open(filename.c_str(), O_RDONLY); if (fd < 0) { fprintf(stderr, "[File] Could not open file %s\n[File] Requested by %s\n", filename.c_str(), DS::SockIpAddress(client.m_sock).c_str()); client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound); client.m_buffer.write<uint32_t>(0); // Reader ID client.m_buffer.write<uint32_t>(0); // File size client.m_buffer.write<uint32_t>(0); // Data packet size SEND_REPLY(); return; } std::unique_ptr<FileRequest> req(new FileRequest(fd)); client.m_buffer.write<uint32_t>(DS::e_NetSuccess); client.m_buffer.write<uint32_t>(++client.m_readerId); client.m_buffer.write<uint32_t>(req->m_size); FileRequest::chunk_t c = req->nextChunk(); client.m_buffer.write<uint32_t>(std::get<1>(c)); SEND_FD_REPLY(req->m_fd, req->m_pos, std::get<1>(c)); if (!std::get<0>(c)) { client.m_downloads[client.m_readerId] = std::move(req); } }
void cb_downloadStart(AuthServer_Private& client) { START_REPLY(e_AuthToCli_FileDownloadChunk); // Trans ID uint32_t transId = DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt); client.m_buffer.write<uint32_t>(transId); // Download filename DS::String filename = DS::CryptRecvString(client.m_sock, client.m_crypt); // Ensure filename is jailed to our data path if (filename.find("..") != -1) { client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound); client.m_buffer.write<uint32_t>(0); // File size client.m_buffer.write<uint32_t>(0); // Chunk offset client.m_buffer.write<uint32_t>(0); // Data packet size SEND_REPLY(); return; } filename.replace("\\", "/"); filename = DS::Settings::AuthRoot() + filename; DS::FileStream* stream = new DS::FileStream(); try { stream->open(filename.c_str(), "rb"); } catch (const DS::FileIOException& ex) { fprintf(stderr, "[Auth] Could not open file %s: %s\n[Auth] Requested by %s\n", filename.c_str(), ex.what(), DS::SockIpAddress(client.m_sock).c_str()); client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound); client.m_buffer.write<uint32_t>(0); // File size client.m_buffer.write<uint32_t>(0); // Chunk offset client.m_buffer.write<uint32_t>(0); // Data packet size SEND_REPLY(); delete stream; return; } client.m_buffer.write<uint32_t>(DS::e_NetSuccess); client.m_buffer.write<uint32_t>(stream->size()); client.m_buffer.write<uint32_t>(stream->tell()); uint8_t data[CHUNK_SIZE]; if (stream->size() > CHUNK_SIZE) { client.m_buffer.write<uint32_t>(CHUNK_SIZE); stream->readBytes(data, CHUNK_SIZE); client.m_buffer.writeBytes(data, CHUNK_SIZE); client.m_downloads[transId] = stream; } else { client.m_buffer.write<uint32_t>(stream->size()); stream->readBytes(data, stream->size()); client.m_buffer.writeBytes(data, stream->size()); delete stream; } SEND_REPLY(); }
void cb_fileList(AuthServer_Private& client) { START_REPLY(e_AuthToCli_FileListReply); // Trans ID client.m_buffer.write<uint32_t>(DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt)); DS::String directory = DS::CryptRecvString(client.m_sock, client.m_crypt); DS::String fileext = DS::CryptRecvString(client.m_sock, client.m_crypt); // Manifest may not have any path characters if (directory.find(".") != -1 || directory.find("/") != -1 || directory.find("\\") != -1 || directory.find(":") != -1 || fileext.find(".") != -1 || fileext.find("/") != -1 || fileext.find("\\") != -1 || fileext.find(":") != -1) { fprintf(stderr, "[Auth] Invalid manifest request from %s: %s\\%s\n", DS::SockIpAddress(client.m_sock).c_str(), directory.c_str(), fileext.c_str()); client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound); client.m_buffer.write<uint32_t>(0); // Data packet size SEND_REPLY(); return; } DS::String mfsname = DS::String::Format("%s%s_%s.list", DS::Settings::AuthRoot().c_str(), directory.c_str(), fileext.c_str()); DS::AuthManifest mfs; DS::NetResultCode result = mfs.loadManifest(mfsname.c_str()); client.m_buffer.write<uint32_t>(result); if (result != DS::e_NetSuccess) { fprintf(stderr, "[Auth] %s requested invalid manifest %s\n", DS::SockIpAddress(client.m_sock).c_str(), mfsname.c_str()); client.m_buffer.write<uint32_t>(0); // Data packet size } else { uint32_t sizeLocation = client.m_buffer.tell(); client.m_buffer.write<uint32_t>(0); uint32_t dataSize = mfs.encodeToStream(&client.m_buffer); client.m_buffer.seek(sizeLocation, SEEK_SET); client.m_buffer.write<uint32_t>(dataSize); } SEND_REPLY(); }
void DS::GameServer_Init() { dirent** dirls; int count = scandir(DS::Settings::AgePath(), &dirls, &sel_age, &alphasort); if (count < 0) { fprintf(stderr, "[Game] Error reading age descriptors: %s\n", strerror(errno)); } else if (count == 0) { fprintf(stderr, "[Game] Warning: No age descriptors found!\n"); free(dirls); } else { for (int i=0; i<count; ++i) { DS::String filename = DS::String::Format("%s/%s", DS::Settings::AgePath(), dirls[i]->d_name); FILE* ageFile = fopen(filename.c_str(), "r"); if (ageFile) { char magic[12]; fread(magic, 1, 12, ageFile); if (memcmp(magic, "whatdoyousee", 12) == 0 || memcmp(magic, "notthedroids", 12) == 0 || memcmp(magic, "BriceIsSmart", 12) == 0) { fprintf(stderr, "[Game] Error: Please decrypt your .age files before using!\n"); break; } fseek(ageFile, 0, SEEK_SET); DS::String ageName = dirls[i]->d_name; ageName = ageName.left(ageName.find(".age")); Game_AgeInfo age = age_parse(ageFile); if (age.m_seqPrefix >= 0) s_ages[ageName] = age; fclose(ageFile); } free(dirls[i]); } free(dirls); } pthread_mutex_init(&s_gameHostMutex, 0); }
void cb_downloadStart(FileServer_Private& client) { START_REPLY(e_FileToCli_FileDownloadReply); // Trans ID client.m_buffer.write<uint32_t>(DS::RecvValue<uint32_t>(client.m_sock)); // Download filename chr16_t buffer[260]; DS::RecvBuffer(client.m_sock, buffer, 260 * sizeof(chr16_t)); buffer[259] = 0; DS::String filename = DS::String::FromUtf16(buffer); // Build ID uint32_t buildId = DS::RecvValue<uint32_t>(client.m_sock); if (buildId && buildId != CLIENT_BUILD_ID) { fprintf(stderr, "[File] Wrong Build ID from %s: %d\n", DS::SockIpAddress(client.m_sock).c_str(), buildId); DS::CloseSock(client.m_sock); return; } // Ensure filename is jailed to our data path if (filename.find("..") != -1) { client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound); client.m_buffer.write<uint32_t>(0); // Reader ID client.m_buffer.write<uint32_t>(0); // File size client.m_buffer.write<uint32_t>(0); // Data packet size SEND_REPLY(); return; } filename.replace("\\", "/"); filename = DS::Settings::FileRoot() + filename; DS::FileStream* stream = new DS::FileStream(); try { stream->open(filename.c_str(), "rb"); } catch (DS::FileIOException ex) { fprintf(stderr, "[File] Could not open file %s: %s\n[File] Requested by %s\n", filename.c_str(), ex.what(), DS::SockIpAddress(client.m_sock).c_str()); client.m_buffer.write<uint32_t>(DS::e_NetFileNotFound); client.m_buffer.write<uint32_t>(0); // Reader ID client.m_buffer.write<uint32_t>(0); // File size client.m_buffer.write<uint32_t>(0); // Data packet size SEND_REPLY(); delete stream; return; } client.m_buffer.write<uint32_t>(DS::e_NetSuccess); client.m_buffer.write<uint32_t>(++client.m_readerId); client.m_buffer.write<uint32_t>(stream->size()); uint8_t data[CHUNK_SIZE]; if (stream->size() > CHUNK_SIZE) { client.m_buffer.write<uint32_t>(CHUNK_SIZE); stream->readBytes(data, CHUNK_SIZE); client.m_buffer.writeBytes(data, CHUNK_SIZE); client.m_downloads[client.m_readerId] = stream; } else { client.m_buffer.write<uint32_t>(stream->size()); stream->readBytes(data, stream->size()); client.m_buffer.writeBytes(data, stream->size()); delete stream; } SEND_REPLY(); }