Skip to content

Commit

Permalink
feat: add support for Socket.IO v3
Browse files Browse the repository at this point in the history
  • Loading branch information
darrachequesne committed Jan 9, 2021
1 parent b1216ee commit ec4d540
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 57 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,24 @@ By virtue of being written in C++, this client works in several different platfo

[![Clients with iPhone, QT, Console and web](https://cldup.com/ukvVVZmvYV.png)](https://github.com/socketio/socket.io-client-cpp/tree/master/examples)

## Compatibility table

| C++ Client version | Socket.IO server version |
| ------------------- | ------------------------ |
| 2.x (`2.x` branch) | 1.x / 2.x |
| 3.x (master branch) | 3.x |

## Features

- 100% written in modern C++11
- Compatible with socket.io 1.0+ protocol
- Binary support
- Automatic JSON encoding
- Multiplex support
- Similar API to the Socket.IO JS client
- Cross platform

Note: Only the WebSocket transport is currently implemented (no fallback to HTTP long-polling)

## Installation alternatives

* [With CMAKE](./INSTALL.md#with-cmake)
Expand Down
31 changes: 10 additions & 21 deletions src/internal/sio_client_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ namespace sio
} else {
ss<<uo.get_host();
}
ss<<":"<<uo.get_port()<<"/socket.io/?EIO=3&transport=websocket";
ss<<":"<<uo.get_port()<<"/socket.io/?EIO=4&transport=websocket";
if(m_sid.size()>0){
ss<<"&sid="<<m_sid;
}
Expand Down Expand Up @@ -295,12 +295,6 @@ namespace sio
lib::error_code ec;
this->m_client.send(this->m_con, *payload, frame::opcode::text, ec);
});
if(m_ping_timer)
{
asio::error_code e_code;
m_ping_timer->expires_from_now(milliseconds(m_ping_interval), e_code);
m_ping_timer->async_wait(std::bind(&client_impl::ping,this, std::placeholders::_1));
}
if(!m_ping_timeout_timer)
{
m_ping_timeout_timer.reset(new asio::steady_timer(m_client.get_io_service()));
Expand Down Expand Up @@ -497,21 +491,21 @@ namespace sio
m_ping_timeout = 60000;
}

m_ping_timer.reset(new asio::steady_timer(m_client.get_io_service()));
asio::error_code ec;
m_ping_timer->expires_from_now(milliseconds(m_ping_interval), ec);
if(ec)LOG("ec:"<<ec.message()<<endl){};
m_ping_timer->async_wait(std::bind(&client_impl::ping,this, std::placeholders::_1));
LOG("On handshake,sid:"<<m_sid<<",ping interval:"<<m_ping_interval<<",ping timeout"<<m_ping_timeout<<endl);
return;
}
failed:
//just close it.
m_client.get_io_service().dispatch(std::bind(&client_impl::close_impl, this,close::status::policy_violation,"Handshake error"));
}

void client_impl::on_pong()
void client_impl::on_ping()
{
packet p(packet::frame_pong);
m_packet_mgr.encode(p, [&](bool /*isBin*/,shared_ptr<const string> payload)
{
this->m_client.send(this->m_con, *payload, frame::opcode::text);
});

if(m_ping_timeout_timer)
{
m_ping_timeout_timer->cancel();
Expand All @@ -536,8 +530,8 @@ namespace sio
//FIXME how to deal?
this->close_impl(close::status::abnormal_close, "End by server");
break;
case packet::frame_pong:
this->on_pong();
case packet::frame_ping:
this->on_ping();
break;

default:
Expand All @@ -560,11 +554,6 @@ namespace sio
m_ping_timeout_timer->cancel(ec);
m_ping_timeout_timer.reset();
}
if(m_ping_timer)
{
m_ping_timer->cancel(ec);
m_ping_timer.reset();
}
}

void client_impl::reset_states()
Expand Down
4 changes: 1 addition & 3 deletions src/internal/sio_client_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ namespace sio
//socketio callbacks
void on_handshake(message::ptr const& message);

void on_pong();
void on_ping();

void reset_states();

Expand Down Expand Up @@ -201,8 +201,6 @@ namespace sio

packet_manager m_packet_mgr;

std::unique_ptr<asio::steady_timer> m_ping_timer;

std::unique_ptr<asio::steady_timer> m_ping_timeout_timer;

std::unique_ptr<asio::steady_timer> m_reconn_timer;
Expand Down
10 changes: 2 additions & 8 deletions src/internal/sio_packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,7 @@ namespace sio
Value numVal;
numVal.SetInt((int)buffers.size());
val.AddMember("num", numVal, doc.GetAllocator());
//FIXME can not avoid binary copy here.
shared_ptr<string> write_buffer = make_shared<string>();
write_buffer->reserve(msg.get_binary()->size()+1);
char frame_char = packet::frame_message;
write_buffer->append(&frame_char,1);
write_buffer->append(*(msg.get_binary()));
buffers.push_back(write_buffer);
buffers.push_back(msg.get_binary());
}

void accept_array_message(array_message const& msg,Value& val,Document& doc,vector<shared_ptr<const string> >& buffers)
Expand Down Expand Up @@ -253,7 +247,7 @@ namespace sio
{
if (_pending_buffers > 0) {
assert(is_binary_message(buf_payload));//this is ensured by outside.
_buffers.push_back(std::make_shared<string>(buf_payload.data()+1,buf_payload.size()-1));
_buffers.push_back(std::make_shared<string>(buf_payload.data(),buf_payload.size()));
_pending_buffers--;
if (_pending_buffers == 0) {

Expand Down
4 changes: 0 additions & 4 deletions src/sio_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,6 @@ namespace sio
void socket::impl::send_connect()
{
NULL_GUARD(m_client);
if(m_nsp == "/")
{
return;
}
packet p(packet::type_connect,m_nsp);
m_client->send(p);
m_connection_timer.reset(new asio::steady_timer(m_client->get_io_service()));
Expand Down
12 changes: 5 additions & 7 deletions test/echo_server/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
var port = 3000;

var io = require('socket.io').listen(port);
var io = require('socket.io')().listen(port);
console.log("Listening on port " + port);

/* Socket.IO events */
io.on("connection", function(socket){
console.log("new connection");
socket.on('test_text',function()
{
console.log("test text event received.");
socket.on('test_text', (...args) => {
console.log("test text event received.", args);
});

socket.on('test_binary',function()
{
var args =Array.prototype.slice.call(arguments);
socket.on('test_binary', (...args) => {
console.log("test binary event received", args);
if(args[0] instanceof Buffer)
{
console.log("test binary event received,binary length:"+ args[0].length);
Expand Down
165 changes: 165 additions & 0 deletions test/echo_server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions test/echo_server/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "echo_server",
"author":"Melo Yao",
"version":"0.0.0",
"author": "Melo Yao",
"version": "0.0.0",
"dependencies": {
"socket.io": "1.*"
}
"socket.io": "^3.0.5"
}
}
Binary file added test/sio_test
Binary file not shown.
17 changes: 8 additions & 9 deletions test/sio_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,16 @@ TEST_CASE( "test_packet_accept_4" )
int bin1Num = j["bin1"]["num"].get<int>();
char numchar[] = {0,0};
numchar[0] = bin1Num+'0';
CHECK(buffers[bin1Num]->length()==101);
CHECK(buffers[bin1Num]->length()==100);
INFO("outputing payload bin1 num:" << numchar)
CHECK(buffers[bin1Num]->at(50)==0);
CHECK(buffers[bin1Num]->at(0) == packet::frame_message);
CHECK(buffers[bin1Num]->at(0) == 0);
int bin2Num = j["bin2"]["num"].get<int>();
numchar[0] = bin2Num+'0';
CHECK(buffers[bin2Num]->length()==51);
CHECK(buffers[bin2Num]->length()==50);
INFO("outputing payload bin2 num:" << numchar)
CHECK(buffers[bin2Num]->at(25)==1);
CHECK(buffers[bin2Num]->at(0) == packet::frame_message);
CHECK(buffers[bin2Num]->at(0) == 1);
}
#endif

Expand Down Expand Up @@ -209,12 +209,11 @@ TEST_CASE( "test_packet_parse_4" )
packet p;
bool hasbin = p.parse("452-/nsp,101[\"bin_event\",[{\"_placeholder\":true,\"num\":1},{\"_placeholder\":true,\"num\":0},\"text\"]]");
CHECK(hasbin);
char buf[101];
buf[0] = packet::frame_message;
memset(buf+1,0,100);
char buf[100];
memset(buf,0,100);

std::string bufstr(buf,101);
std::string bufstr2(buf,51);
std::string bufstr(buf,100);
std::string bufstr2(buf,50);
CHECK(p.parse_buffer(bufstr));
CHECK(!p.parse_buffer(bufstr2));

Expand Down

0 comments on commit ec4d540

Please sign in to comment.