diff --git a/Destination.h b/Destination.h index 23fd6864..6b41b231 100644 --- a/Destination.h +++ b/Destination.h @@ -28,6 +28,7 @@ namespace client bool IsRunning () const { return m_IsRunning; }; boost::asio::io_service * GetService () { return m_Service; }; i2p::tunnel::TunnelPool * GetTunnelPool () { return m_Pool; }; + bool IsReady () const { return m_LeaseSet && m_LeaseSet->HasNonExpiredLeases (); }; void ResetCurrentOutboundTunnel () { m_CurrentOutboundTunnel = nullptr; }; const i2p::data::LeaseSet * FindLeaseSet (const i2p::data::IdentHash& ident); diff --git a/SAM.cpp b/SAM.cpp index 7bc17c2d..4b96fd26 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -220,18 +220,45 @@ namespace client if (m_Session) { m_SocketType = eSAMSocketTypeSession; - uint8_t buf[1024]; - char priv[1024]; - size_t l = m_Session->localDestination->GetPrivateKeys ().ToBuffer (buf, 1024); - size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024); - priv[l1] = 0; - size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); - SendMessageReply (m_Buffer, l2, false); + if (m_Session->localDestination->IsReady ()) + SendSessionCreateReplyOk (); + else + { + m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); + m_Timer.async_wait (boost::bind (&SAMSocket::HandleSessionReadinessCheckTimer, + this, boost::asio::placeholders::error)); + } } else SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_DEST, strlen(SAM_SESSION_CREATE_DUPLICATED_DEST), true); } + void SAMSocket::HandleSessionReadinessCheckTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + if (m_Session->localDestination->IsReady ()) + SendSessionCreateReplyOk (); + else + { + m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); + m_Timer.async_wait (boost::bind (&SAMSocket::HandleSessionReadinessCheckTimer, + this, boost::asio::placeholders::error)); + } + } + } + + void SAMSocket::SendSessionCreateReplyOk () + { + uint8_t buf[1024]; + char priv[1024]; + size_t l = m_Session->localDestination->GetPrivateKeys ().ToBuffer (buf, 1024); + size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024); + priv[l1] = 0; + size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); + SendMessageReply (m_Buffer, l2, false); + } + void SAMSocket::ProcessStreamConnect (char * buf, size_t len) { LogPrint ("SAM stream connect: ", buf); diff --git a/SAM.h b/SAM.h index cd1e8209..dff0e8e2 100644 --- a/SAM.h +++ b/SAM.h @@ -20,6 +20,7 @@ namespace client const int SAM_SOCKET_CONNECTION_MAX_IDLE = 3600; // in seconds const int SAM_CONNECT_TIMEOUT = 5; // in seconds const int SAM_NAMING_LOOKUP_TIMEOUT = 5; // in seconds + const int SAM_SESSION_READINESS_CHECK_INTERVAL = 20; // in seconds const char SAM_HANDSHAKE[] = "HELLO VERSION"; const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=3.0\n"; const char SAM_SESSION_CREATE[] = "SESSION CREATE"; @@ -95,6 +96,8 @@ namespace client void HandleStreamDestinationRequestTimer (const boost::system::error_code& ecode, i2p::data::IdentHash ident); void HandleNamingLookupDestinationRequestTimer (const boost::system::error_code& ecode, i2p::data::IdentHash ident); void SendNamingLookupReply (const i2p::data::LeaseSet * leaseSet); + void HandleSessionReadinessCheckTimer (const boost::system::error_code& ecode); + void SendSessionCreateReplyOk (); private: