947 lines
31 KiB
C++
947 lines
31 KiB
C++
/****************************************************************************
|
|
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
|
|
|
http://www.cocos.com
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated engine source code (the "Software"), a limited,
|
|
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
|
to use Cocos Creator solely to develop games on your target platforms. You shall
|
|
not use Cocos Creator software for developing other software or tools that's
|
|
used for developing games. You are not granted to publish, distribute,
|
|
sublicense, and/or sell copies of Cocos Creator.
|
|
|
|
The software or tools in this License Agreement are licensed, not sold.
|
|
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
|
|
|
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
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
****************************************************************************/
|
|
#include "base/ccConfig.h"
|
|
|
|
#if (USE_SOCKET > 0) && (USE_WEBSOCKET_SERVER > 0) && (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
|
|
|
#include "jsb_websocket_server.hpp"
|
|
#include "uv/uv.h"
|
|
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
|
|
#include "cocos/scripting/js-bindings/manual/jsb_conversions.hpp"
|
|
#include "cocos/scripting/js-bindings/manual/jsb_global.h"
|
|
#include "cocos/network/WebSocketServer.h"
|
|
|
|
|
|
using namespace cocos2d;
|
|
using namespace cocos2d::network;
|
|
|
|
se::Class* __jsb_WebSocketServer_class = nullptr;
|
|
se::Class* __jsb_WebSocketServer_Connection_class = nullptr;
|
|
|
|
typedef std::shared_ptr<WebSocketServer>* WSSPTR;
|
|
typedef std::shared_ptr<WebSocketServerConnection>* WSCONNPTR;
|
|
|
|
static int __sendIndex = 1;
|
|
|
|
static std::string gen_send_index() {
|
|
char buf[128] = { 0 };
|
|
snprintf(buf, 127, "__send_[%d]", __sendIndex++);
|
|
return buf;
|
|
}
|
|
|
|
static bool WebSocketServer_finalize(se::State& s)
|
|
{
|
|
WSSPTR cobj = (WSSPTR)s.nativeThisObject();
|
|
CCLOGINFO("jsbindings: finalizing JS object %p (WebSocketServer)", cobj);
|
|
delete cobj;
|
|
return true;
|
|
}
|
|
SE_BIND_FINALIZE_FUNC(WebSocketServer_finalize)
|
|
|
|
static bool WebSocketServer_constructor(se::State& s)
|
|
{
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if(argc == 0)
|
|
{
|
|
se::Object* obj = s.thisObject();
|
|
WSSPTR cobj = new std::shared_ptr<WebSocketServer>(new WebSocketServer());
|
|
obj->setPrivateData(cobj);
|
|
(*cobj)->setData(obj);
|
|
|
|
(*cobj)->setOnBegin([obj]() {
|
|
obj->root();
|
|
});
|
|
|
|
(*cobj)->setOnEnd([obj]() {
|
|
obj->unroot();
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
|
|
return false;
|
|
}
|
|
SE_BIND_CTOR(WebSocketServer_constructor, __jsb_WebSocketServer_class, WebSocketServer_finalize)
|
|
|
|
static bool WebSocketServer_listen(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (argc == 0)
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1,2,3", argc);
|
|
return false;
|
|
}
|
|
|
|
WSSPTR cobj = (WSSPTR)s.nativeThisObject();
|
|
int arg_port = 0;
|
|
std::string arg_host = "";
|
|
std::function<void(const std::string&)> arg_callback;
|
|
|
|
bool ok;
|
|
|
|
if (argc >= 1) { // port
|
|
ok = seval_to_int32(args[0], &arg_port);
|
|
SE_PRECONDITION2(ok, false, "Convert args[0] to port failed");
|
|
}
|
|
if (argc >= 2) { // host or callback
|
|
if (args[1].isString()) { //to host
|
|
ok = seval_to_std_string(args[1], &arg_host);
|
|
SE_PRECONDITION2(ok, false, "Convert args[1] to host failed");
|
|
}
|
|
se::Object* funObj = nullptr;
|
|
if (args[1].isObject() && args[1].toObject()->isFunction()) {
|
|
funObj = args[1].toObject();
|
|
}
|
|
|
|
if (argc > 2 && args[2].isObject() && args[2].toObject()->isFunction())
|
|
{
|
|
funObj = args[2].toObject();
|
|
}
|
|
if (funObj) {
|
|
s.thisObject()->setProperty("__onlisten", se::Value(funObj));
|
|
std::weak_ptr<WebSocketServer> serverWeak = *cobj;
|
|
arg_callback = [serverWeak](const std::string &err) {
|
|
se::AutoHandleScope hs;
|
|
|
|
auto serverPtr = serverWeak.lock();
|
|
if (!serverPtr) {
|
|
return;
|
|
}
|
|
se::Object *sobj = (se::Object*) serverPtr->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
se::Value callback;
|
|
if (!sobj->getProperty("__onlisten", &callback))
|
|
{
|
|
SE_REPORT_ERROR("onlisten attribute not set!");
|
|
return;
|
|
}
|
|
|
|
se::ValueArray args;
|
|
if(!err.empty())
|
|
{
|
|
args.push_back(se::Value(err));
|
|
}
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
};
|
|
|
|
}
|
|
}
|
|
|
|
WebSocketServer::listenAsync(*cobj, arg_port, arg_host, arg_callback);
|
|
return true;
|
|
}
|
|
SE_BIND_FUNC(WebSocketServer_listen)
|
|
|
|
static bool WebSocketServer_onconnection(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (!(argc ==1 && args[0].isObject() && args[0].toObject()->isFunction()))
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
|
|
return false;
|
|
}
|
|
|
|
WSSPTR cobj = (WSSPTR)s.nativeThisObject();
|
|
s.thisObject()->setProperty("__onconnection", args[0]);
|
|
std::weak_ptr<WebSocketServer> serverWeak = *cobj;
|
|
|
|
cobj->get()->setOnConnection([serverWeak](std::shared_ptr<WebSocketServerConnection> conn) {
|
|
se::AutoHandleScope hs;
|
|
|
|
auto server = serverWeak.lock();
|
|
if (!server) {
|
|
return;
|
|
}
|
|
se::Object* sobj= (se::Object*)server->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
se::Value callback;
|
|
if (!sobj->getProperty("__onconnection", &callback)) {
|
|
SE_REPORT_ERROR("onconnection callback not found!");
|
|
return;
|
|
}
|
|
|
|
se::Object* obj = se::Object::createObjectWithClass(__jsb_WebSocketServer_Connection_class);
|
|
WSCONNPTR prv = new std::shared_ptr<WebSocketServerConnection>(conn);
|
|
// a connection is dead only if no reference & closed!
|
|
obj->root();
|
|
obj->setPrivateData(prv);
|
|
conn->setData(obj);
|
|
std::weak_ptr<WebSocketServerConnection> connWeak = conn;
|
|
prv->get()->setOnEnd([connWeak]() {
|
|
// release we connection is gone!
|
|
auto ptr = connWeak.lock();
|
|
if (ptr) {
|
|
se::Object* sobj = (se::Object*)ptr->getData();
|
|
sobj->unroot();
|
|
}
|
|
});
|
|
se::ValueArray args;
|
|
args.push_back(se::Value(obj));
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);;
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
SE_BIND_PROP_SET(WebSocketServer_onconnection)
|
|
|
|
static bool WebSocketServer_onclose(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (argc != 1)
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1", argc);
|
|
return false;
|
|
}
|
|
if(!(args[0].isObject() && args[0].toObject()->isFunction())){
|
|
SE_REPORT_ERROR("argument type error, function expected!");
|
|
}
|
|
|
|
WSSPTR cobj = (WSSPTR)s.nativeThisObject();
|
|
std::function<void(const std::string&)> callback;
|
|
std::weak_ptr<WebSocketServer> serverWeak = *cobj;
|
|
s.thisObject()->setProperty("__onclose", args[0]);
|
|
|
|
callback = [serverWeak](const std::string& err) {
|
|
se::AutoHandleScope hs;
|
|
|
|
auto server = serverWeak.lock();
|
|
if (!server) {
|
|
return;
|
|
}
|
|
se::Object* sobj = (se::Object*)server->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
se::Value callback;
|
|
if (!sobj->getProperty("__onclose", &callback)) {
|
|
SE_REPORT_ERROR("onclose callback not found!");
|
|
return;
|
|
}
|
|
|
|
se::ValueArray args;
|
|
if (!err.empty())
|
|
{
|
|
args.push_back(se::Value(err));
|
|
}
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
};
|
|
(*cobj)->setOnClose(callback);
|
|
|
|
return true;
|
|
|
|
}
|
|
SE_BIND_PROP_SET(WebSocketServer_onclose)
|
|
|
|
static bool WebSocketServer_close(se::State& s)
|
|
{
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (argc > 1)
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0, 1", argc);
|
|
return false;
|
|
}
|
|
|
|
|
|
WSSPTR cobj = (WSSPTR)s.nativeThisObject();
|
|
std::function<void(const std::string&)> callback;
|
|
|
|
if (argc == 1) {
|
|
if(args[0].isObject() && args[0].toObject()->isFunction()) {
|
|
|
|
s.thisObject()->setProperty("__close", args[0]);
|
|
std::weak_ptr<WebSocketServer> serverWeak = *cobj;
|
|
|
|
callback = [serverWeak](const std::string& err) {
|
|
se::AutoHandleScope hs;
|
|
|
|
auto server = serverWeak.lock();
|
|
if (!server) {
|
|
return;
|
|
}
|
|
se::Object* sobj = (se::Object*)server->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
se::Value callback;
|
|
if (!sobj->getProperty("__close", &callback)) {
|
|
SE_REPORT_ERROR("onclose callback not found!");
|
|
return;
|
|
}
|
|
|
|
se::ValueArray args;
|
|
if (!err.empty())
|
|
{
|
|
args.push_back(se::Value(err));
|
|
}
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
};
|
|
(*cobj)->closeAsync(callback);
|
|
}
|
|
else {
|
|
SE_REPORT_ERROR("wrong argument type, function expected");
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
(*cobj)->closeAsync();
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
SE_BIND_FUNC(WebSocketServer_close)
|
|
|
|
|
|
static bool WebSocketServer_connections(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
|
|
if (argc == 0)
|
|
{
|
|
WSSPTR cobj = (WSSPTR)s.nativeThisObject();
|
|
auto conns = cobj->get()->getConnections();
|
|
se::Object* ret = se::Object::createArrayObject(conns.size());
|
|
for (auto i = 0;i < conns.size(); i++) {
|
|
std::shared_ptr<WebSocketServerConnection>& con = conns[i];
|
|
se::Object *obj = (se::Object*)con->getData();
|
|
ret->setArrayElement(i, se::Value(obj));
|
|
}
|
|
s.rval().setObject(ret);
|
|
return true;
|
|
}
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
|
|
return false;
|
|
}
|
|
SE_BIND_PROP_GET(WebSocketServer_connections)
|
|
|
|
|
|
static bool WebSocketServer_Connection_finalize(se::State& s)
|
|
{
|
|
WSCONNPTR cob = (WSCONNPTR)s.nativeThisObject();
|
|
CCLOGINFO("jsbindings: finalizing JS object %p (WebSocketServer_Connection)", cobj);
|
|
delete cob;
|
|
return true;
|
|
}
|
|
SE_BIND_FINALIZE_FUNC(WebSocketServer_Connection_finalize)
|
|
|
|
static bool WebSocketServer_Connection_constructor(se::State& s)
|
|
{
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (argc == 0)
|
|
{
|
|
se::Object* obj = s.thisObject();
|
|
//private data should be set when connected
|
|
return true;
|
|
}
|
|
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
|
|
return false;
|
|
}
|
|
SE_BIND_CTOR(WebSocketServer_Connection_constructor, __jsb_WebSocketServer_Connection_class, WebSocketServer_Connection_finalize)
|
|
|
|
static bool WebSocketServer_Connection_send(se::State& s)
|
|
{
|
|
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
|
|
if (!cobj) {
|
|
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
|
|
return false;
|
|
}
|
|
|
|
if (argc >= 1)
|
|
{
|
|
std::function<void(const std::string & cb)> callback;
|
|
if (args[argc - 1].isObject() && args[argc - 1].toObject()->isFunction())
|
|
{
|
|
std::string callbackId = gen_send_index();
|
|
s.thisObject()->setProperty(callbackId.c_str(), args[argc - 1]);
|
|
std::weak_ptr<WebSocketServerConnection> connWeak = *cobj;
|
|
|
|
callback = [callbackId, connWeak](const std::string& err) {
|
|
se::AutoHandleScope hs;
|
|
auto conn = connWeak.lock();
|
|
if (!conn) {
|
|
return;
|
|
}
|
|
se::Object* sobj = (se::Object*)conn->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
se::Value callback;
|
|
if (!sobj->getProperty(callbackId.c_str(), &callback)) {
|
|
SE_REPORT_ERROR("send[%s] callback not found!", callbackId.c_str());
|
|
return;
|
|
}
|
|
se::ValueArray args;
|
|
if (!err.empty())
|
|
{
|
|
args.push_back(se::Value(err));
|
|
}
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
sobj->deleteProperty(callbackId.c_str());
|
|
};
|
|
}
|
|
|
|
bool ok = false;
|
|
if (args[0].isString())
|
|
{
|
|
std::string data;
|
|
ok = seval_to_std_string(args[0], &data);
|
|
SE_PRECONDITION2(ok, false, "Convert string failed");
|
|
(*cobj)->sendTextAsync(data, callback);
|
|
}
|
|
else if (args[0].isObject())
|
|
{
|
|
se::Object* dataObj = args[0].toObject();
|
|
uint8_t* ptr = nullptr;
|
|
size_t length = 0;
|
|
if (dataObj->isArrayBuffer())
|
|
{
|
|
ok = dataObj->getArrayBufferData(&ptr, &length);
|
|
SE_PRECONDITION2(ok, false, "getArrayBufferData failed!");
|
|
}
|
|
else if (dataObj->isTypedArray())
|
|
{
|
|
ok = dataObj->getTypedArrayData(&ptr, &length);
|
|
SE_PRECONDITION2(ok, false, "getTypedArrayData failed!");
|
|
}
|
|
else
|
|
{
|
|
assert(false);
|
|
}
|
|
|
|
(*cobj)->sendBinaryAsync(ptr, (unsigned int)length, callback);
|
|
}
|
|
else
|
|
{
|
|
assert(false);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1", argc);
|
|
return false;
|
|
}
|
|
SE_BIND_FUNC(WebSocketServer_Connection_send)
|
|
|
|
|
|
|
|
static bool WebSocketServer_Connection_close(se::State& s)
|
|
{
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (argc > 1)
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0, 1", argc);
|
|
return false;
|
|
}
|
|
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
|
|
if (!cobj) {
|
|
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
|
|
return false;
|
|
}
|
|
|
|
std::function<void(const std::string&)> callback;
|
|
int arg_code = -1;
|
|
std::string arg_reason;
|
|
bool ok;
|
|
|
|
if (argc >= 1) {
|
|
|
|
ok = seval_to_int32(args[0], &arg_code);
|
|
SE_PRECONDITION2(ok, false, "Convert args[0] should be a number");
|
|
|
|
if (argc >= 2) {
|
|
|
|
ok = seval_to_std_string(args[1], &arg_reason);
|
|
SE_PRECONDITION2(ok, false, "Convert args[1] should be a string");
|
|
}
|
|
}
|
|
|
|
if (arg_code > 0 && !arg_reason.empty()) {
|
|
(*cobj)->closeAsync(arg_code, arg_reason);
|
|
}
|
|
else if (arg_code > 0) {
|
|
(*cobj)->closeAsync(arg_code, "unknown reason");
|
|
}
|
|
else {
|
|
(*cobj)->closeAsync(1000, "default close reason");
|
|
}
|
|
return true;
|
|
}
|
|
SE_BIND_FUNC(WebSocketServer_Connection_close)
|
|
|
|
|
|
static bool WebSocketServer_Connection_onconnect(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction()))
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
|
|
return false;
|
|
}
|
|
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
if (!cobj) {
|
|
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
|
|
return false;
|
|
}
|
|
|
|
s.thisObject()->setProperty("__onconnect", args[0]);
|
|
|
|
std::weak_ptr<WebSocketServerConnection> connWeak = *cobj;
|
|
|
|
cobj->get()->setOnConnect([connWeak]() {
|
|
se::AutoHandleScope hs;
|
|
auto conn = connWeak.lock();
|
|
if (!conn) {
|
|
return;
|
|
}
|
|
se::Object* sobj = (se::Object*)conn->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
se::Value callback;
|
|
if (!sobj->getProperty("__onconnect", &callback)) {
|
|
SE_REPORT_ERROR("__onconnect callback not found!");
|
|
return;
|
|
}
|
|
se::ValueArray args;
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);;
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
SE_BIND_PROP_SET(WebSocketServer_Connection_onconnect)
|
|
|
|
|
|
static bool WebSocketServer_Connection_onerror(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction()))
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
|
|
return false;
|
|
}
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
|
|
if (!cobj) {
|
|
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
|
|
return false;
|
|
}
|
|
|
|
s.thisObject()->setProperty("__onerror", args[0]);
|
|
std::weak_ptr<WebSocketServerConnection> connWeak = *cobj;
|
|
|
|
cobj->get()->setOnError([connWeak](const std::string &err) {
|
|
se::AutoHandleScope hs;
|
|
auto conn = connWeak.lock();
|
|
if (!conn) {
|
|
return;
|
|
}
|
|
se::Object* sobj = (se::Object*)conn->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
se::Value callback;
|
|
if (!sobj->getProperty("__onerror", &callback)) {
|
|
SE_REPORT_ERROR("__onerror callback not found!");
|
|
return;
|
|
}
|
|
se::ValueArray args;
|
|
if (!err.empty())
|
|
{
|
|
args.push_back(se::Value(err));
|
|
}
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);;
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
SE_BIND_PROP_SET(WebSocketServer_Connection_onerror)
|
|
|
|
|
|
static bool WebSocketServer_Connection_onclose(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction()))
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
|
|
return false;
|
|
}
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
|
|
if (!cobj) {
|
|
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
|
|
return false;
|
|
}
|
|
|
|
s.thisObject()->setProperty("__onclose", args[0]);
|
|
std::weak_ptr<WebSocketServerConnection> connWeak = *cobj;
|
|
|
|
cobj->get()->setOnClose([connWeak](int code, const std::string& err) {
|
|
se::AutoHandleScope hs;
|
|
|
|
auto conn = connWeak.lock();
|
|
if (!conn) {
|
|
return;
|
|
}
|
|
se::Object* sobj = (se::Object*)conn->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
se::Value callback;
|
|
if (!sobj->getProperty("__onclose", &callback)) {
|
|
SE_REPORT_ERROR("__onclose callback not found!");
|
|
return;
|
|
}
|
|
|
|
se::ValueArray args;
|
|
args.push_back(se::Value(code));
|
|
if (!err.empty())
|
|
{
|
|
args.push_back(se::Value(err));
|
|
}
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);;
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
SE_BIND_PROP_SET(WebSocketServer_Connection_onclose)
|
|
|
|
static bool WebSocketServer_Connection_ontext(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction()))
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
|
|
return false;
|
|
}
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
|
|
if (!cobj) {
|
|
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
|
|
return false;
|
|
}
|
|
|
|
s.thisObject()->setProperty("__ontext", args[0]);
|
|
std::weak_ptr<WebSocketServerConnection> connWeak = *cobj;
|
|
|
|
cobj->get()->setOnText([connWeak](const std::shared_ptr<DataFrame> text) {
|
|
se::AutoHandleScope hs;
|
|
|
|
auto conn = connWeak.lock();
|
|
if (!conn) {
|
|
return;
|
|
}
|
|
se::Object* sobj = (se::Object*)conn->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
se::Value callback;
|
|
if (!sobj->getProperty("__ontext", &callback)) {
|
|
SE_REPORT_ERROR("__ontext callback not found!");
|
|
return;
|
|
}
|
|
|
|
se::ValueArray args;
|
|
args.push_back(se::Value(text->toString()));
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);;
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
SE_BIND_PROP_SET(WebSocketServer_Connection_ontext)
|
|
|
|
static bool WebSocketServer_Connection_onbinary(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction()))
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
|
|
return false;
|
|
}
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
|
|
if (!cobj) {
|
|
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
|
|
return false;
|
|
}
|
|
|
|
s.thisObject()->setProperty("__onbinary", args[0]);
|
|
std::weak_ptr<WebSocketServerConnection> connWeak = *cobj;
|
|
|
|
cobj->get()->setOnBinary([connWeak](const std::shared_ptr<DataFrame> text) {
|
|
se::AutoHandleScope hs;
|
|
auto conn = connWeak.lock();
|
|
if (!conn) {
|
|
return;
|
|
}
|
|
se::Object* sobj = (se::Object*)conn->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
se::Value callback;
|
|
if (!sobj->getProperty("__onbinary", &callback)) {
|
|
SE_REPORT_ERROR("__onbinary callback not found!");
|
|
return;
|
|
}
|
|
|
|
se::ValueArray args;
|
|
se::Object* buffer = se::Object::createArrayBufferObject(text->getData(), text->size());
|
|
args.push_back(se::Value(buffer));
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);;
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
SE_BIND_PROP_SET(WebSocketServer_Connection_onbinary)
|
|
|
|
|
|
|
|
static bool WebSocketServer_Connection_ondata(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
if (!(argc == 1 && args[0].isObject() && args[0].toObject()->isFunction()))
|
|
{
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 1 & function", argc);
|
|
return false;
|
|
}
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
|
|
if (!cobj) {
|
|
SE_REPORT_ERROR("Connection is not constructed by WebSocketServer, invalidate format!!");
|
|
return false;
|
|
}
|
|
|
|
s.thisObject()->setProperty("__ondata", args[0]);
|
|
std::weak_ptr<WebSocketServerConnection> connWeak = *cobj;
|
|
|
|
cobj->get()->setOnData([connWeak](const std::shared_ptr<DataFrame> text) {
|
|
se::AutoHandleScope hs;
|
|
|
|
auto connPtr = connWeak.lock();
|
|
if (!connPtr) {
|
|
return;
|
|
}
|
|
se::Object *sobj = (se::Object*) connPtr->getData();
|
|
if (!sobj) {
|
|
return;
|
|
}
|
|
|
|
se::Value callback;
|
|
if (!sobj->getProperty("__ondata", &callback)) {
|
|
return;
|
|
}
|
|
|
|
se::ValueArray args;
|
|
if(text->isBinary())
|
|
{
|
|
se::Object* buffer = se::Object::createArrayBufferObject(text->getData(), text->size());
|
|
args.push_back(se::Value(buffer));
|
|
}
|
|
else if (text->isString())
|
|
{
|
|
args.push_back(se::Value(text->toString()));
|
|
}
|
|
bool success = callback.toObject()->call(args, sobj, nullptr);;
|
|
if (!success) {
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
SE_BIND_PROP_SET(WebSocketServer_Connection_ondata)
|
|
|
|
|
|
static bool WebSocketServer_Connection_headers(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
|
|
if (argc == 0)
|
|
{
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
auto headers = cobj->get()->getHeaders();
|
|
se::Object* ret = se::Object::createPlainObject();
|
|
for (auto &itr : headers) {
|
|
ret->setProperty(itr.first.c_str(), se::Value(itr.second));
|
|
}
|
|
s.rval().setObject(ret);
|
|
return true;
|
|
}
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
|
|
return false;
|
|
}
|
|
SE_BIND_PROP_GET(WebSocketServer_Connection_headers)
|
|
|
|
static bool WebSocketServer_Connection_protocols(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
|
|
if (argc == 0)
|
|
{
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
auto protocols= cobj->get()->getProtocols();
|
|
se::Object* ret = se::Object::createArrayObject(protocols.size());
|
|
for (int i = 0; i < protocols.size(); i++) {
|
|
ret->setArrayElement(i, se::Value(protocols[i]));
|
|
}
|
|
s.rval().setObject(ret);
|
|
return true;
|
|
}
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
|
|
return false;
|
|
}
|
|
SE_BIND_PROP_GET(WebSocketServer_Connection_protocols)
|
|
|
|
|
|
static bool WebSocketServer_Connection_protocol(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
|
|
if (argc == 0)
|
|
{
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
auto protocols = cobj->get()->getProtocols();
|
|
if (protocols.size() > 0) {
|
|
s.rval().setString(protocols[0]);
|
|
}
|
|
else {
|
|
s.rval().setUndefined();
|
|
}
|
|
return true;
|
|
}
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
|
|
return false;
|
|
}
|
|
SE_BIND_PROP_GET(WebSocketServer_Connection_protocol)
|
|
|
|
static bool WebSocketServer_Connection_readyState(se::State& s) {
|
|
const auto& args = s.args();
|
|
int argc = (int)args.size();
|
|
|
|
if (argc == 0)
|
|
{
|
|
WSCONNPTR cobj = (WSCONNPTR)s.nativeThisObject();
|
|
auto state = cobj->get()->getReadyState();
|
|
s.rval().setInt32(state);
|
|
return true;
|
|
}
|
|
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting 0", argc);
|
|
return false;
|
|
}
|
|
SE_BIND_PROP_GET(WebSocketServer_Connection_readyState)
|
|
|
|
|
|
bool register_all_websocket_server(se::Object* obj)
|
|
{
|
|
se::Class* cls = se::Class::create("WebSocketServer", obj, nullptr, _SE(WebSocketServer_constructor));
|
|
cls->defineFinalizeFunction(_SE(WebSocketServer_finalize));
|
|
|
|
cls->defineFunction("close", _SE(WebSocketServer_close));
|
|
cls->defineFunction("listen", _SE(WebSocketServer_listen));
|
|
cls->defineProperty("onconnection", nullptr, _SE(WebSocketServer_onconnection));
|
|
cls->defineProperty("onclose", nullptr, _SE(WebSocketServer_onclose));
|
|
cls->defineProperty("connections", _SE(WebSocketServer_connections), nullptr);
|
|
cls->install();
|
|
|
|
JSBClassType::registerClass<WebSocketServer>(cls);
|
|
__jsb_WebSocketServer_class = cls;
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
|
|
|
|
cls = se::Class::create("WebSocketServerConnection", obj, nullptr, _SE(WebSocketServer_Connection_constructor));
|
|
cls->defineFinalizeFunction(_SE(WebSocketServer_Connection_finalize));
|
|
cls->defineFunction("close", _SE(WebSocketServer_Connection_close));
|
|
cls->defineFunction("send", _SE(WebSocketServer_Connection_send));
|
|
|
|
cls->defineProperty("ontext", nullptr, _SE(WebSocketServer_Connection_ontext));
|
|
cls->defineProperty("onbinary", nullptr, _SE(WebSocketServer_Connection_onbinary));
|
|
cls->defineProperty("onconnect", nullptr, _SE(WebSocketServer_Connection_onconnect));
|
|
cls->defineProperty("onerror", nullptr, _SE(WebSocketServer_Connection_onerror));
|
|
cls->defineProperty("onclose", nullptr, _SE(WebSocketServer_Connection_onclose));
|
|
cls->defineProperty("ondata", nullptr, _SE(WebSocketServer_Connection_ondata));
|
|
|
|
cls->defineProperty("headers", _SE(WebSocketServer_Connection_headers), nullptr);
|
|
cls->defineProperty("protocols", _SE(WebSocketServer_Connection_protocols), nullptr);
|
|
cls->defineProperty("protocol", _SE(WebSocketServer_Connection_protocol), nullptr);
|
|
cls->defineProperty("readyState", _SE(WebSocketServer_Connection_readyState), nullptr);
|
|
|
|
|
|
cls->install();
|
|
|
|
se::Value tmp;
|
|
obj->getProperty("WebSocketServerConnection", &tmp);
|
|
tmp.toObject()->setProperty("CONNECTIONG", se::Value(WebSocketServerConnection::CONNECTING));
|
|
tmp.toObject()->setProperty("OPEN", se::Value(WebSocketServerConnection::OPEN));
|
|
tmp.toObject()->setProperty("CLOSING", se::Value(WebSocketServerConnection::CLOSING));
|
|
tmp.toObject()->setProperty("CLOSED", se::Value(WebSocketServerConnection::CLOSED));
|
|
|
|
JSBClassType::registerClass<WebSocketServerConnection>(cls);
|
|
__jsb_WebSocketServer_Connection_class = cls;
|
|
se::ScriptEngine::getInstance()->clearException();
|
|
|
|
return true;
|
|
}
|
|
#endif //#if (USE_SOCKET > 0) && (USE_WEBSOCKET_SERVER > 0)
|