Update for cmake
parent
f43e8b9710
commit
ab3f2510fe
|
@ -0,0 +1,2 @@
|
|||
add_subdirectory(GSock)
|
||||
add_library(LibWS sha1.cpp websocket.cpp)
|
|
@ -9,28 +9,16 @@
|
|||
#include <WinSock2.h> // htonl
|
||||
using namespace std;
|
||||
|
||||
int HandleKey(sock& s, const string& key)
|
||||
string GetResponseKey(const string& key)
|
||||
{
|
||||
string server_key = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
SHA1 sha;
|
||||
sha.update(server_key);
|
||||
uint32_t arr[5];
|
||||
sha.final(arr);
|
||||
for (int i = 0; i < 5; i++) arr[i] = htonl(arr[i]); // 重要
|
||||
string response_key = base64_encode_std((const unsigned char*)arr, sizeof(arr));
|
||||
sock_helper sp(s);
|
||||
string response_header = string("HTTP/1.1 101 Switching Protocols\r\n") +
|
||||
"Connection: upgrade\r\n" +
|
||||
"Sec-WebSocket-Accept: " + response_key + "\r\n" +
|
||||
"Upgrade: websocket\r\n\r\n";
|
||||
if (sp.sendall(response_header) <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// 必须转换成网络字节序
|
||||
for (int i = 0; i < 5; i++) arr[i] = htonl(arr[i]);
|
||||
return base64_encode_std((const unsigned char*)arr, sizeof(arr));
|
||||
}
|
||||
|
||||
int Handshake(sock& s)
|
||||
|
@ -47,21 +35,26 @@ int Handshake(sock& s)
|
|||
// cout << str << endl;
|
||||
}
|
||||
|
||||
string target("Sec-WebSocket-Key");
|
||||
for (auto& str : lines)
|
||||
{
|
||||
string target("Sec-WebSocket-Key");
|
||||
if (str.find(target) != string::npos)
|
||||
{
|
||||
string key = str.substr(str.find(target) + 19, 24);
|
||||
if (HandleKey(s, key) == 0)
|
||||
string response_key = GetResponseKey(key);
|
||||
string response_header = string("HTTP/1.1 101 Switching Protocols\r\n") +
|
||||
"Connection: upgrade\r\n" +
|
||||
"Sec-WebSocket-Accept: " + response_key + "\r\n" +
|
||||
"Upgrade: websocket\r\n\r\n";
|
||||
if (sp.sendall(response_header) <= 0)
|
||||
{
|
||||
// Handshake OK
|
||||
return 0;
|
||||
// Network error.
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handshake Failed: Key is not ok
|
||||
return -1;
|
||||
// Handshake finished successfully.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +103,7 @@ int ReadFrame(sock& s, WSFrame& f)
|
|||
if (sp.recvall(xp.get(), f.len) <= 0) return -1;
|
||||
if (f.ismask)
|
||||
{
|
||||
// 处理掩码问题
|
||||
// 处理掩码问题
|
||||
for (unsigned long long i = 0; i < f.len; i++)
|
||||
{
|
||||
xp[i] ^= f.mask[i % 4];
|
||||
|
@ -198,18 +191,18 @@ int ReadMsg(sock& s, string& out_data)
|
|||
{
|
||||
int ret = ReadFrame(s, f);
|
||||
if (ret < 0) return -1;
|
||||
if (f.opcode == 0x9) // ping包则回复一个pong包
|
||||
if (f.opcode == 0x9) // ping包则回复一个pong包
|
||||
{
|
||||
cout << "Received ping from " << (&s) << endl;
|
||||
if (SendPong(s, f) < 0) return -2;
|
||||
continue;
|
||||
}
|
||||
else if (f.opcode == 0xA) // pong包则什么都不做
|
||||
else if (f.opcode == 0xA) // pong包则什么都不做
|
||||
{
|
||||
cout << "Received pong from " << (&s) << endl;
|
||||
continue;
|
||||
}
|
||||
else if (f.opcode == 0x8) // 连接主动关闭
|
||||
else if (f.opcode == 0x8) // 连接主动关闭
|
||||
{
|
||||
cout << "Websocket is closing " << (&s) << endl;
|
||||
return 0;
|
||||
|
|
31
websocket.h
31
websocket.h
|
@ -2,9 +2,17 @@
|
|||
#include <string>
|
||||
#include "GSock/gsock.h"
|
||||
|
||||
int HandleKey(sock& s, const std::string& key);
|
||||
// 获取Sec-WebSocket-Key的结果
|
||||
std::string GetResponseKey(const std::string& key);
|
||||
|
||||
// 完成Websocket握手过程(http头获取和发送)
|
||||
// 返回值:
|
||||
// 0 握手成功
|
||||
// -1 网络连接中断
|
||||
// -2 请求的不是websocket协议/非法的ws请求
|
||||
int Handshake(sock& s);
|
||||
|
||||
// WebSocket数据帧
|
||||
struct WSFrame
|
||||
{
|
||||
// 1 bit
|
||||
|
@ -12,14 +20,14 @@ struct WSFrame
|
|||
// 1 bit
|
||||
bool rsv1, rsv2, rsv3;
|
||||
|
||||
// 0x0 附加数据帧
|
||||
// 0x1 文本数据帧
|
||||
// 0x2 二进制数据帧
|
||||
// 0x3~7 保留
|
||||
// 0x8 连接关闭
|
||||
// 0x0 附加数据帧
|
||||
// 0x1 文本数据帧
|
||||
// 0x2 二进制数据帧
|
||||
// 0x3~7 保留
|
||||
// 0x8 连接关闭
|
||||
// 0x9 ping
|
||||
// 0xA pong
|
||||
// 0xB~F 保留
|
||||
// 0xB~F 保留
|
||||
// 4 bit
|
||||
int opcode;
|
||||
|
||||
|
@ -29,12 +37,19 @@ struct WSFrame
|
|||
// 4 byte
|
||||
char mask[4];
|
||||
|
||||
// data是未经过编码处理的数据(如果源数据是带掩码的则已经经过解掩码处理)
|
||||
// data是未经过编码处理的数据(如果源数据是带掩码的则已经经过解掩码处理)
|
||||
std::string data;
|
||||
};
|
||||
|
||||
// 读写单个数据帧
|
||||
int ReadFrame(sock& s, WSFrame& f);
|
||||
int SendFrame(sock& s, const WSFrame& f);
|
||||
|
||||
// 发送对ping的响应
|
||||
int SendPong(sock& s, const WSFrame& ping);
|
||||
|
||||
// 读写数据
|
||||
// 读取时可能会读取多个数据帧,同时也会自动对ping包进行响应.
|
||||
// 写入时不会分为多个数据帧.
|
||||
int ReadMsg(sock& s, std::string& out_data);
|
||||
int SendMsg(sock& s, const std::string& data, bool is_text = true);
|
Loading…
Reference in New Issue