Http clean up.

--HG--
branch : dev
This commit is contained in:
Martín Lucas Golini
2019-05-08 02:13:07 -03:00
parent 9a42b7606a
commit f028f7b2b9
8 changed files with 239 additions and 205 deletions
+6 -6
View File
@@ -24,17 +24,17 @@ class EE_API IOStreamDeflate : public IOStream {
virtual ~IOStreamDeflate();
ios_size read( char * data, ios_size size );
virtual ios_size read( char * data, ios_size size );
ios_size write( const char * data, ios_size size );
virtual ios_size write( const char * data, ios_size size );
ios_size seek( ios_size position );
virtual ios_size seek( ios_size position );
ios_size tell();
virtual ios_size tell();
ios_size getSize();
virtual ios_size getSize();
bool isOpen();
virtual bool isOpen();
const Compression::Mode& getMode() const;
protected:
+6 -6
View File
@@ -23,17 +23,17 @@ class EE_API IOStreamInflate : public IOStream {
virtual ~IOStreamInflate();
ios_size read( char * data, ios_size size );
virtual ios_size read( char * data, ios_size size );
ios_size write( const char * data, ios_size size );
virtual ios_size write( const char * data, ios_size size );
ios_size seek( ios_size position );
virtual ios_size seek( ios_size position );
ios_size tell();
virtual ios_size tell();
ios_size getSize();
virtual ios_size getSize();
bool isOpen();
virtual bool isOpen();
const Compression::Mode& getMode() const;
protected:
+7 -7
View File
@@ -11,19 +11,19 @@ class EE_API IOStreamString : public IOStream {
public:
IOStreamString();
ios_size read( char * data, ios_size size );
virtual ios_size read( char * data, ios_size size );
ios_size write( const char * data, ios_size size );
virtual ios_size write( const char * data, ios_size size );
ios_size write( const std::string& string );
virtual ios_size write( const std::string& string );
ios_size seek( ios_size position );
virtual ios_size seek( ios_size position );
ios_size tell();
virtual ios_size tell();
ios_size getSize();
virtual ios_size getSize();
bool isOpen();
virtual bool isOpen();
void clear();
+56 -55
View File
@@ -145,8 +145,8 @@ newoption { trigger = "with-static-backend", description = "It will try to compi
newoption { trigger = "with-gles2", description = "Compile with GLES2 support" }
newoption { trigger = "with-gles1", description = "Compile with GLES1 support" }
newoption { trigger = "use-frameworks", description = "In Mac OS X it will try to link the external libraries from its frameworks. For example, instead of linking against SDL2 it will link agains SDL2.framework." }
newoption {
trigger = "with-backend",
newoption {
trigger = "with-backend",
description = "Select the backend to use for window and input handling.\n\t\t\tIf no backend is selected or if the selected is not installed the script will search for a backend present in the system, and will use it.",
allowed = {
{ "SDL2", "SDL2 (default and recommended)" },
@@ -167,21 +167,21 @@ function explode(div,str)
end
function os.get_real()
if _OPTIONS.platform == "ios-arm7" or
if _OPTIONS.platform == "ios-arm7" or
_OPTIONS.platform == "ios-x86" or
_OPTIONS.platform == "ios-cross-arm7" or
_OPTIONS.platform == "ios-cross-x86" then
return "ios"
end
if _OPTIONS.platform == "android-arm7" then
return "android"
end
if _OPTIONS.platform == "mingw32" then
return _OPTIONS.platform
end
if _OPTIONS.platform == "emscripten" then
return _OPTIONS.platform
end
@@ -229,7 +229,7 @@ end
function os_findlib( name )
if os.is_real("macosx") and ( is_xcode() or _OPTIONS["use-frameworks"] ) then
local path = "/Library/Frameworks/" .. name .. ".framework"
if os.isdir( path ) then
return path
end
@@ -241,12 +241,12 @@ end
function get_backend_link_name( name )
if os.is_real("macosx") and ( is_xcode() or _OPTIONS["use-frameworks"] ) then
local fname = name .. ".framework"
if os_findlib( name ) then -- Search for the framework
return fname
end
end
return name
end
@@ -254,7 +254,7 @@ function string.starts(String,Start)
if ( _ACTION ) then
return string.sub(String,1,string.len(Start))==Start
end
return false
end
@@ -315,7 +315,7 @@ function build_base_cpp_configuration( package_name )
if not os.is("windows") then
buildoptions{ "-fPIC" }
end
set_ios_config()
set_xcode_config()
@@ -364,7 +364,7 @@ function build_link_configuration( package_name, use_ee_icon )
includedirs { "include" }
local extension = "";
if package_name == "eepp" then
defines { "EE_EXPORTS" }
elseif package_name == "eepp-static" then
@@ -384,13 +384,13 @@ function build_link_configuration( package_name, use_ee_icon )
add_static_links()
links { link_list }
end
if os.is("windows") and not is_vs() then
if os.is("windows") and not is_vs() then
if ( true == use_ee_icon ) then
linkoptions { "../../bin/assets/icon/ee.res" }
end
end
if os.is_real("emscripten") then
extension = ".html"
@@ -403,11 +403,11 @@ function build_link_configuration( package_name, use_ee_icon )
linkoptions { "--preload-file assets/" }
end
end
if _OPTIONS.platform == "ios-cross-arm7" then
extension = ".ios"
end
if _OPTIONS.platform == "ios-cross-x86" then
extension = ".x86.ios"
end
@@ -440,10 +440,10 @@ function build_link_configuration( package_name, use_ee_icon )
fix_shared_lib_linking_path( package_name, "libeepp" )
targetname ( package_name .. extension )
configuration "windows"
add_cross_config_links()
configuration "emscripten"
linkoptions{ "-O2 -s TOTAL_MEMORY=67108864 -s ASM_JS=1 -s VERBOSE=1 -s DISABLE_EXCEPTION_CATCHING=0 -s USE_SDL=2 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s FULL_ES3=1 -s \"BINARYEN_TRAP_MODE='clamp'\"" }
buildoptions { "-fno-strict-aliasing -O2 -s USE_SDL=2 -s PRECISE_F32=1" }
@@ -463,7 +463,7 @@ end
function generate_os_links()
if os.is_real("linux") then
multiple_insert( os_links, { "rt", "pthread", "X11", "openal", "GL", "Xcursor" } )
if _OPTIONS["with-static-eepp"] then
table.insert( os_links, "dl" )
end
@@ -488,28 +488,28 @@ function parse_args()
if _OPTIONS["with-gles2"] then
defines { "EE_GLES2", "SOIL_GLES2" }
end
if _OPTIONS["with-gles1"] then
defines { "EE_GLES1", "SOIL_GLES1" }
end
end
end
function add_static_links()
-- The linking order DOES matter
-- Expose the symbols that need one static library AFTER adding that static lib
-- Add static backends
if next(static_backends) ~= nil then
for _, value in pairs( static_backends ) do
linkoptions { value }
end
end
if _OPTIONS["with-static-freetype"] or not os_findlib("freetype") then
print("Enabled static freetype")
links { "freetype-static" }
end
links { "SOIL2-static",
"chipmunk-static",
"libzip-static",
@@ -523,7 +523,7 @@ function add_static_links()
if _OPTIONS["with-ssl"] and not _OPTIONS["with-openssl"] then
links { "mbedtls-static" }
end
if not os.is_real("haiku") and not os.is_real("ios") and not os.is_real("android") and not os.is_real("emscripten") then
links{ "glew-static" }
end
@@ -544,7 +544,7 @@ function add_sdl2()
print("Using SDL2 backend");
files { "src/eepp/window/backend/SDL2/*.cpp" }
defines { "EE_BACKEND_SDL_ACTIVE", "EE_SDL_VERSION_2" }
if not can_add_static_backend("SDL2") then
table.insert( link_list, get_backend_link_name( "SDL2" ) )
else
@@ -556,7 +556,7 @@ function add_sfml()
print("Using SFML backend");
files { "src/eepp/window/backend/SFML/*.cpp" }
defines { "EE_BACKEND_SFML_ACTIVE" }
if not can_add_static_backend("SFML") then
table.insert( link_list, get_backend_link_name( "sfml-system" ) )
table.insert( link_list, get_backend_link_name( "sfml-window" ) )
@@ -577,13 +577,13 @@ end
function set_ios_config()
if _OPTIONS.platform == "ios-arm7" or _OPTIONS.platform == "ios-x86" then
local err = false
if nil == os.getenv("TOOLCHAINPATH") then
print("You must set TOOLCHAINPATH enviroment variable.")
print("\tExample: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/")
err = true
end
if nil == os.getenv("SYSROOTPATH") then
print("You must set SYSROOTPATH enviroment variable.")
print("\tExample: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk")
@@ -595,7 +595,7 @@ function set_ios_config()
print("\tExample: 5.0")
err = true
end
if err then
os.exit(1)
end
@@ -604,14 +604,14 @@ function set_ios_config()
local framework_path = sysroot_path .. "/System/Library/Frameworks"
local framework_libs_path = framework_path .. "/usr/lib"
local sysroot_ver = " -miphoneos-version-min=" .. os.getenv("IOSVERSION") .. " -isysroot " .. sysroot_path
buildoptions { sysroot_ver .. " -I" .. sysroot_path .. "/usr/include" }
linkoptions { sysroot_ver }
libdirs { framework_libs_path }
linkoptions { " -F" .. framework_path .. " -L" .. framework_libs_path .. " -isysroot " .. sysroot_path }
includedirs { "src/thirdparty/SDL2/include" }
end
if _OPTIONS.platform == "ios-cross-arm7" or _OPTIONS.platform == "ios-cross-x86" then
includedirs { "src/thirdparty/SDL2/include" }
end
@@ -625,7 +625,7 @@ function backend_is( name, libname )
if next(backends) == nil then
backends = string.explode(_OPTIONS["with-backend"],",")
end
local backend_sel = table.contains( backends, name )
local ret_val = os_findlib( libname ) and backend_sel
@@ -641,7 +641,7 @@ function backend_is( name, libname )
return ret_val
end
function select_backend()
function select_backend()
if backend_is("SDL2", "SDL2") then
print("Selected SDL2")
add_sdl2()
@@ -693,10 +693,10 @@ end
function build_eepp( build_name )
includedirs { "include", "src", "src/thirdparty", "include/eepp/thirdparty", "src/thirdparty/freetype2/include", "src/thirdparty/zlib", "src/thirdparty/libogg/include", "src/thirdparty/libvorbis/include", "src/thirdparty/mbedtls/include" }
set_ios_config()
set_xcode_config()
add_static_links()
if is_vs() then
@@ -725,6 +725,7 @@ function build_eepp( build_name )
"src/eepp/window/platform/null/*.cpp",
"src/eepp/network/*.cpp",
"src/eepp/network/ssl/*.cpp",
"src/eepp/network/http/*.cpp",
"src/eepp/scene/*.cpp",
"src/eepp/scene/actions/*.cpp",
"src/eepp/ui/*.cpp",
@@ -736,11 +737,11 @@ function build_eepp( build_name )
"src/eepp/maps/*.cpp",
"src/eepp/maps/mapeditor/*.cpp"
}
check_ssl_support()
select_backend()
if not _OPTIONS["with-static-freetype"] and os_findlib("freetype") then
table.insert( link_list, get_backend_link_name( "freetype" ) )
end
@@ -748,19 +749,19 @@ function build_eepp( build_name )
multiple_insert( link_list, os_links )
links { link_list }
build_link_configuration( build_name )
configuration "windows"
files { "src/eepp/window/platform/win/*.cpp" }
add_cross_config_links()
configuration "linux"
files { "src/eepp/window/platform/x11/*.cpp" }
configuration "macosx"
files { "src/eepp/window/platform/osx/*.cpp" }
configuration "emscripten"
if _OPTIONS["force-gles1"] then
defines{ "EE_GLES1_DEFAULT" }
@@ -776,7 +777,7 @@ function set_targetdir( dir )
end
solution "eepp"
targetdir("./bin/")
configurations { "debug", "release" }
@@ -865,7 +866,7 @@ solution "eepp"
files { "src/thirdparty/freetype2/src/**.c" }
includedirs { "src/thirdparty/freetype2/include" }
build_base_configuration( "freetype" )
project "chipmunk-static"
kind "StaticLib"
@@ -900,15 +901,15 @@ solution "eepp"
language "C++"
set_targetdir("libs/" .. os.get_real() .. "/thirdparty/")
includedirs { "src/thirdparty/efsw/include", "src/thirdparty/efsw/src" }
if os.is("windows") then
osfiles = "src/thirdparty/efsw/src/efsw/platform/win/*.cpp"
else
osfiles = "src/thirdparty/efsw/src/efsw/platform/posix/*.cpp"
end
files { "src/thirdparty/efsw/src/efsw/*.cpp", osfiles }
if os.is("windows") then
excludes { "src/thirdparty/efsw/src/efsw/WatcherKqueue.cpp", "src/thirdparty/efsw/src/efsw/WatcherFSEvents.cpp", "src/thirdparty/efsw/src/efsw/WatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherKqueue.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherFSEvents.cpp" }
elseif os.is("linux") then
@@ -918,7 +919,7 @@ solution "eepp"
elseif os.is("freebsd") then
excludes { "src/thirdparty/efsw/src/efsw/WatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/WatcherWin32.cpp", "src/thirdparty/efsw/src/efsw/WatcherFSEvents.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherWin32.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherFSEvents.cpp" }
end
build_base_cpp_configuration( "efsw" )
project "eepp-main"
@@ -932,7 +933,7 @@ solution "eepp"
language "C++"
set_targetdir("libs/" .. os.get_real() .. "/")
build_eepp( "eepp-static" )
project "eepp-shared"
kind "SharedLib"
language "C++"
@@ -1007,20 +1008,20 @@ solution "eepp"
language "C++"
files { "src/tools/mapeditor/*.cpp" }
build_link_configuration( "eepp-MapEditor", true )
project "eepp-uieditor"
set_kind()
language "C++"
includedirs { "src/thirdparty/efsw/include", "src/thirdparty" }
if not os.is("windows") and not os.is("haiku") then
links { "pthread" }
end
links { "efsw-static", "pugixml-static" }
files { "src/tools/uieditor/*.cpp" }
build_link_configuration( "eepp-UIEditor", true )
if os.isfile("external_projects.lua") then
dofile("external_projects.lua")
end
+2
View File
@@ -591,6 +591,8 @@
../../src/eepp/math/transform.cpp
../../src/eepp/network/ftp.cpp
../../src/eepp/network/http.cpp
../../src/eepp/network/http/httpstreamchunked.cpp
../../src/eepp/network/http/httpstreamchunked.hpp
../../src/eepp/network/ipaddress.cpp
../../src/eepp/network/packet.cpp
../../src/eepp/network/platform/platformimpl.hpp
+22 -131
View File
@@ -6,6 +6,7 @@
#include <eepp/system/iostreaminflate.hpp>
#include <eepp/system/iostreamstring.hpp>
#include <eepp/system/compression.hpp>
#include <eepp/network/http/httpstreamchunked.hpp>
#include <cctype>
#include <algorithm>
#include <iterator>
@@ -13,6 +14,7 @@
#include <limits>
using namespace EE::Network::SSL;
using namespace EE::Network::Private;
namespace EE { namespace Network {
@@ -592,17 +594,14 @@ Http::Response Http::downloadRequest(const Http::Request& request, IOStream& wri
char * eol = NULL; // end of line
char * bol = NULL; // beginning of line
char buffer[PACKET_BUFFER_SIZE+1];
std::string headerBuffer;
std::string chunkBuffer;
IOStreamString fileBuffer;
bool isnheader = false;
bool chunked = false;
bool chunkNewBuffer = false;
bool chunkEnded = false;
bool compressed = false;
IOStreamInflate * inflateStream = NULL;
ios_size inflateChunkSize = 0;
std::size_t contentLength = 0;
std::string headerBuffer;
HttpStreamChunked * chunkedStream = NULL;
IOStreamInflate * inflateStream = NULL;
IOStream * bufferStream = NULL;
while (!request.isCancelled() && ( status = mConnection->getSocket()->receive(buffer, PACKET_BUFFER_SIZE, readed) ) == Socket::Done) {
char * readBuffer = buffer;
@@ -654,11 +653,16 @@ Http::Response Http::downloadRequest(const Http::Request& request, IOStream& wri
if ( compressed ) {
Compression::Mode compressionMode = "gzip" == encoding ? Compression::MODE_GZIP : Compression::MODE_DEFLATE;
inflateChunkSize = Compression::getModeDefaultChunkSize( compressionMode );
inflateStream = IOStreamInflate::New( writeTo, compressionMode );
}
IOStream& writeToStream = compressed ? *inflateStream : writeTo;
if ( chunked )
chunkedStream = eeNew( HttpStreamChunked, ( writeToStream ) );
bufferStream = chunked ? chunkedStream : ( compressed ? inflateStream : &writeTo );
// Get the content length
if ( !received.getField("content-length").empty() ) {
if ( !String::fromString( contentLength, received.getField("content-length") ) )
@@ -689,6 +693,8 @@ Http::Response Http::downloadRequest(const Http::Request& request, IOStream& wri
request.mRedirectionCount++;
eeSAFE_DELETE( chunkedStream );
eeSAFE_DELETE( inflateStream );
return http.downloadRequest( request, writeTo, timeout );
}
}
@@ -715,124 +721,8 @@ Http::Response Http::downloadRequest(const Http::Request& request, IOStream& wri
if ( isnheader ) {
currentTotalBytes += readed;
if ( chunked ) {
if ( readed > 0 ) {
// If the chunk reading ended we just add the buffer received as a header
// Otherwise we process the buffer data as chunk
if ( !chunkEnded ) {
// Keep a chunk buffer until the end of chunk is found
chunkBuffer.append( readBuffer, readBuffer + readed );
// If the new chunk starts with \r\n and the last removed chunk
// did not contain the trailing \r\n, we remove it to detect
// correctly the next length data
if ( chunkNewBuffer ) {
if ( chunkBuffer.substr( 0, 2 ) == "\r\n" ) {
chunkBuffer = chunkBuffer.substr( 2 );
}
chunkNewBuffer = false;
}
bool retry;
do {
retry = false;
// Check for the first \r\n to find the end of the length definition
std::string::size_type lenEnd = chunkBuffer.find_first_of("\r\n");
if ( lenEnd != std::string::npos ) {
std::string::size_type firstCharPos = lenEnd + 2;
unsigned long length;
// Get the length of the chunk
bool res = String::fromString( length, chunkBuffer.substr(0, lenEnd), std::hex );
// If the length is solved...
if ( res ) {
// And it's bigger than 0, means that there are more chunks
if ( length > 0 ) {
// Check if the chunk buffer size at least equals to the length reported
if ( chunkBuffer.size() - firstCharPos >= length ) {
// In that case write the chunk to the file buffer
fileBuffer.write( &chunkBuffer[firstCharPos], length );
// And keep the remaining not completed chunk
chunkBuffer = chunkBuffer.substr( firstCharPos + length );
// Check if already have the \r\n of the next length in the buffer
if ( !chunkBuffer.empty() ) {
std::size_t pos = 0;
// Remove al the \r\n remaining
while ( pos < chunkBuffer.size() && 0 == strncmp( &chunkBuffer[pos], "\r\n", 2 ) ) {
pos += 2;
}
if ( pos > 0 ) {
// Remove it to be able to read the next length
chunkBuffer = chunkBuffer.substr( pos );
}
// If still the chunk is not empty it could be another chunk
// already received, so we check that retrying
if ( !chunkBuffer.empty() ) {
std::string::size_type lenEnd = chunkBuffer.find_first_of("\r\n");
if ( lenEnd != std::string::npos ) {
bool res = String::fromString( length, chunkBuffer.substr(0, lenEnd), std::hex );
if ( res && length > 0 ) {
retry = true;
}
}
}
}
// If the next chunk received starts with \r\n it's because
// it's part of the chunk size information, so we need to flag it
// to remove it
chunkNewBuffer = true;
}
} else {
// If the value is 0 means that the data ended
// But after this we can receive extra headers
chunkEnded = true;
chunkBuffer.clear();
}
}
}
} while ( retry );
} else {
headerBuffer.append( readBuffer, readBuffer + readed );
}
}
} else if ( readed > 0 ) {
// If not chunked just write into the file buffer
fileBuffer.write( readBuffer, readed );
}
if ( compressed ) {
if ( fileBuffer.getSize() - inflateChunkSize >= 0 ) {
inflateStream->write( fileBuffer.getStreamPointer(), inflateChunkSize );
IOStreamString newFileBuffer;
fileBuffer.seek(inflateChunkSize);
std::size_t trailing = fileBuffer.getSize() - inflateChunkSize;
if ( trailing > 0 )
newFileBuffer.write( fileBuffer.getPositionPointer(), trailing );
fileBuffer = newFileBuffer;
}
} else {
fileBuffer.seek(0);
writeTo.write( fileBuffer.getPositionPointer(), fileBuffer.getSize() );
fileBuffer.clear();
}
if ( readed > 0 )
bufferStream->write( readBuffer, readed );
if ( request.getProgressCallback() ) {
if ( !request.getProgressCallback()( *this, request, contentLength, currentTotalBytes ) ) {
@@ -843,20 +733,21 @@ Http::Response Http::downloadRequest(const Http::Request& request, IOStream& wri
}
}
if ( chunked && NULL != chunkedStream && !chunkedStream->getHeaderBuffer().empty() ) {
headerBuffer.append( chunkedStream->getHeaderBuffer() );
}
if ( !headerBuffer.empty() ) {
std::istringstream in(headerBuffer);
received.parseFields(in);
}
if ( compressed && fileBuffer.getSize() > 0 ) {
inflateStream->write( fileBuffer.getStreamPointer(), fileBuffer.getSize() );
}
if ( status == Socket::Status::Disconnected ) {
mConnection->setConnected(false);
mConnection->setTunneled(false);
}
eeSAFE_DELETE( chunkedStream );
eeSAFE_DELETE( inflateStream );
} else {
mConnection->setConnected(false);
+112
View File
@@ -0,0 +1,112 @@
#include <eepp/network/http/httpstreamchunked.hpp>
namespace EE { namespace Network { namespace Private {
HttpStreamChunked::HttpStreamChunked(IOStream & mWriteTo) :
mWriteTo( mWriteTo ),
mChunkNewBuffer(false),
mChunkEnded(false)
{}
ios_size HttpStreamChunked::write(const char * data, ios_size size) {
ios_size writeTotal = 0;
// If the chunk reading ended we just add the buffer received as a header
// Otherwise we process the buffer data as chunk
if ( !mChunkEnded ) {
// Keep a chunk buffer until the end of chunk is found
mChunkBuffer.append( data, size );
// If the new chunk starts with \r\n and the last removed chunk
// did not contain the trailing \r\n, we remove it to detect
// correctly the next length data
if ( mChunkNewBuffer ) {
if ( mChunkBuffer.substr( 0, 2 ) == "\r\n" ) {
mChunkBuffer = mChunkBuffer.substr( 2 );
}
mChunkNewBuffer = false;
}
bool retry;
do {
retry = false;
// Check for the first \r\n to find the end of the length definition
std::string::size_type lenEnd = mChunkBuffer.find_first_of("\r\n");
if ( lenEnd != std::string::npos ) {
std::string::size_type firstCharPos = lenEnd + 2;
unsigned long length;
// Get the length of the chunk
bool res = String::fromString( length, mChunkBuffer.substr(0, lenEnd), std::hex );
// If the length is solved...
if ( res ) {
// And it's bigger than 0, means that there are more chunks
if ( length > 0 ) {
// Check if the chunk buffer size at least equals to the length reported
if ( mChunkBuffer.size() - firstCharPos >= length ) {
// In that case write the chunk to the file buffer
writeTotal = mWriteTo.write( &mChunkBuffer[firstCharPos], length );
// And keep the remaining not completed chunk
mChunkBuffer = mChunkBuffer.substr( firstCharPos + length );
// Check if already have the \r\n of the next length in the buffer
if ( !mChunkBuffer.empty() ) {
std::size_t pos = 0;
// Remove al the \r\n remaining
while ( pos < mChunkBuffer.size() && 0 == strncmp( &mChunkBuffer[pos], "\r\n", 2 ) ) {
pos += 2;
}
if ( pos > 0 ) {
// Remove it to be able to read the next length
mChunkBuffer = mChunkBuffer.substr( pos );
}
// If still the chunk is not empty it could be another chunk
// already received, so we check that retrying
if ( !mChunkBuffer.empty() ) {
std::string::size_type lenEnd = mChunkBuffer.find_first_of("\r\n");
if ( lenEnd != std::string::npos ) {
bool res = String::fromString( length, mChunkBuffer.substr(0, lenEnd), std::hex );
if ( res && length > 0 ) {
retry = true;
}
}
}
}
// If the next chunk received starts with \r\n it's because
// it's part of the chunk size information, so we need to flag it
// to remove it
mChunkNewBuffer = true;
}
} else {
// If the value is 0 means that the data ended
// But after this we can receive extra headers
mChunkEnded = true;
mChunkBuffer.clear();
}
}
}
} while ( retry );
} else {
mHeaderBuffer.append( data, size );
}
return writeTotal;
}
const std::string& HttpStreamChunked::getHeaderBuffer() const {
return mHeaderBuffer;
}
}}}
@@ -0,0 +1,28 @@
#ifndef EE_NETWORK_HTTPSTREAMCHUNKED_HPP
#define EE_NETWORK_HTTPSTREAMCHUNKED_HPP
#include <eepp/system/iostreamstring.hpp>
#include <eepp/core/string.hpp>
using namespace EE::System;
namespace EE { namespace Network { namespace Private {
class HttpStreamChunked : public IOStreamString {
public:
HttpStreamChunked( IOStream& mWriteTo );
ios_size write( const char * data, ios_size size );
const std::string& getHeaderBuffer() const;
protected:
IOStream& mWriteTo;
std::string mChunkBuffer;
std::string mHeaderBuffer;
bool mChunkNewBuffer = false;
bool mChunkEnded = false;
};
}}}
#endif // EE_NETWORK_HTTPSTREAMCHUNKED_HPP