Permalink
Browse files

Merging PION-1186-mike streaming payload content patch from pion-core

  • Loading branch information...
1 parent 054e81c commit 09375d329d6f9dbafe7033640511b20f59b5820d @mikedickey mikedickey committed Jul 23, 2012
@@ -376,8 +376,14 @@ class PionPluginPtr :
/// destroys an instance of the plug-in object
inline void destroy(InterfaceClassType *object_ptr) {
- DestroyObjectFunction *destroy_func =
- (DestroyObjectFunction*)(getDestroyFunction());
+ // fix warning ISO C++ forbids casting from pointer-to-object
+ // to pointer to function
+ union {
+ void* v_;
+ DestroyObjectFunction* f_;
+ } Cast;
+ Cast.v_ = getDestroyFunction();
+ DestroyObjectFunction *destroy_func = Cast.f_;
if (destroy_func == NULL)
throw PluginUndefinedException();
destroy_func(object_ptr);
@@ -78,7 +78,7 @@ class PION_NET_API HTTPMessage
HTTPMessage(void)
: m_is_valid(false), m_is_chunked(false), m_chunks_supported(false),
m_do_not_send_content_length(false),
- m_version_major(1), m_version_minor(1), m_content_length(0),
+ m_version_major(1), m_version_minor(1), m_content_length(0), m_content_buf(),
m_status(STATUS_NONE), m_has_missing_packets(false), m_has_data_after_missing(false)
{}
@@ -93,17 +93,13 @@ class PION_NET_API HTTPMessage
m_version_major(http_msg.m_version_major),
m_version_minor(http_msg.m_version_minor),
m_content_length(http_msg.m_content_length),
+ m_content_buf(http_msg.m_content_buf),
m_chunk_cache(http_msg.m_chunk_cache),
m_headers(http_msg.m_headers),
m_status(http_msg.m_status),
m_has_missing_packets(http_msg.m_has_missing_packets),
m_has_data_after_missing(http_msg.m_has_data_after_missing)
- {
- if (http_msg.m_content_buf) {
- char *ptr = createContentBuffer();
- memcpy(ptr, http_msg.m_content_buf.get(), m_content_length);
- }
- }
+ {}
/// assignment operator
inline HTTPMessage& operator=(const HTTPMessage& http_msg) {
@@ -116,15 +112,12 @@ class PION_NET_API HTTPMessage
m_version_major = http_msg.m_version_major;
m_version_minor = http_msg.m_version_minor;
m_content_length = http_msg.m_content_length;
+ m_content_buf = http_msg.m_content_buf;
m_chunk_cache = http_msg.m_chunk_cache;
m_headers = http_msg.m_headers;
m_status = http_msg.m_status;
m_has_missing_packets = http_msg.m_has_missing_packets;
m_has_data_after_missing = http_msg.m_has_data_after_missing;
- if (http_msg.m_content_buf) {
- char *ptr = createContentBuffer();
- memcpy(ptr, http_msg.m_content_buf.get(), m_content_length);
- }
return *this;
}
@@ -139,7 +132,7 @@ class PION_NET_API HTTPMessage
m_remote_ip = boost::asio::ip::address_v4(0);
m_version_major = m_version_minor = 1;
m_content_length = 0;
- m_content_buf.reset();
+ m_content_buf.clear();
m_chunk_cache.clear();
m_headers.clear();
m_cookie_params.clear();
@@ -178,15 +171,21 @@ class PION_NET_API HTTPMessage
}
/// returns the length of the payload content (in bytes)
- inline std::size_t getContentLength(void) const { return m_content_length; }
+ inline boost::uint64_t getContentLength(void) const { return m_content_length; }
/// returns true if the message content is chunked
inline bool isChunked(void) const { return m_is_chunked; }
- /// returns a pointer to the payload content, or NULL if there is none
+ /// returns true if buffer for content is allocated
+ bool isContentBufferAllocated() const { return !m_content_buf.is_empty(); }
+
+ /// returns size of allocated buffer
+ inline std::size_t getContentBufferSize() const { return m_content_buf.size(); }
+
+ /// returns a pointer to the payload content, or empty string if there is none
inline char *getContent(void) { return m_content_buf.get(); }
- /// returns a const pointer to the payload content, or NULL if there is none
+ /// returns a const pointer to the payload content, or empty string if there is none
inline const char *getContent(void) const { return m_content_buf.get(); }
/// returns a reference to the chunk cache
@@ -282,7 +281,7 @@ class PION_NET_API HTTPMessage
}
/// sets the length of the payload content (in bytes)
- inline void setContentLength(const std::size_t n) { m_content_length = n; }
+ inline void setContentLength(const boost::uint64_t n) { m_content_length = n; }
/// if called, the content-length will not be sent in the HTTP headers
inline void setDoNotSendContentLength(void) { m_do_not_send_content_length = true; }
@@ -301,7 +300,7 @@ class PION_NET_API HTTPMessage
} else {
std::string trimmed_length(i->second);
boost::algorithm::trim(trimmed_length);
- m_content_length = boost::lexical_cast<std::size_t>(trimmed_length);
+ m_content_length = boost::lexical_cast<boost::uint64_t>(trimmed_length);
}
}
@@ -319,8 +318,7 @@ class PION_NET_API HTTPMessage
///creates a payload content buffer of size m_content_length and returns
/// a pointer to the new buffer (memory is managed by HTTPMessage class)
inline char *createContentBuffer(void) {
- m_content_buf.reset(new char[m_content_length + 1]);
- m_content_buf[m_content_length] = '\0';
+ m_content_buf.resize(m_content_length);
return m_content_buf.get();
}
@@ -441,6 +439,71 @@ class PION_NET_API HTTPMessage
protected:
+
+ /// a simple helper class used to manage a fixed-size payload content buffer
+ class ContentBuffer {
+ public:
+ /// simple destructor
+ ~ContentBuffer() {}
+
+ /// default constructor
+ ContentBuffer() : m_buf(), m_len(0), m_empty(0), m_ptr(&m_empty) {}
+
+ /// copy constructor
+ ContentBuffer(const ContentBuffer& buf)
+ : m_buf(), m_len(0), m_empty(0), m_ptr(&m_empty)
+ {
+ if (buf.size()) {
+ resize(buf.size());
+ memcpy(get(), buf.get(), buf.size());
+ }
+ }
+
+ /// assignment operator
+ ContentBuffer& operator=(const ContentBuffer& buf) {
+ if (buf.size()) {
+ resize(buf.size());
+ memcpy(get(), buf.get(), buf.size());
+ } else {
+ clear();
+ }
+ return *this;
+ }
+
+ /// returns true if buffer is empty
+ inline bool is_empty() const { return m_len == 0; }
+
+ /// returns size in bytes
+ inline std::size_t size() const { return m_len; }
+
+ /// returns const pointer to data
+ inline const char *get() const { return m_ptr; }
+
+ /// returns mutable pointer to data
+ inline char *get() { return m_ptr; }
+
+ /// changes the size of the content buffer
+ inline void resize(std::size_t len) {
+ m_len = len;
+ if (len == 0) {
+ m_buf.reset();
+ m_ptr = &m_empty;
+ } else {
+ m_buf.reset(new char[len+1]);
+ m_buf[len] = '\0';
+ m_ptr = m_buf.get();
+ }
+ }
+
+ /// clears the content buffer
+ inline void clear() { resize(0); }
+
+ private:
+ boost::scoped_array<char> m_buf;
+ std::size_t m_len;
+ char m_empty;
+ char *m_ptr;
+ };
/**
* prepares HTTP headers for a send operation
@@ -586,10 +649,10 @@ class PION_NET_API HTTPMessage
boost::uint16_t m_version_minor;
/// the length of the payload content (in bytes)
- std::size_t m_content_length;
+ boost::uint64_t m_content_length;
/// the payload content, if any was sent with the message
- boost::scoped_array<char> m_content_buf;
+ ContentBuffer m_content_buf;
/// buffers for holding chunked data
ChunkCache m_chunk_cache;
@@ -12,6 +12,7 @@
#include <string>
#include <boost/noncopyable.hpp>
+#include <boost/function/function2.hpp>
#include <boost/logic/tribool.hpp>
#include <boost/system/error_code.hpp>
#include <boost/thread/once.hpp>
@@ -39,6 +40,9 @@ class PION_NET_API HTTPParser :
/// maximum length for HTTP payload content
static const std::size_t DEFAULT_CONTENT_MAX;
+ /// callback type used to consume payload content
+ typedef boost::function2<void, const char *, std::size_t> PayloadHandler;
+
/// class-specific error code values
enum ErrorValue {
ERROR_METHOD_CHAR = 1,
@@ -266,6 +270,9 @@ class PION_NET_API HTTPParser :
/// returns true if the parser is being used to parse an HTTP response
inline bool isParsingResponse(void) const { return ! m_is_request; }
+ /// defines a callback function to be used for consuming payload content
+ inline void setPayloadHandler(PayloadHandler& h) { m_payload_handler = h; }
+
/// sets the maximum length for HTTP payload content
inline void setMaxContentLength(std::size_t n) { m_max_content_length = n; }
@@ -361,6 +368,9 @@ class PION_NET_API HTTPParser :
protected:
+ /// Called after we have finished parsing the HTTP message headers
+ virtual void finishedParsingHeaders(const boost::system::error_code& ec) {}
+
/**
* parses an HTTP message up to the end of the headers using bytes
* available in the read buffer
@@ -551,6 +561,9 @@ class PION_NET_API HTTPParser :
/// the current state of parsing chunked content
ChunkedContentParseState m_chunked_content_parse_state;
+
+ /// if defined, this function is used to consume payload content
+ PayloadHandler m_payload_handler;
/// Used for parsing the HTTP response status code
boost::uint16_t m_status_code;
@@ -55,7 +55,10 @@ class HTTPRequestReader :
return boost::shared_ptr<HTTPRequestReader>
(new HTTPRequestReader(tcp_conn, handler));
}
-
+
+ /// sets a function to be called after HTTP headers have been parsed
+ inline void setHeadersParsedCallback(FinishedHandler& h) { m_parsed_headers = h; }
+
protected:
@@ -81,6 +84,12 @@ class HTTPRequestReader :
boost::asio::placeholders::bytes_transferred));
}
+ /// Called after we have finished parsing the HTTP message headers
+ virtual void finishedParsingHeaders(const boost::system::error_code& ec) {
+ // call the finished headers handler with the HTTP message
+ if (m_parsed_headers) m_parsed_headers(m_http_msg, getTCPConnection(), ec);
+ }
+
/// Called after we have finished reading/parsing the HTTP message
virtual void finishedReading(const boost::system::error_code& ec) {
// call the finished handler with the finished HTTP message
@@ -95,6 +104,9 @@ class HTTPRequestReader :
/// function called after the HTTP message has been parsed
FinishedHandler m_finished;
+
+ /// function called after the HTTP message headers have been parsed
+ FinishedHandler m_parsed_headers;
};
@@ -58,6 +58,9 @@ class HTTPResponseReader :
(new HTTPResponseReader(tcp_conn, http_request, handler));
}
+ /// sets a function to be called after HTTP headers have been parsed
+ inline void setHeadersParsedCallback(FinishedHandler& h) { m_parsed_headers = h; }
+
protected:
@@ -85,6 +88,12 @@ class HTTPResponseReader :
boost::asio::placeholders::bytes_transferred));
}
+ /// Called after we have finished parsing the HTTP message headers
+ virtual void finishedParsingHeaders(const boost::system::error_code& ec) {
+ // call the finished headers handler with the HTTP message
+ if (m_parsed_headers) m_parsed_headers(m_http_msg, getTCPConnection(), ec);
+ }
+
/// Called after we have finished reading/parsing the HTTP message
virtual void finishedReading(const boost::system::error_code& ec) {
// call the finished handler with the finished HTTP message
@@ -100,6 +109,9 @@ class HTTPResponseReader :
/// function called after the HTTP message has been parsed
FinishedHandler m_finished;
+
+ /// function called after the HTTP message headers have been parsed
+ FinishedHandler m_parsed_headers;
};
Oops, something went wrong.

0 comments on commit 09375d3

Please sign in to comment.