void OutgoingContactRequest::startConnection()
{
    if (m_client)
        return;

    qDebug() << "Starting outgoing contact request for" << user->uniqueID;

    m_client = new ContactRequestClient(user);

    connect(m_client, SIGNAL(accepted()), SLOT(accept()));
    connect(m_client, SIGNAL(rejected(int)), SLOT(requestRejected(int)));
    connect(m_client, SIGNAL(acknowledged()), SLOT(requestAcknowledged()));
    connect(m_client, SIGNAL(responseChanged()), SIGNAL(connectedChanged()));

    m_client->setMyNickname(myNickname());
    m_client->setMessage(message());
    m_client->sendRequest();
}
bool ContactRequestClient::buildRequestData(QByteArray cookie)
{
    /* [2*length][16*hostname][16*serverCookie][16*connSecret][data:pubkey][str:nick][str:message][data:signature] */
    QByteArray requestData;
    CommandDataParser request(&requestData);

    /* Hostname */
    QString hostname = user->hostname();
    hostname.truncate(hostname.lastIndexOf(QLatin1Char('.')));
    if (hostname.size() != 16)
    {
        qWarning() << "Cannot send contact request: unable to determine the remote service hostname";
        return false;
    }

    /* Connection secret */
    QByteArray connSecret = user->settings()->read<Base64Encode>("localSecret");
    if (connSecret.size() != 16)
    {
        qWarning() << "Cannot send contact request: invalid local secret";
        return false;
    }

    /* Public service key */
    Tor::HiddenService *service = user->identity->hiddenService();
    CryptoKey serviceKey;
    if (!service || !(serviceKey = service->cryptoKey()).isLoaded())
    {
        qWarning() << "Cannot send contact request: failed to load service key";
        return false;
    }

    QByteArray publicKeyData = serviceKey.encodedPublicKey();
    if (publicKeyData.isNull())
    {
        qWarning() << "Cannot send contact request: failed to encode service key";
        return false;
    }

    /* Build request */
    request << (quint16)0; /* placeholder for length */
    request.writeFixedData(hostname.toLatin1());
    request.writeFixedData(cookie);
    request.writeFixedData(connSecret);
    request.writeVariableData(publicKeyData);
    request << myNickname() << message();

    if (request.hasError())
    {
        qWarning() << "Cannot send contact request: command building failed";
        return false;
    }

    /* Sign request, excluding the length field */
    QByteArray signature = serviceKey.signData(requestData.mid(2));
    if (signature.isNull())
    {
        qWarning() << "Cannot send contact request: failed to sign request";
        return false;
    }

    request.writeVariableData(signature);
    if (request.hasError())
    {
        qWarning() << "Cannot send contact request: command building failed";
        return false;
    }

    /* Set length */
    qToBigEndian((quint16)requestData.size(), reinterpret_cast<uchar*>(requestData.data()));

    /* Send */
    qint64 re = socket->write(requestData);
    Q_ASSERT(re == requestData.size());
    Q_UNUSED(re);

    qDebug() << "Contact request for" << user->uniqueID << "sent request data";
    return true;
}