Exemplo n.º 1
0
void EosOsc::Recv(EosTcp &tcp, unsigned int timeoutMS, CMD_Q &cmdQ)
{
	size_t size;
	const char *buf = tcp.Recv(*m_pLog, timeoutMS, size);
	if(buf && size!=0)
	{
		// append incoming data
		if( !m_InputBuffer.data )
		{
			m_InputBuffer.capacity = m_InputBuffer.size = size;
			m_InputBuffer.data = new char[m_InputBuffer.capacity];
			memcpy(m_InputBuffer.data, buf, size);
		}
		else
		{
			size_t requiredCapacity = (m_InputBuffer.size + size);
			if(m_InputBuffer.capacity < requiredCapacity)
			{
				// expand
				char *prevBuf = m_InputBuffer.data;
				size_t prevSize = m_InputBuffer.size;
				m_InputBuffer.capacity = m_InputBuffer.size = requiredCapacity;
				m_InputBuffer.data = new char[m_InputBuffer.capacity];
				memcpy(m_InputBuffer.data, prevBuf, prevSize);
				memcpy(&m_InputBuffer.data[prevSize], buf, size);
				delete[] prevBuf;
			}
			else
			{
				// fits
				memcpy(&m_InputBuffer.data[m_InputBuffer.size], buf, size);
				m_InputBuffer.size += size;
			}
		}

		// do we have a complete osc packet?
		long oscPacketLen = 0;
		while(m_InputBuffer.data && m_InputBuffer.size>=sizeof(oscPacketLen))
		{
			memcpy(&oscPacketLen, m_InputBuffer.data, sizeof(oscPacketLen));
			OSCArgument::Swap32(&oscPacketLen);
			if(oscPacketLen < 0)
				oscPacketLen = 0;
			size_t totalSize = (sizeof(oscPacketLen) + static_cast<size_t>(oscPacketLen));
			if(oscPacketLen>0 && m_InputBuffer.size>=totalSize)
			{
				// yup, great success
				char *oscData = &m_InputBuffer.data[sizeof(oscPacketLen)];

				char text[128];
				sprintf(text, "Received Osc Packet [%d]", static_cast<int>(oscPacketLen));
				m_pLog->AddDebug(text);

				m_Parser.PrintPacket(*this, oscData, oscPacketLen);

				sCommand *cmd = new sCommand;

				cmd->buf = new char[oscPacketLen];
				memcpy(cmd->buf, oscData, oscPacketLen);

				// find osc path null terminator
				for(long i=0; i<oscPacketLen; i++)
				{
					if(cmd->buf[i] == 0)
					{
						cmd->path = cmd->buf;
						cmd->argCount = 0xffffffff;
						cmd->args = OSCArgument::GetArgs(cmd->buf , static_cast<size_t>(oscPacketLen), cmd->argCount);
						break;
					}
				}

				cmdQ.push(cmd);

				// shift away processed data
				m_InputBuffer.size -= totalSize;
				if(m_InputBuffer.size != 0)
					memcpy(m_InputBuffer.data, &m_InputBuffer.data[totalSize], m_InputBuffer.size);
			}
			else
			{
				// awaiting more data
				break;
			}
		}
	}
}
void EosTcpClientThread::run()
{
	QString msg = QString("tcp client %1:%2 thread started").arg(m_Ip).arg(m_Port);
	m_PrivateLog.AddInfo( msg.toUtf8().constData() );
	UpdateLog();
	
	const size_t ReconnectDelay = 5000;
	EosTimer reconnectTimer;

	// outer loop for auto-reconnect
	while( m_Run )
	{
		EosTcp *tcp = EosTcp::Create();

		if( tcp->Initialize(m_PrivateLog,m_Ip.toUtf8().constData(),m_Port) )
		{
			OSCParser parser;
			parser.SetRoot(new OSCHandler(*this));
			std::string inPrefix = QString("TCPIN [%1:%2] ").arg(m_Ip).arg(m_Port).toUtf8().constData();
			std::string outPrefix = QString("TCPOUT [%1:%2] ").arg(m_Ip).arg(m_Port).toUtf8().constData();
			
			sPacket packet;

			// connect
			while(m_Run && tcp->GetConnectState()==EosTcp::CONNECT_IN_PROGRESS)
			{
				tcp->Tick(m_PrivateLog);
				UpdateLog();
				msleep(10);
			}

			UpdateLog();

			// send/recv while connected
			if(m_Run && tcp->GetConnectState()==EosTcp::CONNECT_CONNECTED)
			{
				m_Mutex.lock();
				m_NetEventQ.push_back(NET_EVENT_CONNECTED);
				m_Mutex.unlock();
			
				PACKET_Q sendQ;
				OSCStream oscStream(m_FrameMode);
				do
				{
					size_t len = 0;
					const char *data = tcp->Recv(m_PrivateLog, 100, len);
					
					oscStream.Add(data, len);
					
					while( m_Run )
					{
						packet.data = oscStream.GetNextFrame(packet.size);
						if(packet.data && packet.size!=0)
						{
							m_Prefix = inPrefix;
							m_LogMsgType = EosLog::LOG_MSG_TYPE_RECV;
							parser.PrintPacket(*this, packet.data, packet.size);
							parser.ProcessPacket(*this, packet.data, packet.size);
							delete[] packet.data;
						}
						else
							break;
					}

					msleep(1);

					m_Mutex.lock();
					m_SendQ.swap(sendQ);
					m_Mutex.unlock();

					sPacket framedPacket;
					for(PACKET_Q::iterator i=sendQ.begin(); m_Run && i!=sendQ.end(); i++)
					{
						framedPacket.size = i->size;
						framedPacket.data = OSCStream::CreateFrame(m_FrameMode, i->data, framedPacket.size);
						if(framedPacket.data && framedPacket.size!=0)
						{
							if( tcp->Send(m_PrivateLog,framedPacket.data,framedPacket.size) )
							{
								m_Prefix = outPrefix;
								m_LogMsgType = EosLog::LOG_MSG_TYPE_SEND;
								parser.PrintPacket(*this, i->data, i->size);
							}
							delete[] framedPacket.data;
						}
						delete[] i->data;
					}
					sendQ.clear();
				
					UpdateLog();

					msleep(1);
				}
				while(m_Run && tcp->GetConnectState()==EosTcp::CONNECT_CONNECTED);
				
				m_Mutex.lock();
				m_NetEventQ.push_back(NET_EVENT_DISCONNECTED);
				m_Mutex.unlock();
			}
		}

		delete tcp;

		if( m_Run )
		{
			msg = QString("tcp client %1:%2 reconnecting in %3...").arg(m_Ip).arg(m_Port).arg(ReconnectDelay/1000);
			m_PrivateLog.AddInfo( msg.toUtf8().constData() );
			UpdateLog();
		}

		reconnectTimer.Start();
		while(m_Run && !reconnectTimer.GetExpired(ReconnectDelay))
			msleep(10);
	}
	
	msg = QString("tcp client %1:%2 thread ended").arg(m_Ip).arg(m_Port);
	m_PrivateLog.AddInfo( msg.toUtf8().constData() );
	UpdateLog();
}