Archived
1
Fork 0

Added json, and another protocol

This commit is contained in:
Joshua Moerman 2013-03-05 09:41:44 +01:00
parent 99a89ec22f
commit 78ac57f28e
7 changed files with 106 additions and 23 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "contrib/libwebsockets"] [submodule "contrib/libwebsockets"]
path = contrib/libwebsockets path = contrib/libwebsockets
url = git://github.com/warmcat/libwebsockets.git url = git://github.com/warmcat/libwebsockets.git
[submodule "contrib/json-spirit"]
path = contrib/json-spirit
url = git://github.com/sirikata/json-spirit.git

View file

@ -1,22 +1,30 @@
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
set(CMAKE_CSS_FLAGS "#{CMAKE_CSS_FLAGS} -Wdeprecated-declarations")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -g3") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -g3")
project(server) project(server)
# JSON lib
set(JSON_SPIRIT_BUILD_DEMOS OFF CACHE INTERNAL "" FORCE)
set(JSON_SPIRIT_BUILD_TESTS OFF CACHE INTERNAL "" FORCE)
set(JSON_SPIRIT_LIBRARY_TYPE "STATIC" CACHE INTERNAL "" FORCE)
add_subdirectory(${PROJECT_SOURCE_DIR}/contrib/json-spirit/build ${CMAKE_CURRENT_BINARY_DIR}/json-spirit)
include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/contrib/json-spirit/include/")
# websockets lib
set(WITHOUT_TESTAPPS ON CACHE INTERNAL "" FORCE)
add_subdirectory(${PROJECT_SOURCE_DIR}/contrib/libwebsockets/) add_subdirectory(${PROJECT_SOURCE_DIR}/contrib/libwebsockets/)
set(WITHOUT_TESTAPPS CACHE BOOL ON)
find_package(Boost 1.48 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
set(boost ${Boost_LIBRARIES})
include_directories("${PROJECT_SOURCE_DIR}")
include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/contrib/libwebsockets/") include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/contrib/libwebsockets/")
set(all_libraries ${boost} websockets) # Boost libs
find_package(Boost 1.48 REQUIRED COMPONENTS thread system)
include_directories(${Boost_INCLUDE_DIRS})
set(boost ${Boost_LIBRARIES})
set(all_libraries websockets json_spirit)
# Own files
include_directories("${PROJECT_SOURCE_DIR}")
file(GLOB all_files "*.cpp") file(GLOB all_files "*.cpp")
add_executable(server ${all_files}) add_executable(server ${all_files})

View file

@ -12,6 +12,7 @@
[ [
"-isystem/Users/joshua/Documents/Code/libcxx/include/", "-isystem/Users/joshua/Documents/Code/libcxx/include/",
"-isystem${folder:${project_path:beats-server.sublime-project}}/contrib/libwebsockets/", "-isystem${folder:${project_path:beats-server.sublime-project}}/contrib/libwebsockets/",
"-isystem${folder:${project_path:beats-server.sublime-project}}/contrib/json-spirit/include",
"-Wall", "-Wall",
"-std=c++11", "-std=c++11",
"-stdlib=libc++" "-stdlib=libc++"

1
contrib/json-spirit Submodule

@ -0,0 +1 @@
Subproject commit b585cf771ca10de706f96ddbd6d853dde72c6bbd

View file

@ -3,21 +3,56 @@
#include <string> #include <string>
#include <lib/libwebsockets.h> #include <lib/libwebsockets.h>
#include <json_spirit/json_spirit.h>
#include "websockets.h" #include "websockets.h"
int uid = 0; namespace js = json_spirit;
std::map<int, std::string> people_online;
// NOTE: we cannot use C++ ctors and dtors, because it will be allocated by libwebsockets (= C lib) js::Object get_object(std::string const & in){
js::Value value;
js::read(in, value);
return value.getObject();
}
int uid = 0;
struct User { struct User {
unsigned int index; unsigned int index{0};
std::string name{"Guest"};
int width{0};
int height{0};
static User from_json(const js::Object& obj){
User ret;
#define in(x, f) ret.x = obj.at(#x).f()
in(name, getString);
in(width, getInt);
in(height, getInt);
#undef in
return ret;
}
js::Object to_json() const {
js::Object obj;
#define out(x) obj[#x] = x
out(name);
out(width);
out(height);
#undef out
return obj;
}
}; };
// unfortunately libwebsockets own the user thingy
std::map<unsigned int, User*> people_online;
websockets::TestProtocol<User> default_protocol{ websockets::TestProtocol<User> default_protocol{
// connection established // connection established
[](User& user){ [](User& user){
user.name = "Unknown guest";
user.index = uid++; user.index = uid++;
people_online[user.index] = ""; people_online[user.index] = &user;
}, },
// connection closed // connection closed
[](User& user){ [](User& user){
@ -26,17 +61,47 @@ websockets::TestProtocol<User> default_protocol{
// write (will always come after receive) // write (will always come after receive)
[](User& user) -> std::string{ [](User& user) -> std::string{
std::string string_to_send = "Other People:"; std::string string_to_send = "Other People:";
for(auto x : people_online) if(x.first != user.index) string_to_send += " " + x.second; for(auto x : people_online) if(x.second != &user) string_to_send += " " + x.second->name;
return string_to_send; return string_to_send;
}, },
// receive // receive
[](User& user, std::string in){ [](User& user, std::string in){
people_online[user.index] = in; try{
user = User::from_json(get_object(in));
} catch(std::exception& e) {
throw websockets::runtime_error(e.what());
}
}
};
struct Empty{
int x;
};
websockets::TestProtocol<Empty> observer_protocol{
// connection established
[](Empty& user){},
// connection closed
[](Empty& user){},
// write (will always come after receive)
[](Empty& user) -> std::string{
js::Array array;
for(auto x : people_online){
array.push_back(x.second->to_json());
}
js::Value value(array);
std::cout << "OUTPUT JSON: " << write(value, js::remove_trailing_zeros) << std::endl;
return write(value);
},
// receive
[](Empty& user, std::string in){
std::cout << "INPUT: " << in << std::endl;
} }
}; };
static libwebsocket_protocols protocols[] = { static libwebsocket_protocols protocols[] = {
WSstandard_protocol("default", default_protocol), WSstandard_protocol("default", default_protocol),
WSstandard_protocol("observer", observer_protocol),
{ NULL, NULL, 0 } // end of list { NULL, NULL, 0 } // end of list
}; };

View file

@ -58,6 +58,7 @@ namespace websockets {
info.ssl_private_key_filepath = "libwebsockets-test-server.key.pem"; info.ssl_private_key_filepath = "libwebsockets-test-server.key.pem";
} }
{
websockets::Context context(info); websockets::Context context(info);
static bool force_exit = false; static bool force_exit = false;
@ -67,6 +68,7 @@ namespace websockets {
auto ret = libwebsocket_service(context.get_raw(), 10); auto ret = libwebsocket_service(context.get_raw(), 10);
if(ret < 0) break; if(ret < 0) break;
} }
}
log.notice("libwebsockets-test-echo exited cleanly\n"); log.notice("libwebsockets-test-echo exited cleanly\n");
return 0; return 0;

View file

@ -90,6 +90,7 @@ namespace websockets {
// 4-function Protocol, provide functions to handle establishment, closing, receiving and writing (follows receiving) // 4-function Protocol, provide functions to handle establishment, closing, receiving and writing (follows receiving)
// To let the callback return something non-zero (in case of error), use websockets::runtime_error // To let the callback return something non-zero (in case of error), use websockets::runtime_error
// Only types with no-arg ctor are allowed (uses placement new, because libwebsockets allocates for us)
template <typename T> template <typename T>
struct TestProtocol { struct TestProtocol {
typedef T user_type; typedef T user_type;
@ -111,9 +112,11 @@ namespace websockets {
try{ try{
switch (reason) { switch (reason) {
case LWS_CALLBACK_ESTABLISHED: case LWS_CALLBACK_ESTABLISHED:
new (user_ptr) user_type();
establish_func(user); establish_func(user);
break; break;
case LWS_CALLBACK_CLOSED: case LWS_CALLBACK_CLOSED:
user.~user_type();
close_func(user); close_func(user);
break; break;
case LWS_CALLBACK_SERVER_WRITEABLE:{ case LWS_CALLBACK_SERVER_WRITEABLE:{