void Deserializer::work(const InputItems &, const OutputItems &) { //validate the pkt message type PMCC msg = pop_input_msg(0); if (not msg or not msg.is<gras::PacketMsg>()) return; gras::PacketMsg pkt_msg = msg.as<gras::PacketMsg>(); //handle the packet - non recovery logic if (not _recover) return this->handle_packet(pkt_msg.buff); //////////////////////////////////////////////////////////////// /////////// Recovery logic below /////////////////////////////// //////////////////////////////////////////////////////////////// //was there a buffer previously? then accumulate it if (_accum_buff) { gras::SBufferConfig config; config.length = _accum_buff.length + pkt_msg.buff.length; gras::SBuffer new_buff(config); std::memcpy(new_buff.get(), _accum_buff.get(), _accum_buff.length); std::memcpy(new_buff.get(_accum_buff.length), pkt_msg.buff.get(), pkt_msg.buff.length); _accum_buff = new_buff; } else { _accum_buff = pkt_msg.buff; } //character by character recovery search for packet header while (_accum_buff.length >= MIN_PKT_BYTES) { bool fragment = true; size_t pkt_len = 0; if (inspect_packet(_accum_buff.get(), _accum_buff.length, fragment, pkt_len)) { if (fragment) return; //wait for more incoming buffers to accumulate handle_packet(_accum_buff); //handle the packet, its good probably //increment for the next iteration ASSERT(pkt_len <= _accum_buff.length); _accum_buff.offset += pkt_len; _accum_buff.length -= pkt_len; ASSERT(_accum_buff.length <= _accum_buff.get_actual_length()); } else { //the search continues _accum_buff.offset++; _accum_buff.length--; } } //dont keep a reference if the buffer is empty if (_accum_buff.length == 0) _accum_buff.reset(); }
/* Return a free buffer of size at least MIN_SIZE. */ _cpp_buff * _cpp_get_buff (cpp_reader *pfile, size_t min_size) { _cpp_buff *result, **p; for (p = &pfile->free_buffs;; p = &(*p)->next) { size_t size; if (*p == NULL) return new_buff (min_size); result = *p; size = result->limit - result->base; /* Return a buffer that's big enough, but don't waste one that's way too big. */ if (size >= min_size && size <= BUFF_SIZE_UPPER_BOUND (min_size)) break; } *p = result->next; result->next = NULL; result->cur = result->base; return result; }