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_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(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(); }
bool ds::Texture::Load( const ds::String& Filename, DWORD Type ) { Release( ); if( !ds::Render::GetDevice( ) ) { dsPushMessage( ErrD3DeviceNotCreated ); return false; } D3DX10_IMAGE_LOAD_INFO l_Info = D3DX10_IMAGE_LOAD_INFO( ); CreateInfo( Type, l_Info ); ID3D10Resource* l_Resource = nullptr; HRESULT l_Result = D3DX10CreateTextureFromFile( ds::Render::Device, Filename.c_str( ), &l_Info, nullptr, &l_Resource, nullptr ); if( FAILED( l_Result ) ) { dsPushError( ErrTextureLoad, Filename.c_str( ) ); return false; } l_Resource->QueryInterface( __uuidof( ID3D10Texture2D ), ( LPVOID* )&Texture2D ); l_Resource->Release( ); D3D10_TEXTURE2D_DESC l_Desc; Texture2D->GetDesc( &l_Desc ); Size = ds::Size( l_Desc.Width, l_Desc.Height ); if( Type & RenderTarget ) { D3D10_RENDER_TARGET_VIEW_DESC l_Target; l_Target.Format = l_Info.Format; l_Target.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D; l_Target.Texture2D.MipSlice = 0; ds::Render::Device->CreateRenderTargetView( Texture2D, &l_Target, &TargetView ); } ShaderView[ 0 ] = CreateResourceView( this ); return true; }
bool ds::Audio::Create( const ds::String& Filename ) { if( Library ) Release( ); Library = LoadLibrary( Filename.c_str( ) ); if( !Library ) return false; BASS_Init = ( BOOL (__stdcall *)( int, DWORD, DWORD, HWND, const GUID* ) )GetProcAddress( Library, "BASS_Init" ); BASS_Pause = ( BOOL (__stdcall *) ( ) )GetProcAddress( Library, "BASS_Pause" ); BASS_Stop = ( BOOL (__stdcall *) ( ) )GetProcAddress( Library, "BASS_Stop" ); BASS_Start = ( BOOL (__stdcall *) ( ) )GetProcAddress( Library, "BASS_Start" ); BASS_SetVolume = ( BOOL (__stdcall *) ( float ) )GetProcAddress( Library, "BASS_SetVolume" ); BASS_Free = ( BOOL (__stdcall *) ( ) )GetProcAddress( Library, "BASS_Free" ); BASS_StreamFree = ( BOOL (__stdcall *) ( DWORD ) )GetProcAddress( Library, "BASS_StreamFree" ); BASS_SampleFree = ( BOOL (__stdcall *) ( DWORD ) )GetProcAddress( Library, "BASS_SampleFree" ); BASS_ChannelPause = ( BOOL (__stdcall *)( DWORD ) )GetProcAddress( Library, "BASS_ChannelPause" ); BASS_ChannelStop = ( BOOL (__stdcall *)( DWORD ) )GetProcAddress( Library, "BASS_ChannelStop" ); BASS_ChannelPlay = ( BOOL (__stdcall *)( DWORD, BOOL ) )GetProcAddress( Library, "BASS_ChannelPlay" ); BASS_ChannelSetAttribute = ( BOOL (__stdcall *)( DWORD, DWORD, float ) )GetProcAddress( Library, "BASS_ChannelSetAttribute" ); BASS_ChannelIsActive = ( DWORD (__stdcall *)( DWORD ) )GetProcAddress( Library, "BASS_ChannelIsActive" ); BASS_StreamCreateFile = ( DWORD (__stdcall *)( BOOL, const void*, QWORD, QWORD, DWORD ) )GetProcAddress( Library, "BASS_StreamCreateFile" ); BASS_SampleLoad = ( DWORD (__stdcall *)( BOOL, const void*, QWORD, DWORD, DWORD, DWORD ) )GetProcAddress( Library, "BASS_SampleLoad" ); BASS_SampleGetChannel = ( DWORD (__stdcall *)( DWORD, BOOL ) )GetProcAddress( Library, "BASS_SampleGetChannel" ); BASS_Init( -1, 44100, 0, ds::Render::GetHandle( ), nullptr ); return true; }
DS::Blob gen_default_sdl(const DS::String& filename) { SDL::StateDescriptor* desc = SDL::DescriptorDb::FindDescriptor(filename, -1); if (!desc) { fprintf(stderr, "[Vault] Warning: Could not find SDL descriptor for %s\n", filename.c_str()); return DS::Blob(); } SDL::State state(desc); return state.toBlob(); }
bool ds::Texture::Save( const ds::String& Filename, ds::Texture::FileFormat Format ) const { if( !Texture2D ) { dsPushMessage( ErrTextureIsEmpty ); return false; } HRESULT l_Result = D3DX10SaveTextureToFileA( Texture2D, ( D3DX10_IMAGE_FILE_FORMAT )Format, Filename.c_str( ) ); if( FAILED( l_Result ) ) { dsPushError( ErrTextureSave, Filename.c_str( ) ); return false; } return true; }
DS::Blob gen_default_sdl(const DS::String& filename) { SDL::StateDescriptor* desc = SDL::DescriptorDb::FindDescriptor(filename, -1); if (!desc) { fprintf(stderr, "[Vault] Warning: Could not find SDL descriptor for %s\n", filename.c_str()); return DS::Blob(); } SDL::State state(desc); DS::BufferStream stream; state.write(&stream); return DS::Blob(stream.buffer(), stream.size()); }
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_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(); }
bool v_update_node(const DS::Vault::Node& node) { /* This should be plenty to store everything we need without a bunch * of dynamic reallocations */ PostgresStrings<32> parms; char fieldbuf[1024]; size_t parmcount = 1; char* fieldp = fieldbuf; #define SET_FIELD(name, value) \ { \ parms.set(parmcount++, value); \ fieldp += sprintf(fieldp, "\"" #name "\"=$%Zu,", parmcount); \ } int now = time(0); SET_FIELD(ModifyTime, now); if (node.has_CreateAgeName()) SET_FIELD(CreateAgeName, node.m_CreateAgeName); if (node.has_CreateAgeUuid()) SET_FIELD(CreateAgeUuid, node.m_CreateAgeUuid.toString()); if (node.has_CreatorUuid()) SET_FIELD(CreatorUuid, node.m_CreatorUuid.toString()); if (node.has_CreatorIdx()) SET_FIELD(CreatorIdx, node.m_CreatorIdx); if (node.has_NodeType()) SET_FIELD(NodeType, node.m_NodeType); if (node.has_Int32_1()) SET_FIELD(Int32_1, node.m_Int32_1); if (node.has_Int32_2()) SET_FIELD(Int32_2, node.m_Int32_2); if (node.has_Int32_3()) SET_FIELD(Int32_3, node.m_Int32_3); if (node.has_Int32_4()) SET_FIELD(Int32_4, node.m_Int32_4); if (node.has_Uint32_1()) SET_FIELD(Uint32_1, node.m_Uint32_1); if (node.has_Uint32_2()) SET_FIELD(Uint32_2, node.m_Uint32_2); if (node.has_Uint32_3()) SET_FIELD(Uint32_3, node.m_Uint32_3); if (node.has_Uint32_4()) SET_FIELD(Uint32_4, node.m_Uint32_4); if (node.has_Uuid_1()) SET_FIELD(Uuid_1, node.m_Uuid_1.toString()); if (node.has_Uuid_2()) SET_FIELD(Uuid_2, node.m_Uuid_2.toString()); if (node.has_Uuid_3()) SET_FIELD(Uuid_3, node.m_Uuid_3.toString()); if (node.has_Uuid_4()) SET_FIELD(Uuid_4, node.m_Uuid_4.toString()); if (node.has_String64_1()) SET_FIELD(String64_1, node.m_String64_1); if (node.has_String64_2()) SET_FIELD(String64_2, node.m_String64_2); if (node.has_String64_3()) SET_FIELD(String64_3, node.m_String64_3); if (node.has_String64_4()) SET_FIELD(String64_4, node.m_String64_4); if (node.has_String64_5()) SET_FIELD(String64_5, node.m_String64_5); if (node.has_String64_6()) SET_FIELD(String64_6, node.m_String64_6); if (node.has_IString64_1()) SET_FIELD(IString64_1, node.m_IString64_1); if (node.has_IString64_2()) SET_FIELD(IString64_2, node.m_IString64_2); if (node.has_Text_1()) SET_FIELD(Text_1, node.m_Text_1); if (node.has_Text_2()) SET_FIELD(Text_2, node.m_Text_2); if (node.has_Blob_1()) SET_FIELD(Blob_1, DS::Base64Encode(node.m_Blob_1.buffer(), node.m_Blob_1.size())); if (node.has_Blob_2()) SET_FIELD(Blob_2, DS::Base64Encode(node.m_Blob_2.buffer(), node.m_Blob_2.size())); #undef SET_FIELD DS_DASSERT(fieldp - fieldbuf < 1024); *(fieldp - 1) = 0; // Get rid of the last comma DS::String queryStr = "UPDATE vault.\"Nodes\"\n SET "; queryStr += fieldbuf; queryStr += "\n WHERE idx=$1"; parms.set(0, node.m_NodeIdx); check_postgres(); PGresult* result = PQexecParams(s_postgres, queryStr.c_str(), parmcount, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_COMMAND_OK) { fprintf(stderr, "%s:%d:\n Postgres UPDATE error: %s\n", __FILE__, __LINE__, PQerrorMessage(s_postgres)); PQclear(result); return false; } PQclear(result); return true; }
uint32_t v_create_node(const DS::Vault::Node& node) { /* This should be plenty to store everything we need without a bunch * of dynamic reallocations */ PostgresStrings<31> parms; char fieldbuf[1024]; size_t parmcount = 0; char* fieldp = fieldbuf; #define SET_FIELD(name, value) \ { \ parms.set(parmcount++, value); \ fieldp += sprintf(fieldp, "\"" #name "\","); \ } int now = time(0); SET_FIELD(CreateTime, now); SET_FIELD(ModifyTime, now); if (node.has_CreateAgeName()) SET_FIELD(CreateAgeName, node.m_CreateAgeName); if (node.has_CreateAgeUuid()) SET_FIELD(CreateAgeUuid, node.m_CreateAgeUuid.toString()); if (node.has_CreatorUuid()) SET_FIELD(CreatorUuid, node.m_CreatorUuid.toString()); if (node.has_CreatorIdx()) SET_FIELD(CreatorIdx, node.m_CreatorIdx); if (node.has_NodeType()) SET_FIELD(NodeType, node.m_NodeType); if (node.has_Int32_1()) SET_FIELD(Int32_1, node.m_Int32_1); if (node.has_Int32_2()) SET_FIELD(Int32_2, node.m_Int32_2); if (node.has_Int32_3()) SET_FIELD(Int32_3, node.m_Int32_3); if (node.has_Int32_4()) SET_FIELD(Int32_4, node.m_Int32_4); if (node.has_Uint32_1()) SET_FIELD(Uint32_1, node.m_Uint32_1); if (node.has_Uint32_2()) SET_FIELD(Uint32_2, node.m_Uint32_2); if (node.has_Uint32_3()) SET_FIELD(Uint32_3, node.m_Uint32_3); if (node.has_Uint32_4()) SET_FIELD(Uint32_4, node.m_Uint32_4); if (node.has_Uuid_1()) SET_FIELD(Uuid_1, node.m_Uuid_1.toString()); if (node.has_Uuid_2()) SET_FIELD(Uuid_2, node.m_Uuid_2.toString()); if (node.has_Uuid_3()) SET_FIELD(Uuid_3, node.m_Uuid_3.toString()); if (node.has_Uuid_4()) SET_FIELD(Uuid_4, node.m_Uuid_4.toString()); if (node.has_String64_1()) SET_FIELD(String64_1, node.m_String64_1); if (node.has_String64_2()) SET_FIELD(String64_2, node.m_String64_2); if (node.has_String64_3()) SET_FIELD(String64_3, node.m_String64_3); if (node.has_String64_4()) SET_FIELD(String64_4, node.m_String64_4); if (node.has_String64_5()) SET_FIELD(String64_5, node.m_String64_5); if (node.has_String64_6()) SET_FIELD(String64_6, node.m_String64_6); if (node.has_IString64_1()) SET_FIELD(IString64_1, node.m_IString64_1); if (node.has_IString64_2()) SET_FIELD(IString64_2, node.m_IString64_2); if (node.has_Text_1()) SET_FIELD(Text_1, node.m_Text_1); if (node.has_Text_2()) SET_FIELD(Text_2, node.m_Text_2); if (node.has_Blob_1()) SET_FIELD(Blob_1, DS::Base64Encode(node.m_Blob_1.buffer(), node.m_Blob_1.size())); if (node.has_Blob_2()) SET_FIELD(Blob_2, DS::Base64Encode(node.m_Blob_2.buffer(), node.m_Blob_2.size())); #undef SET_FIELD DS_DASSERT(fieldp - fieldbuf < 1024); *(fieldp - 1) = ')'; // Get rid of the last comma DS::String queryStr = "INSERT INTO vault.\"Nodes\" ("; queryStr += fieldbuf; fieldp = fieldbuf; for (size_t i=0; i<parmcount; ++i) { sprintf(fieldp, "$%Zu,", i+1); fieldp += strlen(fieldp); } DS_DASSERT(fieldp - fieldbuf < 1024); *(fieldp - 1) = ')'; // Get rid of the last comma queryStr += "\n VALUES ("; queryStr += fieldbuf; queryStr += "\n RETURNING idx"; check_postgres(); PGresult* result = PQexecParams(s_postgres, queryStr.c_str(), parmcount, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_TUPLES_OK) { fprintf(stderr, "%s:%d:\n Postgres INSERT error: %s\n", __FILE__, __LINE__, PQerrorMessage(s_postgres)); PQclear(result); return 0; } DS_DASSERT(PQntuples(result) == 1); uint32_t idx = strtoul(PQgetvalue(result, 0, 0), 0, 10); PQclear(result); return idx; }
std::list<AuthServer_AgeInfo> configure_static_ages() { AuthServer_AgeInfo age; std::list<AuthServer_AgeInfo> configs; DS::String filename = DS::Settings::SettingsPath() + "/static_ages.ini"; FILE* cfgfile = fopen(filename.c_str(), "r"); if (!cfgfile) { fprintf(stderr, "Cannot open %s for reading\n", filename.c_str()); return configs; } try { char buffer[4096]; bool haveAge = false; while (fgets(buffer, 4096, cfgfile)) { DS::String line = DS::String(buffer).strip('#'); if (line.isEmpty()) continue; if (line.strip().c_str()[0] == '[') { if (haveAge) configs.push_back(age); age.clear(); DS::String header = line.strip(); header.replace("[",""); header.replace("]",""); if (header == "auto") age.m_ageId = gen_uuid(); else age.m_ageId = DS::Uuid(header.c_str()); haveAge = true; continue; } std::vector<DS::String> params = line.split('=', 1); if (params.size() != 2) { fprintf(stderr, "Warning: Invalid config line: %s\n", line.c_str()); continue; } // Clean any whitespace around the '=' params[0] = params[0].strip(); params[1] = params[1].strip(); if (params[0] == "Filename") { age.m_filename = params[1]; } else if (params[0] == "Instance") { age.m_instName = params[1]; } else if (params[0] == "UserName") { age.m_userName = params[1]; } else { fprintf(stderr, "Warning: Unknown setting '%s' ignored\n", params[0].c_str()); } } if (haveAge) configs.push_back(age); } catch (DS::AssertException ex) { fprintf(stderr, "[Auth] Assertion failed at %s:%ld: %s\n", ex.m_file, ex.m_line, ex.m_cond); fclose(cfgfile); return configs; } fclose(cfgfile); return configs; }
bool v_find_nodes(const DS::Vault::Node& nodeTemplate, std::vector<uint32_t>& nodes) { if (nodeTemplate.isNull()) return false; /* This should be plenty to store everything we need without a bunch * of dynamic reallocations */ PostgresStrings<31> parms; char fieldbuf[1024]; size_t parmcount = 0; char* fieldp = fieldbuf; #define SET_FIELD(name, value) \ { \ parms.set(parmcount++, value); \ fieldp += sprintf(fieldp, "\"" #name "\"=$%Zu AND ", parmcount); \ } #define SET_FIELD_I(name, value) \ { \ parms.set(parmcount++, value); \ fieldp += sprintf(fieldp, "LOWER(\"" #name "\")=LOWER($%Zu) AND ", parmcount); \ } if (nodeTemplate.has_CreateTime()) SET_FIELD(CreateTime, nodeTemplate.m_CreateTime); if (nodeTemplate.has_ModifyTime()) SET_FIELD(ModifyTime, nodeTemplate.m_ModifyTime); if (nodeTemplate.has_CreateAgeName()) SET_FIELD(CreateAgeName, nodeTemplate.m_CreateAgeName); if (nodeTemplate.has_CreateAgeUuid()) SET_FIELD(CreateAgeUuid, nodeTemplate.m_CreateAgeUuid.toString()); if (nodeTemplate.has_CreatorUuid()) SET_FIELD(CreatorUuid, nodeTemplate.m_CreatorUuid.toString()); if (nodeTemplate.has_CreatorIdx()) SET_FIELD(CreatorIdx, nodeTemplate.m_CreatorIdx); if (nodeTemplate.has_NodeType()) SET_FIELD(NodeType, nodeTemplate.m_NodeType); if (nodeTemplate.has_Int32_1()) SET_FIELD(Int32_1, nodeTemplate.m_Int32_1); if (nodeTemplate.has_Int32_2()) SET_FIELD(Int32_2, nodeTemplate.m_Int32_2); if (nodeTemplate.has_Int32_3()) SET_FIELD(Int32_3, nodeTemplate.m_Int32_3); if (nodeTemplate.has_Int32_4()) SET_FIELD(Int32_4, nodeTemplate.m_Int32_4); if (nodeTemplate.has_Uint32_1()) SET_FIELD(Uint32_1, nodeTemplate.m_Uint32_1); if (nodeTemplate.has_Uint32_2()) SET_FIELD(Uint32_2, nodeTemplate.m_Uint32_2); if (nodeTemplate.has_Uint32_3()) SET_FIELD(Uint32_3, nodeTemplate.m_Uint32_3); if (nodeTemplate.has_Uint32_4()) SET_FIELD(Uint32_4, nodeTemplate.m_Uint32_4); if (nodeTemplate.has_Uuid_1()) SET_FIELD(Uuid_1, nodeTemplate.m_Uuid_1.toString()); if (nodeTemplate.has_Uuid_2()) SET_FIELD(Uuid_2, nodeTemplate.m_Uuid_2.toString()); if (nodeTemplate.has_Uuid_3()) SET_FIELD(Uuid_3, nodeTemplate.m_Uuid_3.toString()); if (nodeTemplate.has_Uuid_4()) SET_FIELD(Uuid_4, nodeTemplate.m_Uuid_4.toString()); if (nodeTemplate.has_String64_1()) SET_FIELD(String64_1, nodeTemplate.m_String64_1); if (nodeTemplate.has_String64_2()) SET_FIELD(String64_2, nodeTemplate.m_String64_2); if (nodeTemplate.has_String64_3()) SET_FIELD(String64_3, nodeTemplate.m_String64_3); if (nodeTemplate.has_String64_4()) SET_FIELD(String64_4, nodeTemplate.m_String64_4); if (nodeTemplate.has_String64_5()) SET_FIELD(String64_5, nodeTemplate.m_String64_5); if (nodeTemplate.has_String64_6()) SET_FIELD(String64_6, nodeTemplate.m_String64_6); if (nodeTemplate.has_IString64_1()) SET_FIELD_I(IString64_1, nodeTemplate.m_IString64_1); if (nodeTemplate.has_IString64_2()) SET_FIELD_I(IString64_2, nodeTemplate.m_IString64_2); if (nodeTemplate.has_Text_1()) SET_FIELD(Text_1, nodeTemplate.m_Text_1); if (nodeTemplate.has_Text_2()) SET_FIELD(Text_2, nodeTemplate.m_Text_2); if (nodeTemplate.has_Blob_1()) SET_FIELD(Blob_1, DS::Base64Encode(nodeTemplate.m_Blob_1.buffer(), nodeTemplate.m_Blob_1.size())); if (nodeTemplate.has_Blob_2()) SET_FIELD(Blob_2, DS::Base64Encode(nodeTemplate.m_Blob_2.buffer(), nodeTemplate.m_Blob_2.size())); #undef SET_FIELD #undef SET_FIELD_I DS_DASSERT(parmcount > 0); DS_DASSERT(fieldp - fieldbuf < 1024); *(fieldp - 5) = 0; // Get rid of the last ' AND ' DS::String queryStr = "SELECT idx FROM vault.\"Nodes\"\n WHERE "; queryStr += fieldbuf; check_postgres(); PGresult* result = PQexecParams(s_postgres, queryStr.c_str(), parmcount, 0, parms.m_values, 0, 0, 0); if (PQresultStatus(result) != PGRES_TUPLES_OK) { fprintf(stderr, "%s:%d:\n Postgres SELECT error: %s\n", __FILE__, __LINE__, PQerrorMessage(s_postgres)); PQclear(result); return false; } nodes.resize(PQntuples(result)); for (size_t i=0; i<nodes.size(); ++i) nodes[i] = strtoul(PQgetvalue(result, i, 0), 0, 10); PQclear(result); return true; }
void dm_htserv() { printf("[Status] Running on %s\n", DS::SockIpAddress(s_listenSock).c_str()); try { for ( ;; ) { DS::SocketHandle client; try { client = DS::AcceptSock(s_listenSock); } catch (DS::SockHup) { break; } if (!client) continue; std::list<DS::String> lines; for ( ;; ) { std::unique_ptr<char[]> buffer; DS::String scratch; try { size_t bufSize = DS::PeekSize(client); buffer.reset(new char[scratch.length() + bufSize + 1]); memcpy(buffer.get(), scratch.c_str(), scratch.length()); DS::RecvBuffer(client, buffer.get() + scratch.length(), bufSize); buffer[scratch.length() + bufSize] = 0; } catch (const DS::SockHup&) { lines.clear(); break; } char* cp = buffer.get(); char* sp = buffer.get(); while (*cp) { if (*cp == '\r' || *cp == '\n') { if (*cp == '\r' && *(cp + 1) == '\n') { // Delete both chars of the Windows newline *cp++ = 0; } *cp++ = 0; lines.push_back(DS::String(sp)); sp = cp; scratch = ""; } else { ++cp; } } if (cp != sp) scratch += sp; if (lines.size() && lines.back().isEmpty()) { // Got the separator line break; } } if (lines.empty()) { DS::FreeSock(client); continue; } // First line contains the action std::vector<DS::String> action = lines.front().split(); if (action.size() < 2) { fprintf(stderr, "[Status] Incorrectly formatted HTTP request: %s\n", lines.front().c_str()); DS::FreeSock(client); continue; } if (action[0] != "GET") { fprintf(stderr, "[Status] Unsupported method: %s\n", action[0].c_str()); DS::FreeSock(client); continue; } if (action.size() < 3 || action[2] != "HTTP/1.1") { fputs("[Status] Unsupported HTTP Version\n", stderr); DS::FreeSock(client); continue; } DS::String path = action[1]; lines.pop_front(); for (auto lniter = lines.begin(); lniter != lines.end(); ++lniter) { // TODO: See if any of these fields are useful to us... } if (path == "/status") { DS::String json = "{'online':true"; DS::String welcome = DS::Settings::WelcomeMsg(); welcome.replace("\"", "\\\""); json += DS::String::Format(",'welcome':\"%s\"", welcome.c_str()); json += "}\r\n"; // TODO: Add more status fields (players/ages, etc) SEND_RAW(client, "HTTP/1.1 200 OK\r\n"); SEND_RAW(client, "Server: Dirtsand\r\n"); SEND_RAW(client, "Connection: close\r\n"); SEND_RAW(client, "Accept-Ranges: bytes\r\n"); DS::String lengthParam = DS::String::Format("Content-Length: %u\r\n", json.length()); DS::SendBuffer(client, lengthParam.c_str(), lengthParam.length()); SEND_RAW(client, "Content-Type: application/json\r\n"); SEND_RAW(client, "\r\n"); DS::SendBuffer(client, json.c_str(), json.length()); DS::FreeSock(client); } else if (path == "/welcome") { DS::String welcome = DS::Settings::WelcomeMsg(); welcome.replace("\\n", "\r\n"); SEND_RAW(client, "HTTP/1.1 200 OK\r\n"); SEND_RAW(client, "Server: Dirtsand\r\n"); SEND_RAW(client, "Connection: close\r\n"); SEND_RAW(client, "Accept-Ranges: bytes\r\n"); DS::String lengthParam = DS::String::Format("Content-Length: %u\r\n", welcome.length()); DS::SendBuffer(client, lengthParam.c_str(), lengthParam.length()); SEND_RAW(client, "Content-Type: text/plain\r\n"); SEND_RAW(client, "\r\n"); DS::SendBuffer(client, welcome.c_str(), welcome.length()); DS::FreeSock(client); } else { DS::String content = DS::String::Format("No page found at %s\r\n", path.c_str()); SEND_RAW(client, "HTTP/1.1 404 NOT FOUND\r\n"); SEND_RAW(client, "Server: Dirtsand\r\n"); SEND_RAW(client, "Connection: close\r\n"); SEND_RAW(client, "Accept-Ranges: bytes\r\n"); DS::String lengthParam = DS::String::Format("Content-Length: %u\r\n", content.length()); DS::SendBuffer(client, lengthParam.c_str(), lengthParam.length()); SEND_RAW(client, "Content-Type: text/plain\r\n"); SEND_RAW(client, "\r\n"); DS::SendBuffer(client, content.c_str(), content.length()); DS::FreeSock(client); } } } catch (DS::AssertException ex) { fprintf(stderr, "[Status] Assertion failed at %s:%ld: %s\n", ex.m_file, ex.m_line, ex.m_cond); } DS::FreeSock(s_listenSock); }
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(); }