Compare commits

...

16 Commits

Author SHA1 Message Date
Peter Thorson 9161119b4d bump version to alpha2 2013-06-09 17:24:24 -05:00
Peter Thorson 7db60e3429 fix poor server handling of double close frames fixes #259 2013-06-09 17:03:14 -05:00
Peter Thorson 3c0b8a81b0 Fix handling of spurious frames after close. Fixes #258 2013-06-09 16:41:04 -05:00
Peter Thorson b812fd001b Change default HTTP response error code to 426
Changes default HTTP response error code when no http_handler is
defined from 500/Internal Server Error to 426/Upgrade Required
2013-06-09 16:20:53 -05:00
Peter Thorson 3a43986d9e add documentation & normalize code style 2013-06-09 14:58:32 -05:00
Peter Thorson 64b1b52297 adds documentation on locations of version info 2013-06-09 11:07:19 -05:00
Peter Thorson dc048ed021 test use of doxygen todo command 2013-06-09 11:05:48 -05:00
Peter Thorson 60b167bcb7 updates changelog 2013-06-09 09:27:08 -05:00
Peter Thorson e680ca1ef4 add comment + TODO regarding VSPP warning 2013-06-09 09:25:30 -05:00
Peter Thorson 21d79e28c6 maybe fix markdown # escape? 2013-06-09 09:20:31 -05:00
Peter Thorson d25a254e81 remove logger dynamic allocation 2013-06-09 09:20:04 -05:00
Peter Thorson 3e144cfd75 Merge pull request #257 from zaphoyd/experimental
merge last bit of changes from experimental to master
2013-06-09 07:15:12 -07:00
Peter Thorson a5bb90807b Merge pull request #252 from breyed/visual-studio
Fixed Visual Studio 2012 warnings and formatting
2013-06-09 07:05:53 -07:00
Peter Thorson 096a7dbaa8 escape # in readme 2013-06-09 08:58:15 -05:00
Peter Thorson 577591aaa1 readme updates 2013-06-09 08:55:53 -05:00
breyed e68d492ed2 Fixed Visual Studio 2012 warnings
Fixed daylight savings time formatting problem on Windows
2013-06-08 11:07:02 -05:00
14 changed files with 212 additions and 55 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ PROJECT_NAME = "websocketpp"
# if some version control system is used.
PROJECT_NUMBER = "0.3.0-alpha1"
PROJECT_NUMBER = "0.3.0-alpha2"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
+14
View File
@@ -1,2 +1,16 @@
0.3.0-alpha2 - 2013-06-09
- Fixes a regression that caused servers being sent two close frames in a row
to end a connection uncleanly. #259
- Fixes a regression that caused spurious frames following a legitimate close
frames to erroneously trigger handlers. #258
- Changes default HTTP response error code when no http_handler is defined from
500/Internal Server Error to 426/Upgrade Required
- Removes timezone from logger timestamp to work around issues with the Windows
implimentation of strftime. Thank you breyed for testing and code. #257
- Switches integer literals to char literals to improve VCPP compatibility.
Thank you breyed for testing and code. #257
- Adds MSVCPP warning suppression for the bundled SHA1 library. Thank you breyed
for testing and code. #257
0.3.0-alpha1 - 2013-06-09
- Initial Release
+1 -1
View File
@@ -61,7 +61,7 @@ int main(int argc, char* argv[]) {
std::stringstream url;
url << uri << "/runCase?case=" << i << "&agent=WebSocket++/0.3.0-dev";
url << uri << "/runCase?case=" << i << "&agent=WebSocketpp/0.3.0-alpha2";
con = echo_client.get_connection(url.str(), ec);
+3 -2
View File
@@ -14,7 +14,8 @@ Major Features
* Supports secure WebSockets (TLS), IPv6, and explicit proxies.
* Flexible dependency management (C++11 Standard Library or Boost)
* Interchangeable network transport modules (iostream and Boost Asio)
* Portable, cross platform and architecture design
* Portable/cross platform (Posix/Windows, 32/64bit, Intel/ARM/PPC)
* Thread-safe
Get Involved
============
@@ -34,7 +35,7 @@ https://github.com/zaphoyd/websocketpp/
http://groups.google.com/group/websocketpp-announcements/
**IRC Channel**
#websocketpp (freenode)
#websocketpp (freenode)
**Discussion / Development / Support Mailing List / Forum**
http://groups.google.com/group/websocketpp/
+1 -1
View File
@@ -54,7 +54,7 @@ namespace lib {
using boost::bind;
using boost::ref;
namespace placeholders {
// TODO: there has got to be a better way than this
/// \todo this feels hacky, is there a better way?
using ::_1;
using ::_2;
}
+10 -7
View File
@@ -193,6 +193,7 @@ public:
, m_rng(rng)
, m_local_close_code(close::status::abnormal_close)
, m_remote_close_code(close::status::abnormal_close)
, m_was_clean(false)
{
m_alog.write(log::alevel::devel,"connection constructor");
}
@@ -399,7 +400,7 @@ public:
* and then added
*
* Errors are returned via an exception
* TODO: make exception system_error rather than error_code
* \todo make exception system_error rather than error_code
*
* This method invokes the m_write_lock mutex
*
@@ -871,7 +872,7 @@ public:
/// Checks if there are frames in the send queue and if there are sends one
/**
* TODO: unit tests
* \todo unit tests
*
* This method locks the m_write_lock mutex
*/
@@ -879,7 +880,7 @@ public:
/// Process the results of a frame write operation and start the next write
/**
* TODO: unit tests
* \todo unit tests
*
* This method locks the m_write_lock mutex
*
@@ -1011,7 +1012,7 @@ private:
*
* Must be called while holding m_write_lock
*
* TODO: unit tests
* \todo unit tests
*
* @param msg The message to push
*/
@@ -1024,7 +1025,7 @@ private:
*
* Must be called while holding m_write_lock
*
* TODO: unit tests
* \todo unit tests
*
* @return the message_ptr at the front of the queue
*/
@@ -1097,8 +1098,8 @@ private:
timer_ptr m_handshake_timer;
timer_ptr m_ping_timer;
// TODO: this is not memory efficient. this value is not used after the
// handshake.
/// \todo this is not memory efficient. this value is not used after the
/// handshake.
std::string m_handshake_buffer;
/// Pointer to the processor object for this connection
@@ -1172,6 +1173,8 @@ private:
/// Detailed internal error code
lib::error_code m_ec;
bool m_was_clean;
/// Whether or not this endpoint initiated the closing handshake.
bool m_closed_by_me;
+113 -29
View File
@@ -35,8 +35,16 @@ namespace websocketpp {
namespace http {
namespace parser {
inline bool parser::parse_parameter_list(const std::string& in,
parameter_list& out) const
/// Extract an HTTP parameter list from a string.
/**
* @param [in] in The input string.
*
* @param [out] out The parameter list to store extracted parameters in.
*
* @return Whether or not the input was a valid parameter list.
*/
inline bool parser::parse_parameter_list(std::string const & in,
parameter_list & out) const
{
if (in.size() == 0) {
return false;
@@ -47,33 +55,48 @@ inline bool parser::parse_parameter_list(const std::string& in,
return (it == in.begin());
}
inline bool parser::get_header_as_plist(const std::string& key,
parameter_list& out) const
/// Extract an HTTP parameter list from a parser header.
/**
* If the header requested doesn't exist or exists and is empty the parameter
* list is valid (but empty).
*
* @param [in] key The name/key of the HTTP header to use as input.
*
* @param [out] out The parameter list to store extracted parameters in.
*
* @return Whether or not the input was a valid parameter list.
*/
inline bool parser::get_header_as_plist(std::string const & key,
parameter_list & out) const
{
header_list::const_iterator it = m_headers.find(key);
// If this header doesn't exist it is valid
if (it == m_headers.end()) {
return false;
}
// If this header exists but is empty it is valid
if (it->second.size() == 0) {
if (it == m_headers.end() || it->second.size() == 0) {
return false;
}
return this->parse_parameter_list(it->second,out);
}
inline void parser::set_version(const std::string& version) {
// TODO: validation?
// first four chars == HTTP/
/// Set HTTP parser Version
/**
* \todo Does this method need any validation?
*
* @param [in] version The value to set the HTTP version to.
*/
inline void parser::set_version(std::string const & version) {
m_version = version;
}
inline const std::string& parser::get_header(const std::string& key) const {
/// Get the value of an HTTP header
/**
* \todo Make this method case insensitive.
*
* @param [in] key The name/key of the header to get.
*
* @return The value associated with the given HTTP header key.
*/
inline std::string const & parser::get_header(std::string const & key) const {
header_list::const_iterator h = m_headers.find(key);
if (h == m_headers.end()) {
@@ -82,15 +105,28 @@ inline const std::string& parser::get_header(const std::string& key) const {
return h->second;
}
}
inline void parser::append_header(const std::string &key,const std::string
&val)
/// Append a value to an existing HTTP header
/**
* This method will set the value of the HTTP header `key` with the indicated
* value. If a header with the name `key` already exists, `val` will be appended
* to the existing value.
*
* \todo Make this method case insensitive.
* \todo Should there be any restrictions on which keys are allowed to be set?
* \todo Exception free varient
*
* @param [in] key The name/key of the header to append to.
*
* @param [in] val The value to append.
*/
inline void parser::append_header(std::string const & key, std::string const &
val)
{
if (std::find_if(key.begin(),key.end(),is_not_token_char) != key.end()) {
throw exception("Invalid header name",status_code::bad_request);
}
// TODO: prevent use of reserved headers?
if (this->get_header(key) == "") {
m_headers[key] = val;
} else {
@@ -98,29 +134,63 @@ inline void parser::append_header(const std::string &key,const std::string
}
}
inline void parser::replace_header(const std::string &key,const std::string
&val)
/// Set a value for an HTTP header, replacing an existing value
/**
* This method will set the value of the HTTP header `key` with the indicated
* value. If a header with the name `key` already exists, `val` will replace the
* existing value.
*
* \todo Make this method case insensitive.
* \todo Should there be any restrictions on which keys are allowed to be set?
* \todo Exception free varient
*
* @param [in] key The name/key of the header to append to.
*
* @param [in] val The value to append.
*/
inline void parser::replace_header(std::string const & key, std::string const &
val)
{
m_headers[key] = val;
}
inline void parser::remove_header(const std::string &key) {
/// Remove a header from the parser
/**
* Removes the header entirely from the parser. This is different than setting
* the value of the header to blank.
*
* \todo Make this method case insensitive.
*
* @param [in] key The name/key of the header to remove.
*/
inline void parser::remove_header(std::string const & key) {
m_headers.erase(key);
}
inline void parser::set_body(const std::string& value) {
/// Set HTTP body
/**
* Sets the body of the HTTP object and fills in the appropriate content length
* header
*
* @param [in] value The value to set the body to.
*/
inline void parser::set_body(std::string const & value) {
if (value.size() == 0) {
remove_header("Content-Length");
m_body = "";
return;
}
std::stringstream foo;
foo << value.size();
replace_header("Content-Length", foo.str());
std::stringstream len;
len << value.size();
replace_header("Content-Length", len.str());
m_body = value;
}
/// Parse headers from an istream
/**
* @param [in] s The istream to extract headers from.
*/
inline bool parser::parse_headers(std::istream& s) {
std::string header;
std::string::size_type end;
@@ -143,6 +213,13 @@ inline bool parser::parse_headers(std::istream& s) {
return true;
}
/// Generate and return the HTTP headers as a string
/**
* Each headers will be followed by the \r\n sequence including the last one.
* A second \r\n sequence (blank header) is not appended by this method
*
* @return The HTTP headers as a string.
*/
inline std::string parser::raw_headers() const {
std::stringstream raw;
@@ -154,6 +231,13 @@ inline std::string parser::raw_headers() const {
return raw.str();
}
/// Process a header
/**
*
* \todo Update this method to be exception free.
*
* @param [in] s The istream to extract headers from.
*/
inline void parser::process_header(std::string::iterator begin,
std::string::iterator end)
{
+8 -1
View File
@@ -148,7 +148,14 @@ inline void request::set_method(const std::string& method) {
m_method = method;
}
/// Set HTTP body
/**
* Sets the body of the HTTP object and fills in the appropriate content length
* header
*
* @param value The value to set the body to.
*/
inline void request::set_uri(const std::string& uri) {
// TODO: validation?
m_uri = uri;
+23 -3
View File
@@ -896,7 +896,10 @@ void connection<config>::handle_read_frame(const lib::error_code& ec,
"null message from m_processor");
} else if (!is_control(msg->get_opcode())) {
// data message, dispatch to user
if (m_message_handler) {
if (m_state != session::state::open) {
m_elog.write(log::elevel::warn,
"got non-close data frame in state closing");
} else if (m_message_handler) {
m_message_handler(m_connection_hdl, msg);
}
} else {
@@ -989,6 +992,8 @@ bool connection<config>::process_handshake_request() {
if (m_http_handler) {
m_http_handler(m_connection_hdl);
} else {
set_status(http::status_code::upgrade_required);
}
return true;
@@ -1635,7 +1640,16 @@ void connection<config>::process_control_frame(typename
std::stringstream s;
s << "Control frame received with opcode " << op;
m_alog.write(log::alevel::control,s.str());
if (m_state == session::state::closed) {
m_elog.write(log::elevel::warn,"got frame in state closed");
return;
}
if (op != frame::opcode::CLOSE && m_state != session::state::open) {
m_elog.write(log::elevel::warn,"got non-close frame in state closing");
return;
}
if (op == frame::opcode::PING) {
bool pong = true;
@@ -1710,10 +1724,12 @@ void connection<config>::process_control_frame(typename
m_elog.write(log::elevel::devel,
"send_close_ack error: "+ec.message());
}
} else if (m_state == session::state::closing) {
} else if (m_state == session::state::closing && !m_was_clean) {
// ack of our close
m_alog.write(log::alevel::devel,"Got acknowledgement of close");
m_was_clean = true;
// If we are a server terminate the connection now. Clients should
// leave the connection open to give the server an opportunity to
// initiate the TCP close. The client's timer will handle closing
@@ -1801,6 +1817,10 @@ lib::error_code connection<config>::send_close_frame(close::status::value code,
m_state = session::state::closing;
if (ack) {
m_was_clean = true;
}
// Start a timer so we don't wait forever for the acknowledgement close
// frame
m_handshake_timer = transport_con_type::set_timer(
+11 -5
View File
@@ -111,15 +111,21 @@ private:
typedef typename concurrency::scoped_lock_type scoped_lock_type;
typedef typename concurrency::mutex_type mutex_type;
const char* get_timestamp() {
// The timestamp does not include the time zone, because on Windows with the
// default registry settings, the time zone would be written out in full,
// which would be obnoxiously verbose.
//
// TODO: find a workaround for this or make this format user settable
char const * get_timestamp() {
std::time_t t = std::time(NULL);
std::strftime(buffer,39,"%Y-%m-%d %H:%M:%S%z",std::localtime(&t));
return buffer;
std::strftime(m_buffer,sizeof(m_buffer),"%Y-%m-%d %H:%M:%S",
std::localtime(&t));
return m_buffer;
}
mutex_type m_lock;
char buffer[40];
char m_buffer[20];
const level m_static_channels;
level m_dynamic_channels;
std::ostream* m_out;
+2 -2
View File
@@ -338,8 +338,8 @@ public:
}
std::string val;
val.append(1,0xff);
val.append(1,0x00);
val.append(1,'\xff');
val.append(1,'\x00');
out->set_payload(val);
out->set_prepared(true);
+2 -1
View File
@@ -837,6 +837,8 @@ protected:
/**
* Validates an incoming hybi13 full header.
*
* \todo unit test for the >32 bit frames on 32 bit systems case
*
* @param h The basic header to validate
*
* @param e The extended header to validate
@@ -864,7 +866,6 @@ protected:
}
// Check for >32bit frames on 32 bit systems
// TODO: unit test for this case
if (sizeof(size_t) == 4 && (payload_size >> 32)) {
return make_error_code(error::requires_64bit);
}
+12
View File
@@ -102,7 +102,19 @@ class SHA1
while(length-- && !Corrupted)
{
// Suppresses Visual Studio code analysis for write overrun. It doesn't know the
// index into Message_Block is protected by checking length.
//
// TODO: is there a more compatible way to write the original code to avoid
// this sort of warning?
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(suppress: 6386)
#endif
Message_Block[Message_Block_Index++] = (*message_array & 0xFF);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
Length_Low += 8;
Length_Low &= 0xFFFFFFFF; // Force it to 32 bits
+11 -2
View File
@@ -30,12 +30,21 @@
namespace websocketpp {
/*
other places where version information is kept
- echo_client
- readme.md
- changelog.md
- Doxyfile
- CMakeLists.txt
*/
static int const major_version = 0;
static int const minor_version = 3;
static int const patch_version = 0;
static char const prerelease_flag[] = "alpha1";
static char const prerelease_flag[] = "alpha2";
static char const user_agent[] = "WebSocket++/0.3.0-alpha1";
static char const user_agent[] = "WebSocket++/0.3.0-alpha2";
} // namespace websocketpp