diff options
author | Alexander Tkachev | 2016-07-07 18:04:48 +0600 |
---|---|---|
committer | Alexander Tkachev | 2016-08-24 16:07:55 +0600 |
commit | f91bb39192cd11a0cb30a39bfb630d2fd9fad89e (patch) | |
tree | ab07ff6532d41c97fc5f970eda219586bdaed02a /backends/networking | |
parent | 589b4cd45741ff73ba2d1260a14a14351cfba914 (diff) | |
download | scummvm-rg350-f91bb39192cd11a0cb30a39bfb630d2fd9fad89e.tar.gz scummvm-rg350-f91bb39192cd11a0cb30a39bfb630d2fd9fad89e.tar.bz2 scummvm-rg350-f91bb39192cd11a0cb30a39bfb630d2fd9fad89e.zip |
CLOUD: Use Reader in Client
Instead of copy-pasting it I'm just "integrating" it in.
Diffstat (limited to 'backends/networking')
-rw-r--r-- | backends/networking/sdl_net/client.cpp | 86 | ||||
-rw-r--r-- | backends/networking/sdl_net/client.h | 6 | ||||
-rw-r--r-- | backends/networking/sdl_net/localwebserver.cpp | 4 | ||||
-rw-r--r-- | backends/networking/sdl_net/reader.cpp | 119 | ||||
-rw-r--r-- | backends/networking/sdl_net/reader.h | 31 |
5 files changed, 125 insertions, 121 deletions
diff --git a/backends/networking/sdl_net/client.cpp b/backends/networking/sdl_net/client.cpp index f567891dd8..adcbafdb12 100644 --- a/backends/networking/sdl_net/client.cpp +++ b/backends/networking/sdl_net/client.cpp @@ -45,6 +45,7 @@ void Client::open(SDLNet_SocketSet set, TCPsocket socket) { _socket = socket; _set = set; _headers = ""; + _reader = Reader(); _method = ""; _path = ""; _query = ""; @@ -63,88 +64,25 @@ void Client::readHeaders() { if (!SDLNet_SocketReady(_socket)) return; const uint32 BUFFER_SIZE = 16 * 1024; - char buffer[BUFFER_SIZE]; + byte buffer[BUFFER_SIZE]; int bytes = SDLNet_TCP_Recv(_socket, buffer, BUFFER_SIZE); if (bytes <= 0) { warning("Client::readHeaders recv fail"); close(); return; } - _headers += Common::String(buffer, bytes); - checkIfHeadersEnded(); - checkIfBadRequest(); -} - -void Client::checkIfHeadersEnded() { - const char *cstr = _headers.c_str(); - const char *position = strstr(cstr, "\r\n\r\n"); - if (position) _state = READ_HEADERS; -} - -void Client::checkIfBadRequest() { - uint32 headersSize = _headers.size(); - bool bad = false; - - const uint32 SUSPICIOUS_HEADERS_SIZE = 128 * 1024; - if (headersSize > SUSPICIOUS_HEADERS_SIZE) bad = true; - - if (!bad) { - if (headersSize > 0) { - const char *cstr = _headers.c_str(); - const char *position = strstr(cstr, "\r\n"); - if (position) { //we have at least one line - and we want the first one - //"<METHOD> <path> HTTP/<VERSION>\r\n" - Common::String method, path, http, buf; - uint32 length = position - cstr; - if (headersSize > length) headersSize = length; - for (uint32 i = 0; i < headersSize; ++i) { - if (_headers[i] != ' ') buf += _headers[i]; - if (_headers[i] == ' ' || i == headersSize - 1) { - if (method == "") method = buf; - else if (path == "") path = buf; - else if (http == "") http = buf; - else { - bad = true; - break; - } - buf = ""; - } - } - - //check that method is supported - if (method != "GET" && method != "PUT" && method != "POST") bad = true; - - //check that HTTP/<VERSION> is OK - if (!http.hasPrefix("HTTP/")) bad = true; - - _method = method; - parsePathQueryAndAnchor(path); - } + + _reader.setContent(buffer, bytes); + if (_reader.readResponse()) { + if (_reader.badRequest()) _state = BAD_REQUEST; + else { + _state = READ_HEADERS; + _method = _reader.method(); + _path = _reader.path(); + _query = _reader.query(); + _anchor = _reader.anchor(); } } - - if (bad) _state = BAD_REQUEST; -} - -void Client::parsePathQueryAndAnchor(Common::String path) { - //<path>[?query][#anchor] - bool readingPath = true; - bool readingQuery = false; - _path = ""; - _query = ""; - _anchor = ""; - for (uint32 i = 0; i < path.size(); ++i) { - if (readingPath) { - if (path[i] == '?') { - readingPath = false; - readingQuery = true; - } else _path += path[i]; - } else if(readingQuery) { - if (path[i] == '#') { - readingQuery = false; - } else _query += path[i]; - } else _anchor += path[i]; - } } void Client::setHandler(ClientHandler *handler) { diff --git a/backends/networking/sdl_net/client.h b/backends/networking/sdl_net/client.h index eba5dabfba..a54f72ae2b 100644 --- a/backends/networking/sdl_net/client.h +++ b/backends/networking/sdl_net/client.h @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/str.h" +#include "reader.h" typedef struct _SDLNet_SocketSet *SDLNet_SocketSet; typedef struct _TCPsocket *TCPsocket; @@ -51,14 +52,11 @@ class Client { ClientState _state; SDLNet_SocketSet _set; TCPsocket _socket; + Reader _reader; Common::String _headers; Common::String _method, _path, _query, _anchor; ClientHandler *_handler; - void checkIfHeadersEnded(); - void checkIfBadRequest(); - void parsePathQueryAndAnchor(Common::String path); - public: Client(); Client(SDLNet_SocketSet set, TCPsocket socket); diff --git a/backends/networking/sdl_net/localwebserver.cpp b/backends/networking/sdl_net/localwebserver.cpp index d8f12b8220..8f9c30d069 100644 --- a/backends/networking/sdl_net/localwebserver.cpp +++ b/backends/networking/sdl_net/localwebserver.cpp @@ -48,10 +48,6 @@ LocalWebserver::LocalWebserver(): _set(nullptr), _serverSocket(nullptr), _timerS addPathHandler("/create", _createDirectoryHandler.getHandler()); addPathHandler("/download", _downloadFileHandler.getHandler()); _defaultHandler = _resourceHandler.getHandler(); - - Reader reader; - reader.setBytesLeft(128); - while (!reader.readResponse()) reader.setBytesLeft(20); } LocalWebserver::~LocalWebserver() { diff --git a/backends/networking/sdl_net/reader.cpp b/backends/networking/sdl_net/reader.cpp index b6bf9e52ba..3f7983506a 100644 --- a/backends/networking/sdl_net/reader.cpp +++ b/backends/networking/sdl_net/reader.cpp @@ -29,11 +29,9 @@ namespace Networking { Reader::Reader() { _state = RS_NONE; + _content = nullptr; _bytesLeft = 0; - _contentLength = 0; - _availableBytes = 0; - _window = nullptr; _windowUsed = 0; _windowSize = 0; @@ -41,28 +39,9 @@ Reader::Reader() { _headers = ""; _buffer = ""; - _content = - "POST /upload HTTP/1.1\r\n" \ - "Host: 127.0.0.1:12345\r\n" \ - "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0\r\n" \ - "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \ - "Accept-Language: ru,en-US;q=0.7,en;q=0.3\r\n" \ - "Accept-Encoding: gzip, deflate\r\n" \ - "Referer: http://127.0.0.1:12345/files\r\n" \ - "Connection: keep-alive\r\n" \ - "Content-Type: multipart/form-data; boundary=---------------------------93411339527546\r\n" \ - "Content-Length: 319\r\n" \ - "\r\n" \ - "-----------------------------93411339527546\r\n" \ - "Content-Disposition: form-data; name=\"path\"\r\n" \ - "\r\n" \ - "/root\r\n" \ - "-----------------------------93411339527546\r\n" \ - "Content-Disposition: form-data; name=\"upload_file\"; filename=\"irc.txt\"\r\n" \ - "Content-Type: text/plain\r\n" \ - "\r\n" \ - "shells.fnordserver.eu/1400\r\n" \ - "-----------------------------93411339527546--"; + _contentLength = 0; + _availableBytes = 0; + _isBadRequest = false; } Reader::~Reader() {} @@ -77,6 +56,10 @@ bool Reader::readResponse() { if (!readHeaders()) return false; + if (_boundary.empty()) return true; //not POST multipart + + if (!bytesLeft()) return false; + if (_state == RS_READING_CONTENT) if (!readContent()) return false; @@ -133,7 +116,8 @@ void readFromThatUntilLineEnd(const char *cstr, Common::String needle, Common::S void Reader::handleHeaders(Common::String headers) { debug("\nHANDLE HEADERS:\n>>%s<<", headers.c_str()); if (_boundary.empty()) { - //TODO: parse method, path, query, fragment + //parse method, path, query, fragment + parseFirstLine(headers); //find boundary _boundary = ""; @@ -162,6 +146,72 @@ void Reader::handleHeaders(Common::String headers) { } } +void Reader::parseFirstLine(const Common::String &headers) { + uint32 headersSize = headers.size(); + bool bad = false; + + const uint32 SUSPICIOUS_HEADERS_SIZE = 128 * 1024; + if (headersSize > SUSPICIOUS_HEADERS_SIZE) bad = true; + + if (!bad) { + if (headersSize > 0) { + const char *cstr = headers.c_str(); + const char *position = strstr(cstr, "\r\n"); + if (position) { //we have at least one line - and we want the first one + //"<METHOD> <path> HTTP/<VERSION>\r\n" + Common::String method, path, http, buf; + uint32 length = position - cstr; + if (headersSize > length) headersSize = length; + for (uint32 i = 0; i < headersSize; ++i) { + if (headers[i] != ' ') buf += headers[i]; + if (headers[i] == ' ' || i == headersSize - 1) { + if (method == "") method = buf; + else if (path == "") path = buf; + else if (http == "") http = buf; + else { + bad = true; + break; + } + buf = ""; + } + } + + //check that method is supported + if (method != "GET" && method != "PUT" && method != "POST") bad = true; + + //check that HTTP/<VERSION> is OK + if (!http.hasPrefix("HTTP/")) bad = true; + + _method = method; + parsePathQueryAndAnchor(path); + } + } + } + + if (bad) _isBadRequest = true; +} + +void Reader::parsePathQueryAndAnchor(Common::String path) { + //<path>[?query][#anchor] + bool readingPath = true; + bool readingQuery = false; + _path = ""; + _query = ""; + _anchor = ""; + for (uint32 i = 0; i < path.size(); ++i) { + if (readingPath) { + if (path[i] == '?') { + readingPath = false; + readingQuery = true; + } else _path += path[i]; + } else if (readingQuery) { + if (path[i] == '#') { + readingQuery = false; + } else _query += path[i]; + } else _anchor += path[i]; + } +} + bool Reader::readContent() { Common::String boundary = "--" + _boundary; if (_window == nullptr) { @@ -251,7 +301,7 @@ bool Reader::readOneByteInString(Common::String &buffer, const Common::String &b byte Reader::readOne() { byte b = _content[0]; - _content.deleteChar(0); + ++_content; --_availableBytes; --_bytesLeft; return b; @@ -259,6 +309,19 @@ byte Reader::readOne() { uint32 Reader::bytesLeft() { return _bytesLeft; } -void Reader::setBytesLeft(uint32 b) { _bytesLeft = b; } +void Reader::setContent(byte *buffer, uint32 size) { + _content = buffer; + _bytesLeft = size; +} + +bool Reader::badRequest() { return _isBadRequest; } + +Common::String Reader::method() const { return _method; } + +Common::String Reader::path() const { return _path; } + +Common::String Reader::query() const { return _query; } + +Common::String Reader::anchor() const { return _anchor; } } // End of namespace Networking diff --git a/backends/networking/sdl_net/reader.h b/backends/networking/sdl_net/reader.h index b91973ea22..245f63abd1 100644 --- a/backends/networking/sdl_net/reader.h +++ b/backends/networking/sdl_net/reader.h @@ -37,25 +37,25 @@ enum ReaderState { }; class Reader { - ///Common::String _headers; - ///Common::String _method, _path, _query, _anchor; ReaderState _state; - Common::String _content; + byte *_content; uint32 _bytesLeft; - Common::String _boundary; - uint32 _contentLength; - uint32 _availableBytes; + byte *_window; + uint32 _windowUsed, _windowSize; Common::String _headers; Common::String _buffer; - Common::String _currentFieldName; + ///Common::String _headers; + Common::String _method, _path, _query, _anchor; Common::HashMap<Common::String, Common::String> _fields; Common::HashMap<Common::String, Common::String> _attachedFiles; - - byte *_window; - uint32 _windowUsed, _windowSize; + uint32 _contentLength; + Common::String _boundary; + uint32 _availableBytes; + Common::String _currentFieldName; + bool _isBadRequest; bool readHeaders(); //true when ended reading bool readContent(); //true when ended reading @@ -63,6 +63,9 @@ class Reader { void handleFileContent(Common::String filename); void handleValueContent(Common::String value); + void parseFirstLine(const Common::String &headers); + void parsePathQueryAndAnchor(Common::String path); + void makeWindow(uint32 size); void freeWindow(); ///bool Reader::readOneByteInStream(stream); @@ -76,7 +79,13 @@ public: ~Reader(); bool readResponse(); //true when ended reading - void setBytesLeft(uint32 b); + void setContent(byte *buffer, uint32 size); + bool badRequest(); + + Common::String method() const; + Common::String path() const; + Common::String query() const; + Common::String anchor() const; }; } // End of namespace Networking |