open source

This commit is contained in:
lvfulong
2020-11-11 16:17:13 +08:00
parent 4d989f3ecb
commit bc4ca748de
2441 changed files with 623057 additions and 2 deletions
@@ -0,0 +1,281 @@
#include "V8WSSv.h"
#include <stdio.h>
#include <stdlib.h>
#include <thread>
#include <mutex>
namespace laya {
struct vhdinfo {
struct lws_context *context;
struct lws_vhost *vhost;
int *interrupted;
int *options;
};
/*
参照 https://github.com/warmcat/libwebsockets/tree/master/minimal-examples/ws-server/minimal-ws-server-echo
需要切换版本。
*/
per_session_data__v8dbg* pCurPss = nullptr;
DebuggerAgent* gpDbgAgent = nullptr;
static int callback_def(
struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len) {
int n;
int sendMsgLen = 0;
per_session_data__v8dbg *pss = (per_session_data__v8dbg *)user;
switch (reason) {
case LWS_CALLBACK_PROTOCOL_INIT:
break;
case LWS_CALLBACK_ESTABLISHED: //有人连进来了
printf("connection established\n");
pss->pRecvBuff = nullptr;
pss->index = 0;
pss->nRecvLen = -1;
pss->pDbgAgent = gpDbgAgent;
new (&pss->pTaskLock) std::recursive_mutex();
new (&pss->pSendTask) std::deque<std::string>();
//new (&pss->pSendTask) std::vector<std::string>();
gpDbgAgent->onAcceptNewFrontend(pss);
pCurPss = pss;
break;
case LWS_CALLBACK_SERVER_WRITEABLE: //可以发送了
//缺省的是继续发送。例如上一次可能只发送了一部分
n = LWS_WRITE_CONTINUATION;
if (!pss->continuation) {
//如果是新的任务,就设置文本或者二进制。
if (pss->binary)
n = LWS_WRITE_BINARY;
else
n = LWS_WRITE_TEXT;
pss->continuation = 1;
}
if (!pss->final)
n |= LWS_WRITE_NO_FIN;
//pss->tx += pss->len;
pss->pTaskLock.lock();
//一次处理一个
if (pss->pSendTask.size() > 0) {
std::string& t1 = pss->pSendTask.front();
//printf("send:%s\n", t1.substr(0,200).c_str());
sendMsgLen = t1.length();
if (pss->pSendBuff) {
delete[] pss->pSendBuff;
}
pss->pSendBuff = new unsigned char[sendMsgLen + LWS_PRE];
memcpy(pss->pSendBuff + LWS_PRE, t1.c_str(), sendMsgLen);
//删掉第一个
pss->pSendTask.pop_front();
}
pss->pTaskLock.unlock();
if (sendMsgLen > 0) {
n = lws_write(wsi, &pss->pSendBuff[LWS_PRE], sendMsgLen, (lws_write_protocol)n);
if (n < 0) {
lwsl_err("ERROR %d writing to socket, hanging up\n", n);
return 1;
}
if (n < (int)sendMsgLen) {
lwsl_err("Partial write\n");
//这里不知道怎么处理,按理说部分发送的情况不用管。下次LWS_CALLBACK_SERVER_WRITEABLE的时候应该已经全部发送了。
//所以pss->continuation应该还是=0
//这里直接返回,这样pss->continuation就是1了,是故意的么
return -1;
}
}
if (pss->final)
pss->continuation = 0;
/* 这会导致websocket报错,写返回-1
//一次全部处理
pss->pTaskLock.lock();
if (pss->pSendTask.size() > 0) {
for (std::string& t1 : pss->pSendTask) {
printf("send:%s\n", t1.c_str());
sendMsgLen = t1.length();
if (pss->pSendBuff) {
delete[] pss->pSendBuff;//TODO 优化
}
pss->pSendBuff = new unsigned char[sendMsgLen + LWS_PRE];
memcpy(pss->pSendBuff + LWS_PRE, t1.c_str(), sendMsgLen);
n = lws_write(wsi, &pss->pSendBuff[LWS_PRE], sendMsgLen, (lws_write_protocol)n);
if (n < 0) {
lwsl_err("ERROR %d writing to socket, hanging up\n", n);
return 1;
}
if (n < (int)sendMsgLen) {
lwsl_err("Partial write\n");
//这里不知道怎么处理,按理说部分发送的情况不用管。下次LWS_CALLBACK_SERVER_WRITEABLE的时候应该已经全部发送了。
//所以pss->continuation应该还是=0
//这里直接返回,这样pss->continuation就是1了,是故意的么
return -1;
}
}
}
pss->pTaskLock.unlock();
*/
//lws_rx_flow_control(wsi, 1); //允许在此连接上接收数据。
lws_callback_on_writable(wsi);//一旦有机会,触发写回调
break;
case LWS_CALLBACK_RECEIVE: { // 可以接收了。
// Create a buffer to hold our response
// it has to have some pre and post padding.
// You don't need to care what comes there, libwebsockets
// will do everything for you. For more info see
// http://git.warmcat.com/cgi-bin/cgit/libwebsockets/tree/lib/libwebsockets.h#n597
//amsg.first = lws_is_first_fragment(wsi);
pss->final = lws_is_final_fragment(wsi); //是否是最后一个信息。
pss->binary = lws_frame_is_binary(wsi); //是否是二进制的。
const size_t remaining = lws_remaining_packet_payload(wsi);
//lwsl_info("+++ test-echo: RX len %ld final %ld, pss->len=%ld\n",(long)len, (long)pss->final, (long)pss->len);
if (in && len > 0) {
if (remaining > 0) {
//帧不完整。 TODO
*(int*)0 = 1;
}
else {
if (len+LWS_PRE > sizeof(pss->RecvBuf)) {
*(int*)0 = 1;//TODO
}
memcpy(&pss->RecvBuf[LWS_PRE], in, len);
pss->RecvBuf[LWS_PRE + len] = 0;
pss->nRecvLen = (unsigned int)len;
pss->rx += len;
pss->pDbgAgent->onDbgMsg((char*)(pss->RecvBuf + LWS_PRE), len);
}
}
//lws_rx_flow_control(wsi, 0);//禁止在此连接上接收数据。
lws_callback_on_writable(wsi);//一旦有机会,触发写回调
break;
}
case LWS_CALLBACK_CLOSED:
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
lwsl_debug("closed\n");
pCurPss = nullptr;
if (gpDbgAgent) {
gpDbgAgent->onFrontEndClose();
}
//state = 0;
break;
default:
break;
}
return 0;
}
#define RING_DEPTH 4096
static struct lws_protocols protocols[] = {
/* first protocol must always be HTTP handler */
{
"http-only", // name
callback_def, // callback
sizeof(per_session_data__v8dbg), // per_session_data_size
MAX_V8DBG_PAYLOAD
},
{
NULL, NULL, 0 /* End of list */
}
};
std::thread* wssvth = nullptr;
bool interrupted = false;
void wsserver_run(lws_context* context) {
int n = 0;
while (n >= 0 && !interrupted) {
//nWSSVSleep 是 timeout_ms: 等待超时时间,即没有找到需要处理的连接需要等待的时间,为0则立即返回;
//这个会一通过回调处理消息。
int nSleep = 10;
if (pCurPss) {
pCurPss->pTaskLock.lock();
if (pCurPss->pSendTask.size() > 0) {
nSleep = 0;
}
pCurPss->pTaskLock.unlock();
}
n = lws_service(context, nSleep);
}
lws_context_destroy(context);
}
void startWSSV(int port, DebuggerAgent* pDbgAgent) {
gpDbgAgent = pDbgAgent;
interrupted = false;
struct lws_context *context;
// we're not using ssl
const char *cert_path = NULL;
const char *key_path = NULL;
// no special options
int opts = 0;
static const struct lws_http_mount mount = {
/* .mount_next */ NULL, /* linked-list "next" */
/* .mountpoint */ "/", /* mountpoint URL */
/* .origin */ ".", /* serve from dir */
/* .def */ "index.html", /* default filename */
/* .protocol */ NULL,
/* .cgienv */ NULL,
/* .extra_mimetypes */ NULL,
/* .interpret */ NULL,
/* .cgi_timeout */ 0,
/* .cache_max_age */ 0,
/* .auth_mask */ 0,
/* .cache_reusable */ 0,
/* .cache_revalidate */ 0,
/* .cache_intermediaries */ 0,
/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
/* .mountpoint_len */ 1, /* char count */
/* .basic_auth_login_file */ NULL,
};
lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER/* | LLL_INFO */ /* | LLL_DEBUG */, NULL);
lws_context_creation_info cinfo;
memset(&cinfo, 0, sizeof(cinfo));
cinfo.port = port;
cinfo.mounts = &mount;
cinfo.protocols = protocols;
cinfo.extensions = lws_get_internal_extensions();
//if (!use_ssl) {
cinfo.ssl_cert_filepath = NULL;
cinfo.ssl_private_key_filepath = NULL;
//} else {
// info.ssl_cert_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
// info.ssl_private_key_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
//}
cinfo.gid = -1;
cinfo.uid = -1;
// create libwebsocket context representing this server
context = lws_create_context( &cinfo);
if (context == NULL) {
fprintf(stderr, "libwebsocket init failed\n");
return ;
}
printf("starting server...\n");
wssvth = new std::thread(std::bind(wsserver_run, context));;
}
void stopWSSV() {
interrupted = true;
if (wssvth != NULL)
{
wssvth->join();
}
}
}