NetworkServer::Implementation::Implementation(Jerboa::CollectionInterface* collection, Jerboa::PlayerInterface* player, Jerboa::PlaylistInterface* playlist)
: QObject(0)
, m_collection(collection)
, m_player(player)
, m_playlist(playlist)
, m_discoverySocket(new QUdpSocket(this))
, m_server(new QTcpServer(this))
{
	const bool startedDiscovery = m_discoverySocket->bind(QHostAddress::Any, NetworkCommon::portNumber());
	if(!startedDiscovery)
	{
		qDebug() << "Failed to start network discovery:" << m_discoverySocket->errorString();
		return;
	}

	if(!m_server->listen())
	{
		qDebug() << "Failed to bind network socket:" << m_server->errorString();
		return;
	}

	qDebug() << "Network server started.";

	connect(m_discoverySocket, SIGNAL(readyRead()), SLOT(sendDiscoveryResponses()));


	QSettings settings;

	// Deal with strings in QSettings so the saved values are more human-readable
	QString serverUuid = settings.value("network/serverUuid").toString();
	if(serverUuid.isEmpty())
	{
		serverUuid = Mendeley::Uuid::createUuid();
		settings.setValue("network/serverUuid", serverUuid);
	}

	m_serverUuid = serverUuid.toLatin1();

	// Load up the response
	{
		QByteArray payload;
		payload = QString::number(m_serverUuid.length()).toLatin1();
		payload.append(',');
		payload.append(m_serverUuid);
		payload.append(',');
		const QByteArray host = QHostInfo::localHostName().toUtf8();
		payload.append(QString::number(host.length()).toLatin1());
		payload.append(',');
		payload.append(host);
		payload.append(',');
		const QByteArray port = QString::number(m_server->serverPort()).toLatin1();
		payload.append(QString::number(port.length()).toLatin1());
		payload.append(',');
		payload.append(port);
		payload.append(',');

		m_discoveryResponse = NetworkMessage("ANNOUNCE", payload, NetworkMessage::UnsignedMessage).toByteArray();
	}
}
Esempio n. 2
0
//wiz
//This captured function is what Tibia uses to decrypt the packet
// and determine which action types it contains in order to parse it properly
// The function returns the action type and Tibia then parses the stream.
// If the stream has not yet been used up, it will continually run this function to
// determine the type of and parse the next action.
// We can interfere with this process, but this requires knowing packet structures
// and error handling for incomplete packets which takes much more work than payoff.
int myShouldParseRecv()
{
	CMemReader& reader = CMemReader::getMemReader();

	typedef int(*Proto_fun)();

	Proto_fun fun = (Proto_fun)baseAdjust(reader.m_memAddressFunTibiaShouldParseRecv);
	//This function looks ahead, it returns the next packet type. It will return -1 if no next packet.
	int ret = fun();

	//look for this address near above location, it will be off by 8

	packStream* recvStream = (packStream*)baseAdjust(reader.m_memAddressArrayPtrRecvStream);
	//int packLen = ((unsigned char)recvStream->s[6]) + ((unsigned char)recvStream->s[7])*256;

	if (prevNextRet != -1)
	{
		int actionStart = prevRecvStreamPos - 1; //Tibia eats 1 byte to return "ret" every call it is not -1
		int actionEnd; // index of last byte
		if (recvStream->pos <= prevRecvStreamPos || recvStream->pos > prevRecvStreamLen)  // when stream restarts, use previous length instead of current pos
			actionEnd = prevRecvStreamLen - 1;
		else if (ret == -1)
			actionEnd = recvStream->pos - 1; // did not eat an extra byte
		else
			actionEnd = recvStream->pos - 2; // ate an extra byte
		int actionLen = actionEnd - actionStart + 1;
		//Parse packet and perform any needed actions
		Protocol::parsePacketIn(NetworkMessage((char*)(prevRecvStream + actionStart), actionLen));
		/*
		int packtype = ((char*)prevRecvStream+actionStart)[0]&0xff;
		int wanted = 0xb4;
		if(packtype == wanted){
		Protocol::parsePacketIn(NetworkMessage((char*)(prevRecvStream+actionStart),actionLen),ipcPipeBack);
		bufToHexString(((char*)prevRecvStream+actionStart),actionLen);
		sendTAMessage(bufToHexStringRet);
		}*/
		{for (int i = 0; i < recvRegexCount; i++)
		{
			if (recvRegex[i].inUse == 1)
			{
				int match = regnexec(&(recvRegex[i].preg), ((char*)prevRecvStream + actionStart), actionLen, 0, NULL, 0);
				if (match == 0)
				{
					if (0)
					{
						bufToHexString(((char*)prevRecvStream + actionStart), actionLen);
						sendTAMessage(bufToHexStringRet);
					}
					parseRecvActionData(recvRegex[i].handle, (char*)prevRecvStream + actionStart, actionLen);
				}
			}
		}
		}
	}
	if (ret != -1 && (recvStream->pos <= prevRecvStreamPos || recvStream->pos > prevRecvStreamLen))
	{
		prevRecvStreamLen = recvStream->length;
		memcpy(prevRecvStream, recvStream->s, prevRecvStreamLen);
	}
	prevRecvStreamPos = recvStream->pos;
	prevNextRet = ret;

	//char buf[1111];
	//sprintf(bufToHexStringRet,"%x:%d, %d  %x%x",ret, recvStream->pos, recvStream->length,((char)recvStream->s[recvStream->pos-2]),((char)recvStream->s[recvStream->pos-2-1]));
	//AfxMessageBox(buf);
	//bufToHexString(recvStream->s,30);
	//sendTAMessage(bufToHexStringRet);
	if (0 && reader.isLoggedIn()) // see what happens when packets are ignored
	{
		if (ret == 107)
			ret = -1;
		if (ret == -1)
			recvStream->pos += 10;
	}
	return ret;
}