Untitled

 avatar
unknown
c_cpp
6 months ago
6.4 kB
3
Indexable
NativeByteBuffer *Datacenter::createRequestsData(std::vector<std::unique_ptr<NetworkMessage>> &requests, int32_t *quickAckId, Connection *connection, bool pfsInit) {
    int64_t authKeyId;
    ByteArray *authKey = getAuthKey(connection->getConnectionType(), pfsInit, &authKeyId, 1);
    if (authKey == nullptr) {
        return nullptr;
    }

    int64_t messageId;
    TLObject *messageBody;
    bool freeMessageBody = false;
    int32_t messageSeqNo;

    if (requests.size() == 1) {
        NetworkMessage *networkMessage = requests[0].get();

        if (networkMessage->message->outgoingBody != nullptr) {
            messageBody = networkMessage->message->outgoingBody;
        } else {
            messageBody = networkMessage->message->body.get();
        }
        if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) send message (session: 0x%" PRIx64 ", seqno: %d, messageid: 0x%" PRIx64 "): %s(%p)", connection, instanceNum, datacenterId, connection->getConnectionType(), (uint64_t) connection->getSessionId(), networkMessage->message->seqno, (uint64_t) networkMessage->message->msg_id, typeid(*messageBody).name(), messageBody);

        auto messageTime = (int64_t) (networkMessage->message->msg_id / 4294967296.0 * 1000);
        int64_t currentTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMillis() + (int64_t) ConnectionsManager::getInstance(instanceNum).getTimeDifference() * 1000;

        if (!pfsInit && (networkMessage->forceContainer || messageTime < currentTime - 30000 || messageTime > currentTime + 25000)) {
            if (LOGS_ENABLED) DEBUG_D("wrap message in container");
            auto messageContainer = new TL_msg_container();
            messageContainer->messages.push_back(std::move(networkMessage->message));

            messageId = ConnectionsManager::getInstance(instanceNum).generateMessageId();
            messageBody = messageContainer;
            messageSeqNo = connection->generateMessageSeqNo(false);
            freeMessageBody = true;
        } else {
            messageId = networkMessage->message->msg_id;
            messageSeqNo = networkMessage->message->seqno;
        }
    } else {
        if (LOGS_ENABLED) DEBUG_D("start write messages to container");
        auto messageContainer = new TL_msg_container();
        size_t count = requests.size();
        for (uint32_t a = 0; a < count; a++) {
            NetworkMessage *networkMessage = requests[a].get();
            if (networkMessage->message->outgoingBody != nullptr) {
                messageBody = networkMessage->message->outgoingBody;
            } else {
                messageBody = networkMessage->message->body.get();
            }
            if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) send message (session: 0x%" PRIx64 ", seqno: %d, messageid: 0x%" PRIx64 "): %s(%p)", connection, instanceNum, datacenterId, connection->getConnectionType(), (uint64_t) connection->getSessionId(), networkMessage->message->seqno, (uint64_t) networkMessage->message->msg_id, typeid(*messageBody).name(), messageBody);
            messageContainer->messages.push_back(std::unique_ptr<TL_message>(std::move(networkMessage->message)));
        }
        messageId = ConnectionsManager::getInstance(instanceNum).generateMessageId();
        messageBody = messageContainer;
        freeMessageBody = true;
        messageSeqNo = connection->generateMessageSeqNo(false);
    }

    int32_t mtProtoVersion;
    if (pfsInit) {
        mtProtoVersion = 1;
    } else {
        mtProtoVersion = 2;
    }
    uint32_t messageSize = messageBody->getObjectSize();
    uint32_t additionalSize = (32 + messageSize) % 16;
    if (additionalSize != 0) {
        additionalSize = 16 - additionalSize;
    }
    if (mtProtoVersion == 2) {
        uint8_t index;
        RAND_bytes(&index, 1);
        additionalSize += (2 + (index % 14)) * 16;
    }
    NativeByteBuffer *buffer = BuffersStorage::getInstance().getFreeBuffer(24 + 32 + messageSize + additionalSize);
    buffer->writeInt64(authKeyId);
    buffer->position(24);

    if (pfsInit) {
        int64_t value;
        RAND_bytes((uint8_t *) &value, 8);
        buffer->writeInt64(value);
        RAND_bytes((uint8_t *) &value, 8);
        buffer->writeInt64(value);
    } else {
        buffer->writeInt64(getServerSalt(Connection::isMediaConnectionType(connection->getConnectionType())));
        buffer->writeInt64(connection->getSessionId());
    }
    buffer->writeInt64(messageId);
    buffer->writeInt32(messageSeqNo);
    buffer->writeInt32(messageSize);
    messageBody->serializeToStream(buffer);
    if (freeMessageBody) {
        delete messageBody;
    }

    if (additionalSize != 0) {
        RAND_bytes(buffer->bytes() + 24 + 32 + messageSize, additionalSize);
    }
    thread_local static uint8_t messageKey[96];
    switch (mtProtoVersion) {
        case 2: {
            SHA256_Init(&sha256Ctx);
            SHA256_Update(&sha256Ctx, authKey->bytes + 88, 32);
            SHA256_Update(&sha256Ctx, buffer->bytes() + 24, 32 + messageSize + additionalSize);
            SHA256_Final(messageKey, &sha256Ctx);
            if (quickAckId != nullptr) {
                *quickAckId = (((messageKey[0] & 0xff)) |
                               ((messageKey[1] & 0xff) << 8) |
                               ((messageKey[2] & 0xff) << 16) |
                               ((messageKey[3] & 0xff) << 24)) & 0x7fffffff;
            }
            break;
        }
        default: {
            SHA1(buffer->bytes() + 24, 32 + messageSize, messageKey + 4);
            if (quickAckId != nullptr) {
                *quickAckId = (((messageKey[4] & 0xff)) |
                               ((messageKey[5] & 0xff) << 8) |
                               ((messageKey[6] & 0xff) << 16) |
                               ((messageKey[7] & 0xff) << 24)) & 0x7fffffff;
            }
            break;
        }
    }
    memcpy(buffer->bytes() + 8, messageKey + 8, 16);

    generateMessageKey(instanceNum, authKey->bytes, messageKey + 8, messageKey + 32, false, mtProtoVersion);
    aesIgeEncryption(buffer->bytes() + 24, messageKey + 32, messageKey + 64, true, false, buffer->limit() - 24);

    return buffer;
}
Editor is loading...
Leave a Comment