Files
LayaNative2.0/Conch/source/conch/JSWrapper/LayaWrap/JSWebSocket.cpp
T
2020-11-11 16:17:13 +08:00

323 lines
12 KiB
C++

/**
@file JSWebSocket.cpp
@brief
@author kuo.wang
@version 1.0
@date 2014_4_11
*/
//包含头文件
#include "JSWebSocket.h"
#include "../JSInterface/JSInterface.h"
#include <util/Log.h>
#include <util/JCCommonMethod.h>
#include <util/JCMemorySurvey.h>
#include "../../WebSocket/WebSocket.h"
#include "../../JCScriptRuntime.h"
#include <util/JCIThreadCmdMgr.h>
namespace laya
{
ADDJSCLSINFO(JSWebSocket, JSObjNode);
//------------------------------------------------------------------------------
JSWebSocketDelegate::JSWebSocketDelegate(JSWebSocket* p_js_WebSocket) :jswsref(p_js_WebSocket->m_CallbackRef)
{
m_js_WebSocket = p_js_WebSocket;
m_pCmdPoster = JCScriptRuntime::s_JSRT->m_pPoster;
}
void JSWebSocketDelegate::onOpen(WebSocket* ws)
{
LOGI("JSWebSocketDelegate::onOpen() this=%x ws=%x", (long)this,(long)m_js_WebSocket);
std::string p_sEvent;
m_js_WebSocket->closeTime = 0;
m_pCmdPoster->postToJS(std::bind(&JSWebSocket::onSocketOpenCallJSFunction, m_js_WebSocket, p_sEvent, jswsref));
}
void JSWebSocketDelegate::onMessage(WebSocket* ws, const WebSocket::Data& data)
{
char* pDt = data.bytes;// new char[data.len];
//memcpy(pDt, data.bytes, data.len);
m_pCmdPoster->postToJS(std::bind(&JSWebSocket::onSocketMessageCallJSFunctionArrayBuffer, m_js_WebSocket, pDt, data.len, data.isBinary, jswsref));
}
void JSWebSocketDelegate::onClose(WebSocket* ws)
{
LOGI("JSWebSocketDelegate::onClose()this=%x ws=%x", (long)this, (long)m_js_WebSocket);
std::string p_sEvent = "error";
auto pFuncation = std::bind(&JSWebSocket::onSocketCloseCallJSFunction, m_js_WebSocket, p_sEvent,tmGetCurms(), jswsref);
m_pCmdPoster->postToJS(pFuncation);
}
void JSWebSocketDelegate::onError(WebSocket* ws, const WebSocket::ErrorCode& error)
{
LOGW("JSWebSocketDelegate::onError( code=%d )this=%x ws=%x", error, (long)this, (long)m_js_WebSocket);
if (m_js_WebSocket->m_nWebSocketState == WSS_OPEN)
{
LOGW("JSWebSocketDelegate::onError123( code=%d )this=%x ws=%x", error, (long)this, (long)m_js_WebSocket);
std::string p_sEvent = "error";
auto pFuncation = std::bind(&JSWebSocket::onSocketErrorCallJSFunction, m_js_WebSocket, p_sEvent, jswsref);
m_pCmdPoster->postToJS(pFuncation);
}
}
//------------------------------------------------------------------------------
JSWebSocket::JSWebSocket()
{
m_CallbackRef.reset(new int(1));
m_pCmdPoster = JCScriptRuntime::s_JSRT->m_pPoster;
m_pWebSocket = NULL;
m_pWebSocketDelegate = NULL;
m_nBinaryType = Type_String;
m_nWebSocketState = WSS_INIT;
AdjustAmountOfExternalAllocatedMemory(1024);
JCMemorySurvey::GetInstance()->newClass("webSocket", 1024, this);
}
//------------------------------------------------------------------------------
JSWebSocket::JSWebSocket(const char* p_sUrl)
{
m_CallbackRef.reset(new int(1));
m_pCmdPoster = JCScriptRuntime::s_JSRT->m_pPoster;
m_pWebSocket = new WebSocket();
closeTime = 0;
m_pWebSocketDelegate = new JSWebSocketDelegate(this);
LOGI("new JSWebSocket::this=%x deletgate=%x", (long)this, (long)m_pWebSocketDelegate);
m_nBinaryType = Type_String;
m_nWebSocketState = WSS_INIT;
if (Init(p_sUrl))
{
m_nWebSocketState = WSS_OPEN;
}
else
{
m_nWebSocketState = WSS_CLOSE;
}
AdjustAmountOfExternalAllocatedMemory(1024);
JCMemorySurvey::GetInstance()->newClass("webSocket", 1024, this);
}
//------------------------------------------------------------------------------
JSWebSocket::~JSWebSocket()
{
LOGI("release JSWebSocket this=%x deletgate=%x", (long) this, (long)m_pWebSocketDelegate);
if (m_pWebSocket)
{
m_pWebSocket->clearDelegate(); //去掉delegate,防止发给js对象。因为跨线程之后,js对象已经删除了。
m_pWebSocket->close();
}
//下面删除socket的时候会先同步关掉socket线程,所以不用考虑再有消息来的时候对象已经删除这种事情。
LAYA_SAFE_DELETE(m_pWebSocket);
LAYA_SAFE_DELETE(m_pWebSocketDelegate);
JCMemorySurvey::GetInstance()->releaseClass("webSocket", this);
}
//------------------------------------------------------------------------------
void JSWebSocket::onSocketOpenCallJSFunction(std::string p_sEvent, std::weak_ptr<int> cbref)
{
if (!cbref.lock())return;
m_pJSFunctionOnOpen.Call(p_sEvent.c_str());
}
//------------------------------------------------------------------------------
void JSWebSocket::onSocketCloseCallJSFunction(std::string p_sEvent, int64_t closetm, std::weak_ptr<int> cbref)
{
if (!cbref.lock())return;
closeTime = closetm;
LOGI("JSWebSocket::onSocketCloseCallJSFunction this=%x", (long) this);
if (m_nWebSocketState == WSS_OPEN)
{
m_nWebSocketState = WSS_CLOSE;
m_pJSFunctionOnClose.Call(p_sEvent.c_str());
}
else
{
m_nWebSocketState = WSS_CLOSE;
}
}
//------------------------------------------------------------------------------
void JSWebSocket::onSocketErrorCallJSFunction(std::string p_sEvent, std::weak_ptr<int> cbref)
{
if (!cbref.lock())
return;
if (m_nWebSocketState == WSS_OPEN)
{
m_nWebSocketState = WSS_CLOSE;
m_pJSFunctionOnError.Call(p_sEvent.c_str());
}
else
{
m_nWebSocketState = WSS_CLOSE;
}
}
void JSWebSocket::onSocketMessageCallJSFunctionArrayBuffer(const char* pBuf, int p_nLen, bool isBin, std::weak_ptr<int> cbref)
{
if (!cbref.lock()) return;
#ifdef JS_V8
v8::HandleScope scope(v8::Isolate::GetCurrent());
#endif
if (isBin)
{
JsValue ab = createJSAB((char*)pBuf, p_nLen);
delete[] pBuf;
m_pJSFunctionOnMessage.Call(ab);
}
else
{
std::string strMsg;
strMsg.append(pBuf, p_nLen); //怕有0的問題,就新建一個string了
m_pJSFunctionOnMessage.Call(strMsg.c_str());
delete[] pBuf;
}
}
//------------------------------------------------------------------------------
bool JSWebSocket::Init(const char* p_sUrl)
{
if (p_sUrl == NULL) return false;
if (p_sUrl != NULL)
{
//ws->init(deleg, "ws://echo.websocket.org");
m_pWebSocket->init(*m_pWebSocketDelegate, p_sUrl, NULL);
return true;
}
return false;
}
//------------------------------------------------------------------------------
void JSWebSocket::SetOnOpen(JSValueAsParam p_pFunction)
{
m_pJSFunctionOnOpen.set(onopenid, this, p_pFunction);
}
//------------------------------------------------------------------------------
JsValue JSWebSocket::GetOnOpen()
{
return m_pJSFunctionOnOpen.getJsObj();
}
//------------------------------------------------------------------------------
void JSWebSocket::SetOnMessage(JSValueAsParam p_pFunction)
{
m_pJSFunctionOnMessage.set(onmsgid, this, p_pFunction);
}
//------------------------------------------------------------------------------
JsValue JSWebSocket::GetOnMessage()
{
return m_pJSFunctionOnMessage.getJsObj();
}
//------------------------------------------------------------------------------
void JSWebSocket::SetOnClose(JSValueAsParam p_pFunction)
{
m_pJSFunctionOnClose.set(oncloseid, this, p_pFunction);
}
//------------------------------------------------------------------------------
JsValue JSWebSocket::GetOnClose()
{
return m_pJSFunctionOnClose.getJsObj();
}
//------------------------------------------------------------------------------
void JSWebSocket::SetOnError(JSValueAsParam p_pFunction)
{
m_pJSFunctionOnError.set(onerrid, this, p_pFunction);
}
//------------------------------------------------------------------------------
JsValue JSWebSocket::GetOnError()
{
return m_pJSFunctionOnError.getJsObj();
}
//------------------------------------------------------------------------------
void JSWebSocket::send(const char* p_sMessage)
{
if (m_nWebSocketState == WSS_OPEN)
{
if (m_pWebSocket)
{
m_pWebSocket->send(p_sMessage);
}
}
}
//------------------------------------------------------------------------------
void JSWebSocket::close()
{
LOGI("JSWebSocket::close this=%x deletgate=%x", (long)this, (long)m_pWebSocketDelegate);
if (m_nWebSocketState == WSS_OPEN)
{
if (m_pWebSocket)
{
m_nWebSocketState = WSS_CLOSEING;
m_pWebSocket->close();
}
}
}
const char* JSWebSocket::getBinaryType()
{
switch (m_nBinaryType)
{
case Type_String:break;
case Type_Blob:return "blob";
case Type_ArrayBuffer:return "arraybuffer";
}
return NULL;
}
void JSWebSocket::setBinaryType(const char* p_pszBinaryType)
{
if (!p_pszBinaryType)return;
if (strcmp(p_pszBinaryType, "blob") == 0)
{
m_nBinaryType = Type_Blob;
}
else if (strcmp(p_pszBinaryType, "arraybuffer") == 0)
{
m_nBinaryType = Type_ArrayBuffer;
}
}
void JSWebSocket::JsSend(JSValueAsParam args)
{
enBinaryType type = m_nBinaryType;
char* pABPtr = NULL;
int nABLen = 0;
if (__TransferToCpp<char *>::is(args))
{
type = Type_String;
}
else
{
bool bisab = extractJSAB(args, pABPtr, nABLen);
type = bisab ? Type_ArrayBuffer : Type_Unknown;
}
switch (type)
{
case Type_ArrayBuffer:
if (m_nWebSocketState == WSS_OPEN && m_pWebSocket)
{
m_pWebSocket->send((const unsigned char*)pABPtr, (unsigned int)nABLen);
}
break;
case Type_String:
if (m_nWebSocketState == WSS_OPEN && m_pWebSocket)
{
char* sColor = JS_TO_CPP(char*, args);
if (sColor)
{
m_pWebSocket->send(sColor);
}
}
break;
default:
LOGW("JSWebSocket::JsSend send不支持的参数!");
break;
}
}
int JSWebSocket::getTimeGap()
{
if (closeTime == 0)
return 0;
else
return int(tmGetCurms() - closeTime);
}
void JSWebSocket::exportJS()
{
JSP_CLASS("ConchWebSocket", JSWebSocket);
JSP_ADD_PROPERTY(onopen, JSWebSocket, GetOnOpen, SetOnOpen);
JSP_ADD_PROPERTY(_onmessage, JSWebSocket, GetOnMessage, SetOnMessage);
JSP_ADD_PROPERTY(onclose, JSWebSocket, GetOnClose, SetOnClose);
JSP_ADD_PROPERTY(onerror, JSWebSocket, GetOnError, SetOnError);
JSP_ADD_PROPERTY(binaryType, JSWebSocket, getBinaryType, setBinaryType);
JSP_ADD_PROPERTY_RO(timegap, JSWebSocket, getTimeGap);
JSP_ADD_PROPERTY_RO(readyState, JSWebSocket, getReadState);
JSP_ADD_METHOD("close", JSWebSocket::close);
JSP_ADD_METHOD("send", JSWebSocket::JsSend);
JSP_REG_CONSTRUCTOR(JSWebSocket, const char*);
JSP_INSTALL_CLASS("ConchWebSocket", JSWebSocket);
}
}
//-----------------------------END FILE--------------------------------