TEST(MemoryCluster, Size) { tawara::MemoryCluster c; tawara::UIntElement tc(tawara::ids::Timecode, 0); std::streamsize body_size(tc.size()); EXPECT_EQ(tawara::ids::size(tawara::ids::Cluster) + 8 + body_size, c.size()); }
std::istream& OggPage::read(std::istream& from, bool read_body) { raw_read(from, capture_pattern); raw_read(from, version); raw_read(from, header_type); raw_read(from, absolute_granule_position); raw_read(from, stream_serial_number); raw_read(from, page_sequence_no); raw_read(from, page_checksum); raw_read(from, page_segments); segment_table.resize(page_segments); from.read(reinterpret_cast<char*>(segment_table.data()), page_segments); const std::size_t bsz = body_size(); if(read_body) { body.resize(bsz); from.read(reinterpret_cast<char*>(body.data()), bsz); } else { body.clear(); from.ignore(bsz); } return from; }
AmqpProcessor::Result AmqpProcessor::process_frame(const amqp_frame_t& frame) { Result result; if(is_deliver(frame)) { listener_->process_event(Deliver()); result = delivery_decoded(frame); } else if(is_header(frame)) { listener_->process_event(Header(body_size(frame))); result = properties(frame); } else if(is_body(frame)) { amqp_bytes_t fragment = get_body_fragment(frame); listener_->process_event(Body(fragment.len)); AmqpListener::Delivery& delivery = listener_->get_state<AmqpListener::Delivery&>(); bool last = delivery.is_flag_active<Delivered>(); result = std::make_pair(fragment, last); } else { std::cout << "unprocessed frame: " << frame.frame_type << std::endl; } return result; }
const std::string response::to_buffer() { std::stringstream ss; ss << "HTTP/1.1 " << _status << " " << status::status_to_reason(_status) << "\r\n"; // If server header not specified we add served version stamp if ( _headers.find("server") == _headers.end() ) { ss << "Server: served-v" << APPLICATION_VERSION_STRING << "\r\n"; } for ( const auto & header : _headers ) { ss << std::get<0>(header.second) << ": " << std::get<1>(header.second) << "\r\n"; } // If content length not specified we check body size if ( _headers.find("content-length") == _headers.end() ) { ss << "Content-Length: " << body_size() << "\r\n"; } ss << "\r\n"; ss << _body.str(); _buffer = ss.str(); return _buffer; }
inline int pack_body(uint8_t* dest, int dest_len) const { if (dest_len < body_size()) { return -1; } write64be(id, dest); dest += 8; write16be(address.size(), dest); dest += 2; memcpy(dest, address.c_str(), address.size()); return 0; }
TEST(BaseCluster, Read) { std::stringstream input; tawara::UIntElement tc(tawara::ids::Timecode, 42); tawara::UIntElement st1(tawara::ids::SilentTrackNumber, 1); tawara::UIntElement st2(tawara::ids::SilentTrackNumber, 2); tawara::UIntElement ps(tawara::ids::PrevSize, 0x1234); FakeCluster e; std::streamsize body_size(tc.size()); tawara::vint::write(body_size, input); tc.write(input); EXPECT_EQ(tawara::vint::size(body_size) + body_size, e.read(input)); EXPECT_EQ(42, e.timecode()); EXPECT_TRUE(e.silent_tracks().empty()); EXPECT_EQ(0, e.previous_size()); body_size += tawara::ids::size(tawara::ids::SilentTracks) + tawara::vint::size(st1.size() + st2.size()) + st1.size() + st2.size() + ps.size(); tawara::vint::write(body_size, input); tc.write(input); tawara::ids::write(tawara::ids::SilentTracks, input); tawara::vint::write(st1.size() + st2.size(), input); st1.write(input); st2.write(input); ps.write(input); EXPECT_EQ(tawara::vint::size(body_size) + body_size, e.read(input)); EXPECT_EQ(42, e.timecode()); EXPECT_FALSE(e.silent_tracks().empty()); EXPECT_EQ(0x1234, e.previous_size()); // Body size value wrong (too small) input.str(std::string()); tawara::vint::write(2, input); tc.write(input); ps.write(input); EXPECT_THROW(e.read(input), tawara::BadBodySize); // Invalid child input.str(std::string()); tawara::UIntElement ue(tawara::ids::EBML, 0xFFFF); tawara::vint::write(ue.size(), input); ue.write(input); EXPECT_THROW(e.read(input), tawara::InvalidChildID); // Missing timecode input.str(std::string()); tawara::vint::write(ps.size(), input); ps.write(input); EXPECT_THROW(e.read(input), tawara::MissingChild); }
inline int unpack_body(uint8_t* src, int src_len) { if (src_len < body_size()) { return -1; } id = read64be(src); src += 8; seq = read64be(src); src += 8; round = read64be(src); return 0; }
inline int pack_body(uint8_t* dest, int dest_len) const { if (dest_len < body_size()) { return -1; } write64be(id, dest); dest += 8; write64be(seq, dest); dest += 8; write64be(round, dest); return 0; }
inline int unpack_body(uint8_t* src, int src_len) { if (src_len < body_size()) { return -1; } id = read64be(src); src += 8; uint16_t address_size = read16be(src); src += 2; if (src_len < 8 + 2 + address_size) { return -2; } address = std::string((const char*)src, address_size); return 0; }
inline int pack_body(uint8_t* dest, int dest_len) const { if (dest_len < body_size()) { return -1; } write64be(id, dest); dest += 8; write64be(seq, dest); dest += 8; write64be(round, dest); dest += 8; write64be(next, dest); dest += 8; write32be(next_content.size(), dest); dest += 4; memcpy(dest, next_content.c_str(), next_content.size()); return 0; }
TEST(BaseCluster, Size) { FakeCluster e; tawara::UIntElement tc(tawara::ids::Timecode, 0); std::streamsize body_size(tc.size()); EXPECT_EQ(tawara::ids::size(tawara::ids::Cluster) + 8 + body_size, e.size()); tawara::UIntElement st1(tawara::ids::SilentTrackNumber, 1); tawara::UIntElement st2(tawara::ids::SilentTrackNumber, 2); body_size += tawara::ids::size(tawara::ids::SilentTracks) + tawara::vint::size(st1.size() + st2.size()) + st1.size() + st2.size(); e.silent_tracks().push_back(tawara::SilentTrackNumber(1)); e.silent_tracks().push_back(tawara::SilentTrackNumber(2)); EXPECT_EQ(tawara::ids::size(tawara::ids::Cluster) + 8 + body_size, e.size()); tawara::UIntElement ps(tawara::ids::PrevSize, 0x1234); body_size += ps.size(); e.previous_size(0x1234); EXPECT_EQ(tawara::ids::size(tawara::ids::Cluster) + 8 + body_size, e.size()); }
inline int unpack_body(uint8_t* src, int src_len) { if (src_len < body_size()) { return -1; } id = read64be(src); src += 8; seq = read64be(src); src += 8; round = read64be(src); src += 8; next = read64be(src); src += 8; uint32_t next_content_size = read32be(src); src += 4; if (src_len < 8+8+8+8+4 + next_content_size) { return -2; } next_content = std::string((const char*)src, next_content_size); return 0; }
TEST(MemoryCluster, Read) { std::stringstream input; tawara::UIntElement tc(tawara::ids::Timecode, 42); tawara::BlockElement::Ptr b1(new tawara::SimpleBlock(1, 12345, tawara::Block::LACING_NONE)); tawara::BlockElement::Ptr b2(new tawara::SimpleBlock(2, 26262, tawara::Block::LACING_NONE)); tawara::Block::value_type f1(test_utils::make_blob(5)); b1->push_back(f1); tawara::Block::value_type f2(test_utils::make_blob(10)); b2->push_back(f2); tawara::MemoryCluster c; std::streamsize body_size(tc.size()); tawara::vint::write(body_size, input); tc.write(input); EXPECT_EQ(tawara::vint::size(body_size) + body_size, c.read(input)); EXPECT_EQ(42, c.timecode()); input.str(std::string()); body_size += b1->size() + b2->size(); tawara::vint::write(body_size, input); tc.write(input); b1->write(input); b2->write(input); EXPECT_EQ(tawara::vint::size(body_size) + body_size, c.read(input)); EXPECT_EQ(42, c.timecode()); EXPECT_EQ(2, c.count()); EXPECT_TRUE((*boost::static_pointer_cast<tawara::SimpleBlock>(b1)) == (*boost::static_pointer_cast<tawara::SimpleBlock>(*c.begin()))); EXPECT_TRUE((*boost::static_pointer_cast<tawara::SimpleBlock>(b2)) == (*boost::static_pointer_cast<tawara::SimpleBlock>(*(++c.begin())))); }
/*virtual */void HTTPDataHandler::onDataReady(boost::shared_ptr< Connection > connection) { // get any pending data from the connection std::vector< char > buffer; std::size_t bytes_read; int reason; boost::tie( bytes_read, reason ) = connection->read(buffer); buffer.resize(bytes_read); /* Regardless of whether we have all the data pending on the * connection or not, we may have enough to get a request. In any * case, buffer now contains anything we have. */ /* If the connection has an attribute, it's the request with any data * that was left over from the last time. */ boost::any & connection_attribute(connection->getAttribute(attribute_index__)); boost::shared_ptr< Details::Request > request; std::vector< char >::iterator where; bool end_of_headers_found(false); after_connection_attributes_are_got: do { if (connection_attribute.empty() /* no existing attribute */) { // parse the request, as it is new boost::tie(request, where) = extractRequestHeader< Connection, Details::Request, Exceptions::HTTP::UnknownMethod, Exceptions::HTTP::UnsupportedProtocol >(connection, supported_methods__, buffer.begin(), buffer.end()); if (!request && where == buffer.begin()) { /* the extraction errored out because the first line was incomplete. * If this is the case, we will store whatever we got in the connection * attributes and return. */ break; } else { /* all is well */ } assert(request || where == buffer.end()); } else { std::vector< char > temp_buffer; boost::tie( request, temp_buffer, end_of_headers_found ) = boost::any_cast< boost::tuple< boost::shared_ptr< Details::Request >, std::vector< char >, bool > >(connection_attribute); buffer.insert(buffer.begin(), temp_buffer.begin(), temp_buffer.end()); /* connection_attribute.clear(); ==> */ boost::any a; connection_attribute.swap(a); where = buffer.begin(); } } while(!(request || where == buffer.end())); /* from here on, white space is important as we need to count the number of * carriage returns (13) or newlines (10). If we find two of them before * finding a non-whitespace character (that is: two newlines or two carriage * returns), the requests consists of only the header. If we find only one, * there is a header before the end of the request, and there might be a * body. */ bool end_of_buffer_found(false); if (request) do { std::vector< char >::iterator whence(where); whence = advanceThroughIgnorableWhiteSpace(whence, buffer.end()); if (moreHeaders(where, whence)) { where = whence; whence = findHeaderEnd(where, buffer.end()); if (where != whence) { Details::Header header; boost::tie(header.name_, header.value_) = splitHeader< Exceptions::HTTP::InvalidHeader >(where, whence); request->header_fields_.push_back(header); where = whence; } else { /* we're at the end of the current buffer, but more headers are still * to come. We'll break out of the loop (by setting end_of_buffer_found, * in some corner-cases, where will not be at buffer.end() but we will * still have found the end of the buffer) and store what we currently know * about the request in the connection attributes (the end of the headers * will not have been found, so this will happen automatically) */ end_of_buffer_found = true; } } else // we have all of the header { where = whence; end_of_headers_found = true; } } while (!end_of_headers_found && where != buffer.end() && !end_of_buffer_found); if (end_of_headers_found) { /* When we get here, we don't know whether the request has a body. * If it does, there is a Content-Length header among the headers * that will contain the size of the body. */ Details::HeaderFields::const_iterator curr(request->header_fields_.begin()); Details::HeaderFields::const_iterator end(request->header_fields_.end()); while (curr != end && curr->name_ != "Content-Length") ++curr; bool complete_body_found(false); if (curr != end) { std::size_t body_size(boost::lexical_cast< std::size_t >(curr->value_)); std::vector< char >::iterator whence(where); /* When we get here, the "where" and "whence" iterators should both be * at the start of the body. We will advance "whence" to the end of the * body - which should be within the bounds of the buffer. */ if (std::size_t(std::distance(whence, buffer.end())) < body_size) { connection_attribute = boost::make_tuple(request, std::vector< char >(where, buffer.end()), end_of_headers_found); } else { std::advance(whence, body_size); assert(request->body_.empty()); request->body_.insert(request->body_.end(), where, whence); where = whence; complete_body_found = true; } } else { /* request does not have a body */ complete_body_found = true; } if (complete_body_found) { request_handler_.handle(request); /* Now, if whence is not at the end of the buffer, more requests may be * in the buffer. We need to handle those. */ if (where != buffer.end()) { connection_attribute = boost::make_tuple(boost::shared_ptr< Details::Request >(), std::vector< char >(where, buffer.end()), false); buffer.clear(); goto after_connection_attributes_are_got; } else { /* done */ } } } else { connection_attribute = boost::make_tuple(request, std::vector< char >(where, buffer.end()), end_of_headers_found); } }