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())
|
||||
client.Handshake();
|
||||
else {
|
||||
std::cout << "Shook." << std::endl;
|
||||
break;
|
||||
sosc::Packet pck;
|
||||
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)
|
||||
return false;
|
||||
|
||||
return this->client.Send(packet.ToString()) == 0;
|
||||
}
|
||||
|
||||
sosc::IntraClient::~IntraClient() {
|
||||
this->Close();
|
||||
std::string packet_raw;
|
||||
packet.ToString(&packet_raw);
|
||||
return this->client.Send(packet_raw) == 0;
|
||||
}
|
||||
|
||||
/****************************/
|
||||
|
@ -84,10 +82,6 @@ bool sosc::IntraServer::Accept(IntraClient* client) {
|
|||
return false;
|
||||
}
|
||||
|
||||
sosc::IntraServer::~IntraServer() {
|
||||
this->Close();
|
||||
}
|
||||
|
||||
/****************************/
|
||||
/* END INTRASERVER CODE */
|
||||
/****************************/
|
||||
|
|
|
@ -21,8 +21,6 @@ public:
|
|||
this->client_open = false;
|
||||
this->client.Close();
|
||||
}
|
||||
|
||||
~IntraClient();
|
||||
private:
|
||||
void Open(TcpClient client);
|
||||
|
||||
|
@ -48,8 +46,6 @@ public:
|
|||
this->server_open = false;
|
||||
this->server.Close();
|
||||
}
|
||||
|
||||
~IntraServer();
|
||||
private:
|
||||
bool server_open;
|
||||
TcpServer server;
|
||||
|
|
|
@ -121,7 +121,7 @@ int sosc::Packet::Parse(const std::string& data, std::string* extra) {
|
|||
|
||||
if(length > expected_length && extra != nullptr)
|
||||
*extra = data.substr(expected_length);
|
||||
else
|
||||
else if(extra != nullptr)
|
||||
*extra = "";
|
||||
|
||||
return PCK_OK;
|
||||
|
@ -143,6 +143,35 @@ bool sosc::Packet::Check(int region_count, ...) {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string sosc::Packet::ToString() const {
|
||||
return "TODO";
|
||||
std::string* sosc::Packet::ToString(std::string* packet) const {
|
||||
*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];
|
||||
}
|
||||
|
||||
std::string* ToString(std::string* packet) const;
|
||||
std::string ToString() const;
|
||||
inline operator std::string () const {
|
||||
return this->ToString();
|
||||
|
|
|
@ -67,8 +67,48 @@ int sosc::ScapeConnection::Handshake() {
|
|||
return SOSC_SHAKE_DONE;
|
||||
}
|
||||
|
||||
sosc::ScapeConnection::~ScapeConnection() {
|
||||
this->Close();
|
||||
int sosc::ScapeConnection::Receive(Packet* packet, bool block) {
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
sosc::ScapeServer::~ScapeServer() {
|
||||
this->Close();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#ifndef SOSC_SCAPESOCK_H
|
||||
#define SOSC_SCAPESOCK_H
|
||||
|
||||
#include <queue>
|
||||
#include "../crypto/sha1.hpp"
|
||||
#include "../crypto/base64.hpp"
|
||||
#include "frame.hpp"
|
||||
#include "packet.hpp"
|
||||
#include "tcpsock.hpp"
|
||||
|
||||
|
@ -31,15 +33,15 @@ public:
|
|||
this->client_open = false;
|
||||
this->client.Close();
|
||||
}
|
||||
|
||||
~ScapeConnection();
|
||||
private:
|
||||
void Open(TcpClient client);
|
||||
|
||||
bool client_open;
|
||||
bool handshaked;
|
||||
TcpClient client;
|
||||
|
||||
std::string buffer;
|
||||
std::queue<ws::Frame> frameQueue;
|
||||
|
||||
friend class ScapeServer;
|
||||
};
|
||||
|
@ -59,8 +61,6 @@ public:
|
|||
this->server_open = false;
|
||||
this->server.Close();
|
||||
}
|
||||
|
||||
~ScapeServer();
|
||||
private:
|
||||
bool server_open;
|
||||
TcpServer server;
|
||||
|
|
|
@ -59,7 +59,6 @@ public:
|
|||
}
|
||||
|
||||
void Close();
|
||||
~TcpClient();
|
||||
private:
|
||||
void Open(SOSC_SOCK_T sock, SOSC_ADDR_T addr, int addr_len);
|
||||
void SetBlocking(bool will_block);
|
||||
|
@ -84,7 +83,6 @@ public:
|
|||
bool Accept(TcpClient* client);
|
||||
|
||||
void Close();
|
||||
~TcpServer();
|
||||
private:
|
||||
SOSC_SOCK_T sock;
|
||||
bool sock_open;
|
||||
|
|
|
@ -154,10 +154,6 @@ void sosc::TcpClient::Close() {
|
|||
close(this->sock);
|
||||
}
|
||||
|
||||
sosc::TcpClient::~TcpClient() {
|
||||
this->Close();
|
||||
}
|
||||
|
||||
/****************************/
|
||||
/* END TCPCLIENT CODE */
|
||||
/****************************/
|
||||
|
@ -234,10 +230,6 @@ void sosc::TcpServer::Close() {
|
|||
close(this->sock);
|
||||
}
|
||||
|
||||
sosc::TcpServer::~TcpServer() {
|
||||
this->Close();
|
||||
}
|
||||
|
||||
/****************************/
|
||||
/* END TCPSERVER CODE */
|
||||
/****************************/
|
||||
|
|
|
@ -168,10 +168,6 @@ void sosc::TcpClient::Close() {
|
|||
this->sock_open = false;
|
||||
}
|
||||
|
||||
sosc::TcpClient::~TcpClient() {
|
||||
this->Close();
|
||||
}
|
||||
|
||||
/****************************/
|
||||
/* END TCPCLIENT CODE */
|
||||
/****************************/
|
||||
|
@ -250,10 +246,6 @@ void sosc::TcpServer::Close() {
|
|||
closesocket(this->sock);
|
||||
this->sock_open = false;
|
||||
}
|
||||
|
||||
sosc::TcpServer::~TcpServer() {
|
||||
this->Close();
|
||||
}
|
||||
|
||||
/****************************/
|
||||
/* END TCPSERVER CODE */
|
||||
|
|
Loading…
Reference in a new issue