diff --git a/src/System/HttpParser.cpp b/src/System/HttpParser.cpp
new file mode 100644
index 00000000..3e4efd2d
--- /dev/null
+++ b/src/System/HttpParser.cpp
@@ -0,0 +1,215 @@
+// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
+//
+// This file is part of Bytecoin.
+//
+// Bytecoin is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Bytecoin is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with Bytecoin. If not, see .
+
+#include "HttpParser.h"
+
+#include
+
+namespace cryptonote {
+
+HttpResponse::HTTP_STATUS HttpParser::parseResponseStatusFromString(const std::string& status) {
+ if (status == "200 OK" || status == "200 Ok") return cryptonote::HttpResponse::STATUS_200;
+ else if (status == "404 Not Found") return cryptonote::HttpResponse::STATUS_404;
+ else if (status == "500 Internal Server Error") return cryptonote::HttpResponse::STATUS_500;
+ else throw std::runtime_error("Unknown HTTP status code is given");
+
+ return cryptonote::HttpResponse::STATUS_200; //unaccessible
+}
+
+
+void HttpParser::receiveRequest(std::istream& stream, HttpRequest& request) {
+ readWord(stream, request.method);
+ readWord(stream, request.url);
+
+ std::string httpVersion;
+ readWord(stream, httpVersion);
+
+ readHeaders(stream, request.headers);
+
+ std::string body;
+ size_t bodyLen = getBodyLen(request.headers);
+ if (bodyLen) {
+ readBody(stream, request.body, bodyLen);
+ }
+}
+
+
+void HttpParser::receiveResponse(std::istream& stream, HttpResponse& response) {
+ std::string httpVersion;
+ readWord(stream, httpVersion);
+
+ std::string status;
+ char c;
+
+ stream.get(c);
+ while (stream.good() && c != '\r') { //Till the end
+ status += c;
+ stream.get(c);
+ }
+
+ if (!stream.good()) {
+ throw std::runtime_error("Parser error: stream is not good");
+ }
+
+ if (c == '\r') {
+ stream.get(c);
+ if (c != '\n') {
+ throw std::runtime_error("Parser error: '\\n' symbol is expected");
+ }
+ }
+
+ response.setStatus(parseResponseStatusFromString(status));
+
+ std::string name;
+ std::string value;
+
+ while (readHeader(stream, name, value)) {
+ response.addHeader(name, value);
+ name.clear();
+ value.clear();
+ }
+
+ response.addHeader(name, value);
+ auto headers = response.getHeaders();
+ size_t length = 0;
+ auto it = headers.find("Content-Length");
+ if (it != headers.end()) {
+ length = std::stoul(it->second);
+ }
+
+ std::string body;
+ if (length) {
+ readBody(stream, body, length);
+ }
+
+ response.setBody(body);
+}
+
+
+void HttpParser::readWord(std::istream& stream, std::string& word) {
+ char c;
+
+ stream.get(c);
+ while (stream.good() && c != ' ' && c != '\r') {
+ word += c;
+ stream.get(c);
+ }
+
+ if (!stream.good()) {
+ throw std::runtime_error("Parser error: stream is not good");
+ }
+
+ if (c == '\r') {
+ stream.get(c);
+ if (c != '\n') {
+ throw std::runtime_error("Parser error: '\\n' symbol is expected");
+ }
+ }
+}
+
+void HttpParser::readHeaders(std::istream& stream, HttpRequest::Headers& headers) {
+ std::string name;
+ std::string value;
+
+ while (readHeader(stream, name, value)) {
+ headers[name] = value; //use insert
+ name.clear();
+ value.clear();
+ }
+
+ headers[name] = value; //use insert
+}
+
+bool HttpParser::readHeader(std::istream& stream, std::string& name, std::string& value) {
+ char c;
+ bool isName = true;
+
+ stream.get(c);
+ while (stream.good() && c != '\r') {
+ if (c == ':') {
+ if (stream.peek() == ' ') {
+ stream.get(c);
+ }
+
+ if (name.empty()) {
+ throw std::runtime_error("Header name must be not empty");
+ }
+
+ if (isName) {
+ isName = false;
+ stream.get(c);
+ continue;
+ }
+ }
+
+ if (isName) {
+ name += c;
+ stream.get(c);
+ } else {
+ value += c;
+ stream.get(c);
+ }
+ }
+
+ if (!stream.good()) {
+ throw std::runtime_error("Parser error: stream is not good");
+ }
+
+ stream.get(c);
+ if (c != '\n') {
+ throw std::runtime_error("Parser error: '\\n' symbol is expected");
+ }
+
+ c = stream.peek();
+ if (c == '\r') {
+ stream.get(c).get(c);
+ if (c != '\n') {
+ throw std::runtime_error("Parser error: '\\n' symbol is expected");
+ }
+
+ return false; //no more headers
+ }
+
+ return true;
+}
+
+size_t HttpParser::getBodyLen(const HttpRequest::Headers& headers) {
+ auto it = headers.find("Content-Length");
+ if (it != headers.end()) {
+ size_t bytes = std::stoul(it->second);
+ return bytes;
+ }
+
+ return 0;
+}
+
+void HttpParser::readBody(std::istream& stream, std::string& body, const size_t bodyLen) {
+ size_t read = 0;
+
+ while (stream.good() && read < bodyLen) {
+ body += stream.get();
+ ++read;
+ }
+
+ if (!stream.good()) {
+ throw std::runtime_error("stream is not good");
+ }
+}
+
+}
+
+
diff --git a/src/System/HttpParser.h b/src/System/HttpParser.h
new file mode 100644
index 00000000..75991781
--- /dev/null
+++ b/src/System/HttpParser.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
+//
+// This file is part of Bytecoin.
+//
+// Bytecoin is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Bytecoin is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with Bytecoin. If not, see .
+
+#ifndef HTTPPARSER_H_
+#define HTTPPARSER_H_
+
+#include
+#include