mirror of https://github.com/axmolengine/axmol.git
Merge pull request #5939 from dumganhar/merge5923
Merge PR #5923: implement fireEventToScript method to integrate JSB event handling with the original native code
This commit is contained in:
commit
ec4b1ee485
|
@ -1,19 +1,19 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013 Chris Hannon
|
||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
|
@ -43,114 +43,114 @@ namespace network {
|
|||
|
||||
/**
|
||||
* @brief The implementation of the socket.io connection
|
||||
* Clients/endpoints may share the same impl to accomplish multiplexing on the same websocket
|
||||
* Clients/endpoints may share the same impl to accomplish multiplexing on the same websocket
|
||||
*/
|
||||
class SIOClientImpl :
|
||||
public cocos2d::Ref,
|
||||
public WebSocket::Delegate
|
||||
class SIOClientImpl :
|
||||
public cocos2d::Ref,
|
||||
public WebSocket::Delegate
|
||||
{
|
||||
private:
|
||||
int _port, _heartbeat, _timeout;
|
||||
std::string _host, _sid, _uri;
|
||||
bool _connected;
|
||||
private:
|
||||
int _port, _heartbeat, _timeout;
|
||||
std::string _host, _sid, _uri;
|
||||
bool _connected;
|
||||
|
||||
WebSocket *_ws;
|
||||
WebSocket *_ws;
|
||||
|
||||
Map<std::string, SIOClient*> _clients;
|
||||
Map<std::string, SIOClient*> _clients;
|
||||
|
||||
public:
|
||||
SIOClientImpl(const std::string& host, int port);
|
||||
virtual ~SIOClientImpl(void);
|
||||
SIOClientImpl(const std::string& host, int port);
|
||||
virtual ~SIOClientImpl(void);
|
||||
|
||||
static SIOClientImpl* create(const std::string& host, int port);
|
||||
|
||||
virtual void onOpen(WebSocket* ws);
|
||||
static SIOClientImpl* create(const std::string& host, int port);
|
||||
|
||||
virtual void onOpen(WebSocket* ws);
|
||||
virtual void onMessage(WebSocket* ws, const WebSocket::Data& data);
|
||||
virtual void onClose(WebSocket* ws);
|
||||
virtual void onError(WebSocket* ws, const WebSocket::ErrorCode& error);
|
||||
|
||||
void connect();
|
||||
void disconnect();
|
||||
bool init();
|
||||
void handshake();
|
||||
void handshakeResponse(HttpClient *sender, HttpResponse *response);
|
||||
void openSocket();
|
||||
void heartbeat(float dt);
|
||||
void connect();
|
||||
void disconnect();
|
||||
bool init();
|
||||
void handshake();
|
||||
void handshakeResponse(HttpClient *sender, HttpResponse *response);
|
||||
void openSocket();
|
||||
void heartbeat(float dt);
|
||||
|
||||
SIOClient* getClient(const std::string& endpoint);
|
||||
void addClient(const std::string& endpoint, SIOClient* client);
|
||||
|
||||
void connectToEndpoint(const std::string& endpoint);
|
||||
void disconnectFromEndpoint(const std::string& endpoint);
|
||||
SIOClient* getClient(const std::string& endpoint);
|
||||
void addClient(const std::string& endpoint, SIOClient* client);
|
||||
|
||||
void send(std::string endpoint, std::string s);
|
||||
void emit(std::string endpoint, std::string eventname, std::string args);
|
||||
void connectToEndpoint(const std::string& endpoint);
|
||||
void disconnectFromEndpoint(const std::string& endpoint);
|
||||
|
||||
void send(std::string endpoint, std::string s);
|
||||
void emit(std::string endpoint, std::string eventname, std::string args);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//method implementations
|
||||
|
||||
//begin SIOClientImpl methods
|
||||
SIOClientImpl::SIOClientImpl(const std::string& host, int port) :
|
||||
_port(port),
|
||||
_host(host),
|
||||
_connected(false)
|
||||
_port(port),
|
||||
_host(host),
|
||||
_connected(false)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << host << ":" << port;
|
||||
_uri = s.str();
|
||||
std::stringstream s;
|
||||
s << host << ":" << port;
|
||||
_uri = s.str();
|
||||
|
||||
_ws = nullptr;
|
||||
_ws = nullptr;
|
||||
}
|
||||
|
||||
SIOClientImpl::~SIOClientImpl()
|
||||
{
|
||||
if (_connected)
|
||||
if (_connected)
|
||||
disconnect();
|
||||
|
||||
CC_SAFE_DELETE(_ws);
|
||||
CC_SAFE_DELETE(_ws);
|
||||
}
|
||||
|
||||
void SIOClientImpl::handshake()
|
||||
{
|
||||
log("SIOClientImpl::handshake() called");
|
||||
log("SIOClientImpl::handshake() called");
|
||||
|
||||
std::stringstream pre;
|
||||
pre << "http://" << _uri << "/socket.io/1";
|
||||
std::stringstream pre;
|
||||
pre << "http://" << _uri << "/socket.io/1";
|
||||
|
||||
HttpRequest* request = new HttpRequest();
|
||||
request->setUrl(pre.str().c_str());
|
||||
HttpRequest* request = new HttpRequest();
|
||||
request->setUrl(pre.str().c_str());
|
||||
request->setRequestType(HttpRequest::Type::GET);
|
||||
|
||||
request->setResponseCallback(this, httpresponse_selector(SIOClientImpl::handshakeResponse));
|
||||
request->setTag("handshake");
|
||||
|
||||
log("SIOClientImpl::handshake() waiting");
|
||||
log("SIOClientImpl::handshake() waiting");
|
||||
|
||||
HttpClient::getInstance()->send(request);
|
||||
|
||||
request->release();
|
||||
|
||||
return;
|
||||
|
||||
request->release();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SIOClientImpl::handshakeResponse(HttpClient *sender, HttpResponse *response)
|
||||
{
|
||||
log("SIOClientImpl::handshakeResponse() called");
|
||||
log("SIOClientImpl::handshakeResponse() called");
|
||||
|
||||
if (0 != strlen(response->getHttpRequest()->getTag()))
|
||||
if (0 != strlen(response->getHttpRequest()->getTag()))
|
||||
{
|
||||
log("%s completed", response->getHttpRequest()->getTag());
|
||||
}
|
||||
|
||||
long statusCode = response->getResponseCode();
|
||||
long statusCode = response->getResponseCode();
|
||||
char statusString[64] = {};
|
||||
sprintf(statusString, "HTTP Status Code: %ld, tag = %s", statusCode, response->getHttpRequest()->getTag());
|
||||
log("response code: %ld", statusCode);
|
||||
log("response code: %ld", statusCode);
|
||||
|
||||
if (!response->isSucceed())
|
||||
if (!response->isSucceed())
|
||||
{
|
||||
log("SIOClientImpl::handshake() failed");
|
||||
log("error buffer: %s", response->getErrorBuffer());
|
||||
|
@ -163,302 +163,302 @@ void SIOClientImpl::handshakeResponse(HttpClient *sender, HttpResponse *response
|
|||
return;
|
||||
}
|
||||
|
||||
log("SIOClientImpl::handshake() succeeded");
|
||||
log("SIOClientImpl::handshake() succeeded");
|
||||
|
||||
std::vector<char> *buffer = response->getResponseData();
|
||||
std::stringstream s;
|
||||
|
||||
for (unsigned int i = 0; i < buffer->size(); i++)
|
||||
std::vector<char> *buffer = response->getResponseData();
|
||||
std::stringstream s;
|
||||
|
||||
for (unsigned int i = 0; i < buffer->size(); i++)
|
||||
{
|
||||
s << (*buffer)[i];
|
||||
s << (*buffer)[i];
|
||||
}
|
||||
|
||||
log("SIOClientImpl::handshake() dump data: %s", s.str().c_str());
|
||||
|
||||
std::string res = s.str();
|
||||
std::string sid;
|
||||
size_t pos = 0;
|
||||
int heartbeat = 0, timeout = 0;
|
||||
log("SIOClientImpl::handshake() dump data: %s", s.str().c_str());
|
||||
|
||||
pos = res.find(":");
|
||||
if(pos != std::string::npos)
|
||||
std::string res = s.str();
|
||||
std::string sid;
|
||||
size_t pos = 0;
|
||||
int heartbeat = 0, timeout = 0;
|
||||
|
||||
pos = res.find(":");
|
||||
if(pos != std::string::npos)
|
||||
{
|
||||
sid = res.substr(0, pos);
|
||||
res.erase(0, pos+1);
|
||||
}
|
||||
sid = res.substr(0, pos);
|
||||
res.erase(0, pos+1);
|
||||
}
|
||||
|
||||
pos = res.find(":");
|
||||
pos = res.find(":");
|
||||
if(pos != std::string::npos)
|
||||
{
|
||||
heartbeat = atoi(res.substr(pos+1, res.size()).c_str());
|
||||
}
|
||||
|
||||
pos = res.find(":");
|
||||
pos = res.find(":");
|
||||
if(pos != std::string::npos)
|
||||
{
|
||||
timeout = atoi(res.substr(pos+1, res.size()).c_str());
|
||||
}
|
||||
|
||||
_sid = sid;
|
||||
_heartbeat = heartbeat;
|
||||
_timeout = timeout;
|
||||
|
||||
openSocket();
|
||||
_sid = sid;
|
||||
_heartbeat = heartbeat;
|
||||
_timeout = timeout;
|
||||
|
||||
return;
|
||||
openSocket();
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void SIOClientImpl::openSocket()
|
||||
{
|
||||
log("SIOClientImpl::openSocket() called");
|
||||
log("SIOClientImpl::openSocket() called");
|
||||
|
||||
std::stringstream s;
|
||||
s << _uri << "/socket.io/1/websocket/" << _sid;
|
||||
std::stringstream s;
|
||||
s << _uri << "/socket.io/1/websocket/" << _sid;
|
||||
|
||||
_ws = new WebSocket();
|
||||
if (!_ws->init(*this, s.str()))
|
||||
{
|
||||
CC_SAFE_DELETE(_ws);
|
||||
}
|
||||
|
||||
return;
|
||||
_ws = new WebSocket();
|
||||
if (!_ws->init(*this, s.str()))
|
||||
{
|
||||
CC_SAFE_DELETE(_ws);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool SIOClientImpl::init()
|
||||
{
|
||||
log("SIOClientImpl::init() successful");
|
||||
return true;
|
||||
log("SIOClientImpl::init() successful");
|
||||
return true;
|
||||
}
|
||||
|
||||
void SIOClientImpl::connect()
|
||||
{
|
||||
this->handshake();
|
||||
this->handshake();
|
||||
}
|
||||
|
||||
void SIOClientImpl::disconnect()
|
||||
{
|
||||
if(_ws->getReadyState() == WebSocket::State::OPEN)
|
||||
if(_ws->getReadyState() == WebSocket::State::OPEN)
|
||||
{
|
||||
std::string s = "0::";
|
||||
std::string s = "0::";
|
||||
|
||||
_ws->send(s);
|
||||
_ws->send(s);
|
||||
|
||||
log("Disconnect sent");
|
||||
log("Disconnect sent");
|
||||
|
||||
_ws->close();
|
||||
}
|
||||
_ws->close();
|
||||
}
|
||||
|
||||
Director::getInstance()->getScheduler()->unscheduleAllForTarget(this);
|
||||
Director::getInstance()->getScheduler()->unscheduleAllForTarget(this);
|
||||
|
||||
_connected = false;
|
||||
_connected = false;
|
||||
|
||||
SocketIO::getInstance()->removeSocket(_uri);
|
||||
SocketIO::getInstance()->removeSocket(_uri);
|
||||
}
|
||||
|
||||
SIOClientImpl* SIOClientImpl::create(const std::string& host, int port)
|
||||
{
|
||||
SIOClientImpl *s = new SIOClientImpl(host, port);
|
||||
SIOClientImpl *s = new SIOClientImpl(host, port);
|
||||
|
||||
if (s && s->init())
|
||||
if (s && s->init())
|
||||
{
|
||||
return s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SIOClient* SIOClientImpl::getClient(const std::string& endpoint)
|
||||
{
|
||||
return _clients.at(endpoint);
|
||||
{
|
||||
return _clients.at(endpoint);
|
||||
}
|
||||
|
||||
void SIOClientImpl::addClient(const std::string& endpoint, SIOClient* client)
|
||||
{
|
||||
_clients.insert(endpoint, client);
|
||||
_clients.insert(endpoint, client);
|
||||
}
|
||||
|
||||
void SIOClientImpl::connectToEndpoint(const std::string& endpoint)
|
||||
{
|
||||
std::string path = endpoint == "/" ? "" : endpoint;
|
||||
std::string path = endpoint == "/" ? "" : endpoint;
|
||||
|
||||
std::string s = "1::" + path;
|
||||
std::string s = "1::" + path;
|
||||
|
||||
_ws->send(s);
|
||||
_ws->send(s);
|
||||
}
|
||||
|
||||
void SIOClientImpl::disconnectFromEndpoint(const std::string& endpoint)
|
||||
{
|
||||
_clients.erase(endpoint);
|
||||
_clients.erase(endpoint);
|
||||
|
||||
if (_clients.empty() || endpoint == "/")
|
||||
if (_clients.empty() || endpoint == "/")
|
||||
{
|
||||
log("SIOClientImpl::disconnectFromEndpoint out of endpoints, checking for disconnect");
|
||||
|
||||
if(_connected)
|
||||
log("SIOClientImpl::disconnectFromEndpoint out of endpoints, checking for disconnect");
|
||||
|
||||
if(_connected)
|
||||
this->disconnect();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string path = endpoint == "/" ? "" : endpoint;
|
||||
std::string path = endpoint == "/" ? "" : endpoint;
|
||||
|
||||
std::string s = "0::" + path;
|
||||
std::string s = "0::" + path;
|
||||
|
||||
_ws->send(s);
|
||||
}
|
||||
_ws->send(s);
|
||||
}
|
||||
}
|
||||
|
||||
void SIOClientImpl::heartbeat(float dt)
|
||||
{
|
||||
std::string s = "2::";
|
||||
std::string s = "2::";
|
||||
|
||||
_ws->send(s);
|
||||
_ws->send(s);
|
||||
|
||||
log("Heartbeat sent");
|
||||
log("Heartbeat sent");
|
||||
}
|
||||
|
||||
|
||||
void SIOClientImpl::send(std::string endpoint, std::string s)
|
||||
{
|
||||
std::stringstream pre;
|
||||
std::stringstream pre;
|
||||
|
||||
std::string path = endpoint == "/" ? "" : endpoint;
|
||||
|
||||
pre << "3::" << path << ":" << s;
|
||||
std::string path = endpoint == "/" ? "" : endpoint;
|
||||
|
||||
std::string msg = pre.str();
|
||||
pre << "3::" << path << ":" << s;
|
||||
|
||||
log("sending message: %s", msg.c_str());
|
||||
std::string msg = pre.str();
|
||||
|
||||
_ws->send(msg);
|
||||
log("sending message: %s", msg.c_str());
|
||||
|
||||
_ws->send(msg);
|
||||
}
|
||||
|
||||
void SIOClientImpl::emit(std::string endpoint, std::string eventname, std::string args)
|
||||
{
|
||||
std::stringstream pre;
|
||||
std::stringstream pre;
|
||||
|
||||
std::string path = endpoint == "/" ? "" : endpoint;
|
||||
|
||||
pre << "5::" << path << ":{\"name\":\"" << eventname << "\",\"args\":" << args << "}";
|
||||
std::string path = endpoint == "/" ? "" : endpoint;
|
||||
|
||||
std::string msg = pre.str();
|
||||
pre << "5::" << path << ":{\"name\":\"" << eventname << "\",\"args\":" << args << "}";
|
||||
|
||||
log("emitting event with data: %s", msg.c_str());
|
||||
std::string msg = pre.str();
|
||||
|
||||
_ws->send(msg);
|
||||
log("emitting event with data: %s", msg.c_str());
|
||||
|
||||
_ws->send(msg);
|
||||
}
|
||||
|
||||
void SIOClientImpl::onOpen(WebSocket* ws)
|
||||
{
|
||||
_connected = true;
|
||||
_connected = true;
|
||||
|
||||
SocketIO::getInstance()->addSocket(_uri, this);
|
||||
SocketIO::getInstance()->addSocket(_uri, this);
|
||||
|
||||
for (auto iter = _clients.begin(); iter != _clients.end(); ++iter)
|
||||
{
|
||||
iter->second->onOpen();
|
||||
}
|
||||
|
||||
Director::getInstance()->getScheduler()->schedule(schedule_selector(SIOClientImpl::heartbeat), this, (_heartbeat * .9f), false);
|
||||
|
||||
log("SIOClientImpl::onOpen socket connected!");
|
||||
Director::getInstance()->getScheduler()->schedule(schedule_selector(SIOClientImpl::heartbeat), this, (_heartbeat * .9f), false);
|
||||
|
||||
log("SIOClientImpl::onOpen socket connected!");
|
||||
}
|
||||
|
||||
void SIOClientImpl::onMessage(WebSocket* ws, const WebSocket::Data& data)
|
||||
{
|
||||
log("SIOClientImpl::onMessage received: %s", data.bytes);
|
||||
log("SIOClientImpl::onMessage received: %s", data.bytes);
|
||||
|
||||
int control = atoi(&data.bytes[0]);
|
||||
int control = atoi(&data.bytes[0]);
|
||||
|
||||
std::string payload, msgid, endpoint, s_data, eventname;
|
||||
payload = data.bytes;
|
||||
std::string payload, msgid, endpoint, s_data, eventname;
|
||||
payload = data.bytes;
|
||||
|
||||
size_t pos, pos2;
|
||||
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 ) {
|
||||
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 ) {
|
||||
msgid = atoi(payload.substr(0, pos+1).c_str());
|
||||
}
|
||||
payload.erase(0, pos+1);
|
||||
|
||||
pos = payload.find(":");
|
||||
if(pos != std::string::npos)
|
||||
pos = payload.find(":");
|
||||
if(pos != std::string::npos)
|
||||
{
|
||||
endpoint = payload.substr(0, pos);
|
||||
payload.erase(0, pos+1);
|
||||
}
|
||||
endpoint = payload.substr(0, pos);
|
||||
payload.erase(0, pos+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
endpoint = payload;
|
||||
}
|
||||
endpoint = payload;
|
||||
}
|
||||
|
||||
if (endpoint == "") endpoint = "/";
|
||||
if (endpoint == "") endpoint = "/";
|
||||
|
||||
|
||||
s_data = payload;
|
||||
SIOClient *c = NULL;
|
||||
c = getClient(endpoint);
|
||||
if (c == NULL) log("SIOClientImpl::onMessage client lookup returned NULL");
|
||||
s_data = payload;
|
||||
SIOClient *c = NULL;
|
||||
c = getClient(endpoint);
|
||||
if (c == NULL) log("SIOClientImpl::onMessage client lookup returned NULL");
|
||||
|
||||
switch(control)
|
||||
switch(control)
|
||||
{
|
||||
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 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());
|
||||
|
||||
if(c)
|
||||
if(c)
|
||||
{
|
||||
eventname = "";
|
||||
pos = s_data.find(":");
|
||||
pos2 = s_data.find(",");
|
||||
if(pos2 > pos)
|
||||
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), '"');
|
||||
}
|
||||
s_data = s_data.substr(pos+1, pos2-pos-1);
|
||||
std::remove_copy(s_data.begin(), s_data.end(),
|
||||
std::back_inserter(eventname), '"');
|
||||
}
|
||||
|
||||
c->fireEvent(eventname, payload);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
c->fireEvent(eventname, payload);
|
||||
}
|
||||
|
||||
return;
|
||||
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;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SIOClientImpl::onClose(WebSocket* ws)
|
||||
|
@ -467,11 +467,11 @@ void SIOClientImpl::onClose(WebSocket* ws)
|
|||
{
|
||||
for (auto iter = _clients.begin(); iter != _clients.end(); ++iter)
|
||||
{
|
||||
iter->second->receivedDisconnect();
|
||||
iter->second->receivedDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
this->release();
|
||||
this->release();
|
||||
}
|
||||
|
||||
void SIOClientImpl::onError(WebSocket* ws, const WebSocket::ErrorCode& error)
|
||||
|
@ -479,104 +479,106 @@ void SIOClientImpl::onError(WebSocket* ws, const WebSocket::ErrorCode& error)
|
|||
}
|
||||
|
||||
//begin SIOClient methods
|
||||
SIOClient::SIOClient(const std::string& host, int port, const std::string& path, SIOClientImpl* impl, SocketIO::SIODelegate& delegate)
|
||||
: _port(port)
|
||||
, _host(host)
|
||||
, _path(path)
|
||||
SIOClient::SIOClient(const std::string& host, int port, const std::string& path, SIOClientImpl* impl, SocketIO::SIODelegate& delegate)
|
||||
: _port(port)
|
||||
, _host(host)
|
||||
, _path(path)
|
||||
, _connected(false)
|
||||
, _socket(impl)
|
||||
, _delegate(&delegate)
|
||||
, _socket(impl)
|
||||
, _delegate(&delegate)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SIOClient::~SIOClient(void)
|
||||
{
|
||||
if (_connected)
|
||||
if (_connected)
|
||||
{
|
||||
_socket->disconnectFromEndpoint(_path);
|
||||
}
|
||||
_socket->disconnectFromEndpoint(_path);
|
||||
}
|
||||
}
|
||||
|
||||
void SIOClient::onOpen()
|
||||
{
|
||||
if (_path != "/")
|
||||
if (_path != "/")
|
||||
{
|
||||
_socket->connectToEndpoint(_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SIOClient::onConnect()
|
||||
{
|
||||
_connected = true;
|
||||
_delegate->onConnect(this);
|
||||
_connected = true;
|
||||
_delegate->onConnect(this);
|
||||
}
|
||||
|
||||
void SIOClient::send(std::string s)
|
||||
{
|
||||
if (_connected)
|
||||
if (_connected)
|
||||
{
|
||||
_socket->send(_path, s);
|
||||
}
|
||||
_socket->send(_path, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
_delegate->onError(this, "Client not yet connected");
|
||||
}
|
||||
_delegate->onError(this, "Client not yet connected");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SIOClient::emit(std::string eventname, std::string args)
|
||||
{
|
||||
if(_connected)
|
||||
if(_connected)
|
||||
{
|
||||
_socket->emit(_path, eventname, args);
|
||||
}
|
||||
_socket->emit(_path, eventname, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
_delegate->onError(this, "Client not yet connected");
|
||||
}
|
||||
_delegate->onError(this, "Client not yet connected");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SIOClient::disconnect()
|
||||
{
|
||||
_connected = false;
|
||||
_connected = false;
|
||||
|
||||
_socket->disconnectFromEndpoint(_path);
|
||||
_socket->disconnectFromEndpoint(_path);
|
||||
|
||||
_delegate->onClose(this);
|
||||
|
||||
this->release();
|
||||
_delegate->onClose(this);
|
||||
|
||||
this->release();
|
||||
}
|
||||
|
||||
void SIOClient::receivedDisconnect()
|
||||
{
|
||||
_connected = false;
|
||||
_connected = false;
|
||||
|
||||
_delegate->onClose(this);
|
||||
_delegate->onClose(this);
|
||||
|
||||
this->release();
|
||||
this->release();
|
||||
}
|
||||
|
||||
void SIOClient::on(const std::string& eventName, SIOEvent e)
|
||||
{
|
||||
_eventRegistry[eventName] = e;
|
||||
_eventRegistry[eventName] = e;
|
||||
}
|
||||
|
||||
void SIOClient::fireEvent(const std::string& eventName, const std::string& data)
|
||||
{
|
||||
log("SIOClient::fireEvent called with event name: %s and data: %s", eventName.c_str(), data.c_str());
|
||||
log("SIOClient::fireEvent called with event name: %s and data: %s", eventName.c_str(), data.c_str());
|
||||
|
||||
if(_eventRegistry[eventName])
|
||||
_delegate->fireEventToScript(this, eventName, data);
|
||||
|
||||
if(_eventRegistry[eventName])
|
||||
{
|
||||
SIOEvent e = _eventRegistry[eventName];
|
||||
SIOEvent e = _eventRegistry[eventName];
|
||||
|
||||
e(this, data);
|
||||
e(this, data);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
log("SIOClient::fireEvent no event with name %s found", eventName.c_str());
|
||||
log("SIOClient::fireEvent no native event with name %s found", eventName.c_str());
|
||||
}
|
||||
|
||||
//begin SocketIO methods
|
||||
|
@ -592,102 +594,109 @@ SocketIO::~SocketIO(void)
|
|||
|
||||
SocketIO* SocketIO::getInstance()
|
||||
{
|
||||
if (nullptr == _inst)
|
||||
if (nullptr == _inst)
|
||||
_inst = new SocketIO();
|
||||
|
||||
return _inst;
|
||||
|
||||
return _inst;
|
||||
}
|
||||
|
||||
void SocketIO::destroyInstance()
|
||||
{
|
||||
CC_SAFE_DELETE(_inst);
|
||||
}
|
||||
|
||||
|
||||
SIOClient* SocketIO::connect(SocketIO::SIODelegate& delegate, const std::string& uri)
|
||||
{
|
||||
std::string host = uri;
|
||||
int port = 0;
|
||||
|
||||
return SocketIO::connect(uri, delegate);
|
||||
|
||||
}
|
||||
|
||||
SIOClient* SocketIO::connect(const std::string& uri, SocketIO::SIODelegate& delegate)
|
||||
{
|
||||
std::string host = uri;
|
||||
int port = 0;
|
||||
size_t pos = 0;
|
||||
|
||||
pos = host.find("//");
|
||||
if (pos != std::string::npos)
|
||||
pos = host.find("//");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
host.erase(0, pos+2);
|
||||
}
|
||||
host.erase(0, pos+2);
|
||||
}
|
||||
|
||||
pos = host.find(":");
|
||||
pos = host.find(":");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
port = atoi(host.substr(pos+1, host.size()).c_str());
|
||||
}
|
||||
|
||||
pos = host.find("/", 0);
|
||||
pos = host.find("/", 0);
|
||||
std::string path = "/";
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
path += host.substr(pos + 1, host.size());
|
||||
}
|
||||
|
||||
pos = host.find(":");
|
||||
pos = host.find(":");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
host.erase(pos, host.size());
|
||||
}
|
||||
else if ((pos = host.find("/")) != std::string::npos)
|
||||
{
|
||||
host.erase(pos, host.size());
|
||||
host.erase(pos, host.size());
|
||||
}
|
||||
|
||||
std::stringstream s;
|
||||
s << host << ":" << port;
|
||||
|
||||
SIOClientImpl* socket = nullptr;
|
||||
SIOClient *c = nullptr;
|
||||
std::stringstream s;
|
||||
s << host << ":" << port;
|
||||
|
||||
socket = SocketIO::getInstance()->getSocket(s.str());
|
||||
SIOClientImpl* socket = nullptr;
|
||||
SIOClient *c = nullptr;
|
||||
|
||||
if(socket == nullptr)
|
||||
socket = SocketIO::getInstance()->getSocket(s.str());
|
||||
|
||||
if(socket == nullptr)
|
||||
{
|
||||
//create a new socket, new client, connect
|
||||
socket = SIOClientImpl::create(host, port);
|
||||
//create a new socket, new client, connect
|
||||
socket = SIOClientImpl::create(host, port);
|
||||
|
||||
c = new SIOClient(host, port, path, socket, delegate);
|
||||
|
||||
socket->addClient(path, c);
|
||||
c = new SIOClient(host, port, path, socket, delegate);
|
||||
|
||||
socket->connect();
|
||||
}
|
||||
socket->addClient(path, c);
|
||||
|
||||
socket->connect();
|
||||
}
|
||||
else
|
||||
{
|
||||
//check if already connected to endpoint, handle
|
||||
c = socket->getClient(path);
|
||||
//check if already connected to endpoint, handle
|
||||
c = socket->getClient(path);
|
||||
|
||||
if(c == NULL)
|
||||
if(c == NULL)
|
||||
{
|
||||
c = new SIOClient(host, port, path, socket, delegate);
|
||||
|
||||
socket->addClient(path, c);
|
||||
c = new SIOClient(host, port, path, socket, delegate);
|
||||
|
||||
socket->connectToEndpoint(path);
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
socket->addClient(path, c);
|
||||
|
||||
socket->connectToEndpoint(path);
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
SIOClientImpl* SocketIO::getSocket(const std::string& uri)
|
||||
{
|
||||
return _sockets.at(uri);
|
||||
return _sockets.at(uri);
|
||||
}
|
||||
|
||||
void SocketIO::addSocket(const std::string& uri, SIOClientImpl* socket)
|
||||
{
|
||||
_sockets.insert(uri, socket);
|
||||
_sockets.insert(uri, socket);
|
||||
}
|
||||
|
||||
void SocketIO::removeSocket(const std::string& uri)
|
||||
{
|
||||
_sockets.erase(uri);
|
||||
_sockets.erase(uri);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013 Chris Hannon http://www.channon.us
|
||||
Copyright (c) 2013-2014 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
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
|
@ -27,32 +27,32 @@ Usage is described below, a full working example can be found in TestCpp under E
|
|||
|
||||
creating a new connection to a socket.io server running at localhost:3000
|
||||
|
||||
SIOClient *client = SocketIO::connect(*delegate, "ws://localhost:3000");
|
||||
SIOClient *client = SocketIO::connect(*delegate, "ws://localhost:3000");
|
||||
|
||||
the connection process will begin and if successful delegate::onOpen will be called
|
||||
if the connection process results in an error, delegate::onError will be called with the err msg
|
||||
|
||||
sending a message to the server
|
||||
|
||||
client->send("Hello!");
|
||||
client->send("Hello!");
|
||||
|
||||
emitting an event to be handled by the server, argument json formatting is up to you
|
||||
|
||||
client->emit("eventname", "[{\"arg\":\"value\"}]");
|
||||
client->emit("eventname", "[{\"arg\":\"value\"}]");
|
||||
|
||||
registering an event callback, target should be a member function in a subclass of SIODelegate
|
||||
CC_CALLBACK_2 is used to wrap the callback with std::bind and store as an SIOEvent
|
||||
|
||||
client->on("eventname", CC_CALLBACK_2(TargetClass::targetfunc, *targetclass_instance));
|
||||
client->on("eventname", CC_CALLBACK_2(TargetClass::targetfunc, *targetclass_instance));
|
||||
|
||||
event target function should match this pattern, *this pointer will be made available
|
||||
|
||||
void TargetClass::targetfunc(SIOClient *, const std::string&)
|
||||
void TargetClass::targetfunc(SIOClient *, const std::string&)
|
||||
|
||||
disconnect from the endpoint by calling disconnect(), onClose will be called on the delegate once complete
|
||||
in the onClose method the pointer should be set to NULL or used to connect to a new endpoint
|
||||
|
||||
client->disconnect();
|
||||
client->disconnect();
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -78,44 +78,47 @@ class SIOClient;
|
|||
class SocketIO
|
||||
{
|
||||
public:
|
||||
static SocketIO* getInstance();
|
||||
static SocketIO* getInstance();
|
||||
static void destroyInstance();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief The delegate class to process socket.io events
|
||||
*/
|
||||
class SIODelegate
|
||||
class SIODelegate
|
||||
{
|
||||
public:
|
||||
virtual ~SIODelegate() {}
|
||||
virtual void onConnect(SIOClient* client) = 0;
|
||||
virtual void onConnect(SIOClient* client) = 0;
|
||||
virtual void onMessage(SIOClient* client, const std::string& data) = 0;
|
||||
virtual void onClose(SIOClient* client) = 0;
|
||||
virtual void onError(SIOClient* client, const std::string& data) = 0;
|
||||
virtual void fireEventToScript(SIOClient* client, const std::string& eventName, const std::string& data) { CCLOG("SIODelegate event '%s' fired with data: %s", eventName.c_str(), data.c_str()); };
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Static client creation method, similar to socketio.connect(uri) in JS
|
||||
* @param delegate The delegate which want to receive events from the socket.io client
|
||||
* @param uri The URI of the socket.io server
|
||||
* @return An initialized SIOClient if connected successfully, otherwise NULL
|
||||
*/
|
||||
static SIOClient* connect(SocketIO::SIODelegate& delegate, const std::string& uri);
|
||||
|
||||
static SIOClient* connect(const std::string& uri, SocketIO::SIODelegate& delegate);
|
||||
|
||||
CC_DEPRECATED_ATTRIBUTE static SIOClient* connect(SocketIO::SIODelegate& delegate, const std::string& uri);
|
||||
|
||||
private:
|
||||
|
||||
SocketIO();
|
||||
virtual ~SocketIO(void);
|
||||
|
||||
static SocketIO *_inst;
|
||||
virtual ~SocketIO(void);
|
||||
|
||||
cocos2d::Map<std::string, SIOClientImpl*> _sockets;
|
||||
static SocketIO *_inst;
|
||||
|
||||
SIOClientImpl* getSocket(const std::string& uri);
|
||||
void addSocket(const std::string& uri, SIOClientImpl* socket);
|
||||
void removeSocket(const std::string& uri);
|
||||
cocos2d::Map<std::string, SIOClientImpl*> _sockets;
|
||||
|
||||
friend class SIOClientImpl;
|
||||
SIOClientImpl* getSocket(const std::string& uri);
|
||||
void addSocket(const std::string& uri, SIOClientImpl* socket);
|
||||
void removeSocket(const std::string& uri);
|
||||
|
||||
friend class SIOClientImpl;
|
||||
private:
|
||||
CC_DISALLOW_COPY_AND_ASSIGN(SocketIO)
|
||||
};
|
||||
|
@ -129,59 +132,59 @@ typedef std::unordered_map<std::string, SIOEvent> EventRegistry;
|
|||
* @brief A single connection to a socket.io endpoint
|
||||
*/
|
||||
class SIOClient
|
||||
: public cocos2d::Ref
|
||||
: public cocos2d::Ref
|
||||
{
|
||||
private:
|
||||
int _port;
|
||||
std::string _host, _path, _tag;
|
||||
bool _connected;
|
||||
SIOClientImpl* _socket;
|
||||
int _port;
|
||||
std::string _host, _path, _tag;
|
||||
bool _connected;
|
||||
SIOClientImpl* _socket;
|
||||
|
||||
SocketIO::SIODelegate* _delegate;
|
||||
SocketIO::SIODelegate* _delegate;
|
||||
|
||||
EventRegistry _eventRegistry;
|
||||
EventRegistry _eventRegistry;
|
||||
|
||||
void fireEvent(const std::string& eventName, const std::string& data);
|
||||
void fireEvent(const std::string& eventName, const std::string& data);
|
||||
|
||||
void onOpen();
|
||||
void onConnect();
|
||||
void receivedDisconnect();
|
||||
void onOpen();
|
||||
void onConnect();
|
||||
void receivedDisconnect();
|
||||
|
||||
friend class SIOClientImpl;
|
||||
friend class SIOClientImpl;
|
||||
|
||||
public:
|
||||
SIOClient(const std::string& host, int port, const std::string& path, SIOClientImpl* impl, SocketIO::SIODelegate& delegate);
|
||||
virtual ~SIOClient(void);
|
||||
SIOClient(const std::string& host, int port, const std::string& path, SIOClientImpl* impl, SocketIO::SIODelegate& delegate);
|
||||
virtual ~SIOClient(void);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Returns the delegate for the client
|
||||
*/
|
||||
SocketIO::SIODelegate* getDelegate() { return _delegate; };
|
||||
SocketIO::SIODelegate* getDelegate() { return _delegate; };
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Disconnect from the endpoint, onClose will be called on the delegate when comlpete
|
||||
*/
|
||||
void disconnect();
|
||||
/**
|
||||
void disconnect();
|
||||
/**
|
||||
* @brief Send a message to the socket.io server
|
||||
*/
|
||||
void send(std::string s);
|
||||
/**
|
||||
void send(std::string s);
|
||||
/**
|
||||
* @brief The delegate class to process socket.io events
|
||||
*/
|
||||
void emit(std::string eventname, std::string args);
|
||||
/**
|
||||
void emit(std::string eventname, std::string args);
|
||||
/**
|
||||
* @brief Used to resgister a socket.io event callback
|
||||
* Event argument should be passed using CC_CALLBACK2(&Base::function, this)
|
||||
* Event argument should be passed using CC_CALLBACK2(&Base::function, this)
|
||||
*/
|
||||
void on(const std::string& eventName, SIOEvent e);
|
||||
|
||||
inline void setTag(const char* tag)
|
||||
void on(const std::string& eventName, SIOEvent e);
|
||||
|
||||
inline void setTag(const char* tag)
|
||||
{
|
||||
_tag = tag;
|
||||
};
|
||||
|
||||
inline const char* getTag()
|
||||
|
||||
inline const char* getTag()
|
||||
{
|
||||
return _tag.c_str();
|
||||
};
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
|
@ -59,7 +59,7 @@ public:
|
|||
* @lua NA
|
||||
*/
|
||||
virtual ~WebSocket();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Data structure for message
|
||||
*/
|
||||
|
@ -70,7 +70,7 @@ public:
|
|||
ssize_t len, issued;
|
||||
bool isBinary;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Errors in websocket
|
||||
*/
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
CONNECTION_FAILURE,
|
||||
UNKNOWN,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Websocket state
|
||||
*/
|
||||
|
@ -104,8 +104,8 @@ public:
|
|||
virtual void onClose(WebSocket* ws) = 0;
|
||||
virtual void onError(WebSocket* ws, const ErrorCode& error) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The initialized method for websocket.
|
||||
* It needs to be invoked right after websocket instance is allocated.
|
||||
|
@ -116,53 +116,53 @@ public:
|
|||
bool init(const Delegate& delegate,
|
||||
const std::string& url,
|
||||
const std::vector<std::string>* protocols = nullptr);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sends string data to websocket server.
|
||||
*/
|
||||
void send(const std::string& message);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sends binary data to websocket server.
|
||||
*/
|
||||
void send(const unsigned char* binaryMsg, unsigned int len);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Closes the connection to server.
|
||||
*/
|
||||
void close();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets current state of connection.
|
||||
*/
|
||||
State getReadyState();
|
||||
|
||||
|
||||
private:
|
||||
virtual void onSubThreadStarted();
|
||||
virtual int onSubThreadLoop();
|
||||
virtual void onSubThreadEnded();
|
||||
virtual void onUIThreadReceiveMessage(WsMessage* msg);
|
||||
|
||||
|
||||
|
||||
friend class WebSocketCallbackWrapper;
|
||||
int onSocketCallback(struct libwebsocket_context *ctx,
|
||||
struct libwebsocket *wsi,
|
||||
int reason,
|
||||
void *user, void *in, ssize_t len);
|
||||
|
||||
|
||||
private:
|
||||
State _readyState;
|
||||
State _readyState;
|
||||
std::string _host;
|
||||
unsigned int _port;
|
||||
std::string _path;
|
||||
|
||||
|
||||
ssize_t _pendingFrameDataLen;
|
||||
ssize_t _currentDataLen;
|
||||
char *_currentData;
|
||||
|
||||
friend class WsThreadHelper;
|
||||
WsThreadHelper* _wsHelper;
|
||||
|
||||
|
||||
struct libwebsocket* _wsInstance;
|
||||
struct libwebsocket_context* _wsContext;
|
||||
Delegate* _delegate;
|
||||
|
|
Loading…
Reference in New Issue