Repository: bitcoin/bitcoin
File: src/i2p.cpp (C++)

Code before:
                      "i2cp.leaseSetEncType=4,0 inbound.quantity=1 outbound.quantity=1",
                      session_id));

        m_private_key = DecodeI2PBase64(reply.Get("DESTINATION"));
    } else {
        // Read our persistent destination (private key) from disk or generate
        // one and save it to disk. Then use it when creating the session.
        const auto& [read_ok, data] = ReadBinaryFile(m_private_key_file);
        if (read_ok) {
            m_private_key.assign(data.begin(), data.end());
        } else {
            GenerateAndSavePrivateKey(*sock);
        }

        const std::string& private_key_b64 = SwapBase64(EncodeBase64(m_private_key));

        SendRequestAndGetReply(*sock,
                               strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s "
                                         "i2cp.leaseSetEncType=4,0 inbound.quantity=3 outbound.quantity=3",
                                         session_id,
                                         private_key_b64));
    }

    m_my_addr = CService(DestBinToAddr(MyDestination()), I2P_SAM31_PORT);
    m_session_id = session_id;
    m_control_sock = std::move(sock);

    Log("%s SAM session %s created, my address=%s",
        Capitalize(session_type),
        m_session_id,
        m_my_addr.ToStringAddrPort());
}

std::unique_ptr<Sock> Session::StreamAccept()
{
    auto sock = Hello();

    const Reply& reply = SendRequestAndGetReply(
        *sock, strprintf("STREAM ACCEPT ID=%s SILENT=false", m_session_id), false);

    const std::string& result = reply.Get("RESULT");

    if (result == "OK") {
        return sock;
    }

    if (result == "INVALID_ID") {
        // If our session id is invalid, then force session re-creation on next usage.
        Disconnect();
    }


Review comment (suggestion):
Commit 48dc2ff8e7819e810d2436219268f220b39c14f

in fc0a50e92aaaf3b049fcfcd0873dadc7150cfecf I made this one `info` (default) level [here](https://github.com/bitcoin/bitcoin/pull/25203/commits/fc0a50e92aaaf3b049fcfcd0873dadc7150cfecf#diff-8945a03581b372d674f34dcb6a63e537343e376ebcd9d8c7c3d94d4366cd9b9dR379). It seems important, when the user turns `i2p` logging on, to see if the session was successfully created. I look for this logging when launching a node or restarting the I2P router.

Code after:

        m_private_key = DecodeI2PBase64(reply.Get("DESTINATION"));
    } else {
        // Read our persistent destination (private key) from disk or generate
        // one and save it to disk. Then use it when creating the session.
        const auto& [read_ok, data] = ReadBinaryFile(m_private_key_file);
        if (read_ok) {
            m_private_key.assign(data.begin(), data.end());
        } else {
            GenerateAndSavePrivateKey(*sock);
        }

        const std::string& private_key_b64 = SwapBase64(EncodeBase64(m_private_key));

        SendRequestAndGetReply(*sock,
                               strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s "
                                         "i2cp.leaseSetEncType=4,0 inbound.quantity=3 outbound.quantity=3",
                                         session_id,
                                         private_key_b64));
    }

    m_my_addr = CService(DestBinToAddr(MyDestination()), I2P_SAM31_PORT);
    m_session_id = session_id;
    m_control_sock = std::move(sock);

    LogPrintLevel(BCLog::I2P, BCLog::Level::Info, "%s SAM session %s created, my address=%s\n",
        Capitalize(session_type),
        m_session_id,
        m_my_addr.ToStringAddrPort());
}

std::unique_ptr<Sock> Session::StreamAccept()
{
    auto sock = Hello();

    const Reply& reply = SendRequestAndGetReply(
        *sock, strprintf("STREAM ACCEPT ID=%s SILENT=false", m_session_id), false);

    const std::string& result = reply.Get("RESULT");

    if (result == "OK") {
        return sock;
    }

    if (result == "INVALID_ID") {
        // If our session id is invalid, then force session re-creation on next usage.
        Disconnect();
    }

    throw std::runtime_error(strprintf("\"%s\"", reply.full));
}