continues frame reading changes fixes a lot of underspecified close behavior. NOTE: this revision won't compile

This commit is contained in:
Peter Thorson
2011-10-07 08:26:41 -05:00
parent 831da9e12b
commit 9180e52103
4 changed files with 122 additions and 82 deletions

View File

@@ -49,6 +49,7 @@ uint8_t frame::get_state() const {
void frame::reset() {
m_state = STATE_BASIC_HEADER;
m_bytes_needed = BASIC_HEADER_LENGTH;
m_payload.empty();
}
void frame::consume(std::istream &s) {
@@ -78,6 +79,15 @@ void frame::consume(std::istream &s) {
process_extended_header();
m_state = STATE_PAYLOAD;
}
} else if (m_state == STATE_PAYLOAD) {
s.read(reinterpret_cast<char *>(&m_payload[0]),m_bytes_needed);
m_bytes_needed -= s.gcount();
if (m_bytes_needed == 0) {
process_payload();
m_state = STATE_READY;
}
}
}
@@ -324,13 +334,10 @@ std::string frame::print_frame() const {
}
void frame::process_basic_header() {
m_payload.empty();
m_bytes_needed = get_header_len() - BASIC_HEADER_LENGTH;
}
void frame::process_extended_header() {
m_extended_header_bytes_needed = 0;
uint8_t s = get_basic_size();
uint64_t payload_size;
int mask_index = BASIC_HEADER_LENGTH;
@@ -345,7 +352,8 @@ void frame::process_extended_header() {
));
if (payload_size < s) {
throw frame_error("payload length not minimally encoded");
throw frame_error("payload length not minimally encoded",
FERR_PROTOCOL_VIOLATION);
}
mask_index += 2;
@@ -357,7 +365,8 @@ void frame::process_extended_header() {
));
if (payload_size <= PAYLOAD_16BIT_LIMIT) {
throw frame_error("payload length not minimally encoded");
throw frame_error("payload length not minimally encoded",
FERR_PROTOCOL_VIOLATION);
}
mask_index += 8;
@@ -378,9 +387,11 @@ void frame::process_extended_header() {
}
if (payload_size > max_payload_size) {
// TODO: frame/message size limits
throw server_error("got frame with payload greater than maximum frame buffer size.");
}
m_payload.resize(payload_size);
m_bytes_needed = payload_size;
}
void frame::process_payload() {
@@ -420,43 +431,39 @@ void frame::process_payload2() {
}
}
bool frame::validate_utf8(uint32_t* state,uint32_t* codep) const {
void frame::validate_utf8(uint32_t* state,uint32_t* codep) const {
for (size_t i = 0; i < m_payload.size(); i++) {
using utf8_validator::decode;
//std::cout << "decoding: " << std::hex << m_payload[i] << std::endl;
if (decode(state,codep,m_payload[i]) == utf8_validator::UTF8_REJECT) {
// std::cout << "bad byte" << std::endl;
return false;
throw frame_error("Invalid UTF-8 Data",FERR_PAYLOAD_VIOLATION);
}
}
return true;
}
void frame::validate_basic_header() const {
// check for control frame size
if (get_basic_size() > BASIC_PAYLOAD_LIMIT && is_control()) {
throw frame_error("Control Frame is too large");
throw frame_error("Control Frame is too large",FERR_PROTOCOL_VIOLATION);
}
// check for reserved opcodes
if (get_rsv1() || get_rsv2() || get_rsv3()) {
throw frame_error("Reserved bit used");
throw frame_error("Reserved bit used",FERR_PROTOCOL_VIOLATION);
}
// check for reserved opcodes
opcode op = get_opcode();
if (op > 0x02 && op < 0x08) {
throw frame_error("Reserved opcode used");
throw frame_error("Reserved opcode used",FERR_PROTOCOL_VIOLATION);
}
if (op > 0x0A) {
throw frame_error("Reserved opcode used");
throw frame_error("Reserved opcode used",FERR_PROTOCOL_VIOLATION);
}
// check for fragmented control message
if (is_control() && !get_fin()) {
throw frame_error("Fragmented control message");
throw frame_error("Fragmented control message",FERR_PROTOCOL_VIOLATION);
}
}