static int read_packet(struct stream_pfring* st, int block){
	assert(st);

	do {
		/* read next frame */
		struct pfring_pkthdr hdr;
		switch ( pfring_recv(st->pd, (u_char**)&st->frame[st->base.writePos], 0, &hdr, block) ){
		case 0:
			return 0;
		case 1:
			break;
		case -1:
			fprintf(stderr, "pfring_recv(..) failed.\n");
			return 0;
		}

		char* dst = st->frame[st->base.writePos];

		/* Setup pointers */
		const struct ethhdr* eh = (const struct ethhdr*)dst;
		const struct sendhead* sh = (const struct sendhead*)(dst + sizeof(struct ethhdr));

		/* Check if it is a valid packet and if it was destinationed here */
		int match;
		if ( (match=match_ma_pkt(st, eh)) == -1 ){
			continue;
		}

		#ifdef DEBUG
		fprintf(stderr, "got measurement frame with %d capture packets [BU: %3.2f%%]\n", ntohl(sh->nopkts), 0.0f);
		#endif

		/* increase packet count */
		st->base.stat.recv += ntohl(sh->nopkts);

    /* if no sequencenr is set some additional checks are made.
     * they will also run when the sequence number wraps, but that ok since the
     * sequence number will match in that case anyway. */
    if ( st->seqnum[match] == 0 ){
      /* read stream version */
	    struct file_header_t FH;
	    FH.version.major=ntohs(sh->version.major);
	    FH.version.minor=ntohs(sh->version.minor);

	    /* ensure we can read this version */
	    if ( !is_valid_version(&FH) ){
		    perror("invalid stream version");
		    break;
	    }

      /* this is set last, as we want to wait until a packet with valid version
       * arrives before proceeding. */
      st->seqnum[match] = ntohl(sh->sequencenr);
    }
    match_inc_seqnr(&st->base, &st->seqnum[match], sh);

    st->base.writePos = (st->base.writePos+1) % st->num_frames;

    /* This indicates a flush from the sender.. */
    if( ntohs(sh->flush) == 1 ){
	    fprintf(stderr, "Sender terminated.\n");
	    st->base.flushed=1;
    }

    return 1;

	} while (1);

	return 0;
}
Exemple #2
0
static int stream_ethernet_read_frame(struct stream_ethernet* st, char* dst, struct timeval* timeout){
	assert(st);
	assert(dst);

	do {
		fd_set fds;
		FD_ZERO(&fds);
		FD_SET(st->socket, &fds);

		if ( select(st->socket+1, &fds, NULL, NULL, timeout) != 1 ){
			break;
		}

		/* Read data into framebuffer. */
		int bytes = recvfrom(st->socket, dst, st->fb.frame_size, 0, NULL, NULL);
		if ( bytes < 0 ){ /* error occurred */
			perror("Cannot receive Ethernet data.");
			break;
		} else if ( bytes == 0 ){ /* proper shutdown */
			perror("Connection closed by client.");
			break;
		}

		/* Setup pointers */
		const struct ethhdr* eh = (const struct ethhdr*)dst;
		const struct sendhead* sh = (const struct sendhead*)(dst + sizeof(struct ethhdr));

		/* Check if it is a valid packet and if it was destinationed here */
		int match;
		if ( (match=match_ma_pkt(st, eh)) == -1 ){
			continue;
		}

#ifdef DEBUG
		fprintf(stderr, "got measurement frame with %d capture packets [BU: %3.2f%%]\n", ntohl(sh->nopkts), 0.0f);
		fprintf(stderr, "  address: %s (%d)\n", hexdump_address(&st->address[match]), match);
#endif

		/* validate frame */
		if ( !valid_framesize(bytes, sh) ){
			/* error message already shown */
			continue;
		}

		/* increase packet count */
		st->base.stat.recv += ntohl(sh->nopkts);

		/* if no sequencenr is set some additional checks are made.
		 * they will also run when the sequence number wraps, but that ok since the
		 * sequence number will match in that case anyway. */
		if ( st->seqnum[match] == 0 ){
			/* read stream version */
			struct file_header_t FH;
			FH.version.major=ntohs(sh->version.major);
			FH.version.minor=ntohs(sh->version.minor);

			/* ensure we can read this version */
			if ( !is_valid_version(&FH) ){
				perror("invalid stream version");
				break;
			}

			/* this is set last, as we want to wait until a packet with valid version
			 * arrives before proceeding. */
			st->seqnum[match] = ntohl(sh->sequencenr);
		}
		match_inc_seqnr(&st->base, &st->seqnum[match], sh);

		/* This indicates a flush from the sender.. */
		if( ntohl(sh->flags) & SENDER_FLUSH ){
			fprintf(stderr, "Sender terminated.\n");
			st->base.flushed=1;
		}

		return 1;

	} while (1);

	return 0;
}