/*!	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;
}
Example #2
0
	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;
}
Example #5
0
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;
}