size_t StreamProcessor::DispatchProcessPacket(const UInt32 packetID, DataVector::iterator curr, DataVector::iterator bufferEnd) 
	{
		for(UInt32 i=0; i<m_numPacketTypes; i++)
		{
			const PacketDescriptorPacket &desc = m_packetDescriptors[i];
			if(desc.packetID == packetID)
			{
				const ProcessPacketFunc processFunc = m_packetProcessors[i];
				if(processFunc)
				{
					return processFunc(*this, curr, bufferEnd);
				}
				else
				{
					// No process function available for this packet type! Attempt to skip it!
					switch(desc.sizeofPayloadSizeType)
					{
						case 0: return SkipPacket(                    (size_t)desc.sizeofPacket, curr, bufferEnd );
						case 1: return SkipPacketWithPayload<UInt8>(  (size_t)desc.sizeofPacket, curr, bufferEnd );
						case 2: return SkipPacketWithPayload<UInt16>( (size_t)desc.sizeofPacket, curr, bufferEnd );
						case 4: return SkipPacketWithPayload<UInt32>( (size_t)desc.sizeofPacket, curr, bufferEnd );
					}
				}
			}
		}

		// We should never reach here...
		// typically means unknown packet type, so any further reading from the socket will yield undefined results...
		OVR_CAPTURE_ASSERT(0);
		return 0;
	}
    // Flushes all available packets over the network... returns number of bytes sent
    bool AsyncStream::Flush(Socket &s)
    {
        OVR_CAPTURE_CPU_ZONE(AsyncStream_Flush);

        bool okay = true;

        // Take ownership of any pending data...
        SpinLock(m_bufferLock);
        Swap(m_cacheBegin, m_flushBegin);
        Swap(m_cacheTail,  m_flushTail);
        Swap(m_cacheEnd,   m_flushEnd);
        SpinUnlock(m_bufferLock);

        // Signal that we just swapped in a new buffer... wake up any threads that were waiting on us to flush.
        m_gate.Open();

        if(m_flushTail > m_flushBegin)
        {
            const size_t sendSize = (size_t)(m_flushTail-m_flushBegin);

            // first send stream header...
            StreamHeaderPacket streamheader;
            streamheader.threadID   = m_threadID;
            streamheader.streamSize = sendSize;
            okay = s.Send(&streamheader, sizeof(streamheader));

            // This send payload...
            okay = okay && s.Send(m_flushBegin, sendSize);
            m_flushTail = m_flushBegin;
        }

        OVR_CAPTURE_ASSERT(m_flushBegin == m_flushTail); // should be empty at this point...

        return okay;
    }
	// does not check whether value is new
	void VarStore::Set(key_t key, var_t var, bool isClient)
	{
		m_tableLock.WriteLock();
		VarInfo *varRet = FindUnsafe(key);
		if (varRet == NULL)
		{
			m_varTable.push_back(VarInfo(key, var, isClient));
		}			
		else
		{
			OVR_CAPTURE_ASSERT(varRet->key == key);
			varRet->valCur = var;
			varRet->isClient = isClient;
		}
		OVR_CAPTURE_ASSERT(FindUnsafe(key) != NULL);
		m_tableLock.WriteUnlock();
	}
 // Closes the capture system... no other Capture calls on *any* thead should be called after this.
 void Shutdown(void)
 {
     if(g_server)
     {
         delete g_server;
         g_server = NULL;
     }
     OVR_CAPTURE_ASSERT(!g_connectionFlags);
     g_initFlags       = 0;
     g_connectionFlags = 0;
 }
void Thread::Start(void)
{
    OVR_CAPTURE_ASSERT(!m_thread && !m_quitSignaled);
#if defined(OVR_CAPTURE_POSIX)
    pthread_attr_init(&m_threadAttrs);
    pthread_create(&m_thread, &m_threadAttrs, ThreadEntry, this);
#elif defined(OVR_CAPTURE_WINDOWS)
    m_thread = CreateThread(NULL, 0, ThreadEntry, this, 0, NULL);
#else
#error Unknown Platform!
#endif
}
    // Initializes the Capture system... should be called before any other Capture call.
    bool Init(const char *packageName, UInt32 flags)
    {
        OVR_CAPTURE_ASSERT(!g_initFlags && !g_connectionFlags);

        // sanitze input flags;
        flags = flags & All_Flags;

        // If no capture features are enabled... then don't initialize anything!
        if(!flags)
            return false;

        g_initFlags       = flags;
        g_connectionFlags = 0;

        // Initialize the pre-thread stream system...
        AsyncStream::Init();

        OVR_CAPTURE_ASSERT(!g_server);
        g_server = new Server(packageName);
        g_server->Start();

        return true;
    }
 // Upload the framebuffer for the current frame... should be called once a frame!
 void FrameBuffer(UInt64 timestamp, FrameBufferFormat format, UInt32 width, UInt32 height, const void *buffer)
 {
     if(CheckConnectionFlag(Enable_FrameBuffer_Capture))
     {
         UInt32 pixelSize = 0;
         switch(format)
         {
             case FrameBuffer_RGB_565:   pixelSize=2; break;
             case FrameBuffer_RGBA_8888: pixelSize=4; break;
         }
         OVR_CAPTURE_ASSERT(pixelSize);
         const UInt32 payloadSize = pixelSize * width * height;
         FrameBufferPacket packet;
         packet.format     = format;
         packet.width      = width;
         packet.height     = height;
         packet.timestamp  = timestamp;
         // TODO: we should probably just send framebuffer packets directly over the network rather than
         //       caching them due to their size and to reduce latency.
         AsyncStream::Acquire()->WritePacket(packet, buffer, payloadSize);
     }
 }
 // Initialize the per-thread stream system... MUST be called before being connected!
 void AsyncStream::Init(void)
 {
     OVR_CAPTURE_ASSERT(g_tlskey == NullThreadLocalKey);
     g_tlskey = CreateThreadLocalKey(ThreadDetach);
 }
	bool StreamProcessor::ProcessData(const void *buffer, size_t bufferSize)
	{
		// First, append the incoming data to our unprocessed data buffer...
		m_buffer.insert(m_buffer.end(), (const UInt8*)buffer, ((const UInt8*)buffer)+bufferSize);

		const DataVector::iterator begin = m_buffer.begin();
		const DataVector::iterator end   = m_buffer.end();
		DataVector::iterator       curr  = begin;

		// 1) read ConnectionHeaderPacket
		if(!m_hasReadConnectionHeader && std::distance(curr, end) > (DataVector::difference_type)sizeof(ConnectionHeaderPacket))
		{
			ConnectionHeaderPacket connectionHeader;
			memcpy(&connectionHeader, &*curr, sizeof(connectionHeader));
			curr += sizeof(connectionHeader);
			m_hasReadConnectionHeader = true;

			if(connectionHeader.size != sizeof(connectionHeader))
			{
				onStreamError("Connection header size mismatch!");
				return false;
			}

			if(connectionHeader.version != ConnectionHeaderPacket::s_version)
			{
				onStreamError("Connection header version mismatch!");
				return false;
			}

			if(connectionHeader.flags == 0)
			{
				onStreamError("No capture features enabled!");
				return false;
			}
		}

		// Have not successfully read the connection header but no error, so return until we have more data
		if(!m_hasReadConnectionHeader)
			return true;

		// 2) read PacketDescriptorHeaderPacket
		if(!m_hasReadPacketDescriptorHeader && std::distance(curr, end) > (DataVector::difference_type)sizeof(PacketDescriptorHeaderPacket))
		{
			PacketDescriptorHeaderPacket packetDescHeader;
			memcpy(&packetDescHeader, &*curr, sizeof(packetDescHeader));
			curr += sizeof(packetDescHeader);
			m_hasReadPacketDescriptorHeader = true;
			m_numPacketTypes = packetDescHeader.numPacketTypes;

			if(m_numPacketTypes == 0)
			{
				onStreamError("No packet types received!");
				return false;
			}

			if(m_numPacketTypes > 1024)
			{
				onStreamError("Too many packet types received!");
				return false;
			}
		}

		// Have not successfully read the packet descriptor header but no error, so return until we have more data
		if(!m_hasReadPacketDescriptorHeader)
			return true;

		// 3) read array of PacketDescriptorPacket
		if(!m_hasReadPacketDescriptors && std::distance(curr, end) > (DataVector::difference_type)(sizeof(PacketDescriptorPacket)*m_numPacketTypes))
		{
			m_packetDescriptors = new PacketDescriptorPacket[m_numPacketTypes];
			m_packetProcessors  = new ProcessPacketFunc[m_numPacketTypes];
			for(UInt32 i=0; i<m_numPacketTypes; i++)
			{
				memcpy(&m_packetDescriptors[i], &*curr, sizeof(PacketDescriptorPacket));
				curr += sizeof(PacketDescriptorPacket);
				m_packetProcessors[i] = GetProcessPacketFunction(m_packetDescriptors[i].packetID, m_packetDescriptors[i].version);
			}
			m_hasReadPacketDescriptors = true;
		}

		// Have not successfully read the packet descriptors but no error, so return until we have more data
		if(!m_hasReadPacketDescriptors)
			return true;

		// 4) read streams...
		while(curr < end)
		{
			// Compute the end of the readable stream...
			// We take the minimum end point between end of buffer actually read in and stream size...
			// because we don't want to overrun the stream or the buffer that is actually read in...
			const DataVector::iterator streamEnd = curr + std::min((size_t)(end - curr), m_streamBytesRemaining);

			// If we are currently in a stream... try parsing packets out of it...
			while(curr < streamEnd)
			{
				const size_t s = LoadAndProcessNextPacket(curr, streamEnd);
				if(!s)
					break;
				OVR_CAPTURE_ASSERT(curr+s <= streamEnd);
				curr                   += s;
				m_streamBytesRemaining -= s;
			}

			// If we are at the end of the stream... that means the next data available will be a stream header...
			// so load that if we can. And once loaded stay in the loop and try parsing the following packets...
			if(curr == streamEnd && sizeof(StreamHeaderPacket) <= (size_t)(end - curr))
			{
				StreamHeaderPacket streamHeader = {0};
				memcpy(&streamHeader, &*curr, sizeof(streamHeader));
				m_streamThreadID       = streamHeader.threadID;
				m_streamBytesRemaining = streamHeader.streamSize;
				curr += sizeof(streamHeader);
			}
			else
			{
				// If we ran out of parsable data we need to exit and allow the CaptureThread to load more data...
				break;
			}
		}

		// Finally, remove processed data...
		// Note: we so cannot do this if we decide the DataVector should
		// shrink on popAll
		if(curr > begin)
		{
			m_buffer.erase(m_buffer.begin(), curr);
		}

		return true;
	}