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; }
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; }