Skip to content

Commit

Permalink
Added RequestStream
Browse files Browse the repository at this point in the history
  • Loading branch information
craigminihan committed Mar 3, 2015
1 parent 6c5e6d7 commit 988c9db
Show file tree
Hide file tree
Showing 17 changed files with 240 additions and 38 deletions.
3 changes: 3 additions & 0 deletions src/httpserver/main.cpp
Expand Up @@ -38,6 +38,9 @@ int main(int argc, char** argv) {

socket->Send(html.str());

// TODO: remove the close when we have a proper response object
socket->Close();

return true;
};

Expand Down
3 changes: 2 additions & 1 deletion src/libhttpserver/config.h
Expand Up @@ -10,7 +10,8 @@ class Config final : private boost::noncopyable {
public:
const static int MaxResponseCount = 100;

const static int ReceiveTimeoutPeriod = 30;
const static int HeaderReceiveTimeoutPeriod = 30;
const static int BodyReceiveTimeoutPeriod = 60;
const static int KeepAliveTimeout = 10;
const static int KeepAliveTimeoutGrace = 2;
const static int KeepAliveTimeoutTotal = KeepAliveTimeout + KeepAliveTimeoutGrace;
Expand Down
18 changes: 18 additions & 0 deletions src/libhttpserver/exceptions.h
Expand Up @@ -18,6 +18,15 @@ class InvalidBufferDataLengthException : public HttpServerException {
const char* what_ = "Invalid buffer data length specified";
};

class InvalidBufferPositionException : public HttpServerException {
public:
virtual const char* what() const noexcept override {
return what_;
}
private:
const char* what_ = "Invalid buffer position specified";
};

class HeaderTimeoutException : public HttpServerException {
public:
virtual const char* what() const noexcept override {
Expand Down Expand Up @@ -45,6 +54,15 @@ class HeaderMalformedException : public HttpServerException {
const char* what_ = "The request header was malformed";
};

class InvalidStreamOperationException : public HttpServerException {
public:
virtual const char* what() const noexcept override {
return what_;
}
private:
const char* what_ = "The stream operation was invalid";
};

}}

#endif /* RS_LIBHTTPSERVER_EXCEPTIONS_H */
Expand Down
32 changes: 31 additions & 1 deletion src/libhttpserver/header_buffer.cpp
@@ -1 +1,31 @@
#include "header_buffer.h"
#include <algorithm>

#include "header_buffer.h"
#include "socket.h"
#include "stream.h"

std::size_t rs::httpserver::HeaderBuffer::Receive(rs::httpserver::socket_ptr socket) {
auto bytes = socket->Receive(reinterpret_cast<rs::httpserver::Stream::byte*>(&data_[0]) + dataLength_, data_.size() - dataLength_);
if (bytes > 0) {
dataLength_ += bytes;
}

return bytes;
}

std::size_t rs::httpserver::HeaderBuffer::Receive(rs::httpserver::socket_ptr socket, int timeout) {
auto bytes = socket->Receive(timeout, reinterpret_cast<rs::httpserver::Stream::byte*>(&data_[0]) + dataLength_, data_.size() - dataLength_);
if (bytes > 0) {
dataLength_ += bytes;
}

return bytes;
}

int rs::httpserver::HeaderBuffer::Copy(value_type* buffer, int count) {
auto length = std::min(dataLength_ - position_, count);
auto start = cbegin() + position_;
std::copy(start, start + length, buffer);
position_ += length;
return length;
}
37 changes: 31 additions & 6 deletions src/libhttpserver/header_buffer.h
Expand Up @@ -13,7 +13,9 @@ namespace httpserver {

class HeaderBuffer final : private boost::noncopyable {
public:
HeaderBuffer(int size) : data_(size), dataLength_(0) {}
typedef char value_type;

HeaderBuffer(int size) : data_(size), dataLength_(0), position_(0) {}

int getLength() const {
return data_.size();
Expand All @@ -23,6 +25,10 @@ class HeaderBuffer final : private boost::noncopyable {
return dataLength_;
}

int getPosition() const {
return position_;
}

void setDataLength(int length) {
if (length >= data_.size()) {
throw InvalidBufferDataLengthException();
Expand All @@ -31,29 +37,48 @@ class HeaderBuffer final : private boost::noncopyable {
dataLength_ = length;
}

char* getData() {
void setPosition(int pos) {
if (pos > dataLength_) {
throw InvalidBufferPositionException();
}

position_ = pos;
}

value_type* getData() {
return &data_[0];
}

bool IsFull () {
bool IsFull() {
return dataLength_ == data_.size();
}

bool HasData() {
return position_ < dataLength_;
}

const char* const cbegin() const {
const value_type* const cbegin() const {
return &data_[0];
}

const char* const cend() const {
const value_type* const cend() const {
return cbegin() + dataLength_;
}

void Reset() {
dataLength_ = 0;
position_ = 0;
}

std::size_t Receive(rs::httpserver::socket_ptr socket);
std::size_t Receive(rs::httpserver::socket_ptr socket, int timeout);

int Copy(value_type* buffer, int count);

private:
std::vector<char> data_;
std::vector<value_type> data_;
int dataLength_;
int position_;
};

}}
Expand Down
12 changes: 6 additions & 6 deletions src/libhttpserver/httpserver.cpp
Expand Up @@ -65,28 +65,28 @@ void rs::httpserver::HttpServer::HandleAccept(socket_ptr socket, const boost::sy
}

void rs::httpserver::HttpServer::HandleRequest(socket_ptr socket) {
HeaderBuffer buffer(Config::MaxRequestHeaderSize);
HeaderBuffer headerBuffer(Config::MaxRequestHeaderSize);
auto responseCount = 0;

try {
while (socket->Connected() && responseCount < Config::MaxResponseCount) {
auto responseBytes = socket->Receive(Config::ReceiveTimeoutPeriod, buffer);
auto responseBytes = headerBuffer.Receive(socket, Config::HeaderReceiveTimeoutPeriod);
if (responseBytes <= 0) {
throw HeaderTimeoutException();
}

auto requestHeaders = RequestHeaders::Create(buffer);
auto requestHeaders = RequestHeaders::Create(headerBuffer);
if (!!requestHeaders) {
auto request = Request::Create(requestHeaders);
auto request = Request::Create(socket, requestHeaders, headerBuffer);
request_callback_(socket, request);

buffer.Reset();
headerBuffer.Reset();
++responseCount;

if (request->ShouldClose()) {
socket->Close();
}
} else if (buffer.IsFull()) {
} else if (headerBuffer.IsFull()) {
throw HeaderSizeException();
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/libhttpserver/nbproject/Makefile-Debug.mk
Expand Up @@ -40,6 +40,7 @@ OBJECTFILES= \
${OBJECTDIR}/query_string.o \
${OBJECTDIR}/request.o \
${OBJECTDIR}/request_headers.o \
${OBJECTDIR}/request_stream.o \
${OBJECTDIR}/socket.o


Expand Down Expand Up @@ -94,6 +95,11 @@ ${OBJECTDIR}/request_headers.o: request_headers.cpp
${RM} "$@.d"
$(COMPILE.cc) -g -std=c++11 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/request_headers.o request_headers.cpp

${OBJECTDIR}/request_stream.o: request_stream.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"
$(COMPILE.cc) -g -std=c++11 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/request_stream.o request_stream.cpp

${OBJECTDIR}/socket.o: socket.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"
Expand Down
6 changes: 6 additions & 0 deletions src/libhttpserver/nbproject/Makefile-Release.mk
Expand Up @@ -40,6 +40,7 @@ OBJECTFILES= \
${OBJECTDIR}/query_string.o \
${OBJECTDIR}/request.o \
${OBJECTDIR}/request_headers.o \
${OBJECTDIR}/request_stream.o \
${OBJECTDIR}/socket.o


Expand Down Expand Up @@ -94,6 +95,11 @@ ${OBJECTDIR}/request_headers.o: request_headers.cpp
${RM} "$@.d"
$(COMPILE.cc) -O2 -std=c++11 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/request_headers.o request_headers.cpp

${OBJECTDIR}/request_stream.o: request_stream.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"
$(COMPILE.cc) -O2 -std=c++11 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/request_stream.o request_stream.cpp

${OBJECTDIR}/socket.o: socket.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"
Expand Down
15 changes: 15 additions & 0 deletions src/libhttpserver/nbproject/configurations.xml
Expand Up @@ -12,7 +12,9 @@
<itemPath>query_string.h</itemPath>
<itemPath>request.h</itemPath>
<itemPath>request_headers.h</itemPath>
<itemPath>request_stream.h</itemPath>
<itemPath>socket.h</itemPath>
<itemPath>stream.h</itemPath>
<itemPath>types.h</itemPath>
</logicalFolder>
<logicalFolder name="ResourceFiles"
Expand All @@ -27,6 +29,7 @@
<itemPath>query_string.cpp</itemPath>
<itemPath>request.cpp</itemPath>
<itemPath>request_headers.cpp</itemPath>
<itemPath>request_stream.cpp</itemPath>
<itemPath>socket.cpp</itemPath>
</logicalFolder>
<logicalFolder name="TestFiles"
Expand Down Expand Up @@ -83,10 +86,16 @@
</item>
<item path="request_headers.h" ex="false" tool="3" flavor2="0">
</item>
<item path="request_stream.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="request_stream.h" ex="false" tool="3" flavor2="0">
</item>
<item path="socket.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="socket.h" ex="false" tool="3" flavor2="0">
</item>
<item path="stream.h" ex="false" tool="3" flavor2="0">
</item>
<item path="types.h" ex="false" tool="3" flavor2="0">
</item>
</conf>
Expand Down Expand Up @@ -140,10 +149,16 @@
</item>
<item path="request_headers.h" ex="false" tool="3" flavor2="0">
</item>
<item path="request_stream.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="request_stream.h" ex="false" tool="3" flavor2="0">
</item>
<item path="socket.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="socket.h" ex="false" tool="3" flavor2="0">
</item>
<item path="stream.h" ex="false" tool="3" flavor2="0">
</item>
<item path="types.h" ex="false" tool="3" flavor2="0">
</item>
</conf>
Expand Down
16 changes: 13 additions & 3 deletions src/libhttpserver/request.h
Expand Up @@ -9,14 +9,15 @@
#include "types.h"
#include "request_headers.h"
#include "query_string.h"
#include "request_stream.h"

namespace rs {
namespace httpserver {

class Request final : public boost::enable_shared_from_this<Request>, private boost::noncopyable {
public:
static request_ptr Create(request_headers_ptr request_headers) {
return request_ptr(new Request(request_headers));
static request_ptr Create(socket_ptr socket, request_headers_ptr request_headers, HeaderBuffer& headerBuffer) {
return request_ptr(new Request(socket, request_headers, headerBuffer));
}

request_headers_ptr getHeaders() {
Expand Down Expand Up @@ -66,11 +67,20 @@ class Request final : public boost::enable_shared_from_this<Request>, private bo
}
}

RequestStream& getRequestStream() {
return requestStream_;
}

private:
Request(request_headers_ptr request_headers) : request_headers_(request_headers), queryString_(request_headers->getQueryString()) {}
Request(socket_ptr socket, request_headers_ptr request_headers, HeaderBuffer& headerBuffer) :
socket_(socket), request_headers_(request_headers),
queryString_(request_headers->getQueryString()),
requestStream_(socket, headerBuffer) {}

const socket_ptr socket_;
const request_headers_ptr request_headers_;
const QueryString queryString_;
RequestStream requestStream_;

};

Expand Down
6 changes: 4 additions & 2 deletions src/libhttpserver/request_headers.cpp
Expand Up @@ -4,12 +4,14 @@ const char rs::httpserver::RequestHeaders::endOfLine_[4] = { '\r', '\n', '\r', '

const std::string rs::httpserver::RequestHeaders::emptyValue_;

rs::httpserver::request_headers_ptr rs::httpserver::RequestHeaders::Create(const HeaderBuffer& buffer) {
rs::httpserver::request_headers_ptr rs::httpserver::RequestHeaders::Create(HeaderBuffer& buffer) {
auto headersEnd = std::search(buffer.cbegin(), buffer.cend(), endOfLine_, endOfLine_ + sizeof(endOfLine_));

if (headersEnd != buffer.cend()) {
auto headers = request_headers_ptr(new RequestHeaders());
headers->GetHeaders(buffer, headersEnd - buffer.cbegin() + sizeof(endOfLine_));
auto headersLength = headersEnd - buffer.cbegin() + sizeof(endOfLine_);
headers->GetHeaders(buffer, headersLength);
buffer.setPosition(headersLength);
return headers;
} else {
return nullptr;
Expand Down
2 changes: 1 addition & 1 deletion src/libhttpserver/request_headers.h
Expand Up @@ -18,7 +18,7 @@ namespace httpserver {
class RequestHeaders final : public boost::enable_shared_from_this<RequestHeaders>, private boost::noncopyable {
public:

static request_headers_ptr Create(const HeaderBuffer& buffer);
static request_headers_ptr Create(HeaderBuffer& buffer);

const std::string& getMethod() {
return method_;
Expand Down
24 changes: 24 additions & 0 deletions src/libhttpserver/request_stream.cpp
@@ -0,0 +1,24 @@
#include "request_stream.h"
#include "config.h"

int rs::httpserver::RequestStream::Read(Stream::byte* buffer, int offset, int count, bool peek) {
auto bytes = 0;

if (headerBuffer_.HasData()) {
bytes += headerBuffer_.Copy(reinterpret_cast<HeaderBuffer::value_type*>(buffer + offset), count);
offset += bytes;
count -= bytes;
}

if (count > 0 && (bytes == 0 || socket_->Available())) {
auto socketBytes = socket_->Receive(Config::BodyReceiveTimeoutPeriod, buffer + offset, count, peek);
if (socketBytes > 0) {
bytes += socketBytes;
}
}

position_ += bytes;
length_ += bytes;

return bytes;
}

0 comments on commit 988c9db

Please sign in to comment.