/*! Reassembles the fragments to the specified buffer \a to. This buffer must have been added via AddFragment() before. */ status_t FragmentPacket::Reassemble(net_buffer* to) { if (!IsComplete()) return B_ERROR; net_buffer* buffer = NULL; net_buffer* fragment; while ((fragment = fFragments.RemoveHead()) != NULL) { if (buffer != NULL) { status_t status; if (to == fragment) { status = gBufferModule->merge(fragment, buffer, false); buffer = fragment; } else status = gBufferModule->merge(buffer, fragment, true); if (status != B_OK) return status; } else buffer = fragment; } if (buffer != to) panic("ipv6 packet reassembly did not work correctly."); to->index = fIndex; // reset the buffer's device index return B_OK; }
FragmentList fragments(const AtomContainer& fragment, bool selected_only) { // iterate over all fragments FragmentList result; AtomContainerConstIterator it = fragment.beginAtomContainer(); for (; +it; ++it) { const Fragment* fragment = dynamic_cast<const Fragment*>(&*it); if ((fragment != 0) && (it->isSelected() || !selected_only)) { // store the fragment pointer in the list result.push_back(const_cast<Fragment*>(fragment)); } } return result; }
void CollectionFilterState::push( const FragmentList& input ) { fragments.insert( fragments.end(), input.begin(), input.end() ); }
status_t FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer* buffer, bool lastFragment) { // restart the timer gStackModule->set_timer(&fTimer, FRAGMENT_TIMEOUT); if (start >= end) { // invalid fragment return B_BAD_DATA; } // Search for a position in the list to insert the fragment FragmentList::ReverseIterator iterator = fFragments.GetReverseIterator(); net_buffer* previous = NULL; net_buffer* next = NULL; while ((previous = iterator.Next()) != NULL) { if (previous->fragment.start <= start) { // The new fragment can be inserted after this one break; } next = previous; } // See if we already have the fragment's data if (previous != NULL && previous->fragment.start <= start && previous->fragment.end >= end) { // we do, so we can just drop this fragment gBufferModule->free(buffer); return B_OK; } fIndex = buffer->index; // adopt the buffer's device index TRACE(" previous: %p, next: %p", previous, next); // If we have parts of the data already, truncate as needed if (previous != NULL && previous->fragment.end > start) { TRACE(" remove header %d bytes", previous->fragment.end - start); gBufferModule->remove_header(buffer, previous->fragment.end - start); start = previous->fragment.end; } if (next != NULL && next->fragment.start < end) { TRACE(" remove trailer %d bytes", next->fragment.start - end); gBufferModule->remove_trailer(buffer, next->fragment.start - end); end = next->fragment.start; } // Now try if we can already merge the fragments together // We will always keep the last buffer received, so that we can still // report an error (in which case we're not responsible for freeing it) if (previous != NULL && previous->fragment.end == start) { fFragments.Remove(previous); buffer->fragment.start = previous->fragment.start; buffer->fragment.end = end; status_t status = gBufferModule->merge(buffer, previous, false); TRACE(" merge previous: %s", strerror(status)); if (status != B_OK) { fFragments.Insert(next, previous); return status; } fFragments.Insert(next, buffer); // cut down existing hole fBytesLeft -= end - start; if (lastFragment && !fReceivedLastFragment) { fReceivedLastFragment = true; fBytesLeft -= IPV6_MAXPACKET - end; } TRACE(" hole length: %d", (int)fBytesLeft); return B_OK; } else if (next != NULL && next->fragment.start == end) { net_buffer* afterNext = (net_buffer*)next->link.next; fFragments.Remove(next); buffer->fragment.start = start; buffer->fragment.end = next->fragment.end; status_t status = gBufferModule->merge(buffer, next, true); TRACE(" merge next: %s", strerror(status)); if (status != B_OK) { // Insert "next" at its previous position fFragments.Insert(afterNext, next); return status; } fFragments.Insert(afterNext, buffer); // cut down existing hole fBytesLeft -= end - start; if (lastFragment && !fReceivedLastFragment) { fReceivedLastFragment = true; fBytesLeft -= IPV6_MAXPACKET - end; } TRACE(" hole length: %d", (int)fBytesLeft); return B_OK; } // We couldn't merge the fragments, so we need to add it as is TRACE(" new fragment: %p, bytes %d-%d", buffer, start, end); buffer->fragment.start = start; buffer->fragment.end = end; fFragments.Insert(next, buffer); // update length of the hole, if any fBytesLeft -= end - start; if (lastFragment && !fReceivedLastFragment) { fReceivedLastFragment = true; fBytesLeft -= IPV6_MAXPACKET - end; } TRACE(" hole length: %d", (int)fBytesLeft); return B_OK; }
FragmentList BuildGeomFilter::process( Feature* input, FilterEnv* env ) { FragmentList output; // LIMITATION: this filter assumes all feature's shapes are the same // shape type! TODO: sort into bins of shape type and create a separate // geometry for each. Then merge the geometries. bool needs_tessellation = false; Fragment* frag = new Fragment(); const GeoShapeList& shapes = input->getShapes(); // if we're in batch mode, the color was resolved in the other process() function. // otherwise we still need to resolve it. osg::Vec4 color = getColorForFeature( input, env ); for( GeoShapeList::const_iterator s = shapes.begin(); s != shapes.end(); s++ ) { const GeoShape& shape = *s; if ( shape.getShapeType() == GeoShape::TYPE_POLYGON ) { needs_tessellation = true; } osg::Geometry* geom = new osg::Geometry(); // TODO: pre-total points and pre-allocate these arrays: osg::Vec3Array* verts = new osg::Vec3Array(); geom->setVertexArray( verts ); unsigned int vert_ptr = 0; // per-vertex coloring takes more memory than per-primitive-set coloring, // but it renders faster. osg::Vec4Array* colors = new osg::Vec4Array(); geom->setColorArray( colors ); geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX ); //osg::Vec3Array* normals = new osg::Vec3Array(); //geom->setNormalArray( normals ); //geom->setNormalBinding( osg::Geometry::BIND_OVERALL ); //normals->push_back( osg::Vec3( 0, 0, 1 ) ); GLenum prim_type = shape.getShapeType() == GeoShape::TYPE_POINT? osg::PrimitiveSet::POINTS : shape.getShapeType() == GeoShape::TYPE_LINE? osg::PrimitiveSet::LINE_STRIP : osg::PrimitiveSet::LINE_LOOP; for( unsigned int pi = 0; pi < shape.getPartCount(); pi++ ) { unsigned int part_ptr = vert_ptr; const GeoPointList& points = shape.getPart( pi ); for( unsigned int vi = 0; vi < points.size(); vi++ ) { verts->push_back( points[vi] ); vert_ptr++; colors->push_back( color ); } geom->addPrimitiveSet( new osg::DrawArrays( prim_type, part_ptr, vert_ptr-part_ptr ) ); } // tessellate all polygon geometries. Tessellating each geometry separately // with TESS_TYPE_GEOMETRY is much faster than doing the whole bunch together // using TESS_TYPE_DRAWABLE. if ( needs_tessellation ) { osgUtil::Tessellator tess; tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY ); tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE ); tess.retessellatePolygons( *geom ); applyOverlayTexturing( geom, input, env ); } generateNormals( geom ); frag->addDrawable( geom ); } frag->addAttributes( input->getAttributes() ); applyFragmentName( frag, input, env ); output.push_back( frag ); return output; }