diff --git a/Datagram.cpp b/Datagram.cpp index 412ef318..9faf9ab2 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -17,7 +17,7 @@ namespace datagram { } - void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, std::shared_ptr remote) + void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident) { uint8_t buf[MAX_DATAGRAM_SIZE]; auto identityLen = m_Owner.GetIdentity ().ToBuffer (buf, MAX_DATAGRAM_SIZE); @@ -35,11 +35,30 @@ namespace datagram } else m_Owner.Sign (buf1, len, signature); - - m_Owner.GetService ().post (std::bind (&DatagramDestination::SendMsg, this, - CreateDataMessage (buf, len + headerLen), remote)); + + auto msg = CreateDataMessage (buf, len + headerLen); + auto remote = m_Owner.FindLeaseSet (ident); + if (remote) + m_Owner.GetService ().post (std::bind (&DatagramDestination::SendMsg, this, msg, remote)); + else + m_Owner.RequestDestination (ident, std::bind (&DatagramDestination::HandleLeaseSetRequestComplete, + this, std::placeholders::_1, msg, ident)); } + void DatagramDestination::HandleLeaseSetRequestComplete (bool success, I2NPMessage * msg, i2p::data::IdentHash ident) + { + if (success) + { + auto remote = m_Owner.FindLeaseSet (ident); + if (remote) + { + SendMsg (msg, remote); + return; + } + } + DeleteI2NPMessage (msg); + } + void DatagramDestination::SendMsg (I2NPMessage * msg, std::shared_ptr remote) { auto outboundTunnel = m_Owner.GetTunnelPool ()->GetNextOutboundTunnel (); diff --git a/Datagram.h b/Datagram.h index 7df5e3cd..dd84b656 100644 --- a/Datagram.h +++ b/Datagram.h @@ -26,7 +26,7 @@ namespace datagram DatagramDestination (i2p::client::ClientDestination& owner); ~DatagramDestination () {}; - void SendDatagramTo (const uint8_t * payload, size_t len, std::shared_ptr remote); + void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident); void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; @@ -34,6 +34,8 @@ namespace datagram private: + void HandleLeaseSetRequestComplete (bool success, I2NPMessage * msg, i2p::data::IdentHash ident); + I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len); void SendMsg (I2NPMessage * msg, std::shared_ptr remote); void HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); diff --git a/SAM.cpp b/SAM.cpp index 41499dd5..f90bac19 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -102,7 +102,7 @@ namespace client { separator++; std::map params; - ExtractParams (separator, bytes_transferred - (separator - m_Buffer), params); + ExtractParams (separator, params); auto it = params.find (SAM_PARAM_MAX); // TODO: check MIN as well if (it != params.end ()) @@ -208,6 +208,8 @@ namespace client ProcessStreamConnect (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_STREAM_ACCEPT)) ProcessStreamAccept (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); + else if (!strcmp (m_Buffer, SAM_DATAGRAM_SEND)) + ProcessDatagramSend (separator + 1, bytes_transferred - (separator - m_Buffer) - 1, eol + 1); else if (!strcmp (m_Buffer, SAM_DEST_GENERATE)) ProcessDestGenerate (); else if (!strcmp (m_Buffer, SAM_NAMING_LOOKUP)) @@ -236,7 +238,7 @@ namespace client { LogPrint ("SAM session create: ", buf); std::map params; - ExtractParams (buf, len, params); + ExtractParams (buf, params); std::string& style = params[SAM_PARAM_STYLE]; std::string& id = params[SAM_PARAM_ID]; std::string& destination = params[SAM_PARAM_DESTINATION]; @@ -307,7 +309,7 @@ namespace client { LogPrint ("SAM stream connect: ", buf); std::map params; - ExtractParams (buf, len, params); + ExtractParams (buf, params); std::string& id = params[SAM_PARAM_ID]; std::string& destination = params[SAM_PARAM_DESTINATION]; std::string& silent = params[SAM_PARAM_SILENT]; @@ -361,7 +363,7 @@ namespace client { LogPrint ("SAM stream accept: ", buf); std::map params; - ExtractParams (buf, len, params); + ExtractParams (buf, params); std::string& id = params[SAM_PARAM_ID]; std::string& silent = params[SAM_PARAM_SILENT]; if (silent == SAM_VALUE_TRUE) m_IsSilent = true; @@ -383,6 +385,35 @@ namespace client SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } + void SAMSocket::ProcessDatagramSend (char * buf, size_t len, const char * data) + { + LogPrint ("SAM datagram send: ", buf); + std::map params; + ExtractParams (buf, params); + size_t size = boost::lexical_cast(params[SAM_PARAM_SIZE]); + if (size < len) + { + if (m_Session) + { + auto d = m_Session->localDestination->GetDatagramDestination (); + if (d) + { + i2p::data::IdentityEx dest; + dest.FromBase64 (params[SAM_PARAM_DESTINATION]); + d->SendDatagramTo ((const uint8_t *)data, size, dest.GetIdentHash ()); + } + else + LogPrint (eLogError, "SAM missing datagram destination"); + } + else + LogPrint (eLogError, "SAM session is not created from DATAGRAM SEND"); + } + else + LogPrint (eLogError, "SAM datagram size ", size, " exceeds buffer"); + // since it's SAM v1 reply is not expected + Receive (); + } + void SAMSocket::ProcessDestGenerate () { LogPrint ("SAM dest generate"); @@ -401,7 +432,7 @@ namespace client { LogPrint ("SAM naming lookup: ", buf); std::map params; - ExtractParams (buf, len, params); + ExtractParams (buf, params); std::string& name = params[SAM_PARAM_NAME]; i2p::data::IdentityEx identity; i2p::data::IdentHash ident; @@ -467,7 +498,7 @@ namespace client SendMessageReply (m_Buffer, l, false); } - void SAMSocket::ExtractParams (char * buf, size_t len, std::map& params) + void SAMSocket::ExtractParams (char * buf, std::map& params) { char * separator; do @@ -779,15 +810,8 @@ namespace client { i2p::data::IdentityEx dest; dest.FromBase64 (destination); - auto leaseSet = i2p::data::netdb.FindLeaseSet (dest.GetIdentHash ()); - if (leaseSet) - session->localDestination->GetDatagramDestination ()-> - SendDatagramTo ((uint8_t *)eol, payloadLen, leaseSet); - else - { - LogPrint ("SAM datagram destination not found"); - session->localDestination->RequestDestination (dest.GetIdentHash ()); - } + session->localDestination->GetDatagramDestination ()-> + SendDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ()); } else LogPrint ("Session ", sessionID, " not found"); diff --git a/SAM.h b/SAM.h index de3cc8e0..5da4539b 100644 --- a/SAM.h +++ b/SAM.h @@ -34,6 +34,7 @@ namespace client const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER\n"; const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR\n"; const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT"; + const char SAM_DATAGRAM_SEND[] = "DATAGRAM SEND"; const char SAM_DEST_GENERATE[] = "DEST GENERATE"; const char SAM_DEST_REPLY[] = "DEST REPLY PUB=%s PRIV=%s\n"; const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n"; @@ -49,7 +50,8 @@ namespace client const char SAM_PARAM_SILENT[] = "SILENT"; const char SAM_PARAM_DESTINATION[] = "DESTINATION"; const char SAM_PARAM_NAME[] = "NAME"; - const char SAM_PARAM_SIGNATURE_TYPE[] = "SIGNATURE_TYPE"; + const char SAM_PARAM_SIGNATURE_TYPE[] = "SIGNATURE_TYPE"; + const char SAM_PARAM_SIZE[] = "SIZE"; const char SAM_VALUE_TRANSIENT[] = "TRANSIENT"; const char SAM_VALUE_STREAM[] = "STREAM"; const char SAM_VALUE_DATAGRAM[] = "DATAGRAM"; @@ -101,9 +103,10 @@ namespace client void ProcessSessionCreate (char * buf, size_t len); void ProcessStreamConnect (char * buf, size_t len); void ProcessStreamAccept (char * buf, size_t len); + void ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 void ProcessDestGenerate (); void ProcessNamingLookup (char * buf, size_t len); - void ExtractParams (char * buf, size_t len, std::map& params); + void ExtractParams (char * buf, std::map& params); void Connect (std::shared_ptr remote); void HandleConnectLeaseSetRequestComplete (bool success, i2p::data::IdentHash ident);