static THREAD_RETURN returnChannelMain(void *args) { struct returnChannel *returnChannel = (struct returnChannel *) args; fd_set read_set; int r=0; FD_ZERO(&read_set); while(1) { struct sockaddr_in from; int clNo; int pos = pc_getConsumerPosition(returnChannel->freeSpace); pc_consumeAny(returnChannel->freeSpace); do { struct timeval tv; if(returnChannel->stopIt) return 0; FD_SET(returnChannel->rcvSock,&read_set); tv.tv_sec=0; tv.tv_usec=100; r = select(returnChannel->rcvSock+1, &read_set, NULL, NULL, &tv); } while(r==0); RECV(returnChannel->rcvSock, returnChannel->q[pos].msg, from, returnChannel->config->portBase); clNo = udpc_lookupParticipant(returnChannel->participantsDb, &from); if (clNo < 0) { /* packet from unknown provenance */ continue; } returnChannel->q[pos].clNo = clNo; pc_consumed(returnChannel->freeSpace, 1); pc_produce(returnChannel->incoming, 1); } }
static int ackSlice(struct slice *slice, struct net_config *net_config, struct fifo *fifo, sender_stats_t stats) { if(slice->state == SLICE_ACKED) /* already acked */ return 0; if(!(net_config->flags & FLAG_SN)) { if(net_config->discovery == DSC_DOUBLING) { net_config->sliceSize += net_config->sliceSize / 4; if(net_config->sliceSize >= net_config->max_slice_size) { net_config->sliceSize = net_config->max_slice_size; net_config->discovery = DSC_REDUCING; } udpc_logprintf(udpc_log, "Doubling slice size to %d\n", net_config->sliceSize); } } slice->state = SLICE_ACKED; pc_produce(fifo->freeMemQueue, slice->bytes); /* Statistics */ senderStatsAddBytes(stats, slice->bytes); if(slice->bytes) { displaySenderStats(stats, net_config->blockSize, net_config->sliceSize); } /* End Statistics */ return 0; }
void udpc_initFifo(struct fifo *fifo, int blockSize) { fifo->dataBufSize = blockSize * 4096; fifo->dataBuffer = xmalloc(fifo->dataBufSize+4096); fifo->dataBuffer += 4096 - (((unsigned long)fifo->dataBuffer) % 4096); /* Free memory queue is initially full */ fifo->freeMemQueue = pc_makeProduconsum(fifo->dataBufSize, "free mem"); pc_produce(fifo->freeMemQueue, fifo->dataBufSize); fifo->data = pc_makeProduconsum(fifo->dataBufSize, "receive"); }
static void initReturnChannel(struct returnChannel *returnChannel, struct net_config *config, int sock) { returnChannel->config = config; returnChannel->rcvSock = sock; returnChannel->freeSpace = pc_makeProduconsum(QUEUE_SIZE,"msg:free-queue"); pc_produce(returnChannel->freeSpace, QUEUE_SIZE); returnChannel->incoming = pc_makeProduconsum(QUEUE_SIZE,"msg:incoming"); pthread_create(&returnChannel->thread, NULL, returnChannelMain, returnChannel); }
static THREAD_RETURN fecMain(void *args0) { sender_state_t sendst = (sender_state_t) args0; slice_t slice; int sliceNo = 0; while(1) { /* consume free slice */ slice = makeSlice(sendst, sliceNo++); /* do the fec calculation here */ fec_encode_all_stripes(sendst,slice); pc_produce(sendst->fec_data_pc, 1); } return 0; }
static int freeSlice(sender_state_t sendst, struct slice *slice) { int i; i = slice - sendst->slices; #if DEBUG flprintf("Freeing slice %p %d %d\n", slice, slice->sliceNo, i); #endif slice->state = SLICE_PRE_FREE; while(1) { int pos = pc_getProducerPosition(sendst->free_slices_pc); if(sendst->slices[pos].state == SLICE_PRE_FREE) sendst->slices[pos].state = SLICE_FREE; else break; pc_produce(sendst->free_slices_pc, 1); } return 0; }
static int handleNextMessage(sender_state_t sendst, struct slice *xmitSlice, struct slice *rexmitSlice) { int pos = pc_getConsumerPosition(sendst->rc.incoming); union message *msg = &sendst->rc.q[pos].msg; int clNo = sendst->rc.q[pos].clNo; #if DEBUG flprintf("handle next message\n"); #endif pc_consumeAny(sendst->rc.incoming); switch(ntohs(msg->opCode)) { case CMD_OK: handleOk(sendst, findSlice(xmitSlice, rexmitSlice, ntohl(msg->ok.sliceNo)), clNo); break; case CMD_DISCONNECT: handleDisconnect(sendst->rc.participantsDb, xmitSlice, rexmitSlice, clNo); break; case CMD_RETRANSMIT: #if DEBUG flprintf("Received retransmittal request for %ld from %d:\n", (long) xtohl(msg->retransmit.sliceNo), clNo); #endif handleRetransmit(sendst, findSlice(xmitSlice, rexmitSlice, ntohl(msg->retransmit.sliceNo)), clNo, msg->retransmit.map, msg->retransmit.rxmit); break; default: udpc_flprintf("Bad command %04x\n", (unsigned short) msg->opCode); break; } pc_consumed(sendst->rc.incoming, 1); pc_produce(sendst->rc.freeSpace, 1); return 0; }
int spawnNetSender(struct fifo *fifo, int sock, struct net_config *config, participantsDb_t db, sender_stats_t stats) { int i; sender_state_t sendst = MALLOC(struct senderState); sendst->fifo = fifo; sendst->socket = sock; sendst->config = config; sendst->stats = stats; #ifdef BB_FEATURE_UDPCAST_FEC if(sendst->config->flags & FLAG_FEC) sendst->fec_data = xmalloc(NR_SLICES * config->fec_stripes * config->fec_redundancy * config->blockSize); #endif sendst->rc.participantsDb = db; initReturnChannel(&sendst->rc, sendst->config, sendst->socket); sendst->free_slices_pc = pc_makeProduconsum(NR_SLICES, "free slices"); pc_produce(sendst->free_slices_pc, NR_SLICES); for(i = 0; i <NR_SLICES; i++) sendst->slices[i].state = SLICE_FREE; #ifdef BB_FEATURE_UDPCAST_FEC if(sendst->config->flags & FLAG_FEC) { /* Free memory queue is initially full */ fec_init(); sendst->fec_data_pc = pc_makeProduconsum(NR_SLICES, "fec data"); pthread_create(&sendst->fec_thread, NULL, fecMain, sendst); } #endif pthread_create(&fifo->thread, NULL, netSenderMain, sendst); return 0; }
static THREAD_RETURN returnChannelMain(void *args) { struct returnChannel *returnChannel = (struct returnChannel *) args; while(1) { struct sockaddr_in from; int clNo; int pos = pc_getConsumerPosition(returnChannel->freeSpace); pc_consumeAny(returnChannel->freeSpace); RECV(returnChannel->rcvSock, returnChannel->q[pos].msg, from, returnChannel->config->portBase); clNo = udpc_lookupParticipant(returnChannel->participantsDb, &from); if (clNo < 0) { /* packet from unknown provenance */ continue; } returnChannel->q[pos].clNo = clNo; pc_consumed(returnChannel->freeSpace, 1); pc_produce(returnChannel->incoming, 1); } return 0; }