Beispiel #1
0
void reader_add_fragment (READER       *rp,
			  Change_t     *cp,
			  KeyHash_t    *hp,
			  DataFragSMsg *fragp)
{
	Reader_t	*r = (Reader_t *) rp->endpoint.endpoint;
	RemWriter_t	*rwp, *fwp;
	CCREF		*refp;
	FragInfo_t	*fip;
	Change_t	*ncp;
	unsigned	max_frags;

	/*log_printf (RTPS_ID, 0, "reader_add_fragment: snr:%u, start:%u, num:%u, fsize:%u, tsize:%u\r\n",
				fragp->writer_sn.low, 
				fragp->frag_start, fragp->num_fragments,
				fragp->frag_size, fragp->sample_size);*/
	/* Check if we already got fragments from writer. */
	fwp = NULL;
	LIST_FOREACH (rp->rem_writers, rwp)
		if ((refp = LIST_HEAD (rwp->rw_changes)) != NULL &&
		    refp->u.c.change->c_writer == cp->c_writer) {
			fwp = rwp;
			break;
		}

	/* If this is the first, add a new RemWriter for the fragment,
	   allocate all relevant data, and start the fragment timer. */
	if (!fwp) {
		max_frags = (fragp->sample_size + fragp->frag_size - 1) / fragp->frag_size;
		if (fragp->frag_start + fragp->num_fragments - 1 > max_frags)
			return;

		if ((rwp = mds_pool_alloc (&rtps_mem_blocks [MB_REM_WRITER])) == NULL) {
			warn_printf ("reader_add_fragment: no memory for fragment!");
			return;
		}
		memset (rwp, 0, sizeof (RemWriter_t));
		rwp->rw_reader = rp;
		LIST_INIT (rwp->rw_changes);
		rp->rem_writers.count++;
		fwp = rwp;
		LIST_ADD_TAIL (rp->rem_writers, *rwp);
		ncp = hc_change_new ();
		if (!ncp) {
			warn_printf ("reader_add_fragment: no memory for change!");
			goto no_change_mem;
		}
		ncp->c_kind = cp->c_kind;
		ncp->c_writer = cp->c_writer;
		ncp->c_time = cp->c_time;
		ncp->c_seqnr = cp->c_seqnr;
		refp = ccref_add (&rwp->rw_changes, ncp, 0, 1, CS_RECEIVED);
		if (!refp) {
			warn_printf ("reader_add_fragment: no memory for list element!");
			goto no_ref_mem;
		}
		fip = rfraginfo_create (refp, fragp, max_frags);
		if (!fip) {
			warn_printf ("reader_add_fragment: no memory for fragment info!");
			goto no_frag_mem;
		}
	}
	else {
		refp = LIST_HEAD (rwp->rw_changes);
		fip = refp->fragments;
		ncp = refp->u.c.change;
		if (fip->fsize != fragp->frag_size ||
		    fip->length != fragp->sample_size ||
		    !SEQNR_EQ (ncp->c_seqnr, fragp->writer_sn)) {

			/* Incorrect fragment context: reset it. */
			fip = rfraginfo_update (refp, fragp);
			if (!fip)
				goto cleanup;
		}
		else if (fragp->frag_start + fragp->num_fragments - 1 > fip->total)
			return;
	}

	/* Update key info if present. */
	if (hp) {
		fip->hash = *hp;
		fip->hp = &fip->hash;
		fip->key = fip->hash.hash;
		fip->keylen = 12;
	}

	/* Mark the fragment as correctly received. */
	mark_fragment (fip, fragp, cp);

	/* If all fragments received correctly, cleanup the context. */
	if (!fip->num_na) {
		ncp->c_db = fip->data;
		ncp->c_length = fip->length;
		ncp->c_data = fip->data->data;
		rcl_access (fip->data);
		fip->data->nrefs++;
		rcl_done (fip->data);
		rfraginfo_delete (refp);
		reader_cache_add_key (rp, ncp, &fip->hash, fip->key, fip->keylen);

	    cleanup:

		if (fip) {		
			FRAGSC_TMR_STOP (rwp, &fip->timer);
			rfraginfo_delete (refp);
		}
		mds_pool_free (&rtps_mem_blocks [MB_CCREF], refp);
		remote_writer_remove (rp, rwp);
		mds_pool_free (&rtps_mem_blocks [MB_REM_WRITER], rwp);
	}
	else {
		FRAGSC_TMR_START (rwp,
				  &fip->timer,
				  TICKS_PER_SEC * 2,
				  (uintptr_t) rwp,
				  reader_frag_to,
				  &r->r_lock);
	}
	return;

    no_frag_mem:
	mds_pool_free (&rtps_mem_blocks [MB_CCREF], refp);
    no_ref_mem:
    	hc_change_free (ncp);
    no_change_mem:
	mds_pool_free (&rtps_mem_blocks [MB_REM_WRITER], rwp);
	return;
}
Beispiel #2
0
static void sfr_be_data (RemWriter_t         *rwp,
			 Change_t            *cp,
			 SequenceNumber_t    *cpsnr,
			 const KeyHash_t     *hp,
			 const unsigned char *key,
			 size_t              keylen,
#ifdef RTPS_FRAGMENTS
			 DataFragSMsg        *fragp,
			 FragInfo_t	     **finfo,
#endif
			 int                 ignore)
{
	Change_t	*ncp;
	READER		*rp = rwp->rw_reader;
	Reader_t	*r = (Reader_t *) rp->endpoint.endpoint;
#ifdef RTPS_FRAGMENTS
	CCREF		*refp;
	FragInfo_t	*fip;
	unsigned	max_frags = 0;
#if defined (DDS_SECURITY) && defined (DDS_NATIVE_SECURITY)
	DB		*dbp;
	DBW		walk;
	int		error;
#endif
	size_t		ofs;
#endif

	ctrc_printd (RTPS_ID, RTPS_SFR_BE_DATA, &rwp, sizeof (rwp));
	prof_start (rtps_br_data);
#ifdef RTPS_FRAGMENTS
	if (rwp->rw_changes.nchanges) {	/* Lingering fragment? */
		refp = LIST_HEAD (rwp->rw_changes);
		fip = refp->fragments;
	}
	else {
		refp = NULL;
		fip = NULL;
	}
	if (fragp) {
		STATS_INC (rwp->rw_ndatafrags);
		if (!fip) {
			max_frags = (fragp->sample_size + fragp->frag_size - 1) / fragp->frag_size;
			if (fragp->frag_start != 1 ||
			    fragp->frag_start + fragp->num_fragments - 1 > max_frags)
				return;

			ncp = hc_change_new ();
			if (!ncp) {
				warn_printf ("sfr_be_data: no memory for change!");
				return;
			}
			ncp->c_kind = cp->c_kind;
			ncp->c_writer = cp->c_writer;
			ncp->c_time = cp->c_time;
			ncp->c_seqnr = cp->c_seqnr;
			refp = ccref_add (&rwp->rw_changes, ncp, 0, 1, CS_RECEIVED);
			if (!refp) {
				warn_printf ("sfr_be_data: no memory for list element!");
				goto no_ref_mem;
			}

		    new_finfo:

			if (*finfo) {
				fip = *finfo;
				rcl_access (fip);
				fip->nrefs++;
				rcl_done (fip);
			}
			else {
				fip = *finfo = rfraginfo_create (refp, fragp, max_frags);
				if (!fip) {
					goto no_frag_mem;
				}
			}
		}
		else {
			ncp = refp->u.c.change;
			if (fip->fsize != fragp->frag_size ||
			    fip->length != fragp->sample_size ||
			    !SEQNR_EQ (ncp->c_seqnr, fragp->writer_sn)) {

				if (fragp->frag_start != 1)
					return;

				/* Incorrect fragment context: reset it. */
				if (fip->nrefs == 1) {
					fip = rfraginfo_update (refp, fragp);
					if (!fip)
						goto no_frag_mem;
				}
				else {
					rfraginfo_delete (refp);
					goto new_finfo;
				}
			}
			else if (fragp->frag_start != fip->first_na + 1 ||
				 fragp->frag_start + fragp->num_fragments - 1 >
								fip->total)
				return;
		}

		/* Update key info if present. */
		if (hp) {
			fip->hash = *hp;
			fip->hp = &fip->hash;
			fip->key = fip->hash.hash;
			fip->keylen = 12;
		}

		/* Mark the fragment as correctly received. */
		mark_fragment (fip, fragp, cp);
		fip->first_na++;

		/* Check if all fragments are received correctly. */
		if (fip->num_na) {
			FRAGSC_TMR_START (rwp,
					  &fip->timer,
					  TICKS_PER_SEC * 2,
					  (uintptr_t) rwp,
					  sfr_be_frag_to,
					  &r->r_lock);
			return;
		}

#if defined (DDS_SECURITY) && defined (DDS_NATIVE_SECURITY)

		/* Decrypt payload data if an encrypted payload is present. */
		if (rwp->rw_endpoint &&
		    rwp->rw_crypto &&
		    fip->length) {
			walk.dbp = fip->data;
			walk.data = fip->data->data;
			walk.length = walk.left = fip->length;
			dbp = sec_decode_serialized_data (&walk,
							  0,
							  rwp->rw_crypto,
							  &fip->length,
							  &ofs,
							  (DDS_ReturnCode_t *) &error);
			if (!dbp)
				return;

			fip->data = dbp;
		}
		else
#endif
			ofs = 0;

		/* Cleanup the context. */
		ncp->c_db = fip->data;
		ncp->c_length = fip->length;
		ncp->c_data = fip->data->data + ofs;
		rcl_access (fip->data);
		fip->data->nrefs++;
		rcl_done (fip->data);
		cp = ncp;
		FRAGSC_TMR_STOP (rwp, &fip->timer);
		rfraginfo_delete (refp);
		mds_pool_free (&rtps_mem_blocks [MB_CCREF], refp);
		LIST_INIT (rwp->rw_changes);
		rwp->rw_changes.nchanges = 0;
	}
	else {
#endif
		STATS_INC (rwp->rw_ndata);

#ifdef RTPS_FRAGMENTS
		if (fip) { /* Lingering fragment?  Cleanup context. */
			FRAGSC_TMR_STOP (rwp, &fip->timer);
			rfraginfo_delete (refp);
			mds_pool_free (&rtps_mem_blocks [MB_CCREF], refp);
			LIST_INIT (rwp->rw_changes);
			rwp->rw_changes.nchanges = 0;
		}
	}
#endif
	RW_SIGNAL (rwp, "BE-Data");

#ifdef RTPS_MARKERS
	if (rp->endpoint.mark_data)
		rtps_marker_notify (r, EM_DATA, "sfr_be_data");
#endif
	if (SEQNR_LT (*cpsnr, rwp->rw_seqnr_next))
		return;

	if (!SEQNR_EQ (*cpsnr, rwp->rw_seqnr_next))
		dcps_samples_lost (r, SEQNR_DELTA (rwp->rw_seqnr_next, *cpsnr));

	if (!ignore) {
		if (cp->c_nrefs > 1) {
			ncp = hc_change_clone (cp);
			if (!ncp) {
				warn_printf ("sfr_be_data: out of memory for change clone!\r\n");
				return;
			}
		}
		else {
			rcl_access (cp);
			cp->c_nrefs++;
			rcl_done (cp);
			ncp = cp;
		}
		ncp->c_seqnr = *cpsnr;
		reader_cache_add_key (rp, ncp, hp, key, keylen);
	}
	rwp->rw_seqnr_next = cp->c_seqnr;
	SEQNR_INC (rwp->rw_seqnr_next);
	prof_stop (rtps_br_data, 1);
	RW_SNR_TRACE (rwp, "BE-data: update");

#ifdef RTPS_FRAGMENTS
	return;

    no_frag_mem:
	warn_printf ("sfr_be_data: no memory for fragment info!");
	LIST_INIT (rwp->rw_changes);
	rwp->rw_changes.nchanges = 0;
	hc_change_free (refp->u.c.change);
	mds_pool_free (&rtps_mem_blocks [MB_CCREF], refp);
    no_ref_mem:
    	hc_change_free (ncp);
#endif
}