Merge pull request #790 from majestrate/sam-datagrams

udp datagrams and whitespace cleanups in SAM
This commit is contained in:
orignal 2017-01-31 12:14:27 -05:00 committed by GitHub
commit 9030b3e04c
3 changed files with 227 additions and 154 deletions

View File

@ -1,5 +1,5 @@
# set defaults instead redefine # set defaults instead redefine
CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
INCFLAGS ?= INCFLAGS ?=
## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time ## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time

68
SAM.cpp
View File

@ -252,6 +252,7 @@ namespace client
Terminate (); Terminate ();
} }
} }
else else
{ {
LogPrint (eLogWarning, "SAM: incomplete message ", bytes_transferred); LogPrint (eLogWarning, "SAM: incomplete message ", bytes_transferred);
@ -278,6 +279,29 @@ namespace client
return; return;
} }
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())
{
// udp forward selected
boost::system::error_code e;
// TODO: support hostnames in udp forward
auto addr = boost::asio::ip::address::from_string(params[SAM_VALUE_HOST], e);
if (e)
{
// not an ip address
SendI2PError("Invalid IP Address in HOST");
return;
}
auto port = std::stoi(params[SAM_VALUE_PORT]);
if (port == -1)
{
SendI2PError("Invalid port");
return;
}
forward = std::make_shared<boost::asio::ip::udp::endpoint>(addr, port);
}
// create destination // create destination
m_Session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, &params); m_Session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, &params);
if (m_Session) if (m_Session)
@ -285,6 +309,7 @@ namespace client
m_SocketType = eSAMSocketTypeSession; m_SocketType = eSAMSocketTypeSession;
if (style == SAM_VALUE_DATAGRAM) if (style == SAM_VALUE_DATAGRAM)
{ {
m_Session->UDPEndpoint = forward;
auto dest = m_Session->localDestination->CreateDatagramDestination (); auto dest = m_Session->localDestination->CreateDatagramDestination ();
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));
@ -491,6 +516,17 @@ namespace client
} }
} }
void SAMSocket::SendI2PError(const std::string & msg)
{
LogPrint (eLogError, "SAM: i2p error ", msg);
#ifdef _MSC_VER
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
#else
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
#endif
SendMessageReply (m_Buffer, len, true);
}
void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet, i2p::data::IdentHash ident) void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet, i2p::data::IdentHash ident)
{ {
if (leaseSet) if (leaseSet)
@ -692,6 +728,26 @@ namespace client
{ {
LogPrint (eLogDebug, "SAM: datagram received ", len); LogPrint (eLogDebug, "SAM: datagram received ", len);
auto base64 = from.ToBase64 (); auto base64 = from.ToBase64 ();
auto ep = m_Session->UDPEndpoint;
if (ep)
{
// udp forward enabled
size_t bsz = base64.size();
size_t sz = bsz + 1 + len;
// build datagram body
uint8_t * data = new uint8_t[sz];
// Destination
memcpy(data, base64.c_str(), bsz);
// linefeed
data[bsz] = '\n';
// Payload
memcpy(data+bsz+1, buf, len);
// send to remote endpoint
m_Owner.SendTo(data, sz, ep);
delete [] data;
}
else
{
#ifdef _MSC_VER #ifdef _MSC_VER
size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len);
#else #else
@ -706,9 +762,11 @@ namespace client
else else
LogPrint (eLogWarning, "SAM: received datagram size ", len," exceeds buffer"); LogPrint (eLogWarning, "SAM: received datagram size ", len," exceeds buffer");
} }
}
SAMSession::SAMSession (std::shared_ptr<ClientDestination> dest): SAMSession::SAMSession (std::shared_ptr<ClientDestination> dest):
localDestination (dest) localDestination (dest),
UDPEndpoint(nullptr)
{ {
} }
@ -873,6 +931,14 @@ namespace client
return nullptr; return nullptr;
} }
void SAMBridge::SendTo(const uint8_t * buf, size_t len, std::shared_ptr<boost::asio::ip::udp::endpoint> remote)
{
if(remote)
{
m_DatagramSocket.send_to(boost::asio::buffer(buf, len), *remote);
}
}
void SAMBridge::ReceiveDatagram () void SAMBridge::ReceiveDatagram ()
{ {
m_DatagramSocket.async_receive_from ( m_DatagramSocket.async_receive_from (

9
SAM.h
View File

@ -29,6 +29,7 @@ namespace client
const char SAM_SESSION_CREATE_DUPLICATED_ID[] = "SESSION STATUS RESULT=DUPLICATED_ID\n"; const char SAM_SESSION_CREATE_DUPLICATED_ID[] = "SESSION STATUS RESULT=DUPLICATED_ID\n";
const char SAM_SESSION_CREATE_DUPLICATED_DEST[] = "SESSION STATUS RESULT=DUPLICATED_DEST\n"; const char SAM_SESSION_CREATE_DUPLICATED_DEST[] = "SESSION STATUS RESULT=DUPLICATED_DEST\n";
const char SAM_SESSION_STATUS_INVALID_KEY[] = "SESSION STATUS RESULT=INVALID_KEY\n"; const char SAM_SESSION_STATUS_INVALID_KEY[] = "SESSION STATUS RESULT=INVALID_KEY\n";
const char SAM_SESSION_STATUS_I2P_ERROR[] = "SESSION STATUS RESULT=I2P_ERROR MESSAGE=%s\n";
const char SAM_STREAM_CONNECT[] = "STREAM CONNECT"; const char SAM_STREAM_CONNECT[] = "STREAM CONNECT";
const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n"; const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n";
const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n"; const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n";
@ -59,6 +60,8 @@ namespace client
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";
const char SAM_VALUE_HOST[] = "HOST";
const char SAM_VALUE_PORT[] = "PORT";
enum SAMSocketType enum SAMSocketType
{ {
@ -106,6 +109,7 @@ namespace client
void ProcessStreamAccept (char * buf, size_t len); void ProcessStreamAccept (char * buf, size_t len);
void ProcessDestGenerate (); void ProcessDestGenerate ();
void ProcessNamingLookup (char * buf, size_t len); void ProcessNamingLookup (char * buf, size_t len);
void SendI2PError(const std::string & msg);
size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0
void ExtractParams (char * buf, std::map<std::string, std::string>& params); void ExtractParams (char * buf, std::map<std::string, std::string>& params);
@ -135,6 +139,7 @@ namespace client
{ {
std::shared_ptr<ClientDestination> localDestination; std::shared_ptr<ClientDestination> localDestination;
std::list<std::shared_ptr<SAMSocket> > m_Sockets; std::list<std::shared_ptr<SAMSocket> > m_Sockets;
std::shared_ptr<boost::asio::ip::udp::endpoint> UDPEndpoint;
std::mutex m_SocketsMutex; std::mutex m_SocketsMutex;
/** safely add a socket to this session */ /** safely add a socket to this session */
@ -181,6 +186,9 @@ namespace client
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;
/** send raw data to remote endpoint from our UDP Socket */
void SendTo(const uint8_t * buf, size_t len, std::shared_ptr<boost::asio::ip::udp::endpoint> remote);
private: private:
void Run (); void Run ();
@ -212,4 +220,3 @@ namespace client
} }
#endif #endif