Destination.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224
  1. #include <algorithm>
  2. #include <cassert>
  3. #include <string>
  4. #include "Crypto.h"
  5. #include "Log.h"
  6. #include "FS.h"
  7. #include "Timestamp.h"
  8. #include "NetDb.hpp"
  9. #include "Destination.h"
  10. #include "util.h"
  11. namespace i2p
  12. {
  13. namespace client
  14. {
  15. LeaseSetDestination::LeaseSetDestination (bool isPublic, const std::map<std::string, std::string> * params):
  16. m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic),
  17. m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
  18. m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service),
  19. m_LeaseSetType (DEFAULT_LEASESET_TYPE)
  20. {
  21. int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH;
  22. int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY;
  23. int outLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH;
  24. int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY;
  25. int numTags = DEFAULT_TAGS_TO_SEND;
  26. std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
  27. try
  28. {
  29. if (params)
  30. {
  31. auto it = params->find (I2CP_PARAM_INBOUND_TUNNEL_LENGTH);
  32. if (it != params->end ())
  33. inLen = std::stoi(it->second);
  34. it = params->find (I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH);
  35. if (it != params->end ())
  36. outLen = std::stoi(it->second);
  37. it = params->find (I2CP_PARAM_INBOUND_TUNNELS_QUANTITY);
  38. if (it != params->end ())
  39. inQty = std::stoi(it->second);
  40. it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY);
  41. if (it != params->end ())
  42. outQty = std::stoi(it->second);
  43. it = params->find (I2CP_PARAM_TAGS_TO_SEND);
  44. if (it != params->end ())
  45. numTags = std::stoi(it->second);
  46. LogPrint (eLogInfo, "Destination: parameters for tunnel set to: ", inQty, " inbound (", inLen, " hops), ", outQty, " outbound (", outLen, " hops), ", numTags, " tags");
  47. it = params->find (I2CP_PARAM_EXPLICIT_PEERS);
  48. if (it != params->end ())
  49. {
  50. explicitPeers = std::make_shared<std::vector<i2p::data::IdentHash> >();
  51. std::stringstream ss(it->second);
  52. std::string b64;
  53. while (std::getline (ss, b64, ','))
  54. {
  55. i2p::data::IdentHash ident;
  56. ident.FromBase64 (b64);
  57. explicitPeers->push_back (ident);
  58. LogPrint (eLogInfo, "Destination: Added to explicit peers list: ", b64);
  59. }
  60. }
  61. it = params->find (I2CP_PARAM_INBOUND_NICKNAME);
  62. if (it != params->end ()) m_Nickname = it->second;
  63. else // try outbound
  64. {
  65. it = params->find (I2CP_PARAM_OUTBOUND_NICKNAME);
  66. if (it != params->end ()) m_Nickname = it->second;
  67. // otherwise we set default nickname in Start when we know local address
  68. }
  69. it = params->find (I2CP_PARAM_LEASESET_TYPE);
  70. if (it != params->end ())
  71. m_LeaseSetType = std::stoi(it->second);
  72. it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY);
  73. if (it != params->end ())
  74. {
  75. m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>());
  76. if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32)
  77. {
  78. LogPrint(eLogError, "Destination: invalid value i2cp.leaseSetPrivKey ", it->second);
  79. m_LeaseSetPrivKey.reset (nullptr);
  80. }
  81. }
  82. }
  83. }
  84. catch (std::exception & ex)
  85. {
  86. LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what());
  87. }
  88. SetNumTags (numTags);
  89. m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty);
  90. if (explicitPeers)
  91. m_Pool->SetExplicitPeers (explicitPeers);
  92. if(params)
  93. {
  94. auto itr = params->find(I2CP_PARAM_MAX_TUNNEL_LATENCY);
  95. if (itr != params->end()) {
  96. auto maxlatency = std::stoi(itr->second);
  97. itr = params->find(I2CP_PARAM_MIN_TUNNEL_LATENCY);
  98. if (itr != params->end()) {
  99. auto minlatency = std::stoi(itr->second);
  100. if ( minlatency > 0 && maxlatency > 0 ) {
  101. // set tunnel pool latency
  102. LogPrint(eLogInfo, "Destination: requiring tunnel latency [", minlatency, "ms, ", maxlatency, "ms]");
  103. m_Pool->RequireLatency(minlatency, maxlatency);
  104. }
  105. }
  106. }
  107. }
  108. }
  109. LeaseSetDestination::~LeaseSetDestination ()
  110. {
  111. if (m_IsRunning)
  112. Stop ();
  113. if (m_Pool)
  114. i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool);
  115. for (auto& it: m_LeaseSetRequests)
  116. it.second->Complete (nullptr);
  117. }
  118. void LeaseSetDestination::Run ()
  119. {
  120. while (m_IsRunning)
  121. {
  122. try
  123. {
  124. m_Service.run ();
  125. }
  126. catch (std::exception& ex)
  127. {
  128. LogPrint (eLogError, "Destination: runtime exception: ", ex.what ());
  129. }
  130. }
  131. }
  132. bool LeaseSetDestination::Start ()
  133. {
  134. if (!m_IsRunning)
  135. {
  136. if (m_Nickname.empty ())
  137. m_Nickname = i2p::data::GetIdentHashAbbreviation (GetIdentHash ()); // set default nickname
  138. LoadTags ();
  139. m_IsRunning = true;
  140. m_Pool->SetLocalDestination (shared_from_this ());
  141. m_Pool->SetActive (true);
  142. m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT));
  143. m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer,
  144. shared_from_this (), std::placeholders::_1));
  145. m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ()));
  146. return true;
  147. }
  148. else
  149. return false;
  150. }
  151. bool LeaseSetDestination::Stop ()
  152. {
  153. if (m_IsRunning)
  154. {
  155. m_CleanupTimer.cancel ();
  156. m_PublishConfirmationTimer.cancel ();
  157. m_PublishVerificationTimer.cancel ();
  158. m_IsRunning = false;
  159. if (m_Pool)
  160. {
  161. m_Pool->SetLocalDestination (nullptr);
  162. i2p::tunnel::tunnels.StopTunnelPool (m_Pool);
  163. }
  164. m_Service.stop ();
  165. if (m_Thread)
  166. {
  167. m_Thread->join ();
  168. delete m_Thread;
  169. m_Thread = 0;
  170. }
  171. SaveTags ();
  172. CleanUp (); // GarlicDestination
  173. return true;
  174. }
  175. else
  176. return false;
  177. }
  178. bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
  179. {
  180. auto itr = params.find("i2cp.dontPublishLeaseSet");
  181. if (itr != params.end())
  182. {
  183. m_IsPublic = itr->second != "true";
  184. }
  185. int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency;
  186. std::map<std::string, int&> intOpts = {
  187. {I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen},
  188. {I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen},
  189. {I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, inQuant},
  190. {I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, outQuant},
  191. {I2CP_PARAM_TAGS_TO_SEND, numTags},
  192. {I2CP_PARAM_MIN_TUNNEL_LATENCY, minLatency},
  193. {I2CP_PARAM_MAX_TUNNEL_LATENCY, maxLatency}
  194. };
  195. auto pool = GetTunnelPool();
  196. inLen = pool->GetNumInboundHops();
  197. outLen = pool->GetNumOutboundHops();
  198. inQuant = pool->GetNumInboundTunnels();
  199. outQuant = pool->GetNumOutboundTunnels();
  200. minLatency = 0;
  201. maxLatency = 0;
  202. for (auto & opt : intOpts)
  203. {
  204. itr = params.find(opt.first);
  205. if(itr != params.end())
  206. {
  207. opt.second = std::stoi(itr->second);
  208. }
  209. }
  210. pool->RequireLatency(minLatency, maxLatency);
  211. return pool->Reconfigure(inLen, outLen, inQuant, outQuant);
  212. }
  213. std::shared_ptr<i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
  214. {
  215. std::shared_ptr<i2p::data::LeaseSet> remoteLS;
  216. {
  217. std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
  218. auto it = m_RemoteLeaseSets.find (ident);
  219. if (it != m_RemoteLeaseSets.end ())
  220. remoteLS = it->second;
  221. }
  222. if (remoteLS)
  223. {
  224. if (!remoteLS->IsExpired ())
  225. {
  226. if (remoteLS->ExpiresSoon())
  227. {
  228. LogPrint(eLogDebug, "Destination: Lease Set expires soon, updating before expire");
  229. // update now before expiration for smooth handover
  230. auto s = shared_from_this ();
  231. RequestDestination(ident, [s, ident] (std::shared_ptr<i2p::data::LeaseSet> ls) {
  232. if(ls && !ls->IsExpired())
  233. {
  234. ls->PopulateLeases();
  235. {
  236. std::lock_guard<std::mutex> _lock(s->m_RemoteLeaseSetsMutex);
  237. s->m_RemoteLeaseSets[ident] = ls;
  238. }
  239. }
  240. });
  241. }
  242. return remoteLS;
  243. }
  244. else
  245. {
  246. LogPrint (eLogWarning, "Destination: remote LeaseSet expired");
  247. std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
  248. m_RemoteLeaseSets.erase (ident);
  249. return nullptr;
  250. }
  251. }
  252. else
  253. {
  254. auto ls = i2p::data::netdb.FindLeaseSet (ident);
  255. if (ls && !ls->IsExpired ())
  256. {
  257. ls->PopulateLeases (); // since we don't store them in netdb
  258. std::lock_guard<std::mutex> _lock(m_RemoteLeaseSetsMutex);
  259. m_RemoteLeaseSets[ident] = ls;
  260. return ls;
  261. }
  262. }
  263. return nullptr;
  264. }
  265. std::shared_ptr<const i2p::data::LocalLeaseSet> LeaseSetDestination::GetLeaseSet ()
  266. {
  267. if (!m_Pool) return nullptr;
  268. if (!m_LeaseSet)
  269. UpdateLeaseSet ();
  270. auto ls = GetLeaseSetMt ();
  271. return (ls && ls->GetInnerLeaseSet ()) ? ls->GetInnerLeaseSet () : ls; // always non-encrypted
  272. }
  273. std::shared_ptr<const i2p::data::LocalLeaseSet> LeaseSetDestination::GetLeaseSetMt ()
  274. {
  275. std::lock_guard<std::mutex> l(m_LeaseSetMutex);
  276. return m_LeaseSet;
  277. }
  278. void LeaseSetDestination::SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet)
  279. {
  280. {
  281. std::lock_guard<std::mutex> l(m_LeaseSetMutex);
  282. m_LeaseSet = newLeaseSet;
  283. }
  284. i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
  285. if (m_IsPublic)
  286. {
  287. auto s = shared_from_this ();
  288. m_Service.post ([s](void)
  289. {
  290. s->m_PublishVerificationTimer.cancel ();
  291. s->Publish ();
  292. });
  293. }
  294. }
  295. void LeaseSetDestination::UpdateLeaseSet ()
  296. {
  297. int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels
  298. if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum
  299. CreateNewLeaseSet (m_Pool->GetInboundTunnels (numTunnels));
  300. }
  301. bool LeaseSetDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
  302. {
  303. struct
  304. {
  305. uint8_t k[32], t[32];
  306. } data;
  307. memcpy (data.k, key, 32);
  308. memcpy (data.t, tag, 32);
  309. auto s = shared_from_this ();
  310. m_Service.post ([s,data](void)
  311. {
  312. s->AddSessionKey (data.k, data.t);
  313. });
  314. return true;
  315. }
  316. void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
  317. {
  318. m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg));
  319. }
  320. void LeaseSetDestination::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
  321. {
  322. m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg));
  323. }
  324. void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
  325. {
  326. uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET];
  327. switch (typeID)
  328. {
  329. case eI2NPData:
  330. HandleDataMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
  331. break;
  332. case eI2NPDeliveryStatus:
  333. // we assume tunnel tests non-encrypted
  334. HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
  335. break;
  336. case eI2NPDatabaseStore:
  337. HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
  338. break;
  339. case eI2NPDatabaseSearchReply:
  340. HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
  341. break;
  342. default:
  343. i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
  344. }
  345. }
  346. void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
  347. {
  348. uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
  349. size_t offset = DATABASE_STORE_HEADER_SIZE;
  350. if (replyToken)
  351. {
  352. LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore");
  353. offset += 36;
  354. }
  355. i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET);
  356. std::shared_ptr<i2p::data::LeaseSet> leaseSet;
  357. switch (buf[DATABASE_STORE_TYPE_OFFSET])
  358. {
  359. case i2p::data::NETDB_STORE_TYPE_LEASESET: // 1
  360. case i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2: // 3
  361. {
  362. LogPrint (eLogDebug, "Destination: Remote LeaseSet");
  363. std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
  364. auto it = m_RemoteLeaseSets.find (key);
  365. if (it != m_RemoteLeaseSets.end ())
  366. {
  367. leaseSet = it->second;
  368. if (leaseSet->IsNewer (buf + offset, len - offset))
  369. {
  370. leaseSet->Update (buf + offset, len - offset);
  371. if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
  372. LogPrint (eLogDebug, "Destination: Remote LeaseSet updated");
  373. else
  374. {
  375. LogPrint (eLogDebug, "Destination: Remote LeaseSet update failed");
  376. m_RemoteLeaseSets.erase (it);
  377. leaseSet = nullptr;
  378. }
  379. }
  380. else
  381. LogPrint (eLogDebug, "Destination: Remote LeaseSet is older. Not updated");
  382. }
  383. else
  384. {
  385. if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET)
  386. leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset); // LeaseSet
  387. else
  388. leaseSet = std::make_shared<i2p::data::LeaseSet2> (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset); // LeaseSet2
  389. if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
  390. {
  391. if (leaseSet->GetIdentHash () != GetIdentHash ())
  392. {
  393. LogPrint (eLogDebug, "Destination: New remote LeaseSet added");
  394. m_RemoteLeaseSets[key] = leaseSet;
  395. }
  396. else
  397. LogPrint (eLogDebug, "Destination: Own remote LeaseSet dropped");
  398. }
  399. else
  400. {
  401. LogPrint (eLogError, "Destination: New remote LeaseSet failed");
  402. leaseSet = nullptr;
  403. }
  404. }
  405. break;
  406. }
  407. case i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2: // 5
  408. {
  409. auto it2 = m_LeaseSetRequests.find (key);
  410. if (it2 != m_LeaseSetRequests.end () && it2->second->requestedBlindedKey)
  411. {
  412. auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset, it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? *m_LeaseSetPrivKey : nullptr);
  413. if (ls2->IsValid ())
  414. {
  415. m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
  416. m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup
  417. leaseSet = ls2;
  418. }
  419. }
  420. else
  421. LogPrint (eLogInfo, "Destination: Couldn't find request for encrypted LeaseSet2");
  422. break;
  423. }
  424. default:
  425. LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped");
  426. }
  427. auto it1 = m_LeaseSetRequests.find (key);
  428. if (it1 != m_LeaseSetRequests.end ())
  429. {
  430. it1->second->requestTimeoutTimer.cancel ();
  431. if (it1->second) it1->second->Complete (leaseSet);
  432. m_LeaseSetRequests.erase (it1);
  433. }
  434. }
  435. void LeaseSetDestination::HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len)
  436. {
  437. i2p::data::IdentHash key (buf);
  438. int num = buf[32]; // num
  439. LogPrint (eLogDebug, "Destination: DatabaseSearchReply for ", key.ToBase64 (), " num=", num);
  440. auto it = m_LeaseSetRequests.find (key);
  441. if (it != m_LeaseSetRequests.end ())
  442. {
  443. auto request = it->second;
  444. bool found = false;
  445. if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
  446. {
  447. for (int i = 0; i < num; i++)
  448. {
  449. i2p::data::IdentHash peerHash (buf + 33 + i*32);
  450. if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash))
  451. {
  452. LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); // TODO: recheck this message
  453. i2p::data::netdb.RequestDestination (peerHash);
  454. }
  455. }
  456. auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
  457. if (floodfill)
  458. {
  459. LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ());
  460. if (SendLeaseSetRequest (key, floodfill, request))
  461. found = true;
  462. }
  463. }
  464. if (!found)
  465. {
  466. LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills");
  467. request->Complete (nullptr);
  468. m_LeaseSetRequests.erase (key);
  469. }
  470. }
  471. else
  472. LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found");
  473. }
  474. void LeaseSetDestination::HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
  475. {
  476. uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET);
  477. if (msgID == m_PublishReplyToken)
  478. {
  479. LogPrint (eLogDebug, "Destination: Publishing LeaseSet confirmed for ", GetIdentHash().ToBase32());
  480. m_ExcludedFloodfills.clear ();
  481. m_PublishReplyToken = 0;
  482. // schedule verification
  483. m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
  484. m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer,
  485. shared_from_this (), std::placeholders::_1));
  486. }
  487. else
  488. i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg);
  489. }
  490. void LeaseSetDestination::SetLeaseSetUpdated ()
  491. {
  492. UpdateLeaseSet ();
  493. }
  494. void LeaseSetDestination::Publish ()
  495. {
  496. auto leaseSet = GetLeaseSetMt ();
  497. if (!leaseSet || !m_Pool)
  498. {
  499. LogPrint (eLogError, "Destination: Can't publish non-existing LeaseSet");
  500. return;
  501. }
  502. if (m_PublishReplyToken)
  503. {
  504. LogPrint (eLogDebug, "Destination: Publishing LeaseSet is pending");
  505. return;
  506. }
  507. auto ts = i2p::util::GetSecondsSinceEpoch ();
  508. if (ts < m_LastSubmissionTime + PUBLISH_MIN_INTERVAL)
  509. {
  510. LogPrint (eLogDebug, "Destination: Publishing LeaseSet is too fast. Wait for ", PUBLISH_MIN_INTERVAL, " seconds");
  511. m_PublishDelayTimer.cancel ();
  512. m_PublishDelayTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_MIN_INTERVAL));
  513. m_PublishDelayTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishDelayTimer,
  514. shared_from_this (), std::placeholders::_1));
  515. return;
  516. }
  517. auto outbound = m_Pool->GetNextOutboundTunnel ();
  518. if (!outbound)
  519. {
  520. LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
  521. return;
  522. }
  523. auto inbound = m_Pool->GetNextInboundTunnel ();
  524. if (!inbound)
  525. {
  526. LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels");
  527. return;
  528. }
  529. auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
  530. if (!floodfill)
  531. {
  532. LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
  533. m_ExcludedFloodfills.clear ();
  534. return;
  535. }
  536. m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
  537. LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
  538. RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
  539. auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound));
  540. m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
  541. m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
  542. shared_from_this (), std::placeholders::_1));
  543. outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
  544. m_LastSubmissionTime = ts;
  545. }
  546. void LeaseSetDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode)
  547. {
  548. if (ecode != boost::asio::error::operation_aborted)
  549. {
  550. if (m_PublishReplyToken)
  551. {
  552. m_PublishReplyToken = 0;
  553. if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
  554. {
  555. LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again");
  556. Publish ();
  557. }
  558. else
  559. {
  560. LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ());
  561. // Java floodfill never sends confirmation back for unknown crypto type
  562. // assume it successive and try to verify
  563. m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
  564. m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer,
  565. shared_from_this (), std::placeholders::_1));
  566. }
  567. }
  568. }
  569. }
  570. void LeaseSetDestination::HandlePublishVerificationTimer (const boost::system::error_code& ecode)
  571. {
  572. if (ecode != boost::asio::error::operation_aborted)
  573. {
  574. auto ls = GetLeaseSetMt ();
  575. if (!ls)
  576. {
  577. LogPrint (eLogWarning, "Destination: couldn't verify LeaseSet for ", GetIdentHash().ToBase32());
  578. return;
  579. }
  580. auto s = shared_from_this ();
  581. // we must capture this for gcc 4.7 due the bug
  582. RequestLeaseSet (ls->GetStoreHash (),
  583. [s, ls, this](std::shared_ptr<const i2p::data::LeaseSet> leaseSet)
  584. {
  585. if (leaseSet)
  586. {
  587. if (*ls == *leaseSet)
  588. {
  589. // we got latest LeasetSet
  590. LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", s->GetIdentHash().ToBase32());
  591. s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
  592. s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
  593. return;
  594. }
  595. else
  596. LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", s->GetIdentHash().ToBase32());
  597. }
  598. else
  599. LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", s->GetIdentHash().ToBase32());
  600. // we have to publish again
  601. s->Publish ();
  602. });
  603. }
  604. }
  605. void LeaseSetDestination::HandlePublishDelayTimer (const boost::system::error_code& ecode)
  606. {
  607. if (ecode != boost::asio::error::operation_aborted)
  608. Publish ();
  609. }
  610. bool LeaseSetDestination::RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete)
  611. {
  612. if (!m_Pool || !IsReady ())
  613. {
  614. if (requestComplete)
  615. m_Service.post ([requestComplete](void){requestComplete (nullptr);});
  616. return false;
  617. }
  618. m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete, nullptr));
  619. return true;
  620. }
  621. bool LeaseSetDestination::RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, RequestComplete requestComplete)
  622. {
  623. if (!dest || !m_Pool || !IsReady ())
  624. {
  625. if (requestComplete)
  626. m_Service.post ([requestComplete](void){requestComplete (nullptr);});
  627. return false;
  628. }
  629. auto storeHash = dest->GetStoreHash ();
  630. auto leaseSet = FindLeaseSet (storeHash);
  631. if (leaseSet)
  632. {
  633. if (requestComplete)
  634. m_Service.post ([requestComplete, leaseSet](void){requestComplete (leaseSet);});
  635. return true;
  636. }
  637. m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), storeHash, requestComplete, dest));
  638. return true;
  639. }
  640. void LeaseSetDestination::CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify)
  641. {
  642. auto s = shared_from_this ();
  643. m_Service.post ([dest, notify, s](void)
  644. {
  645. auto it = s->m_LeaseSetRequests.find (dest);
  646. if (it != s->m_LeaseSetRequests.end ())
  647. {
  648. auto requestComplete = it->second;
  649. s->m_LeaseSetRequests.erase (it);
  650. if (notify && requestComplete) requestComplete->Complete (nullptr);
  651. }
  652. });
  653. }
  654. void LeaseSetDestination::CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, bool notify)
  655. {
  656. if (dest)
  657. CancelDestinationRequest (dest->GetStoreHash (), notify);
  658. }
  659. void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey)
  660. {
  661. std::set<i2p::data::IdentHash> excluded;
  662. auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, excluded);
  663. if (floodfill)
  664. {
  665. auto request = std::make_shared<LeaseSetRequest> (m_Service);
  666. request->requestedBlindedKey = requestedBlindedKey; // for encrypted LeaseSet2
  667. if (requestComplete)
  668. request->requestComplete.push_back (requestComplete);
  669. auto ts = i2p::util::GetSecondsSinceEpoch ();
  670. auto ret = m_LeaseSetRequests.insert (std::pair<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> >(dest,request));
  671. if (ret.second) // inserted
  672. {
  673. request->requestTime = ts;
  674. if (!SendLeaseSetRequest (dest, floodfill, request))
  675. {
  676. // request failed
  677. m_LeaseSetRequests.erase (ret.first);
  678. if (requestComplete) requestComplete (nullptr);
  679. }
  680. }
  681. else // duplicate
  682. {
  683. LogPrint (eLogInfo, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already");
  684. if (ts > ret.first->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT)
  685. {
  686. // something went wrong
  687. m_LeaseSetRequests.erase (ret.first);
  688. if (requestComplete) requestComplete (nullptr);
  689. }
  690. else if (requestComplete)
  691. ret.first->second->requestComplete.push_back (requestComplete);
  692. }
  693. }
  694. else
  695. {
  696. LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found");
  697. if (requestComplete) requestComplete (nullptr);
  698. }
  699. }
  700. bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
  701. std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
  702. {
  703. if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
  704. request->replyTunnel = m_Pool->GetNextInboundTunnel ();
  705. if (!request->replyTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no inbound tunnels found");
  706. if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ())
  707. request->outboundTunnel = m_Pool->GetNextOutboundTunnel ();
  708. if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found");
  709. if (request->replyTunnel && request->outboundTunnel)
  710. {
  711. request->excluded.insert (nextFloodfill->GetIdentHash ());
  712. request->requestTimeoutTimer.cancel ();
  713. uint8_t replyKey[32], replyTag[32];
  714. RAND_bytes (replyKey, 32); // random session key
  715. RAND_bytes (replyTag, 32); // random session tag
  716. AddSessionKey (replyKey, replyTag);
  717. auto msg = WrapMessage (nextFloodfill,
  718. CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
  719. request->replyTunnel, replyKey, replyTag));
  720. request->outboundTunnel->SendTunnelDataMsg (
  721. {
  722. i2p::tunnel::TunnelMessageBlock
  723. {
  724. i2p::tunnel::eDeliveryTypeRouter,
  725. nextFloodfill->GetIdentHash (), 0, msg
  726. }
  727. });
  728. request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT));
  729. request->requestTimeoutTimer.async_wait (std::bind (&LeaseSetDestination::HandleRequestTimoutTimer,
  730. shared_from_this (), std::placeholders::_1, dest));
  731. }
  732. else
  733. return false;
  734. return true;
  735. }
  736. void LeaseSetDestination::HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest)
  737. {
  738. if (ecode != boost::asio::error::operation_aborted)
  739. {
  740. auto it = m_LeaseSetRequests.find (dest);
  741. if (it != m_LeaseSetRequests.end ())
  742. {
  743. bool done = false;
  744. uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
  745. if (ts < it->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT)
  746. {
  747. auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, it->second->excluded);
  748. if (floodfill)
  749. {
  750. // reset tunnels, because one them might fail
  751. it->second->outboundTunnel = nullptr;
  752. it->second->replyTunnel = nullptr;
  753. done = !SendLeaseSetRequest (dest, floodfill, it->second);
  754. }
  755. else
  756. done = true;
  757. }
  758. else
  759. {
  760. LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
  761. done = true;
  762. }
  763. if (done)
  764. {
  765. auto requestComplete = it->second;
  766. m_LeaseSetRequests.erase (it);
  767. if (requestComplete) requestComplete->Complete (nullptr);
  768. }
  769. }
  770. }
  771. }
  772. void LeaseSetDestination::HandleCleanupTimer (const boost::system::error_code& ecode)
  773. {
  774. if (ecode != boost::asio::error::operation_aborted)
  775. {
  776. CleanupExpiredTags ();
  777. CleanupRemoteLeaseSets ();
  778. CleanupDestination ();
  779. m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT));
  780. m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer,
  781. shared_from_this (), std::placeholders::_1));
  782. }
  783. }
  784. void LeaseSetDestination::CleanupRemoteLeaseSets ()
  785. {
  786. auto ts = i2p::util::GetMillisecondsSinceEpoch ();
  787. std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
  788. for (auto it = m_RemoteLeaseSets.begin (); it != m_RemoteLeaseSets.end ();)
  789. {
  790. if (it->second->IsEmpty () || ts > it->second->GetExpirationTime ()) // leaseset expired
  791. {
  792. LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired");
  793. it = m_RemoteLeaseSets.erase (it);
  794. }
  795. else
  796. ++it;
  797. }
  798. }
  799. ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params):
  800. LeaseSetDestination (isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
  801. m_DatagramDestination (nullptr), m_RefCounter (0),
  802. m_ReadyChecker(GetService()), m_AuthType (i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE)
  803. {
  804. if (keys.IsOfflineSignature () && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
  805. SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // offline keys can be published with LS2 only
  806. m_EncryptionKeyType = GetIdentity ()->GetCryptoKeyType ();
  807. // extract encryption type params for LS2
  808. if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 && params)
  809. {
  810. auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
  811. if (it != params->end ())
  812. m_EncryptionKeyType = std::stoi(it->second);
  813. }
  814. if (isPublic && m_EncryptionKeyType == GetIdentity ()->GetCryptoKeyType ()) // TODO: presist key type
  815. PersistTemporaryKeys ();
  816. else
  817. i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey);
  818. m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_EncryptionKeyType, m_EncryptionPrivateKey);
  819. if (isPublic)
  820. LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
  821. try
  822. {
  823. if (params)
  824. {
  825. // extract streaming params
  826. auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY);
  827. if (it != params->end ())
  828. m_StreamingAckDelay = std::stoi(it->second);
  829. if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
  830. {
  831. // authentication for encrypted LeaseSet
  832. it = params->find (I2CP_PARAM_LEASESET_AUTH_TYPE);
  833. m_AuthType = std::stoi (it->second);
  834. if (m_AuthType > 0)
  835. {
  836. m_AuthKeys = std::make_shared<std::vector<i2p::data::AuthPublicKey> >();
  837. if (m_AuthType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_DH)
  838. ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_DH, params);
  839. else if (m_AuthType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
  840. ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params);
  841. else
  842. {
  843. LogPrint (eLogError, "Destination: Unexpected auth type ", m_AuthType);
  844. m_AuthType = 0;
  845. }
  846. if (m_AuthKeys->size ())
  847. LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read");
  848. else
  849. {
  850. LogPrint (eLogError, "Destination: No auth keys read for auth type ", m_AuthType);
  851. m_AuthKeys = nullptr;
  852. }
  853. }
  854. }
  855. }
  856. }
  857. catch (std::exception & ex)
  858. {
  859. LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what());
  860. }
  861. }
  862. ClientDestination::~ClientDestination ()
  863. {
  864. }
  865. bool ClientDestination::Start ()
  866. {
  867. if (LeaseSetDestination::Start ())
  868. {
  869. m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis ()); // TODO:
  870. m_StreamingDestination->Start ();
  871. for (auto& it: m_StreamingDestinationsByPorts)
  872. it.second->Start ();
  873. return true;
  874. }
  875. else
  876. return false;
  877. }
  878. bool ClientDestination::Stop ()
  879. {
  880. if (LeaseSetDestination::Stop ())
  881. {
  882. m_ReadyChecker.cancel();
  883. m_StreamingDestination->Stop ();
  884. //m_StreamingDestination->SetOwner (nullptr);
  885. m_StreamingDestination = nullptr;
  886. for (auto& it: m_StreamingDestinationsByPorts)
  887. {
  888. it.second->Stop ();
  889. //it.second->SetOwner (nullptr);
  890. }
  891. m_StreamingDestinationsByPorts.clear ();
  892. if (m_DatagramDestination)
  893. {
  894. delete m_DatagramDestination;
  895. m_DatagramDestination = nullptr;
  896. }
  897. return true;
  898. }
  899. else
  900. return false;
  901. }
  902. #ifdef I2LUA
  903. void ClientDestination::Ready(ReadyPromise & p)
  904. {
  905. ScheduleCheckForReady(&p);
  906. }
  907. void ClientDestination::ScheduleCheckForReady(ReadyPromise * p)
  908. {
  909. // tick every 100ms
  910. m_ReadyChecker.expires_from_now(boost::posix_time::milliseconds(100));
  911. m_ReadyChecker.async_wait([&, p] (const boost::system::error_code & ecode) {
  912. HandleCheckForReady(ecode, p);
  913. });
  914. }
  915. void ClientDestination::HandleCheckForReady(const boost::system::error_code & ecode, ReadyPromise * p)
  916. {
  917. if(ecode) // error happened
  918. p->set_value(nullptr);
  919. else if(IsReady()) // we are ready
  920. p->set_value(std::shared_ptr<ClientDestination>(this));
  921. else // we are not ready
  922. ScheduleCheckForReady(p);
  923. }
  924. #endif
  925. void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
  926. {
  927. uint32_t length = bufbe32toh (buf);
  928. if(length > len - 4)
  929. {
  930. LogPrint(eLogError, "Destination: Data message length ", length, " exceeds buffer length ", len);
  931. return;
  932. }
  933. buf += 4;
  934. // we assume I2CP payload
  935. uint16_t fromPort = bufbe16toh (buf + 4), // source
  936. toPort = bufbe16toh (buf + 6); // destination
  937. switch (buf[9])
  938. {
  939. case PROTOCOL_TYPE_STREAMING:
  940. {
  941. // streaming protocol
  942. auto dest = GetStreamingDestination (toPort);
  943. if (dest)
  944. dest->HandleDataMessagePayload (buf, length);
  945. else
  946. LogPrint (eLogError, "Destination: Missing streaming destination");
  947. }
  948. break;
  949. case PROTOCOL_TYPE_DATAGRAM:
  950. // datagram protocol
  951. if (m_DatagramDestination)
  952. m_DatagramDestination->HandleDataMessagePayload (fromPort, toPort, buf, length);
  953. else
  954. LogPrint (eLogError, "Destination: Missing datagram destination");
  955. break;
  956. case PROTOCOL_TYPE_RAW:
  957. // raw datagram
  958. if (m_DatagramDestination)
  959. m_DatagramDestination->HandleDataMessagePayload (fromPort, toPort, buf, length, true);
  960. else
  961. LogPrint (eLogError, "Destination: Missing raw datagram destination");
  962. break;
  963. default:
  964. LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]);
  965. }
  966. }
  967. void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port)
  968. {
  969. if (!streamRequestComplete)
  970. {
  971. LogPrint (eLogError, "Destination: request callback is not specified in CreateStream");
  972. return;
  973. }
  974. auto leaseSet = FindLeaseSet (dest);
  975. if (leaseSet)
  976. streamRequestComplete(CreateStream (leaseSet, port));
  977. else
  978. {
  979. auto s = GetSharedFromThis ();
  980. RequestDestination (dest,
  981. [s, streamRequestComplete, port](std::shared_ptr<const i2p::data::LeaseSet> ls)
  982. {
  983. if (ls)
  984. streamRequestComplete(s->CreateStream (ls, port));
  985. else
  986. streamRequestComplete (nullptr);
  987. });
  988. }
  989. }
  990. void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
  991. {
  992. if (!streamRequestComplete)
  993. {
  994. LogPrint (eLogError, "Destination: request callback is not specified in CreateStream");
  995. return;
  996. }
  997. auto s = GetSharedFromThis ();
  998. RequestDestinationWithEncryptedLeaseSet (dest,
  999. [s, streamRequestComplete, port](std::shared_ptr<i2p::data::LeaseSet> ls)
  1000. {
  1001. if (ls)
  1002. streamRequestComplete(s->CreateStream (ls, port));
  1003. else
  1004. streamRequestComplete (nullptr);
  1005. });
  1006. }
  1007. std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port)
  1008. {
  1009. if (m_StreamingDestination)
  1010. return m_StreamingDestination->CreateNewOutgoingStream (remote, port);
  1011. else
  1012. return nullptr;
  1013. }
  1014. std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::GetStreamingDestination (int port) const
  1015. {
  1016. if (port)
  1017. {
  1018. auto it = m_StreamingDestinationsByPorts.find (port);
  1019. if (it != m_StreamingDestinationsByPorts.end ())
  1020. return it->second;
  1021. }
  1022. // if port is zero or not found, use default destination
  1023. return m_StreamingDestination;
  1024. }
  1025. void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor)
  1026. {
  1027. if (m_StreamingDestination)
  1028. m_StreamingDestination->SetAcceptor (acceptor);
  1029. }
  1030. void ClientDestination::StopAcceptingStreams ()
  1031. {
  1032. if (m_StreamingDestination)
  1033. m_StreamingDestination->ResetAcceptor ();
  1034. }
  1035. bool ClientDestination::IsAcceptingStreams () const
  1036. {
  1037. if (m_StreamingDestination)
  1038. return m_StreamingDestination->IsAcceptorSet ();
  1039. return false;
  1040. }
  1041. void ClientDestination::AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor)
  1042. {
  1043. if (m_StreamingDestination)
  1044. m_StreamingDestination->AcceptOnce (acceptor);
  1045. }
  1046. std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::CreateStreamingDestination (int port, bool gzip)
  1047. {
  1048. auto dest = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis (), port, gzip);
  1049. if (port)
  1050. m_StreamingDestinationsByPorts[port] = dest;
  1051. else // update default
  1052. m_StreamingDestination = dest;
  1053. return dest;
  1054. }
  1055. i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination ()
  1056. {
  1057. if (m_DatagramDestination == nullptr)
  1058. m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis ());
  1059. return m_DatagramDestination;
  1060. }
  1061. std::vector<std::shared_ptr<const i2p::stream::Stream> > ClientDestination::GetAllStreams () const
  1062. {
  1063. std::vector<std::shared_ptr<const i2p::stream::Stream> > ret;
  1064. if (m_StreamingDestination)
  1065. {
  1066. for (auto& it: m_StreamingDestination->GetStreams ())
  1067. ret.push_back (it.second);
  1068. }
  1069. for (auto& it: m_StreamingDestinationsByPorts)
  1070. for (auto& it1: it.second->GetStreams ())
  1071. ret.push_back (it1.second);
  1072. return ret;
  1073. }
  1074. void ClientDestination::PersistTemporaryKeys ()
  1075. {
  1076. std::string ident = GetIdentHash().ToBase32();
  1077. std::string path = i2p::fs::DataDirPath("destinations", (ident + ".dat"));
  1078. std::ifstream f(path, std::ifstream::binary);
  1079. if (f) {
  1080. f.read ((char *)m_EncryptionPublicKey, 256);
  1081. f.read ((char *)m_EncryptionPrivateKey, 256);
  1082. return;
  1083. }
  1084. LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p");
  1085. memset (m_EncryptionPrivateKey, 0, 256);
  1086. memset (m_EncryptionPublicKey, 0, 256);
  1087. i2p::data::PrivateKeys::GenerateCryptoKeyPair (GetIdentity ()->GetCryptoKeyType (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
  1088. std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
  1089. if (f1) {
  1090. f1.write ((char *)m_EncryptionPublicKey, 256);
  1091. f1.write ((char *)m_EncryptionPrivateKey, 256);
  1092. return;
  1093. }
  1094. LogPrint(eLogError, "Destinations: Can't save keys to ", path);
  1095. }
  1096. void ClientDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
  1097. {
  1098. std::shared_ptr<i2p::data::LocalLeaseSet> leaseSet;
  1099. if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
  1100. {
  1101. leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), m_EncryptionPublicKey, tunnels);
  1102. // sign
  1103. Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
  1104. }
  1105. else
  1106. {
  1107. // standard LS2 (type 3) first
  1108. auto keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256;
  1109. auto ls2 = std::make_shared<i2p::data::LocalLeaseSet2> (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2,
  1110. m_Keys, m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels, IsPublic ());
  1111. if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) // encrypt if type 5
  1112. ls2 = std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (ls2, m_Keys, m_AuthType, m_AuthKeys);
  1113. leaseSet = ls2;
  1114. }
  1115. SetLeaseSet (leaseSet);
  1116. }
  1117. void ClientDestination::CleanupDestination ()
  1118. {
  1119. if (m_DatagramDestination) m_DatagramDestination->CleanUp ();
  1120. }
  1121. bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
  1122. {
  1123. if (m_Decryptor)
  1124. return m_Decryptor->Decrypt (encrypted, data, ctx, true);
  1125. else
  1126. LogPrint (eLogError, "Destinations: decryptor is not set");
  1127. return false;
  1128. }
  1129. void ClientDestination::ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params)
  1130. {
  1131. for (auto it: *params)
  1132. if (it.first.length () >= group.length () && !it.first.compare (0, group.length (), group))
  1133. {
  1134. auto pos = it.second.find (':');
  1135. if (pos != std::string::npos)
  1136. {
  1137. i2p::data::AuthPublicKey pubKey;
  1138. if (pubKey.FromBase64 (it.second.substr (pos+1)))
  1139. m_AuthKeys->push_back (pubKey);
  1140. else
  1141. LogPrint (eLogError, "Destination: Unexpected auth key ", it.second.substr (pos+1));
  1142. }
  1143. }
  1144. }
  1145. }
  1146. }