forked from amjuarez/bytecoin
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
jezal
committed
Sep 15, 2014
1 parent
6d74194
commit 640efb3
Showing
6 changed files
with
528 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <http://www.gnu.org/licenses/>. | ||
|
||
#include "HttpParser.h" | ||
|
||
#include <stdexcept> | ||
|
||
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"); | ||
} | ||
} | ||
|
||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <http://www.gnu.org/licenses/>. | ||
|
||
#ifndef HTTPPARSER_H_ | ||
#define HTTPPARSER_H_ | ||
|
||
#include <iostream> | ||
#include <map> | ||
#include <string> | ||
#include "HttpRequest.h" | ||
#include "HttpResponse.h" | ||
|
||
namespace cryptonote { | ||
|
||
//Blocking HttpParser | ||
class HttpParser { | ||
public: | ||
HttpParser() {}; | ||
|
||
void receiveRequest(std::istream& stream, HttpRequest& request); | ||
void receiveResponse(std::istream& stream, HttpResponse& response); | ||
static HttpResponse::HTTP_STATUS parseResponseStatusFromString(const std::string& status); | ||
private: | ||
void readWord(std::istream& stream, std::string& word); | ||
void readHeaders(std::istream& stream, HttpRequest::Headers &headers); | ||
bool readHeader(std::istream& stream, std::string& name, std::string& value); | ||
size_t getBodyLen(const HttpRequest::Headers& headers); | ||
void readBody(std::istream& stream, std::string& body, const size_t bodyLen); | ||
}; | ||
|
||
} //namespace cryptonote | ||
|
||
#endif /* HTTPPARSER_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// 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 <http://www.gnu.org/licenses/>. | ||
|
||
#include "HttpRequest.h" | ||
|
||
namespace cryptonote { | ||
|
||
const std::string& HttpRequest::getMethod() const { | ||
return method; | ||
} | ||
|
||
const std::string& HttpRequest::getUrl() const { | ||
return url; | ||
} | ||
|
||
const HttpRequest::Headers& HttpRequest::getHeaders() const { | ||
return headers; | ||
} | ||
|
||
const std::string& HttpRequest::getBody() const { | ||
return body; | ||
} | ||
|
||
void HttpRequest::addHeader(const std::string& name, const std::string& value) { | ||
headers[name] = value; | ||
} | ||
void HttpRequest::setBody(const std::string& b) { | ||
body = b; | ||
if (!body.empty()) { | ||
headers["Content-Length"] = std::to_string(body.size()); | ||
} | ||
else { | ||
headers.erase("Content-Length"); | ||
} | ||
} | ||
|
||
void HttpRequest::setUrl(const std::string& u) { | ||
url = u; | ||
} | ||
|
||
std::ostream& HttpRequest::printHttpRequest(std::ostream& os) const { | ||
os << "POST " << url << " HTTP/1.1\r\n"; | ||
auto host = headers.find("Host"); | ||
if (host == headers.end()) { | ||
os << "Host: " << "127.0.0.1" << "\r\n"; | ||
} | ||
|
||
for (auto pair : headers) { | ||
os << pair.first << ": " << pair.second << "\r\n"; | ||
} | ||
|
||
os << "\r\n"; | ||
if (!body.empty()) { | ||
os << body; | ||
} | ||
|
||
return os; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// 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 <http://www.gnu.org/licenses/>. | ||
|
||
#pragma once | ||
|
||
#include <iostream> | ||
#include <map> | ||
#include <string> | ||
|
||
namespace cryptonote { | ||
class HttpRequest { | ||
public: | ||
typedef std::map<std::string, std::string> Headers; | ||
|
||
const std::string& getMethod() const; | ||
const std::string& getUrl() const; | ||
const Headers& getHeaders() const; | ||
const std::string& getBody() const; | ||
|
||
void addHeader(const std::string& name, const std::string& value); | ||
void setBody(const std::string& b); | ||
void setUrl(const std::string& uri); | ||
|
||
private: | ||
friend class HttpParser; | ||
|
||
std::string method; | ||
std::string url; | ||
Headers headers; | ||
std::string body; | ||
|
||
friend std::ostream& operator<<(std::ostream& os, const HttpRequest& resp); | ||
std::ostream& printHttpRequest(std::ostream& os) const; | ||
}; | ||
|
||
inline std::ostream& operator<<(std::ostream& os, const HttpRequest& resp) { | ||
return resp.printHttpRequest(os); | ||
} | ||
} |
Oops, something went wrong.