Пример #1
0
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();
}
Пример #2
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
    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);
    }
}
Пример #3
0
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();
}
Пример #4
0
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();
}
Пример #5
0
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);
}
Пример #6
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();
}