Exemplo n.º 1
0
static int handleDisconnect(participantsDb_t db,
			    struct slice *slice1,
			    struct slice *slice2,
			    int clNo)
{
    handleDisconnect1(slice1, clNo);
    handleDisconnect1(slice2, clNo);
    udpc_removeParticipant(db, clNo);
    return 0;
}
Exemplo n.º 2
0
static int handleDisconnect(participantsDb_t db,
                            struct slice *slice1,
                            struct slice *slice2,
                            int clNo)
{
    handleDisconnect1(db, slice1, clNo);
    handleDisconnect1(db, slice2, clNo);
    udpc_removeParticipant(db, clNo);
    if(udpc_nrParticipants(db) == 0)
        exit(0);
    return 0;
}
Exemplo n.º 3
0
static THREAD_RETURN netSenderMain(void *args0)
{
    sender_state_t sendst = (sender_state_t) args0;
    struct net_config *config = sendst->config;
    struct timeval tv;
    struct timespec ts;
    int atEnd = 0;
    int nrWaited=0;
    unsigned long waitAverage=10000; /* Exponential average of last wait times */

    struct slice *xmitSlice=NULL; /* slice being transmitted a first time */
    struct slice *rexmitSlice=NULL; /* slice being re-transmitted */
    int sliceNo = 0;

    /* transmit the data */
    if(config->default_slice_size == 0) {
#ifdef BB_FEATURE_UDPCAST_FEC
        if(config->flags & FLAG_FEC) {
            config->sliceSize = 
                config->fec_stripesize * config->fec_stripes;
        } else
#endif
          if(config->flags & FLAG_ASYNC)
            config->sliceSize = 1024;
        else if (sendst->config->flags & FLAG_SN) {
            sendst->config->sliceSize = 112;
        } else
            sendst->config->sliceSize = 130;
        sendst->config->discovery = DSC_DOUBLING;
    } else {
        config->sliceSize = config->default_slice_size;
#ifdef BB_FEATURE_UDPCAST_FEC
        if((config->flags & FLAG_FEC) &&
           (config->sliceSize > 128 * config->fec_stripes))
            config->sliceSize = 128 * config->fec_stripes;
#endif
    }

#ifdef BB_FEATURE_UDPCAST_FEC
    if( (sendst->config->flags & FLAG_FEC) &&
        config->max_slice_size > config->fec_stripes * 128)
      config->max_slice_size = config->fec_stripes * 128;
#endif

    if(config->sliceSize > config->max_slice_size)
        config->sliceSize = config->max_slice_size;

    assert(config->sliceSize <= MAX_SLICE_SIZE);

    do {
        /* first, cleanup rexmit Slice if needed */

        if(rexmitSlice != NULL) {
            if(rexmitSlice->nrReady == 
               udpc_nrParticipants(sendst->rc.participantsDb)){
#if DEBUG
                flprintf("slice is ready\n");
#endif
                ackSlice(rexmitSlice, sendst->config, sendst->fifo, 
                         sendst->stats);
            }
            if(isSliceAcked(rexmitSlice)) {
                freeSlice(sendst, rexmitSlice);
                rexmitSlice = NULL;
            }
        }

        /* then shift xmit slice to rexmit slot, if possible */
        if(rexmitSlice == NULL &&  xmitSlice != NULL && 
           isSliceXmitted(xmitSlice)) {
            rexmitSlice = xmitSlice;
            xmitSlice = NULL;
            sendReqack(rexmitSlice, sendst->config, sendst->fifo, sendst->stats,
                       sendst->socket);
        }

        /* handle any messages */
        if(pc_getWaiting(sendst->rc.incoming)) {
#if DEBUG
            flprintf("Before message %d\n",
                    pc_getWaiting(sendst->rc.incoming));
#endif
            handleNextMessage(sendst, xmitSlice, rexmitSlice);

            /* restart at beginning of loop: we may have acked the rxmit
             * slice, makeing it possible to shift the pipe */
            continue;
        }

        /* do any needed retransmissions */
        if(rexmitSlice != NULL && rexmitSlice->needRxmit) {
            doRetransmissions(sendst, rexmitSlice);
            /* restart at beginning: new messages may have arrived during
             * retransmission  */
            continue;
        }

        /* if all participants answered, send req ack */
        if(rexmitSlice != NULL && 
           rexmitSlice->nrAnswered == 
           udpc_nrParticipants(sendst->rc.participantsDb)) {
            rexmitSlice->rxmitId++;
            sendReqack(rexmitSlice, sendst->config, sendst->fifo, sendst->stats,
                       sendst->socket);
        }

        if(xmitSlice == NULL && !atEnd) {
#if DEBUG
            flprintf("SN=%d\n", sendst->config->flags & FLAG_SN);
#endif
            if((sendst->config->flags & FLAG_SN) ||
               rexmitSlice == NULL) {
#ifdef BB_FEATURE_UDPCAST_FEC
                if(sendst->config->flags & FLAG_FEC) {
                    int i;
                    pc_consume(sendst->fec_data_pc, 1);
                    i = pc_getConsumerPosition(sendst->fec_data_pc);
                    xmitSlice = &sendst->slices[i];
                    pc_consumed(sendst->fec_data_pc, 1);
                } else
#endif
                  {
                    xmitSlice = makeSlice(sendst, sliceNo++);
                }
                if(xmitSlice->bytes == 0)
                    atEnd = 1;
            }
        }
         
        if(xmitSlice != NULL && xmitSlice->state == SLICE_NEW) {
            sendSlice(sendst, xmitSlice, 0);
#if DEBUG
            flprintf("%d Interrupted at %d/%d\n", xmitSlice->sliceNo, 
                     xmitSlice->nextBlock, 
                     getSliceBlocks(xmitSlice, sendst->config));
#endif
            continue;
        }
        if(atEnd && rexmitSlice == NULL && xmitSlice == NULL)
            break;

        if(sendst->config->flags & FLAG_ASYNC)
            break;

#if DEBUG
        flprintf("Waiting for timeout...\n");
#endif
        gettimeofday(&tv, 0);
        ts.tv_sec = tv.tv_sec;
        ts.tv_nsec = (tv.tv_usec + 1.1*waitAverage) * 1000;

#ifdef WINDOWS
        /* Windows has a granularity of 1 millisecond in its timer. Take this
         * into account here */
        #define GRANULARITY 1000000
        ts.tv_nsec += 3*GRANULARITY/2;
        ts.tv_nsec -= ts.tv_nsec % GRANULARITY;
#endif

#define BILLION 1000000000

        while(ts.tv_nsec >= BILLION) {
            ts.tv_nsec -= BILLION;
            ts.tv_sec++;
        }

        if(rexmitSlice->rxmitId > 10)
            /* after tenth retransmission, wait minimum one second */
            ts.tv_sec++;

        if(pc_consumeAnyWithTimeout(sendst->rc.incoming, &ts) != 0) {
#if DEBUG
            flprintf("Have data\n");
#endif
            {
                struct timeval tv2;
                unsigned long timeout;
                gettimeofday(&tv2, 0);
                timeout = 
                    (tv2.tv_sec - tv.tv_sec) * 1000000+
                    tv2.tv_usec - tv.tv_usec;
                if(nrWaited)
                    timeout += waitAverage;
                waitAverage += 9; /* compensate against rounding errors */
                waitAverage = (0.9 * waitAverage + 0.1 * timeout);
            }
            nrWaited = 0;
            continue;
        }
        if(rexmitSlice == NULL) {
            udpc_flprintf("Weird. Timeout and no rxmit slice");
            break;
        }
        if(nrWaited > 5){
#ifndef WINDOWS
            /* on Cygwin, we would get too many of those messages... */
            udpc_flprintf("Timeout notAnswered=");
            udpc_printNotSet(sendst->rc.participantsDb, 
                             rexmitSlice->answeredSet);
            udpc_flprintf(" notReady=");
            udpc_printNotSet(sendst->rc.participantsDb, rexmitSlice->sl_reqack.readySet);
            udpc_flprintf(" nrAns=%d nrRead=%d nrPart=%d avg=%ld\n",
                          rexmitSlice->nrAnswered,
                          rexmitSlice->nrReady,
                          udpc_nrParticipants(sendst->rc.participantsDb),
                          waitAverage);
            nrWaited=0;
#endif
        }
        nrWaited++;
        if(rexmitSlice->rxmitId > config->retriesUntilDrop) {
            int i;
            for(i=0; i < MAX_CLIENTS; i++) {
                if(udpc_isParticipantValid(sendst->rc.participantsDb, i) && 
                   !BIT_ISSET(i, rexmitSlice->sl_reqack.readySet)) {
                    udpc_flprintf("Dropping client #%d because of timeout\n",
                                  i);
#ifdef USE_SYSLOG
                    syslog(LOG_INFO, "dropped client #%d because of timeout", 
                                    i);
#endif
                    udpc_removeParticipant(sendst->rc.participantsDb, i);
                    if(nrParticipants(sendst->rc.participantsDb) == 0)
                        exit(0);
                }
            }
            continue;
        }
        rexmitSlice->rxmitId++;
        sendReqack(rexmitSlice, sendst->config, sendst->fifo, sendst->stats,
                   sendst->socket);
    } while(udpc_nrParticipants(sendst->rc.participantsDb)||
            (config->flags & FLAG_ASYNC));
    cancelReturnChannel(&sendst->rc);
    return 0;
}