bool ConnectionIn::addPacket(Packet& p){ PacketHeader h; if(cc.transform){ if(!cc.transform->remove(p, buffer.reset())){ return false; // removal of packet transformation failed. } } Packet& input = cc.transform ? buffer : p; if(!h.read(input) || h.version != 0){ return false; // packet has invalid header / unknown version. } int packet_age = 0; if(packet_history.none()){ // first packet recieved cc.seq_num = h.seq_num; packet_history[0] = 1; } else { int16_t seq_dist = static_cast<int16_t>(h.seq_num - cc.seq_num); if(abs(seq_dist) >= NRG_CONN_PACKET_HISTORY){ return true; // packet is out of history range. } // states need to know about retransmissons of the newest packet if(seq_dist < 0 && (h.flags & PKTFLAG_RETRANSMISSION)){ return true; } if(seq_dist > 0){ // new packet packet_history <<= seq_dist; packet_history[0] = 1; cc.seq_num = h.seq_num; // update ages of reassembly fragments and remove them if they're too old. for(auto& i : reassembly_buf){ if(i.age >= 0) i.age += seq_dist; if(i.age > (int)NRG_CONN_PACKET_HISTORY){ i.age = -1; i.data.reset(); } } } else { if(packet_history[-seq_dist]){ // already recieved this packet. return true; } else { packet_history[-seq_dist] = 1; packet_age = -seq_dist; } } } if((h.flags & PKTFLAG_FINISHED) && (cc.seq_num != h.seq_num)){ return false; // packet claims end of stream, but there is a newer one... } new_packet = true; // reconstruct packets that were split into multiple fragments. if(h.frag_index > 0 || (h.flags & PKTFLAG_CONTINUED)){ if(h.frag_index >= reassembly_buf.size()){ return false; } ReassemblyInfo& frag = reassembly_buf[h.frag_index]; if(frag.age >= 0 && packet_age > frag.age){ new_packet = false; } else { frag.data.writeArray(input.getPointer(), input.remaining()); frag.age = packet_age; frag.continued = h.flags & PKTFLAG_CONTINUED; // check if the newly added fragment completes a full packet. for(size_t i = 0; i < reassembly_buf.size(); ++i){ NRG_DEBUG("Age calc: [%d, %d]\n", (int)i, reassembly_buf[i].age); if(reassembly_buf[i].age == -1 || (i > 0 && reassembly_buf[i].age != reassembly_buf[i-1].age - 1)){ new_packet = false; } if(!reassembly_buf[i].continued) break; } NRG_DEBUG("Got fragment, idx: %d, continued?: %d, age: %d full?: %d\n", h.frag_index, h.flags & PKTFLAG_CONTINUED, packet_age, new_packet ); // write all the fragments out if they do form a full packet. if(new_packet){ latest.reset(); int age_counter = reassembly_buf[0].age; for(auto& i : reassembly_buf){ if(i.age != age_counter--) break; latest.writeArray(i.data.getBasePointer(), i.data.size()); i.data.reset(); i.age = -1; } } } } else { latest.reset().writeArray(input.getPointer(), input.remaining()); } if(cc.seq_num > h.seq_num) h.flags |= PKTFLAG_OUT_OF_ORDER; latest_flags = static_cast<PacketFlags>(h.flags); return true; }