const char* stream_addr_ntoa_r(const stream_addr_t* src, char* buf, size_t bytes){ int __attribute__((unused)) written = 0; switch(stream_addr_type(src)){ case STREAM_ADDR_GUESS: abort(); case STREAM_ADDR_TCP: case STREAM_ADDR_UDP: written = snprintf(buf, bytes, "%s://%s:%d", stream_addr_type(src) == STREAM_ADDR_UDP ? "udp" : "tcp", inet_ntoa(src->in_addr), ntohs(src->in_port)); break; case STREAM_ADDR_ETHERNET: written = snprintf(buf, bytes, "eth://%s", hexdump_address(&src->ether_addr)); break; case STREAM_ADDR_CAPFILE: if ( stream_addr_have_flag(src, STREAM_ADDR_LOCAL) ){ strncpy(buf, src->local_filename, bytes); } else { strncpy(buf, src->filename, bytes); } buf[bytes-1] = 0; /* force null-terminator */ break; } assert(written < bytes); return buf; }
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; }