This commit is contained in:
aozhiwei 2023-05-28 15:12:15 +08:00
parent 0a6ae55785
commit b6e0b07313
2 changed files with 168 additions and 2 deletions

View File

@ -61,9 +61,13 @@ namespace a8
{
};
tcp_client_->on_socketread =
[] (a8::AsioTcpClient* socket, char* buf, unsigned int buf_len)
[this] (a8::AsioTcpClient* socket, char* buf, unsigned int buflen)
{
int i = 0;
if (!handshook_) {
buf[buflen] = '\0';
} else {
}
};
}
@ -116,6 +120,162 @@ namespace a8
}
}
void WebSocketClient::ProcessHandShake(char* buf, int& offset, unsigned int buflen)
{
char* pend = strstr(buf + offset, "\r\n\r\n");
if (!pend) {
return;
}
if (strstr(buf + offset, WEB_SOCKET_KEY) || strstr(buf + offset, WEB_SOCKET_KEY2)) {
ProcessWsHandShake(buf, offset, buflen);
} else {
//ProcessHttpHandShake(buf, offset, buflen);
}
}
void WebSocketClient::ProcessWsHandShake(char* buf, int& offset, unsigned int buflen)
{
char* pend = strstr(buf + offset, "\r\n\r\n");
if (!pend) {
return;
}
if (strncmp(buf + offset, "GET ", strlen("GET ")) == 0) {
std::string url;
std::string querystr;
std::string location;
a8::ParserQueryStr(buf + offset + 4, url, querystr);
}
std::string server_key;
{
char* p1 = strstr(buf + offset, WEB_SOCKET_KEY);
if (!p1) {
p1 = strstr(buf + offset, WEB_SOCKET_KEY2);
}
if (p1) {
p1 += strlen(WEB_SOCKET_KEY);
char* p2 = strstr(p1 , "\r\n");
if (p2) {
server_key.append(p1, p2-p1);
}
}
}
#if 0
server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
std::string sha1_data = a8::openssl::Sha1Encode(server_key);
std::string hash_data;
a8::openssl::Base64Encode(sha1_data, hash_data);
std::string response = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Accept: " + hash_data + "\r\n" +
"\r\n";
SendBuff(response.data(), response.size());
handshook_ = true;
#endif
offset += pend - buf - offset + strlen("\r\n\r\n");
}
void WebSocketClient::ProcessUserPacket()
{
int offset = 0;
int prev_offset = 0;
do {
prev_offset = offset;
//DecodeUserPacket(decoded_buff_, offset, decoded_bufflen_);
} while (prev_offset < offset && offset < decoded_bufflen_);
if (offset > 0 && offset < decoded_bufflen_){
memmove(decoded_buff_, decoded_buff_ + offset, decoded_bufflen_ - offset);
}
decoded_bufflen_ -= offset;
#if 0
if (decoded_bufflen_ >= max_packet_len_) {
//收到超长包
Close();
return;
}
#endif
}
void WebSocketClient::DecodeFrame(char* buf, int& offset, unsigned int buflen)
{
if (offset + 2 > (int)buflen) {
return;
}
char* real_buf = buf + offset;
unsigned int ava_len = buflen - offset;
unsigned char header = real_buf[0];
unsigned char mask_payloadlen = real_buf[1];
bool is_final_frame = (header & FIN) == FIN;
#if 0
bool reserved_bits = (header & FIN) == RSV_MASK;
#endif
unsigned char opcode = header & OPCODE_MASK;
#if 0
bool opcode_is_control = opcode & 0x8;
#endif
if (opcode == WEBSOCKET_FRAME_CLOSE) {
Close();
return;
}
if (opcode != BINARY_MODE) {
if (opcode != WEBSOCKET_FRAME_PING) {
Close();
return;
}
}
if (!is_final_frame) {
Close();
return;
}
bool is_masked = (mask_payloadlen & 0x80) == 0x80;
if (!is_masked) {
Close();
return;
}
unsigned char payloadlen = mask_payloadlen & 0x7F;
unsigned int framelen = 0;
int mask_offset = 0;
if (payloadlen < 126) {
framelen = payloadlen;
mask_offset = 2;
} else if (payloadlen == 126 && ava_len >= 4) {
framelen = ntohs( *(u_short*) (real_buf + 2) );
mask_offset = 4;
} else if (payloadlen == 127 && ava_len >= 8) {
//int32 or int64?
framelen = ntohl( *(u_long*) (real_buf + 2) );
mask_offset = 8;
} else {
return;
}
unsigned int real_pkg_len = mask_offset + framelen + (is_masked ? 4 : 0);
if (ava_len < real_pkg_len) {
return;
}
if (is_masked) {
unsigned char *frame_mask = (unsigned char*)(real_buf + mask_offset);
memcpy(&decoded_buff_[decoded_bufflen_], real_buf + mask_offset + 4, framelen);
for (unsigned int i = 0; i < framelen; i++) {
decoded_buff_[decoded_bufflen_ + i] = (decoded_buff_[i] ^ frame_mask[i%4]);
}
} else {
memcpy(&decoded_buff_[decoded_bufflen_], real_buf + mask_offset, framelen);
}
decoded_bufflen_ += framelen;
ProcessUserPacket();
offset += real_pkg_len;
}
}
#endif

View File

@ -28,6 +28,12 @@ namespace a8
bool Connected();
void SendBuff(const char* buff, unsigned int bufflen);
private:
void ProcessHandShake(char* buf, int& offset, unsigned int buflen);
void ProcessWsHandShake(char* buf, int& offset, unsigned int buflen);
void ProcessUserPacket();
void DecodeFrame(char* buf, int& offset, unsigned int buflen);
private:
std::shared_ptr<AsioTcpClient> tcp_client_;
char *decoded_buff_ = nullptr;