This commit is contained in:
malloc 2018-04-04 17:01:20 -05:00
parent 9de61fb44f
commit 3a2cb8d449
12 changed files with 301 additions and 46 deletions

View file

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

View file

@ -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 */
/****************************/ /****************************/

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 */
/****************************/ /****************************/

View file

@ -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 */
/****************************/ /****************************/
@ -251,10 +247,6 @@ void sosc::TcpServer::Close() {
this->sock_open = false; this->sock_open = false;
} }
sosc::TcpServer::~TcpServer() {
this->Close();
}
/****************************/ /****************************/
/* END TCPSERVER CODE */ /* END TCPSERVER CODE */
/****************************/ /****************************/