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
|
#include <WinSock2.h> // htonl
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int HandleKey(sock& s, const string& key)
|
string GetResponseKey(const string& key)
|
||||||
{
|
{
|
||||||
string server_key = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
string server_key = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||||
SHA1 sha;
|
SHA1 sha;
|
||||||
sha.update(server_key);
|
sha.update(server_key);
|
||||||
uint32_t arr[5];
|
uint32_t arr[5];
|
||||||
sha.final(arr);
|
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));
|
for (int i = 0; i < 5; i++) arr[i] = htonl(arr[i]);
|
||||||
sock_helper sp(s);
|
return base64_encode_std((const unsigned char*)arr, sizeof(arr));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Handshake(sock& s)
|
int Handshake(sock& s)
|
||||||
|
@ -47,21 +35,26 @@ int Handshake(sock& s)
|
||||||
// cout << str << endl;
|
// cout << str << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string target("Sec-WebSocket-Key");
|
||||||
for (auto& str : lines)
|
for (auto& str : lines)
|
||||||
{
|
{
|
||||||
string target("Sec-WebSocket-Key");
|
|
||||||
if (str.find(target) != string::npos)
|
if (str.find(target) != string::npos)
|
||||||
{
|
{
|
||||||
string key = str.substr(str.find(target) + 19, 24);
|
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
|
// Network error.
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Handshake Failed: Key is not ok
|
// Handshake finished successfully.
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +103,7 @@ int ReadFrame(sock& s, WSFrame& f)
|
||||||
if (sp.recvall(xp.get(), f.len) <= 0) return -1;
|
if (sp.recvall(xp.get(), f.len) <= 0) return -1;
|
||||||
if (f.ismask)
|
if (f.ismask)
|
||||||
{
|
{
|
||||||
// 处理掩码问题
|
// 处理掩码问题
|
||||||
for (unsigned long long i = 0; i < f.len; i++)
|
for (unsigned long long i = 0; i < f.len; i++)
|
||||||
{
|
{
|
||||||
xp[i] ^= f.mask[i % 4];
|
xp[i] ^= f.mask[i % 4];
|
||||||
|
@ -198,18 +191,18 @@ int ReadMsg(sock& s, string& out_data)
|
||||||
{
|
{
|
||||||
int ret = ReadFrame(s, f);
|
int ret = ReadFrame(s, f);
|
||||||
if (ret < 0) return -1;
|
if (ret < 0) return -1;
|
||||||
if (f.opcode == 0x9) // ping包则回复一个pong包
|
if (f.opcode == 0x9) // ping包则回复一个pong包
|
||||||
{
|
{
|
||||||
cout << "Received ping from " << (&s) << endl;
|
cout << "Received ping from " << (&s) << endl;
|
||||||
if (SendPong(s, f) < 0) return -2;
|
if (SendPong(s, f) < 0) return -2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (f.opcode == 0xA) // pong包则什么都不做
|
else if (f.opcode == 0xA) // pong包则什么都不做
|
||||||
{
|
{
|
||||||
cout << "Received pong from " << (&s) << endl;
|
cout << "Received pong from " << (&s) << endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (f.opcode == 0x8) // 连接主动关闭
|
else if (f.opcode == 0x8) // 连接主动关闭
|
||||||
{
|
{
|
||||||
cout << "Websocket is closing " << (&s) << endl;
|
cout << "Websocket is closing " << (&s) << endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
31
websocket.h
31
websocket.h
|
@ -2,9 +2,17 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "GSock/gsock.h"
|
#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);
|
int Handshake(sock& s);
|
||||||
|
|
||||||
|
// WebSocket数据帧
|
||||||
struct WSFrame
|
struct WSFrame
|
||||||
{
|
{
|
||||||
// 1 bit
|
// 1 bit
|
||||||
|
@ -12,14 +20,14 @@ struct WSFrame
|
||||||
// 1 bit
|
// 1 bit
|
||||||
bool rsv1, rsv2, rsv3;
|
bool rsv1, rsv2, rsv3;
|
||||||
|
|
||||||
// 0x0 附加数据帧
|
// 0x0 附加数据帧
|
||||||
// 0x1 文本数据帧
|
// 0x1 文本数据帧
|
||||||
// 0x2 二进制数据帧
|
// 0x2 二进制数据帧
|
||||||
// 0x3~7 保留
|
// 0x3~7 保留
|
||||||
// 0x8 连接关闭
|
// 0x8 连接关闭
|
||||||
// 0x9 ping
|
// 0x9 ping
|
||||||
// 0xA pong
|
// 0xA pong
|
||||||
// 0xB~F 保留
|
// 0xB~F 保留
|
||||||
// 4 bit
|
// 4 bit
|
||||||
int opcode;
|
int opcode;
|
||||||
|
|
||||||
|
@ -29,12 +37,19 @@ struct WSFrame
|
||||||
// 4 byte
|
// 4 byte
|
||||||
char mask[4];
|
char mask[4];
|
||||||
|
|
||||||
// data是未经过编码处理的数据(如果源数据是带掩码的则已经经过解掩码处理)
|
// data是未经过编码处理的数据(如果源数据是带掩码的则已经经过解掩码处理)
|
||||||
std::string data;
|
std::string data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 读写单个数据帧
|
||||||
int ReadFrame(sock& s, WSFrame& f);
|
int ReadFrame(sock& s, WSFrame& f);
|
||||||
int SendFrame(sock& s, const WSFrame& f);
|
int SendFrame(sock& s, const WSFrame& f);
|
||||||
|
|
||||||
|
// 发送对ping的响应
|
||||||
int SendPong(sock& s, const WSFrame& ping);
|
int SendPong(sock& s, const WSFrame& ping);
|
||||||
|
|
||||||
|
// 读写数据
|
||||||
|
// 读取时可能会读取多个数据帧,同时也会自动对ping包进行响应.
|
||||||
|
// 写入时不会分为多个数据帧.
|
||||||
int ReadMsg(sock& s, std::string& out_data);
|
int ReadMsg(sock& s, std::string& out_data);
|
||||||
int SendMsg(sock& s, const std::string& data, bool is_text = true);
|
int SendMsg(sock& s, const std::string& data, bool is_text = true);
|
Loading…
Reference in New Issue