gnunet-service-transport_neighbours.c 124 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file transport/gnunet-service-transport_neighbours.c
  19. * @brief neighbour management
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet_ats_service.h"
  24. #include "gnunet-service-transport_ats.h"
  25. #include "gnunet-service-transport_blacklist.h"
  26. #include "gnunet-service-transport_clients.h"
  27. #include "gnunet-service-transport_neighbours.h"
  28. #include "gnunet-service-transport_manipulation.h"
  29. #include "gnunet-service-transport_plugins.h"
  30. #include "gnunet-service-transport_validation.h"
  31. #include "gnunet-service-transport.h"
  32. #include "gnunet_peerinfo_service.h"
  33. #include "gnunet_constants.h"
  34. #include "transport.h"
  35. /**
  36. * Size of the neighbour hash map.
  37. */
  38. #define NEIGHBOUR_TABLE_SIZE 256
  39. /**
  40. * Time we give plugin to transmit DISCONNECT message before the
  41. * neighbour entry self-destructs.
  42. */
  43. #define DISCONNECT_SENT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500)
  44. /**
  45. * How often must a peer violate bandwidth quotas before we start
  46. * to simply drop its messages?
  47. */
  48. #define QUOTA_VIOLATION_DROP_THRESHOLD 10
  49. /**
  50. * How long are we willing to wait for a response from ATS before timing out?
  51. */
  52. #define ATS_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
  53. /**
  54. * How long are we willing to wait for an ACK from the other peer before
  55. * giving up on our connect operation?
  56. */
  57. #define SETUP_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
  58. /**
  59. * How long are we willing to wait for a successful reconnect if
  60. * an existing connection went down? Much shorter than the
  61. * usual SETUP_CONNECTION_TIMEOUT as we do not inform the
  62. * higher layers about the disconnect during this period.
  63. */
  64. #define FAST_RECONNECT_TIMEOUT GNUNET_TIME_UNIT_SECONDS
  65. /**
  66. * Interval to send utilization data
  67. */
  68. #define UTIL_TRANSMISSION_INTERVAL GNUNET_TIME_UNIT_SECONDS
  69. /**
  70. * State describing which kind a reply this neighbour should send
  71. */
  72. enum GST_ACK_State
  73. {
  74. /**
  75. * We did not receive a SYN message for this neighbour
  76. */
  77. ACK_UNDEFINED = 0,
  78. /**
  79. * The neighbour received a SYN message and has to send a SYN_ACK
  80. * as reply
  81. */
  82. ACK_SEND_SYN_ACK = 1,
  83. /**
  84. * The neighbour sent a SYN_ACK message and has to send a ACK
  85. * as reply
  86. */
  87. ACK_SEND_ACK = 2
  88. };
  89. GNUNET_NETWORK_STRUCT_BEGIN
  90. /**
  91. * Message a peer sends to another to indicate that it intends to
  92. * setup a connection/session for data exchange. A 'SESSION_SYN'
  93. * should be answered with a 'SESSION_SYN_ACK' with the same body
  94. * to confirm. A 'SESSION_SYN_ACK' should then be followed with
  95. * a 'ACK'. Once the 'ACK' is received, both peers
  96. * should be connected.
  97. */
  98. struct TransportSynMessage
  99. {
  100. /**
  101. * Header of type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN
  102. * or #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK
  103. */
  104. struct GNUNET_MessageHeader header;
  105. /**
  106. * Always zero.
  107. */
  108. uint32_t reserved GNUNET_PACKED;
  109. /**
  110. * Absolute time at the sender. Only the most recent connect
  111. * message implies which session is preferred by the sender.
  112. */
  113. struct GNUNET_TIME_AbsoluteNBO timestamp;
  114. };
  115. /**
  116. * Message a peer sends to another when connected to indicate that a
  117. * session is in use and the peer is still alive or to respond to a keep alive.
  118. * A peer sends a message with type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE
  119. * to request a message with #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE.
  120. * When the keep alive response with type is received, transport service
  121. * will call the respective plugin to update the session timeout
  122. */
  123. struct SessionKeepAliveMessage
  124. {
  125. /**
  126. * Header of type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE or
  127. * #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE.
  128. */
  129. struct GNUNET_MessageHeader header;
  130. /**
  131. * A nonce to identify the session the keep alive is used for
  132. */
  133. uint32_t nonce GNUNET_PACKED;
  134. };
  135. /**
  136. * Message we send to the other peer to notify him that we intentionally
  137. * are disconnecting (to reduce timeouts). This is just a friendly
  138. * notification, peers must not rely on always receiving disconnect
  139. * messages.
  140. */
  141. struct SessionDisconnectMessage
  142. {
  143. /**
  144. * Header of type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT
  145. */
  146. struct GNUNET_MessageHeader header;
  147. /**
  148. * Always zero.
  149. */
  150. uint32_t reserved GNUNET_PACKED;
  151. /**
  152. * Purpose of the signature. Extends over the timestamp.
  153. * Purpose should be #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DISCONNECT.
  154. */
  155. struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
  156. /**
  157. * Absolute time at the sender. Only the most recent connect
  158. * message implies which session is preferred by the sender.
  159. */
  160. struct GNUNET_TIME_AbsoluteNBO timestamp;
  161. /**
  162. * Public key of the sender.
  163. */
  164. struct GNUNET_CRYPTO_EddsaPublicKey public_key;
  165. /**
  166. * Signature of the peer that sends us the disconnect. Only
  167. * valid if the timestamp is AFTER the timestamp from the
  168. * corresponding 'SYN' message.
  169. */
  170. struct GNUNET_CRYPTO_EddsaSignature signature;
  171. };
  172. GNUNET_NETWORK_STRUCT_END
  173. /**
  174. * For each neighbour we keep a list of messages
  175. * that we still want to transmit to the neighbour.
  176. */
  177. struct MessageQueue
  178. {
  179. /**
  180. * This is a doubly linked list.
  181. */
  182. struct MessageQueue *next;
  183. /**
  184. * This is a doubly linked list.
  185. */
  186. struct MessageQueue *prev;
  187. /**
  188. * Function to call once we're done.
  189. */
  190. GST_NeighbourSendContinuation cont;
  191. /**
  192. * Closure for @e cont
  193. */
  194. void *cont_cls;
  195. /**
  196. * The message(s) we want to transmit, GNUNET_MessageHeader(s)
  197. * stuck together in memory. Allocated at the end of this struct.
  198. */
  199. const char *message_buf;
  200. /**
  201. * Size of the message buf
  202. */
  203. size_t message_buf_size;
  204. /**
  205. * At what time should we fail?
  206. */
  207. struct GNUNET_TIME_Absolute timeout;
  208. };
  209. /**
  210. * A possible address we could use to communicate with a neighbour.
  211. */
  212. struct NeighbourAddress
  213. {
  214. /**
  215. * Active session for this address.
  216. */
  217. struct Session *session;
  218. /**
  219. * Network-level address information.
  220. */
  221. struct GNUNET_HELLO_Address *address;
  222. /**
  223. * Timestamp of the 'SESSION_CONNECT' message we sent to the other
  224. * peer for this address. Use to check that the ACK is in response
  225. * to our most recent 'SYN'.
  226. */
  227. struct GNUNET_TIME_Absolute connect_timestamp;
  228. /**
  229. * Inbound bandwidth from ATS for this address.
  230. */
  231. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
  232. /**
  233. * Outbound bandwidth from ATS for this address.
  234. */
  235. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
  236. /**
  237. * Did we tell ATS that this is our 'active' address?
  238. */
  239. int ats_active;
  240. /**
  241. * The current nonce sent in the last keep alive messages
  242. */
  243. uint32_t keep_alive_nonce;
  244. };
  245. /**
  246. * Entry in neighbours.
  247. */
  248. struct NeighbourMapEntry
  249. {
  250. /**
  251. * Head of list of messages we would like to send to this peer;
  252. * must contain at most one message per client.
  253. */
  254. struct MessageQueue *messages_head;
  255. /**
  256. * Tail of list of messages we would like to send to this peer; must
  257. * contain at most one message per client.
  258. */
  259. struct MessageQueue *messages_tail;
  260. /**
  261. * Are we currently trying to send a message? If so, which one?
  262. */
  263. struct MessageQueue *is_active;
  264. /**
  265. * Primary address we currently use to communicate with the neighbour.
  266. */
  267. struct NeighbourAddress primary_address;
  268. /**
  269. * Alternative address currently under consideration for communicating
  270. * with the neighbour.
  271. */
  272. struct NeighbourAddress alternative_address;
  273. /**
  274. * Identity of this neighbour.
  275. */
  276. struct GNUNET_PeerIdentity id;
  277. /**
  278. * Main task that drives this peer (timeouts, keepalives, etc.).
  279. * Always runs the 'master_task'.
  280. */
  281. struct GNUNET_SCHEDULER_Task *task;
  282. /**
  283. * Task to disconnect neighbour after we received a DISCONNECT message
  284. */
  285. struct GNUNET_SCHEDULER_Task *delayed_disconnect_task;
  286. /**
  287. * At what time should we sent the next keep-alive message?
  288. */
  289. struct GNUNET_TIME_Absolute keep_alive_time;
  290. /**
  291. * At what time did we sent the last keep-alive message? Used
  292. * to calculate round-trip time ("latency").
  293. */
  294. struct GNUNET_TIME_Absolute last_keep_alive_time;
  295. /**
  296. * Timestamp we should include in our next SYN_ACK message.
  297. * (only valid if 'send_connect_ack' is #GNUNET_YES). Used to build
  298. * our SYN_ACK message.
  299. */
  300. struct GNUNET_TIME_Absolute connect_ack_timestamp;
  301. /**
  302. * ATS address suggest handle
  303. */
  304. struct GNUNET_ATS_ConnectivitySuggestHandle *suggest_handle;
  305. /**
  306. * Time where we should cut the connection (timeout) if we don't
  307. * make progress in the state machine (or get a KEEPALIVE_RESPONSE
  308. * if we are in #S_CONNECTED).
  309. */
  310. struct GNUNET_TIME_Absolute timeout;
  311. /**
  312. * Tracker for inbound bandwidth.
  313. */
  314. struct GNUNET_BANDWIDTH_Tracker in_tracker;
  315. /**
  316. * How often has the other peer (recently) violated the inbound
  317. * traffic limit? Incremented by 10 per violation, decremented by 1
  318. * per non-violation (for each time interval).
  319. */
  320. unsigned int quota_violation_count;
  321. /**
  322. * The current state of the peer.
  323. */
  324. enum GNUNET_TRANSPORT_PeerState state;
  325. /**
  326. * Did we sent an KEEP_ALIVE message and are we expecting a response?
  327. */
  328. int expect_latency_response;
  329. /**
  330. * When a peer wants to connect we have to reply to the 1st SYN message
  331. * with a SYN_ACK message. But sometime we cannot send this message
  332. * immediately since we do not have an address and then we have to remember
  333. * to send this message as soon as we have an address.
  334. *
  335. * Flag to set if we still need to send a SYN_ACK message to the other peer
  336. * (once we have an address to use and the peer has been allowed by our
  337. * blacklist). Initially set to #ACK_UNDEFINED. Set to #ACK_SEND_SYN_ACK
  338. * if we need to send a SYN_ACK. Set to #ACK_SEND_ACK if we did
  339. * send a SYN_ACK and should go to #S_CONNECTED upon receiving a
  340. * 'ACK' (regardless of what our own state machine might say).
  341. */
  342. enum GST_ACK_State ack_state;
  343. /**
  344. * Tracking utilization of outbound bandwidth
  345. */
  346. uint32_t util_total_bytes_sent;
  347. /**
  348. * Tracking utilization of inbound bandwidth
  349. */
  350. uint32_t util_total_bytes_recv;
  351. /**
  352. * Date of last utilization transmission
  353. */
  354. struct GNUNET_TIME_Absolute last_util_transmission;
  355. };
  356. /**
  357. * Context for blacklist checks and the #try_connect_bl_check_cont()
  358. * function. Stores information about ongoing blacklist checks.
  359. */
  360. struct BlackListCheckContext
  361. {
  362. /**
  363. * We keep blacklist checks in a DLL.
  364. */
  365. struct BlackListCheckContext *next;
  366. /**
  367. * We keep blacklist checks in a DLL.
  368. */
  369. struct BlackListCheckContext *prev;
  370. /**
  371. * Address that is being checked.
  372. */
  373. struct NeighbourAddress na;
  374. /**
  375. * Handle to the ongoing blacklist check.
  376. */
  377. struct GST_BlacklistCheck *bc;
  378. };
  379. /**
  380. * Hash map from peer identities to the respective `struct NeighbourMapEntry`.
  381. */
  382. static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
  383. /**
  384. * We keep blacklist checks in a DLL so that we can find
  385. * the 'sessions' in their 'struct NeighbourAddress' if
  386. * a session goes down.
  387. */
  388. static struct BlackListCheckContext *bc_head;
  389. /**
  390. * We keep blacklist checks in a DLL.
  391. */
  392. static struct BlackListCheckContext *bc_tail;
  393. /**
  394. * List of pending blacklist checks: head
  395. */
  396. static struct BlacklistCheckSwitchContext *pending_bc_head;
  397. /**
  398. * List of pending blacklist checks: tail
  399. */
  400. static struct BlacklistCheckSwitchContext *pending_bc_tail;
  401. /**
  402. * counter for connected neighbours
  403. */
  404. static unsigned int neighbours_connected;
  405. /**
  406. * Number of bytes we have currently queued for transmission.
  407. */
  408. static unsigned long long bytes_in_send_queue;
  409. /**
  410. * Task transmitting utilization data
  411. */
  412. static struct GNUNET_SCHEDULER_Task *util_transmission_tk;
  413. /**
  414. * Convert the given ACK state to a string.
  415. *
  416. * @param s state
  417. * @return corresponding human-readable string
  418. */
  419. static char *
  420. print_ack_state (enum GST_ACK_State s)
  421. {
  422. switch (s) {
  423. case ACK_UNDEFINED:
  424. return "UNDEFINED";
  425. case ACK_SEND_SYN_ACK:
  426. return "SEND_SYN_ACK";
  427. case ACK_SEND_ACK:
  428. return "SEND_ACK";
  429. default:
  430. GNUNET_break (0);
  431. return "N/A";
  432. }
  433. }
  434. /**
  435. * Notify our clients that another peer connected to us.
  436. *
  437. * @param peer the peer that connected
  438. * @param bandwidth_in inbound bandwidth in NBO
  439. * @param bandwidth_out outbound bandwidth in NBO
  440. */
  441. static void
  442. neighbours_connect_notification (const struct GNUNET_PeerIdentity *peer,
  443. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
  444. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
  445. {
  446. size_t len = sizeof(struct ConnectInfoMessage);
  447. char buf[len] GNUNET_ALIGN;
  448. struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *) buf;
  449. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  450. "We are now connected to peer `%s'\n",
  451. GNUNET_i2s (peer));
  452. connect_msg->header.size = htons (sizeof(buf));
  453. connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
  454. connect_msg->id = *peer;
  455. connect_msg->quota_in = bandwidth_in;
  456. connect_msg->quota_out = bandwidth_out;
  457. GST_clients_broadcast (&connect_msg->header, GNUNET_NO);
  458. }
  459. /**
  460. * Notify our clients (and manipulation) that a peer disconnected from
  461. * us.
  462. *
  463. * @param peer the peer that disconnected
  464. */
  465. static void
  466. neighbours_disconnect_notification (const struct GNUNET_PeerIdentity *peer)
  467. {
  468. struct DisconnectInfoMessage disconnect_msg;
  469. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  470. "Peer `%s' disconnected\n",
  471. GNUNET_i2s (peer));
  472. GST_manipulation_peer_disconnect (peer);
  473. disconnect_msg.header.size = htons (sizeof(struct DisconnectInfoMessage));
  474. disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
  475. disconnect_msg.reserved = htonl (0);
  476. disconnect_msg.peer = *peer;
  477. GST_clients_broadcast (&disconnect_msg.header,
  478. GNUNET_NO);
  479. }
  480. /**
  481. * Notify transport clients that a neighbour peer changed its active
  482. * address.
  483. *
  484. * @param peer identity of the peer
  485. * @param address address possibly NULL if peer is not connected
  486. * @param state current state this peer is in
  487. * @param state_timeout timeout for the current state of the peer
  488. * @param bandwidth_in bandwidth assigned inbound, 0 on disconnect
  489. * @param bandwidth_out bandwidth assigned outbound, 0 on disconnect
  490. */
  491. static void
  492. neighbours_changed_notification (const struct GNUNET_PeerIdentity *peer,
  493. const struct GNUNET_HELLO_Address *address,
  494. enum GNUNET_TRANSPORT_PeerState state,
  495. struct GNUNET_TIME_Absolute state_timeout,
  496. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
  497. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
  498. {
  499. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  500. "Notifying about change for peer `%s' with address `%s' in state `%s' timing out at %s\n",
  501. GNUNET_i2s (peer),
  502. GST_plugins_a2s (address),
  503. GNUNET_TRANSPORT_ps2s (state),
  504. GNUNET_STRINGS_absolute_time_to_string (state_timeout));
  505. /* FIXME: include bandwidth in notification! */
  506. GST_clients_broadcast_peer_notification (peer,
  507. address,
  508. state,
  509. state_timeout);
  510. }
  511. /**
  512. * Lookup a neighbour entry in the neighbours hash map.
  513. *
  514. * @param pid identity of the peer to look up
  515. * @return the entry, NULL if there is no existing record
  516. */
  517. static struct NeighbourMapEntry *
  518. lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
  519. {
  520. if (NULL == neighbours)
  521. return NULL;
  522. return GNUNET_CONTAINER_multipeermap_get (neighbours, pid);
  523. }
  524. /**
  525. * Test if we're connected to the given peer.
  526. *
  527. * @param n neighbour entry of peer to test
  528. * @return #GNUNET_YES if we are connected, #GNUNET_NO if not
  529. */
  530. static int
  531. test_connected (struct NeighbourMapEntry *n)
  532. {
  533. if (NULL == n)
  534. return GNUNET_NO;
  535. return GNUNET_TRANSPORT_is_connected (n->state);
  536. }
  537. /**
  538. * Send information about a new outbound quota to our clients.
  539. *
  540. * @param target affected peer
  541. * @param quota new quota
  542. */
  543. static void
  544. send_outbound_quota (const struct GNUNET_PeerIdentity *target,
  545. struct GNUNET_BANDWIDTH_Value32NBO quota)
  546. {
  547. struct QuotaSetMessage q_msg;
  548. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  549. "Sending outbound quota of %u Bps for peer `%s' to all clients\n",
  550. ntohl (quota.value__),
  551. GNUNET_i2s (target));
  552. q_msg.header.size = htons (sizeof (struct QuotaSetMessage));
  553. q_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA);
  554. q_msg.quota = quota;
  555. q_msg.peer = (*target);
  556. GST_clients_broadcast (&q_msg.header, GNUNET_NO);
  557. }
  558. /**
  559. * We don't need a given neighbour address any more.
  560. * Release its resources and give appropriate notifications
  561. * to ATS and other subsystems.
  562. *
  563. * @param na address we are done with; @a na itself must NOT be 'free'd, only the contents!
  564. */
  565. static void
  566. free_address (struct NeighbourAddress *na)
  567. {
  568. if (GNUNET_YES == na->ats_active)
  569. GST_validation_set_address_use (na->address,
  570. GNUNET_NO);
  571. if (NULL != na->address)
  572. {
  573. GST_ats_block_address (na->address,
  574. na->session);
  575. GNUNET_HELLO_address_free (na->address);
  576. na->address = NULL;
  577. }
  578. na->bandwidth_in = GNUNET_BANDWIDTH_value_init (0);
  579. na->bandwidth_out = GNUNET_BANDWIDTH_value_init (0);
  580. na->ats_active = GNUNET_NO;
  581. na->keep_alive_nonce = 0;
  582. na->session = NULL;
  583. }
  584. /**
  585. * Master task run for every neighbour. Performs all of the time-related
  586. * activities (keep alive, send next message, disconnect if idle, finish
  587. * clean up after disconnect).
  588. *
  589. * @param cls the `struct NeighbourMapEntry` for which we are running
  590. * @param tc scheduler context (unused)
  591. */
  592. static void
  593. master_task (void *cls,
  594. const struct GNUNET_SCHEDULER_TaskContext *tc);
  595. /**
  596. * Set net state and state timeout for this neighbour and notify monitoring
  597. *
  598. * @param n the respective neighbour
  599. * @param s the new state
  600. * @param timeout the new timeout
  601. */
  602. static void
  603. set_state_and_timeout (struct NeighbourMapEntry *n,
  604. enum GNUNET_TRANSPORT_PeerState s,
  605. struct GNUNET_TIME_Absolute timeout)
  606. {
  607. if (GNUNET_TRANSPORT_is_connected (s) &&
  608. ! GNUNET_TRANSPORT_is_connected (n->state) )
  609. {
  610. neighbours_connect_notification (&n->id,
  611. n->primary_address.bandwidth_in,
  612. n->primary_address.bandwidth_out);
  613. GNUNET_STATISTICS_set (GST_stats,
  614. gettext_noop ("# peers connected"),
  615. ++neighbours_connected,
  616. GNUNET_NO);
  617. }
  618. if (! GNUNET_TRANSPORT_is_connected (s) &&
  619. GNUNET_TRANSPORT_is_connected (n->state) )
  620. {
  621. GNUNET_STATISTICS_set (GST_stats,
  622. gettext_noop ("# peers connected"),
  623. --neighbours_connected,
  624. GNUNET_NO);
  625. neighbours_disconnect_notification (&n->id);
  626. }
  627. n->state = s;
  628. if ( (timeout.abs_value_us < n->timeout.abs_value_us) &&
  629. (NULL != n->task ) )
  630. {
  631. /* new timeout is earlier, reschedule master task */
  632. GNUNET_SCHEDULER_cancel (n->task);
  633. n->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (timeout),
  634. &master_task,
  635. n);
  636. }
  637. n->timeout = timeout;
  638. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  639. "Neighbour `%s' changed state to %s with timeout %s\n",
  640. GNUNET_i2s (&n->id),
  641. GNUNET_TRANSPORT_ps2s(s),
  642. GNUNET_STRINGS_absolute_time_to_string (timeout));
  643. neighbours_changed_notification (&n->id,
  644. n->primary_address.address,
  645. n->state,
  646. n->timeout,
  647. n->primary_address.bandwidth_in,
  648. n->primary_address.bandwidth_out);
  649. }
  650. /**
  651. * Initialize the alternative address of a neighbour
  652. *
  653. * @param n the neighbour
  654. * @param address address of the other peer, NULL if other peer
  655. * connected to us
  656. * @param session session to use (or NULL, in which case an
  657. * address must be setup)
  658. * @param bandwidth_in inbound quota to be used when connection is up
  659. * @param bandwidth_out outbound quota to be used when connection is up
  660. */
  661. static void
  662. set_alternative_address (struct NeighbourMapEntry *n,
  663. const struct GNUNET_HELLO_Address *address,
  664. struct Session *session,
  665. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
  666. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
  667. {
  668. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  669. if (NULL == (papi = GST_plugins_find (address->transport_name)))
  670. {
  671. GNUNET_break (0);
  672. return;
  673. }
  674. if (session == n->alternative_address.session)
  675. {
  676. n->alternative_address.bandwidth_in = bandwidth_in;
  677. n->alternative_address.bandwidth_out = bandwidth_out;
  678. return;
  679. }
  680. if (NULL != n->alternative_address.address)
  681. {
  682. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  683. "Replacing existing alternative address with another one\n");
  684. free_address (&n->alternative_address);
  685. }
  686. if (NULL == session)
  687. session = papi->get_session (papi->cls,
  688. address);
  689. if (NULL == session)
  690. {
  691. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  692. "Failed to obtain new session for peer `%s' and address '%s'\n",
  693. GNUNET_i2s (&address->peer),
  694. GST_plugins_a2s (address));
  695. GNUNET_STATISTICS_update (GST_stats,
  696. gettext_noop ("# session creation failed"),
  697. 1,
  698. GNUNET_NO);
  699. return;
  700. }
  701. GST_ats_new_session (address,
  702. session);
  703. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  704. "Neighbour `%s' configured alternative address %s\n",
  705. GNUNET_i2s (&n->id),
  706. GST_plugins_a2s(address));
  707. n->alternative_address.address = GNUNET_HELLO_address_copy (address);
  708. n->alternative_address.bandwidth_in = bandwidth_in;
  709. n->alternative_address.bandwidth_out = bandwidth_out;
  710. n->alternative_address.session = session;
  711. n->alternative_address.ats_active = GNUNET_NO;
  712. n->alternative_address.keep_alive_nonce = 0;
  713. }
  714. /**
  715. * Initialize the primary address of a neighbour
  716. *
  717. * @param n the neighbour
  718. * @param address address of the other peer, NULL if other peer
  719. * connected to us
  720. * @param session session to use (or NULL, in which case an
  721. * address must be setup)
  722. * @param bandwidth_in inbound quota to be used when connection is up
  723. * @param bandwidth_out outbound quota to be used when connection is up
  724. */
  725. static void
  726. set_primary_address (struct NeighbourMapEntry *n,
  727. const struct GNUNET_HELLO_Address *address,
  728. struct Session *session,
  729. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
  730. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
  731. {
  732. if (session == n->primary_address.session)
  733. {
  734. GST_validation_set_address_use (n->primary_address.address,
  735. GNUNET_YES);
  736. if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
  737. {
  738. n->primary_address.bandwidth_in = bandwidth_in;
  739. GST_neighbours_set_incoming_quota (&address->peer,
  740. bandwidth_in);
  741. }
  742. if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
  743. {
  744. n->primary_address.bandwidth_out = bandwidth_out;
  745. send_outbound_quota (&address->peer,
  746. bandwidth_out);
  747. }
  748. return;
  749. }
  750. if ( (NULL != n->primary_address.address) &&
  751. (0 == GNUNET_HELLO_address_cmp (address,
  752. n->primary_address.address)) )
  753. {
  754. GNUNET_break (0);
  755. return;
  756. }
  757. if (NULL == session)
  758. {
  759. GNUNET_break (0);
  760. GST_ats_block_address (address,
  761. session);
  762. return;
  763. }
  764. if (NULL != n->primary_address.address)
  765. {
  766. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  767. "Replacing existing primary address with another one\n");
  768. free_address (&n->primary_address);
  769. }
  770. n->primary_address.address = GNUNET_HELLO_address_copy (address);
  771. n->primary_address.bandwidth_in = bandwidth_in;
  772. n->primary_address.bandwidth_out = bandwidth_out;
  773. n->primary_address.session = session;
  774. n->primary_address.keep_alive_nonce = 0;
  775. /* subsystems about address use */
  776. GST_validation_set_address_use (n->primary_address.address,
  777. GNUNET_YES);
  778. GST_neighbours_set_incoming_quota (&address->peer,
  779. bandwidth_in);
  780. send_outbound_quota (&address->peer,
  781. bandwidth_out);
  782. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  783. "Neighbour `%s' switched to address `%s'\n",
  784. GNUNET_i2s (&n->id),
  785. GST_plugins_a2s(address));
  786. neighbours_changed_notification (&n->id,
  787. n->primary_address.address,
  788. n->state,
  789. n->timeout,
  790. n->primary_address.bandwidth_in,
  791. n->primary_address.bandwidth_out);
  792. }
  793. /**
  794. * Clear the primary address of a neighbour since this address is not
  795. * valid anymore and notify monitoring about it
  796. *
  797. * @param n the neighbour
  798. */
  799. static void
  800. unset_primary_address (struct NeighbourMapEntry *n)
  801. {
  802. /* Notify monitoring about change */
  803. if (NULL == n->primary_address.address)
  804. return;
  805. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  806. "Disabling primary address\n");
  807. neighbours_changed_notification (&n->id,
  808. n->primary_address.address,
  809. n->state,
  810. n->timeout,
  811. GNUNET_BANDWIDTH_value_init (0),
  812. GNUNET_BANDWIDTH_value_init (0));
  813. free_address (&n->primary_address);
  814. }
  815. /**
  816. * Free a neighbour map entry.
  817. *
  818. * @param n entry to free
  819. */
  820. static void
  821. free_neighbour (struct NeighbourMapEntry *n)
  822. {
  823. struct MessageQueue *mq;
  824. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  825. "Freeing neighbour state of peer `%s'\n",
  826. GNUNET_i2s (&n->id));
  827. n->is_active = NULL; /* always free'd by its own continuation! */
  828. /* fail messages currently in the queue */
  829. while (NULL != (mq = n->messages_head))
  830. {
  831. GNUNET_CONTAINER_DLL_remove (n->messages_head,
  832. n->messages_tail,
  833. mq);
  834. if (NULL != mq->cont)
  835. mq->cont (mq->cont_cls,
  836. GNUNET_SYSERR,
  837. mq->message_buf_size,
  838. 0);
  839. GNUNET_free (mq);
  840. }
  841. /* Mark peer as disconnected */
  842. set_state_and_timeout (n,
  843. GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED,
  844. GNUNET_TIME_UNIT_FOREVER_ABS);
  845. /* free addresses and mark as unused */
  846. unset_primary_address (n);
  847. if (NULL != n->alternative_address.address)
  848. {
  849. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  850. "Cleaning up alternative address\n");
  851. free_address (&n->alternative_address);
  852. }
  853. GNUNET_assert (GNUNET_YES ==
  854. GNUNET_CONTAINER_multipeermap_remove (neighbours,
  855. &n->id, n));
  856. /* Cancel address requests for this peer */
  857. if (NULL != n->suggest_handle)
  858. {
  859. GNUNET_ATS_connectivity_suggest_cancel (n->suggest_handle);
  860. n->suggest_handle = NULL;
  861. }
  862. /* Cancel the disconnect task */
  863. if (NULL != n->delayed_disconnect_task)
  864. {
  865. GNUNET_SCHEDULER_cancel (n->delayed_disconnect_task);
  866. n->delayed_disconnect_task = NULL;
  867. }
  868. /* Cancel the master task */
  869. if (NULL != n->task)
  870. {
  871. GNUNET_SCHEDULER_cancel (n->task);
  872. n->task = NULL;
  873. }
  874. /* free rest of memory */
  875. GNUNET_free (n);
  876. }
  877. /**
  878. * Transmit a message using the current session of the given
  879. * neighbour.
  880. *
  881. * @param n entry for the recipient
  882. * @param msgbuf buffer to transmit
  883. * @param msgbuf_size number of bytes in @a msgbuf buffer
  884. * @param priority transmission priority
  885. * @param timeout transmission timeout
  886. * @param use_keepalive_timeout #GNUNET_YES to use plugin-specific keep-alive
  887. * timeout (@a timeout is ignored in that case), #GNUNET_NO otherwise
  888. * @param cont continuation to call when finished (can be NULL)
  889. * @param cont_cls closure for @a cont
  890. * @return timeout (copy of @a timeout or a calculated one if
  891. * @a use_keepalive_timeout is #GNUNET_YES.
  892. */
  893. static struct GNUNET_TIME_Relative
  894. send_with_session (struct NeighbourMapEntry *n,
  895. const void *msgbuf,
  896. size_t msgbuf_size,
  897. uint32_t priority,
  898. struct GNUNET_TIME_Relative timeout,
  899. unsigned int use_keepalive_timeout,
  900. GNUNET_TRANSPORT_TransmitContinuation cont,
  901. void *cont_cls)
  902. {
  903. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  904. struct GNUNET_TIME_Relative result = GNUNET_TIME_UNIT_FOREVER_REL;
  905. GNUNET_assert (NULL != n->primary_address.session);
  906. if ( ((NULL == (papi = GST_plugins_find (n->primary_address.address->transport_name)) ||
  907. (-1 == papi->send (papi->cls,
  908. n->primary_address.session,
  909. msgbuf,
  910. msgbuf_size,
  911. priority,
  912. (result = (GNUNET_NO == use_keepalive_timeout) ? timeout :
  913. GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
  914. papi->query_keepalive_factor (papi->cls))),
  915. cont,
  916. cont_cls)))) &&
  917. (NULL != cont))
  918. cont (cont_cls,
  919. &n->id,
  920. GNUNET_SYSERR,
  921. msgbuf_size,
  922. 0);
  923. GST_neighbours_notify_data_sent (n->primary_address.address,
  924. n->primary_address.session,
  925. msgbuf_size);
  926. GNUNET_break (NULL != papi);
  927. return result;
  928. }
  929. /**
  930. * Function called when the 'DISCONNECT' message has been sent by the
  931. * plugin. Frees the neighbour --- if the entry still exists.
  932. *
  933. * @param cls NULL
  934. * @param target identity of the neighbour that was disconnected
  935. * @param result #GNUNET_OK if the disconnect got out successfully
  936. * @param payload bytes payload
  937. * @param physical bytes on wire
  938. */
  939. static void
  940. send_disconnect_cont (void *cls,
  941. const struct GNUNET_PeerIdentity *target,
  942. int result,
  943. size_t payload,
  944. size_t physical)
  945. {
  946. struct NeighbourMapEntry *n;
  947. n = lookup_neighbour (target);
  948. if (NULL == n)
  949. return; /* already gone */
  950. if (GNUNET_TRANSPORT_PS_DISCONNECT != n->state)
  951. return; /* have created a fresh entry since */
  952. if (NULL != n->task)
  953. GNUNET_SCHEDULER_cancel (n->task);
  954. n->task = GNUNET_SCHEDULER_add_now (&master_task, n);
  955. }
  956. /**
  957. * Transmit a DISCONNECT message to the other peer.
  958. *
  959. * @param n neighbour to send DISCONNECT message.
  960. */
  961. static void
  962. send_disconnect (struct NeighbourMapEntry *n)
  963. {
  964. struct SessionDisconnectMessage disconnect_msg;
  965. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  966. "Sending DISCONNECT message to peer `%4s'\n",
  967. GNUNET_i2s (&n->id));
  968. disconnect_msg.header.size = htons (sizeof (struct SessionDisconnectMessage));
  969. disconnect_msg.header.type =
  970. htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT);
  971. disconnect_msg.reserved = htonl (0);
  972. disconnect_msg.purpose.size =
  973. htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
  974. sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) +
  975. sizeof (struct GNUNET_TIME_AbsoluteNBO));
  976. disconnect_msg.purpose.purpose =
  977. htonl (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT);
  978. disconnect_msg.timestamp =
  979. GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
  980. disconnect_msg.public_key = GST_my_identity.public_key;
  981. GNUNET_assert (GNUNET_OK ==
  982. GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
  983. &disconnect_msg.purpose,
  984. &disconnect_msg.signature));
  985. (void) send_with_session (n,
  986. &disconnect_msg,
  987. sizeof (disconnect_msg),
  988. UINT32_MAX,
  989. GNUNET_TIME_UNIT_FOREVER_REL,
  990. GNUNET_NO,
  991. &send_disconnect_cont,
  992. NULL);
  993. GNUNET_STATISTICS_update (GST_stats,
  994. gettext_noop ("# DISCONNECT messages sent"),
  995. 1,
  996. GNUNET_NO);
  997. }
  998. /**
  999. * Disconnect from the given neighbour, clean up the record.
  1000. *
  1001. * @param n neighbour to disconnect from
  1002. */
  1003. static void
  1004. disconnect_neighbour (struct NeighbourMapEntry *n)
  1005. {
  1006. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1007. "Disconnecting from peer %s in state %s\n",
  1008. GNUNET_i2s (&n->id),
  1009. GNUNET_TRANSPORT_ps2s (n->state));
  1010. /* depending on state, notify neighbour and/or upper layers of this peer
  1011. about disconnect */
  1012. switch (n->state)
  1013. {
  1014. case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
  1015. case GNUNET_TRANSPORT_PS_INIT_ATS:
  1016. /* other peer is completely unaware of us, no need to send DISCONNECT */
  1017. free_neighbour (n);
  1018. return;
  1019. case GNUNET_TRANSPORT_PS_SYN_SENT:
  1020. send_disconnect (n);
  1021. set_state_and_timeout (n,
  1022. GNUNET_TRANSPORT_PS_DISCONNECT,
  1023. GNUNET_TIME_UNIT_FOREVER_ABS);
  1024. break;
  1025. case GNUNET_TRANSPORT_PS_SYN_RECV_ATS:
  1026. /* we never ACK'ed the other peer's request, no need to send DISCONNECT */
  1027. free_neighbour (n);
  1028. return;
  1029. case GNUNET_TRANSPORT_PS_SYN_RECV_ACK:
  1030. /* we DID ACK the other peer's request, must send DISCONNECT */
  1031. send_disconnect (n);
  1032. set_state_and_timeout (n,
  1033. GNUNET_TRANSPORT_PS_DISCONNECT,
  1034. GNUNET_TIME_UNIT_FOREVER_ABS);
  1035. break;
  1036. case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
  1037. case GNUNET_TRANSPORT_PS_CONNECTED:
  1038. case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
  1039. /* we are currently connected, need to send disconnect and do
  1040. internal notifications and update statistics */
  1041. send_disconnect (n);
  1042. set_state_and_timeout (n,
  1043. GNUNET_TRANSPORT_PS_DISCONNECT,
  1044. GNUNET_TIME_UNIT_FOREVER_ABS);
  1045. break;
  1046. case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
  1047. /* Disconnecting while waiting for an ATS address to reconnect,
  1048. * cannot send DISCONNECT */
  1049. free_neighbour (n);
  1050. return;
  1051. case GNUNET_TRANSPORT_PS_DISCONNECT:
  1052. /* already disconnected, ignore */
  1053. break;
  1054. case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
  1055. /* already cleaned up, how did we get here!? */
  1056. GNUNET_assert (0);
  1057. break;
  1058. default:
  1059. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1060. "Unhandled state `%s'\n",
  1061. GNUNET_TRANSPORT_ps2s (n->state));
  1062. GNUNET_break (0);
  1063. break;
  1064. }
  1065. /* schedule timeout to clean up */
  1066. if (NULL != n->task)
  1067. GNUNET_SCHEDULER_cancel (n->task);
  1068. n->task = GNUNET_SCHEDULER_add_delayed (DISCONNECT_SENT_TIMEOUT,
  1069. &master_task,
  1070. n);
  1071. }
  1072. /**
  1073. * We're done with our transmission attempt, continue processing.
  1074. *
  1075. * @param cls the `struct MessageQueue` of the message
  1076. * @param receiver intended receiver
  1077. * @param success whether it worked or not
  1078. * @param size_payload bytes payload sent
  1079. * @param physical bytes sent on wire
  1080. */
  1081. static void
  1082. transmit_send_continuation (void *cls,
  1083. const struct GNUNET_PeerIdentity *receiver,
  1084. int success, size_t size_payload, size_t physical)
  1085. {
  1086. struct MessageQueue *mq = cls;
  1087. struct NeighbourMapEntry *n;
  1088. if (NULL == (n = lookup_neighbour (receiver)))
  1089. {
  1090. GNUNET_free (mq);
  1091. return; /* disconnect or other error while transmitting, can happen */
  1092. }
  1093. if (n->is_active == mq)
  1094. {
  1095. /* this is still "our" neighbour, remove us from its queue
  1096. and allow it to send the next message now */
  1097. n->is_active = NULL;
  1098. if (NULL != n->task)
  1099. GNUNET_SCHEDULER_cancel (n->task);
  1100. n->task = GNUNET_SCHEDULER_add_now (&master_task, n);
  1101. }
  1102. if (bytes_in_send_queue < mq->message_buf_size)
  1103. {
  1104. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1105. "Bytes_in_send_queue `%u', Message_size %u, result: %s, payload %u, on wire %u\n",
  1106. bytes_in_send_queue,
  1107. mq->message_buf_size,
  1108. (GNUNET_OK == success) ? "OK" : "FAIL",
  1109. size_payload,
  1110. physical);
  1111. GNUNET_break (0);
  1112. }
  1113. GNUNET_break (size_payload == mq->message_buf_size);
  1114. bytes_in_send_queue -= mq->message_buf_size;
  1115. GNUNET_STATISTICS_set (GST_stats,
  1116. gettext_noop
  1117. ("# bytes in message queue for other peers"),
  1118. bytes_in_send_queue, GNUNET_NO);
  1119. if (GNUNET_OK == success)
  1120. GNUNET_STATISTICS_update (GST_stats,
  1121. gettext_noop
  1122. ("# messages transmitted to other peers"),
  1123. 1, GNUNET_NO);
  1124. else
  1125. GNUNET_STATISTICS_update (GST_stats,
  1126. gettext_noop
  1127. ("# transmission failures for messages to other peers"),
  1128. 1, GNUNET_NO);
  1129. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1130. "Sending message to `%s' of type %u with %u bytes was a %s\n",
  1131. GNUNET_i2s (receiver),
  1132. ntohs (((struct GNUNET_MessageHeader *) mq->message_buf)->type),
  1133. mq->message_buf_size,
  1134. (success == GNUNET_OK) ? "success" : "FAILURE");
  1135. if (NULL != mq->cont)
  1136. mq->cont (mq->cont_cls, success, size_payload, physical);
  1137. GNUNET_free (mq);
  1138. }
  1139. /**
  1140. * Check the message list for the given neighbour and if we can
  1141. * send a message, do so. This function should only be called
  1142. * if the connection is at least generally ready for transmission.
  1143. * While we will only send one message at a time, no bandwidth
  1144. * quota management is performed here. If a message was given to
  1145. * the plugin, the continuation will automatically re-schedule
  1146. * the 'master' task once the next message might be transmitted.
  1147. *
  1148. * @param n target peer for which to transmit
  1149. */
  1150. static void
  1151. try_transmission_to_peer (struct NeighbourMapEntry *n)
  1152. {
  1153. struct MessageQueue *mq;
  1154. struct GNUNET_TIME_Relative timeout;
  1155. if (NULL == n->primary_address.address)
  1156. {
  1157. /* no address, why are we here? */
  1158. GNUNET_break (0);
  1159. return;
  1160. }
  1161. if ((0 == n->primary_address.address->address_length) &&
  1162. (NULL == n->primary_address.session))
  1163. {
  1164. /* no address, why are we here? */
  1165. GNUNET_break (0);
  1166. return;
  1167. }
  1168. if (NULL != n->is_active)
  1169. {
  1170. /* transmission already pending */
  1171. return;
  1172. }
  1173. /* timeout messages from the queue that are past their due date */
  1174. while (NULL != (mq = n->messages_head))
  1175. {
  1176. timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
  1177. if (timeout.rel_value_us > 0)
  1178. break;
  1179. GNUNET_STATISTICS_update (GST_stats,
  1180. gettext_noop
  1181. ("# messages timed out while in transport queue"),
  1182. 1, GNUNET_NO);
  1183. GNUNET_CONTAINER_DLL_remove (n->messages_head,
  1184. n->messages_tail,
  1185. mq);
  1186. n->is_active = mq;
  1187. transmit_send_continuation (mq,
  1188. &n->id,
  1189. GNUNET_SYSERR,
  1190. mq->message_buf_size,
  1191. 0); /* timeout */
  1192. }
  1193. if (NULL == mq)
  1194. return; /* no more messages */
  1195. GNUNET_CONTAINER_DLL_remove (n->messages_head,
  1196. n->messages_tail,
  1197. mq);
  1198. n->is_active = mq;
  1199. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1200. "Giving message with %u bytes to plugin session %p\n",
  1201. mq->message_buf_size,
  1202. n->primary_address.session);
  1203. (void) send_with_session (n,
  1204. mq->message_buf,
  1205. mq->message_buf_size,
  1206. 0 /* priority */,
  1207. timeout,
  1208. GNUNET_NO,
  1209. &transmit_send_continuation,
  1210. mq);
  1211. }
  1212. /**
  1213. * Send keepalive message to the neighbour. Must only be called
  1214. * if we are on 'connected' state or while trying to switch addresses.
  1215. * Will internally determine if a keepalive is truly needed (so can
  1216. * always be called).
  1217. *
  1218. * @param n neighbour that went idle and needs a keepalive
  1219. */
  1220. static void
  1221. send_keepalive (struct NeighbourMapEntry *n)
  1222. {
  1223. struct SessionKeepAliveMessage m;
  1224. struct GNUNET_TIME_Relative timeout;
  1225. uint32_t nonce;
  1226. GNUNET_assert ((GNUNET_TRANSPORT_PS_CONNECTED == n->state) ||
  1227. (GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT == n->state));
  1228. if (GNUNET_TIME_absolute_get_remaining (n->keep_alive_time).rel_value_us > 0)
  1229. return; /* no keepalive needed at this time */
  1230. nonce = 0; /* 0 indicates 'not set' */
  1231. while (0 == nonce)
  1232. nonce = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
  1233. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1234. "Sending keep alive to peer `%s' with nonce %u\n",
  1235. GNUNET_i2s (&n->id),
  1236. nonce);
  1237. m.header.size = htons (sizeof (struct SessionKeepAliveMessage));
  1238. m.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE);
  1239. m.nonce = htonl (nonce);
  1240. timeout = send_with_session (n,
  1241. &m,
  1242. sizeof (m),
  1243. UINT32_MAX /* priority */,
  1244. GNUNET_TIME_UNIT_FOREVER_REL,
  1245. GNUNET_YES,
  1246. NULL, NULL);
  1247. GNUNET_STATISTICS_update (GST_stats,
  1248. gettext_noop ("# keepalives sent"),
  1249. 1,
  1250. GNUNET_NO);
  1251. n->primary_address.keep_alive_nonce = nonce;
  1252. n->expect_latency_response = GNUNET_YES;
  1253. n->last_keep_alive_time = GNUNET_TIME_absolute_get ();
  1254. n->keep_alive_time = GNUNET_TIME_relative_to_absolute (timeout);
  1255. }
  1256. /**
  1257. * Keep the connection to the given neighbour alive longer,
  1258. * we received a KEEPALIVE (or equivalent); send a response.
  1259. *
  1260. * @param neighbour neighbour to keep alive (by sending keep alive response)
  1261. * @param m the keep alive message containing the nonce to respond to
  1262. */
  1263. void
  1264. GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour,
  1265. const struct GNUNET_MessageHeader *m)
  1266. {
  1267. struct NeighbourMapEntry *n;
  1268. const struct SessionKeepAliveMessage *msg_in;
  1269. struct SessionKeepAliveMessage msg;
  1270. if (sizeof (struct SessionKeepAliveMessage) != ntohs (m->size))
  1271. return;
  1272. msg_in = (struct SessionKeepAliveMessage *) m;
  1273. if (NULL == (n = lookup_neighbour (neighbour)))
  1274. {
  1275. GNUNET_STATISTICS_update (GST_stats,
  1276. gettext_noop
  1277. ("# KEEPALIVE messages discarded (peer unknown)"),
  1278. 1, GNUNET_NO);
  1279. return;
  1280. }
  1281. if (NULL == n->primary_address.session)
  1282. {
  1283. GNUNET_STATISTICS_update (GST_stats,
  1284. gettext_noop
  1285. ("# KEEPALIVE messages discarded (no session)"),
  1286. 1, GNUNET_NO);
  1287. return;
  1288. }
  1289. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1290. "Received keep alive request from peer `%s' with nonce %u\n",
  1291. GNUNET_i2s (&n->id), ntohl (msg_in->nonce));
  1292. /* send reply to allow neighbour to measure latency */
  1293. msg.header.size = htons (sizeof (struct SessionKeepAliveMessage));
  1294. msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE);
  1295. msg.nonce = msg_in->nonce;
  1296. (void) send_with_session (n,
  1297. &msg,
  1298. sizeof (struct SessionKeepAliveMessage),
  1299. UINT32_MAX /* priority */,
  1300. GNUNET_TIME_UNIT_FOREVER_REL,
  1301. GNUNET_YES,
  1302. NULL, NULL);
  1303. }
  1304. /**
  1305. * We received a KEEP_ALIVE_RESPONSE message and use this to calculate
  1306. * latency to this peer. Pass the updated information (existing ats
  1307. * plus calculated latency) to ATS.
  1308. *
  1309. * @param neighbour neighbour to keep alive
  1310. * @param m the message containing the keep alive response
  1311. */
  1312. void
  1313. GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour,
  1314. const struct GNUNET_MessageHeader *m)
  1315. {
  1316. struct NeighbourMapEntry *n;
  1317. const struct SessionKeepAliveMessage *msg;
  1318. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  1319. struct GNUNET_TIME_Relative latency;
  1320. if (sizeof (struct SessionKeepAliveMessage) != ntohs (m->size))
  1321. return;
  1322. msg = (const struct SessionKeepAliveMessage *) m;
  1323. if (NULL == (n = lookup_neighbour (neighbour)))
  1324. {
  1325. GNUNET_STATISTICS_update (GST_stats,
  1326. gettext_noop
  1327. ("# KEEPALIVE_RESPONSE messages discarded (not connected)"),
  1328. 1, GNUNET_NO);
  1329. return;
  1330. }
  1331. if ( (GNUNET_TRANSPORT_PS_CONNECTED != n->state) ||
  1332. (GNUNET_YES != n->expect_latency_response) )
  1333. {
  1334. GNUNET_STATISTICS_update (GST_stats,
  1335. gettext_noop
  1336. ("# KEEPALIVE_RESPONSE messages discarded (not expected)"),
  1337. 1, GNUNET_NO);
  1338. return;
  1339. }
  1340. if (NULL == n->primary_address.address)
  1341. {
  1342. GNUNET_STATISTICS_update (GST_stats,
  1343. gettext_noop
  1344. ("# KEEPALIVE_RESPONSE messages discarded (address changed)"),
  1345. 1, GNUNET_NO);
  1346. return;
  1347. }
  1348. if (n->primary_address.keep_alive_nonce != ntohl (msg->nonce))
  1349. {
  1350. GNUNET_STATISTICS_update (GST_stats,
  1351. gettext_noop
  1352. ("# KEEPALIVE_RESPONSE messages discarded (wrong nonce)"),
  1353. 1, GNUNET_NO);
  1354. return;
  1355. }
  1356. else
  1357. {
  1358. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1359. "Received keep alive response from peer `%s' for session %p\n",
  1360. GNUNET_i2s (&n->id),
  1361. n->primary_address.session);
  1362. }
  1363. /* Update session timeout here */
  1364. if (NULL != (papi = GST_plugins_find (n->primary_address.address->transport_name)))
  1365. {
  1366. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1367. "Updating session for peer `%s' for session %p\n",
  1368. GNUNET_i2s (&n->id),
  1369. n->primary_address.session);
  1370. papi->update_session_timeout (papi->cls,
  1371. &n->id,
  1372. n->primary_address.session);
  1373. }
  1374. else
  1375. {
  1376. GNUNET_break (0);
  1377. }
  1378. n->primary_address.keep_alive_nonce = 0;
  1379. n->expect_latency_response = GNUNET_NO;
  1380. set_state_and_timeout (n,
  1381. n->state,
  1382. GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT));
  1383. latency = GNUNET_TIME_absolute_get_duration (n->last_keep_alive_time);
  1384. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1385. "Latency for peer `%s' is %s\n",
  1386. GNUNET_i2s (&n->id),
  1387. GNUNET_STRINGS_relative_time_to_string (latency,
  1388. GNUNET_YES));
  1389. GST_ats_update_delay (n->primary_address.address,
  1390. GNUNET_TIME_relative_divide (latency, 2));
  1391. }
  1392. /**
  1393. * We have received a message from the given sender. How long should
  1394. * we delay before receiving more? (Also used to keep the peer marked
  1395. * as live).
  1396. *
  1397. * @param sender sender of the message
  1398. * @param size size of the message
  1399. * @param do_forward set to #GNUNET_YES if the message should be forwarded to clients
  1400. * #GNUNET_NO if the neighbour is not connected or violates the quota,
  1401. * #GNUNET_SYSERR if the connection is not fully up yet
  1402. * @return how long to wait before reading more from this sender
  1403. */
  1404. struct GNUNET_TIME_Relative
  1405. GST_neighbours_calculate_receive_delay (const struct GNUNET_PeerIdentity *sender,
  1406. ssize_t size,
  1407. int *do_forward)
  1408. {
  1409. struct NeighbourMapEntry *n;
  1410. struct GNUNET_TIME_Relative ret;
  1411. if (NULL == neighbours)
  1412. {
  1413. *do_forward = GNUNET_NO;
  1414. return GNUNET_TIME_UNIT_FOREVER_REL; /* This can happen during shutdown */
  1415. }
  1416. if (NULL == (n = lookup_neighbour (sender)))
  1417. {
  1418. GST_neighbours_try_connect (sender);
  1419. if (NULL == (n = lookup_neighbour (sender)))
  1420. {
  1421. GNUNET_STATISTICS_update (GST_stats,
  1422. gettext_noop
  1423. ("# messages discarded due to lack of neighbour record"),
  1424. 1, GNUNET_NO);
  1425. *do_forward = GNUNET_NO;
  1426. return GNUNET_TIME_UNIT_ZERO;
  1427. }
  1428. }
  1429. if (! test_connected (n))
  1430. {
  1431. *do_forward = GNUNET_SYSERR;
  1432. return GNUNET_TIME_UNIT_ZERO;
  1433. }
  1434. if (GNUNET_YES == GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, size))
  1435. {
  1436. n->quota_violation_count++;
  1437. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1438. "Bandwidth quota (%u b/s) violation detected (total of %u).\n",
  1439. n->in_tracker.available_bytes_per_s__,
  1440. n->quota_violation_count);
  1441. /* Discount 32k per violation */
  1442. GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, -32 * 1024);
  1443. }
  1444. else
  1445. {
  1446. if (n->quota_violation_count > 0)
  1447. {
  1448. /* try to add 32k back */
  1449. GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, 32 * 1024);
  1450. n->quota_violation_count--;
  1451. }
  1452. }
  1453. if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
  1454. {
  1455. GNUNET_STATISTICS_update (GST_stats,
  1456. gettext_noop
  1457. ("# bandwidth quota violations by other peers"),
  1458. 1, GNUNET_NO);
  1459. *do_forward = GNUNET_NO;
  1460. return GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT;
  1461. }
  1462. *do_forward = GNUNET_YES;
  1463. ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 32 * 1024);
  1464. if (ret.rel_value_us > 0)
  1465. {
  1466. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1467. "Throttling read (%lld bytes excess at %u b/s), waiting %s before reading more.\n",
  1468. (long long) n->in_tracker.consumption_since_last_update__,
  1469. (unsigned int) n->in_tracker.available_bytes_per_s__,
  1470. GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES));
  1471. GNUNET_STATISTICS_update (GST_stats,
  1472. gettext_noop ("# ms throttling suggested"),
  1473. (int64_t) ret.rel_value_us / 1000LL,
  1474. GNUNET_NO);
  1475. }
  1476. return ret;
  1477. }
  1478. /**
  1479. * Transmit a message to the given target using the active connection.
  1480. *
  1481. * @param target destination
  1482. * @param msg message to send
  1483. * @param msg_size number of bytes in msg
  1484. * @param timeout when to fail with timeout
  1485. * @param cont function to call when done
  1486. * @param cont_cls closure for @a cont
  1487. */
  1488. void
  1489. GST_neighbours_send (const struct GNUNET_PeerIdentity *target,
  1490. const void *msg,
  1491. size_t msg_size,
  1492. struct GNUNET_TIME_Relative timeout,
  1493. GST_NeighbourSendContinuation cont,
  1494. void *cont_cls)
  1495. {
  1496. struct NeighbourMapEntry *n;
  1497. struct MessageQueue *mq;
  1498. /* All ove these cases should never happen; they are all API violations.
  1499. But we check anyway, just to be sure. */
  1500. if (NULL == (n = lookup_neighbour (target)))
  1501. {
  1502. GNUNET_break (0);
  1503. if (NULL != cont)
  1504. cont (cont_cls,
  1505. GNUNET_SYSERR,
  1506. msg_size,
  1507. 0);
  1508. return;
  1509. }
  1510. if (GNUNET_YES != test_connected (n))
  1511. {
  1512. GNUNET_break (0);
  1513. if (NULL != cont)
  1514. cont (cont_cls,
  1515. GNUNET_SYSERR,
  1516. msg_size,
  1517. 0);
  1518. return;
  1519. }
  1520. bytes_in_send_queue += msg_size;
  1521. GNUNET_STATISTICS_set (GST_stats,
  1522. gettext_noop
  1523. ("# bytes in message queue for other peers"),
  1524. bytes_in_send_queue, GNUNET_NO);
  1525. mq = GNUNET_malloc (sizeof (struct MessageQueue) + msg_size);
  1526. mq->cont = cont;
  1527. mq->cont_cls = cont_cls;
  1528. memcpy (&mq[1], msg, msg_size);
  1529. mq->message_buf = (const char *) &mq[1];
  1530. mq->message_buf_size = msg_size;
  1531. mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
  1532. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1533. "Enqueueing %u bytes to send to peer %s\n",
  1534. msg_size,
  1535. GNUNET_i2s (target));
  1536. GNUNET_CONTAINER_DLL_insert_tail (n->messages_head,
  1537. n->messages_tail,
  1538. mq);
  1539. if (NULL != n->task)
  1540. GNUNET_SCHEDULER_cancel (n->task);
  1541. n->task = GNUNET_SCHEDULER_add_now (&master_task, n);
  1542. }
  1543. /**
  1544. * Continuation called from our attempt to transmitted our
  1545. * #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN to the specified @a
  1546. * target. Continue processing based on the @a result. Specifically,
  1547. * if we failed to transmit, discard the address we used.
  1548. *
  1549. * @param cls NULL
  1550. * @param target which peer received the transmission
  1551. * @param result #GNUNET_OK if sending worked
  1552. * @param size_payload how many bytes of payload were sent (ignored)
  1553. * @param size_on_wire how much bandwidth was consumed on the wire (ignored)
  1554. */
  1555. static void
  1556. send_session_syn_cont (void *cls,
  1557. const struct GNUNET_PeerIdentity *target,
  1558. int result,
  1559. size_t size_payload,
  1560. size_t size_on_wire)
  1561. {
  1562. struct NeighbourMapEntry *n;
  1563. n = lookup_neighbour (target);
  1564. if (NULL == n)
  1565. {
  1566. /* SYN continuation was called after neighbor was freed,
  1567. * for example due to a time out for the state or the session
  1568. * used was already terminated: nothing to do here... */
  1569. return;
  1570. }
  1571. if ( (GNUNET_TRANSPORT_PS_SYN_SENT != n->state) &&
  1572. (GNUNET_TRANSPORT_PS_RECONNECT_SENT != n->state) &&
  1573. (GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT != n->state))
  1574. {
  1575. /* SYN continuation was called after neighbor changed state,
  1576. * for example due to a time out for the state or the session
  1577. * used was already terminated: nothing to do here... */
  1578. return;
  1579. }
  1580. if (GNUNET_OK == result)
  1581. return;
  1582. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1583. _("Failed to send SYN message to peer `%s'\n"),
  1584. GNUNET_i2s (target));
  1585. switch (n->state) {
  1586. case GNUNET_TRANSPORT_PS_SYN_SENT:
  1587. /* Remove address and request an additional one */
  1588. unset_primary_address (n);
  1589. set_state_and_timeout (n,
  1590. GNUNET_TRANSPORT_PS_INIT_ATS,
  1591. GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT));
  1592. break;
  1593. case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
  1594. /* Remove address and request an additional one */
  1595. unset_primary_address (n);
  1596. set_state_and_timeout (n,
  1597. GNUNET_TRANSPORT_PS_RECONNECT_ATS,
  1598. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  1599. break;
  1600. case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
  1601. /* Remove address and request and go back to primary address */
  1602. GNUNET_STATISTICS_update (GST_stats,
  1603. gettext_noop ("# Failed attempts to switch addresses (failed to send SYN CONT)"),
  1604. 1,
  1605. GNUNET_NO);
  1606. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1607. "Switch failed, cleaning up alternative address\n");
  1608. free_address (&n->alternative_address);
  1609. set_state_and_timeout (n,
  1610. GNUNET_TRANSPORT_PS_CONNECTED,
  1611. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  1612. break;
  1613. default:
  1614. disconnect_neighbour (n);
  1615. break;
  1616. }
  1617. }
  1618. /**
  1619. * Send a SYN message via the given address.
  1620. *
  1621. * @param na address to use
  1622. */
  1623. static void
  1624. send_syn (struct NeighbourAddress *na)
  1625. {
  1626. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  1627. struct TransportSynMessage connect_msg;
  1628. struct NeighbourMapEntry *n;
  1629. GNUNET_assert (NULL != na->session);
  1630. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1631. "Sending SYN message to peer `%s' at %s\n",
  1632. GNUNET_i2s (&na->address->peer),
  1633. GST_plugins_a2s (na->address));
  1634. papi = GST_plugins_find (na->address->transport_name);
  1635. GNUNET_assert (NULL != papi);
  1636. GNUNET_STATISTICS_update (GST_stats,
  1637. gettext_noop
  1638. ("# SYN messages sent"),
  1639. 1, GNUNET_NO);
  1640. na->connect_timestamp = GNUNET_TIME_absolute_get ();
  1641. connect_msg.header.size = htons (sizeof (struct TransportSynMessage));
  1642. connect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN);
  1643. connect_msg.reserved = htonl (0);
  1644. connect_msg.timestamp = GNUNET_TIME_absolute_hton (na->connect_timestamp);
  1645. if (-1 ==
  1646. papi->send (papi->cls,
  1647. na->session,
  1648. (const char *) &connect_msg,
  1649. sizeof (struct TransportSynMessage),
  1650. UINT_MAX,
  1651. SETUP_CONNECTION_TIMEOUT,
  1652. &send_session_syn_cont, NULL))
  1653. {
  1654. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1655. _("Failed to transmit SYN message to %s\n"),
  1656. GST_plugins_a2s (na->address));
  1657. n = lookup_neighbour (&na->address->peer);
  1658. if (NULL == n)
  1659. {
  1660. GNUNET_break (0);
  1661. return;
  1662. }
  1663. switch (n->state) {
  1664. case GNUNET_TRANSPORT_PS_SYN_SENT:
  1665. /* Remove address and request and additional one */
  1666. GNUNET_assert (na == &n->primary_address);
  1667. unset_primary_address (n);
  1668. set_state_and_timeout (n,
  1669. GNUNET_TRANSPORT_PS_INIT_ATS,
  1670. GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT));
  1671. /* Hard failure to send the SYN message with this address:
  1672. Destroy address and session */
  1673. break;
  1674. case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
  1675. /* Remove address and request an additional one */
  1676. GNUNET_assert (na == &n->primary_address);
  1677. unset_primary_address (n);
  1678. set_state_and_timeout (n,
  1679. GNUNET_TRANSPORT_PS_RECONNECT_ATS,
  1680. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  1681. break;
  1682. case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
  1683. GNUNET_assert (na == &n->alternative_address);
  1684. GNUNET_STATISTICS_update (GST_stats,
  1685. gettext_noop ("# Failed attempts to switch addresses (failed to send SYN)"),
  1686. 1,
  1687. GNUNET_NO);
  1688. /* Remove address and request an additional one */
  1689. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1690. "Switch failed, cleaning up alternative address\n");
  1691. free_address (&n->alternative_address);
  1692. set_state_and_timeout (n,
  1693. GNUNET_TRANSPORT_PS_CONNECTED,
  1694. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  1695. break;
  1696. default:
  1697. GNUNET_break (0);
  1698. disconnect_neighbour (n);
  1699. break;
  1700. }
  1701. return;
  1702. }
  1703. GST_neighbours_notify_data_sent (na->address,
  1704. na->session,
  1705. sizeof (struct TransportSynMessage));
  1706. }
  1707. /**
  1708. * Continuation called from our attempt to transmitted our
  1709. * #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK to the specified @a
  1710. * target. Continue processing based on the @a result. Specifically,
  1711. * if we failed to transmit, discard the address we used.
  1712. *
  1713. * @param cls NULL
  1714. * @param target which peer received the transmission
  1715. * @param result #GNUNET_OK if sending worked
  1716. * @param size_payload how many bytes of payload were sent (ignored)
  1717. * @param size_on_wire how much bandwidth was consumed on the wire (ignored)
  1718. */
  1719. static void
  1720. send_session_syn_ack_cont (void *cls,
  1721. const struct GNUNET_PeerIdentity *target,
  1722. int result,
  1723. size_t size_payload,
  1724. size_t size_on_wire)
  1725. {
  1726. struct NeighbourMapEntry *n;
  1727. n = lookup_neighbour (target);
  1728. if (NULL == n)
  1729. {
  1730. /* SYN_ACK continuation was called after neighbor was freed,
  1731. * for example due to a time out for the state or the session
  1732. * used was already terminated: nothing to do here... */
  1733. return;
  1734. }
  1735. if (GNUNET_TRANSPORT_PS_SYN_RECV_ACK != n->state)
  1736. {
  1737. /* SYN_ACK continuation was called after neighbor changed state,
  1738. * for example due to a time out for the state or the session
  1739. * used was already terminated: nothing to do here... */
  1740. return;
  1741. }
  1742. if (GNUNET_OK == result)
  1743. return;
  1744. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1745. _("Failed to send SYN_ACK message to peer `%s' using address `%s'\n"),
  1746. GNUNET_i2s (target),
  1747. GST_plugins_a2s (n->primary_address.address));
  1748. /* Remove address and request and additional one */
  1749. /* FIXME: what if the neighbour's primary address
  1750. changed in the meantime? Might want to instead
  1751. pass "something" around in closure to be sure. */
  1752. unset_primary_address (n);
  1753. n->ack_state = ACK_SEND_SYN_ACK;
  1754. set_state_and_timeout (n,
  1755. GNUNET_TRANSPORT_PS_SYN_RECV_ATS,
  1756. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  1757. }
  1758. /**
  1759. * Send a SYN_ACK message via the given address.
  1760. *
  1761. * @param na address and session to use
  1762. * @param timestamp timestamp to use for the ACK message
  1763. * @return #GNUNET_SYSERR if sending immediately failed, #GNUNET_OK otherwise
  1764. */
  1765. static void
  1766. send_syn_ack_message (struct NeighbourAddress *na,
  1767. struct GNUNET_TIME_Absolute timestamp)
  1768. {
  1769. const struct GNUNET_HELLO_Address *address = na->address;
  1770. struct Session *session = na->session;
  1771. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  1772. struct TransportSynMessage connect_msg;
  1773. struct NeighbourMapEntry *n;
  1774. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1775. "Sending SYN_ACK to peer `%s'\n",
  1776. GNUNET_i2s (&address->peer));
  1777. if (NULL == (papi = GST_plugins_find (address->transport_name)))
  1778. {
  1779. GNUNET_break (0);
  1780. return;
  1781. }
  1782. if (NULL == session)
  1783. session = papi->get_session (papi->cls,
  1784. address);
  1785. if (NULL == session)
  1786. {
  1787. GNUNET_break (0);
  1788. return;
  1789. }
  1790. GST_ats_new_session (address,
  1791. session);
  1792. GNUNET_STATISTICS_update (GST_stats,
  1793. gettext_noop
  1794. ("# SYN_ACK messages sent"),
  1795. 1, GNUNET_NO);
  1796. connect_msg.header.size = htons (sizeof (struct TransportSynMessage));
  1797. connect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK);
  1798. connect_msg.reserved = htonl (0);
  1799. connect_msg.timestamp = GNUNET_TIME_absolute_hton (timestamp);
  1800. if (GNUNET_SYSERR ==
  1801. papi->send (papi->cls,
  1802. session,
  1803. (const char *) &connect_msg,
  1804. sizeof (struct TransportSynMessage),
  1805. UINT_MAX,
  1806. GNUNET_TIME_UNIT_FOREVER_REL,
  1807. &send_session_syn_ack_cont, NULL))
  1808. {
  1809. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1810. _("Failed to transmit SYN_ACK message to %s\n"),
  1811. GST_plugins_a2s (address));
  1812. n = lookup_neighbour (&address->peer);
  1813. if (NULL == n)
  1814. {
  1815. GNUNET_break (0);
  1816. return;
  1817. }
  1818. /* Remove address and request and additional one */
  1819. unset_primary_address (n);
  1820. n->ack_state = ACK_SEND_SYN_ACK;
  1821. set_state_and_timeout (n,
  1822. GNUNET_TRANSPORT_PS_SYN_RECV_ATS,
  1823. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  1824. return;
  1825. }
  1826. }
  1827. /**
  1828. * Function called by the bandwidth tracker for a peer whenever
  1829. * the tracker's state changed such that we need to recalculate
  1830. * the delay for flow control. We calculate the latest delay
  1831. * and inform the plugin (if applicable).
  1832. *
  1833. * @param cls the `struct NeighbourMapEntry` to update calculations for
  1834. */
  1835. static void
  1836. inbound_bw_tracker_update (void *cls)
  1837. {
  1838. struct NeighbourMapEntry *n = cls;
  1839. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  1840. struct GNUNET_TIME_Relative delay;
  1841. int do_forward;
  1842. if (NULL == n->primary_address.address)
  1843. return; /* not active, ignore */
  1844. papi = GST_plugins_find (n->primary_address.address->transport_name);
  1845. GNUNET_assert (NULL != papi);
  1846. if (NULL == papi->update_inbound_delay)
  1847. return;
  1848. delay = GST_neighbours_calculate_receive_delay (&n->id,
  1849. 0,
  1850. &do_forward);
  1851. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1852. "New inbound delay for peer `%s' is %llu ms\n",
  1853. GNUNET_i2s (&n->id),
  1854. delay.rel_value_us / 1000);
  1855. papi->update_inbound_delay (papi->cls,
  1856. &n->id,
  1857. n->primary_address.session,
  1858. delay);
  1859. }
  1860. /**
  1861. * Create a fresh entry in the neighbour map for the given peer
  1862. *
  1863. * @param peer peer to create an entry for
  1864. * @return new neighbour map entry
  1865. */
  1866. static struct NeighbourMapEntry *
  1867. setup_neighbour (const struct GNUNET_PeerIdentity *peer)
  1868. {
  1869. struct NeighbourMapEntry *n;
  1870. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1871. "Creating new neighbour entry for `%s'\n",
  1872. GNUNET_i2s (peer));
  1873. n = GNUNET_new (struct NeighbourMapEntry);
  1874. n->id = *peer;
  1875. n->ack_state = ACK_UNDEFINED;
  1876. n->last_util_transmission = GNUNET_TIME_absolute_get();
  1877. GNUNET_BANDWIDTH_tracker_init (&n->in_tracker,
  1878. &inbound_bw_tracker_update,
  1879. n,
  1880. GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
  1881. MAX_BANDWIDTH_CARRY_S);
  1882. n->task = GNUNET_SCHEDULER_add_now (&master_task, n);
  1883. set_state_and_timeout (n,
  1884. GNUNET_TRANSPORT_PS_NOT_CONNECTED,
  1885. GNUNET_TIME_UNIT_FOREVER_ABS);
  1886. GNUNET_assert (GNUNET_OK ==
  1887. GNUNET_CONTAINER_multipeermap_put (neighbours,
  1888. &n->id, n,
  1889. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  1890. n->suggest_handle = GNUNET_ATS_connectivity_suggest (GST_ats_connect,
  1891. peer);
  1892. return n;
  1893. }
  1894. /**
  1895. * Entry in a DLL we use to keep track of pending blacklist checks.
  1896. */
  1897. struct BlacklistCheckSwitchContext
  1898. {
  1899. /**
  1900. * DLL prev pointer.
  1901. */
  1902. struct BlacklistCheckSwitchContext *prev;
  1903. /**
  1904. * DLL next pointer.
  1905. */
  1906. struct BlacklistCheckSwitchContext *next;
  1907. /**
  1908. * Handle to the blacklist check we are performing.
  1909. */
  1910. struct GST_BlacklistCheck *blc;
  1911. /**
  1912. * Address we are asking the blacklist subsystem about.
  1913. */
  1914. struct GNUNET_HELLO_Address *address;
  1915. /**
  1916. * Session we should use in conjunction with @e address, can be NULL.
  1917. */
  1918. struct Session *session;
  1919. /**
  1920. * Inbound bandwidth that was assigned to @e address.
  1921. */
  1922. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
  1923. /**
  1924. * Outbound bandwidth that was assigned to @e address.
  1925. */
  1926. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
  1927. };
  1928. /**
  1929. * Black list check result for try_connect call
  1930. * If connection to the peer is allowed request adddress and
  1931. *
  1932. * @param cls blc_ctx bl context
  1933. * @param peer the peer
  1934. * @param result the result
  1935. */
  1936. static void
  1937. try_connect_bl_check_cont (void *cls,
  1938. const struct GNUNET_PeerIdentity *peer,
  1939. int result)
  1940. {
  1941. struct BlacklistCheckSwitchContext *blc_ctx = cls;
  1942. struct NeighbourMapEntry *n;
  1943. GNUNET_CONTAINER_DLL_remove (pending_bc_head,
  1944. pending_bc_tail,
  1945. blc_ctx);
  1946. GNUNET_free (blc_ctx);
  1947. if (GNUNET_OK != result)
  1948. {
  1949. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1950. _("Blacklisting disapproved to connect to peer `%s'\n"),
  1951. GNUNET_i2s (peer));
  1952. return;
  1953. }
  1954. /* Setup a new neighbour */
  1955. if (NULL != lookup_neighbour(peer))
  1956. return; /* The neighbor was created in the meantime while waited for BL clients */
  1957. n = setup_neighbour (peer);
  1958. /* Request address suggestions for this peer */
  1959. set_state_and_timeout (n,
  1960. GNUNET_TRANSPORT_PS_INIT_ATS,
  1961. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  1962. }
  1963. /**
  1964. * Try to create a connection to the given target (eventually).
  1965. *
  1966. * @param target peer to try to connect to
  1967. */
  1968. void
  1969. GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target)
  1970. {
  1971. struct NeighbourMapEntry *n;
  1972. struct GST_BlacklistCheck *blc;
  1973. struct BlacklistCheckSwitchContext *blc_ctx;
  1974. if (NULL == neighbours)
  1975. {
  1976. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1977. "Asked to connect to peer `%s' during shutdown\n",
  1978. GNUNET_i2s (target));
  1979. return; /* during shutdown, do nothing */
  1980. }
  1981. n = lookup_neighbour (target);
  1982. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1983. "Asked to connect to peer `%s' (state: %s)\n",
  1984. GNUNET_i2s (target),
  1985. (NULL != n) ? GNUNET_TRANSPORT_ps2s(n->state) : "NEW PEER");
  1986. if (NULL != n)
  1987. {
  1988. switch (n->state)
  1989. {
  1990. case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
  1991. /* this should not be possible */
  1992. GNUNET_break (0);
  1993. free_neighbour (n);
  1994. break;
  1995. case GNUNET_TRANSPORT_PS_INIT_ATS:
  1996. case GNUNET_TRANSPORT_PS_SYN_SENT:
  1997. case GNUNET_TRANSPORT_PS_SYN_RECV_ATS:
  1998. case GNUNET_TRANSPORT_PS_SYN_RECV_ACK:
  1999. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2000. "Ignoring request to try to connect to `%s', already trying!\n",
  2001. GNUNET_i2s (target));
  2002. return; /* already trying */
  2003. case GNUNET_TRANSPORT_PS_CONNECTED:
  2004. case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
  2005. case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
  2006. case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
  2007. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2008. "Ignoring request to try to connect, already connected to `%s'!\n",
  2009. GNUNET_i2s (target));
  2010. return; /* already connected */
  2011. case GNUNET_TRANSPORT_PS_DISCONNECT:
  2012. /* get rid of remains, ready to re-try immediately */
  2013. free_neighbour (n);
  2014. break;
  2015. case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
  2016. /* should not be possible */
  2017. GNUNET_assert (0);
  2018. return;
  2019. default:
  2020. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2021. "Unhandled state `%s'\n",
  2022. GNUNET_TRANSPORT_ps2s (n->state));
  2023. GNUNET_break (0);
  2024. free_neighbour (n);
  2025. break;
  2026. }
  2027. }
  2028. /* Do blacklist check if connecting to this peer is allowed */
  2029. blc_ctx = GNUNET_new (struct BlacklistCheckSwitchContext);
  2030. GNUNET_CONTAINER_DLL_insert (pending_bc_head,
  2031. pending_bc_tail,
  2032. blc_ctx);
  2033. if (NULL !=
  2034. (blc = GST_blacklist_test_allowed (target,
  2035. NULL,
  2036. &try_connect_bl_check_cont,
  2037. blc_ctx)))
  2038. {
  2039. blc_ctx->blc = blc;
  2040. }
  2041. }
  2042. /**
  2043. * We received a 'SYN' message from the other peer.
  2044. * Consider switching to it.
  2045. *
  2046. * @param message possibly a 'struct TransportSynMessage' (check format)
  2047. * @param peer identity of the peer to switch the address for
  2048. * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error
  2049. */
  2050. int
  2051. GST_neighbours_handle_session_syn (const struct GNUNET_MessageHeader *message,
  2052. const struct GNUNET_PeerIdentity *peer)
  2053. {
  2054. const struct TransportSynMessage *scm;
  2055. struct NeighbourMapEntry *n;
  2056. struct GNUNET_TIME_Absolute ts;
  2057. if (ntohs (message->size) != sizeof (struct TransportSynMessage))
  2058. {
  2059. GNUNET_break_op (0);
  2060. return GNUNET_SYSERR;
  2061. }
  2062. GNUNET_STATISTICS_update (GST_stats,
  2063. gettext_noop
  2064. ("# SYN messages received"),
  2065. 1, GNUNET_NO);
  2066. if (NULL == neighbours)
  2067. {
  2068. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2069. _("SYN request from peer `%s' ignored due impending shutdown\n"),
  2070. GNUNET_i2s (peer));
  2071. return GNUNET_OK; /* we're shutting down */
  2072. }
  2073. scm = (const struct TransportSynMessage *) message;
  2074. GNUNET_break_op (0 == ntohl (scm->reserved));
  2075. ts = GNUNET_TIME_absolute_ntoh (scm->timestamp);
  2076. n = lookup_neighbour (peer);
  2077. if (NULL == n)
  2078. {
  2079. /* This is a new neighbour and set to not connected */
  2080. n = setup_neighbour (peer);
  2081. }
  2082. /* Remember this SYN message in neighbour */
  2083. n->ack_state = ACK_SEND_SYN_ACK;
  2084. n->connect_ack_timestamp = ts;
  2085. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2086. "Received SYN for peer `%s' in state %s/%s\n",
  2087. GNUNET_i2s (peer),
  2088. GNUNET_TRANSPORT_ps2s (n->state),
  2089. print_ack_state (n->ack_state));
  2090. switch (n->state)
  2091. {
  2092. case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
  2093. /* Request an address from ATS to send SYN_ACK to this peer */
  2094. set_state_and_timeout (n,
  2095. GNUNET_TRANSPORT_PS_SYN_RECV_ATS,
  2096. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  2097. break;
  2098. case GNUNET_TRANSPORT_PS_INIT_ATS:
  2099. /* SYN message takes priority over us asking ATS for address:
  2100. * Wait for ATS to suggest an address and send SYN_ACK */
  2101. set_state_and_timeout (n,
  2102. GNUNET_TRANSPORT_PS_SYN_RECV_ATS,
  2103. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  2104. break;
  2105. case GNUNET_TRANSPORT_PS_SYN_RECV_ATS:
  2106. /* We already wait for an address to send an SYN_ACK */
  2107. break;
  2108. case GNUNET_TRANSPORT_PS_SYN_SENT:
  2109. case GNUNET_TRANSPORT_PS_SYN_RECV_ACK:
  2110. /* Send ACK immediately */
  2111. n->ack_state = ACK_SEND_ACK;
  2112. send_syn_ack_message (&n->primary_address,
  2113. ts);
  2114. break;
  2115. case GNUNET_TRANSPORT_PS_CONNECTED:
  2116. /* we are already connected and can thus send the ACK immediately */
  2117. GNUNET_assert (NULL != n->primary_address.address);
  2118. GNUNET_assert (NULL != n->primary_address.session);
  2119. n->ack_state = ACK_SEND_ACK;
  2120. send_syn_ack_message (&n->primary_address,
  2121. ts);
  2122. break;
  2123. case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
  2124. /* We wait for ATS address suggestion */
  2125. break;
  2126. case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
  2127. /* We received a SYN message while waiting for a SYN_ACK in fast
  2128. * reconnect. Send SYN_ACK immediately */
  2129. n->ack_state = ACK_SEND_ACK;
  2130. send_syn_ack_message (&n->primary_address,
  2131. n->connect_ack_timestamp);
  2132. break;
  2133. case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
  2134. /* We are already connected and can thus send the ACK immediately;
  2135. still, it can never hurt to have an alternative address, so also
  2136. tell ATS about it */
  2137. GNUNET_assert (NULL != n->primary_address.address);
  2138. GNUNET_assert (NULL != n->primary_address.session);
  2139. n->ack_state = ACK_SEND_ACK;
  2140. send_syn_ack_message (&n->primary_address,
  2141. ts);
  2142. break;
  2143. case GNUNET_TRANSPORT_PS_DISCONNECT:
  2144. /* Get rid of remains and re-try */
  2145. free_neighbour (n);
  2146. n = setup_neighbour (peer);
  2147. /* Remember the SYN time stamp for ACK message */
  2148. n->ack_state = ACK_SEND_SYN_ACK;
  2149. n->connect_ack_timestamp = ts;
  2150. /* Request an address for the peer */
  2151. set_state_and_timeout (n,
  2152. GNUNET_TRANSPORT_PS_SYN_RECV_ATS,
  2153. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  2154. break;
  2155. case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
  2156. /* should not be possible */
  2157. GNUNET_assert (0);
  2158. break;
  2159. default:
  2160. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2161. "Unhandled state `%s'\n",
  2162. GNUNET_TRANSPORT_ps2s (n->state));
  2163. GNUNET_break (0);
  2164. return GNUNET_SYSERR;
  2165. }
  2166. return GNUNET_OK;
  2167. }
  2168. /**
  2169. * Check if the given @a address is the same that we are already
  2170. * using for the respective neighbour. If so, update the bandwidth
  2171. * assignment and possibly the session and return #GNUNET_OK.
  2172. * If the new address is different from what the neighbour is
  2173. * using right now, return #GNUNET_NO.
  2174. *
  2175. * @param address address of the other peer,
  2176. * @param session session to use or NULL if transport should initiate a session
  2177. * @param bandwidth_in inbound quota to be used when connection is up,
  2178. * 0 to disconnect from peer
  2179. * @param bandwidth_out outbound quota to be used when connection is up,
  2180. * 0 to disconnect from peer
  2181. * @return #GNUNET_OK if we were able to just update the bandwidth and session,
  2182. * #GNUNET_NO if more extensive changes are required (address changed)
  2183. */
  2184. static int
  2185. try_run_fast_ats_update (const struct GNUNET_HELLO_Address *address,
  2186. struct Session *session,
  2187. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
  2188. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
  2189. {
  2190. struct NeighbourMapEntry *n;
  2191. n = lookup_neighbour (&address->peer);
  2192. if ( (NULL == n) ||
  2193. (NULL == n->primary_address.address) ||
  2194. (0 != GNUNET_HELLO_address_cmp (address,
  2195. n->primary_address.address)) )
  2196. return GNUNET_NO;
  2197. /* We are not really switching addresses, but merely adjusting
  2198. session and/or bandwidth, can do fast ATS update! */
  2199. if (session != n->primary_address.session)
  2200. {
  2201. /* switch to a different session, but keeping same address; could
  2202. happen if there is a 2nd inbound connection */
  2203. n->primary_address.session = session;
  2204. }
  2205. n->primary_address.bandwidth_in = bandwidth_in;
  2206. n->primary_address.bandwidth_out = bandwidth_out;
  2207. GST_neighbours_set_incoming_quota (&address->peer,
  2208. bandwidth_in);
  2209. send_outbound_quota (&address->peer,
  2210. bandwidth_out);
  2211. return GNUNET_OK;
  2212. }
  2213. /**
  2214. * We've been asked to switch addresses, and just now got the result
  2215. * from the blacklist check to see if this is allowed.
  2216. *
  2217. * @param cls the `struct BlacklistCheckSwitchContext` with
  2218. * the information about the future address
  2219. * @param peer the peer we may switch addresses on
  2220. * @param result #GNUNET_NO if we are not allowed to use the new
  2221. * address
  2222. */
  2223. static void
  2224. switch_address_bl_check_cont (void *cls,
  2225. const struct GNUNET_PeerIdentity *peer,
  2226. int result)
  2227. {
  2228. struct BlacklistCheckSwitchContext *blc_ctx = cls;
  2229. struct GNUNET_TRANSPORT_PluginFunctions *papi;
  2230. struct NeighbourMapEntry *n;
  2231. if (result == GNUNET_NO)
  2232. {
  2233. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2234. "Blacklist denied to switch to suggested address `%s' session %p for peer `%s'\n",
  2235. GST_plugins_a2s (blc_ctx->address),
  2236. blc_ctx->session,
  2237. GNUNET_i2s (&blc_ctx->address->peer));
  2238. GNUNET_STATISTICS_update (GST_stats,
  2239. "# ATS suggestions ignored (blacklist denied)",
  2240. 1,
  2241. GNUNET_NO);
  2242. /* FIXME: tell plugin to force killing session here and now
  2243. (note: _proper_ plugin API for this does not yet exist) */
  2244. GST_ats_block_address (blc_ctx->address,
  2245. blc_ctx->session);
  2246. goto cleanup;
  2247. }
  2248. papi = GST_plugins_find (blc_ctx->address->transport_name);
  2249. GNUNET_assert (NULL != papi);
  2250. if (NULL == blc_ctx->session)
  2251. {
  2252. /* need to create a session, ATS only gave us an address */
  2253. blc_ctx->session = papi->get_session (papi->cls,
  2254. blc_ctx->address);
  2255. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2256. "Obtained new session for peer `%s' and address '%s': %p\n",
  2257. GNUNET_i2s (&blc_ctx->address->peer),
  2258. GST_plugins_a2s (blc_ctx->address),
  2259. blc_ctx->session);
  2260. if (NULL != blc_ctx->session)
  2261. GST_ats_new_session (blc_ctx->address,
  2262. blc_ctx->session);
  2263. }
  2264. if (NULL == blc_ctx->session)
  2265. {
  2266. /* session creation failed, bad!, fail! */
  2267. GNUNET_STATISTICS_update (GST_stats,
  2268. "# ATS suggestions ignored (failed to create session)",
  2269. 1,
  2270. GNUNET_NO);
  2271. /* No session could be obtained, remove blacklist check and clean up */
  2272. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2273. "Failed to obtain new session for peer `%s' and address '%s'\n",
  2274. GNUNET_i2s (&blc_ctx->address->peer),
  2275. GST_plugins_a2s (blc_ctx->address));
  2276. GST_ats_block_address (blc_ctx->address,
  2277. blc_ctx->session);
  2278. goto cleanup;
  2279. }
  2280. /* We did this check already before going into blacklist, but
  2281. it is theoretically possible that the situation changed in
  2282. the meantime, hence we check again here */
  2283. if (GNUNET_OK ==
  2284. try_run_fast_ats_update (blc_ctx->address,
  2285. blc_ctx->session,
  2286. blc_ctx->bandwidth_in,
  2287. blc_ctx->bandwidth_out))
  2288. goto cleanup; /* was just a minor update, we're done */
  2289. /* check if we also need to setup the neighbour entry */
  2290. if (NULL == (n = lookup_neighbour (peer)))
  2291. {
  2292. n = setup_neighbour (peer);
  2293. n->state = GNUNET_TRANSPORT_PS_INIT_ATS;
  2294. }
  2295. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2296. "Peer `%s' switches to address `%s'\n",
  2297. GNUNET_i2s (&blc_ctx->address->peer),
  2298. GST_plugins_a2s (blc_ctx->address));
  2299. switch (n->state)
  2300. {
  2301. case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
  2302. GNUNET_break (0);
  2303. GST_ats_block_address (blc_ctx->address,
  2304. blc_ctx->session);
  2305. free_neighbour (n);
  2306. return;
  2307. case GNUNET_TRANSPORT_PS_INIT_ATS:
  2308. /* We requested an address and ATS suggests one:
  2309. * set primary address and send SYN message*/
  2310. set_primary_address (n,
  2311. blc_ctx->address,
  2312. blc_ctx->session,
  2313. blc_ctx->bandwidth_in,
  2314. blc_ctx->bandwidth_out);
  2315. if (ACK_SEND_SYN_ACK == n->ack_state)
  2316. {
  2317. /* Send pending SYN_ACK message */
  2318. n->ack_state = ACK_SEND_ACK;
  2319. send_syn_ack_message (&n->primary_address,
  2320. n->connect_ack_timestamp);
  2321. }
  2322. set_state_and_timeout (n,
  2323. GNUNET_TRANSPORT_PS_SYN_SENT,
  2324. GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT));
  2325. send_syn (&n->primary_address);
  2326. break;
  2327. case GNUNET_TRANSPORT_PS_SYN_SENT:
  2328. /* ATS suggested a new address while waiting for an SYN_ACK:
  2329. * Switch and send new SYN */
  2330. /* ATS suggests a different address, switch again */
  2331. set_primary_address (n,
  2332. blc_ctx->address,
  2333. blc_ctx->session,
  2334. blc_ctx->bandwidth_in,
  2335. blc_ctx->bandwidth_out);
  2336. if (ACK_SEND_SYN_ACK == n->ack_state)
  2337. {
  2338. /* Send pending SYN_ACK message */
  2339. n->ack_state = ACK_SEND_ACK;
  2340. send_syn_ack_message (&n->primary_address,
  2341. n->connect_ack_timestamp);
  2342. }
  2343. set_state_and_timeout (n,
  2344. GNUNET_TRANSPORT_PS_SYN_SENT,
  2345. GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT));
  2346. send_syn (&n->primary_address);
  2347. break;
  2348. case GNUNET_TRANSPORT_PS_SYN_RECV_ATS:
  2349. /* We requested an address and ATS suggests one:
  2350. * set primary address and send SYN_ACK message*/
  2351. set_primary_address (n,
  2352. blc_ctx->address,
  2353. blc_ctx->session,
  2354. blc_ctx->bandwidth_in,
  2355. blc_ctx->bandwidth_out);
  2356. /* Send an ACK message as a response to the SYN msg */
  2357. set_state_and_timeout (n,
  2358. GNUNET_TRANSPORT_PS_SYN_RECV_ACK,
  2359. GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT));
  2360. send_syn_ack_message (&n->primary_address,
  2361. n->connect_ack_timestamp);
  2362. if ( (ACK_SEND_SYN_ACK == n->ack_state) ||
  2363. (ACK_UNDEFINED == n->ack_state) )
  2364. n->ack_state = ACK_SEND_ACK;
  2365. break;
  2366. case GNUNET_TRANSPORT_PS_SYN_RECV_ACK:
  2367. /* ATS asks us to switch while we were trying to connect; switch to new
  2368. address and check blacklist again */
  2369. if ( (ACK_SEND_SYN_ACK == n->ack_state) )
  2370. {
  2371. n->ack_state = ACK_SEND_ACK;
  2372. send_syn_ack_message (&n->primary_address,
  2373. n->connect_ack_timestamp);
  2374. }
  2375. set_primary_address (n,
  2376. blc_ctx->address,
  2377. blc_ctx->session,
  2378. blc_ctx->bandwidth_in,
  2379. blc_ctx->bandwidth_out);
  2380. set_state_and_timeout (n,
  2381. GNUNET_TRANSPORT_PS_SYN_RECV_ACK,
  2382. GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT));
  2383. break;
  2384. case GNUNET_TRANSPORT_PS_CONNECTED:
  2385. GNUNET_assert (NULL != n->primary_address.address);
  2386. GNUNET_assert (NULL != n->primary_address.session);
  2387. GNUNET_break (n->primary_address.session != blc_ctx->session);
  2388. /* ATS asks us to switch a life connection; see if we can get
  2389. a SYN_ACK on it before we actually do this! */
  2390. set_alternative_address (n,
  2391. blc_ctx->address,
  2392. blc_ctx->session,
  2393. blc_ctx->bandwidth_in,
  2394. blc_ctx->bandwidth_out);
  2395. set_state_and_timeout (n,
  2396. GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT,
  2397. GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT));
  2398. GNUNET_STATISTICS_update (GST_stats,
  2399. gettext_noop ("# Attempts to switch addresses"),
  2400. 1,
  2401. GNUNET_NO);
  2402. send_syn (&n->alternative_address);
  2403. break;
  2404. case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
  2405. set_primary_address (n,
  2406. blc_ctx->address,
  2407. blc_ctx->session,
  2408. blc_ctx->bandwidth_in,
  2409. blc_ctx->bandwidth_out);
  2410. if (ACK_SEND_SYN_ACK == n->ack_state)
  2411. {
  2412. /* Send pending SYN_ACK message */
  2413. n->ack_state = ACK_SEND_ACK;
  2414. send_syn_ack_message (&n->primary_address,
  2415. n->connect_ack_timestamp);
  2416. }
  2417. set_state_and_timeout (n,
  2418. GNUNET_TRANSPORT_PS_RECONNECT_SENT,
  2419. GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT));
  2420. send_syn (&n->primary_address);
  2421. break;
  2422. case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
  2423. /* ATS asks us to switch while we were trying to reconnect; switch to new
  2424. address and send SYN again */
  2425. set_primary_address (n,
  2426. blc_ctx->address,
  2427. blc_ctx->session,
  2428. blc_ctx->bandwidth_in,
  2429. blc_ctx->bandwidth_out);
  2430. set_state_and_timeout (n,
  2431. GNUNET_TRANSPORT_PS_RECONNECT_SENT,
  2432. GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT));
  2433. send_syn (&n->primary_address);
  2434. break;
  2435. case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
  2436. if ( (0 == GNUNET_HELLO_address_cmp (n->primary_address.address,
  2437. blc_ctx->address)) &&
  2438. (n->primary_address.session == blc_ctx->session) )
  2439. {
  2440. /* ATS switches back to still-active session */
  2441. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2442. "ATS double-switched, cleaning up alternative address\n");
  2443. free_address (&n->alternative_address);
  2444. set_state_and_timeout (n,
  2445. GNUNET_TRANSPORT_PS_CONNECTED,
  2446. n->timeout);
  2447. break;
  2448. }
  2449. /* ATS asks us to switch a life connection, send */
  2450. set_alternative_address (n,
  2451. blc_ctx->address,
  2452. blc_ctx->session,
  2453. blc_ctx->bandwidth_in,
  2454. blc_ctx->bandwidth_out);
  2455. set_state_and_timeout (n,
  2456. GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT,
  2457. GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT));
  2458. send_syn (&n->alternative_address);
  2459. break;
  2460. case GNUNET_TRANSPORT_PS_DISCONNECT:
  2461. /* not going to switch addresses while disconnecting */
  2462. GNUNET_STATISTICS_update (GST_stats,
  2463. "# ATS suggestion ignored (disconnecting)",
  2464. 1,
  2465. GNUNET_NO);
  2466. return;
  2467. case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
  2468. GNUNET_assert (0);
  2469. break;
  2470. default:
  2471. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2472. "Unhandled state `%s'\n",
  2473. GNUNET_TRANSPORT_ps2s (n->state));
  2474. GNUNET_break (0);
  2475. break;
  2476. }
  2477. cleanup:
  2478. GNUNET_CONTAINER_DLL_remove (pending_bc_head,
  2479. pending_bc_tail,
  2480. blc_ctx);
  2481. GNUNET_HELLO_address_free (blc_ctx->address);
  2482. GNUNET_free (blc_ctx);
  2483. }
  2484. /**
  2485. * For the given peer, switch to this address.
  2486. *
  2487. * Before accepting this addresses and actively using it, a blacklist check
  2488. * is performed.
  2489. *
  2490. * If any check fails or the suggestion can somehow not be followed, we
  2491. * MUST call #GST_ats_block_address() to tell ATS that the suggestion
  2492. * could not be satisfied and force ATS to do something else.
  2493. *
  2494. * @param address address of the other peer,
  2495. * @param session session to use or NULL if transport should initiate a session
  2496. * @param bandwidth_in inbound quota to be used when connection is up,
  2497. * 0 to disconnect from peer
  2498. * @param bandwidth_out outbound quota to be used when connection is up,
  2499. * 0 to disconnect from peer
  2500. */
  2501. void
  2502. GST_neighbours_switch_to_address (const struct GNUNET_HELLO_Address *address,
  2503. struct Session *session,
  2504. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
  2505. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
  2506. {
  2507. struct GST_BlacklistCheck *blc;
  2508. struct BlacklistCheckSwitchContext *blc_ctx;
  2509. GNUNET_assert (NULL != address->transport_name);
  2510. if (GNUNET_OK ==
  2511. try_run_fast_ats_update (address,
  2512. session,
  2513. bandwidth_in,
  2514. bandwidth_out))
  2515. return;
  2516. /* Check if plugin is available */
  2517. if (NULL == (GST_plugins_find (address->transport_name)))
  2518. {
  2519. /* we don't have the plugin for this address */
  2520. GNUNET_break (0);
  2521. GST_ats_block_address (address,
  2522. session);
  2523. return;
  2524. }
  2525. if ((NULL == session) &&
  2526. (GNUNET_HELLO_address_check_option (address,
  2527. GNUNET_HELLO_ADDRESS_INFO_INBOUND)))
  2528. {
  2529. /* This is a inbound address and we do not have a session to use! */
  2530. GNUNET_break (0);
  2531. GST_ats_block_address (address,
  2532. session);
  2533. return;
  2534. }
  2535. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2536. "ATS suggests address '%s' for peer `%s' at %u/%u speed\n",
  2537. GST_plugins_a2s (address),
  2538. GNUNET_i2s (&address->peer),
  2539. (unsigned int) ntohl (bandwidth_in.value__),
  2540. (unsigned int) ntohl (bandwidth_out.value__));
  2541. /* Perform blacklist check */
  2542. blc_ctx = GNUNET_new (struct BlacklistCheckSwitchContext);
  2543. blc_ctx->address = GNUNET_HELLO_address_copy (address);
  2544. blc_ctx->session = session;
  2545. blc_ctx->bandwidth_in = bandwidth_in;
  2546. blc_ctx->bandwidth_out = bandwidth_out;
  2547. GNUNET_CONTAINER_DLL_insert (pending_bc_head,
  2548. pending_bc_tail,
  2549. blc_ctx);
  2550. if (NULL != (blc = GST_blacklist_test_allowed (&address->peer,
  2551. address->transport_name,
  2552. &switch_address_bl_check_cont,
  2553. blc_ctx)))
  2554. {
  2555. blc_ctx->blc = blc;
  2556. }
  2557. }
  2558. /**
  2559. * Function called to send network utilization data to ATS for
  2560. * each active connection.
  2561. *
  2562. * @param cls NULL
  2563. * @param key peer we send utilization data for
  2564. * @param value the `struct NeighbourMapEntry *` with data to send
  2565. * @return #GNUNET_OK (continue to iterate)
  2566. */
  2567. static int
  2568. send_utilization_data (void *cls,
  2569. const struct GNUNET_PeerIdentity *key,
  2570. void *value)
  2571. {
  2572. struct NeighbourMapEntry *n = value;
  2573. uint32_t bps_in;
  2574. uint32_t bps_out;
  2575. struct GNUNET_TIME_Relative delta;
  2576. if ( (GNUNET_YES != test_connected (n)) ||
  2577. (NULL == n->primary_address.address) )
  2578. return GNUNET_OK;
  2579. delta = GNUNET_TIME_absolute_get_difference (n->last_util_transmission,
  2580. GNUNET_TIME_absolute_get ());
  2581. bps_in = 0;
  2582. if ((0 != n->util_total_bytes_recv) && (0 != delta.rel_value_us))
  2583. bps_in = (1000LL * 1000LL * n->util_total_bytes_recv) / (delta.rel_value_us);
  2584. bps_out = 0;
  2585. if ((0 != n->util_total_bytes_sent) && (0 != delta.rel_value_us))
  2586. bps_out = (1000LL * 1000LL * n->util_total_bytes_sent) / delta.rel_value_us;
  2587. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2588. "`%s' total: received %u Bytes/s, sent %u Bytes/s\n",
  2589. GNUNET_i2s (key),
  2590. bps_in,
  2591. bps_out);
  2592. GST_ats_update_utilization (n->primary_address.address,
  2593. bps_in,
  2594. bps_out);
  2595. n->util_total_bytes_recv = 0;
  2596. n->util_total_bytes_sent = 0;
  2597. n->last_util_transmission = GNUNET_TIME_absolute_get ();
  2598. return GNUNET_OK;
  2599. }
  2600. /**
  2601. * Task transmitting utilization in a regular interval
  2602. *
  2603. * @param cls the 'struct NeighbourMapEntry' for which we are running
  2604. * @param tc scheduler context (unused)
  2605. */
  2606. static void
  2607. utilization_transmission (void *cls,
  2608. const struct GNUNET_SCHEDULER_TaskContext *tc)
  2609. {
  2610. util_transmission_tk = NULL;
  2611. GNUNET_CONTAINER_multipeermap_iterate (neighbours,
  2612. &send_utilization_data,
  2613. NULL);
  2614. util_transmission_tk
  2615. = GNUNET_SCHEDULER_add_delayed (UTIL_TRANSMISSION_INTERVAL,
  2616. &utilization_transmission,
  2617. NULL);
  2618. }
  2619. /**
  2620. * Track information about data we received from the
  2621. * given address (used to notify ATS about our utilization
  2622. * of allocated resources).
  2623. *
  2624. * @param address the address we got data from
  2625. * @param message the message we received (really only the size is used)
  2626. */
  2627. void
  2628. GST_neighbours_notify_data_recv (const struct GNUNET_HELLO_Address *address,
  2629. const struct GNUNET_MessageHeader *message)
  2630. {
  2631. struct NeighbourMapEntry *n;
  2632. n = lookup_neighbour (&address->peer);
  2633. if (NULL == n)
  2634. return;
  2635. n->util_total_bytes_recv += ntohs (message->size);
  2636. }
  2637. /**
  2638. * Track information about data we transmitted using the given @a
  2639. * address and @a session (used to notify ATS about our utilization of
  2640. * allocated resources).
  2641. *
  2642. * @param address the address we transmitted data to
  2643. * @param session session we used to transmit data
  2644. * @param message the message we sent (really only the size is used)
  2645. */
  2646. void
  2647. GST_neighbours_notify_data_sent (const struct GNUNET_HELLO_Address *address,
  2648. struct Session *session,
  2649. size_t size)
  2650. {
  2651. struct NeighbourMapEntry *n;
  2652. n = lookup_neighbour (&address->peer);
  2653. if (NULL == n)
  2654. return;
  2655. if (n->primary_address.session != session)
  2656. return;
  2657. n->util_total_bytes_sent += size;
  2658. }
  2659. /**
  2660. * Master task run for every neighbour. Performs all of the time-related
  2661. * activities (keep alive, send next message, disconnect if idle, finish
  2662. * clean up after disconnect).
  2663. *
  2664. * @param cls the 'struct NeighbourMapEntry' for which we are running
  2665. * @param tc scheduler context (unused)
  2666. */
  2667. static void
  2668. master_task (void *cls,
  2669. const struct GNUNET_SCHEDULER_TaskContext *tc)
  2670. {
  2671. struct NeighbourMapEntry *n = cls;
  2672. struct GNUNET_TIME_Relative delay;
  2673. n->task = NULL;
  2674. delay = GNUNET_TIME_absolute_get_remaining (n->timeout);
  2675. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2676. "Master task runs for neighbour `%s' in state %s with timeout in %s\n",
  2677. GNUNET_i2s (&n->id),
  2678. GNUNET_TRANSPORT_ps2s(n->state),
  2679. GNUNET_STRINGS_relative_time_to_string (delay,
  2680. GNUNET_YES));
  2681. switch (n->state)
  2682. {
  2683. case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
  2684. /* invalid state for master task, clean up */
  2685. GNUNET_break (0);
  2686. free_neighbour (n);
  2687. return;
  2688. case GNUNET_TRANSPORT_PS_INIT_ATS:
  2689. if (0 == delay.rel_value_us)
  2690. {
  2691. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2692. "Connection to `%s' timed out waiting for ATS to provide address\n",
  2693. GNUNET_i2s (&n->id));
  2694. free_neighbour (n);
  2695. return;
  2696. }
  2697. break;
  2698. case GNUNET_TRANSPORT_PS_SYN_SENT:
  2699. if (0 == delay.rel_value_us)
  2700. {
  2701. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2702. "Connection to `%s' timed out waiting for other peer to send SYN_ACK\n",
  2703. GNUNET_i2s (&n->id));
  2704. /* Remove address and request and additional one */
  2705. unset_primary_address (n);
  2706. set_state_and_timeout (n,
  2707. GNUNET_TRANSPORT_PS_INIT_ATS,
  2708. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  2709. return;
  2710. }
  2711. break;
  2712. case GNUNET_TRANSPORT_PS_SYN_RECV_ATS:
  2713. if (0 == delay.rel_value_us)
  2714. {
  2715. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2716. "Connection to `%s' timed out waiting ATS to provide address to use for SYN_ACK\n",
  2717. GNUNET_i2s (&n->id));
  2718. free_neighbour (n);
  2719. return;
  2720. }
  2721. break;
  2722. case GNUNET_TRANSPORT_PS_SYN_RECV_ACK:
  2723. if (0 == delay.rel_value_us)
  2724. {
  2725. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2726. "Connection to `%s' timed out waiting for other peer to send ACK\n",
  2727. GNUNET_i2s (&n->id));
  2728. disconnect_neighbour (n);
  2729. return;
  2730. }
  2731. break;
  2732. case GNUNET_TRANSPORT_PS_CONNECTED:
  2733. if (0 == delay.rel_value_us)
  2734. {
  2735. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2736. "Connection to `%s' timed out, missing KEEPALIVE_RESPONSEs\n",
  2737. GNUNET_i2s (&n->id));
  2738. disconnect_neighbour (n);
  2739. return;
  2740. }
  2741. try_transmission_to_peer (n);
  2742. send_keepalive (n);
  2743. break;
  2744. case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
  2745. if (0 == delay.rel_value_us)
  2746. {
  2747. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2748. "Connection to `%s' timed out, waiting for ATS replacement address\n",
  2749. GNUNET_i2s (&n->id));
  2750. disconnect_neighbour (n);
  2751. return;
  2752. }
  2753. break;
  2754. case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
  2755. if (0 == delay.rel_value_us)
  2756. {
  2757. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2758. "Connection to `%s' timed out, waiting for other peer to SYN_ACK replacement address\n",
  2759. GNUNET_i2s (&n->id));
  2760. disconnect_neighbour (n);
  2761. return;
  2762. }
  2763. break;
  2764. case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
  2765. if (0 == delay.rel_value_us)
  2766. {
  2767. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2768. "Switch failed, cleaning up alternative address\n");
  2769. free_address (&n->alternative_address);
  2770. set_state_and_timeout (n,
  2771. GNUNET_TRANSPORT_PS_CONNECTED,
  2772. GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT));
  2773. }
  2774. try_transmission_to_peer (n);
  2775. send_keepalive (n);
  2776. break;
  2777. case GNUNET_TRANSPORT_PS_DISCONNECT:
  2778. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2779. "Cleaning up connection to `%s' after sending DISCONNECT\n",
  2780. GNUNET_i2s (&n->id));
  2781. free_neighbour (n);
  2782. return;
  2783. case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
  2784. /* how did we get here!? */
  2785. GNUNET_assert (0);
  2786. break;
  2787. default:
  2788. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2789. "Unhandled state `%s'\n",
  2790. GNUNET_TRANSPORT_ps2s (n->state));
  2791. GNUNET_break (0);
  2792. break;
  2793. }
  2794. delay = GNUNET_TIME_absolute_get_remaining (n->timeout);
  2795. if ( (GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT == n->state) ||
  2796. (GNUNET_TRANSPORT_PS_CONNECTED == n->state) )
  2797. {
  2798. /* if we are *now* in one of the two states, we're sending
  2799. keep alive messages, so we need to consider the keepalive
  2800. delay, not just the connection timeout */
  2801. delay = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (n->keep_alive_time),
  2802. delay);
  2803. }
  2804. if (NULL == n->task)
  2805. n->task = GNUNET_SCHEDULER_add_delayed (delay,
  2806. &master_task,
  2807. n);
  2808. }
  2809. /**
  2810. * Send a ACK message to the neighbour to confirm that we
  2811. * got his SYN_ACK.
  2812. *
  2813. * @param n neighbour to send the ACK to
  2814. */
  2815. static void
  2816. send_session_ack_message (struct NeighbourMapEntry *n)
  2817. {
  2818. struct GNUNET_MessageHeader msg;
  2819. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2820. "Sending ACK message to peer `%s'\n",
  2821. GNUNET_i2s (&n->id));
  2822. msg.size = htons (sizeof (struct GNUNET_MessageHeader));
  2823. msg.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK);
  2824. (void) send_with_session (n,
  2825. &msg,
  2826. sizeof (struct GNUNET_MessageHeader),
  2827. UINT32_MAX,
  2828. GNUNET_TIME_UNIT_FOREVER_REL,
  2829. GNUNET_NO,
  2830. NULL, NULL);
  2831. }
  2832. /**
  2833. * We received a 'SESSION_SYN_ACK' message from the other peer.
  2834. * Consider switching to it.
  2835. *
  2836. * @param message possibly a `struct SessionConnectMessage` (check format)
  2837. * @param peer identity of the peer to switch the address for
  2838. * @param address address of the other peer, NULL if other peer
  2839. * connected to us
  2840. * @param session session to use (or NULL)
  2841. * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error
  2842. */
  2843. int
  2844. GST_neighbours_handle_session_syn_ack (const struct GNUNET_MessageHeader *message,
  2845. const struct GNUNET_HELLO_Address *address,
  2846. struct Session *session)
  2847. {
  2848. const struct TransportSynMessage *scm;
  2849. struct GNUNET_TIME_Absolute ts;
  2850. struct NeighbourMapEntry *n;
  2851. if (ntohs (message->size) != sizeof (struct TransportSynMessage))
  2852. {
  2853. GNUNET_break_op (0);
  2854. return GNUNET_SYSERR;
  2855. }
  2856. GNUNET_STATISTICS_update (GST_stats,
  2857. gettext_noop
  2858. ("# SYN_ACK messages received"),
  2859. 1, GNUNET_NO);
  2860. scm = (const struct TransportSynMessage *) message;
  2861. GNUNET_break_op (ntohl (scm->reserved) == 0);
  2862. if (NULL == (n = lookup_neighbour (&address->peer)))
  2863. {
  2864. GNUNET_STATISTICS_update (GST_stats,
  2865. gettext_noop
  2866. ("# unexpected SYN_ACK messages (no peer)"),
  2867. 1, GNUNET_NO);
  2868. return GNUNET_SYSERR;
  2869. }
  2870. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2871. "Received SYN_ACK message from peer `%s' in state %s/%s\n",
  2872. GNUNET_i2s (&address->peer),
  2873. GNUNET_TRANSPORT_ps2s (n->state),
  2874. print_ack_state (n->ack_state));
  2875. ts = GNUNET_TIME_absolute_ntoh (scm->timestamp);
  2876. switch (n->state)
  2877. {
  2878. case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
  2879. GNUNET_break (0);
  2880. free_neighbour (n);
  2881. return GNUNET_SYSERR;
  2882. case GNUNET_TRANSPORT_PS_INIT_ATS:
  2883. GNUNET_STATISTICS_update (GST_stats,
  2884. gettext_noop ("# unexpected SYN_ACK messages (not ready)"),
  2885. 1,
  2886. GNUNET_NO);
  2887. break;
  2888. case GNUNET_TRANSPORT_PS_SYN_SENT:
  2889. if (ts.abs_value_us != n->primary_address.connect_timestamp.abs_value_us)
  2890. {
  2891. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  2892. "SYN_ACK ignored as the timestamp does not match our SYN request\n");
  2893. return GNUNET_OK;
  2894. }
  2895. set_state_and_timeout (n,
  2896. GNUNET_TRANSPORT_PS_CONNECTED,
  2897. GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT));
  2898. set_primary_address (n,
  2899. n->primary_address.address,
  2900. n->primary_address.session,
  2901. n->primary_address.bandwidth_in,
  2902. n->primary_address.bandwidth_out);
  2903. send_session_ack_message (n);
  2904. break;
  2905. case GNUNET_TRANSPORT_PS_SYN_RECV_ATS:
  2906. case GNUNET_TRANSPORT_PS_SYN_RECV_ACK:
  2907. GNUNET_STATISTICS_update (GST_stats,
  2908. gettext_noop ("# unexpected SYN_ACK messages (not ready)"),
  2909. 1,
  2910. GNUNET_NO);
  2911. break;
  2912. case GNUNET_TRANSPORT_PS_CONNECTED:
  2913. /* duplicate SYN_ACK, let's answer by duplicate ACK just in case */
  2914. send_session_ack_message (n);
  2915. break;
  2916. case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
  2917. /* we didn't expect any SYN_ACK, as we are waiting for ATS
  2918. to give us a new address... */
  2919. GNUNET_STATISTICS_update (GST_stats,
  2920. gettext_noop ("# unexpected SYN_ACK messages (waiting on ATS)"),
  2921. 1,
  2922. GNUNET_NO);
  2923. break;
  2924. case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
  2925. /* Reconnecting with new address address worked; go back to connected! */
  2926. set_state_and_timeout (n,
  2927. GNUNET_TRANSPORT_PS_CONNECTED,
  2928. GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT));
  2929. send_session_ack_message (n);
  2930. break;
  2931. case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
  2932. /* new address worked; adopt it and go back to connected! */
  2933. set_state_and_timeout (n,
  2934. GNUNET_TRANSPORT_PS_CONNECTED,
  2935. GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT));
  2936. GNUNET_break (GNUNET_NO == n->alternative_address.ats_active);
  2937. /* Set primary addresses */
  2938. set_primary_address (n,
  2939. n->alternative_address.address,
  2940. n->alternative_address.session,
  2941. n->alternative_address.bandwidth_in,
  2942. n->alternative_address.bandwidth_out);
  2943. GNUNET_STATISTICS_update (GST_stats,
  2944. gettext_noop ("# Successful attempts to switch addresses"),
  2945. 1,
  2946. GNUNET_NO);
  2947. GNUNET_HELLO_address_free (n->alternative_address.address);
  2948. memset (&n->alternative_address,
  2949. 0,
  2950. sizeof (n->alternative_address));
  2951. send_session_ack_message (n);
  2952. break;
  2953. case GNUNET_TRANSPORT_PS_DISCONNECT:
  2954. GNUNET_STATISTICS_update (GST_stats,
  2955. gettext_noop
  2956. ("# unexpected SYN_ACK messages (disconnecting)"),
  2957. 1, GNUNET_NO);
  2958. return GNUNET_SYSERR;
  2959. case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
  2960. GNUNET_assert (0);
  2961. break;
  2962. default:
  2963. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2964. "Unhandled state `%s'\n",
  2965. GNUNET_TRANSPORT_ps2s (n->state));
  2966. GNUNET_break (0);
  2967. return GNUNET_SYSERR;
  2968. }
  2969. return GNUNET_OK;
  2970. }
  2971. /**
  2972. * A session was terminated. Take note; if needed, try to get
  2973. * an alternative address from ATS.
  2974. *
  2975. * @param peer identity of the peer where the session died
  2976. * @param session session that is gone
  2977. * @return #GNUNET_YES if this was a session used, #GNUNET_NO if
  2978. * this session was not in use
  2979. */
  2980. int
  2981. GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer,
  2982. struct Session *session)
  2983. {
  2984. struct NeighbourMapEntry *n;
  2985. struct BlackListCheckContext *bcc;
  2986. struct BlackListCheckContext *bcc_next;
  2987. /* make sure to cancel all ongoing blacklist checks involving 'session' */
  2988. bcc_next = bc_head;
  2989. while (NULL != (bcc = bcc_next))
  2990. {
  2991. bcc_next = bcc->next;
  2992. if (bcc->na.session == session)
  2993. {
  2994. if (NULL != bcc->bc)
  2995. GST_blacklist_test_cancel (bcc->bc);
  2996. GNUNET_HELLO_address_free (bcc->na.address);
  2997. GNUNET_CONTAINER_DLL_remove (bc_head,
  2998. bc_tail,
  2999. bcc);
  3000. GNUNET_free (bcc);
  3001. }
  3002. }
  3003. if (NULL == (n = lookup_neighbour (peer)))
  3004. return GNUNET_NO; /* can't affect us */
  3005. if (session != n->primary_address.session)
  3006. {
  3007. /* Free alternative address */
  3008. if (session == n->alternative_address.session)
  3009. {
  3010. if (GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT == n->state)
  3011. set_state_and_timeout (n,
  3012. GNUNET_TRANSPORT_PS_CONNECTED,
  3013. n->timeout);
  3014. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3015. "Session died, cleaning up alternative address\n");
  3016. free_address (&n->alternative_address);
  3017. }
  3018. return GNUNET_NO; /* doesn't affect us further */
  3019. }
  3020. n->expect_latency_response = GNUNET_NO;
  3021. /* The session for neighbour's primary address died */
  3022. switch (n->state)
  3023. {
  3024. case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
  3025. GNUNET_break (0);
  3026. free_neighbour (n);
  3027. return GNUNET_YES;
  3028. case GNUNET_TRANSPORT_PS_INIT_ATS:
  3029. GNUNET_break (0);
  3030. free_neighbour (n);
  3031. return GNUNET_YES;
  3032. case GNUNET_TRANSPORT_PS_SYN_SENT:
  3033. /* The session used to send the SYN terminated:
  3034. * this implies a connect error*/
  3035. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  3036. "Failed to send SYN in %s with `%s' %p: session terminated\n",
  3037. "CONNECT_SENT",
  3038. GST_plugins_a2s (n->primary_address.address),
  3039. n->primary_address.session,
  3040. GNUNET_i2s (peer));
  3041. /* Destroy the address since it cannot be used */
  3042. unset_primary_address (n);
  3043. set_state_and_timeout (n,
  3044. GNUNET_TRANSPORT_PS_INIT_ATS,
  3045. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  3046. break;
  3047. case GNUNET_TRANSPORT_PS_SYN_RECV_ATS:
  3048. case GNUNET_TRANSPORT_PS_SYN_RECV_ACK:
  3049. /* error on inbound session; free neighbour entirely */
  3050. free_neighbour (n);
  3051. return GNUNET_YES;
  3052. case GNUNET_TRANSPORT_PS_CONNECTED:
  3053. /* Our primary connection died, try a fast reconnect */
  3054. unset_primary_address (n);
  3055. set_state_and_timeout (n,
  3056. GNUNET_TRANSPORT_PS_RECONNECT_ATS,
  3057. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  3058. break;
  3059. case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
  3060. /* we don't have an address, how can it go down? */
  3061. GNUNET_break (0);
  3062. break;
  3063. case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
  3064. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  3065. "Failed to send SYN in %s with `%s' %p: session terminated\n",
  3066. "RECONNECT_SENT",
  3067. GST_plugins_a2s (n->primary_address.address),
  3068. n->primary_address.session,
  3069. GNUNET_i2s (peer));
  3070. /* Destroy the address since it cannot be used */
  3071. unset_primary_address (n);
  3072. set_state_and_timeout (n,
  3073. GNUNET_TRANSPORT_PS_RECONNECT_ATS,
  3074. GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT));
  3075. break;
  3076. case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
  3077. /* primary went down while we were waiting for SYN_ACK on secondary;
  3078. secondary as primary */
  3079. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3080. "Connection `%s' %p to peer `%s' was terminated while switching, "
  3081. "switching to alternative address `%s' %p\n",
  3082. GST_plugins_a2s (n->primary_address.address),
  3083. n->primary_address.session,
  3084. GNUNET_i2s (peer),
  3085. GST_plugins_a2s (n->alternative_address.address),
  3086. n->alternative_address.session);
  3087. /* Destroy the inbound address since it cannot be used */
  3088. free_address (&n->primary_address);
  3089. n->primary_address = n->alternative_address;
  3090. memset (&n->alternative_address,
  3091. 0,
  3092. sizeof (struct NeighbourAddress));
  3093. set_state_and_timeout (n,
  3094. GNUNET_TRANSPORT_PS_RECONNECT_SENT,
  3095. GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT));
  3096. break;
  3097. case GNUNET_TRANSPORT_PS_DISCONNECT:
  3098. unset_primary_address (n);
  3099. break;
  3100. case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
  3101. /* neighbour was freed and plugins told to terminate session */
  3102. return GNUNET_NO;
  3103. default:
  3104. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  3105. "Unhandled state `%s'\n",
  3106. GNUNET_TRANSPORT_ps2s (n->state));
  3107. GNUNET_break (0);
  3108. break;
  3109. }
  3110. if (NULL != n->task)
  3111. GNUNET_SCHEDULER_cancel (n->task);
  3112. n->task = GNUNET_SCHEDULER_add_now (&master_task, n);
  3113. return GNUNET_YES;
  3114. }
  3115. /**
  3116. * We received a 'ACK' message from the other peer.
  3117. * If we sent a 'SYN_ACK' last, this means we are now
  3118. * connected. Otherwise, do nothing.
  3119. *
  3120. * @param message possibly a 'struct SessionConnectMessage' (check format)
  3121. * @param address address of the other peer
  3122. * @param session session to use (or NULL)
  3123. * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error
  3124. */
  3125. int
  3126. GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message,
  3127. const struct GNUNET_HELLO_Address *address,
  3128. struct Session *session)
  3129. {
  3130. struct NeighbourMapEntry *n;
  3131. if (ntohs (message->size) != sizeof (struct GNUNET_MessageHeader))
  3132. {
  3133. GNUNET_break_op (0);
  3134. return GNUNET_SYSERR;
  3135. }
  3136. GNUNET_STATISTICS_update (GST_stats,
  3137. gettext_noop ("# ACK messages received"),
  3138. 1,
  3139. GNUNET_NO);
  3140. if (NULL == (n = lookup_neighbour (&address->peer)))
  3141. {
  3142. GNUNET_break_op (0);
  3143. return GNUNET_SYSERR;
  3144. }
  3145. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3146. "Received ACK for peer `%s' in state %s/%s\n",
  3147. GNUNET_i2s (&address->peer),
  3148. GNUNET_TRANSPORT_ps2s (n->state),
  3149. print_ack_state (n->ack_state));
  3150. /* Check if we are in a plausible state for having sent
  3151. a SYN_ACK. If not, return, otherwise break.
  3152. The remote peers sends a ACK as a response for a SYN_ACK
  3153. message.
  3154. We expect a ACK:
  3155. - If a remote peer has sent a SYN, we responded with a SYN_ACK and
  3156. now wait for the ACK to finally be connected
  3157. - If we sent a SYN_ACK to this peer before */
  3158. if ( (GNUNET_TRANSPORT_PS_SYN_RECV_ACK != n->state) &&
  3159. (ACK_SEND_ACK != n->ack_state))
  3160. {
  3161. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  3162. "Received unexpected ACK message from peer `%s' in state %s/%s\n",
  3163. GNUNET_i2s (&address->peer),
  3164. GNUNET_TRANSPORT_ps2s (n->state),
  3165. print_ack_state (n->ack_state));
  3166. GNUNET_STATISTICS_update (GST_stats,
  3167. gettext_noop ("# unexpected ACK messages"), 1,
  3168. GNUNET_NO);
  3169. return GNUNET_OK;
  3170. }
  3171. if (GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT == n->state)
  3172. {
  3173. /* We tried to switch addresses while being connect. We explicitly wait
  3174. * for a SYN_ACK before going to GNUNET_TRANSPORT_PS_CONNECTED,
  3175. * so we do not want to set the address as in use! */
  3176. return GNUNET_OK;
  3177. }
  3178. set_state_and_timeout (n,
  3179. GNUNET_TRANSPORT_PS_CONNECTED,
  3180. GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT));
  3181. /* Set primary address to used */
  3182. set_primary_address (n,
  3183. n->primary_address.address,
  3184. n->primary_address.session,
  3185. n->primary_address.bandwidth_in,
  3186. n->primary_address.bandwidth_out);
  3187. return GNUNET_OK;
  3188. }
  3189. /**
  3190. * Test if we're connected to the given peer.
  3191. *
  3192. * @param target peer to test
  3193. * @return #GNUNET_YES if we are connected, #GNUNET_NO if not
  3194. */
  3195. int
  3196. GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target)
  3197. {
  3198. return test_connected (lookup_neighbour (target));
  3199. }
  3200. /**
  3201. * Change the incoming quota for the given peer.
  3202. *
  3203. * @param neighbour identity of peer to change qutoa for
  3204. * @param quota new quota
  3205. */
  3206. void
  3207. GST_neighbours_set_incoming_quota (const struct GNUNET_PeerIdentity *neighbour,
  3208. struct GNUNET_BANDWIDTH_Value32NBO quota)
  3209. {
  3210. struct NeighbourMapEntry *n;
  3211. if (NULL == (n = lookup_neighbour (neighbour)))
  3212. {
  3213. GNUNET_STATISTICS_update (GST_stats,
  3214. gettext_noop
  3215. ("# SET QUOTA messages ignored (no such peer)"),
  3216. 1, GNUNET_NO);
  3217. return;
  3218. }
  3219. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3220. "Setting inbound quota of %u Bps for peer `%s' to all clients\n",
  3221. ntohl (quota.value__), GNUNET_i2s (&n->id));
  3222. GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker, quota);
  3223. if (0 != ntohl (quota.value__))
  3224. return;
  3225. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  3226. "Disconnecting peer `%4s' due to SET_QUOTA\n",
  3227. GNUNET_i2s (&n->id));
  3228. if (GNUNET_YES == test_connected (n))
  3229. GNUNET_STATISTICS_update (GST_stats,
  3230. gettext_noop ("# disconnects due to quota of 0"),
  3231. 1, GNUNET_NO);
  3232. disconnect_neighbour (n);
  3233. }
  3234. /**
  3235. * Task to asynchronously run #free_neighbour().
  3236. *
  3237. * @param cls the `struct NeighbourMapEntry` to free
  3238. * @param tc unused
  3239. */
  3240. static void
  3241. delayed_disconnect (void *cls,
  3242. const struct GNUNET_SCHEDULER_TaskContext* tc)
  3243. {
  3244. struct NeighbourMapEntry *n = cls;
  3245. n->delayed_disconnect_task = NULL;
  3246. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  3247. "Disconnecting by request from peer %s\n",
  3248. GNUNET_i2s (&n->id));
  3249. free_neighbour (n);
  3250. }
  3251. /**
  3252. * We received a disconnect message from the given peer,
  3253. * validate and process.
  3254. *
  3255. * @param peer sender of the message
  3256. * @param msg the disconnect message
  3257. */
  3258. void
  3259. GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity *peer,
  3260. const struct GNUNET_MessageHeader *msg)
  3261. {
  3262. struct NeighbourMapEntry *n;
  3263. const struct SessionDisconnectMessage *sdm;
  3264. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  3265. "Received DISCONNECT message from peer `%s'\n",
  3266. GNUNET_i2s (peer));
  3267. if (ntohs (msg->size) != sizeof (struct SessionDisconnectMessage))
  3268. {
  3269. GNUNET_break_op (0);
  3270. GNUNET_STATISTICS_update (GST_stats,
  3271. gettext_noop
  3272. ("# disconnect messages ignored (malformed)"), 1,
  3273. GNUNET_NO);
  3274. return;
  3275. }
  3276. GNUNET_STATISTICS_update (GST_stats,
  3277. gettext_noop
  3278. ("# DISCONNECT messages received"),
  3279. 1, GNUNET_NO);
  3280. sdm = (const struct SessionDisconnectMessage *) msg;
  3281. if (NULL == (n = lookup_neighbour (peer)))
  3282. {
  3283. /* gone already */
  3284. return;
  3285. }
  3286. if (GNUNET_TIME_absolute_ntoh (sdm->timestamp).abs_value_us <= n->connect_ack_timestamp.abs_value_us)
  3287. {
  3288. GNUNET_STATISTICS_update (GST_stats,
  3289. gettext_noop ("# disconnect messages ignored (timestamp)"),
  3290. 1,
  3291. GNUNET_NO);
  3292. return;
  3293. }
  3294. if (0 != memcmp (peer,
  3295. &sdm->public_key,
  3296. sizeof (struct GNUNET_PeerIdentity)))
  3297. {
  3298. GNUNET_break_op (0);
  3299. return;
  3300. }
  3301. if (ntohl (sdm->purpose.size) !=
  3302. sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
  3303. sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) +
  3304. sizeof (struct GNUNET_TIME_AbsoluteNBO))
  3305. {
  3306. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3307. "DISCONNECT message from peer `%s' has invalid size\n",
  3308. GNUNET_i2s (peer));
  3309. GNUNET_break_op (0);
  3310. return;
  3311. }
  3312. if (GNUNET_OK !=
  3313. GNUNET_CRYPTO_eddsa_verify (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT,
  3314. &sdm->purpose,
  3315. &sdm->signature,
  3316. &sdm->public_key))
  3317. {
  3318. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3319. "DISCONNECT message from peer `%s' cannot be verified \n",
  3320. GNUNET_i2s (peer));
  3321. GNUNET_break_op (0);
  3322. return;
  3323. }
  3324. n->delayed_disconnect_task = GNUNET_SCHEDULER_add_now (&delayed_disconnect, n);
  3325. }
  3326. /**
  3327. * Closure for the #neighbours_iterate() function.
  3328. */
  3329. struct IteratorContext
  3330. {
  3331. /**
  3332. * Function to call on each connected neighbour.
  3333. */
  3334. GST_NeighbourIterator cb;
  3335. /**
  3336. * Closure for @e cb.
  3337. */
  3338. void *cb_cls;
  3339. };
  3340. /**
  3341. * Call the callback from the closure for each neighbour.
  3342. *
  3343. * @param cls the `struct IteratorContext`
  3344. * @param key the hash of the public key of the neighbour
  3345. * @param value the `struct NeighbourMapEntry`
  3346. * @return #GNUNET_OK (continue to iterate)
  3347. */
  3348. static int
  3349. neighbours_iterate (void *cls,
  3350. const struct GNUNET_PeerIdentity *key,
  3351. void *value)
  3352. {
  3353. struct IteratorContext *ic = cls;
  3354. struct NeighbourMapEntry *n = value;
  3355. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
  3356. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
  3357. if (NULL != n->primary_address.address)
  3358. {
  3359. bandwidth_in = n->primary_address.bandwidth_in;
  3360. bandwidth_out = n->primary_address.bandwidth_out;
  3361. }
  3362. else
  3363. {
  3364. bandwidth_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
  3365. bandwidth_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT;
  3366. }
  3367. ic->cb (ic->cb_cls,
  3368. &n->id,
  3369. n->primary_address.address,
  3370. n->state,
  3371. n->timeout,
  3372. bandwidth_in, bandwidth_out);
  3373. return GNUNET_OK;
  3374. }
  3375. /**
  3376. * Iterate over all connected neighbours.
  3377. *
  3378. * @param cb function to call
  3379. * @param cb_cls closure for cb
  3380. */
  3381. void
  3382. GST_neighbours_iterate (GST_NeighbourIterator cb, void *cb_cls)
  3383. {
  3384. struct IteratorContext ic;
  3385. if (NULL == neighbours)
  3386. return; /* can happen during shutdown */
  3387. ic.cb = cb;
  3388. ic.cb_cls = cb_cls;
  3389. GNUNET_CONTAINER_multipeermap_iterate (neighbours,
  3390. &neighbours_iterate,
  3391. &ic);
  3392. }
  3393. /**
  3394. * If we have an active connection to the given target, it must be shutdown.
  3395. *
  3396. * @param target peer to disconnect from
  3397. */
  3398. void
  3399. GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target)
  3400. {
  3401. struct NeighbourMapEntry *n;
  3402. if (NULL == (n = lookup_neighbour (target)))
  3403. return; /* not active */
  3404. if (GNUNET_YES == test_connected (n))
  3405. GNUNET_STATISTICS_update (GST_stats,
  3406. gettext_noop ("# disconnected from peer upon explicit request"),
  3407. 1,
  3408. GNUNET_NO);
  3409. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  3410. "Forced disconnect from peer %s\n",
  3411. GNUNET_i2s (target));
  3412. disconnect_neighbour (n);
  3413. }
  3414. /**
  3415. * Obtain current address information for the given neighbour.
  3416. *
  3417. * @param peer
  3418. * @return address currently used
  3419. */
  3420. struct GNUNET_HELLO_Address *
  3421. GST_neighbour_get_current_address (const struct GNUNET_PeerIdentity *peer)
  3422. {
  3423. struct NeighbourMapEntry *n;
  3424. n = lookup_neighbour (peer);
  3425. if (NULL == n)
  3426. return NULL;
  3427. return n->primary_address.address;
  3428. }
  3429. /**
  3430. * Initialize the neighbours subsystem.
  3431. *
  3432. * @param max_fds maximum number of fds to use
  3433. */
  3434. void
  3435. GST_neighbours_start (unsigned int max_fds)
  3436. {
  3437. neighbours = GNUNET_CONTAINER_multipeermap_create (NEIGHBOUR_TABLE_SIZE,
  3438. GNUNET_NO);
  3439. util_transmission_tk = GNUNET_SCHEDULER_add_delayed (UTIL_TRANSMISSION_INTERVAL,
  3440. &utilization_transmission,
  3441. NULL);
  3442. }
  3443. /**
  3444. * Disconnect from the given neighbour.
  3445. *
  3446. * @param cls unused
  3447. * @param key hash of neighbour's public key (not used)
  3448. * @param value the 'struct NeighbourMapEntry' of the neighbour
  3449. * @return #GNUNET_OK (continue to iterate)
  3450. */
  3451. static int
  3452. disconnect_all_neighbours (void *cls,
  3453. const struct GNUNET_PeerIdentity *key,
  3454. void *value)
  3455. {
  3456. struct NeighbourMapEntry *n = value;
  3457. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3458. "Disconnecting peer `%4s' during shutdown\n",
  3459. GNUNET_i2s (&n->id));
  3460. free_neighbour (n);
  3461. return GNUNET_OK;
  3462. }
  3463. /**
  3464. * Cleanup the neighbours subsystem.
  3465. */
  3466. void
  3467. GST_neighbours_stop ()
  3468. {
  3469. struct BlacklistCheckSwitchContext *cur;
  3470. struct BlacklistCheckSwitchContext *next;
  3471. if (NULL == neighbours)
  3472. return;
  3473. if (NULL != util_transmission_tk)
  3474. {
  3475. GNUNET_SCHEDULER_cancel (util_transmission_tk);
  3476. util_transmission_tk = NULL;
  3477. }
  3478. GNUNET_CONTAINER_multipeermap_iterate (neighbours,
  3479. &disconnect_all_neighbours,
  3480. NULL);
  3481. GNUNET_CONTAINER_multipeermap_destroy (neighbours);
  3482. neighbours = NULL;
  3483. next = pending_bc_head;
  3484. for (cur = next; NULL != cur; cur = next)
  3485. {
  3486. next = cur->next;
  3487. GNUNET_CONTAINER_DLL_remove (pending_bc_head,
  3488. pending_bc_tail,
  3489. cur);
  3490. if (NULL != cur->blc)
  3491. {
  3492. GST_blacklist_test_cancel (cur->blc);
  3493. cur->blc = NULL;
  3494. }
  3495. if (NULL != cur->address)
  3496. GNUNET_HELLO_address_free (cur->address);
  3497. GNUNET_free (cur);
  3498. }
  3499. }
  3500. /* end of file gnunet-service-transport_neighbours.c */