diff --git a/Destination.cpp b/Destination.cpp index af425694..b0e33d63 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -84,7 +84,8 @@ namespace client delete m_LeaseSet; delete m_Work; delete m_Service; - delete m_StreamingDestination; // TODO + delete m_StreamingDestination; + delete m_DatagramDestination; } void ClientDestination::Run () @@ -292,5 +293,11 @@ namespace client return m_StreamingDestination->IsAcceptorSet (); return false; } + + void ClientDestination::CreateDatagramDestination () + { + if (!m_DatagramDestination) + m_DatagramDestination = new i2p::datagram::DatagramDestination (*this); + } } } diff --git a/Destination.h b/Destination.h index fcb8329d..b605cc9d 100644 --- a/Destination.h +++ b/Destination.h @@ -46,6 +46,10 @@ namespace client void StopAcceptingStreams (); bool IsAcceptingStreams () const; + // datagram + i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; + void CreateDatagramDestination (); + // implements LocalDestination const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; diff --git a/SAM.cpp b/SAM.cpp index 897fe5a0..fcc90106 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -206,6 +206,7 @@ namespace client LogPrint ("SAM session create: ", buf); std::map params; ExtractParams (buf, len, params); + std::string& style = params[SAM_PARAM_STYLE]; std::string& id = params[SAM_PARAM_ID]; std::string& destination = params[SAM_PARAM_DESTINATION]; m_ID = id; @@ -220,7 +221,11 @@ namespace client { m_SocketType = eSAMSocketTypeSession; if (m_Session->localDestination->IsReady ()) + { + if (style == SAM_VALUE_DATAGRAM) + m_Session->localDestination->CreateDatagramDestination (); SendSessionCreateReplyOk (); + } else { m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); @@ -523,7 +528,8 @@ namespace client SAMBridge::SAMBridge (int port): m_IsRunning (false), m_Thread (nullptr), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)), - m_NewSocket (nullptr) + m_DatagramEndpoint (boost::asio::ip::udp::v4 (), port-1), m_DatagramSocket (m_Service, m_DatagramEndpoint), + m_NewSocket (nullptr) { } @@ -536,6 +542,7 @@ namespace client void SAMBridge::Start () { Accept (); + ReceiveDatagram (); m_IsRunning = true; m_Thread = new std::thread (std::bind (&SAMBridge::Run, this)); } @@ -641,5 +648,23 @@ namespace client return &it->second; return nullptr; } + + void SAMBridge::ReceiveDatagram () + { + m_DatagramSocket.async_receive_from ( + boost::asio::buffer (m_DatagramReceiveBuffer, i2p::datagram::MAX_DATAGRAM_SIZE), + m_SenderEndpoint, + boost::bind (&SAMBridge::HandleReceivedDatagram, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + } + + void SAMBridge::HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred) + { + if (!ecode) + { + ReceiveDatagram (); + } + else + LogPrint ("SAM datagram receive error: ", ecode.message ()); + } } } diff --git a/SAM.h b/SAM.h index 00ce366d..abf2b609 100644 --- a/SAM.h +++ b/SAM.h @@ -47,6 +47,9 @@ namespace client const char SAM_PARAM_DESTINATION[] = "DESTINATION"; const char SAM_PARAM_NAME[] = "NAME"; const char SAM_VALUE_TRANSIENT[] = "TRANSIENT"; + const char SAM_VALUE_STREAM[] = "STREAM"; + const char SAM_VALUE_DATAGRAM[] = "DATAGRAM"; + const char SAM_VALUE_RAW[] = "RAW"; const char SAM_VALUE_TRUE[] = "true"; const char SAM_VALUE_FALSE[] = "false"; @@ -142,15 +145,21 @@ namespace client void Accept (); void HandleAccept(const boost::system::error_code& ecode); + void ReceiveDatagram (); + void HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred); + private: bool m_IsRunning; std::thread * m_Thread; boost::asio::io_service m_Service; boost::asio::ip::tcp::acceptor m_Acceptor; + boost::asio::ip::udp::endpoint m_DatagramEndpoint, m_SenderEndpoint; + boost::asio::ip::udp::socket m_DatagramSocket; SAMSocket * m_NewSocket; std::mutex m_SessionsMutex; std::map m_Sessions; + uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE]; }; } }