Update for cmake

master
Kirigaya Kazuto 2018-09-17 18:29:44 +08:00
parent f43e8b9710
commit ab3f2510fe
3 changed files with 44 additions and 34 deletions

2
CMakeLists.txt Normal file
View File

@ -0,0 +1,2 @@
add_subdirectory(GSock)
add_library(LibWS sha1.cpp websocket.cpp)

View File

@ -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;

View File

@ -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);