Browse Source

Merge pull request #275 from majestrate/master

add datagram forwarding to sam
pull/281/head
EinMByte 9 years ago
parent
commit
9da8f44761
  1. 91
      client/SAM.cpp
  2. 17
      client/SAM.h

91
client/SAM.cpp

@ -42,6 +42,7 @@ namespace client
switch (m_SocketType) switch (m_SocketType)
{ {
case eSAMSocketTypeUDPForward:
case eSAMSocketTypeSession: case eSAMSocketTypeSession:
m_Owner.CloseSession (m_ID); m_Owner.CloseSession (m_ID);
break; break;
@ -282,8 +283,27 @@ namespace client
if (style == SAM_VALUE_DATAGRAM) if (style == SAM_VALUE_DATAGRAM)
{ {
auto dest = m_Session->localDestination->CreateDatagramDestination (); auto dest = m_Session->localDestination->CreateDatagramDestination ();
auto portitr = params.find(SAM_PARAM_PORT);
if ( portitr != params.end() ) {
// port parameter set, this means they want to do UDP forward
auto port = boost::lexical_cast<int> (portitr->second);
// XXX: have default host configurable?
std::string host = "127.0.0.1";
auto hostitr = params.find(SAM_PARAM_HOST);
if ( hostitr != params.end() ) {
// host parameter set use that instead of loopback
host = hostitr->second;
}
// set forward addresss
m_udpForward = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(host), port);
// we are now a udp forward socket
m_SocketType = eSAMSocketTypeUDPForward;
}
dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (), dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
} }
if (m_Session->localDestination->IsReady ()) if (m_Session->localDestination->IsReady ())
@ -646,20 +666,27 @@ namespace client
void SAMSocket::HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t, uint16_t, const uint8_t * buf, size_t len) void SAMSocket::HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t, uint16_t, const uint8_t * buf, size_t len)
{ {
LogPrint (eLogDebug, "SAM datagram received ", len); LogPrint (eLogDebug, "SAM datagram received ", len);
auto base64 = from.ToBase64 (); if (m_SocketType == eSAMSocketTypeUDPForward)
{
// use the bridge to forward it via udp
m_Owner.ForwardUDP(m_udpForward, from, buf, len);
} else {
auto base64 = from.ToBase64 ();
// use the session socket
#ifdef _MSC_VER #ifdef _MSC_VER
size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), len); size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), len);
#else #else
size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), len); size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), len);
#endif #endif
if (len < SAM_SOCKET_BUFFER_SIZE - l) if (len < SAM_SOCKET_BUFFER_SIZE - l)
{ {
memcpy (m_StreamBuffer + l, buf, len); memcpy (m_StreamBuffer + l, buf, len);
boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, len + l), boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, len + l),
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1));
}
else
LogPrint (eLogWarning, "SAM received datagram size ", len," exceeds buffer");
} }
else
LogPrint (eLogWarning, "SAM received datagram size ", len," exceeds buffer");
} }
SAMSession::SAMSession (std::shared_ptr<ClientDestination> dest): SAMSession::SAMSession (std::shared_ptr<ClientDestination> dest):
@ -690,7 +717,8 @@ namespace client
boost::asio::ip::address::from_string(address), port) boost::asio::ip::address::from_string(address), port)
), ),
m_DatagramEndpoint(boost::asio::ip::address::from_string(address), port - 1), m_DatagramEndpoint(boost::asio::ip::address::from_string(address), port - 1),
m_DatagramSocket(m_Service, m_DatagramEndpoint) m_DatagramSocket(m_Service, m_DatagramEndpoint),
m_Forward(nullptr)
{ {
} }
@ -870,5 +898,44 @@ namespace client
else else
LogPrint ("SAM datagram receive error: ", ecode.message ()); LogPrint ("SAM datagram receive error: ", ecode.message ());
} }
void SAMBridge::ForwardUDP(const boost::asio::ip::udp::endpoint & to_ep, const i2p::data::IdentityEx& from, const uint8_t * buff, size_t bufflen)
{
if (m_Forward)
{
// drop, we are already trying to send
LogPrint(eLogWarning, "Dropping a forwarded datagram");
} else {
auto base64 = from.ToBase64();
auto b64_size = base64.size();
std::size_t forward_len = bufflen + sizeof(char) + b64_size;
m_Forward = new uint8_t[forward_len];
// make datagram
memcpy(m_Forward, base64.c_str(), b64_size);
memset(m_Forward + b64_size, 10, 1);
memcpy(m_Forward + b64_size + 1, buff, bufflen);
// async sendto
m_DatagramSocket.async_send_to(
boost::asio::buffer(m_Forward, forward_len),
to_ep,
std::bind(&SAMBridge::HandleForwardedUDP, this, std::placeholders::_1, std::placeholders::_2));
}
}
void SAMBridge::HandleForwardedUDP(const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
if(!ecode)
{
LogPrint("Forwarded ", bytes_transferred, "B");
}
if(m_Forward)
{
delete [] m_Forward;
m_Forward = nullptr;
}
}
} }
} }

17
client/SAM.h

@ -53,10 +53,13 @@ namespace client
const char SAM_PARAM_NAME[] = "NAME"; 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_PARAM_SIZE[] = "SIZE";
const char SAM_PARAM_FORWARD[] = "FORWARD";
const char SAM_PARAM_HOST[] = "HOST";
const char SAM_PARAM_PORT[] = "PORT";
const char SAM_VALUE_TRANSIENT[] = "TRANSIENT"; const char SAM_VALUE_TRANSIENT[] = "TRANSIENT";
const char SAM_VALUE_STREAM[] = "STREAM"; const char SAM_VALUE_STREAM[] = "STREAM";
const char SAM_VALUE_DATAGRAM[] = "DATAGRAM"; const char SAM_VALUE_DATAGRAM[] = "DATAGRAM";
const char SAM_VALUE_RAW[] = "RAW"; const char SAM_VALUE_RAW[] = "RAW";
const char SAM_VALUE_TRUE[] = "true"; const char SAM_VALUE_TRUE[] = "true";
const char SAM_VALUE_FALSE[] = "false"; const char SAM_VALUE_FALSE[] = "false";
@ -66,7 +69,8 @@ namespace client
eSAMSocketTypeSession, eSAMSocketTypeSession,
eSAMSocketTypeStream, eSAMSocketTypeStream,
eSAMSocketTypeAcceptor, eSAMSocketTypeAcceptor,
eSAMSocketTypeTerminated eSAMSocketTypeUDPForward,
eSAMSocketTypeTerminated,
}; };
class SAMBridge; class SAMBridge;
@ -119,6 +123,7 @@ namespace client
private: private:
SAMBridge& m_Owner; SAMBridge& m_Owner;
boost::asio::ip::udp::endpoint m_udpForward;
boost::asio::ip::tcp::socket m_Socket; boost::asio::ip::tcp::socket m_Socket;
boost::asio::deadline_timer m_Timer; boost::asio::deadline_timer m_Timer;
char m_Buffer[SAM_SOCKET_BUFFER_SIZE + 1]; char m_Buffer[SAM_SOCKET_BUFFER_SIZE + 1];
@ -158,6 +163,9 @@ namespace client
void CloseSession (const std::string& id); void CloseSession (const std::string& id);
SAMSession * FindSession (const std::string& id) const; SAMSession * FindSession (const std::string& id) const;
// forward a datagran to a udp endpoint
void ForwardUDP(const boost::asio::ip::udp::endpoint & to_ep, const i2p::data::IdentityEx& from, const uint8_t * buff, size_t bufflen);
private: private:
void Run (); void Run ();
@ -167,7 +175,8 @@ namespace client
void ReceiveDatagram (); void ReceiveDatagram ();
void HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleForwardedUDP(const boost::system::error_code& ecode, std::size_t bytes_transferrted);
private: private:
bool m_IsRunning; bool m_IsRunning;
@ -179,7 +188,7 @@ namespace client
mutable std::mutex m_SessionsMutex; mutable std::mutex m_SessionsMutex;
std::map<std::string, SAMSession *> m_Sessions; std::map<std::string, SAMSession *> m_Sessions;
uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE+1]; uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE+1];
uint8_t * m_Forward; // current buffer to forward or nullptr if there is none to forward now
public: public:
// for HTTP // for HTTP

Loading…
Cancel
Save