goodboob
This commit is contained in:
parent
9de61fb44f
commit
3a2cb8d449
12 changed files with 301 additions and 46 deletions
|
@ -33,8 +33,9 @@ int main(int argc, char **argv) {
|
||||||
if(!client.Handshaked())
|
if(!client.Handshaked())
|
||||||
client.Handshake();
|
client.Handshake();
|
||||||
else {
|
else {
|
||||||
std::cout << "Shook." << std::endl;
|
sosc::Packet pck;
|
||||||
break;
|
client.Receive(&pck, true);
|
||||||
|
std::cout << pck.RegionCount() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
135
server/src/sock/frame.cpp
Normal file
135
server/src/sock/frame.cpp
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
#include "frame.hpp"
|
||||||
|
|
||||||
|
static int calc_header_length(uint64_t body_length) {
|
||||||
|
return
|
||||||
|
(body_length < 0x7E
|
||||||
|
? 2
|
||||||
|
: (body_length <= 0xFFFF)
|
||||||
|
? 4
|
||||||
|
: 10
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
sosc::ws::Frame::Frame
|
||||||
|
(const std::string& body, kOpCode opcode, bool final)
|
||||||
|
{
|
||||||
|
this->body = body;
|
||||||
|
this->opcode = opcode;
|
||||||
|
this->is_final = final;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sosc::ws::Frame::Parse(const std::string& data, std::string* extra) {
|
||||||
|
if(data.length() < 2)
|
||||||
|
return FRAME_MORE;
|
||||||
|
|
||||||
|
int header_length = Frame::GetHeaderLength(data);
|
||||||
|
if(data.length() < header_length)
|
||||||
|
return FRAME_MORE;
|
||||||
|
|
||||||
|
uint64_t body_length = Frame::GetBodyLength(data);
|
||||||
|
if(data.length() < header_length + body_length)
|
||||||
|
return FRAME_MORE;
|
||||||
|
|
||||||
|
this->is_final = (data[0] & 0x80) != 0;
|
||||||
|
if((data[0] & 0x70) != 0)
|
||||||
|
return FRAME_ERR;
|
||||||
|
if(!IsValidOpCode(data[0] & 0x0F))
|
||||||
|
return FRAME_ERR;
|
||||||
|
|
||||||
|
this->opcode = static_cast<kOpCode>(data[0] & 0x0F);
|
||||||
|
this->body = data.substr(header_length);
|
||||||
|
|
||||||
|
if((data[1] & 0x80) != 0) {
|
||||||
|
int offset = calc_header_length(body_length);
|
||||||
|
|
||||||
|
std::string mask = data.substr(offset, 4);
|
||||||
|
for(uint64_t i = 0; i < body_length; ++i)
|
||||||
|
this->body[i] ^= mask[i % 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t expected_length = header_length + body_length;
|
||||||
|
if(expected_length < data.length() && extra != nullptr)
|
||||||
|
*extra = data.substr(expected_length);
|
||||||
|
else if(extra != nullptr)
|
||||||
|
*extra = "";
|
||||||
|
|
||||||
|
return FRAME_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sosc::ws::Frame::GetHeaderLength(const std::string& data) {
|
||||||
|
if(data.length() < 2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uint8_t length_byte = data[1] & 0x7F;
|
||||||
|
return 2 +
|
||||||
|
((data[1] & 0x80) != 0 ? 4 : 0) +
|
||||||
|
((length_byte == 0x7E) ? 2 : 0) +
|
||||||
|
((length_byte == 0x7F) ? 8 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t sosc::ws::Frame::GetBodyLength(const std::string& data) {
|
||||||
|
if(data.length() < 2)
|
||||||
|
return -1;
|
||||||
|
if(data.length() < Frame::GetHeaderLength(data))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uint8_t length_byte = data[1] & 0x7F;
|
||||||
|
return
|
||||||
|
(length_byte < 0x7E
|
||||||
|
? length_byte
|
||||||
|
: (length_byte == 0x7E
|
||||||
|
? net::ntohv<uint16_t>(data, 2)
|
||||||
|
: net::ntohv<uint64_t>(data, 2)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sosc::ws::Frame::IsTooLarge(const std::string& data) {
|
||||||
|
uint64_t header_length = Frame::GetHeaderLength(data),
|
||||||
|
body_length = Frame::GetBodyLength(data);
|
||||||
|
|
||||||
|
return (header_length + body_length) <= body_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sosc::ws::Frame::PingFrame(Frame* frame) {
|
||||||
|
frame->opcode = Ping;
|
||||||
|
frame->is_final = true;
|
||||||
|
frame->body = net::htonv<uint32_t>(0x600DB00B);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sosc::ws::Frame::PongFrame(Frame* pingFrame) {
|
||||||
|
pingFrame->opcode = Pong;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sosc::ws::Frame::ClosingFrame
|
||||||
|
(Frame* frame, kClosingReason status, const std::string& reason)
|
||||||
|
{
|
||||||
|
frame->opcode = Close;
|
||||||
|
frame->is_final = true;
|
||||||
|
frame->body = net::htonv<uint16_t>(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string* sosc::ws::Frame::ToString(std::string* frame) const {
|
||||||
|
uint64_t body_length = this->body.length();
|
||||||
|
*frame = std::string(2, 0);
|
||||||
|
|
||||||
|
(*frame)[0] = (this->is_final ? 0x80 : 0x00) | this->opcode;
|
||||||
|
if(body_length < 0x7E)
|
||||||
|
(*frame)[1] = body_length;
|
||||||
|
else if(body_length < 0xFFFF) {
|
||||||
|
(*frame)[1] = 0x7E;
|
||||||
|
*frame += net::htonv<uint16_t>(body_length);
|
||||||
|
} else {
|
||||||
|
(*frame)[1] = 0x7F;
|
||||||
|
*frame += net::htonv<uint64_t>(body_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
*frame += this->body;
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sosc::ws::Frame::ToString() const {
|
||||||
|
std::string frame;
|
||||||
|
this->ToString(&frame);
|
||||||
|
return frame;
|
||||||
|
}
|
81
server/src/sock/frame.hpp
Normal file
81
server/src/sock/frame.hpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#ifndef SOSC_WS_FRAME_H
|
||||||
|
#define SOSC_WS_FRAME_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include "../utils/net.hpp"
|
||||||
|
|
||||||
|
#define FRAME_OK 0
|
||||||
|
#define FRAME_MORE 1
|
||||||
|
#define FRAME_ERR -1
|
||||||
|
|
||||||
|
namespace sosc {
|
||||||
|
namespace ws {
|
||||||
|
class Frame {
|
||||||
|
public:
|
||||||
|
enum kOpCode {
|
||||||
|
Continuation = 0x0,
|
||||||
|
TextFrame = 0x1,
|
||||||
|
BinaryFrame = 0x2,
|
||||||
|
Close = 0x8,
|
||||||
|
Ping = 0x9,
|
||||||
|
Pong = 0xA
|
||||||
|
};
|
||||||
|
|
||||||
|
enum kClosingReason {
|
||||||
|
Normal = 1000,
|
||||||
|
GoingAway = 1001,
|
||||||
|
ProtocolError = 1002,
|
||||||
|
FrameTypeError = 1003,
|
||||||
|
DataError = 1007,
|
||||||
|
PolicyError = 1008,
|
||||||
|
FrameTooBig = 1009,
|
||||||
|
RequestError = 1011
|
||||||
|
};
|
||||||
|
|
||||||
|
Frame() {};
|
||||||
|
Frame(const std::string& body, kOpCode opcode = BinaryFrame,
|
||||||
|
bool final = true);
|
||||||
|
|
||||||
|
int Parse(const std::string& data, std::string* extra = nullptr);
|
||||||
|
|
||||||
|
static int GetHeaderLength(const std::string& data);
|
||||||
|
static uint64_t GetBodyLength(const std::string& data);
|
||||||
|
static bool IsTooLarge(const std::string& data);
|
||||||
|
|
||||||
|
static void PingFrame(Frame* frame);
|
||||||
|
static void PongFrame(Frame* pingFrame);
|
||||||
|
static void ClosingFrame
|
||||||
|
(Frame* frame, kClosingReason status = Normal,
|
||||||
|
const std::string& reason = "");
|
||||||
|
|
||||||
|
inline bool IsFinal() const {
|
||||||
|
return this->is_final;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline kOpCode GetOpCode() const {
|
||||||
|
return this->opcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::string& GetBody() const {
|
||||||
|
return this->body;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string* ToString(std::string* frame) const;
|
||||||
|
std::string ToString() const;
|
||||||
|
inline operator std::string () const {
|
||||||
|
return this->ToString();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
kOpCode opcode;
|
||||||
|
bool is_final;
|
||||||
|
std::string body;
|
||||||
|
|
||||||
|
inline static bool IsValidOpCode(int op) {
|
||||||
|
return !(op == 0x0 || op == 0x1 || op == 0x2
|
||||||
|
|| op == 0x8 || op == 0x9 || op == 0xA);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif
|
|
@ -48,11 +48,9 @@ bool sosc::IntraClient::Send(const Packet& packet) {
|
||||||
if(!this->client_open)
|
if(!this->client_open)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return this->client.Send(packet.ToString()) == 0;
|
std::string packet_raw;
|
||||||
}
|
packet.ToString(&packet_raw);
|
||||||
|
return this->client.Send(packet_raw) == 0;
|
||||||
sosc::IntraClient::~IntraClient() {
|
|
||||||
this->Close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
|
@ -84,10 +82,6 @@ bool sosc::IntraServer::Accept(IntraClient* client) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sosc::IntraServer::~IntraServer() {
|
|
||||||
this->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
/* END INTRASERVER CODE */
|
/* END INTRASERVER CODE */
|
||||||
/****************************/
|
/****************************/
|
||||||
|
|
|
@ -21,8 +21,6 @@ public:
|
||||||
this->client_open = false;
|
this->client_open = false;
|
||||||
this->client.Close();
|
this->client.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
~IntraClient();
|
|
||||||
private:
|
private:
|
||||||
void Open(TcpClient client);
|
void Open(TcpClient client);
|
||||||
|
|
||||||
|
@ -48,8 +46,6 @@ public:
|
||||||
this->server_open = false;
|
this->server_open = false;
|
||||||
this->server.Close();
|
this->server.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
~IntraServer();
|
|
||||||
private:
|
private:
|
||||||
bool server_open;
|
bool server_open;
|
||||||
TcpServer server;
|
TcpServer server;
|
||||||
|
|
|
@ -121,7 +121,7 @@ int sosc::Packet::Parse(const std::string& data, std::string* extra) {
|
||||||
|
|
||||||
if(length > expected_length && extra != nullptr)
|
if(length > expected_length && extra != nullptr)
|
||||||
*extra = data.substr(expected_length);
|
*extra = data.substr(expected_length);
|
||||||
else
|
else if(extra != nullptr)
|
||||||
*extra = "";
|
*extra = "";
|
||||||
|
|
||||||
return PCK_OK;
|
return PCK_OK;
|
||||||
|
@ -143,6 +143,35 @@ bool sosc::Packet::Check(int region_count, ...) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sosc::Packet::ToString() const {
|
std::string* sosc::Packet::ToString(std::string* packet) const {
|
||||||
return "TODO";
|
*packet = std::string(8, 0);
|
||||||
|
(*packet)[0] = 0xB0;
|
||||||
|
(*packet)[1] = 0x0B;
|
||||||
|
(*packet)[6] = this->id;
|
||||||
|
(*packet)[7] = regions.size();
|
||||||
|
|
||||||
|
for(auto i = this->regions.begin(); i != this->regions.end(); ++i) {
|
||||||
|
if(i->size() < 0xFE)
|
||||||
|
*packet += (char)i->size();
|
||||||
|
else if(i->size() <= 0xFFFF) {
|
||||||
|
*packet += (char)0xFE;
|
||||||
|
*packet += net::htonv<uint16_t>(i->size());
|
||||||
|
} else {
|
||||||
|
*packet += (char)0xFF;
|
||||||
|
*packet += net::htonv<uint32_t>(i->size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto i = this->regions.begin(); i != this->regions.end(); ++i)
|
||||||
|
*packet += *i;
|
||||||
|
|
||||||
|
packet->assign(net::htonv<uint32_t>(packet->length()), 2, 4);
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sosc::Packet::ToString() const {
|
||||||
|
std::string packet;
|
||||||
|
this->ToString(&packet);
|
||||||
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
return this->regions[index];
|
return this->regions[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string* ToString(std::string* packet) const;
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
inline operator std::string () const {
|
inline operator std::string () const {
|
||||||
return this->ToString();
|
return this->ToString();
|
||||||
|
|
|
@ -67,8 +67,48 @@ int sosc::ScapeConnection::Handshake() {
|
||||||
return SOSC_SHAKE_DONE;
|
return SOSC_SHAKE_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sosc::ScapeConnection::~ScapeConnection() {
|
int sosc::ScapeConnection::Receive(Packet* packet, bool block) {
|
||||||
this->Close();
|
if(!this->client_open)
|
||||||
|
return PCK_ERR;
|
||||||
|
if(!this->handshaked)
|
||||||
|
return PCK_ERR;
|
||||||
|
|
||||||
|
int status;
|
||||||
|
ws::Frame frame;
|
||||||
|
bool first_recv = true;
|
||||||
|
while((status = frame.Parse(this->buffer, &this->buffer)) != FRAME_OK) {
|
||||||
|
if(status == FRAME_ERR)
|
||||||
|
return PCK_ERR;
|
||||||
|
if(!block && !first_recv)
|
||||||
|
return PCK_MORE;
|
||||||
|
|
||||||
|
status = this->client.Receive
|
||||||
|
(&this->buffer, SOSC_TCP_APPEND | (block ? SOSC_TCP_BLOCK : 0));
|
||||||
|
|
||||||
|
if(status == -1)
|
||||||
|
return PCK_ERR;
|
||||||
|
first_recv = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO optimize
|
||||||
|
this->frameQueue.push(frame);
|
||||||
|
if(frame.IsFinal()) {
|
||||||
|
std::string pck;
|
||||||
|
while(!this->frameQueue.empty())
|
||||||
|
pck.
|
||||||
|
} else
|
||||||
|
return PCK_MORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sosc::ScapeConnection::Send(const Packet& packet) {
|
||||||
|
if(!this->client_open)
|
||||||
|
return PCK_ERR;
|
||||||
|
if(!this->handshaked)
|
||||||
|
return PCK_ERR;
|
||||||
|
|
||||||
|
std::string packet_raw;
|
||||||
|
packet.ToString(&packet_raw);
|
||||||
|
return this->client.Send(packet_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************/
|
/******************************/
|
||||||
|
@ -99,7 +139,3 @@ bool sosc::ScapeServer::Accept(ScapeConnection* client) {
|
||||||
client->Open(raw_client);
|
client->Open(raw_client);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sosc::ScapeServer::~ScapeServer() {
|
|
||||||
this->Close();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#ifndef SOSC_SCAPESOCK_H
|
#ifndef SOSC_SCAPESOCK_H
|
||||||
#define SOSC_SCAPESOCK_H
|
#define SOSC_SCAPESOCK_H
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
#include "../crypto/sha1.hpp"
|
#include "../crypto/sha1.hpp"
|
||||||
#include "../crypto/base64.hpp"
|
#include "../crypto/base64.hpp"
|
||||||
|
#include "frame.hpp"
|
||||||
#include "packet.hpp"
|
#include "packet.hpp"
|
||||||
#include "tcpsock.hpp"
|
#include "tcpsock.hpp"
|
||||||
|
|
||||||
|
@ -31,15 +33,15 @@ public:
|
||||||
this->client_open = false;
|
this->client_open = false;
|
||||||
this->client.Close();
|
this->client.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ScapeConnection();
|
|
||||||
private:
|
private:
|
||||||
void Open(TcpClient client);
|
void Open(TcpClient client);
|
||||||
|
|
||||||
bool client_open;
|
bool client_open;
|
||||||
bool handshaked;
|
bool handshaked;
|
||||||
TcpClient client;
|
TcpClient client;
|
||||||
|
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
|
std::queue<ws::Frame> frameQueue;
|
||||||
|
|
||||||
friend class ScapeServer;
|
friend class ScapeServer;
|
||||||
};
|
};
|
||||||
|
@ -59,8 +61,6 @@ public:
|
||||||
this->server_open = false;
|
this->server_open = false;
|
||||||
this->server.Close();
|
this->server.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ScapeServer();
|
|
||||||
private:
|
private:
|
||||||
bool server_open;
|
bool server_open;
|
||||||
TcpServer server;
|
TcpServer server;
|
||||||
|
|
|
@ -59,7 +59,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close();
|
void Close();
|
||||||
~TcpClient();
|
|
||||||
private:
|
private:
|
||||||
void Open(SOSC_SOCK_T sock, SOSC_ADDR_T addr, int addr_len);
|
void Open(SOSC_SOCK_T sock, SOSC_ADDR_T addr, int addr_len);
|
||||||
void SetBlocking(bool will_block);
|
void SetBlocking(bool will_block);
|
||||||
|
@ -84,7 +83,6 @@ public:
|
||||||
bool Accept(TcpClient* client);
|
bool Accept(TcpClient* client);
|
||||||
|
|
||||||
void Close();
|
void Close();
|
||||||
~TcpServer();
|
|
||||||
private:
|
private:
|
||||||
SOSC_SOCK_T sock;
|
SOSC_SOCK_T sock;
|
||||||
bool sock_open;
|
bool sock_open;
|
||||||
|
|
|
@ -154,10 +154,6 @@ void sosc::TcpClient::Close() {
|
||||||
close(this->sock);
|
close(this->sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
sosc::TcpClient::~TcpClient() {
|
|
||||||
this->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
/* END TCPCLIENT CODE */
|
/* END TCPCLIENT CODE */
|
||||||
/****************************/
|
/****************************/
|
||||||
|
@ -234,10 +230,6 @@ void sosc::TcpServer::Close() {
|
||||||
close(this->sock);
|
close(this->sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
sosc::TcpServer::~TcpServer() {
|
|
||||||
this->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
/* END TCPSERVER CODE */
|
/* END TCPSERVER CODE */
|
||||||
/****************************/
|
/****************************/
|
||||||
|
|
|
@ -168,10 +168,6 @@ void sosc::TcpClient::Close() {
|
||||||
this->sock_open = false;
|
this->sock_open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sosc::TcpClient::~TcpClient() {
|
|
||||||
this->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
/* END TCPCLIENT CODE */
|
/* END TCPCLIENT CODE */
|
||||||
/****************************/
|
/****************************/
|
||||||
|
@ -250,10 +246,6 @@ void sosc::TcpServer::Close() {
|
||||||
closesocket(this->sock);
|
closesocket(this->sock);
|
||||||
this->sock_open = false;
|
this->sock_open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sosc::TcpServer::~TcpServer() {
|
|
||||||
this->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
/* END TCPSERVER CODE */
|
/* END TCPSERVER CODE */
|
||||||
|
|
Loading…
Reference in a new issue