Browse Source

send/receive raw datagrams through the SAM

pull/1389/head
orignal 5 years ago
parent
commit
cc451809cc
  1. 77
      libi2pd_client/SAM.cpp
  2. 15
      libi2pd_client/SAM.h

77
libi2pd_client/SAM.cpp

@ -337,8 +337,20 @@ namespace client
return; return;
} }
SAMSessionType type = eSAMSessionTypeUnknown;
if (style == SAM_VALUE_STREAM) type = eSAMSessionTypeStream;
else if (style == SAM_VALUE_DATAGRAM) type = eSAMSessionTypeDatagram;
else if (style == SAM_VALUE_RAW) type = eSAMSessionTypeRaw;
if (type == eSAMSessionTypeUnknown)
{
// unknown style
SendI2PError("Unknown STYLE");
return;
}
std::shared_ptr<boost::asio::ip::udp::endpoint> forward = nullptr; std::shared_ptr<boost::asio::ip::udp::endpoint> forward = nullptr;
if (style == SAM_VALUE_DATAGRAM && params.find(SAM_VALUE_HOST) != params.end() && params.find(SAM_VALUE_PORT) != params.end()) if ((type == eSAMSessionTypeDatagram || type == eSAMSessionTypeRaw) &&
params.find(SAM_VALUE_HOST) != params.end() && params.find(SAM_VALUE_PORT) != params.end())
{ {
// udp forward selected // udp forward selected
boost::system::error_code e; boost::system::error_code e;
@ -379,16 +391,20 @@ namespace client
} }
// create destination // create destination
auto session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, &params); auto session = m_Owner.CreateSession (id, type, destination == SAM_VALUE_TRANSIENT ? "" : destination, &params);
if (session) if (session)
{ {
m_SocketType = eSAMSocketTypeSession; m_SocketType = eSAMSocketTypeSession;
if (style == SAM_VALUE_DATAGRAM) if (type == eSAMSessionTypeDatagram || type == eSAMSessionTypeRaw)
{ {
session->UDPEndpoint = forward; session->UDPEndpoint = forward;
auto dest = session->localDestination->CreateDatagramDestination (); auto dest = session->localDestination->CreateDatagramDestination ();
dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (), if (type == eSAMSessionTypeDatagram)
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
else // raw
dest->SetRawReceiver (std::bind (&SAMSocket::HandleI2PRawDatagramReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
} }
if (session->localDestination->IsReady ()) if (session->localDestination->IsReady ())
@ -550,7 +566,10 @@ namespace client
{ {
i2p::data::IdentityEx dest; i2p::data::IdentityEx dest;
dest.FromBase64 (params[SAM_PARAM_DESTINATION]); dest.FromBase64 (params[SAM_PARAM_DESTINATION]);
d->SendDatagramTo ((const uint8_t *)data, size, dest.GetIdentHash ()); if (session->Type == eSAMSessionTypeDatagram)
d->SendDatagramTo ((const uint8_t *)data, size, dest.GetIdentHash ());
else // raw
d->SendRawDatagramTo ((const uint8_t *)data, size, dest.GetIdentHash ());
} }
else else
LogPrint (eLogError, "SAM: missing datagram destination"); LogPrint (eLogError, "SAM: missing datagram destination");
@ -926,16 +945,44 @@ namespace client
} }
} }
void SAMSocket::HandleI2PRawDatagramReceive (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
{
LogPrint (eLogDebug, "SAM: raw datagram received ", len);
auto session = m_Owner.FindSession(m_ID);
if(session)
{
auto ep = session->UDPEndpoint;
if (ep)
// udp forward enabled
m_Owner.SendTo(buf, len, ep);
else
{
#ifdef _MSC_VER
size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_RAW_RECEIVED, (long unsigned int)len);
#else
size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_RAW_RECEIVED, (long unsigned int)len);
#endif
if (len < SAM_SOCKET_BUFFER_SIZE - l)
{
memcpy (m_StreamBuffer + l, buf, len);
WriteI2PData(len + l);
}
else
LogPrint (eLogWarning, "SAM: received raw datagram size ", len," exceeds buffer");
}
}
}
void SAMSocket::HandleStreamSend(const boost::system::error_code & ec) void SAMSocket::HandleStreamSend(const boost::system::error_code & ec)
{ {
m_Owner.GetService ().post (std::bind( !ec ? &SAMSocket::Receive : &SAMSocket::TerminateClose, shared_from_this())); m_Owner.GetService ().post (std::bind( !ec ? &SAMSocket::Receive : &SAMSocket::TerminateClose, shared_from_this()));
} }
SAMSession::SAMSession (SAMBridge & parent, const std::string & id, std::shared_ptr<ClientDestination> dest): SAMSession::SAMSession (SAMBridge & parent, const std::string & id, SAMSessionType type, std::shared_ptr<ClientDestination> dest):
m_Bridge(parent), m_Bridge(parent),
localDestination (dest), localDestination (dest),
UDPEndpoint(nullptr), UDPEndpoint(nullptr),
Name(id) Name(id), Type (type)
{ {
} }
@ -1061,8 +1108,8 @@ namespace client
Accept (); Accept ();
} }
std::shared_ptr<SAMSession> SAMBridge::CreateSession (const std::string& id, const std::string& destination, std::shared_ptr<SAMSession> SAMBridge::CreateSession (const std::string& id, SAMSessionType type,
const std::map<std::string, std::string> * params) const std::string& destination, const std::map<std::string, std::string> * params)
{ {
std::shared_ptr<ClientDestination> localDestination = nullptr; std::shared_ptr<ClientDestination> localDestination = nullptr;
if (destination != "") if (destination != "")
@ -1102,7 +1149,7 @@ namespace client
if (localDestination) if (localDestination)
{ {
localDestination->Acquire (); localDestination->Acquire ();
auto session = std::make_shared<SAMSession>(*this, id, localDestination); auto session = std::make_shared<SAMSession>(*this, id, type, localDestination);
std::unique_lock<std::mutex> l(m_SessionsMutex); std::unique_lock<std::mutex> l(m_SessionsMutex);
auto ret = m_Sessions.insert (std::make_pair(id, session)); auto ret = m_Sessions.insert (std::make_pair(id, session));
if (!ret.second) if (!ret.second)
@ -1193,8 +1240,12 @@ namespace client
{ {
i2p::data::IdentityEx dest; i2p::data::IdentityEx dest;
dest.FromBase64 (destination); dest.FromBase64 (destination);
session->localDestination->GetDatagramDestination ()-> if (session->Type == eSAMSessionTypeDatagram)
SendDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ()); session->localDestination->GetDatagramDestination ()->
SendDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ());
else // raw
session->localDestination->GetDatagramDestination ()->
SendRawDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ());
} }
else else
LogPrint (eLogError, "SAM: Session ", sessionID, " not found"); LogPrint (eLogError, "SAM: Session ", sessionID, " not found");

15
libi2pd_client/SAM.h

@ -46,6 +46,7 @@ namespace client
const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP"; const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP";
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n"; const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n";
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n"; const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n";
const char SAM_RAW_RECEIVED[] = "RAW RECEIVED SIZE=%lu\n";
const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n"; const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n";
const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=KEY_NOT_FOUND NAME=%s\n"; const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=KEY_NOT_FOUND NAME=%s\n";
const char SAM_PARAM_MIN[] = "MIN"; const char SAM_PARAM_MIN[] = "MIN";
@ -111,6 +112,7 @@ namespace client
void HandleI2PAccept (std::shared_ptr<i2p::stream::Stream> stream); void HandleI2PAccept (std::shared_ptr<i2p::stream::Stream> stream);
void HandleWriteI2PData (const boost::system::error_code& ecode, size_t sz); void HandleWriteI2PData (const boost::system::error_code& ecode, size_t sz);
void HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void HandleI2PRawDatagramReceive (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void ProcessSessionCreate (char * buf, size_t len); void ProcessSessionCreate (char * buf, size_t len);
void ProcessStreamConnect (char * buf, size_t len, size_t rem); void ProcessStreamConnect (char * buf, size_t len, size_t rem);
@ -149,14 +151,23 @@ namespace client
std::shared_ptr<i2p::stream::Stream> m_Stream; std::shared_ptr<i2p::stream::Stream> m_Stream;
}; };
enum SAMSessionType
{
eSAMSessionTypeUnknown,
eSAMSessionTypeStream,
eSAMSessionTypeDatagram,
eSAMSessionTypeRaw
};
struct SAMSession struct SAMSession
{ {
SAMBridge & m_Bridge; SAMBridge & m_Bridge;
std::shared_ptr<ClientDestination> localDestination; std::shared_ptr<ClientDestination> localDestination;
std::shared_ptr<boost::asio::ip::udp::endpoint> UDPEndpoint; std::shared_ptr<boost::asio::ip::udp::endpoint> UDPEndpoint;
std::string Name; std::string Name;
SAMSessionType Type;
SAMSession (SAMBridge & parent, const std::string & name, std::shared_ptr<ClientDestination> dest); SAMSession (SAMBridge & parent, const std::string & name, SAMSessionType type, std::shared_ptr<ClientDestination> dest);
~SAMSession (); ~SAMSession ();
void CloseStreams (); void CloseStreams ();
@ -173,7 +184,7 @@ namespace client
void Stop (); void Stop ();
boost::asio::io_service& GetService () { return m_Service; }; boost::asio::io_service& GetService () { return m_Service; };
std::shared_ptr<SAMSession> CreateSession (const std::string& id, const std::string& destination, // empty string means transient std::shared_ptr<SAMSession> CreateSession (const std::string& id, SAMSessionType type, const std::string& destination, // empty string means transient
const std::map<std::string, std::string> * params); const std::map<std::string, std::string> * params);
void CloseSession (const std::string& id); void CloseSession (const std::string& id);
std::shared_ptr<SAMSession> FindSession (const std::string& id) const; std::shared_ptr<SAMSession> FindSession (const std::string& id) const;

Loading…
Cancel
Save