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(); } }
//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; }