| 406 | } |
| 407 | |
| 408 | void Session::CreateIfNotCreatedAlready() |
| 409 | { |
| 410 | std::string errmsg; |
| 411 | if (m_control_sock && m_control_sock->IsConnected(errmsg)) { |
| 412 | return; |
| 413 | } |
| 414 | |
| 415 | const auto session_type = m_transient ? "transient" : "persistent"; |
| 416 | const auto session_id = GetRandHash().GetHex().substr(0, 10); // full is overkill, too verbose in the logs |
| 417 | |
| 418 | LogDebug(BCLog::I2P, "Creating %s I2P SAM session %s with %s\n", session_type, session_id, m_control_host.ToString()); |
| 419 | |
| 420 | auto sock = Hello(); |
| 421 | |
| 422 | if (m_transient) { |
| 423 | // The destination (private key) is generated upon session creation and returned |
| 424 | // in the reply in DESTINATION=. |
| 425 | const Reply& reply = SendRequestAndGetReply( |
| 426 | *sock, |
| 427 | strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=TRANSIENT SIGNATURE_TYPE=7 " |
| 428 | "i2cp.leaseSetEncType=4,0 inbound.quantity=1 outbound.quantity=1", |
| 429 | session_id)); |
| 430 | |
| 431 | m_private_key = DecodeI2PBase64(reply.Get("DESTINATION")); |
| 432 | } else { |
| 433 | // Read our persistent destination (private key) from disk or generate |
| 434 | // one and save it to disk. Then use it when creating the session. |
| 435 | const auto& [read_ok, data] = ReadBinaryFile(m_private_key_file); |
| 436 | if (read_ok) { |
| 437 | m_private_key.assign(data.begin(), data.end()); |
| 438 | } else { |
| 439 | GenerateAndSavePrivateKey(*sock); |
| 440 | } |
| 441 | |
| 442 | const std::string& private_key_b64 = SwapBase64(EncodeBase64(m_private_key)); |
| 443 | |
| 444 | SendRequestAndGetReply(*sock, |
| 445 | strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s " |
| 446 | "i2cp.leaseSetEncType=4,0 inbound.quantity=3 outbound.quantity=3", |
| 447 | session_id, |
| 448 | private_key_b64)); |
| 449 | } |
| 450 | |
| 451 | m_my_addr = CService(DestBinToAddr(MyDestination()), I2P_SAM31_PORT); |
| 452 | m_session_id = session_id; |
| 453 | m_control_sock = std::move(sock); |
| 454 | |
| 455 | LogInfo("%s I2P SAM session %s created, my address=%s", |
| 456 | Capitalize(session_type), |
| 457 | m_session_id, |
| 458 | m_my_addr.ToStringAddrPort()); |
| 459 | } |
| 460 | |
| 461 | std::unique_ptr<Sock> Session::StreamAccept() |
| 462 | { |
nothing calls this directly
no test coverage detected