#include "pch.h"
#include "lws_server.h"
MSG_CONNECTED_CALLBACK lws_server::msg_connect = NULL;
MSG_DESTORY_CALLBACK lws_server::msg_destory = NULL;
MSG_RECEIVE_CALLBACK lws_server::msg_receive = NULL;
static struct lws_context_creation_info ctx_info = { 0 };
static struct lws_context *context = NULL;
/**
* 会话上下文对象,结构根据需要自定义
*/
/*
构造函数
*/
lws_server::lws_server(int listen_port)
{
port = listen_port;
}
/*
析构函数
*/
lws_server::~lws_server()
{
lwsl_notice("析构完成\n");
}
/*
拷贝构造
*/
lws_server::lws_server(const lws_server &obj)
{
}
int lws_server::get_port()
{
return port;
}
/*
服务器底层实现的回调函数
*/
static int protocol_my_callback(struct lws *wsi,
enum lws_callback_reasons reason,
void *user,
void *in,
size_t len)
{
struct session_data *data = (struct session_data *) user;
switch (reason) {
case LWS_CALLBACK_RECEIVE: // 当接收到客户端发来的帧以后
lwsl_notice("recvied message");
// 判断是否最后一帧
data->fin = lws_is_final_fragment(wsi);
// 判断是否二进制消息
data->bin = lws_frame_is_binary(wsi);
// 对服务器的接收端进行流量控制,如果来不及处理,可以控制之
// 下面的调用禁止在此连接上接收数据
lws_rx_flow_control(wsi, 0);
// 业务处理部分,为了实现Echo服务器,把客户端数据保存起来
memcpy(&data->buf[LWS_PRE], in, len);
data->len = len;
//lwsl_notice("recvied message:%s\n", &data->buf[LWS_PRE]);
lwsl_notice("recvied message:%s\n", &data->buf[LWS_PRE]);
if (lws_server::msg_receive != NULL) {
lws_server::msg_receive(data, wsi);
}
// 需要给客户端应答时,触发一次写回调
lws_callback_on_writable(wsi);
data = NULL;
break;
case LWS_CALLBACK_SERVER_WRITEABLE: // 当此连接可写时
lwsl_notice("LWS_CALLBACK_PROTOCOL_INIT\n");
lws_write(wsi, &data->buf[LWS_PRE], data->len, LWS_WRITE_TEXT);
// 下面的调用允许在此连接上接收数据
lws_rx_flow_control(wsi, 1);
break;
case LWS_CALLBACK_PROTOCOL_INIT:
lwsl_notice("LWS_CALLBACK_PROTOCOL_INIT send message:%s\n", &data->buf[LWS_PRE]);
break;
case LWS_CALLBACK_WSI_DESTROY:
lwsl_notice("LWS_CALLBACK_WSI_DESTROY\n"); //现在认为这里销毁一个链接
//if (lws_server::msg_destory != NULL) {
// lws_server::msg_destory(data, wsi);
//}
break;
case LWS_CALLBACK_WSI_CREATE:
lwsl_notice("LWS_CALLBACK_WSI_CREATE\n"); //现在认为这里创建一个链接
//if (lws_server::msg_connect != NULL) {
// lws_server::msg_connect(data, wsi);
//}
break;
case LWS_CALLBACK_ESTABLISHED: // 当服务器和客户端完成握手后
lwsl_notice("LWS_CALLBACK_ESTABLISHED\n");
break;
}
// 回调函数最终要返回0,否则无法创建服务器
return 0;
}
/**
* 支持的WebSocket子协议数组
* 子协议即JavaScript客户端WebSocket(url, protocols)第2参数数组的元素
* 你需要为每种协议提供回调函数
*/
struct lws_protocols protocols[] = {
{
//协议名称,协议回调,接收缓冲区大小
"ws", protocol_my_callback, sizeof(struct session_data), MAX_PAYLOAD_SIZE,
},
{
NULL, NULL, 0 // 最后一个元素固定为此格式
}
};
void lws_server::init()
{
ctx_info.port = 8000;
ctx_info.iface = NULL; // 在所有网络接口上监听
ctx_info.protocols = protocols;
ctx_info.gid = -1;
ctx_info.uid = -1;
ctx_info.options = LWS_SERVER_OPTION_VALIDATE_UTF8;
}
int lws_server::set_ssl(const char* ca_filepath,
const char* server_cert_filepath,
const char*server_private_key_filepath,
bool is_support_ssl)
{
if (!is_support_ssl)
{
ctx_info.ssl_ca_filepath = NULL;
ctx_info.ssl_cert_filepath = NULL;
ctx_info.ssl_private_key_filepath = NULL;
}
else
{
ctx_info.ssl_ca_filepath = ca_filepath;
ctx_info.ssl_cert_filepath = server_cert_filepath;
ctx_info.ssl_private_key_filepath = server_private_key_filepath;
ctx_info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
//ctx_info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
}
return is_support_ssl;
}
int lws_server::create()
{
context = lws_create_context(&ctx_info);
if (!context) {
lwsl_err("lws_server create failed\n");
return -1;
}
return 1;
}
int lws_server::run(int wait_time)
{
return lws_service(context, wait_time);
}
void lws_server::destroy()
{
lws_context_destroy(context);
}
//-------------------------------------------------设定回调
void lws_server::setConnectCallBack(MSG_CONNECTED_CALLBACK msg_con) {
this->msg_connect = msg_con;
}
void lws_server::setReceiveCallBack(MSG_RECEIVE_CALLBACK msg_recv) {
this->msg_receive = msg_recv;
}
void lws_server::setDesoryCallBack(MSG_DESTORY_CALLBACK msg_des) {
this->msg_destory = msg_des;
}