Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up HTTP server implementation #8775

Merged
merged 12 commits into from
May 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1001,6 +1001,8 @@ add_library(native STATIC
ext/native/net/http_client.h
ext/native/net/resolve.cpp
ext/native/net/resolve.h
ext/native/net/sinks.cpp
ext/native/net/sinks.h
ext/native/net/url.cpp
ext/native/net/url.h
ext/native/profiler/profiler.cpp
Expand Down
13 changes: 12 additions & 1 deletion Core/FileLoaders/CachingFileLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,22 @@ void CachingFileLoader::Seek(s64 absolutePos) {
}

size_t CachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data) {
if (absolutePos >= filesize_) {
bytes = 0;
} else if (absolutePos + (s64)bytes >= filesize_) {
bytes = filesize_ - absolutePos;
}

size_t readSize = ReadFromCache(absolutePos, bytes, data);
// While in case the cache size is too small for the entire read.
while (readSize < bytes) {
SaveIntoCache(absolutePos + readSize, bytes - readSize);
readSize += ReadFromCache(absolutePos + readSize, bytes - readSize, (u8 *)data + readSize);
size_t bytesFromCache = ReadFromCache(absolutePos + readSize, bytes - readSize, (u8 *)data + readSize);
readSize += bytesFromCache;
if (bytesFromCache == 0) {
// We can't read any more.
break;
}
}

StartReadAhead(absolutePos + readSize);
Expand Down
13 changes: 12 additions & 1 deletion Core/FileLoaders/DiskCachingFileLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,24 @@ void DiskCachingFileLoader::Seek(s64 absolutePos) {
size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data) {
size_t readSize;

if (absolutePos >= filesize_) {
bytes = 0;
} else if (absolutePos + (s64)bytes >= filesize_) {
bytes = filesize_ - absolutePos;
}

if (cache_ && cache_->IsValid()) {
readSize = cache_->ReadFromCache(absolutePos, bytes, data);
// While in case the cache size is too small for the entire read.
while (readSize < bytes) {
readSize += cache_->SaveIntoCache(backend_, absolutePos + readSize, bytes - readSize, (u8 *)data + readSize);
// If there are already-cached blocks afterward, we have to read them.
readSize += cache_->ReadFromCache(absolutePos + readSize, bytes - readSize, (u8 *)data + readSize);
size_t bytesFromCache = cache_->ReadFromCache(absolutePos + readSize, bytes - readSize, (u8 *)data + readSize);
readSize += bytesFromCache;
if (bytesFromCache == 0) {
// We can't read any more.
break;
}
}
} else {
readSize = backend_->ReadAt(absolutePos, bytes, data);
Expand Down
9 changes: 7 additions & 2 deletions Core/FileLoaders/RamCachingFileLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@ size_t RamCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data) {
// While in case the cache size is too small for the entire read.
while (readSize < bytes) {
SaveIntoCache(absolutePos + readSize, bytes - readSize);
readSize += ReadFromCache(absolutePos + readSize, bytes - readSize, (u8 *)data + readSize);
size_t bytesFromCache = ReadFromCache(absolutePos + readSize, bytes - readSize, (u8 *)data + readSize);
readSize += bytesFromCache;
if (bytesFromCache == 0) {
// We can't read any more.
break;
}
}
}

Expand Down Expand Up @@ -134,7 +139,7 @@ size_t RamCachingFileLoader::ReadFromCache(s64 pos, size_t bytes, void *data) {
u8 *p = (u8 *)data;

// Clamp bytes to what's actually available.
if (pos + bytes > filesize_) {
if (pos + (s64)bytes > filesize_) {
// Should've been caught above, but just in case.
if (pos >= filesize_) {
return 0;
Expand Down
2 changes: 1 addition & 1 deletion Core/Loaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader) {
return FILETYPE_ARCHIVE_RAR;
} else if (!strcasecmp(extension.c_str(),".r01")) {
return FILETYPE_ARCHIVE_RAR;
} else if (!strcasecmp(extension.substr(1).c_str(), ".7z")) {
} else if (!extension.empty() && !strcasecmp(extension.substr(1).c_str(), ".7z")) {
return FILETYPE_ARCHIVE_7Z;
}
return FILETYPE_UNKNOWN;
Expand Down
8 changes: 6 additions & 2 deletions Windows/GEDebugger/TabState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1007,10 +1007,14 @@ TabStateTexture::TabStateTexture(HINSTANCE _hInstance, HWND _hParent)
}

TabStateWatch::TabStateWatch(HINSTANCE _hInstance, HWND _hParent)
: TabStateValues(&watchList[0], 0, (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
: TabStateValues(nullptr, 0, (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
}

void TabStateWatch::Update() {
values->UpdateRows(&watchList[0], (int)watchList.size());
if (watchList.empty()) {
values->UpdateRows(nullptr, 0);
} else {
values->UpdateRows(&watchList[0], (int)watchList.size());
}
TabStateValues::Update();
}
1 change: 1 addition & 0 deletions ext/native/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ LOCAL_SRC_FILES :=\
net/http_server.cpp \
net/http_headers.cpp \
net/resolve.cpp \
net/sinks.cpp \
net/url.cpp \
profiler/profiler.cpp \
thread/executor.cpp \
Expand Down
14 changes: 11 additions & 3 deletions ext/native/file/fd_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ ssize_t Write(int fd, const std::string &str) {
return WriteLine(fd, str.c_str(), str.size());
}

bool WaitUntilReady(int fd, double timeout) {
bool WaitUntilReady(int fd, double timeout, bool for_write) {
struct timeval tv;
tv.tv_sec = floor(timeout);
tv.tv_usec = (timeout - floor(timeout)) * 1000000.0;
Expand All @@ -84,7 +84,12 @@ bool WaitUntilReady(int fd, double timeout) {
FD_ZERO(&fds);
FD_SET(fd, &fds);
// First argument to select is the highest socket in the set + 1.
int rval = select(fd + 1, &fds, NULL, NULL, &tv);
int rval;
if (for_write) {
rval = select(fd + 1, NULL, &fds, NULL, &tv);
} else {
rval = select(fd + 1, &fds, NULL, NULL, &tv);
}
if (rval < 0) {
// Error calling select.
return false;
Expand Down Expand Up @@ -115,7 +120,10 @@ void SetNonBlocking(int sock, bool non_blocking) {
ELOG("Error setting socket nonblocking status");
}
#else
WLOG("NonBlocking mode not supported on Win32");
u_long val = non_blocking ? 1 : 0;
if (ioctlsocket(sock, FIONBIO, &val) != 0) {
ELOG("Error setting socket nonblocking status");
}
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion ext/native/file/fd_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ssize_t Write(int fd, const std::string &str);

// Returns true if the fd became ready, false if it didn't or
// if there was another error.
bool WaitUntilReady(int fd, double timeout);
bool WaitUntilReady(int fd, double timeout, bool for_write = false);

void SetNonBlocking(int fd, bool non_blocking);

Expand Down
2 changes: 2 additions & 0 deletions ext/native/native.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@
<ClInclude Include="net\resolve.h" />
<ClInclude Include="net\url.h" />
<ClInclude Include="profiler\profiler.h" />
<ClInclude Include="net\sinks.h" />
<ClInclude Include="thin3d\d3dx9_loader.h" />
<ClInclude Include="thin3d\thin3d.h" />
<ClInclude Include="thread\executor.h" />
Expand Down Expand Up @@ -723,6 +724,7 @@
<ClCompile Include="net\resolve.cpp" />
<ClCompile Include="net\url.cpp" />
<ClCompile Include="profiler\profiler.cpp" />
<ClCompile Include="net\sinks.cpp" />
<ClCompile Include="thin3d\d3dx9_loader.cpp" />
<ClCompile Include="thin3d\thin3d.cpp" />
<ClCompile Include="thin3d\thin3d_d3d9.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions ext/native/native.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@
<ClInclude Include="math\dataconv.h">
<Filter>math</Filter>
</ClInclude>
<ClInclude Include="net\sinks.h">
<Filter>net</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="gfx\gl_debug_log.cpp">
Expand Down Expand Up @@ -745,6 +748,9 @@
<ClCompile Include="thin3d\thin3d_vulkan.cpp">
<Filter>thin3d</Filter>
</ClCompile>
<ClCompile Include="net\sinks.cpp">
<Filter>net</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="gfx">
Expand Down
73 changes: 40 additions & 33 deletions ext/native/net/http_headers.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#include "net/http_headers.h"

#include <algorithm>
#include <stdio.h>
#include <stdlib.h>

#include "base/logging.h"
#include "base/stringutil.h"
#include "file/fd_util.h"
#include "net/sinks.h"

namespace http {

Expand Down Expand Up @@ -39,6 +41,15 @@ bool RequestHeader::GetParamValue(const char *param_name, std::string *value) co
return false;
}

bool RequestHeader::GetOther(const char *name, std::string *value) const {
auto it = other.find(name);
if (it != other.end()) {
*value = it->second;
return true;
}
return false;
}

// Intended to be a mad fast parser. It's not THAT fast currently, there's still
// things to optimize, but meh.
int RequestHeader::ParseHttpHeader(const char *buffer) {
Expand All @@ -56,7 +67,7 @@ int RequestHeader::ParseHttpHeader(const char *buffer) {
buffer += 5;
} else {
method = UNSUPPORTED;
status = 501;
status = 405;
return -1;
}
SkipSpace(&buffer);
Expand Down Expand Up @@ -99,56 +110,52 @@ int RequestHeader::ParseHttpHeader(const char *buffer) {

// The header is formatted as key: value.
int key_len = colon - buffer;
char *key = new char[key_len + 1];
strncpy(key, buffer, key_len);
key[key_len] = 0;
StringUpper(key, key_len);
const char *key = buffer;

// Go to after the colon to get the value.
buffer = colon + 1;
SkipSpace(&buffer);
int value_len = (int)strlen(buffer);

if (!strcmp(key, "USER-AGENT")) {
if (!strncasecmp(key, "User-Agent", key_len)) {
user_agent = new char[value_len + 1];
memcpy(user_agent, buffer, value_len + 1);
ILOG("user-agent: %s", user_agent);
} else if (!strcmp(key, "REFERER")) {
} else if (!strncasecmp(key, "Referer", key_len)) {
referer = new char[value_len + 1];
memcpy(referer, buffer, value_len + 1);
} else if (!strcmp(key, "CONTENT-LENGTH")) {
} else if (!strncasecmp(key, "Content-Length", key_len)) {
content_length = atoi(buffer);
ILOG("Content-Length: %i", (int)content_length);
} else {
std::string key_str(key, key_len);
std::transform(key_str.begin(), key_str.end(), key_str.begin(), tolower);
other[key_str] = buffer;
}

delete [] key;
return 0;
}

void RequestHeader::ParseHeaders(int fd) {
int line_count = 0;
// Loop through request headers.
while (true) {
if (!fd_util::WaitUntilReady(fd, 5.0)) { // Wait max 5 secs.
// Timed out or error.
ok = false;
return;
}
char buffer[1024];
fd_util::ReadLine(fd, buffer, 1023);
StringTrimEndNonAlphaNum(buffer);
if (buffer[0] == '\0')
break;
ParseHttpHeader(buffer);
line_count++;
if (type == SIMPLE) {
// Done!
ILOG("Simple: Done parsing http request.");
break;
}
}
ILOG("finished parsing request.");
ok = line_count > 1;
void RequestHeader::ParseHeaders(net::InputSink *sink) {
int line_count = 0;
std::string line;
while (sink->ReadLine(line)) {
if (line.length() == 0) {
// Blank line, this means end of headers.
break;
}

ParseHttpHeader(line.c_str());
line_count++;
if (type == SIMPLE) {
// Done!
ILOG("Simple: Done parsing http request.");
break;
}
}

ILOG("finished parsing request.");
ok = line_count > 1;
}

} // namespace http
11 changes: 10 additions & 1 deletion ext/native/net/http_headers.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#ifndef _NET_HTTP_HTTP_HEADERS
#define _NET_HTTP_HTTP_HEADERS

#include <string>
#include <unordered_map>
#include "base/buffer.h"

namespace net {
class InputSink;
};

namespace http {

class RequestHeader {
Expand All @@ -12,11 +18,13 @@ class RequestHeader {
// Public variables since it doesn't make sense
// to bother with accessors for all these.
int status;
// Intentional misspelling.
char *referer;
char *user_agent;
char *resource;
char *params;
int content_length;
std::unordered_map<std::string, std::string> other;
enum RequestType {
SIMPLE, FULL,
};
Expand All @@ -29,8 +37,9 @@ class RequestHeader {
};
Method method;
bool ok;
void ParseHeaders(int fd);
void ParseHeaders(net::InputSink *sink);
bool GetParamValue(const char *param_name, std::string *value) const;
bool GetOther(const char *name, std::string *value) const;
private:
int ParseHttpHeader(const char *buffer);
bool first_header_;
Expand Down
Loading