mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
adds hybi00 frame read code + tests
This commit is contained in:
@@ -225,6 +225,48 @@ BOOST_AUTO_TEST_CASE( prepare_data_frame ) {
|
||||
unsigned char raw_header[1] = {0x00};
|
||||
unsigned char raw_payload[4] = {0x66,0x6f,0x6f,0xff};
|
||||
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( out->get_header(), std::string(reinterpret_cast<char*>(raw_header),1) );
|
||||
BOOST_CHECK_EQUAL( out->get_payload(), std::string(reinterpret_cast<char*>(raw_payload),4) );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( empty_consume ) {
|
||||
uint8_t frame[2] = {0x00,0x00};
|
||||
|
||||
processor_setup env(true);
|
||||
|
||||
size_t ret = env.p.consume(frame,0,env.ec);
|
||||
|
||||
BOOST_CHECK_EQUAL( ret, 0);
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( empty_frame ) {
|
||||
uint8_t frame[2] = {0x00, 0xff};
|
||||
|
||||
processor_setup env(true);
|
||||
|
||||
size_t ret = env.p.consume(frame,2,env.ec);
|
||||
|
||||
BOOST_CHECK_EQUAL( ret, 2);
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message()->get_payload(), "" );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( short_frame ) {
|
||||
uint8_t frame[5] = {0x00, 0x66, 0x6f, 0x6f, 0xff};
|
||||
|
||||
processor_setup env(true);
|
||||
|
||||
size_t ret = env.p.consume(frame,5,env.ec);
|
||||
|
||||
BOOST_CHECK_EQUAL( ret, 5);
|
||||
BOOST_CHECK( !env.ec );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), true );
|
||||
BOOST_CHECK_EQUAL( env.p.get_message()->get_payload(), "foo" );
|
||||
BOOST_CHECK_EQUAL( env.p.ready(), false );
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#include <websocketpp/processors/processor.hpp>
|
||||
|
||||
#include <websocketpp/frame.hpp>
|
||||
#include <websocketpp/utf8_validator.hpp>
|
||||
|
||||
#include <websocketpp/md5/md5.hpp>
|
||||
|
||||
namespace websocketpp {
|
||||
@@ -63,7 +65,11 @@ public:
|
||||
typedef typename config::con_msg_manager_type::ptr msg_manager_ptr;
|
||||
|
||||
explicit hybi00(bool secure, bool server, msg_manager_ptr manager)
|
||||
: processor<config>(secure, server) {}
|
||||
: processor<config>(secure, server)
|
||||
, msg_hdr(0x00)
|
||||
, msg_ftr(0xff)
|
||||
, m_state(HEADER)
|
||||
, m_msg_manager(manager) {}
|
||||
|
||||
int get_version() const {
|
||||
return 0;
|
||||
@@ -196,12 +202,65 @@ public:
|
||||
|
||||
/// Process new websocket connection bytes
|
||||
size_t consume(uint8_t * buf, size_t len, lib::error_code & ec) {
|
||||
ec = make_error_code(error::not_implimented);
|
||||
return 0;
|
||||
// if in state header we are expecting a 0x00 byte, if we don't get one
|
||||
// it is a fatal error
|
||||
size_t p = 0; // bytes processed
|
||||
size_t l = 0;
|
||||
|
||||
ec = lib::error_code();
|
||||
|
||||
while (p < len) {
|
||||
if (m_state == HEADER) {
|
||||
if (buf[p] == msg_hdr) {
|
||||
p++;
|
||||
m_msg_ptr = m_msg_manager->get_message(frame::opcode::text,1);
|
||||
|
||||
if (!m_msg_ptr) {
|
||||
ec = make_error_code(websocketpp::error::no_incoming_buffers);
|
||||
m_state = FATAL_ERROR;
|
||||
} else {
|
||||
m_state = PAYLOAD;
|
||||
}
|
||||
} else {
|
||||
ec = make_error_code(error::protocol_violation);
|
||||
m_state = FATAL_ERROR;
|
||||
}
|
||||
} else if (m_state == PAYLOAD) {
|
||||
uint8_t *it = std::find(buf+p,buf+len,uint8_t(msg_ftr));
|
||||
|
||||
// 0 1 2 3 4 5
|
||||
// 0x00 0x23 0x23 0x23 0xff 0xXX
|
||||
|
||||
// Copy payload bytes into message
|
||||
l = it-(buf+p);
|
||||
m_msg_ptr->append_payload(buf+p,l);
|
||||
p += l;
|
||||
|
||||
if (it != buf+len) {
|
||||
// message is done, copy it and the trailing
|
||||
p++;
|
||||
// TODO: validation
|
||||
m_state = READY;
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we get one, we create a new message and move to application state
|
||||
|
||||
// if in state application we are copying bytes into the output message
|
||||
// and validating them for UTF8 until we hit a 0xff byte. Once we hit
|
||||
// 0x00, the message is complete and is dispatched. Then we go back to
|
||||
// header state.
|
||||
|
||||
//ec = make_error_code(error::not_implimented);
|
||||
return p;
|
||||
}
|
||||
|
||||
bool ready() const {
|
||||
return false;
|
||||
std::cout << "state: " << m_state << std::endl;
|
||||
return (m_state == READY);
|
||||
}
|
||||
|
||||
bool get_error() const {
|
||||
@@ -209,7 +268,10 @@ public:
|
||||
}
|
||||
|
||||
message_ptr get_message() {
|
||||
return message_ptr();
|
||||
message_ptr ret = m_msg_ptr;
|
||||
m_msg_ptr = message_ptr();
|
||||
m_state = HEADER;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Prepare a message for writing
|
||||
@@ -239,13 +301,11 @@ public:
|
||||
}
|
||||
|
||||
// generate header
|
||||
char h = 0x00;
|
||||
char f = 0xff;
|
||||
out->set_header(std::string(&h,1));
|
||||
out->set_header(std::string(&msg_hdr,1));
|
||||
|
||||
// process payload
|
||||
out->set_payload(i);
|
||||
out->append_payload(std::string(&f,1));
|
||||
out->append_payload(std::string(&msg_ftr,1));
|
||||
|
||||
// hybi00 doesn't support compression
|
||||
// hybi00 doesn't have masking
|
||||
@@ -295,6 +355,22 @@ private:
|
||||
std::fill(result,result+4,0);
|
||||
}
|
||||
}
|
||||
|
||||
enum state {
|
||||
HEADER = 0,
|
||||
PAYLOAD = 1,
|
||||
READY = 2,
|
||||
FATAL_ERROR = 3
|
||||
};
|
||||
|
||||
const char msg_hdr;
|
||||
const char msg_ftr;
|
||||
|
||||
state m_state;
|
||||
|
||||
msg_manager_ptr m_msg_manager;
|
||||
message_ptr m_msg_ptr;
|
||||
utf8_validator::validator m_validator;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user