diff --git a/SSU.cpp b/SSU.cpp index 4a9892ab..314a62da 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -47,6 +47,11 @@ namespace ssu { switch (m_State) { + case eSessionStateEstablised: + // most common case + ProcessMessage (buf, len); + break; + // establishing case eSessionStateUnknown: // session request ProcessSessionRequest (buf, len, senderEndpoint); @@ -64,6 +69,34 @@ namespace ssu } } + void SSUSession::ProcessMessage (uint8_t * buf, size_t len) + { + if (Validate (buf, len, m_MacKey)) + { + Decrypt (buf, len, m_SessionKey); + SSUHeader * header = (SSUHeader *)buf; + uint8_t payloadType = header->flag >> 4; + switch (payloadType) + { + case PAYLOAD_TYPE_DATA: + LogPrint ("SSU data received"); + ProcessData (buf + sizeof (SSUHeader), len - sizeof (SSUHeader)); + break; + case PAYLOAD_TYPE_TEST: + LogPrint ("SSU test received"); + break; + case PAYLOAD_TYPE_SESSION_DESTROY: + LogPrint ("SSU session destroy received"); + break; + default: + LogPrint ("Unexpected SSU payload type ", (int)payloadType); + } + } + // TODO: try intro key as well + else + LogPrint ("MAC verifcation failed"); + } + void SSUSession::ProcessSessionRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { LogPrint ("Process session request"); @@ -98,6 +131,7 @@ namespace ssu LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort); uint32_t relayTag = be32toh (*(uint32_t *)(buf + sizeof (SSUHeader) + 263)); SendSessionConfirmed (buf + sizeof (SSUHeader), ourAddress, relayTag); + m_State = eSessionStateEstablised; } } @@ -113,6 +147,7 @@ namespace ssu m_State = eSessionStateConfirmedReceived; LogPrint ("Session confirmed received"); // TODO: + m_State = eSessionStateEstablised; } else LogPrint ("Unexpected payload type ", (int)(header->flag >> 4)); @@ -327,6 +362,31 @@ namespace ssu // TODO: } + void SSUSession::ProcessData (uint8_t * buf, size_t len) + { + //uint8_t * start = buf; + uint8_t flag = *buf; + buf++; + LogPrint ("Process SSU data flags=", (int)flag); + uint8_t numFragments = *buf; // number of fragments + buf++; + for (int i = 0; i < numFragments; i++) + { + uint32_t msgID = be32toh (*(uint32_t *)buf); // message ID + buf += 4; + uint8_t frag[4]; + frag[0] = 0; + memcpy (frag + 1, buf, 3); + buf += 3; + uint32_t fragmentInfo = be32toh (*(uint32_t *)frag); // fragment info + uint16_t fragmentSize = fragmentInfo & 0x1FFF; // bits 0 - 13 + bool isLast = fragmentInfo & 0x010000; // bit 16 + uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17 + LogPrint ("SSU data fragment ", (int)fragmentNum, " of message ", msgID, " size=", (int)fragmentSize, isLast ? " last" : " non-last"); + buf += fragmentSize; + } + } + SSUServer::SSUServer (boost::asio::io_service& service, int port): m_Endpoint (boost::asio::ip::udp::v4 (), port), m_Socket (service, m_Endpoint) { diff --git a/SSU.h b/SSU.h index c33b3f83..aee160ae 100644 --- a/SSU.h +++ b/SSU.h @@ -65,12 +65,14 @@ namespace ssu void CreateAESandMacKey (uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey); + void ProcessMessage (uint8_t * buf, size_t len); // call for established session void ProcessSessionRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); void SendSessionRequest (); void ProcessSessionCreated (uint8_t * buf, size_t len); void SendSessionCreated (const uint8_t * x); void ProcessSessionConfirmed (uint8_t * buf, size_t len); void SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress, uint32_t relayTag); + void ProcessData (uint8_t * buf, size_t len); bool ProcessIntroKeyEncryptedMessage (uint8_t expectedPayloadType, i2p::data::RouterInfo& r, uint8_t * buf, size_t len); void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, uint8_t * aesKey, uint8_t * iv, uint8_t * macKey); diff --git a/i2p.cpp b/i2p.cpp index 24341fe7..355c2003 100644 --- a/i2p.cpp +++ b/i2p.cpp @@ -29,23 +29,29 @@ int running = 1; #ifndef _WIN32 -void handle_sighup(int n) +void handle_signal(int sig) { - if (i2p::util::config::GetArg("daemon", 0) == 1) + switch (sig) { - static bool first=true; - if (first) - { - first=false; - return; - } + case SIGHUP: + if (i2p::util::config::GetArg("daemon", 0) == 1) + { + static bool first=true; + if (first) + { + first=false; + return; + } + } + LogPrint("Reloading config."); + i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); + break; + case SIGABRT: + case SIGTERM: + case SIGINT: + running = 0; // Exit loop + break; } - LogPrint("Reloading config."); - i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); -} -void handle_shutdown(int sig) -{ - running = 0; // Exit loop } #endif @@ -66,15 +72,6 @@ int main( int argc, char* argv[] ) i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); #ifndef _WIN32 - struct sigaction sa; - sa.sa_handler = handle_sighup; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - if (sigaction(SIGHUP,&sa,0) == -1) - { - LogPrint("Failed to install SIGHUP handler."); - } - if (i2p::util::config::GetArg("-daemon", 0) == 1) { pid_t pid; @@ -96,12 +93,36 @@ int main( int argc, char* argv[] ) LogPrint("Error, could not create process group."); return -1; } + chdir(i2p::util::filesystem::GetDataDir().string().c_str()); } - // Handle shutdown - signal(SIGABRT, &handle_shutdown); - signal(SIGTERM, &handle_shutdown); - signal(SIGINT, &handle_shutdown); + // Pidfile + std::string pidfile = i2p::util::filesystem::GetDataDir().string(); + pidfile.append("/i2pd.pid"); + int pidFilehandle = open(pidfile.c_str(), O_RDWR|O_CREAT, 0600); + if (pidFilehandle == -1 ) + { + LogPrint("Error, could not create pid file (", pidfile, ")\nIs an instance already running?"); + return -1; + } + if (lockf(pidFilehandle,F_TLOCK,0) == -1) + { + LogPrint("Error, could not lock pid file (", pidfile, ")\nIs an instance already running?"); + return -1; + } + char pid[10]; + sprintf(pid,"%d\n",getpid()); + write(pidFilehandle, pid, strlen(pid)); + + // Signal handler + struct sigaction sa; + sa.sa_handler = handle_signal; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction(SIGHUP,&sa,0); + sigaction(SIGABRT,&sa,0); + sigaction(SIGTERM,&sa,0); + sigaction(SIGINT,&sa,0); #endif if (i2p::util::config::GetArg("-log", 0) == 1) @@ -123,9 +144,9 @@ int main( int argc, char* argv[] ) i2p::util::HTTPServer httpServer (i2p::util::config::GetArg("-httpport", 7070)); - httpServer.Start (); + httpServer.Start (); i2p::data::netdb.Start (); - i2p::transports.Start (); + i2p::transports.Start (); i2p::tunnel::tunnels.Start (); while (running) @@ -135,14 +156,18 @@ int main( int argc, char* argv[] ) } LogPrint("Shutdown started."); - i2p::tunnel::tunnels.Stop (); - i2p::transports.Stop (); - i2p::data::netdb.Stop (); + i2p::tunnel::tunnels.Stop (); + i2p::transports.Stop (); + i2p::data::netdb.Stop (); httpServer.Stop (); if (i2p::util::config::GetArg("-log", 0) == 1) { fclose (stdout); } +#ifndef _WIN32 + close(pidFilehandle); + unlink(pidfile.c_str()); +#endif return 0; }