Compare commits

...

12 Commits

Author SHA1 Message Date
Peter Thorson 51a692ffcc Merge pull request #86 from blindmatrix/master
some makefile fixes
2012-03-14 04:44:24 -07:00
Sven Almgren 0195101f31 Use ldconfig for all OS other then Darwin 2012-03-14 11:33:40 +01:00
Sven Almgren 37d611e267 Changed how Make decides if lfconfig should be called 2012-03-14 04:57:08 +01:00
Sven Almgren 9d585b635e Allow building with -j 2012-03-14 04:21:54 +01:00
Sven Almgren 3770302154 Updated Makefile to allow specifying extra CXXFLAGS and LDFLAGS 2012-03-14 04:17:05 +01:00
Peter Thorson e5b87e66bc Merge pull request #45 from muhler/patch-1
Fixed some typos.
2011-11-24 08:15:52 -08:00
muhler 186ae090c6 Fixed some typos. 2011-11-23 00:28:47 +01:00
Peter Thorson ec28725873 ignore binaries 2011-11-05 18:55:09 -05:00
Peter Thorson 4f7470840e fixes #41 issues compiling on Ubuntu 2011-11-05 23:49:18 +00:00
Peter Thorson 6c6977e48f resolves issues differentiating between no close and 1005 close code. Updates server default logging settings 2011-10-30 08:06:50 -05:00
Peter Thorson 23501149e0 fixes client host header 2011-10-29 13:31:59 -05:00
Peter Thorson 511930ac89 adjusts close behavior 2011-10-29 13:31:48 -05:00
10 changed files with 142 additions and 70 deletions
+5 -1
View File
@@ -6,8 +6,10 @@
*.o
*.so
*.so.?.?.?
*.a
*.dylib
*.dylib.?.?.?
objs_shared/
objs_static/
@@ -16,9 +18,11 @@ examples/chat_server/chat_server
examples/echo_server/echo_server
examples/chat_client/chat_client
examples/echo_client/echo_client
test/basic/tests
libwebsocketpp.dylib.0.1.0
websocketpp.xcodeproj/xcuserdata/*
websocketpp.xcodeproj/project.xcworkspace/xcuserdata/*
policy_based_notes.hpp
examples/echo_server/echo_server_old
+17 -13
View File
@@ -63,8 +63,14 @@ srcdir ?= src
CXX ?= c++
AR ?= ar
PIC ?= PIC
BUILD_TYPE ?= "default"
SHARED ?= "1"
BUILD_TYPE ?= default
SHARED ?= 1
ifneq ($(OS),Darwin)
ldconfig = ldconfig
else
ldconfig =
endif
# Internal Variables
inst_path = $(exec_prefix)/$(libdir)
@@ -72,10 +78,10 @@ include_path = $(prefix)/$(includedir)
# BUILD_TYPE specific settings
ifeq ($(BUILD_TYPE), debug)
CXXFLAGS = $(cxxflags_debug)
CXXFLAGS := $(cxxflags_debug) $(CXXFLAGS_EXTRA)
libname := $(libname_debug)
else
CXXFLAGS ?= $(cxxflags_default)
CXXFLAGS := $(cxxflags_default) $(CXXFLAGS_EXTRA)
endif
# SHARED specific settings
@@ -99,7 +105,7 @@ endif
uninstall_headers
# Targets
all: $(lib_target)
all: banner $(lib_target)
@echo "============================================================"
@echo "Done"
@echo "============================================================"
@@ -118,9 +124,9 @@ $(lib_target): banner installdirs $(addprefix $(objdir)/, $(objects))
@echo "Link "
cd $(objdir) ; \
if test "$(OS)" = "Darwin" ; then \
$(CXX) -dynamiclib $(libs) -Wl,-dylib_install_name -Wl,$(libname_shared_major_version) -o $@ $(objects) ; \
$(CXX) -dynamiclib $(libs) $(LDFLAGS) -Wl,-dylib_install_name -Wl,$(libname_shared_major_version) -o $@ $(objects) ; \
else \
$(CXX) -shared $(libs) -Wl,-soname,$(libname_shared_major_version) -o $@ $(objects) ; \
$(CXX) -shared $(libs) $(LDFLAGS) -Wl,-soname,$(libname_shared_major_version) -o $@ $(objects) ; \
fi ; \
mv -f $@ ../
@echo "Link: Done"
@@ -134,13 +140,13 @@ $(lib_target): banner installdirs $(addprefix $(objdir)/, $(objects))
endif
# Compile object files
$(objdir)/sha1.o: $(srcdir)/sha1/sha1.cpp
$(objdir)/sha1.o: $(srcdir)/sha1/sha1.cpp installdirs
$(CXX) $< -o $@ $(CXXFLAGS)
$(objdir)/base64.o: $(srcdir)/base64/base64.cpp
$(objdir)/base64.o: $(srcdir)/base64/base64.cpp installdirs
$(CXX) $< -o $@ $(CXXFLAGS)
$(objdir)/%.o: $(srcdir)/%.cpp
$(objdir)/%.o: $(srcdir)/%.cpp installdirs
$(CXX) $< -o $@ $(CXXFLAGS)
ifeq ($(SHARED),1)
@@ -150,9 +156,7 @@ install: banner install_headers $(lib_target)
cd $(inst_path) ; \
ln -sf $(lib_target) $(libname_shared_major_version) ; \
ln -sf $(libname_shared_major_version) $(libname_shared)
ifneq ($(OS),Darwin)
ldconfig
endif
$(ldconfig)
@echo "Install shared library: Done."
else
install: banner install_headers $(lib_target)
Binary file not shown.
+95 -46
View File
@@ -1,55 +1,61 @@
How to use this library
WebSocket++ is a C++ websocket server library implimented using the Boost Asio networking stack. It is designed to provide a simple interface
WebSocket++ is a C++ websocket server library implemented using the Boost Asio networking stack. It is designed to provide a simple interface.
Built on Asio's proactor asyncronious event loop.
Built on Asio's proactor asynchronous event loop.
Building a program using WebSocket++ has two parts
1. Impliment a connection handler.
This is done by subclassing websocketpp::connection_handler. Each websocket connection is attached to a connection handler. The handler impliments the following methods:
1. Implement a connection handler.
This is done by subclassing websocketpp::connection_handler. Each websocket connection is attached to a connection handler.
The handler implements the following methods:
validate:
Called after the client handshake is recieved but before the connection is accepted. Allows cookie authentication, origin checking, subprotocol negotiation, etc
Called after the client handshake is received but before the connection is accepted. Allows cookie authentication, origin checking, subprotocol negotiation, etc.
connect:
Called when the connection has been established and writes are allowed.
disconnect:
Called when the connection has been disconnected
Called when the connection has been disconnected.
message: text and binary variants
Called when a new websocket message is recieved.
Called when a new websocket message is received.
The handler has access to the following websocket session api:
The handler has access to the following websocket session API:
get_header
returns the value of an HTTP header sent by the client during the handshake
returns the value of an HTTP header sent by the client during the handshake.
get_request
returns the resource requested by the client in the handshake
returns the resource requested by the client in the handshake.
set_handler:
pass responsibility for this connection to another connection handler
pass responsibility for this connection to another connection handler.
set_http_error:
reject the connection with a specific HTTP error
reject the connection with a specific HTTP error.
add_header
adds an HTTP header to the server handshake
adds an HTTP header to the server handshake.
set_subprotocol
selects a subprotocol for the connection
selects a subprotocol for the connection.
send: text and binary varients
send a websocket message
send: text and binary variants
send a websocket message.
ping:
send a ping
send a ping.
2. Start Asio's event loop with a TCP endpoint and your connection handler
There are two example programs in the examples directory that demonstrate this use pattern. One is a trivial stateless echo server, the other is a simple web based chat client. Both include example javascript clients. The echo server is suitable for use with automated testing suites such as the Autobahn test suite.
There are two example programs in the examples directory that demonstrate this use pattern.
One is a trivial stateless echo server, the other is a simple web based chat client.
Both include example javascript clients. The echo server is suitable for use with automated
testing suites such as the Autobahn test suite.
By default, a single connection handler object is used for all connections. If needs require, that default handler can either store per-connection state itself or create new handlers and pass off responsibility for the connection to them.
By default, a single connection handler object is used for all connections.
If needs require, that default handler can either store per-connection state itself
or create new handlers and pass off responsibility for the connection to them.
How to build this library
@@ -59,7 +65,7 @@ make
Build and install in system include directories
make install
Avaliable flags:
Available flags:
- SHARED=1: build a shared instead of static library.
- DEBUG=1: build library with no optimizations, suitable for debugging. Debug library
is called libwebsocketpp_dbg
@@ -89,9 +95,9 @@ To check
- double check bugs in autobahn (sending wrong localhost:9000 header) not
- checking masking in the 9.x tests
Unimplimented features
Unimplemented features
- SSL
- frame or streaming based api
- frame or streaming based API
- client features
- extension negotiation interface
@@ -117,19 +123,31 @@ websocketpp.hpp
create a websocketpp::server_ptr initialized to a new websocketpp::server object
the server constructor will need three things.
- A boost::asio::io_service object to use to manage its async operations
- A boost::asio::io_service object to manage its async operations
- A boost::asio::ip::tcp::endpoint to listen to for new connections
- An object that impliments the websocketpp::connection_handler interface to provide callback functions (See Handler API)
- An object that implements the websocketpp::connection_handler interface to provide callback functions (See Handler API)
After construction the server object will be in the initialization state. At this time you can set up server config options either via calling individual set option commands or by loading them in a batch from a config file.
After construction, the server object will be in the initialization state.
At this time you can set up server configuration options either via calling individual set option commands
or by loading them in a batch from a configuration file.
The only required option is that at least one host value must be set. Incoming websocket connections must specify a host value that they wish to connect to and if the server object does not have that host value in it's list of canonical hosts it will reject the connection.
The only required option is that at least one host value must be set.
Incoming websocket connections must specify a host value that they wish to connect to
and if the server object does not have that host value in it's list of canonical hosts it will reject the connection.
[note about settings that can be changed live?]
Once the server has been configured the way you want, call the start_accept() method. This will add the first async call to your io_service. If your io_service was already running, the server will start accepting connections immediately. If not you will need to call io_service.run() to start it.
Once the server has been configured the way you want, call the start_accept() method.
This will add the first async call to your io_service. If your io_service was already running,
the server will start accepting connections immediately. If not you will need to call io_service.run() to start it.
Once the server has started it will accept new connections. A new session object will be created for each connection accepted. The session will perform the websocket handshake and if it is successful begin reading frames. The session will continue reading frames until an error occurs or a connection close frame is seen. The session will notify the handler that it was initilized with (see Handler API) as necessary. The Session API defines how a handler (or other part of the end application) can interact with the session (to get information about the session, send messages back to the client, etc)
Once the server has started it will accept new connections.
A new session object will be created for each connection accepted.
The session will perform the websocket handshake and if it is successful begin reading frames.
The session will continue reading frames until an error occurs or a connection close frame is seen.
The session will notify the handler that it was initialized with (see Handler API) as necessary.
The Session API defines how a handler (or other part of the end application) can interact with the session
(to get information about the session, send messages back to the client, etc).
## Client API ##
include websocketpp.hpp
@@ -137,22 +155,30 @@ include websocketpp.hpp
create a websocketpp::client_ptr initialized to a new websocketpp::client object
the client constructor will need:
- A boost::asio::io_service object to use to manage its async operations
- An object that impliments the websocketpp::connection_handler interface to privde callback functions (See Handler API)
- A boost::asio::io_service object to manage its async operations
- An object that implements the websocketpp::connection_handler interface to provide callback functions (See Handler API)
After construction, the client object will be in the initialization state. At this time you can set up client config options either via calling individual set options commands or by loading them in a batch from a config file.
After construction, the client object will be in the initialization state.
At this time you can set up client configuration options either via calling individual set options commands
or by loading them in a batch from a configuration file.
Opening a new connection:
Per the websocket spec, a client can only have one connection in the connecting state at a time. Client method new_session() will create a new session and return a shared pointer to it. After this point new_session will throw an exception if you attempt to call it again before the most recently created session has either successfully connected or failed to connect. new_session()
Per the websocket spec, a client can only have one connection in the connecting state at a time.
Client method new_session() will create a new session and return a shared pointer to it.
After this point new_session will throw an exception if you attempt to call it again
before the most recently created session has either successfully connected or failed to connect.
new_session()
- call websocketpp::client::new_session(). This will return a session_ptr
## Handler API ##
The handler API defines the interface that a websocketpp session will use to communicate information about the session state and new messages to your application.
The handler API defines the interface that a websocketpp session will use to communicate information
about the session state and new messages to your application.
A client or server must be initialized with a default handler that will be used for all sessions. The default handler may pass a session off to another handler as necessary.
A client or server must be initialized with a default handler that will be used for all sessions.
The default handler may pass a session off to another handler as necessary.
A handler must impliment the following methods:
A handler must implement the following methods:
- validate(session_ptr)
- on_fail(session_ptr)
- on_open(session_ptr)
@@ -160,23 +186,43 @@ A handler must impliment the following methods:
- on_message(session_ptr,const std::vector<unsigned char> &)
- on_message(session_ptr,const std::string &)
validate will be called after a websocket handshake has been received and before it is accepted. It provides a handler the ability to refuse a connection based on application specific logic (ex: restrict domains or negotiate subprotocols). To reject the connection throw a handshake_error. Validate is never called for client sessions. To refuse a client session (ex: if you do not like the set of extensions/subprotocols the server chose) you can close the connection immediately in the on_open member function.
validate will be called after a websocket handshake has been received and before it is accepted.
It provides a handler with the ability to refuse a connection based on application specific logic
(ex: restrict domains or negotiate subprotocols). To reject the connection throw a handshake_error.
Validate is never called for client sessions.
To refuse a client session (ex: if you do not like the set of extensions/subprotocols the server chose)
you can close the connection immediately in the on_open member function.
on_fail is called whenever a session is terminated or failed before it was successfully established. This happens if there is an error during the handshake process or if the server refused the connection.
on_fail will be the last time a session calls its handler. If your application will need information from `session` after this function you should either save the session_ptr somewhere or copy the data out.
on_fail is called whenever a session is terminated or failed before it was successfully established.
This happens if there is an error during the handshake process or if the server refused the connection.
on_open is called after the websocket session has been successfully established and is in the OPEN state. The session is now avaliable to send messages and will begin reading frames and calling the on_message/on_close/on_error callbacks. A client may reject the connection by closing the session at this point.
on_fail will be the last time a session calls its handler.
If your application will need information from `session` after this function you should either
save the session_ptr somewhere or copy the data out.
on_close is called whenever an open session is closed for any reason. This can be due to either endpoint requesting a connection close or an error occuring. Information about why the session was closed can be extracted from the session itself.
on_close will be the last time a session calls its handler. If your application will need information from `session` after this function you should either save the session_ptr somewhere or copy the data out.
on_open is called after the websocket session has been successfully established and is in the OPEN state.
The session is now available to send messages and will begin reading frames
and calling the on_message/on_close/on_error callbacks.
A client may reject the connection by closing the session at this point.
on_message (binary version) will be called when a binary message is recieved. Message data is passed as a vector of bytes (unsigned char). data will not be avaliable after this callback ends so the handler must either completely process the message or copy it somewhere else for processing later.
on_close is called whenever an open session is closed for any reason.
This can be due to either endpoint requesting a connection close or an error occurring.
Information about why the session was closed can be extracted from the session itself.
on_close will be the last time a session calls its handler.
If your application will need information from `session` after this function you should either
save the session_ptr somewhere or copy the data out.
on_message (binary version) will be called when a binary message is received.
Message data is passed as a vector of bytes (unsigned char).
Data will not be available after this callback ends so the handler must either
completely process the message or copy it somewhere else for processing later.
TODO: Notes about thread safety
## Session API ##
The Session API allows a handler to look up information about a session as well as interact with that session (send messages, close the connection, etc)
The Session API allows a handler to look up information about a session
as well as interact with that session (send messages, close the connection, etc).
Session pointers are returned with every handler callback as well as every call to websocketpp::client::connect.
@@ -185,8 +231,11 @@ Handler Interface:
- set_handler(connection_handler_ptr)
Handshake Interface:
For the client these methods are valid after the server's handshake has been received. This is guaranteed to be the case by the time `on_open` is called.
For the server these methods are valid after the client's handshake has been received. This is guaranteed to be the case by the time `validate` is called.
For the client these methods are valid after the server's handshake has been received.
This is guaranteed to be the case by the time `on_open` is called.
For the server these methods are valid after the client's handshake has been received.
This is guaranteed to be the case by the time `validate` is called.
- const std::string& get_subprotocol() const;
- const std::string& get_resource() const;
@@ -204,7 +253,7 @@ Frame Interface
These methods are valid only for open connections. They will throw an exception if called from any other state.
WebSocket++ does not queue messages. As such only one send operation can be occuring at once.
WebSocket++ does not queue messages. As such only one send operation can be occurring at once.
TODO: failure behavior. OPTIONS:
- send will throw a `session_busy` exception if busy
- send will return true/false
+1 -1
View File
@@ -24,7 +24,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "websocketpp.hpp"
#include "websocket_client.hpp"
#include <boost/bind.hpp>
+5 -1
View File
@@ -282,7 +282,11 @@ void client_session::write_handshake() {
set_header("Connection","Upgrade");
set_header("Sec-WebSocket-Version","13");
set_header("Host",m_uri.host);
std::stringstream h;
h << m_uri.host << ":" << m_uri.port;
set_header("Host",h.str());
if (m_client_origin != "") {
set_header("Origin",m_client_origin);
+6 -1
View File
@@ -24,7 +24,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "websocketpp.hpp"
#include "websocket_frame.hpp"
#include "websocket_server.hpp"
@@ -297,6 +297,11 @@ uint16_t frame::get_close_status() const {
reinterpret_cast<uint16_t*>(&val[0])
));
// these two codes should never be on the wire
if (code == close::status::NO_STATUS || code == close::status::ABNORMAL_CLOSE) {
throw frame_error("Invalid close status code on the wire");
}
return code;
} else {
return close::status::PROTOCOL_ERROR;
+3 -2
View File
@@ -25,6 +25,7 @@
*
*/
#include "websocketpp.hpp"
#include "websocket_server.hpp"
#include <boost/bind.hpp>
@@ -39,8 +40,8 @@ using websocketpp::server;
server::server(boost::asio::io_service& io_service,
const tcp::endpoint& endpoint,
websocketpp::connection_handler_ptr defc)
: m_elog_level(LOG_ALL),
m_alog_level(ALOG_ALL),
: m_elog_level(LOG_ERROR),
m_alog_level(ALOG_CONTROL),
m_max_message_size(DEFAULT_MAX_MESSAGE_SIZE),
m_io_service(io_service),
m_acceptor(io_service, endpoint),
+9 -5
View File
@@ -559,11 +559,15 @@ void session::process_close() {
// send acknowledgement
// check if the remote close code
if (m_remote_close_code >= close::status::RSV_START) {
if (m_remote_close_code == close::status::NO_STATUS) {
send_close(close::status::NORMAL,"");
} else if (close::status::invalid(m_remote_close_code)) {
send_close(close::status::PROTOCOL_ERROR,"Invalid status code");
} else if (close::status::reserved(m_remote_close_code)) {
send_close(close::status::PROTOCOL_ERROR,"Reserved status code");
} else {
send_close(m_remote_close_code,m_remote_close_msg);
}
send_close(m_remote_close_code,m_remote_close_msg);
} else if (m_state == STATE_CLOSING) {
log("process_close got ack",LOG_DEBUG);
// this is an ack of our close message
@@ -692,7 +696,7 @@ void session::log_open_result() {
<< (get_client_header("User-Agent") == "" ? "NULL" : get_client_header("User-Agent"))
<< " " << m_resource << " " << m_server_http_code;
access_log(msg.str(),ALOG_HANDSHAKE);
access_log(msg.str(),ALOG_CONNECT);
}
// this is called when an async asio call encounters an error
+1
View File
@@ -30,6 +30,7 @@
#ifndef WEBSOCKETPP_HPP
#define WEBSOCKETPP_HPP
#define __STDC_LIMIT_MACROS
#include <stdint.h>
// Defaults