Exemplo n.º 1
0
// ============================================================================================
void contribute_log_entry(uint32_t temperature_set, uint32_t onproportion_set,
                          uint32_t setpoint_set, uint32_t time_tick)

// Add part of an entry for logging - we don't log as often as we refresh the sample, so
// the purpose of this routine is to average the readings and write them at the logging interval.

{
    static uint32_t acc_temp = 0, acc_onprop = 0, acc_time = 0, acc_setpoint = 0;
    static uint32_t old_onprop = 0, old_setpoint = 0;
    uint32_t time_part;

    // Only work in integer seconds, to keep sizes under control
    time_tick/=mS;
    acc_time += time_tick;          // Time is in integer seconds

    if (acc_time >= sysConfig.recordInterval)
        {
            // It's time to write some data
            time_part = (sysConfig.recordInterval) - (acc_time - time_tick);
        }
    else
        time_part = time_tick;

    // Accumulate variables ....
    acc_temp += temperature_set * time_part;
    acc_onprop += onproportion_set * time_part;
    acc_setpoint += setpoint_set * time_part;

    if (acc_time >= sysConfig.recordInterval)
        {
            acc_onprop/=acc_time;
            acc_temp/=acc_time;
            acc_setpoint/=acc_time;

            // Write the average for this period of time
            if (old_onprop != acc_onprop)
                {
                    logWrite(LOG_ON_PERCENTAGE, acc_onprop);
                    old_onprop = acc_onprop;
                }

            if (old_setpoint != acc_setpoint)
                {
                    logWrite(LOG_SETPOINT_SET, acc_setpoint);
                    old_setpoint = acc_setpoint;
                }

            // We make sure temperature is written last as it simplifies reconstruction
            logWrite(LOG_TEMPERATURE, acc_temp);

            // Zero the variables
            acc_temp = 0;
            acc_onprop = 0;
            acc_time = 0;
            acc_setpoint = 0;

            // .. and store whatever is left over for the next minute
            if (time_tick-time_part)
                contribute_log_entry(temperature_set, onproportion_set, setpoint_set, time_tick - time_part);
        }
}
Exemplo n.º 2
0
void GLContext::scale(float scale)
{
    logWrite("scale: %.02f", scale);
    //Matrix::scaleM(modelMatrix, 0.0f, 0.0f, 0.8f);
    //transform_->scale(scale);
}
Exemplo n.º 3
0
void GLContext::translate(float x, float y)
{
    logWrite("translate: (%.02f, %.02f)", x, y);
    Matrix::translateM(modelMatrix, x/10., -y/10., 0.0f);
    //transform_->translate(x, y);
}
Exemplo n.º 4
0
void CTestMonitor::monitorQueueTimesBeforeReturnToFreeQueue(CVideoFrame* pFrame, CFrameGrinder* pFrameGrinder)
{
    std::string sLine;
    static struct timespec timeAtStartOfInterval = {0};
    std::string sMsg;
    unsigned int i = 0;
    double timeIntervalSeconds = 0.0;
    getTicks(&pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_FREE]);
    if (m_nTasksDone[TASK_DONE_CAMERA] >= NUMBER_OF_SAMPLES_PER_TEST_INTERVAL)
    {
        timeIntervalSeconds = getDeltaTimeSeconds(
                timeAtStartOfInterval,
                pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_FREE]);
        timeAtStartOfInterval = pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_FREE];
        if (m_nIntervalisUpperGoalFound == 0)
        {
            sLine += "Upper goal not found\n";
        }
        else
        {
            m_avgUpperGoalRectangle.center.x /= m_nIntervalisUpperGoalFound;
            m_avgUpperGoalRectangle.center.y /= m_nIntervalisUpperGoalFound;
            m_avgUpperGoalRectangle.angle /= m_nIntervalisUpperGoalFound;
            sLine += "Upper goal (";
            sLine += numberToText(m_nIntervalisUpperGoalFound);
            sLine += " in this interval) avg ";
            sLine += m_avgUpperGoalRectangle.displayText();
            sLine += "\n";
        }

        for (i = 0; i < NUMBER_OF_TIME_IN_TASK; i++)
        {
            m_avgElapsedSeconds[i] /= NUMBER_OF_SAMPLES_PER_TEST_INTERVAL;
        }
        m_avgTimeBetweenCameraFramesMilliseconds /= NUMBER_OF_SAMPLES_PER_TEST_INTERVAL;
        m_avgLatencyForProcessingFrameMilliseconds /= NUMBER_OF_SAMPLES_PER_TEST_INTERVAL;
        memcpy(&m_savedElapsedSeconds, &m_avgElapsedSeconds, sizeof (double)*NUMBER_OF_TIME_IN_TASK);
        sLine += displayQueueTimes(timeIntervalSeconds, pFrameGrinder);

        logWrite(sLine);
        sLine = "";

        for (i = 0; i < NUMBER_OF_TASK_DONE_TYPES; i++)
        {
            m_nTasksDone[i] = 0;
        }

        m_nIntervalisUpperGoalFound = 0;
        m_avgUpperGoalRectangle.init();

        m_nCountTestInterval = 0;
        memset(&m_avgElapsedSeconds, 0, sizeof (unsigned int)*NUMBER_OF_TIME_IN_TASK);
        m_avgTimeBetweenCameraFramesMilliseconds = 0;
        m_avgLatencyForProcessingFrameMilliseconds = 0;

        // 'true' is returned when the end of the interval is reached
        for (i = 0; i < CVideoFrame::NUMBER_OF_FRAME_QUEUES; i++)
        {
            pFrameGrinder->m_frameQueueList[i].m_droppedFrames = 0;
        }
    }
    if (pFrame->m_targetInfo.isUpperGoalFound())
    {
        m_nIntervalisUpperGoalFound++;
        m_avgUpperGoalRectangle.center.x += pFrame->m_upperGoalRectangle.center.x;
        m_avgUpperGoalRectangle.center.y += pFrame->m_upperGoalRectangle.center.y;
        m_avgUpperGoalRectangle.angle += pFrame->m_upperGoalRectangle.angle;
    }
    m_avgElapsedSeconds[TIME_IN_TASK_CAMERA] += getDeltaTimeSeconds(
            pFrame->m_timeRemovedFromQueue[(int) CVideoFrame::FRAME_QUEUE_FREE], // earlier time
            pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_BLOB_DETECT]); // later time

    m_avgElapsedSeconds[TIME_IN_TASK_WAIT_FOR_BLOB_DETECT] += getDeltaTimeSeconds(
            pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_BLOB_DETECT],
            pFrame->m_timeRemovedFromQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_BLOB_DETECT]);

    m_avgElapsedSeconds[TIME_IN_TASK_BLOB_DETECT] += getDeltaTimeSeconds(
            pFrame->m_timeRemovedFromQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_BLOB_DETECT],
            pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_TEXT_CLIENT]);

    m_avgElapsedSeconds[TIME_IN_TASK_WAIT_FOR_TEXT_CLIENT] += getDeltaTimeSeconds(
            pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_TEXT_CLIENT],
            pFrame->m_timeRemovedFromQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_TEXT_CLIENT]);

    m_avgElapsedSeconds[TIME_IN_TASK_TEXT_CLIENT] += getDeltaTimeSeconds(
            pFrame->m_timeRemovedFromQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_TEXT_CLIENT],
            pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_BROWSER_CLIENT]);

    m_avgElapsedSeconds[TIME_IN_TASK_WAIT_FOR_BROWSER_CLIENT] += getDeltaTimeSeconds(
            pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_BROWSER_CLIENT],
            pFrame->m_timeRemovedFromQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_BROWSER_CLIENT]);

    m_avgElapsedSeconds[TIME_IN_TASK_BROWSER_CLIENT] += getDeltaTimeSeconds(
            pFrame->m_timeRemovedFromQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_BROWSER_CLIENT],
            pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_FREE]);

    m_avgElapsedSeconds[TIME_TOTAL_CAMDONE_TO_TEXTDONE] += getDeltaTimeSeconds(
            pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_BLOB_DETECT],
            pFrame->m_timeAddedToQueue[(int) CVideoFrame::FRAME_QUEUE_WAIT_FOR_BROWSER_CLIENT]);
    m_avgTimeBetweenCameraFramesMilliseconds += pFrame->m_targetInfo.getTimeSinceLastCameraFrameMilliseconds();
    m_avgLatencyForProcessingFrameMilliseconds += pFrame->m_targetInfo.getTimeLatencyThisCameraFrameMilliseconds();
}
Exemplo n.º 5
0
void GLContext::rotate(float rotateX, float rotateY, float rotateZ)
{
    logWrite("rotate: (%.02f, %.02f, %.02f)", rotateX, rotateY, rotateZ);
    //Matrix::setRotateM(modelMatrix, 30.0f, 0.0f, 1.0f, 0.0f);
    //transform_->rotate(rotateX, rotateY, rotateZ);
}
Exemplo n.º 6
0
void handle_packet_buffer(struct timeval * deadline, fd_set * write_fds_copy)
{
  struct timeval now;
  packet_info packet;
  gettimeofday(&now, NULL);
  int index = 0;
  int error = 0;

#ifdef USE_PACKET_BUFFER
  if (packet_buffer_more())
  {
    packet = packet_buffer_front();
  }
  while (packet_buffer_more() && (deadline->tv_sec < now.tv_sec ||
        (deadline->tv_sec == now.tv_sec && deadline->tv_usec < now.tv_usec)))
  {
//    struct in_addr debug_temp;
//    debug_temp.s_addr = packet.ip;
//    printf("Sending packet to %s of size %ld\n", inet_ntoa(debug_temp),
//           packet.size);

    process_control_packet(packet, *deadline);

    packet_buffer_advance();
    if (packet_buffer_more())
    {
      packet = packet_buffer_front();
      deadline->tv_usec += packet.delta * 1000;
      if (deadline->tv_usec > 1000000)
      {
        deadline->tv_sec += deadline->tv_usec / 1000000;
        deadline->tv_usec = deadline->tv_usec % 1000000;
      }
    }
  }
#else
  if (write_buffer != NULL)
  {
    packet = write_buffer[write_buffer_index];

    while (deadline->tv_sec < now.tv_sec ||
           (deadline->tv_sec == now.tv_sec && deadline->tv_usec < now.tv_usec))
    {
      int delta = 0;
      index = insert_by_address(packet.ip, packet.source_port,
                                packet.dest_port);
      if (index == -1)
      {
        printf("No more connection slots.\n");
        clean_exit(1);
      }
      logWrite(CONTROL_RECEIVE, NULL, "Told to write %d bytes", packet.value);
      error = send_with_reconnect(index, packet.value);
      if (error > 0)
      {
        // There are bytes that were unwritten.
        buffer_full[index] = 1;
        logWrite(DELAY_DETAIL, NULL, "Buffer Full");
      }

      ++write_buffer_index;
      if (write_buffer_index == write_buffer_size)
      {
        // If we are going to wraparound, then we need to add the
        // delay of the remaining quanta time. This is to prevent a
        // single write from causing link saturation, for instance.
        write_buffer_index = 0;
        delta = QUANTA - write_delta_total;
        if (delta < 0)
        {
          delta = 0;
        }
      }
      while (write_buffer[write_buffer_index].type != PACKET_WRITE)
      {
        ++write_buffer_index;
        if (write_buffer_index == write_buffer_size)
        {
          // If we are going to wraparound, then we need to add the
          // delay of the remaining quanta time. This is to prevent a
          // single write from causing link saturation, for instance.
          write_buffer_index = 0;
          delta = QUANTA - write_delta_total;
          if (delta < 0)
          {
            delta = 0;
          }
        }
      }
      if (packet.delta == 0)
      {
        ++delta;
      }
      else
      {
        delta += packet.delta;
      }
      if (delta <= 0)
      {
        fprintf(stderr, "Delta is below 0! delta: %d, packet.delta %ld"
                ", write_delta_total: %d\n",
                delta, packet.delta, write_delta_total);
        clean_exit(1);
      }
      deadline->tv_usec += delta * 1000;
      if (deadline->tv_usec > 1000000)
      {
        deadline->tv_sec += deadline->tv_usec / 1000000;
        deadline->tv_usec = deadline->tv_usec % 1000000;
      }
    }
  }
#endif
}
Exemplo n.º 7
0
void init_pcap(int to_ms, unsigned short port, char * device) {
    char errbuf[PCAP_ERRBUF_SIZE];

    if (flag_debug) {
      printf("The sniff_interface: %s \n", device);
    }
    if (is_live)
    {
      logWrite(MAIN_LOOP, NULL,
               "Initializing pcap live interface with device %s, and port %d",
               device, port);
      // We are running using live data. device refers to the network
      // device.
      struct bpf_program fp;      /* hold compiled program     */
      bpf_u_int32 maskp;          /* subnet mask               */
      bpf_u_int32 netp;           /* ip                        */
      char string_filter[128];

      /* ask pcap for the network address and mask of the device */
      pcap_lookupnet(device, &netp, &maskp, errbuf);
      //For an unknown reason, netp has the wrong 4th number
      //addr.s_addr = netp;
      sprintf(string_filter, "port %d and tcp", port);

      /* open device for reading.
       * NOTE: We use non-promiscuous */
      descr = pcap_open_live(device, BUFSIZ, 0, to_ms, errbuf);
      if(descr == NULL) {
        printf("Error: pcap_open_live(): %s\n",errbuf);
        exit(1);
      }

      // Lets try and compile the program, optimized
      if(pcap_compile(descr, &fp, string_filter, 1, maskp) == -1) {
        fprintf(stderr,"Error: calling pcap_compile\n");
        exit(1);
      }
      // set the compiled program as the filter
      if(pcap_setfilter(descr,&fp) == -1) {
        fprintf(stderr,"Error: setting filter\n");
        exit(1);
      }

      /*
        if (pcap_setnonblock(descr, 1, errbuf) == -1){
        printf("Error: pcap_setnonblock(): %s\n",errbuf);
        exit(1);
        }
      */
    }
    else
    {
      logWrite(MAIN_LOOP, NULL, "Initializing pcap replay interface");
      // We are running offline using data recorded by tcpdump
      // earlier. device is the filename. If device == '-', then we
      // read from stdin.
      descr = pcap_open_offline(device, errbuf);
      if(descr == NULL) {
        printf("Error: pcap_open_offline(): %s\n", errbuf);
        exit(1);
      }
    }
//    pcapfd = pcap_fileno(descr);
    pcapfd = pcap_get_selectable_fd(descr);
    if (pcapfd == -1)
    {
      fprintf(stderr, "Error: pcap file descriptor is not selectable\n");
      exit(1);
    }
    init_sniff_rcvdb();

    loss_log = fopen("loss.log", "w"); //loss log

}
Exemplo n.º 8
0
void debugTestConsoleVars() {
	logWrite("Testing convars...");

	ConvarID cvar1 = Convar.Create("cvar1");
	ConvarID cvar2 = Convar.Create("cvar2",123.0f);
	ConvarID cvar3 = Convar.Create("cvar3",456);
	ConvarID cvar4 = Convar.Create("cvar4",cvar_read,cvar_write);

	logWrite("Initial cvar contents:");
	PRINT_CVAR(cvar1,"Var1")
	PRINT_CVAR(cvar2,"Var2")
	PRINT_CVAR(cvar3,"Var3")
	PRINT_CVAR(cvar4,"Var4")

	logWrite("Contents after setting stuff:");
	Convar[cvar1]->SetInt(Random.Int(111,999));
	PRINT_CVAR(cvar1,"Var1")
	Convar[cvar1]->SetFloat(Random.Float(111,999));
	PRINT_CVAR(cvar1,"Var1")

	Convar[cvar2]->SetInt(Random.Int(111,999));
	PRINT_CVAR(cvar2,"Var2")
	Convar[cvar2]->SetFloat(Random.Float(111,999));
	PRINT_CVAR(cvar2,"Var2")

	Convar[cvar3]->SetInt(Random.Int(111,999));
	PRINT_CVAR(cvar3,"Var3")
	Convar[cvar3]->SetFloat(Random.Float(111,999));
	PRINT_CVAR(cvar3,"Var3")

	Convar[cvar4]->SetInt(Random.Int(111,999));
	PRINT_CVAR(cvar4,"Var4")
	Convar[cvar4]->SetFloat(Random.Float(111,999));
	PRINT_CVAR(cvar4,"Var4")

	Convar.Create("cvar5");
	logWrite("Get CVAR1: %.5f",Convar.GetFloat("cvar1"));
	logWrite("Get CVAR5 with def 123: %.5f",Convar.GetFloat("cvar5",123));
	logWrite("Set CVAR1");
	Convar.SetFloat("cvar1",345);
	logWrite("Get CVAR1: %.5f",Convar.GetFloat("cvar1"));
	logWrite("Set CVAR6");
	logWrite("Get CVAR6 with def 123: %.5f",Convar.GetFloat("cvar6",123));
	Convar.SetFloat("cvar6",456456);
	logWrite("Get CVAR6: %.5f",Convar.GetFloat("cvar6"));

	logWrite("(cvar5 was created uninitialized, cvar6 was created implictly)");


	logWrite("Convar test passed!\n");
}
Exemplo n.º 9
0
void GLFWCALL debugThread_InfLoop(void* t) {
	logWrite("Infinite loop thread %d starts, thread ID 0x%X",(int)t,Thread.GetCurrentThreadID());
	while (1) Thread.Sleep();
}
Exemplo n.º 10
0
void Thread_Manager::Kill(ThreadID threadID) {
	logWrite("Killed thread (ThreadID[0x%x])",threadID);
	glfwDestroyThread(threadID);
}
Exemplo n.º 11
0
void debugTestMalloc() {
	logWrite("Testing memory allocation");
	float startTime;
	logDisableDebugOutput = true;

	void* ptrs[TEST_ALLOCATIONS_IN_CYCLE];
	for (int j = 0; j < TEST_ALLOCATION_CYCLES; j++) {
		logWrite("Memory alloc/free cycle %d, peak usage %d bytes",j,mem.malloc_max);
		startTime = curtime();

		for (int i = 0; i < TEST_ALLOCATIONS_IN_CYCLE; i++) {
			ptrs[i] = mem.alloc(TEST_ALLOCATION_CYCLE_SIZE);
			if (!ptrs[i]) {
				logError("Memory test failed: null block returned");
				return;
			}
		}

		for (int i = 0; i < TEST_ALLOCATIONS_IN_CYCLE; i++) mem.free(ptrs[i]);

		logWrite("Cycle time %.5f seconds",curtime() - startTime);
	}

	logWrite("Allocating large memory chunk (%d mb)",TEST_ALLOC_LARGE_CHUNK_MB);
	startTime = curtime();
	void* largePtr = mem.alloc(TEST_ALLOC_LARGE_CHUNK_MB*1024*1024);
	logWrite("Done, %.5f seconds",curtime() - startTime);
	if (!largePtr) {
		logError("Could not allocate large memory chunk");
	}

	logWrite("Filling with pattern...");
	startTime = curtime();
	for (int i = 0; i < TEST_ALLOC_LARGE_CHUNK_MB*1024*1024; i++) {
		((char*)largePtr)[i] = (i ^ 0xFF) & 0xFF;
	}
	logWrite("Done, %.5f seconds",curtime() - startTime);	
	mem.free(largePtr);


	logWrite("Testing string pool...");
	for (int i = 0; i < TEST_ALLOCATE_NUM_STRINGS; i++) {
		int strSize = Random.Int(1,TEST_ALLOCATE_MAX_STR_SIZE);
		char* strPtr = mem.alloc_string(strSize);
		if (mem.malloc_memory > 256*1024*1024) {
			logWrite("Too much memory used, terminating earlier with %d strings",i+1);
			break;
		}
		for (int j = 0; j < strSize; j++) strPtr[j] = (i ^ j) & 0xFF;
	}
	int stringpool_size = 0;
	int stringpool_used = 0;
	int stringpool_lost = 0;
	for (int i = 0; i <= mem.malloc_curstringpool; i++) { 
		stringpool_size += mem.malloc_stringpoolsz[i];
		stringpool_used += mem.malloc_curstringpoolsz[i];
		stringpool_lost += mem.malloc_stringpoolsz[i] - mem.malloc_curstringpoolsz[i];
		
		if ((mem.malloc_stringpoolsz[i] <= 0) || (mem.malloc_stringpoolsz[i] > 16384) ||
			(mem.malloc_curstringpoolsz[i] <= 0) || (mem.malloc_curstringpoolsz[i] > 16384)) {
			logError("Memory test failed: corrupted string pool block %d",i);
			return;
		}
	}

	logWrite("String pool usage: %d out of %d bytes (%.2f percent, lost %d bytes, %d entries used)",
			stringpool_used,stringpool_size,(100.0f*stringpool_used) / stringpool_size,stringpool_lost,mem.malloc_curstringpool+1);

	logWrite("Testing boundary overflow detection");
	char* testPtr = (char*)mem.alloc(512);
	testPtr[600] = 0x10;
	mem.free(testPtr);

	logWrite("Reinitializing memory (and console variables, they are in mem too)...");
	logWrite("You should see warning about memory leak");
	Convar.Deinitialize();
	Memory.Deinitialize();
	logDisableDebugOutput = false;
	Memory.Initialize();
	Convar.Initialize();

	logWrite("Memory allocation test passed!\n");
}
Exemplo n.º 12
0
ThreadID Thread_Manager::Create(ThreadFunction* funcptr, void* param) {
	ThreadID th = glfwCreateThread(funcptr,param);
	logWrite("Spawned thread [%p] (ThreadID[0x%x])",funcptr,th);
	return th;
}
Exemplo n.º 13
0
void Graphics_Manager::LoadGraphics(GraphicsID graphicsEntry) {
	logWrite("STUB CALL TO LOADGRAPHICS!!! FIXME");
}
Exemplo n.º 14
0
void Graphics_Manager::Initialize(bool PreloadTextures) {
	//Update maps info
	logWrite("Initializing graphics manager (updating texture file entries)");

	int TexSize = 0;
	DIR *directory;
	struct dirent *direntry;

	globalIDCounter = 0;
	graphicsEntries.Create();
	graphicsEntries.Preallocate(MAX_TEXTURE_FILE_ENTRIES);
	Animations.Initialize();

	directory = opendir("./data");
	while ((directory) && ((direntry = readdir(directory)) != 0)) {
		int len = strlen(direntry->d_name);
		switch (len) {
		case 1:
			if (direntry->d_name[0] == '.') continue;
		case 2:
			if (direntry->d_name[0] == '.' && direntry->d_name[1] == '.') continue;
		default:
			break;
		}

		//Check file format
		Chunk_Loader TEX;
		//Read map header
		char Filename[256];
		snprintf(Filename,256,"./data/%s",direntry->d_name);

		TEX.Open(Filename);
		if (TEX.IsFileFormat("ZTEX",TEX_VERSION) == false) {
			continue;
		}

		logWrite("Loading graphics from %s...",Filename);

		//Read all chunks from file
		int lastRead = 0;
		while (TEX.ReadChunk()) {
			LockID lockID = Thread.EnterLock(MUTEX_CRESOURCE_LOAD);
				Graphics.texReadGTA2Graphics(&TEX, false);
				Graphics.texReadFonts(&TEX, false);
				Animations.LoadFromChunk(&TEX);				
			Thread.LeaveLock(lockID);
		}
		TexSize += TEX.fileSize;
		TEX.Close();
	}
	if (directory) closedir(directory);

	totalTextures = globalIDCounter + 1;

	logWrite("Found %d KB worth of texture files (%d textures)",TexSize/1024,totalTextures);

	logWritem("shrinking graphicsEntries, animationEntries, fontEntries...");
	LockID lockID = Thread.EnterLock(MUTEX_CRESOURCE_LOAD);
		graphicsEntries.Shrink();
	Thread.LeaveLock(lockID);
	Animations.Entries.Shrink();
	//FIXME: should be shrink call directly
	Fonts.shrinkFontEntries(); //FIXME: ??? this should shrink font entries, call only after all fonts have been loaded
}
Exemplo n.º 15
0
void on_new_component(MX *mx, int fd, const char *name, void *udata)
{
    logWrite(logger, "New component %s on fd %d.\n", name, fd);
}
Exemplo n.º 16
0
//FIXME: a lot less map requests (therefore a lot higher map rendering speed) can be made
//if you draw volumes of cells separately. transparency may break
void Map_Render_Debug::drawPlane(int bx1, int by1, int bx2, int by2, int bz) {
	int tx = (int)floor(bx1 / 64.0f);
	int ty = (int)floor(by1 / 64.0f);
	rmp_cityscape* cityscape = Map.cellCityscape(tx,ty); //cityscape to gather data from
	
	for (int x = bx1; x <= bx2; x++)
		for (int y = by1; y <= by2; y++) {
			int cx = (int)floor(x / 64.0f); //current cityscape
			int cy = (int)floor(y / 64.0f);
			if ((tx != cx)  || (ty != cy)) {
				tx = cx; ty = cy; //precache new one
				cityscape = Map.cellCityscape(tx,ty);
			}

			int kx = x - 64*(x / 64);//abs(x % 64);//x-abs(cx*64);
			int ky = y - 64*(y / 64);//abs(y % 64);//y-abs(cy*64);

			//int texID = 

			if ((cityscape->rmp_city_scape) && (bz < cityscape->maxHeight)) {
				Vertex_Buffer* vBuffer = 0;
				TexID texBase = 0;
				for (uint i = 0; i < VBOEntry.Count; i++) {
					if (strcmp(VBOEntry[i]->GraphicsName,cityscape->GraphicsName[0]) == 0) { 
						vBuffer = &VBOEntry[i]->VBO;
						texBase = VBOEntry[i]->SpriteBase;
						break;
					}
				}

				if (vBuffer == 0) {
					//debugrender_vboentry* vboEntry = VBOEntry.Add();
					VBOEntry.Count++; //Add();
					if (VBOEntry.Count >= VBOEntry.AllocCount) {
						logWrite("BAD ERROR: attempting to draw more different VBO's than allocated entries");
						return;
					}
					VBOEntry[VBOEntry.Count-1]->GraphicsName = cityscape->GraphicsName[0];
					VBOEntry[VBOEntry.Count-1]->VBO.Clear();
					vBuffer = &VBOEntry[VBOEntry.Count-1]->VBO;

					//Get sprite base TexID to use later to bind texture atlas (also this is offset for blockgeometry)
					char texName[256];
					snprintf(texName,256,"%s_0",VBOEntry[VBOEntry.Count-1]->GraphicsName);
					VBOEntry[VBOEntry.Count-1]->SpriteBase = Graphics.GetTextureID(texName);
					texBase = VBOEntry[VBOEntry.Count-1]->SpriteBase;
				}

				//Block fetched from map:
				rmp_block_info* block = &cityscape->rmp_city_scape[bz*64*64+ky*64+kx];
				//Block with (possibly) animated textures:
				rmp_block_info _block;
				memcpy(&_block,block,sizeof(rmp_block_info));

				TexID tex_left =	texBase+block->tex_left;
				TexID tex_right =	texBase+block->tex_right;
				TexID tex_top =		texBase+block->tex_top;
				TexID tex_bottom =	texBase+block->tex_bottom;
				TexID tex_lid =		texBase+block->tex_lid;

				AnimSeqID anim_left		= Animations.GetAnimationSeq(tex_left);
				AnimSeqID anim_right	= Animations.GetAnimationSeq(tex_right);
				AnimSeqID anim_top		= Animations.GetAnimationSeq(tex_top);
				AnimSeqID anim_bottom	= Animations.GetAnimationSeq(tex_bottom);
				AnimSeqID anim_lid		= Animations.GetAnimationSeq(tex_lid);

				//Animate faces
				float tgtAnimationTime = 0.0f;
				if (anim_left != BAD_ID) { //HAX
					Animation anim = Animations.GetAnimation(anim_left);
					anim.startTime = 0.0f;

					_block.tex_left = anim.GetTexID()-texBase;
					tgtAnimationTime = Timer.Time() + anim.RemainingTime();
				}
				if (anim_right != BAD_ID) {
					Animation anim = Animations.GetAnimation(anim_right);
					anim.startTime = 0.0f;

					_block.tex_right = anim.GetTexID()-texBase;
					tgtAnimationTime = Timer.Time() + anim.RemainingTime();
				}
				if (anim_top != BAD_ID) {
					Animation anim = Animations.GetAnimation(anim_top);
					anim.startTime = 0.0f;

					_block.tex_top = anim.GetTexID()-texBase;
					tgtAnimationTime = Timer.Time() + anim.RemainingTime();
				}
				if (anim_bottom != BAD_ID) {
					Animation anim = Animations.GetAnimation(anim_bottom);
					anim.startTime = 0.0f;

					_block.tex_bottom = anim.GetTexID()-texBase;
					tgtAnimationTime = Timer.Time() + anim.RemainingTime();
				}
				if (anim_lid != BAD_ID) {
					Animation anim = Animations.GetAnimation(anim_lid);
					anim.startTime = 0.0f;

					_block.tex_lid = anim.GetTexID()-texBase;
					tgtAnimationTime = Timer.Time() + anim.RemainingTime();
				}
				if (tgtAnimationTime > 0.0f) {
					if (nextAnimationTime > 0.0f) {
						nextAnimationTime = min(tgtAnimationTime,nextAnimationTime);
					} else {
						nextAnimationTime = tgtAnimationTime;
					}
				}

				//if ((block->block_type & 0xF) > 0) 
				Map_Vertex_Geometry.blockGeometry(vBuffer, &_block, texBase, Vector3f(x*1.0f,y*1.0f,bz*1.0f-1.0f));
			}
		}
}
Exemplo n.º 17
0
void on_end_component(MX *mx, int fd, const char *name, void *udata)
{
    logWrite(logger, "End of component %s on fd %d.\n", name, fd);
}
Exemplo n.º 18
0
void Map_Manager::Initialize() {
	logWrite("Initializing map manager (scanning for maps)");

	DIR *directory;
	struct dirent *direntry;

	int MapSize = 0; //Total size of maps loaded (for stats)

	mapsInfo.Preallocate(1024);
	cacheCityscape.Preallocate(1024);

	directory = opendir("./data");
	while ((directory) && ((direntry = readdir(directory)) != 0)) {
		int len = strlen(direntry->d_name);
		switch (len) {
			case 1:
				if (direntry->d_name[0] == '.') continue;
			case 2:
				if (direntry->d_name[0] == '.' && direntry->d_name[1] == '.') continue;
			default:
				break;
		}

		Chunk_Loader RMP;

		//Read the map
		char Filename[256];
		snprintf(Filename,256,"./data/%s",direntry->d_name);

		RMP.Open(Filename);
		if (RMP.IsFileFormat("ZRMP",RMP_VERSION) == false) {
			continue;
		}

		//Read all chunks from file
		while (RMP.ReadChunk()) {
			if (RMP.IsChunk("RMAP")) { //Scan the chunk for district name, and cell coordinates
				int CX,CY;
				char districtName[5] = "    ";
				RMP.Read(&CX,4);
				RMP.Read(&CY,4);
				RMP.Read(districtName,4);
				
				//Check if the map entry was already there
				int idx = cellEntryIndex(CX,CY);
				if (idx == BAD_ID) {
					logWritem("Found cell [%d;%d belongs to %s]: %s",CX,CY,districtName,direntry->d_name);

					rmp_entry* entry = mapsInfo.Add();
					entry->CX = CX;
					entry->CY = CY;
					strncpy(entry->Filename,Filename,256);
				} else {
					logWritem("Duplicate map cell! No place for [%d;%d] from %s",CX,CY,direntry->d_name);
				}
			}
		}
		MapSize += RMP.fileSize;
		RMP.Close();
	}
	if (directory) closedir(directory);
	logWrite("Found %d KB worth of maps",MapSize/1024);
	
	//Shrink entry table
	mapsInfo.Shrink();
}
Exemplo n.º 19
0
int main(int argc, char *argv[]) {
  int sockfd_snd, sockfd_rcv_sender, sockfd_rcv_monitor, sockfd_monitor=-1;
  struct sockaddr_in my_addr;   // my address information
  struct sockaddr_in their_addr; // connector's address information
  fd_set read_fds_copy, write_fds_copy;
  socklen_t sin_size;
  struct timeval start_tv, left_tv;
  int yes=1;//, flag_send_monitor=0;
  struct timeval packet_deadline;
  struct in_addr addr;
  int flag_measure=0;
  char ch;
  unsigned short standalone_port = SENDER_PORT;
  // Do we use live data? Or previously recorded data?
  FILE * logfile = NULL;
  unsigned long quantum_no=0;
  int logflags = LOG_NOTHING;
  int select_count = 0;

  gettimeofday(&packet_deadline, NULL);

  init();

  //set up debug flag
  if (getenv("Debug")!=NULL)
    flag_debug=1;
  else
    flag_debug=0;
  flag_standalone = 0;

  /*
   * Process command-line arguments
   */
  while ((ch = getopt(argc,argv,"df:l:b:rst")) != -1) {
    switch (ch) {
      case 'd':
        flag_debug = 1; break;
      case 'f':
        if (logfile == NULL)
        {
          logfile = fopen(optarg, "a");
          if (logfile == NULL)
          {
            perror("Log fopen()");
            exit(1);
          }
        }
        break;
      case 'b':
        if (strcmp(optarg, "average") == 0)
        {
          bandwidth_method = BANDWIDTH_AVERAGE;
        } else if (strcmp(optarg, "max") == 0) {
          bandwidth_method = BANDWIDTH_MAX;
        } else if (strcmp(optarg, "vegas") == 0) {
          bandwidth_method = BANDWIDTH_VEGAS;
        } else if (strcmp(optarg, "buffer") == 0) {
          bandwidth_method = BANDWIDTH_BUFFER;
        } else {
          fprintf(stderr, "Unknown bandwidth method\n");
          usage();
          exit(1);
        }
        break;
      case 'l':
        if (strcmp(optarg, "everything") == 0)
        {
          logflags = LOG_EVERYTHING;
        }
        else if (strcmp(optarg, "nothing") == 0)
        {
          logflags = LOG_NOTHING;
        }
        else if (strcmp(optarg, "control-send") == 0)
        {
          logflags = logflags | CONTROL_SEND;
        }
        else if (strcmp(optarg, "control-receive") == 0)
        {
          logflags = logflags | CONTROL_RECEIVE;
        }
        else if (strcmp(optarg, "tcptrace-send") == 0)
        {
          logflags = logflags | TCPTRACE_SEND;
        }
        else if (strcmp(optarg, "tcptrace-receive") == 0)
        {
          logflags = logflags | TCPTRACE_RECEIVE;
        }
        else if (strcmp(optarg, "sniff-send") == 0)
        {
          logflags = logflags | SNIFF_SEND;
        }
        else if (strcmp(optarg, "sniff-receive") == 0)
        {
          logflags = logflags | SNIFF_RECEIVE;
        }
        else if (strcmp(optarg, "peer-write") == 0)
        {
          logflags = logflags | PEER_WRITE;
        }
        else if (strcmp(optarg, "peer-read") == 0)
        {
          logflags = logflags | PEER_READ;
        }
        else if (strcmp(optarg, "main-loop") == 0)
        {
          logflags = logflags | MAIN_LOOP;
        }
        else if (strcmp(optarg, "lookup-db") == 0)
        {
          logflags = logflags | LOOKUP_DB;
        }
        else if (strcmp(optarg, "delay-detail") == 0)
        {
            logflags = logflags | DELAY_DETAIL;
        }
        else if (strcmp(optarg, "packet-buffer-detail") == 0)
        {
            logflags = logflags | PACKET_BUFFER_DETAIL;
        }
        else
        {
            fprintf(stderr, "Unknown logging option %s\n", optarg);
            usage();
            exit(1);
        }
        break;
      case 's':
        flag_standalone = 1; break;
      case 'r':
        flag_standalone = 1;
        is_live = 0;
        break;
      case 't':
        flag_testmode = 1; break;
      default:
        fprintf(stderr,"Unknown option %c\n",ch);
        usage(); exit(1);
    }
  }
  argc -= optind;
  argv += optind;

  if (logfile == NULL)
  {
    logfile = stderr;
  }

  logInit(logfile, logflags, 1);

  if (flag_standalone) {
    if (argc != 3) {
      fprintf(stderr,"Wrong number of options for standalone: %i\n",argc);
      usage();
      exit(1);
    } else {
      flag_measure = 1;
//      rcvdb[0].valid = 1;
      standalone_port = atoi(argv[2]);
      inet_aton(argv[1], &addr);
      insert_fake(addr.s_addr, standalone_port);
//      rcvdb[0].ip    =  addr.s_addr;
//      rcvdb[0].sockfd= -1; //show error if used
//      rcvdb[0].last_usetime = time(NULL);
    }
    printf("Running in standalone mode\n");
  } else {
    if (argc != 1) {
      fprintf(stderr,"Wrong number of options: %i\n",argc);
      usage();
      exit(1);
    }
  }

  if (flag_testmode) {
      printf("Running in testmode\n");
      test_state = TEST_NOTSTARTED;
  }

  if (strlen(argv[0]) > 127) {
    fprintf(stderr,"Error: the <sniff-interface> name must be less than 127 characters \n");
    exit(1);
  }

//  strcpy(sniff_interface, argv[0]);


  //set up the sender connection listener
  if ((sockfd_rcv_sender = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("socket");
    exit(1);
  }
  if (setsockopt(sockfd_rcv_sender, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
    perror("setsockopt");
    exit(1);
  }
  my_addr.sin_family = AF_INET;           // host byte order
  my_addr.sin_port = htons(SENDER_PORT);  // short, network byte order
  my_addr.sin_addr.s_addr = INADDR_ANY;   // automatically fill with my IP
//  memset(&(my_addr.sin_zero), '\0', 8);   // zero the rest of the struct
  if (flag_debug) printf("Listen on %s\n",inet_ntoa(my_addr.sin_addr));
  if (bind(sockfd_rcv_sender, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
    perror("bind");
    exit(1);
  }
  if (listen(sockfd_rcv_sender, PENDING_CONNECTIONS) == -1) {
    perror("listen");
    exit(1);
  }

  //set up the monitor connection listener
  if ((sockfd_rcv_monitor = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("socket");
    exit(1);
  }
  if (setsockopt(sockfd_rcv_monitor, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
    perror("setsockopt");
    exit(1);
  }
  my_addr.sin_family = AF_INET;           // host byte order
  my_addr.sin_port = htons(MONITOR_PORT); // short, network byte order
  my_addr.sin_addr.s_addr = INADDR_ANY;   // automatically fill with my IP
//  memset(&(my_addr.sin_zero), '\0', 8);   // zero the rest of the struct
  if (flag_debug) printf("Listen on %s\n",inet_ntoa(my_addr.sin_addr));
  if (bind(sockfd_rcv_monitor, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
    perror("bind");
    exit(1);
  }
  if (listen(sockfd_rcv_monitor, 1) == -1) {
    perror("listen");
    exit(1);
  }

  //initialization
  packet_buffer_init();
  init_random_buffer();
  init_pcap(SNIFF_TIMEOUT, standalone_port, argv[0]);
  FD_ZERO(&read_fds);
  FD_ZERO(&read_fds_copy);
  FD_ZERO(&write_fds);
  FD_ZERO(&write_fds_copy);
  FD_SET(pcapfd,  &read_fds);
  FD_SET(sockfd_rcv_sender,  &read_fds);
  FD_SET(sockfd_rcv_monitor, &read_fds);
  maxfd = pcapfd; //socket order
  sin_size = sizeof(struct sockaddr_in);

  //main loop - the stubd runs forever
  while (1) {
//    flag_send_monitor=0; //reset flag for each quanta
    gettimeofday(&start_tv, NULL); //reset start time for each quanta

//    printf("Total: %d\n", total_size);
//    printf("========== Quantum %lu ==========\n", quantum_no);
    logWrite(MAIN_LOOP, NULL, "Quantum %lu", quantum_no);
    if (is_live)
    {
        update_stats();
        logWrite(MAIN_LOOP, NULL, "PCAP Received: %u Dropped: %u",
                 received_stat(), dropped_stat());
    }
    quantum_no++;

    //while in a quanta
    while(have_time(&start_tv, &left_tv)) {
      read_fds_copy  = read_fds;
      write_fds_copy = write_fds;

      select_count = select(maxfd+1, &read_fds_copy, &write_fds_copy, NULL,
                            &left_tv);
      if (select_count == -1)
      {
        perror("select");
        clean_exit(1);
      }
//      fprintf(stderr, "Select count: %d\n", select_count);
      // Send out packets to our peers if the deadline has passed.
//      logWrite(MAIN_LOOP, NULL, "Send normal packets to peers");
      handle_packet_buffer(&packet_deadline, &write_fds_copy);

      // send to destinations which are writeable and are behind.
//      logWrite(MAIN_LOOP, NULL, "Send pending packets to peers");
#ifdef USE_PACKET_BUFFER
      for_each_pending(try_pending, &write_fds_copy);
#endif

      // receive from existing senders
//      logWrite(MAIN_LOOP, NULL, "Receive packets from peers");
      for_each_readable_sender(receive_sender, &read_fds_copy);

/*
      //receive from existent senders
      for (i=0; i<CONCURRENT_SENDERS; i++){
        // Send pending data if it exists.
        if (snddb[i].valid==1 && FD_ISSET(snddb[i].sockfd, &read_fds_copy)) {
          receive_sender(i);
        }
      }
*/
      //handle new senders
      if (FD_ISSET(sockfd_rcv_sender, &read_fds_copy)) {
        if ((sockfd_snd = accept(sockfd_rcv_sender, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
          perror("accept");
          continue;
        } else {
          logWrite(MAIN_LOOP, NULL, "Accept new peer (%s)",
                   inet_ntoa(their_addr.sin_addr));
          replace_sender_by_stub_port(their_addr.sin_addr.s_addr,
                                      ntohs(their_addr.sin_port), sockfd_snd,
                                      &read_fds);
//        insert_db(their_addr.sin_addr.s_addr, their_addr.sin_port,
//                  SENDER_PORT, sockfd_snd, 1); //insert snddb
//        FD_SET(sockfd_snd, &read_fds); // add to master set
//        if (sockfd_snd > maxfd) { // keep track of the maximum
//          maxfd = sockfd_snd;
//        }
          if (flag_debug) printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
        }
      }

      //handle the new monitor
      if (FD_ISSET(sockfd_rcv_monitor, &read_fds_copy)) {
        if ((sockfd_monitor = accept(sockfd_rcv_monitor, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
          perror("accept");
          continue;
        } else {
          int nodelay = 1;
          int nodelay_error = setsockopt(sockfd_monitor, IPPROTO_TCP,
                                         TCP_NODELAY, &nodelay,
                                         sizeof(nodelay));
          if (nodelay_error == -1)
          {
            perror("setsockopt (TCP_NODELAY)");
            clean_exit(1);
          }
          logWrite(MAIN_LOOP, NULL, "Accept new monitor (%s)",
                   inet_ntoa(their_addr.sin_addr));

          FD_CLR(sockfd_rcv_monitor, &read_fds);  //allow only one monitor connection
          FD_SET(sockfd_monitor, &read_fds);  //check the monitor connection for read
//        FD_SET(sockfd_monitor, &write_fds); //check the monitor connection for write
          if (sockfd_monitor > maxfd) { //keep track of the maximum
            maxfd = sockfd_monitor;
          }
          if (flag_debug) printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
        }
      }

      //receive from the monitor
      if (sockfd_monitor!=-1 && FD_ISSET(sockfd_monitor, &read_fds_copy)) {
        logWrite(MAIN_LOOP, NULL, "Receive control message from monitor");
        if (receive_monitor(sockfd_monitor, &packet_deadline) == 0) { //socket_monitor closed by peer
          FD_CLR(sockfd_monitor, &read_fds); //stop checking the monitor socket
//        FD_CLR(sockfd_monitor, &write_fds);
          sockfd_monitor = -1;
          FD_SET(sockfd_rcv_monitor, &read_fds); //start checking the receiver control socket
          if (sockfd_rcv_monitor > maxfd) { // keep track of the maximum
            maxfd = sockfd_rcv_monitor;
          }
        }
      }

      //sniff packets
      if (FD_ISSET(pcapfd, &read_fds_copy)) {
        logWrite(MAIN_LOOP, NULL, "Sniff packet stream");
        sniff();
      }

    } //while in quanta

    //send measurements to the monitor once in each quanta
    if (sockfd_monitor!=-1)
// && FD_ISSET(sockfd_monitor, &write_fds_copy)) {
    {
        logWrite(MAIN_LOOP, NULL, "Send control message to monitor");
        if (send_monitor(sockfd_monitor) == 0) { //socket_monitor closed by peer
            logWrite(MAIN_LOOP, NULL, "Message to monitor failed");
            FD_CLR(sockfd_monitor, &read_fds); //stop checking the monitor socket
//        FD_CLR(sockfd_monitor, &write_fds);
            sockfd_monitor = -1;
            FD_SET(sockfd_rcv_monitor, &read_fds); //start checking the receiver control socket
            if (sockfd_rcv_monitor > maxfd) { // keep track of the maximum
                maxfd = sockfd_rcv_monitor;
            }
        } else {
            logWrite(MAIN_LOOP, NULL, "Message to monitor succeeded");
//        flag_send_monitor=1;
        }
    }

    // In testmode, we only start printing in the quanta we first see a packet
    if (flag_standalone) {
      print_measurements();
    }

    // If running in testmode, and the test is over, exit!
    if (flag_testmode && test_state == TEST_DONE) {
      printf("Test done - total bytes transmitted: %llu\n",total_bytes);
      break;
    }
  } //while forever

  packet_buffer_cleanup();

  return 0;
}
Exemplo n.º 20
0
u_int16_t handle_IP(u_char *args, const struct pcap_pkthdr* pkthdr, const u_char* packet){
  const struct my_ip* ip;
  const struct tcphdr *tp;
  const struct udphdr *up;
  u_char *cp;
  u_int length = pkthdr->len;
  u_int caplen = pkthdr->caplen;
  u_short len, hlen, version, tcp_hlen, ack_bit;
  u_long  seq_start, seq_end, ack_seq, ip_src, ip_dst;
  unsigned short source_port = 0;
  unsigned short dest_port = 0;
  int path_id, record_id, msecs, end;
  sniff_path *path;
  unsigned int acked_size, tmpuint;
//  struct in_addr debug_addr;

  /* jump pass the ethernet header */
  ip = (struct my_ip*)(packet + sizeof(struct ether_header));
  length -= sizeof(struct ether_header);
  caplen -= sizeof(struct ether_header);

  /* check if we have captured enough to continue parse */
  if (caplen < sizeof(struct my_ip)) {
    printf("Error: truncated ip header - %d bytes missing \n",sizeof(struct my_ip)-caplen);
    return -1;
  }

  len     = ntohs(ip->ip_len);
  hlen    = IP_HL(ip); /* header length */
  version = IP_V(ip);  /* ip version */

  /* check version, we will take care of ipv6 later */
  if(version != 4){
    fprintf(stdout,"Error: unknown version %d\n",version);
    return -1;
  }

  /* check header length */
  if(hlen < 5 ){
    fprintf(stdout,"Error: bad ip header length: %d \n",hlen);
    return -1;
  }

  /* see if we have as much packet as we should */
  if(length < len) {
    printf("Error: truncated ip - %d bytes missing\n",len - length);
    return -1;
  }

  /* Check only the unfragmented datagram or the last fragment */
  /* Note: assume all fregments have the same header fields except the segmentation offset and flag */
  if((ntohs(ip->ip_off) & IP_MF) != 1 ) { /* aka the 14 bit != 1 */
    ip_src = ip->ip_src.s_addr;
    ip_dst = ip->ip_dst.s_addr;

    if (flag_debug){
      //Note:inet_ntoa returns the same string if called twice in one line due to static string buffer
      fprintf(stdout,"IP src:%s ", inet_ntoa(ip->ip_src));
      fprintf(stdout,"dst:%s hlen:%d version:%d len:%d\n",inet_ntoa(ip->ip_dst),hlen,version,len);
    }
    /*jump pass the ip header */
    cp = (u_char *)ip + (hlen * 4);
    caplen -=  (hlen * 4);
    length -=  (hlen * 4);

    switch (ip->ip_p) {
    case IPPROTO_TCP:
      if (caplen < sizeof(struct tcphdr)) {
        printf("Error: truncated tcp header - %d bytes missing\n", sizeof(struct tcphdr)-caplen);
        return -1;
      }

      tp = (struct tcphdr *)cp;
      tcp_hlen  = ((tp)->doff & 0x000f);
      length   -= (tcp_hlen * 4); //jump pass the tcp header
      caplen   -= (tcp_hlen * 4); //jump pass the tcp header
      seq_start = ntohl(tp->seq);
      seq_end   = ((unsigned long)(seq_start+length));
      ack_bit= ((tp)->ack & 0x0001);
      source_port = htons(tp->source);
      dest_port = htons(tp->dest);

      if (flag_standalone)
      {
        // If this is standalone mode, the stub_port entry will be the
        // destination port requested by the command line.
        path_id = find_by_stub_port(ip_dst, dest_port);
      }
      else
      {
        // I contacted the receiver. Therefore, my port is unique and
        // the receiver's port is fixed. The destination is the
        // receiver, therefore my port is the one that is of interest.
        path_id = find_by_stub_port(ip_dst, source_port);
      }
      if (path_id != -1) { //a monitored outgoing packet
        //ignore the pure outgoing ack
        if ((ack_bit==1) && (seq_end==seq_start)) {
          return 0;
        }

        path = &(sniff_rcvdb[path_id]);
        loss_records[path_id].total_counter++;

        if (path->end == path->start){ //no previous packet
          throughputInit(&throughput[path_id], seq_start, &(pkthdr->ts));
          throughputProcessSend(&throughput[path_id], seq_start, length);
          return push_sniff_rcvdb(path_id, seq_start, seq_end, &(pkthdr->ts), pkthdr->len); //new packet
        } else {
          throughputProcessSend(&throughput[path_id], seq_start, length);
          //find the real received end index
          end  = nnmod(path->end-1, SNIFF_WINSIZE);

          //if the packet has no payload
          if (seq_end == seq_start) {
            if ((path->records[end].seq_end==path->records[end].seq_start) &&  (path->records[end].seq_end==seq_end)) {
              //the last packet also has no payload and has the same seqnum, pure resent
              loss_records[path_id].loss_counter++;
              fprintf(loss_log, "Resent: %lu\n",seq_end); //loss log
              fflush(loss_log); //loss log
            } else {
              return push_sniff_rcvdb(path_id, seq_start, seq_end, &(pkthdr->ts), pkthdr->len); //new packet
            }
          } else if (seq_start >= path->records[end].seq_end) { //new packet
            return push_sniff_rcvdb(path_id, seq_start, seq_end, &(pkthdr->ts), pkthdr->len);
          } else { //resend
            loss_records[path_id].loss_counter++;
            if (seq_end > path->records[end].seq_end){ //partial resend
              fprintf(loss_log, "Resent: %lu to %lu\n",seq_start, path->records[end].seq_end-1); //loss log
              fflush(loss_log); //loss log
              tmpuint = pkthdr->len - (path->records[end].seq_end-seq_start);
              return push_sniff_rcvdb(path_id, path->records[end].seq_end, seq_end, &(pkthdr->ts), tmpuint);
            }
            fprintf(loss_log, "Resent: %lu to %lu\n",seq_start, seq_end-1); //loss log
            fflush(loss_log); //loss log
          } // if has payload and resent
        }

      } else {
        if (flag_standalone)
        {
          // If this is standalone mode, and the packet is incoming,
          // then the source_port will be the remote port requested on
          // the command line.
          path_id = find_by_stub_port(ip_src, source_port);
        }
        else
        {
          // I contacted the receiver, so my port is unique and their
          // port is the same every time. This means that if a packet is
          // coming from them, the destination port is the one of
          // interest.
          path_id = find_by_stub_port(ip_src, dest_port);
        }
        if (path_id != -1) { //a monitored incoming packet
          if (ack_bit == 1) { //has an acknowledgement
            ack_seq    = ntohl(tp->ack_seq);
            acked_size = 0;

            record_id = search_sniff_rcvdb(path_id, (unsigned long)(ack_seq-1));
           /* Note: we use the in-flight widnow to igore the duplicate Acks in the delay estimation
            * because TCP don't use them to calculate the sample RTT in the RTT estimation */
            if (record_id != -1) { //new ack received
              int delay = 0;
              struct tcp_info info;
              int info_size = sizeof(info);
              int error = 0;

              if (is_live)
              {
                error = getsockopt(rcvdb[path_id].sockfd,
                                   SOL_TCP, TCP_INFO, &info,
                                       &info_size);
                if (error == -1)
                {
                  perror("getsockopt() TCP_INFO");
                  clean_exit(1);
                }
                if ((info.tcpi_snd_cwnd < info.tcpi_snd_ssthresh
                     || ((unsigned int)(tp->window)
                         << info.tcpi_rcv_wscale)
                     <= (info.tcpi_unacked * 1448))
                  && bandwidth_method == BANDWIDTH_BUFFER)
                {
                  // We are in slow start. This means that even if the
                  // socket buffer is full, we are still not sending
                  // at the ABW rate.
                  buffer_full[path_id] = 0;
                  last_through[path_id] = INT_MAX;
                  logWrite(DELAY_DETAIL, NULL, "Buffer Clear");
                }
                logWrite(DELAY_DETAIL, NULL, "receive_window: %u, unacked: %u",
                         (unsigned int)(tp->window)
                         << info.tcpi_rcv_wscale,
                         info.tcpi_unacked * 1448);
              }

              msecs = floor((pkthdr->ts.tv_usec-sniff_rcvdb[path_id].records[record_id].captime.tv_usec)/1000.0+0.5);
              delay = (pkthdr->ts.tv_sec-sniff_rcvdb[path_id].records[record_id].captime.tv_sec)*1000 + msecs;
              if (delay != 0)
              {
                delays[path_id] += delay;
                (delay_count[path_id])++;
                if (delay < base_rtt[path_id])
                {
                  base_rtt[path_id] = delay;
                }
                logWrite(DELAY_DETAIL, NULL, "delay: %d, max_delay: %d",
                         delay, max_delay[path_id]);
                if (delay > max_delay[path_id])
                {
                  max_delay[path_id] = delay + delay/10 + 1;
                }
                if (is_live && delay_count[path_id] > 0
                    && bandwidth_method == BANDWIDTH_VEGAS)
                {
                    int bandwidth = 0;
                    bandwidth = (info.tcpi_unacked/*tcpi_snd_cwnd*/
                                 * info.tcpi_snd_mss * 8)
                        / base_rtt[path_id];
                    if (bandwidth > max_throughput[path_id])
                    {
                        max_throughput[path_id] = bandwidth;
                    }
                    logWrite(DELAY_DETAIL, NULL,
                             "Kernel RTT: %lu, Kernel Losses: %lu, "
                             "Receive Window: %lu, Kernel packets out: %lu",
                             info.tcpi_rtt, info.tcpi_lost, tp->window,
                             info.tcpi_unacked);
                    logWrite(DELAY_DETAIL, NULL,
                             "Tput: %lu, cwnd: %lu, snd_MSS: %lu bytes, "
                             "Base RTT: %lu",
                             bandwidth, info.tcpi_snd_cwnd, info.tcpi_snd_mss,
                             base_rtt[path_id]);
                }
                else if (bandwidth_method == BANDWIDTH_MAX)
                {
                  int goodput = 0;
                  goodput = throughputTick(&throughput[path_id]);
                  logWrite(DELAY_DETAIL, NULL, "Goodput: %d", goodput);
                  if (goodput > max_throughput[path_id])
                  {
                    max_throughput[path_id] = goodput;
                  }
                }
//              append_delay_sample(path_id, delay, &(pkthdr->ts));
                logWrite(DELAY_DETAIL, &(pkthdr->ts),
                         "Delay: %lu, Sum: %lu, Count: %lu", delay,
                         delays[path_id], delay_count[path_id]);
              }

              acked_size = pop_sniff_rcvdb(path_id, (unsigned long)(ack_seq-1)); //advance the sniff window base
            } //ack in rcvdb

            throughputProcessAck(&throughput[path_id], ack_seq, &(pkthdr->ts), acked_size);

          } //has ack
        } //if incoming
      } //if outgoing

      if (flag_debug) {
        printf("TCP start_seq:%lu end_seq:%lu length:%d\n", seq_start, seq_end, length);
        printf("TCP ack_seq:%lu ack_flag:%d hlen:%d\n", ack_seq, ack_bit, tcp_hlen);
      }
      break;
    case IPPROTO_UDP:
      up = (struct udphdr *)cp;
      //sport = ntohs(up->source); //uh_sport in BSD
      //dport = ntohs(up->dest);   //uh_dport in BSD
      //printf("UDP source port: %d dest port: %d \n", sport, dport);
      if (flag_debug) printf("A UDP packet captured.\n");
      break;
    case IPPROTO_ICMP:
      if (flag_debug) printf("A ICMP packet captured.\n");
      break;
    default:
      if (flag_debug) printf("An unknow packet captured: %d \n", ip->ip_p);
      break;
    } //switch
  } else { //if unfragmented or last fragment
      printf("Got an incomplete fragment\n");
  }

  return 0;
}