void *rtp_thread_func(void *arg) { socklen_t si_len = sizeof(rtp_client); char packet[MAX_PACKET]; char *pktp; seq_t seqno; ssize_t plen; int sock = rtp_sockets[0], csock = rtp_sockets[1]; int readsock; char type; fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); FD_SET(csock, &fds); while (select(csock>sock ? csock+1 : sock+1, &fds, 0, 0, 0)!=-1) { if (FD_ISSET(sock, &fds)) { readsock = sock; } else { readsock = csock; } FD_SET(sock, &fds); FD_SET(csock, &fds); plen = recvfrom(readsock, packet, sizeof(packet), 0, (struct sockaddr*)&rtp_client, &si_len); if (plen < 0) continue; assert(plen<=MAX_PACKET); type = packet[1] & ~0x80; if (type == 0x60 || type == 0x56) { // audio data / resend pktp = packet; if (type==0x56) { pktp += 4; plen -= 4; } seqno = ntohs(*(unsigned short *)(pktp+2)); buffer_put_packet(seqno, pktp+12, plen-12); } } return 0; }
static int st_joining(struct state *st) { struct pkt pkt; int ret; // Actually attempt to join the data if (st->buffer_offset >= 0) { struct pkt pkts[REQUIRED_MATCHES]; struct pkt old_pkts[REQUIRED_MATCHES]; int synced = 0; int disk_offset = 0; int buffer_start = st->buffer_offset; for (disk_offset=disk_offset; (disk_offset+REQUIRED_MATCHES) < SKIP_AMOUNT && !synced; disk_offset++) { fill_buffer(st, pkts, REQUIRED_MATCHES, packet_get_next_raw); for (st->search_limit = 0; (st->search_limit + REQUIRED_MATCHES) < SKIP_AMOUNT && !synced; st->search_limit++) { int i; int matches_found = 0; fill_buffer(st, old_pkts, REQUIRED_MATCHES, buffer_get_packet); // Check to see if our run matches up for (i=0; i<REQUIRED_MATCHES; i++) { int dat = pkts[i].data.nand_cycle.data; int old_dat = old_pkts[i].data.nand_cycle.data; int ctrl = pkts[i].data.nand_cycle.control; int old_ctrl = old_pkts[i].data.nand_cycle.control; if (dat == old_dat && ctrl == old_ctrl) matches_found++; } // If enough packets match, we're synced if (matches_found >= REQUIRED_MATCHES-1) { st->last_sec_dif = st->sec_dif; st->last_nsec_dif = st->nsec_dif; st->sec_dif = -(pkts[REQUIRED_MATCHES/2].header.sec-old_pkts[REQUIRED_MATCHES/2].header.sec); st->nsec_dif = -(pkts[REQUIRED_MATCHES/2].header.nsec-old_pkts[REQUIRED_MATCHES/2].header.nsec); if (st->nsec_dif > 1000000000L) { st->nsec_dif -= 1000000000L; st->sec_dif++; } else if (st->nsec_dif < 0) { st->nsec_dif += 1000000000L; st->sec_dif--; } synced=1; buffer_unget_packet(st, old_pkts); } else { empty_buffer(st, old_pkts, REQUIRED_MATCHES, buffer_unget_packet); buffer_get_packet(st, old_pkts); } } if (!synced) { empty_buffer(st, pkts, REQUIRED_MATCHES, packet_unget); empty_buffer(st, old_pkts, REQUIRED_MATCHES, buffer_unget_packet); packet_get_next_raw(st, pkts); } } if (!synced) printf("Couldn't join\n"); // Now we're synced, just ignore the rest of the matched-buffer // packets. This is because if they're in the buffer, they've // already been written out. int tries = 0; while ((st->buffer_offset+st->search_limit)%SKIP_AMOUNT != buffer_start-1) { struct pkt old_pkt; int dat, old_dat, ctrl, old_ctrl; buffer_get_packet(st, &old_pkt); packet_get_next_raw(st, &pkt); dat = pkt.data.nand_cycle.data; old_dat = old_pkt.data.nand_cycle.data; ctrl = pkt.data.nand_cycle.control; old_ctrl = old_pkt.data.nand_cycle.control; tries++; if ((dat != old_dat) || (ctrl != old_ctrl)) { printf("Join anomaly after %d tries: %d/%d and %d/%d\n", tries, old_dat, dat, old_ctrl, ctrl); } } st->buffer_offset = -1; st->search_limit = 0; } // Done now, copy data while ((ret = packet_get_next_raw(st, &pkt)) == 0) { if (!is_nand(st, &pkt)) { packet_unget(st, &pkt); jstate_set(st, ST_SEARCHING); break; } if (st->nsec_dif > 0) { pkt.header.nsec += st->nsec_dif; if (pkt.header.nsec > 1000000000L) { pkt.header.nsec -= 1000000000L; pkt.header.sec++; } pkt.header.sec += st->sec_dif; } else { pkt.header.nsec -= st->nsec_dif; if (pkt.header.nsec <= 0) { pkt.header.nsec += 1000000000L; pkt.header.sec--; } pkt.header.sec -= st->sec_dif; } packet_write(st, &pkt); buffer_put_packet(st, &pkt); } return ret; }
static void *rtp_thread_func(void *arg) { socklen_t si_len = sizeof(rtp_client); char packet[MAX_PACKET]; char *pktp; seq_t seqno; ssize_t plen; int sock = rtp_sockets[0], csock = rtp_sockets[1]; int readsock; char type; fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); FD_SET(csock, &fds); while (select(csock>sock ? csock+1 : sock+1, &fds, 0, 0, 0)!=-1) { if (FD_ISSET(sock, &fds)) { readsock = sock; } else { readsock = csock; } FD_SET(sock, &fds); FD_SET(csock, &fds); plen = recvfrom(readsock, packet, sizeof(packet), 0, (struct sockaddr*)&rtp_client, &si_len); if (plen < 0) continue; #ifdef DEBUG assert(plen<=MAX_PACKET); #endif type = packet[1] & ~0x80; if (type == 0x60 || type == 0x56) { // audio data / resend pktp = packet; if (type==0x56) { pktp += 4; plen -= 4; } seqno = ntohs(*(unsigned short *)(pktp+2)); buffer_put_packet(seqno, pktp+12, plen-12); // adjust pointer and length pktp += 12; plen -= 12; // check if packet contains enough content to be reasonable if (plen >= 16) { buffer_put_packet(seqno, pktp, plen); } else { // resync? if (type == 0x56 && seqno == 0) { fprintf(stderr, "Suspected resync request packet received. Initiating resync.\n"); pthread_mutex_lock(&ab_mutex); ab_resync(); pthread_mutex_unlock(&ab_mutex); } } } } return 0; }