From 5af28838d2c754f4e57c2d2462e9fa82a60bf144 Mon Sep 17 00:00:00 2001 From: Chris Hannon Date: Fri, 24 Apr 2015 00:05:07 -0400 Subject: [PATCH] [v3-update-sio] updates SocketIO network extension to support v1.x socket.io servers as well as maintain backwards compat. for 0.9.x servers Signed-off-by: Chris Hannon --- cocos/network/SocketIO.cpp | 790 ++++++++++++++++++++++++++++++------- cocos/network/SocketIO.h | 14 +- 2 files changed, 659 insertions(+), 145 deletions(-) diff --git a/cocos/network/SocketIO.cpp b/cocos/network/SocketIO.cpp index 2aa7754b38..28b119d46d 100644 --- a/cocos/network/SocketIO.cpp +++ b/cocos/network/SocketIO.cpp @@ -1,6 +1,6 @@ /**************************************************************************** - Copyright (c) 2013 Chris Hannon - Copyright (c) 2013-2014 Chukong Technologies Inc. + Copyright (c) 2015 Chris Hannon http://www.channon.us + Copyright (c) 2013-2015 Chukong Technologies Inc. http://www.cocos2d-x.org @@ -36,12 +36,319 @@ #include "WebSocket.h" #include "HttpClient.h" +#include "json/rapidjson.h" +#include "json/document.h" +#include "json/stringbuffer.h" +#include "json/writer.h" + NS_CC_BEGIN namespace network { //class declarations +class SocketIOPacketV10x; + +class SocketIOPacket +{ +public: + typedef enum + { + V09x, + V10x + }SocketIOVersion; + + SocketIOPacket(); + virtual ~SocketIOPacket(); + void initWithType(std::string packetType); + void initWithTypeIndex(int index); + + std::string toString(); + virtual int typeAsNumber(); + std::string typeForIndex(int index); + + void setEndpoint(std::string endpoint){ _endpoint = endpoint; }; + std::string getEndpoint(){ return _endpoint; }; + void setEvent(std::string event){ _name = event; }; + std::string getEvent(){ return _name; }; + + void addData(std::string data); + std::vector getData(){ return _args; }; + virtual std::string stringify(); + + static SocketIOPacket * createPacketWithType(std::string type, SocketIOPacket::SocketIOVersion version); + static SocketIOPacket * createPacketWithTypeIndex(int type, SocketIOPacket::SocketIOVersion version); +protected: + std::string _pId;//id message + std::string _ack;// + std::string _name;//event name + std::vector _args;//we will be using a vector of strings to store multiple data + std::string _endpoint;// + std::string _endpointseperator;//socket.io 1.x requires a ',' between endpoint and payload + std::string _type;//message type + std::string _separator;//for stringify the object + std::vector _types;//types of messages +}; + +class SocketIOPacketV10x : public SocketIOPacket +{ +public: + SocketIOPacketV10x(); + virtual ~SocketIOPacketV10x(); + int typeAsNumber(); + std::string stringify(); +private: + std::vector _typesMessage; +}; + +SocketIOPacket::SocketIOPacket() +{ + _type = "";//message type + _separator = ":";//for stringify the object + _endpointseperator = "";//socket.io 1.x requires a ',' between endpoint and payload + _pId = "";//id message + _ack = "";// + _name = "";//event name + _endpoint = "";// + _types.push_back("disconnect"); + _types.push_back("connect"); + _types.push_back("heartbeat"); + _types.push_back("message"); + _types.push_back("json"); + _types.push_back("event"); + _types.push_back("ack"); + _types.push_back("error"); + _types.push_back("noop"); +} + +SocketIOPacket::~SocketIOPacket() +{ + _types.clear(); + _type = ""; + _pId = ""; + _name = ""; + _ack = ""; + _endpoint = ""; +} + +void SocketIOPacket::initWithType(std::string packetType) +{ + _type = packetType; +} +void SocketIOPacket::initWithTypeIndex(int index) +{ + _type = _types.at(index); +} + +std::string SocketIOPacket::toString() +{ + std::stringstream encoded; + encoded << this->typeAsNumber(); + encoded << this->_separator; + + std::string pIdL = _pId; + if (_ack == "data") + { + pIdL += "+"; + } + + // Do not write pid for acknowledgements + if (_type != "ack") + { + encoded << pIdL; + } + encoded << this->_separator; + + // Add the endpoint for the namespace to be used if not the default namespace "" or "/", and as long as it is not an ACK, heartbeat, or disconnect packet + if (_endpoint != "/" && _endpoint != "" && _type != "ack" && _type != "heartbeat" && _type != "disconnect") { + encoded << _endpoint << _endpointseperator; + } + encoded << this->_separator; + + + if (_args.size() != 0) + { + std::string ackpId = ""; + // This is an acknowledgement packet, so, prepend the ack pid to the data + if (_type == "ack") + { + ackpId += pIdL + "+"; + } + + encoded << ackpId << this->stringify(); + } + + return encoded.str(); +} +int SocketIOPacket::typeAsNumber() +{ + int num = 0; + std::vector::iterator item = std::find(_types.begin(), _types.end(), _type); + if (item != _types.end()) + { + num = item - _types.begin(); + } + return num; +} +std::string SocketIOPacket::typeForIndex(int index) +{ + return _types.at(index); +} + +void SocketIOPacket::addData(std::string data) +{ + + this->_args.push_back(data); + +} + +std::string SocketIOPacket::stringify() +{ + + std::string outS; + if (_type == "message") { + outS = _args[0]; + } + else { + + rapidjson::StringBuffer s; + rapidjson::Writer writer(s); + + writer.StartObject(); + writer.String("name"); + writer.String(_name.c_str()); + + writer.String("args"); + + writer.StartArray(); + + for (int i = 0; i < _args.size(); i++) { + writer.String(_args[i].c_str()); + } + + writer.EndArray(); + writer.EndObject(); + + outS = s.GetString(); + + log("create args object: %s:", outS.c_str()); + } + + return outS; +} + +SocketIOPacketV10x::SocketIOPacketV10x() +{ + _separator = ":"; + _type = "";//message type + _separator = "";//for stringify the object + _endpointseperator = ","; + _pId = "";//id message + _ack = "";// + _name = "";//event name + _endpoint = "";// + _types.push_back("disconnected"); + _types.push_back("connected"); + _types.push_back("heartbeat"); + _types.push_back("pong"); + _types.push_back("message"); + _types.push_back("upgrade"); + _types.push_back("noop"); + _typesMessage.push_back("connect"); + _typesMessage.push_back("disconnect"); + _typesMessage.push_back("event"); + _typesMessage.push_back("ack"); + _typesMessage.push_back("error"); + _typesMessage.push_back("binarevent"); + _typesMessage.push_back("binaryack"); +} + +int SocketIOPacketV10x::typeAsNumber() +{ + int num = 0; + std::vector::iterator item = std::find(_typesMessage.begin(), _typesMessage.end(), _type); + if (item != _typesMessage.end()) + {//it's a message + num = item - _typesMessage.begin(); + num += 40; + } + else + { + item = std::find(_types.begin(), _types.end(), _type); + num += item - _types.begin(); + } + return num; +} + +std::string SocketIOPacketV10x::stringify() +{ + + std::string outS; + + rapidjson::StringBuffer s; + rapidjson::Writer writer(s); + + writer.StartArray(); + writer.String(_name.c_str()); + + for (int i = 0; i < _args.size(); i++) { + writer.String(_args[i].c_str()); + } + + writer.EndArray(); + + outS = s.GetString(); + + log("create args object: %s:", outS.c_str()); + + return outS; + +} + +SocketIOPacketV10x::~SocketIOPacketV10x() +{ + _types.clear(); + _typesMessage.clear(); + _type = ""; + _pId = ""; + _name = ""; + _ack = ""; + _endpoint = ""; +} + +SocketIOPacket * SocketIOPacket::createPacketWithType(std::string type, SocketIOPacket::SocketIOVersion version) +{ + SocketIOPacket *ret; + switch (version) + { + case SocketIOPacket::V09x: + ret = new SocketIOPacket; + break; + case SocketIOPacket::V10x: + ret = new SocketIOPacketV10x; + break; + } + ret->initWithType(type); + return ret; +} + + +SocketIOPacket * SocketIOPacket::createPacketWithTypeIndex(int type, SocketIOPacket::SocketIOVersion version) +{ + SocketIOPacket *ret; + switch (version) + { + case SocketIOPacket::V09x: + ret = new SocketIOPacket; + break; + case SocketIOPacket::V10x: + return new SocketIOPacketV10x; + break; + } + ret->initWithTypeIndex(type); + return ret; +} + /** * @brief The implementation of the socket.io connection * Clients/endpoints may share the same impl to accomplish multiplexing on the same websocket @@ -54,6 +361,7 @@ private: int _port, _heartbeat, _timeout; std::string _host, _sid, _uri; bool _connected; + SocketIOPacket::SocketIOVersion _version; WebSocket *_ws; @@ -85,6 +393,7 @@ public: void disconnectFromEndpoint(const std::string& endpoint); void send(std::string endpoint, std::string s); + void send(SocketIOPacket *packet); void emit(std::string endpoint, std::string eventname, std::string args); @@ -119,7 +428,7 @@ void SIOClientImpl::handshake() log("SIOClientImpl::handshake() called"); std::stringstream pre; - pre << "http://" << _uri << "/socket.io/1"; + pre << "http://" << _uri << "/socket.io/1/?EIO=2&transport=polling&b64=true"; HttpRequest* request = new (std::nothrow) HttpRequest(); request->setUrl(pre.str().c_str()); @@ -168,6 +477,7 @@ void SIOClientImpl::handshakeResponse(HttpClient *sender, HttpResponse *response std::vector *buffer = response->getResponseData(); std::stringstream s; + s.str(""); for (unsigned int i = 0; i < buffer->size(); i++) { @@ -177,27 +487,76 @@ void SIOClientImpl::handshakeResponse(HttpClient *sender, HttpResponse *response log("SIOClientImpl::handshake() dump data: %s", s.str().c_str()); std::string res = s.str(); - std::string sid; - size_t pos = 0; + std::string sid = ""; int heartbeat = 0, timeout = 0; - pos = res.find(":"); - if(pos != std::string::npos) - { - sid = res.substr(0, pos); - res.erase(0, pos+1); - } + if (res.at(res.size() - 1) == '}') { - pos = res.find(":"); - if(pos != std::string::npos) - { - heartbeat = atoi(res.substr(pos+1, res.size()).c_str()); - } + log("SIOClientImpl::handshake() Socket.IO 1.x detected"); + _version = SocketIOPacket::V10x; + // sample: 97:0{"sid":"GMkL6lzCmgMvMs9bAAAA","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000} + + int a, b; + a = res.find('{'); + std::string temp = res.substr(a, res.size() - a); + + // find the sid + a = temp.find(":"); + b = temp.find(","); + + sid = temp.substr(a + 2, b - (a + 3)); + + temp = temp.erase(0, b + 1); + + // chomp past the upgrades + a = temp.find(":"); + b = temp.find(","); + + temp = temp.erase(0, b + 1); + + // get the pingInterval / heartbeat + a = temp.find(":"); + b = temp.find(","); + + std::string heartbeat_str = temp.substr(a + 1, b - a); + heartbeat = atoi(heartbeat_str.c_str()) / 1000; + temp = temp.erase(0, b + 1); + + // get the timeout + a = temp.find(":"); + b = temp.find("}"); + + std::string timeout_str = temp.substr(a + 1, b - a); + timeout = atoi(timeout_str.c_str()) / 1000; + log("done parsing 1.x"); + + } + else { + + log("SIOClientImpl::handshake() Socket.IO 0.9.x detected"); + _version = SocketIOPacket::V09x; + // sample: 3GYzE9md2Ig-lm3cf8Rv:60:60:websocket,htmlfile,xhr-polling,jsonp-polling + size_t pos = 0; + + pos = res.find(":"); + if (pos != std::string::npos) + { + sid = res.substr(0, pos); + res.erase(0, pos + 1); + } + + pos = res.find(":"); + if (pos != std::string::npos) + { + heartbeat = atoi(res.substr(pos + 1, res.size()).c_str()); + } + + pos = res.find(":"); + if (pos != std::string::npos) + { + timeout = atoi(res.substr(pos + 1, res.size()).c_str()); + } - pos = res.find(":"); - if(pos != std::string::npos) - { - timeout = atoi(res.substr(pos+1, res.size()).c_str()); } _sid = sid; @@ -215,7 +574,16 @@ void SIOClientImpl::openSocket() log("SIOClientImpl::openSocket() called"); std::stringstream s; - s << _uri << "/socket.io/1/websocket/" << _sid; + + switch (_version) + { + case SocketIOPacket::V09x: + s << _uri << "/socket.io/1/websocket/" << _sid; + break; + case SocketIOPacket::V10x: + s << _uri << "/socket.io/1/websocket/?EIO=2&transport=websocket&sid=" << _sid; + break; + } _ws = new (std::nothrow) WebSocket(); if (!_ws->init(*this, s.str())) @@ -241,17 +609,21 @@ void SIOClientImpl::disconnect() { if(_ws->getReadyState() == WebSocket::State::OPEN) { - std::string s = "0::"; + std::string s, endpoint; + s = ""; + endpoint = ""; + if (_version == SocketIOPacket::V09x) + s = "0::" + endpoint; + else + s = "41" + endpoint; _ws->send(s); - - log("Disconnect sent"); - - _ws->close(); } Director::getInstance()->getScheduler()->unscheduleAllForTarget(this); + _ws->close(); + _connected = false; SocketIO::getInstance()->removeSocket(_uri); @@ -281,11 +653,9 @@ void SIOClientImpl::addClient(const std::string& endpoint, SIOClient* client) void SIOClientImpl::connectToEndpoint(const std::string& endpoint) { - std::string path = endpoint == "/" ? "" : endpoint; - - std::string s = "1::" + path; - - _ws->send(s); + SocketIOPacket *packet = SocketIOPacket::createPacketWithType("connect", _version); + packet->setEndpoint(endpoint); + this->send(packet); } void SIOClientImpl::disconnectFromEndpoint(const std::string& endpoint) @@ -296,7 +666,7 @@ void SIOClientImpl::disconnectFromEndpoint(const std::string& endpoint) { log("SIOClientImpl::disconnectFromEndpoint out of endpoints, checking for disconnect"); - if(_connected) + if (_connected) this->disconnect(); } else @@ -311,9 +681,9 @@ void SIOClientImpl::disconnectFromEndpoint(const std::string& endpoint) void SIOClientImpl::heartbeat(float dt) { - std::string s = "2::"; + SocketIOPacket *packet = SocketIOPacket::createPacketWithType("heartbeat", _version); - _ws->send(s); + this->send(packet); log("Heartbeat sent"); } @@ -321,32 +691,43 @@ void SIOClientImpl::heartbeat(float dt) void SIOClientImpl::send(std::string endpoint, std::string s) { - std::stringstream pre; + switch (_version) { + case SocketIOPacket::V09x: + { + SocketIOPacket *packet = SocketIOPacket::createPacketWithType("message", _version); + packet->setEndpoint(endpoint); + packet->addData(s); + this->send(packet); + break; + } + case SocketIOPacket::V10x: + { + this->emit(endpoint, "message", s); + break; + } + } +} - std::string path = endpoint == "/" ? "" : endpoint; - - pre << "3::" << path << ":" << s; - - std::string msg = pre.str(); - - log("sending message: %s", msg.c_str()); - - _ws->send(msg); +void SIOClientImpl::send(SocketIOPacket *packet) +{ + std::string req = packet->toString(); + if (_connected) + { + log("-->SEND:%s", req.data()); + _ws->send(req.data()); + } + else + log("Cant send the message (%s) because disconnected", req); } void SIOClientImpl::emit(std::string endpoint, std::string eventname, std::string args) { - std::stringstream pre; - - std::string path = endpoint == "/" ? "" : endpoint; - - pre << "5::" << path << ":{\"name\":\"" << eventname << "\",\"args\":" << args << "}"; - - std::string msg = pre.str(); - - log("emitting event with data: %s", msg.c_str()); - - _ws->send(msg); + log("Emitting event \"%s\"", eventname); + SocketIOPacket *packet = SocketIOPacket::createPacketWithType("event", _version); + packet->setEndpoint(endpoint == "/" ? "" : endpoint); + packet->setEvent(eventname); + packet->addData(args); + this->send(packet); } void SIOClientImpl::onOpen(WebSocket* ws) @@ -355,13 +736,19 @@ void SIOClientImpl::onOpen(WebSocket* ws) SocketIO::getInstance()->addSocket(_uri, this); + if (_version == SocketIOPacket::V10x) + { + std::string s = "5";//That's a ping https://github.com/Automattic/engine.io-parser/blob/1b8e077b2218f4947a69f5ad18be2a512ed54e93/lib/index.js#L21 + _ws->send(s.data()); + } + + Director::getInstance()->getScheduler()->schedule(CC_SCHEDULE_SELECTOR(SIOClientImpl::heartbeat), this, (_heartbeat * .9f), false); + for (auto iter = _clients.begin(); iter != _clients.end(); ++iter) { iter->second->onOpen(); } - Director::getInstance()->getScheduler()->schedule(CC_SCHEDULE_SELECTOR(SIOClientImpl::heartbeat), this, (_heartbeat * .9f), false); - log("SIOClientImpl::onOpen socket connected!"); } @@ -369,94 +756,223 @@ void SIOClientImpl::onMessage(WebSocket* ws, const WebSocket::Data& data) { log("SIOClientImpl::onMessage received: %s", data.bytes); - int control = atoi(&data.bytes[0]); + std::string payload = data.bytes; + int control = atoi(payload.substr(0, 1).c_str()); + payload = payload.substr(1, payload.size() - 1); - std::string payload, msgid, endpoint, s_data, eventname; - payload = data.bytes; - - size_t pos, pos2; - - pos = payload.find(":"); - if(pos != std::string::npos ) { - payload.erase(0, pos+1); - } - - pos = payload.find(":"); - if(pos != std::string::npos ) { - msgid = atoi(payload.substr(0, pos+1).c_str()); - } - payload.erase(0, pos+1); - - pos = payload.find(":"); - if(pos != std::string::npos) - { - endpoint = payload.substr(0, pos); - payload.erase(0, pos+1); - } - else - { - endpoint = payload; - } - - if (endpoint == "") endpoint = "/"; - - - s_data = payload; SIOClient *c = nullptr; - c = getClient(endpoint); - if (c == nullptr) log("SIOClientImpl::onMessage client lookup returned nullptr"); - switch(control) + switch (_version) { - case 0: - log("Received Disconnect Signal for Endpoint: %s\n", endpoint.c_str()); - if(c) c->receivedDisconnect(); - disconnectFromEndpoint(endpoint); - break; - case 1: - log("Connected to endpoint: %s \n",endpoint.c_str()); - if(c) c->onConnect(); - break; - case 2: - log("Heartbeat received\n"); - break; - case 3: - log("Message received: %s \n", s_data.c_str()); - if(c) c->getDelegate()->onMessage(c, s_data); - break; - case 4: - log("JSON Message Received: %s \n", s_data.c_str()); - if(c) c->getDelegate()->onMessage(c, s_data); - break; - case 5: - log("Event Received with data: %s \n", s_data.c_str()); + case SocketIOPacket::V09x: + { + std::string msgid, endpoint, s_data, eventname; - if(c) - { - eventname = ""; - pos = s_data.find(":"); - pos2 = s_data.find(","); - if(pos2 > pos) - { - s_data = s_data.substr(pos+1, pos2-pos-1); - std::remove_copy(s_data.begin(), s_data.end(), - std::back_inserter(eventname), '"'); - } + size_t pos, pos2; - c->fireEvent(eventname, payload); + pos = payload.find(":"); + if (pos != std::string::npos) { + payload.erase(0, pos + 1); } + pos = payload.find(":"); + if (pos != std::string::npos) { + msgid = atoi(payload.substr(0, pos + 1).c_str()); + } + payload.erase(0, pos + 1); + + pos = payload.find(":"); + if (pos != std::string::npos) + { + endpoint = payload.substr(0, pos); + payload.erase(0, pos + 1); + } + else + { + endpoint = payload; + } + + if (endpoint == "") endpoint = "/"; + + c = getClient(endpoint); + + s_data = payload; + + if (c == nullptr) log("SIOClientImpl::onMessage client lookup returned nullptr"); + + switch (control) + { + case 0: + log("Received Disconnect Signal for Endpoint: %s\n", endpoint.c_str()); + disconnectFromEndpoint(endpoint); + c->fireEvent("disconnect", payload); + break; + case 1: + log("Connected to endpoint: %s \n", endpoint.c_str()); + if (c) { + c->onConnect(); + c->fireEvent("connect", payload); + } + break; + case 2: + log("Heartbeat received\n"); + break; + case 3: + log("Message received: %s \n", s_data.c_str()); + if (c) c->getDelegate()->onMessage(c, s_data); + if (c) c->fireEvent("message", s_data); + break; + case 4: + log("JSON Message Received: %s \n", s_data.c_str()); + if (c) c->getDelegate()->onMessage(c, s_data); + if (c) c->fireEvent("json", s_data); + break; + case 5: + log("Event Received with data: %s \n", s_data.c_str()); + + if (c) + { + eventname = ""; + pos = s_data.find(":"); + pos2 = s_data.find(","); + if (pos2 > pos) + { + eventname = s_data.substr(pos + 2, pos2 - (pos + 3)); + s_data = s_data.substr(pos2 + 9, s_data.size() - (pos2 + 11)); + } + + c->fireEvent(eventname, s_data); + } + + break; + case 6: + log("Message Ack\n"); + break; + case 7: + log("Error\n"); + //if (c) c->getDelegate()->onError(c, s_data); + if (c) c->fireEvent("error", s_data); + break; + case 8: + log("Noop\n"); + break; + } + } + break; + case SocketIOPacket::V10x: + { + switch (control) + { + case 0: + log("Not supposed to receive control 0 for websocket"); + log("That's not good"); + break; + case 1: + log("Not supposed to receive control 1 for websocket"); + break; + case 2: + log("Ping received, send pong"); + payload = "3" + payload; + _ws->send(payload.c_str()); + break; + case 3: + log("Pong received"); + if (payload == "probe") + { + log("Request Update"); + _ws->send("5"); + } + break; + case 4: + + const char second = payload.at(0); + int control2 = atoi(&second); + log("Message code: [%i]", control); + + SocketIOPacket *packetOut = SocketIOPacket::createPacketWithType("event", _version); + std::string endpoint = ""; + + int a = payload.find("/"); + int b = payload.find("["); + + if (b != std::string::npos) { + if (a != std::string::npos && a < b) { + //we have an endpoint and a payload + endpoint = payload.substr(a, b - (a + 1)); + } + } + else if (a != std::string::npos) { + //we have an endpoint with no payload + endpoint = payload.substr(a, payload.size() - a); + } + + // we didn't find and endpoint and we are in the default namespace + if (endpoint == "") endpoint = "/"; + + packetOut->setEndpoint(endpoint); + + c = getClient(endpoint); + + payload = payload.substr(1); + + if (endpoint != "/") payload = payload.substr(endpoint.size()); + if (endpoint != "/" && payload != "") payload = payload.substr(1); + + switch (control2) + { + case 0: + log("Socket Connected"); + if (c) { + c->onConnect(); + c->fireEvent("connect", payload); + } + break; + case 1: + log("Socket Disconnected"); + disconnectFromEndpoint(endpoint); + c->fireEvent("disconnect", payload); + break; + case 2: + { + log("Event Received (%s)", payload.c_str()); + + int a = payload.find("\""); + int b = payload.substr(a + 1).find("\""); + + std::string eventname = payload.substr(a + 1, b - a + 1); + log("event name %s between %i and %i", eventname.c_str(), a, b); + + payload = payload.substr(b + 4, payload.size() - (b + 5)); + + if (c) c->fireEvent(eventname, payload); + if (c) c->getDelegate()->onMessage(c, payload); + + } + break; + case 3: + log("Message Ack"); + break; + case 4: + log("Error"); + if (c) c->fireEvent("error", payload); + break; + case 5: + log("Binary Event"); + break; + case 6: + log("Binary Ack"); + break; + } + } + break; + case 5: + log("Upgrade required"); break; case 6: - log("Message Ack\n"); - break; - case 7: - log("Error\n"); - if(c) c->getDelegate()->onError(c, s_data); - break; - case 8: log("Noop\n"); break; + } + break; } return; @@ -468,7 +984,7 @@ void SIOClientImpl::onClose(WebSocket* ws) { for (auto iter = _clients.begin(); iter != _clients.end(); ++iter) { - iter->second->receivedDisconnect(); + iter->second->socketClosed(); } } @@ -477,6 +993,7 @@ void SIOClientImpl::onClose(WebSocket* ws) void SIOClientImpl::onError(WebSocket* ws, const WebSocket::ErrorCode& error) { + log("Websocket error received: %s", error); } //begin SIOClient methods @@ -510,7 +1027,6 @@ void SIOClient::onOpen() void SIOClient::onConnect() { _connected = true; - _delegate->onConnect(this); } void SIOClient::send(std::string s) @@ -545,12 +1061,10 @@ void SIOClient::disconnect() _socket->disconnectFromEndpoint(_path); - _delegate->onClose(this); - this->release(); } -void SIOClient::receivedDisconnect() +void SIOClient::socketClosed() { _connected = false; diff --git a/cocos/network/SocketIO.h b/cocos/network/SocketIO.h index 57e5d89d6e..b1668b63c9 100644 --- a/cocos/network/SocketIO.h +++ b/cocos/network/SocketIO.h @@ -1,6 +1,6 @@ /**************************************************************************** - Copyright (c) 2013 Chris Hannon http://www.channon.us - Copyright (c) 2013-2014 Chukong Technologies Inc. + Copyright (c) 2015 Chris Hannon http://www.channon.us + Copyright (c) 2013-2015 Chukong Technologies Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -103,22 +103,22 @@ public: /** Destructor of SIODelegate. */ virtual ~SIODelegate() {} /** - * Pure virtual callback function, this function should be overrided by the subclass. + * This is kept for backwards compatibility, connect is now fired as a socket.io event "connect" * * This function would be called when the related SIOClient object recevie messages that mean it have connected to endpoint sucessfully. * * @param client the connected SIOClient object. */ - virtual void onConnect(SIOClient* client) = 0; + virtual void onConnect(SIOClient* client) { CCLOG("SIODelegate onConnect fired"); }; /** - * Pure virtual callback function, this function should be overrided by the subclass. + * This is kept for backwards compatibility, message is now fired as a socket.io event "message" * * This function would be called wwhen the related SIOClient object recevie message or json message. * * @param client the connected SIOClient object. * @param data the message,it could be json message */ - virtual void onMessage(SIOClient* client, const std::string& data) = 0; + virtual void onMessage(SIOClient* client, const std::string& data) { CCLOG("SIODelegate onMessage fired with data: %s", data.c_str()); }; /** * Pure virtual callback function, this function should be overrided by the subclass. * @@ -207,7 +207,7 @@ private: void onOpen(); void onConnect(); - void receivedDisconnect(); + void socketClosed(); friend class SIOClientImpl;