zaphoyd / websocketpp Goto Github PK
View Code? Open in Web Editor NEWC++ websocket client/server library
Home Page: http://www.zaphoyd.com/websocketpp
License: Other
C++ websocket client/server library
Home Page: http://www.zaphoyd.com/websocketpp
License: Other
Add an API to the connection handler to allow local applications to receive message data as it arrives rather than waiting until the entire fragment has been buffered.
I was using Boost 1.47 compiled from source.
Now library build without issue on both, shared and static. But is a problem compiling examples, same problem on four examples.
root@xubuntu:/DEVELOP/websocketpp/examples/chat_client# make
g++ -c -O2 -o chat_client.o chat_client.cpp
g++ -c -O2 -o chat_client_handler.o chat_client_handler.cpp
g++ -O2 chat_client.o chat_client_handler.o -o chat_client -lboost_system -lboost_thread -lboost_date_time -lboost_regex -lboost_random ../../libwebsocketpp.a
../../libwebsocketpp.a(websocket_session.o): In function websocketpp::session::session(boost::asio::io_service&, boost::shared_ptrwebsocketpp::connection_handler, unsigned long long)':
websocket_session.cpp:(.text+0x2345): undefined reference toboost::random::random_device::random_device()'
websocket_session.cpp:(.text+0x23a0): undefined reference to boost::random::random_device::random_device()'
websocket_session.cpp:(.text+0x24c9): undefined reference toboost::random::random_device::~random_device()'
websocket_session.cpp:(.text+0x24e5): undefined reference to boost::random::random_device::~random_device()'
websocket_session.cpp:(.text+0x25c7): undefined reference toboost::random::random_device::~random_device()'
.
.
.
Thanks!
Prerequisite for most of the other features in this milestone
has changed to Origin in protocol 13
Per section 4.4 the server should return a list of version headers in the response if the handshake fails due to the client's advertised version being unsupported.
utf8 validation is not being done.
Chat server example doesn't work with the new API
There is a couple of places where the async_write method is called using a local string variable as the buffer parameter. The places are
void client::connection<connection_type>::write_request() {
.....
boost::asio::async_write(
m_connection.get_socket(),
boost::asio::buffer(raw),
.....
and
void server::connection<connection_type>::write_response() {
.....
boost::asio::async_write(
m_connection.get_socket(),
boost::asio::buffer(raw),
I fixed the issue by using a reference counted buffer from an asio example. The class code is
class shared_const_buffer {
public:
explicit shared_const_buffer(const std::string &data) : m_data(new std::vector<char>(data.begin(), data.end())),
m_buffer(boost::asio::buffer(*m_data)) {}
public:
typedef boost::asio::const_buffer value_type;
typedef const boost::asio::const_buffer *const_iterator;
const boost::asio::const_buffer *begin() const { return &m_buffer; }
const boost::asio::const_buffer *end() const { return &m_buffer + 1; }
private:
boost::shared_ptr< std::vector<char> > m_data;
boost::asio::const_buffer m_buffer;
};
and replacing "boost::asio::buffer(" by "shared_const_buffer"
Plus a mistyping:
diff --git a/src/roles/server.hpp b/src/roles/server.hpp
throw http::exception("Recieved invalid HTTP Request",http::status_code::BAD_REQUEST);
throw http::exception("Received invalid HTTP Request",http::status_code::BAD_REQUEST);
When client disconnects, chat server doesn't remove session_ptr
from m_connections
(chat.cpp, line #79):
send_to_all(encode_message("server",m_connections[client]+" has left the chat."));
this makes server crazy, after sending messages from other clients.
The following logic should fix this:
std::cout << "client " << client << " left the lobby." << std::endl;
const std::string alias = it->second;
m_connections.erase(it);
// send user list and signoff message to all clients
send_to_all(serialize_state());
send_to_all(encode_message("server", alias+" has left the chat."));
file: client.hpp
method: client::connect(const std::string& u)
line: connection_ptr con = m_endpoint.create_connection();
issue description: the con variable can be equal to NULL if the endpoint is in either the stopping or stopped state.
fix:
connection_ptr con = m_endpoint.create_connection();
- con->set_uri(location);
-
- boost::asio::async_connect(
- con->get_raw_socket(),
- iterator,
- boost::bind(
- &endpoint_type::handle_connect,
- this, // shared from this?
- con,
- boost::asio::placeholders::error
- )
- );
- m_state = CONNECTING;
+ if (con != NULL) {
+ con->set_uri(location);
+
+ boost::asio::async_connect(
+ con->get_raw_socket(),
+ iterator,
+ boost::bind(
+ &endpoint_type::handle_connect,
+ this, // shared from this?
+ con,
+ boost::asio::placeholders::error
+ )
+ );
+ m_state = CONNECTING;
+ }
return con;
Add an API to the connection handler to allow local applications to receive fragmented messages in fragments as they arrive rather than waiting until the entire message has been buffered.
see section 7.1.1
All issues bellow are in the endpoint.hpp file.
for (it = m_connections.begin(); it != m_connections.end(); it++) {
(*it)->close(code,reason);
}
while(!m_connections.empty()) { // using for is not correct because the close method calls the remove_connection, which removes connection from m_connections
(*m_connections.begin())->close(code,reason);
}
Ambiguous access of 'm_io_service'. Can be either the endpoint_base or the role or the socket classes. Fix is
explicit endpoint(handler_ptr handler)
: role_type(m_io_service),
socket_type(m_io_service),
: role_type(endpoint_base::m_io_service),
socket_type(endpoint_base::m_io_service),
m_state(IDLE),
The same as previous issue but in different place
<< "Endpoint is stopping immediately" << log::endl;
m_io_service.stop();
endpoint_base::m_io_service.stop();
m_state = STOPPED;
Under Windows the following lines either can't be compiled or do not define correct friend class declarations and as result the "can't access to protected method" error
friend class role< endpoint<role,socket> >;
friend class socket< endpoint<role,socket> >;
friend class connection<type,role< type >::template connection,socket< type >::template connection>;
Quick but not 100% correct fix is to use #if defined(WIN32) ... #else ... #endif with the following lines which are commented in the header file
friend role_type;
friend socket_type;
friend connection_type;
<< "Endpoint recieved signal to close all connections cleanly with code "
<< "Endpoint received signal to close all connections cleanly with code "
max messages sizes (see section 10.4)
time waiting for a handshake after connecting
number of connections per endpoint (see section 4.1 part 3)
I have flagged exit points with TODO: close behavior. These need to be simplified and I need to make sure that all paths result in compliant close behavior.
Add an API to the connection handler to allow local applications to send messages in fragments as data becomes available rather than waiting until the entire message has been buffered.
note this depends on the field type. Sec-WebSocket-Version requests must be singled valued, error responses may be multi-valued (Sec 11.3). subprotocol may be multivalued, also extensions
Found a few small issues in the source code.
is required by the spec
see section 10.6
like the project, my other code style guide requires 4 spaces so kinda clashy, just a request! :)
Thanks for your hard work.
file: uri.cpp
method: the uri class constructor
problem description: if multiple clients call the endpoint's connect method in parallel, then all of them try to instance the static boost::regex expression. The result is an assert and crash somewhere inside of the boost::regex class.
fix:
- static const boost::regex expression("(ws|wss)://([^/:\[]+|[[0-9a-fA-F:.]+])(:\d{1,5})?(/[^#]*)?");
const boost::regex expression("(ws|wss)://([^/:\[]+|[[0-9a-fA-F:.]+])(:\d{1,5})?(/[^#]*)?");
diff --git a/src/rng/boost_rng.cpp b/src/rng/boost_rng.cpp
diff --git a/src/processors/hybi_header.cpp b/src/processors/hybi_header.cpp
-void hybi_header::set_opcode(frame::opcode::value op) {
+void hybi_header::set_opcode(websocketpp::frame::opcode::value op) {
diff --git a/src/processors/hybi_header.hpp b/src/processors/hybi_header.hpp
diff --git a/src/messages/data.cpp b/src/messages/data.cpp
m_payload.reserve(std::max(new_size,static_cast<uint64_t>(2*m_payload.capacity())));
m_payload.reserve(std::max<uint64_t>(new_size, static_cast<uint64_t>(2*m_payload.capacity())));
-void data::reset(frame::opcode::value opcode) {
+void data::reset(websocketpp::frame::opcode::value opcode) {
diff --git a/src/messages/data.hpp b/src/messages/data.hpp
At minimum, catch SIGINT and close all connections/write logs cleanly. Consider how this might work on non-unix systems?
per section 4.1 part 2
See section 7.2.3
Right now this is all up to the end application. Should any of this be supported by the library?
file: data.hpp
issue description: There is a memory leak in the pool class due to a cyclic dependency between the pool and the data classes.
fix:
diff --git a/src/messages/data.hpp b/src/messages/data.hpp
--- a/src/messages/data.hpp
+++ b/src/messages/data.hpp
@@ -61,6 +61,7 @@ template
public:
typedef pool<element_type> type;
typedef boost::shared_ptr ptr;
-
typedef boost::weak_ptr<type> ptr_weak;
typedef typename element_type::ptr element_ptr;
typedef boost::function<void()> callback_type;
@@ -149,6 +150,7 @@ class data {
public:
typedef boost::intrusive_ptr ptr;
typedef pool::ptr pool_ptr;
-
typedef pool<data>::ptr_weak pool_weak_ptr;
data(pool_ptr p, size_t s);
@@ -210,7 +212,10 @@ private:
if (count == 1 && s->m_live) {
// recycle if endpoint exists
s->m_live = false;
-
s->m_pool->recycle(ptr(const_cast<data *>(s)));
-
pool_ptr pp = s->m_pool.lock();
-
if (pp != NULL) {
-
pp->recycle(ptr(const_cast<data *>(s)));
-
}
} else if (count == 0) {
boost::checked_delete(static_cast<data const *>(s));
}
@@ -235,7 +240,7 @@ private:
// reference counting
size_t m_index;
mutable boost::detail::atomic_count m_ref_count;
- mutable pool_ptr m_pool;
mutable pool_weak_ptr m_pool;
mutable bool m_live;
};
closing handshake error codes
Closing handshakes do not include error codes
Basic chat client example
Allow HTTP versions greater than 1.1
Handshake acceptance code is currently hard coded to accept only HTTP/1.1
Policy Refactor: Correct fix of the issue's #50 endpoint::close_all problem
In the issue #50 the 1st problem was linked with the endpoint::close_all method. And the fix is not correct due to the fact that the remove_connection method is not called on every close method and result is a never-ending loop. Here is a new fix:
- while(!m_connections.empty()) {
-
(*m_connections.begin())->close(code,reason);
-
}
-
for (std::set<connection_ptr>::iterator it_con = m_connections.begin(); it_con != m_connections.end();) {
-
const connection_ptr con = *it_con++;
-
con->close(code,reason);
}
The logic is that initially the existent iterator is incremented and after may be called the m_connections.erase() method. Before the issue #50 the for circle incremented the iterator after the m_connections.erase() call.
Strict UTF-8 validation fast fail
Presently UTF8 validation is done on a per frame basis. A frame is read and then checked. True fast UTF8 fail would fail as soon as the first bad byte was read. Doing this would require a different setup for reading from ASIO so it will be low priority for now. THis might need to be done in the future anyways, in particular if a streaming api is ever needed.
client non-101 response behavior
HTTP basic auth on 401, redirects on 3xx, etc
see section 4.1, 10.5
Frames read in with handshake are lost
During the switch from read until CRLF to frame lengths frames or partial frames can discarded if they were sent in the same TCP packet as the handshake.
Reject masked frames from client
per section 5.1
Error compiling on Ubuntu natty and oneiric
Hello!!
Trying to compile on natty and oneiric. gcc -4.5.2 and gcc-4.6.1
.
.
src/websocket_frame.hpp: In constructor ‘websocketpp::frame::frame()’:
src/websocket_frame.hpp:99:54: error: ‘INT32_MIN’ was not declared in this scope
src/websocket_frame.hpp:99:64: error: ‘INT32_MAX’ was not declared in this scope
.
Behavior of send while another send is in progress
This needs to be defined and enforced. Either send should queue (if this is the case the queue should be short) or send should fail. With a fixed size queue send will fail at some point anyways.
message length encoding validation
Per Section 5.2: Note that in all case the minimal number of bytes MUST be used to encode the length, for example the length of a 124 byte long string can't be encoded as the sequence 126, 0, 124.
WebSocket++ always sends compliant values, it does not validate that received values are compliant
ideal set_max_message_size error behavior?
Options:
- Throw exception
- Log error and set value to maximum allowed
- Log error and leave value at whatever it was before
A few memory leaks
There are the following memory leaks:
- class client contains a shared pointer to a client session object (m_client_session), which is instanced in the client::init method. Also the client_session class contains a shared pointer to the parent session m_client. Instancing the client class object as its shared pointer reference counter equals to 1, after calling its init method the reference counter equals to 2, due to the reference in the session object. By deleting the client object reference becomes to 1 and the client object is never deleted.
To resolve this cyclic dependency is necessary to use the boost::weak_ptr class instead of boost::shared_ptr for the client_session::m_client member.
- A similar cyclic dependency between the server and server_session classes. The server_session::m_server member type changing to boost::weak_ptr is required to fix it.
- If a server is stopped by calling of the stop method of the parent boost::asio::io_service instance and the server has connected clients, when active connections which are stored in connection_handler inherited class (the example chat_server_handler class) are not deleted. A fast but not universal solution to fix this issue is to mandatory clear the connections list (chat_server_handler::m_connections) after call of io_service.run.
Send error in chat_server example
As you say for Frame Interface:
WebSocket++ does not queue messages. As such only one send operation can be occuring at once.
So errors in all chat_server_handler functions:
- on_open(session_ptr)
- on_close(session_ptr)
- on_message(session_ptr,const std::string &)
More one send operation in session.
I tried to run under Windows XP debug version of client/server chat which builded with Misrosoft Visual Studio 2008 with boost 1.47.0.
And after getting in client:
[server] Welcome, use the /alias command to set a name, /help for a list of other commands.
[server] 127.0.0.1:1279 has joined the chat.
I get debug exception 'vector iterator not dereferencable' in BOOST_ASIO_ENABLE_BUFFER_DEBUGGING check in win_iocp_operation::complete(win_iocp_io_service& owner,
const boost::system::error_code& ec = boost::system::error_code(),
std::size_t bytes_transferred = 0)
in chatserver.exe.
Maybe to add in WebSocket++ queue messages?
Recommend Projects
-
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
-
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
-