SegmentTransposeCommand::SegmentTransposeCommand(SegmentSelection selection, bool changeKey, int steps, int semitones, bool transposeSegmentBack) :
        MacroCommand(tr("Change segment transposition"))
{
    //SegmentSelection selection(m_view->getSelection());
    for (SegmentSelection::iterator i = selection.begin();
            i != selection.end(); ++i) 
    {
        Segment &segment = **i;    
        processSegment(segment, changeKey, steps, semitones, transposeSegmentBack);
    }
}
Ejemplo n.º 2
0
void Server::incomingConnection( const qintptr socketHandle )
{
    QThread* workerThread = new QThread( this );
    ServerWorker* worker = new ServerWorker( socketHandle );

    worker->moveToThread( workerThread );

    connect( workerThread, SIGNAL( started( )),
             worker, SLOT( initConnection( )));
    connect( worker, SIGNAL( connectionClosed( )),
             workerThread, SLOT( quit( )));

    // Make sure the thread will be deleted
    connect( workerThread, SIGNAL( finished( )), worker, SLOT( deleteLater( )));
    connect( workerThread, SIGNAL( finished( )),
             workerThread, SLOT( deleteLater( )));

    // public signals/slots, forwarding from/to worker
    connect( worker, SIGNAL( registerToEvents( QString, bool,
                                               deflect::EventReceiver* )),
             this, SIGNAL( registerToEvents( QString, bool,
                                             deflect::EventReceiver* )));
    connect( this, SIGNAL( _pixelStreamerClosed( QString )),
             worker, SLOT( closeConnection( QString )));
    connect( this, SIGNAL( _eventRegistrationReply( QString, bool )),
             worker, SLOT( replyToEventRegistration( QString, bool )));

    // Commands
    connect( worker, SIGNAL( receivedCommand( QString, QString )),
             &_impl->commandHandler, SLOT( process( QString, QString )));

    // PixelStreamDispatcher
    connect( worker, SIGNAL( addStreamSource( QString, size_t )),
             &_impl->pixelStreamDispatcher, SLOT(addSource( QString, size_t )));
    connect( worker,
             SIGNAL( receivedSegement( QString, size_t, deflect::Segment )),
             &_impl->pixelStreamDispatcher,
             SLOT( processSegment( QString, size_t, deflect::Segment )));
    connect( worker,
             SIGNAL( receivedFrameFinished( QString, size_t )),
             &_impl->pixelStreamDispatcher,
             SLOT( processFrameFinished( QString, size_t )));
    connect( worker,
             SIGNAL( removeStreamSource( QString, size_t )),
             &_impl->pixelStreamDispatcher,
             SLOT( removeSource( QString, size_t )));

    workerThread->start();
}
SegmentTransposeCommand::SegmentTransposeCommand(Segment &segment, bool changeKey, int steps, int semitones, bool transposeSegmentBack) :
        MacroCommand(tr("Change segment transposition"))
{
    processSegment(segment, changeKey, steps, semitones, transposeSegmentBack);
}
Ejemplo n.º 4
0
/**
 * Perform one time step of Temporal Pooling for this Region.
 *
 * From the Numenta Docs:
 * The input to this code is activeColumns(t), as computed by the spatial pooler.
 * The code computes the active and predictive state for each cell at the
 * current timestep, t. The boolean OR of the active and predictive states
 * for each cell forms the output of the temporal pooler for the next level.
 *
 * Phase 1: compute the active state, activeState(t), for each cell.
 * The first phase calculates the activeState for each cell that is in a winning column.
 * For those columns, the code further selects one cell per column as the
 * learning cell (learnState). The logic is as follows: if the bottom-up
 * input was predicted by any cell (i.e. its predictiveState output was 1 due
 * to a sequence segment), then those cells become active (lines 23-27).
 * If that segment became active from cells chosen with learnState on, this
 * cell is selected as the learning cell (lines 28-30). If the bottom-up input
 * was not predicted, then all cells in the col become active (lines 32-34).
 * In addition, the best matching cell is chosen as the learning cell (lines 36-41)
 * and a new segment is added to that cell.
 *
 * Phase 2: compute the predicted state, predictiveState(t), for each cell.
 * The second phase calculates the predictive state for each cell. A cell will turn on
 * its predictive state output if one of its segments becomes active, i.e. if
 * enough of its lateral inputs are currently active due to feed-forward input.
 * In this case, the cell queues up the following changes: a) reinforcement of the
 * currently active segment (lines 47-48), and b) reinforcement of a segment that
 * could have predicted this activation, i.e. a segment that has a (potentially weak)
 * match to activity during the previous time step (lines 50-53).
 *
 * Phase 3: update synapses.
 * The third and last phase actually carries out learning. In this phase segment
 * updates that have been queued up are actually implemented once we get feed-forward
 * input and the cell is chosen as a learning cell (lines 56-57). Otherwise, if the
 * cell ever stops predicting for any reason, we negatively reinforce the segments
 * (lines 58-60).
 */
void performTemporalPooling(Region* region) {
  /*Phase 1: Compute cell active states and segment learning updates
  //18. for c in activeColumns(t)
  //19.
  //20.   buPredicted = false
  //21.   lcChosen = false
  //22.   for i = 0 to cellsPerColumn - 1
  //23.     if predictiveState(c, i, t-1) == true then
  //24.       s = getActiveSegment(c, i, t-1, activeState)
  //25.       if s.sequenceSegment == true then
  //26.         buPredicted = true
  //27.         activeState(c, i, t) = 1
  //28.         if segmentActive(s, t-1, learnState) then
  //29.           lcChosen = true
  //30.           learnState(c, i, t) = 1
  //31.
  //32.   if buPredicted == false then
  //33.     for i = 0 to cellsPerColumn - 1
  //34.       activeState(c, i, t) = 1
  //35.
  //36.   if lcChosen == false then
  //37.     i,s = getBestMatchingCell(c, t-1)
  //38.     learnState(c, i, t) = 1
  //39.     sUpdate = getSegmentActiveSynapses (c, i, s, t-1, true)
  //40.     sUpdate.sequenceSegment = true
  //41.     segmentUpdateList.add(sUpdate)*/
  int i;
  #pragma omp parallel for
  for(i=0; i<region->numCols; ++i) {
    Column* col = &(region->columns[i]);
    if(col->isActive) {
      bool buPredicted = false;
      bool learningCellChosen = false;
      int c;
      for(c=0; c<col->numCells; ++c) {
        Cell* cell = &(col->cells[c]);
        if(cell->wasPredicted) {
          Segment* segment = getPreviousActiveSegment(cell);

          if(segment!=NULL && segment->isSequence) {
            buPredicted = true;
            cell->isActive = true;

            if(region->temporalLearning && wasSegmentActiveFromLearning(segment)) {
              learningCellChosen = true;
              cell->isLearning = true;
            }
          }
        }
      }

      if(!buPredicted) {
        for(c=0; c<col->numCells; ++c)
          col->cells[c].isActive = true;
      }

      if(region->temporalLearning && !learningCellChosen) {
        /*printf("bestSeg for (%d %d)\n", col->cx(), col->cy());*/
        Segment* bestSeg = NULL;
        Segment** bestSegPtr = &bestSeg;
        int bestSegID = -1;
        Cell* bestCell = getBestMatchingCell(col, bestSegPtr, &bestSegID, 1, true);
        bestCell->isLearning = true;

        bestSeg = *bestSegPtr;

        /*
         * 1) need to processSegment before step1
         * 2) need a processSynapse and store wasActive to fix
         *    since asking wasSynapseActive is using isSynapseConnected
         */

        /*segUpdate is added internally to Cell's update list*/
        SegmentUpdateInfo* segmentToUpdate =
            updateSegmentActiveSynapses(bestCell, true, bestSegID, true);
        segmentToUpdate->numPredictionSteps = 1;/*sequence segment*/

        /*#bestSeg may be partial-sort-of match, but it could dec-perm
        //#other syns from different step if cell overlaps...
        //
        //#try better minOverlap to prevent bad boosting?
        //#try to disable learning if predictions match heavily?
        //
        //#Do we need to enforce max segments per cell?*/
      }
    }
  }

  /*Phase2
  //42. for c, i in cells
  //43.   for s in segments(c, i)
  //44.     if segmentActive(s, t, activeState) then
  //45.       predictiveState(c, i, t) = 1
  //46.
  //47.       activeUpdate = getSegmentActiveSynapses (c, i, s, t, false)
  //48.       segmentUpdateList.add(activeUpdate)
  //49.
  //50.       predSegment = getBestMatchingSegment(c, i, t-1)
  //51.       predUpdate = getSegmentActiveSynapses(
  //52.                                   c, i, predSegment, t-1, true)
  //53.       segmentUpdateList.add(predUpdate)*/
  #pragma omp parallel for
  for(i=0; i<region->numCols; ++i) {
    int c,s;
    for(c=0; c<region->columns[i].numCells; ++c) {
      Cell* cell = &(region->columns[i].cells[c]);

      /*process all segments on the cell to cache the activity for later*/
      for(s=0; s<cell->numSegments; ++s)
        processSegment(&(cell->segments[s]));

      for(s=0; s<cell->numSegments; ++s) {
        Segment* seg = &(cell->segments[s]);
        if(seg->isActive) {
          setCellPredicting(cell, true);

          /*a) reinforcement of the currently active segment*/
          if(region->temporalLearning) {
            /*add segment update to this cell
            //printf("updateSegment (%d,%d) is ",_columns[i].cx(), _columns[i].cy());*/
            updateSegmentActiveSynapses(cell, false, s, false);
          }
          break;
        }
      }

      /*b) reinforcement of a segment that could have predicted
      //   this activation, i.e. a segment that has a (potentially weak)
      //   match to activity during the previous time step (lines 50-53).*/
      if(region->temporalLearning && cell->isPredicting) {
        /*printf("predSegment is ");*/
        int predSegID = -1;
        Segment* predSegment = getBestMatchingPreviousSegment(cell, &predSegID);

        /*either update existing or add new segment for this cell considering
        //only segments matching the number of prediction steps of the
        //best currently active segment for this cell*/
        SegmentUpdateInfo* predSegUpdate =
            updateSegmentActiveSynapses(cell, true, predSegID, true);
        if(predSegment==NULL)
          predSegUpdate->numPredictionSteps = cell->predictionSteps+1;
      }
    }
  }

  /*Phase3
  //54. for c, i in cells
  //55.   if learnState(c, i, t) == 1 then
  //56.     adaptSegments (segmentUpdateList(c, i), true)
  //57.     segmentUpdateList(c, i).delete()
  //58.   else if predictiveState(c, i, t) == 0 and predictiveState(c, i, t-1)==1 then
  //59.     adaptSegments (segmentUpdateList(c,i), false)
  //60.     segmentUpdateList(c, i).delete()*/
  if(!region->temporalLearning)
    return;
  #pragma omp parallel for
  for(i=0; i<region->numCols; ++i) {
    int c;
    for(c=0; c<region->columns[i].numCells; ++c) {
      Cell* cell = &(region->columns[i].cells[c]);
      if(cell->isLearning) {
        applyCellSegmentUpdates(cell, true);
      }
      else if(!cell->isPredicting && cell->wasPredicted) {
        applyCellSegmentUpdates(cell, false);
      }
    }
  }
}
Ejemplo n.º 5
0
/**
 * Region Initialization (from Numenta docs):
 * Prior to receiving any inputs, the region is initialized by computing a list of initial
 * potential synapses for each column. This consists of a random set of inputs selected
 * from the input space. Each input is represented by a synapse and assigned a random
 * permanence value. The random permanence values are chosen with two criteria.
 * First, the values are chosen to be in a small range around connectedPerm (the minimum
 * permanence value at which a synapse is considered "connected"). This enables potential
 * synapses to become connected (or disconnected) after a small number of training
 * iterations. Second, each column has a natural center over the input region, and the
 * permanence values have a bias towards this center (they have higher values near
 * the center).
 *
 * In addition to this I have added a concept of Locality Radius, which is an
 * additional parameter to control how far away synapse connections can be made
 * instead of allowing connections anywhere.  The reason for this is that in the
 * case of video images I wanted to experiment with forcing each Column to only
 * learn on a small section of the total input to more effectively learn lines or
 * corners in a small section without being 'distracted' by learning larger patterns
 * in the overall input space (which hopefully higher hierarchical Regions would
 * handle more successfully).  Passing in 0 for locality radius will mean no restriction
 * which will more closely follow the Numenta doc if desired.
 *
 * @param inputSize: (x,y) size of input data matrix from the external source.
 * @param colGridSize: (x,y) number of Columns to create to represent this Region.
 * @param pctInputPerCol: Percent of input bits each Column has potential synapses for.
 * @param pctMinOverlap: Minimum percent of column's synapses for column to be considered.
 * @param localityRadius: Furthest number of columns away to allow distal synapses.
 * @param pctLocalActivity: Approximate percent of Columns within average receptive
 *  field radius to be winners after inhibition.
 * @param cellsPerCol: Number of (temporal context) cells to use for each Column.
 * @param segActiveThreshold: Number of active synapses to activate a segment.
 * @param newSynapseCount: number of new distal synapses added if none activated during
 *  learning.
 * @param inputData the array to be used for input data bits.  The contents
 *  of this array must be externally updated between time steps (between
 *  calls to Region.runOnce()).
 * @return a pointer to a newly allocated Region structure (NULL if any malloc calls
 *  have failed).
 */
Region* newRegion(int inputSizeX, int inputSizeY, int colGridSizeX, int colGridSizeY,
    float pctInputPerCol, float pctMinOverlap, int localityRadius,
    float pctLocalActivity, int cellsPerCol, int segActiveThreshold,
    int newSynapseCount, char* inputData) {

  Region* region = malloc(sizeof(Region));
  if(region==NULL) return NULL;

  region->inputWidth = inputSizeX;
  region->inputHeight = inputSizeY;
  region->nInput = region->inputWidth * region->inputHeight;
  region->iters = 0;
  region->inputData = inputData;

  region->localityRadius = localityRadius;
  region->cellsPerCol = cellsPerCol;
  region->segActiveThreshold = segActiveThreshold;
  region->newSynapseCount = newSynapseCount;

  region->pctInputPerCol = pctInputPerCol;
  region->pctMinOverlap = pctMinOverlap;
  region->pctLocalActivity = pctLocalActivity;

  region->spatialHardcoded = false;
  region->spatialLearning = true;
  region->temporalLearning = true;

  /*Reduce the number of columns and map centers of input x,y correctly.
  //column grid will be relative to size of input grid in both dimensions*/
  region->width = colGridSizeX;
  region->height = colGridSizeY;
  region->numCols = region->width*region->height;
  region->xSpace = (region->inputWidth-1*1.0) / fmaxf(1.0,(region->width-1));
  region->ySpace = (region->inputHeight-1*1.0) / fmaxf(1.0,(region->height-1));

  /*Create the columns based on the size of the input data to connect to.*/
  region->columns = malloc(region->numCols * sizeof(Column));
  if(region->columns==NULL) return NULL;

  int cx,cy;
  for(cx=0; cx<region->width; ++cx) {
    for(cy=0; cy<region->height; ++cy) {
      int srcPosX = roundf(cx*region->xSpace);
      int srcPosY = roundf(cy*region->ySpace);
      initColumn(&(region->columns[(cy*region->width)+cx]), region,
          srcPosX,srcPosY, cx,cy);
    }
  }

  /*  #size the output array as double grid for 4-cell, else just pad the first
  //  #array dimension for 2 or 3 cell (and same size if just 1-cell)
  //  if cellsPerCol==4:
  //    outShape = (len(self.columnGrid)*2, len(self.columnGrid[0])*2)
  //  else:
  //    outShape = (len(self.columnGrid)*cellsPerCol, len(self.columnGrid[0]))
  //  self.outData = numpy.zeros(outShape, dtype=numpy.uint8)*/

  /*how far apart are 2 Columns in terms of input space; calc radius from that*/
  float inputRadiusf = region->localityRadius*region->xSpace;

  /*Now connect all potentialSynapses for the Columns*/
  int synapsesPerSegment = 1;
  if(region->localityRadius==0)
    synapsesPerSegment = (region->inputWidth*region->inputHeight) * pctInputPerCol;
  else
    synapsesPerSegment = (inputRadiusf*inputRadiusf) * pctInputPerCol;

  /*The minimum number of inputs that must be active for a column to be
  //considered during the inhibition step.*/
  region->minOverlap = synapsesPerSegment * pctMinOverlap;

  /*int longerSide = max(_inputWidth, _inputHeight);
  //random.seed(42) #same connections each time for easier debugging*/

  /* create array of InputCells and array to hold subset of InputCells for
   * selecting random subsets within radius of spatial pooler columns */
  int i,s,x,y;
  int nc = region->nInput;
  region->inputCells = malloc(nc * sizeof(Cell));
  Cell** ssInputCells = malloc(nc * sizeof(Cell*));
  Cell** randCells = malloc(synapsesPerSegment * sizeof(Cell*));
  for(i=0; i<nc; ++i) {
    initInputCell(&(region->inputCells[i]), region, i);
    ssInputCells[i] = &(region->inputCells[i]);
  }

  int inputRadius = roundf(inputRadiusf);
  int minY = 0;
  int maxY = region->inputHeight-1;
  int minX = 0;
  int maxX = region->inputWidth-1;

  for(i=0; i<region->numCols; ++i) {
    if(region->spatialHardcoded) /*no proximal synpases for hardcoded case*/
      break;
    Column* col = &(region->columns[i]);

    /*restrict synapse connections if localityRadius is non-zero*/
    if(region->localityRadius > 0) {
      minY = max(0, col->iy-inputRadius);
      maxY = min(region->inputHeight-1, col->iy+inputRadius);
      minX = max(0, col->ix-inputRadius);
      maxX = min(region->inputWidth-1, col->ix+inputRadius);

      /*repopulate inputCells with cells within locality radius*/
      s=0;
      for(x=minX; x<=maxX; ++x) {
        for(y=minY; y<=maxY; ++y) {
          int index = (y*region->inputWidth)+x;
          ssInputCells[s++] = &(region->inputCells[index]);
        }
      }
      nc = s;
    }

    /*connect initial proximal synapses.
    //ensure we sample unique input positions to connect synapses to*/
    randomSample(ssInputCells, nc, randCells, synapsesPerSegment);

    /*printf("Column %d (%d, %d) connected to: ", i, col->cx, col->cy);*/
    for(s=0; s<synapsesPerSegment; ++s) {
      Cell* icell = randCells[s];
      /*printf("%d ", icell->index);*/
      if(FULL_DEFAULT_SPATIAL_PERMANENCE) {
        createSynapse(col->proximalSegment, icell, MAX_PERM);
      }
      else {
        /*default to all synapses having connected + 1/3.  Unused synapses will
         * be decremented away over time.  This is easier than having half the
         * synapses disconnected since it's harder for them to become connected
         * when first learning.*/
        int permanence = CONNECTED_PERM + (CONNECTED_PERM/3);
        createSynapse(col->proximalSegment, icell, permanence);
      }
    }
    /*printf("\n");*/

    processSegment(col->proximalSegment); /*calculate initial synapse connections*/

    /* This is code suggested by the Numenta doc.  I use fixed default permanence
     * instead to make initial learning faster/easier (based on my experiments).
    //    Util.createRandomSubset(allPos, randPos, synapsesPerSegment, rand);
    //    for(Point pt : randPos) {
    //      InputCell icell = new InputCell(
    //          pt.x, pt.y, (pt.y*_inputHeight)+pt.x, _inputData);
    //      if(FULL_DEFAULT_SPATIAL_PERMANENCE)
    //        col.addProximalSynapse(icell, 1.0f);
    //      else {
    //        double permanence = Synapse.CONNECTED_PERM +
    //                           (Synapse.PERMANENCE_INC*rand.nextGaussian());
    //        permanence = Math.max(0.0, permanence);
    //        double dx = col.ix()-pt.x;
    //        double dy = col.iy()-pt.y;
    //        double distance = Math.sqrt((dx*dx) + (dy*dy));
    //        double ex = distance / (longerSide*RAD_BIAS_STD_DEV);
    //        double localityBias = (RAD_BIAS_PEAK/0.4) * Math.exp((ex*ex)/-2);
    //        col.addProximalSynapse(icell, (float)(permanence*localityBias));
    //      }
    //    }*/
  }
  free(randCells);
  free(ssInputCells);

  if(!region->spatialHardcoded)
    region->inhibitionRadius = averageReceptiveFieldSize(region);
  else
    region->inhibitionRadius = 0;

  /*desiredLocalActivity A parameter controlling the number of columns that will be*/
  float dla = 0;
  if(region->localityRadius==0)
    dla = region->inhibitionRadius * region->pctLocalActivity;
  else
    dla = (region->localityRadius*region->localityRadius) * region->pctLocalActivity;
  region->desiredLocalActivity = max(2, round(dla));

  if(DEBUG) {
    printf("\nRegion Created (ANSI C)");
    printf("\ncolumnGrid = (%d, %d)", colGridSizeX, colGridSizeY);
    printf("\nxSpace, ySpace = %f %f", region->xSpace, region->ySpace);
    printf("\ninputRadius = %d", inputRadius);
    printf("\ninitial inhibitionRadius = %f", region->inhibitionRadius);
    printf("\ndesiredLocalActivity = %d", region->desiredLocalActivity);
    printf("\nsynapsesPerProximalSegment = %d", synapsesPerSegment);
    printf("\nminOverlap = %g", region->minOverlap);
    printf("\nconPerm,permInc = %i %i\n", CONNECTED_PERM, PERMANENCE_INC);
  }

  return region;
}
Ejemplo n.º 6
0
int main (){

  int sock_main, sock_timer;
  struct sockaddr_in main, timer;
  char buf[TCP_SEGMENT_SIZE];
  char hostname[128];
  gethostname (hostname, sizeof(hostname));
  hp = gethostbyname(hostname); 
  
  sock_main = socket (AF_INET, SOCK_DGRAM, 0);
  
  if (sock_main < 0){
    perror("opening UDP socket for main use");
    exit(1);
  }

  bzero ((char*)&main, sizeof (main));
  main.sin_family = AF_INET;
  main.sin_port = TCPD_PORT;
  bcopy((void *)hp->h_addr_list[0], (void *)&main.sin_addr, hp->h_length);
    
  if (bind(sock_main, (struct sockaddr *)&main, sizeof(main)) < 0){
    perror("getting socket name of main TCPD port");
    exit(2);
  }

  printf("TCPD MAIN SOCKET : PORT = %d ADDR = %d\n",main.sin_port,main.sin_addr.s_addr);  
 
  bzero((char*)&timer, sizeof(timer));
  timer.sin_family = AF_INET;
  timer.sin_port = TIMER_PORT;
  bcopy((void *)hp->h_addr_list[0], (void *)&timer.sin_addr, hp->h_length);
  
  /* TODO : Initialize send and receive windows */
  sendWindow.low = 100;
  sendWindow.high = sendWindow.low + WINDOW_SIZE * TCP_MSS;
  recvWindow.low = 100;
  recvWindow.high = recvWindow.low + WINDOW_SIZE * TCP_MSS;

  while (1){
    
      int type = 0;
      void *ptr = NULL;
      int send_bytes = 0;
      int sock  = 0;
      int rlen = 0;
      int i = 0;
      TCP_segment ts;
      TCP_segment ts_recv;
      TCP_segment* tsp;
      struct sockaddr_in name;
      
      /*
      printf("Inside child process to receive data\n");
      */
      printf("\n\n");
      
      /* Initialize buffer to all zeroes */
      bzero(buf, TCP_MSS);
       
      /* Receive data from UDP port */
      rlen = recvSegment((TCP_segment *)&ts, sock_main, main);
       
      /* Get segment type (LOCAL, REMOTE or TIMER) */
      type = getSegmentType (ts);      

      /*
      printf("Segment Type = %d len = %d\n",type,rlen);
      */
    
      /* Segment received from local application process */
      if (type == LOCAL_SEGMENT) {
        
        printf("Received local segment len = %d\n",rlen);
        printf("sBufCount = %d\n",sBufCount);

        printf("Send window : (%d, %d)\n",sendWindow.low, sendWindow.high);        
        
        /* Receiving destination address when a CONNECT is called*/
        if (ts.hdr.seq == DEST_INFO) {
          memcpy ((void*)&dest, (void*)&(ts.data), sizeof(struct sockaddr_in));
          printf("Received destination info from app\n");
          continue;
        }
        /* Receiving source address when a BIND is called*/
        else if (ts.hdr.seq == SRC_INFO) {
          memcpy ((void*)&src, (void*)&(ts.data), sizeof(struct sockaddr_in));
          printf("Received source info from app port = %d\n",src.sin_port);
          continue;
        }

        /* 
        memcpy((void*)&buf[0], (void*)&ts.data, rlen-TCP_HEADER_SIZE);
        for (i = 0; i < rlen-TCP_HEADER_SIZE; ++i)
          printf("%d", buf[i]);
        printf("Recv bytes = %d\n",rlen-TCP_HEADER_SIZE);
        */
        if (sBufCount == BUFFER_SIZE) continue;
        /*
        sBufCount++;
        */
        /* Construct TCP segment with received data */
        ts = constructSegment((void*)&ts.data, rlen-TCP_HEADER_SIZE);
             
        /* Sequence number gets incremented by 
         * 1 for each byte sent */
        nextSeq = nextSeq + rlen-TCP_HEADER_SIZE;

        /* Add segment to send buffer */
        /* TODO: Revisit buffer overflow logic here */
        
        memcpy((void*)&buf, (void*) &ts.data, rlen);
        /*
        for (i = 0; i < rlen; ++i)
          printf("%c");
        printf("\n");
        */
        sBufPtr = addToBuffer (sBufPtr, &sBufCount, ts, rlen); 
          
        /* Send from send buffer */
        sendFromSendBuffer (sBufPtr, sock_main, dest, timer, SEND_ALL, NULL); 
            
      }
      /* Segment received from remote process */
      
      else if (type == REMOTE_SEGMENT) {
        printf("Received remote segment len = %d\n",rlen);
        
        printf("Recv window : (%d, %d)\n",recvWindow.low, recvWindow.high);        
        
        /* TODO : Checksum here */ 
        /*
        printf("seq = %d crc = %d len = %d\n",ts.hdr.seq,ts.hdr.sum, rlen);
        
        memcpy((void*)&buf[0], (void*)&ts, rlen);
        for (i = 0; i < TCP_HEADER_SIZE; ++i)
          printf("%d",buf[i]);
        printf("\n");
        */

        /* Check if segment has valid checksum */
        if (!isValidChecksum(&ts, rlen)){
          printf("Checksum FAILURE\n");
          continue;
        }
        printf("Checksum SUCCESS\n");

 
        /* Check if ACK flag is set */
        if (isACK(&ts)){
          /* TODO :Handle ACK for already ACKed segments here */
          
            printf("Received ACK no = %d\n", ts.hdr.ack);
          
            /* Remove ACKed segment from buffer */
            sBufPtr = removeFromSendBuffer(sBufPtr, sock_main, timer, ts.hdr.ack);        
          
            /* Maintain ACK Count and compute RTO  */
            ackCount += 1;

            computeRTO ();

            continue;
        }
         
        /* Check if segment has valid checksum */
        /*
        if (!isValidChecksum(&ts, rlen)){
          printf("Checksum FAILURE");
          continue;
        }
        printf("Checksum SUCCESS\n");
        */
       
        /* Process received segment and return ptr to data*/
        ptr = processSegment((TCP_segment *)&ts, rlen);

        setACKFlag(&ts);

        /* TODO : How ACK set?*/
        ts.hdr.ack = ts.hdr.seq + rlen-TCP_HEADER_SIZE;
        if (isWithinWindow(recvWindow, ts.hdr.seq+rlen-TCP_HEADER_SIZE)|| (ts.hdr.seq < recvWindow.low)){
          
          int seq = ts.hdr.seq;            
          printf("Sending ACK for seq = %d\n",ts.hdr.seq);
          ts.hdr.seq = nextSeq;
          ts.hdr.urp = 0;
          ts.hdr.sum = 0;
          memcpy((void*)&buf, (void*)&ts, TCP_HEADER_SIZE);
  
          ts.hdr.sum = computeChecksum(&buf[0], TCP_HEADER_SIZE, &(ts.hdr.sum));
        
          /*
          printf("Checksum for ACK seq : %d crc : %d len : %d\n",ts.hdr.seq, ts.hdr.sum, TCP_HEADER_SIZE);
          
          for (i = 0; i < TCP_HEADER_SIZE; ++i)
            printf("%d",buf[i]);
          printf("\n");
          */
          /*ts.hdr.urp = REMOTE_SEGMENT;*/
          /*
          for (i = 0; i < TCP_HEADER_SIZE; ++i)
            printf("%d",buf[i]);
          printf("\n");
          */
          /* Sending ACK to remote process */
          sendSegment(&ts, TCP_HEADER_SIZE, sock_main, replyaddr);
          
          nextSeq = nextSeq + TCP_HEADER_SIZE;      
          ts.hdr.seq = seq;
        }
         /*printf("Sent ACK for seq = %d to dest = %d\n",ts.hdr.seq, replyaddr.sin_addr.s_addr);
          */
        if (!isWithinWindow(recvWindow, ts.hdr.seq+rlen-TCP_HEADER_SIZE) 
            || nextExpectedSeq > ts.hdr.seq){
            
          printf("Not within recv window seq = %d\n",ts.hdr.seq);
          continue;
        }
          
        printf("rBufCount = %d\n",rBufCount);          
        /*
        if (rBufPtr != NULL)  printf("RB : headseq = %d nes = %d\n",rBufPtr->ts.hdr.seq, nextExpectedSeq);
        if (rBufPtr != NULL && rBufPtr->ts.hdr.seq < nextExpectedSeq){
          printf("EXITING.......... \n");
          exit(1);
        }
        */
        /*
        if (nextExpectedSeq < recvWindow.low){
          printf("EXITING..\n");
          exit(1);
        }
        */
        
        if (rBufCount == BUFFER_SIZE) continue;
        
        /*rBufCount++;
        */
        /* TODO: Temporary hack to avoid recv buffer */
        /*sendData(&ts, rlen, sock_main, src);  
        
        continue;
        */

        /* Add segment to receive buffer */
        rBufPtr = addToBuffer (rBufPtr, &rBufCount, ts, rlen); 
          
        if (rBufPtr == NULL){
          printf("rbufptr = NULL post adding\n");
          continue; 
        }
        /* Update receive window */          
        updateWindow(&recvWindow, ts.hdr.seq, rlen-TCP_HEADER_SIZE); 
          
        /* Send data to local process */
        rBufPtr = sendFromRecvBuffer(rBufPtr, sock_main, src);
      }
      else if (type == TIMER_SEGMENT){

          TCP_buffer* ptr = NULL;

          printf("Received timer segment len = %d\n",rlen);
       
          memcpy((void*)&ptr, (void*)&(ts.data), sizeof(ptr));
          
          /* Update RTO on timeout. Message from timer 
           * implies timeout. */
          computeRTO();
          
          /* Retransmit segment to remote process */    
          sendFromSendBuffer (sBufPtr, sock_main, dest, timer, SEND_ONE, ptr);   
      }
  }  
  return 0;
}