gnunet-service-dht.c 173 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2009, 2010 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 dht/gnunet-service-dht.c
  19. * @brief GNUnet DHT service
  20. * @author Christian Grothoff
  21. * @author Nathan Evans
  22. */
  23. #include "platform.h"
  24. #include "gnunet_block_lib.h"
  25. #include "gnunet_client_lib.h"
  26. #include "gnunet_getopt_lib.h"
  27. #include "gnunet_os_lib.h"
  28. #include "gnunet_protocols.h"
  29. #include "gnunet_service_lib.h"
  30. #include "gnunet_core_service.h"
  31. #include "gnunet_signal_lib.h"
  32. #include "gnunet_util_lib.h"
  33. #include "gnunet_datacache_lib.h"
  34. #include "gnunet_transport_service.h"
  35. #include "gnunet_hello_lib.h"
  36. #include "gnunet_dht_service.h"
  37. #include "gnunet_statistics_service.h"
  38. #include "dhtlog.h"
  39. #include "dht.h"
  40. #include <fenv.h>
  41. #define PRINT_TABLES GNUNET_NO
  42. #define REAL_DISTANCE GNUNET_NO
  43. #define EXTRA_CHECKS GNUNET_NO
  44. /**
  45. * How many buckets will we allow total.
  46. */
  47. #define MAX_BUCKETS sizeof (GNUNET_HashCode) * 8
  48. /**
  49. * Should the DHT issue FIND_PEER requests to get better routing tables?
  50. */
  51. #define DEFAULT_DO_FIND_PEER GNUNET_YES
  52. /**
  53. * Defines whether find peer requests send their HELLO's outgoing,
  54. * or expect replies to contain hellos.
  55. */
  56. #define FIND_PEER_WITH_HELLO GNUNET_YES
  57. /**
  58. * What is the maximum number of peers in a given bucket.
  59. */
  60. #define DEFAULT_BUCKET_SIZE 4
  61. #define DEFAULT_CORE_QUEUE_SIZE 32
  62. /**
  63. * Minimum number of peers we need for "good" routing,
  64. * any less than this and we will allow messages to
  65. * travel much further through the network!
  66. */
  67. #define MINIMUM_PEER_THRESHOLD 20
  68. #define DHT_MAX_RECENT 1000
  69. #define FIND_PEER_CALC_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
  70. /**
  71. * Default time to wait to send messages on behalf of other peers.
  72. */
  73. #define DHT_DEFAULT_P2P_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
  74. /**
  75. * Default importance for handling messages on behalf of other peers.
  76. */
  77. #define DHT_DEFAULT_P2P_IMPORTANCE 0
  78. /**
  79. * How long to keep recent requests around by default.
  80. */
  81. #define DEFAULT_RECENT_REMOVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
  82. /**
  83. * Default time to wait to send find peer messages sent by the dht service.
  84. */
  85. #define DHT_DEFAULT_FIND_PEER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
  86. /**
  87. * Default importance for find peer messages sent by the dht service.
  88. */
  89. #define DHT_DEFAULT_FIND_PEER_IMPORTANCE 8
  90. /**
  91. * Default replication parameter for find peer messages sent by the dht service.
  92. */
  93. #define DHT_DEFAULT_FIND_PEER_REPLICATION 4
  94. /**
  95. * Default options for find peer requests sent by the dht service.
  96. */
  97. #define DHT_DEFAULT_FIND_PEER_OPTIONS GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
  98. /*#define DHT_DEFAULT_FIND_PEER_OPTIONS GNUNET_DHT_RO_NONE*/
  99. /**
  100. * How long at least to wait before sending another find peer request.
  101. */
  102. #define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
  103. /**
  104. * How long at most to wait before sending another find peer request.
  105. */
  106. #define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 8)
  107. /**
  108. * How often to update our preference levels for peers in our routing tables.
  109. */
  110. #define DHT_DEFAULT_PREFERENCE_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
  111. /**
  112. * How long at most on average will we allow a reply forward to take
  113. * (before we quit sending out new requests)
  114. */
  115. #define MAX_REQUEST_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
  116. /**
  117. * How many initial requests to send out (in true Kademlia fashion)
  118. */
  119. #define DEFAULT_KADEMLIA_REPLICATION 3
  120. /*
  121. * Default frequency for sending malicious get messages
  122. */
  123. #define DEFAULT_MALICIOUS_GET_FREQUENCY 1000 /* Number of milliseconds */
  124. /*
  125. * Default frequency for sending malicious put messages
  126. */
  127. #define DEFAULT_MALICIOUS_PUT_FREQUENCY 1000 /* Default is in milliseconds */
  128. #define DHT_DEFAULT_PING_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 1)
  129. /**
  130. * Real maximum number of hops, at which point we refuse
  131. * to forward the message.
  132. */
  133. #define DEFAULT_MAX_HOPS 10
  134. /**
  135. * How many time differences between requesting a core send and
  136. * the actual callback to remember.
  137. */
  138. #define MAX_REPLY_TIMES 8
  139. enum ConvergenceOptions
  140. {
  141. /**
  142. * Use the linear method for convergence.
  143. */
  144. DHT_CONVERGE_LINEAR,
  145. /**
  146. * Converge using a fast converging square
  147. * function.
  148. */
  149. DHT_CONVERGE_SQUARE,
  150. /**
  151. * Converge using a slower exponential
  152. * function.
  153. */
  154. DHT_CONVERGE_EXPONENTIAL,
  155. /**
  156. * Don't do any special convergence, allow
  157. * the algorithm to hopefully route to closer
  158. * peers more often.
  159. */
  160. DHT_CONVERGE_RANDOM,
  161. /**
  162. * Binary convergence, start routing to closest
  163. * only after set number of hops.
  164. */
  165. DHT_CONVERGE_BINARY
  166. };
  167. /**
  168. * Linked list of messages to send to clients.
  169. */
  170. struct P2PPendingMessage
  171. {
  172. /**
  173. * Pointer to next item in the list
  174. */
  175. struct P2PPendingMessage *next;
  176. /**
  177. * Pointer to previous item in the list
  178. */
  179. struct P2PPendingMessage *prev;
  180. /**
  181. * Message importance level.
  182. */
  183. unsigned int importance;
  184. /**
  185. * Time when this request was scheduled to be sent.
  186. */
  187. struct GNUNET_TIME_Absolute scheduled;
  188. /**
  189. * How long to wait before sending message.
  190. */
  191. struct GNUNET_TIME_Relative timeout;
  192. /**
  193. * Actual message to be sent; // avoid allocation
  194. */
  195. const struct GNUNET_MessageHeader *msg; // msg = (cast) &pm[1]; // memcpy (&pm[1], data, len);
  196. };
  197. /**
  198. * Per-peer information.
  199. */
  200. struct PeerInfo
  201. {
  202. /**
  203. * Next peer entry (DLL)
  204. */
  205. struct PeerInfo *next;
  206. /**
  207. * Prev peer entry (DLL)
  208. */
  209. struct PeerInfo *prev;
  210. /**
  211. * Count of outstanding messages for peer.
  212. */
  213. unsigned int pending_count;
  214. /**
  215. * Head of pending messages to be sent to this peer.
  216. */
  217. struct P2PPendingMessage *head;
  218. /**
  219. * Tail of pending messages to be sent to this peer.
  220. */
  221. struct P2PPendingMessage *tail;
  222. /**
  223. * Core handle for sending messages to this peer.
  224. */
  225. struct GNUNET_CORE_TransmitHandle *th;
  226. /**
  227. * Task for scheduling message sends.
  228. */
  229. GNUNET_SCHEDULER_TaskIdentifier send_task;
  230. /**
  231. * Task for scheduling preference updates
  232. */
  233. GNUNET_SCHEDULER_TaskIdentifier preference_task;
  234. /**
  235. * Preference update context
  236. */
  237. struct GNUNET_CORE_InformationRequestContext *info_ctx;
  238. /**
  239. * What is the identity of the peer?
  240. */
  241. struct GNUNET_PeerIdentity id;
  242. #if 0
  243. /**
  244. * What is the average latency for replies received?
  245. */
  246. struct GNUNET_TIME_Relative latency;
  247. /**
  248. * Transport level distance to peer.
  249. */
  250. unsigned int distance;
  251. #endif
  252. /**
  253. * Holds matching bits from peer to current target,
  254. * used for distance comparisons between peers. May
  255. * be considered a really bad idea.
  256. * FIXME: remove this value (create struct which holds
  257. * a single peerinfo and the matching bits, use
  258. * that to pass to comparator)
  259. */
  260. unsigned int matching_bits;
  261. /**
  262. * Task for scheduling periodic ping messages for this peer.
  263. */
  264. GNUNET_SCHEDULER_TaskIdentifier ping_task;
  265. };
  266. /**
  267. * Peers are grouped into buckets.
  268. */
  269. struct PeerBucket
  270. {
  271. /**
  272. * Head of DLL
  273. */
  274. struct PeerInfo *head;
  275. /**
  276. * Tail of DLL
  277. */
  278. struct PeerInfo *tail;
  279. /**
  280. * Number of peers in the bucket.
  281. */
  282. unsigned int peers_size;
  283. };
  284. /**
  285. * Linked list of messages to send to clients.
  286. */
  287. struct PendingMessage
  288. {
  289. /**
  290. * Pointer to next item in the list
  291. */
  292. struct PendingMessage *next;
  293. /**
  294. * Pointer to previous item in the list
  295. */
  296. struct PendingMessage *prev;
  297. /**
  298. * Actual message to be sent; // avoid allocation
  299. */
  300. const struct GNUNET_MessageHeader *msg; // msg = (cast) &pm[1]; // memcpy (&pm[1], data, len);
  301. };
  302. /**
  303. * Struct containing information about a client,
  304. * handle to connect to it, and any pending messages
  305. * that need to be sent to it.
  306. */
  307. struct ClientList
  308. {
  309. /**
  310. * Linked list of active clients
  311. */
  312. struct ClientList *next;
  313. /**
  314. * The handle to this client
  315. */
  316. struct GNUNET_SERVER_Client *client_handle;
  317. /**
  318. * Handle to the current transmission request, NULL
  319. * if none pending.
  320. */
  321. struct GNUNET_CONNECTION_TransmitHandle *transmit_handle;
  322. /**
  323. * Linked list of pending messages for this client
  324. */
  325. struct PendingMessage *pending_head;
  326. /**
  327. * Tail of linked list of pending messages for this client
  328. */
  329. struct PendingMessage *pending_tail;
  330. };
  331. /**
  332. * Context containing information about a DHT message received.
  333. */
  334. struct DHT_MessageContext
  335. {
  336. /**
  337. * The client this request was received from.
  338. * (NULL if received from another peer)
  339. */
  340. struct ClientList *client;
  341. /**
  342. * The peer this request was received from.
  343. * (NULL if received from local client)
  344. */
  345. const struct GNUNET_PeerIdentity *peer;
  346. /**
  347. * Bloomfilter for this routing request.
  348. */
  349. struct GNUNET_CONTAINER_BloomFilter *bloom;
  350. /**
  351. * extended query (see gnunet_block_lib.h).
  352. */
  353. const void *xquery;
  354. /**
  355. * Bloomfilter to filter out duplicate replies.
  356. */
  357. struct GNUNET_CONTAINER_BloomFilter *reply_bf;
  358. /**
  359. * The key this request was about
  360. */
  361. GNUNET_HashCode key;
  362. /**
  363. * How long should we wait to transmit this request?
  364. */
  365. struct GNUNET_TIME_Relative timeout;
  366. /**
  367. * The unique identifier of this request
  368. */
  369. uint64_t unique_id;
  370. /**
  371. * Number of bytes in xquery.
  372. */
  373. size_t xquery_size;
  374. /**
  375. * Mutator value for the reply_bf, see gnunet_block_lib.h
  376. */
  377. uint32_t reply_bf_mutator;
  378. /**
  379. * Desired replication level
  380. */
  381. uint32_t replication;
  382. /**
  383. * Network size estimate, either ours or the sum of
  384. * those routed to thus far. =~ Log of number of peers
  385. * chosen from for this request.
  386. */
  387. uint32_t network_size;
  388. /**
  389. * Any message options for this request
  390. */
  391. uint32_t msg_options;
  392. /**
  393. * How many hops has the message already traversed?
  394. */
  395. uint32_t hop_count;
  396. /**
  397. * How many peer identities are present in the path history?
  398. */
  399. uint32_t path_history_len;
  400. /**
  401. * Path history.
  402. */
  403. char *path_history;
  404. /**
  405. * How important is this message?
  406. */
  407. unsigned int importance;
  408. /**
  409. * Should we (still) forward the request on to other peers?
  410. */
  411. int do_forward;
  412. /**
  413. * Did we forward this message? (may need to remember it!)
  414. */
  415. int forwarded;
  416. /**
  417. * Are we the closest known peer to this key (out of our neighbors?)
  418. */
  419. int closest;
  420. };
  421. /**
  422. * Record used for remembering what peers are waiting for what
  423. * responses (based on search key).
  424. */
  425. struct DHTRouteSource
  426. {
  427. /**
  428. * This is a DLL.
  429. */
  430. struct DHTRouteSource *next;
  431. /**
  432. * This is a DLL.
  433. */
  434. struct DHTRouteSource *prev;
  435. /**
  436. * Source of the request. Replies should be forwarded to
  437. * this peer.
  438. */
  439. struct GNUNET_PeerIdentity source;
  440. /**
  441. * If this was a local request, remember the client; otherwise NULL.
  442. */
  443. struct ClientList *client;
  444. /**
  445. * Pointer to this nodes heap location (for removal)
  446. */
  447. struct GNUNET_CONTAINER_HeapNode *hnode;
  448. /**
  449. * Back pointer to the record storing this information.
  450. */
  451. struct DHTQueryRecord *record;
  452. /**
  453. * Task to remove this entry on timeout.
  454. */
  455. GNUNET_SCHEDULER_TaskIdentifier delete_task;
  456. /**
  457. * Bloomfilter of peers we have already sent back as
  458. * replies to the initial request. Allows us to not
  459. * forward the same peer multiple times for a find peer
  460. * request.
  461. */
  462. struct GNUNET_CONTAINER_BloomFilter *find_peers_responded;
  463. };
  464. /**
  465. * Entry in the DHT routing table.
  466. */
  467. struct DHTQueryRecord
  468. {
  469. /**
  470. * Head of DLL for result forwarding.
  471. */
  472. struct DHTRouteSource *head;
  473. /**
  474. * Tail of DLL for result forwarding.
  475. */
  476. struct DHTRouteSource *tail;
  477. /**
  478. * Key that the record concerns.
  479. */
  480. GNUNET_HashCode key;
  481. /**
  482. * GET message of this record (what we already forwarded?).
  483. */
  484. //DV_DHT_MESSAGE get; Try to get away with not saving this.
  485. /**
  486. * Bloomfilter of the peers we've replied to so far
  487. */
  488. //struct GNUNET_BloomFilter *bloom_results; Don't think we need this, just remove from DLL on response.
  489. };
  490. /**
  491. * Context used to calculate the number of find peer messages
  492. * per X time units since our last scheduled find peer message
  493. * was sent. If we have seen too many messages, delay or don't
  494. * send our own out.
  495. */
  496. struct FindPeerMessageContext
  497. {
  498. unsigned int count;
  499. struct GNUNET_TIME_Absolute start;
  500. struct GNUNET_TIME_Absolute end;
  501. };
  502. /**
  503. * DHT Routing results structure
  504. */
  505. struct DHTResults
  506. {
  507. /*
  508. * Min heap for removal upon reaching limit
  509. */
  510. struct GNUNET_CONTAINER_Heap *minHeap;
  511. /*
  512. * Hashmap for fast key based lookup
  513. */
  514. struct GNUNET_CONTAINER_MultiHashMap *hashmap;
  515. };
  516. /**
  517. * DHT structure for recent requests.
  518. */
  519. struct RecentRequests
  520. {
  521. /*
  522. * Min heap for removal upon reaching limit
  523. */
  524. struct GNUNET_CONTAINER_Heap *minHeap;
  525. /*
  526. * Hashmap for key based lookup
  527. */
  528. struct GNUNET_CONTAINER_MultiHashMap *hashmap;
  529. };
  530. struct RecentRequest
  531. {
  532. /**
  533. * Position of this node in the min heap.
  534. */
  535. struct GNUNET_CONTAINER_HeapNode *heap_node;
  536. /**
  537. * Bloomfilter containing entries for peers
  538. * we forwarded this request to.
  539. */
  540. struct GNUNET_CONTAINER_BloomFilter *bloom;
  541. /**
  542. * Timestamp of this request, for ordering
  543. * the min heap.
  544. */
  545. struct GNUNET_TIME_Absolute timestamp;
  546. /**
  547. * Key of this request.
  548. */
  549. GNUNET_HashCode key;
  550. /**
  551. * Unique identifier for this request.
  552. */
  553. uint64_t uid;
  554. /**
  555. * Task to remove this entry on timeout.
  556. */
  557. GNUNET_SCHEDULER_TaskIdentifier remove_task;
  558. };
  559. struct RepublishContext
  560. {
  561. /**
  562. * Key to republish.
  563. */
  564. GNUNET_HashCode key;
  565. /**
  566. * Type of the data.
  567. */
  568. unsigned int type;
  569. };
  570. /**
  571. * Which kind of convergence will we be using?
  572. */
  573. static enum ConvergenceOptions converge_option;
  574. /**
  575. * Modifier for the convergence function
  576. */
  577. static float converge_modifier;
  578. /**
  579. * Recent requests by hash/uid and by time inserted.
  580. */
  581. static struct RecentRequests recent;
  582. /**
  583. * Context to use to calculate find peer rates.
  584. */
  585. static struct FindPeerMessageContext find_peer_context;
  586. /**
  587. * Don't use our routing algorithm, always route
  588. * to closest peer; initially send requests to 3
  589. * peers.
  590. */
  591. static unsigned int strict_kademlia;
  592. /**
  593. * Routing option to end routing when closest peer found.
  594. */
  595. static unsigned int stop_on_closest;
  596. /**
  597. * Routing option to end routing when data is found.
  598. */
  599. static unsigned int stop_on_found;
  600. /**
  601. * Whether DHT needs to manage find peer requests, or
  602. * an external force will do it on behalf of the DHT.
  603. */
  604. static unsigned int do_find_peer;
  605. /**
  606. * Once we have stored an item in the DHT, refresh it
  607. * according to our republish interval.
  608. */
  609. static unsigned int do_republish;
  610. /**
  611. * Use exactly the forwarding formula as described in
  612. * the paper if set to GNUNET_YES, otherwise use the
  613. * slightly modified version.
  614. */
  615. static unsigned int paper_forwarding;
  616. /**
  617. * PUT Peer Identities of peers we know about into
  618. * the datacache.
  619. */
  620. static unsigned int put_peer_identities;
  621. /**
  622. * Use the "real" distance metric when selecting the
  623. * next routing hop. Can be less accurate.
  624. */
  625. static unsigned int use_real_distance;
  626. /**
  627. * How many peers have we added since we sent out our last
  628. * find peer request?
  629. */
  630. static unsigned int newly_found_peers;
  631. /**
  632. * Container of active queries we should remember
  633. */
  634. static struct DHTResults forward_list;
  635. /**
  636. * Handle to the datacache service (for inserting/retrieving data)
  637. */
  638. static struct GNUNET_DATACACHE_Handle *datacache;
  639. /**
  640. * Handle for the statistics service.
  641. */
  642. struct GNUNET_STATISTICS_Handle *stats;
  643. /**
  644. * The configuration the DHT service is running with
  645. */
  646. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  647. /**
  648. * Handle to the core service
  649. */
  650. static struct GNUNET_CORE_Handle *coreAPI;
  651. /**
  652. * Handle to the transport service, for getting our hello
  653. */
  654. static struct GNUNET_TRANSPORT_Handle *transport_handle;
  655. /**
  656. * The identity of our peer.
  657. */
  658. static struct GNUNET_PeerIdentity my_identity;
  659. /**
  660. * Short id of the peer, for printing
  661. */
  662. static char *my_short_id;
  663. /**
  664. * Our HELLO
  665. */
  666. static struct GNUNET_MessageHeader *my_hello;
  667. /**
  668. * Task to run when we shut down, cleaning up all our trash
  669. */
  670. static GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
  671. /**
  672. * The lowest currently used bucket.
  673. */
  674. static unsigned int lowest_bucket; /* Initially equal to MAX_BUCKETS - 1 */
  675. /**
  676. * The maximum number of hops before we stop routing messages.
  677. */
  678. static unsigned long long max_hops;
  679. /**
  680. * How often to republish content we have previously stored.
  681. */
  682. static struct GNUNET_TIME_Relative dht_republish_frequency;
  683. /**
  684. * GNUNET_YES to stop at max_hops, GNUNET_NO to heuristically decide when to stop forwarding.
  685. */
  686. static int use_max_hops;
  687. /**
  688. * The buckets (Kademlia routing table, complete with growth).
  689. * Array of size MAX_BUCKET_SIZE.
  690. */
  691. static struct PeerBucket k_buckets[MAX_BUCKETS]; /* From 0 to MAX_BUCKETS - 1 */
  692. /**
  693. * Hash map of all known peers, for easy removal from k_buckets on disconnect.
  694. */
  695. static struct GNUNET_CONTAINER_MultiHashMap *all_known_peers;
  696. /**
  697. * Recently seen find peer requests.
  698. */
  699. static struct GNUNET_CONTAINER_MultiHashMap *recent_find_peer_requests;
  700. /**
  701. * Maximum size for each bucket.
  702. */
  703. static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; /* Initially equal to DEFAULT_BUCKET_SIZE */
  704. /**
  705. * List of active clients.
  706. */
  707. static struct ClientList *client_list;
  708. /**
  709. * Handle to the DHT logger.
  710. */
  711. static struct GNUNET_DHTLOG_Handle *dhtlog_handle;
  712. /*
  713. * Whether or not to send routing debugging information
  714. * to the dht logging server
  715. */
  716. static unsigned int debug_routes;
  717. /*
  718. * Whether or not to send FULL route information to
  719. * logging server
  720. */
  721. static unsigned int debug_routes_extended;
  722. /*
  723. * GNUNET_YES or GNUNET_NO, whether or not to act as
  724. * a malicious node which drops all messages
  725. */
  726. static unsigned int malicious_dropper;
  727. /*
  728. * GNUNET_YES or GNUNET_NO, whether or not to act as
  729. * a malicious node which sends out lots of GETS
  730. */
  731. static unsigned int malicious_getter;
  732. /**
  733. * GNUNET_YES or GNUNET_NO, whether or not to act as
  734. * a malicious node which sends out lots of PUTS
  735. */
  736. static unsigned int malicious_putter;
  737. /**
  738. * Frequency for malicious get requests.
  739. */
  740. static unsigned long long malicious_get_frequency;
  741. /**
  742. * Frequency for malicious put requests.
  743. */
  744. static unsigned long long malicious_put_frequency;
  745. /**
  746. * Kademlia replication
  747. */
  748. static unsigned long long kademlia_replication;
  749. /**
  750. * Reply times for requests, if we are busy, don't send any
  751. * more requests!
  752. */
  753. static struct GNUNET_TIME_Relative reply_times[MAX_REPLY_TIMES];
  754. /**
  755. * Current counter for replies.
  756. */
  757. static unsigned int reply_counter;
  758. /**
  759. * Our handle to the BLOCK library.
  760. */
  761. static struct GNUNET_BLOCK_Context *block_context;
  762. /**
  763. * Forward declaration.
  764. */
  765. static size_t
  766. send_generic_reply (void *cls, size_t size, void *buf);
  767. /** Declare here so retry_core_send is aware of it */
  768. static size_t
  769. core_transmit_notify (void *cls, size_t size, void *buf);
  770. /**
  771. * Convert unique ID to hash code.
  772. *
  773. * @param uid unique ID to convert
  774. * @param hash set to uid (extended with zeros)
  775. */
  776. static void
  777. hash_from_uid (uint64_t uid, GNUNET_HashCode * hash)
  778. {
  779. memset (hash, 0, sizeof (GNUNET_HashCode));
  780. *((uint64_t *) hash) = uid;
  781. }
  782. #if AVG
  783. /**
  784. * Calculate the average send time between messages so that we can
  785. * ignore certain requests if we get too busy.
  786. *
  787. * @return the average time between asking core to send a message
  788. * and when the buffer for copying it is passed
  789. */
  790. static struct GNUNET_TIME_Relative
  791. get_average_send_delay ()
  792. {
  793. unsigned int i;
  794. unsigned int divisor;
  795. struct GNUNET_TIME_Relative average_time;
  796. average_time = GNUNET_TIME_relative_get_zero ();
  797. divisor = 0;
  798. for (i = 0; i < MAX_REPLY_TIMES; i++)
  799. {
  800. average_time = GNUNET_TIME_relative_add (average_time, reply_times[i]);
  801. if (reply_times[i].abs_value == (uint64_t) 0)
  802. continue;
  803. else
  804. divisor++;
  805. }
  806. if (divisor == 0)
  807. {
  808. return average_time;
  809. }
  810. average_time = GNUNET_TIME_relative_divide (average_time, divisor);
  811. fprintf (stderr, "Avg send delay: %u sends is %llu\n", divisor,
  812. (unsigned long long) average_time.abs_value);
  813. return average_time;
  814. }
  815. #endif
  816. /**
  817. * Given the largest send delay, artificially decrease it
  818. * so the next time around we may have a chance at sending
  819. * again.
  820. */
  821. static void
  822. decrease_max_send_delay (struct GNUNET_TIME_Relative max_time)
  823. {
  824. unsigned int i;
  825. for (i = 0; i < MAX_REPLY_TIMES; i++)
  826. {
  827. if (reply_times[i].rel_value == max_time.rel_value)
  828. {
  829. reply_times[i].rel_value = reply_times[i].rel_value / 2;
  830. return;
  831. }
  832. }
  833. }
  834. /**
  835. * Find the maximum send time of the recently sent values.
  836. *
  837. * @return the average time between asking core to send a message
  838. * and when the buffer for copying it is passed
  839. */
  840. static struct GNUNET_TIME_Relative
  841. get_max_send_delay ()
  842. {
  843. unsigned int i;
  844. struct GNUNET_TIME_Relative max_time;
  845. max_time = GNUNET_TIME_relative_get_zero ();
  846. for (i = 0; i < MAX_REPLY_TIMES; i++)
  847. {
  848. if (reply_times[i].rel_value > max_time.rel_value)
  849. max_time.rel_value = reply_times[i].rel_value;
  850. }
  851. #if DEBUG_DHT
  852. if (max_time.rel_value > MAX_REQUEST_TIME.rel_value)
  853. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Max send delay was %llu\n",
  854. (unsigned long long) max_time.rel_value);
  855. #endif
  856. return max_time;
  857. }
  858. static void
  859. increment_stats (const char *value)
  860. {
  861. if (stats != NULL)
  862. {
  863. GNUNET_STATISTICS_update (stats, value, 1, GNUNET_NO);
  864. }
  865. }
  866. static void
  867. decrement_stats (const char *value)
  868. {
  869. if (stats != NULL)
  870. {
  871. GNUNET_STATISTICS_update (stats, value, -1, GNUNET_NO);
  872. }
  873. }
  874. /**
  875. * Try to send another message from our core send list
  876. */
  877. static void
  878. try_core_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  879. {
  880. struct PeerInfo *peer = cls;
  881. struct P2PPendingMessage *pending;
  882. size_t ssize;
  883. peer->send_task = GNUNET_SCHEDULER_NO_TASK;
  884. if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
  885. return;
  886. if (peer->th != NULL)
  887. return; /* Message send already in progress */
  888. pending = peer->head;
  889. if (pending != NULL)
  890. {
  891. ssize = ntohs (pending->msg->size);
  892. #if DEBUG_DHT > 1
  893. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  894. "`%s:%s': Calling notify_transmit_ready with size %d for peer %s\n",
  895. my_short_id, "DHT", ssize, GNUNET_i2s (&peer->id));
  896. #endif
  897. pending->scheduled = GNUNET_TIME_absolute_get ();
  898. reply_counter++;
  899. if (reply_counter >= MAX_REPLY_TIMES)
  900. reply_counter = 0;
  901. peer->th =
  902. GNUNET_CORE_notify_transmit_ready (coreAPI, GNUNET_YES,
  903. pending->importance,
  904. pending->timeout, &peer->id, ssize,
  905. &core_transmit_notify, peer);
  906. if (peer->th == NULL)
  907. increment_stats ("# notify transmit ready failed");
  908. }
  909. }
  910. /**
  911. * Function called to send a request out to another peer.
  912. * Called both for locally initiated requests and those
  913. * received from other peers.
  914. *
  915. * @param msg the encapsulated message
  916. * @param peer the peer to forward the message to
  917. * @param msg_ctx the context of the message (hop count, bloom, etc.)
  918. */
  919. static void
  920. forward_result_message (const struct GNUNET_MessageHeader *msg,
  921. struct PeerInfo *peer,
  922. struct DHT_MessageContext *msg_ctx)
  923. {
  924. struct GNUNET_DHT_P2PRouteResultMessage *result_message;
  925. struct P2PPendingMessage *pending;
  926. size_t msize;
  927. size_t psize;
  928. char *path_start;
  929. char *path_offset;
  930. #if DEBUG_PATH
  931. unsigned int i;
  932. #endif
  933. increment_stats (STAT_RESULT_FORWARDS);
  934. msize =
  935. sizeof (struct GNUNET_DHT_P2PRouteResultMessage) + ntohs (msg->size) +
  936. (sizeof (struct GNUNET_PeerIdentity) * msg_ctx->path_history_len);
  937. GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
  938. psize = sizeof (struct P2PPendingMessage) + msize;
  939. pending = GNUNET_malloc (psize);
  940. pending->msg = (struct GNUNET_MessageHeader *) &pending[1];
  941. pending->importance = DHT_SEND_PRIORITY;
  942. pending->timeout = GNUNET_TIME_relative_get_forever ();
  943. result_message = (struct GNUNET_DHT_P2PRouteResultMessage *) pending->msg;
  944. result_message->header.size = htons (msize);
  945. result_message->header.type =
  946. htons (GNUNET_MESSAGE_TYPE_DHT_P2P_ROUTE_RESULT);
  947. result_message->outgoing_path_length = htonl (msg_ctx->path_history_len);
  948. if (msg_ctx->path_history_len > 0)
  949. {
  950. /* End of pending is where enc_msg starts */
  951. path_start = (char *) &pending[1];
  952. /* Offset by the size of the enc_msg */
  953. path_start += ntohs (msg->size);
  954. memcpy (path_start, msg_ctx->path_history,
  955. msg_ctx->path_history_len * (sizeof (struct GNUNET_PeerIdentity)));
  956. #if DEBUG_PATH
  957. for (i = 0; i < msg_ctx->path_history_len; i++)
  958. {
  959. path_offset =
  960. &msg_ctx->path_history[i * sizeof (struct GNUNET_PeerIdentity)];
  961. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  962. "(forward_result) Key %s Found peer %d:%s\n",
  963. GNUNET_h2s (&msg_ctx->key), i,
  964. GNUNET_i2s ((struct GNUNET_PeerIdentity *) path_offset));
  965. }
  966. #endif
  967. }
  968. result_message->options = htonl (msg_ctx->msg_options);
  969. result_message->hop_count = htonl (msg_ctx->hop_count + 1);
  970. GNUNET_assert (GNUNET_OK ==
  971. GNUNET_CONTAINER_bloomfilter_get_raw_data (msg_ctx->bloom,
  972. result_message->
  973. bloomfilter,
  974. DHT_BLOOM_SIZE));
  975. result_message->unique_id = GNUNET_htonll (msg_ctx->unique_id);
  976. memcpy (&result_message->key, &msg_ctx->key, sizeof (GNUNET_HashCode));
  977. /* Copy the enc_msg, then the path history as well! */
  978. memcpy (&result_message[1], msg, ntohs (msg->size));
  979. path_offset = (char *) &result_message[1];
  980. path_offset += ntohs (msg->size);
  981. /* If we have path history, copy it to the end of the whole thing */
  982. if (msg_ctx->path_history_len > 0)
  983. memcpy (path_offset, msg_ctx->path_history,
  984. msg_ctx->path_history_len * (sizeof (struct GNUNET_PeerIdentity)));
  985. #if DEBUG_DHT > 1
  986. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  987. "%s:%s Adding pending message size %d for peer %s\n", my_short_id,
  988. "DHT", msize, GNUNET_i2s (&peer->id));
  989. #endif
  990. peer->pending_count++;
  991. increment_stats ("# pending messages scheduled");
  992. GNUNET_CONTAINER_DLL_insert_after (peer->head, peer->tail, peer->tail,
  993. pending);
  994. if (peer->send_task == GNUNET_SCHEDULER_NO_TASK)
  995. peer->send_task = GNUNET_SCHEDULER_add_now (&try_core_send, peer);
  996. }
  997. /**
  998. * Called when core is ready to send a message we asked for
  999. * out to the destination.
  1000. *
  1001. * @param cls closure (NULL)
  1002. * @param size number of bytes available in buf
  1003. * @param buf where the callee should write the message
  1004. * @return number of bytes written to buf
  1005. */
  1006. static size_t
  1007. core_transmit_notify (void *cls, size_t size, void *buf)
  1008. {
  1009. struct PeerInfo *peer = cls;
  1010. char *cbuf = buf;
  1011. struct P2PPendingMessage *pending;
  1012. size_t off;
  1013. size_t msize;
  1014. peer->th = NULL;
  1015. if (buf == NULL)
  1016. {
  1017. /* client disconnected */
  1018. #if DEBUG_DHT
  1019. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s:%s': buffer was NULL\n",
  1020. my_short_id, "DHT");
  1021. #endif
  1022. return 0;
  1023. }
  1024. if (peer->head == NULL)
  1025. return 0;
  1026. off = 0;
  1027. pending = peer->head;
  1028. #if DUMB
  1029. reply_times[reply_counter] =
  1030. GNUNET_TIME_absolute_get_difference (pending->scheduled,
  1031. GNUNET_TIME_absolute_get ());
  1032. msize = ntohs (pending->msg->size);
  1033. if (msize <= size)
  1034. {
  1035. off = msize;
  1036. memcpy (cbuf, pending->msg, msize);
  1037. peer->pending_count--;
  1038. increment_stats ("# pending messages sent");
  1039. GNUNET_assert (peer->pending_count >= 0);
  1040. GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
  1041. GNUNET_free (pending);
  1042. }
  1043. #else
  1044. while (NULL != pending &&
  1045. (size - off >= (msize = ntohs (pending->msg->size))))
  1046. {
  1047. memcpy (&cbuf[off], pending->msg, msize);
  1048. off += msize;
  1049. peer->pending_count--;
  1050. increment_stats ("# pending messages sent");
  1051. GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
  1052. GNUNET_free (pending);
  1053. pending = peer->head;
  1054. }
  1055. #endif
  1056. if ((peer->head != NULL) && (peer->send_task == GNUNET_SCHEDULER_NO_TASK))
  1057. peer->send_task = GNUNET_SCHEDULER_add_now (&try_core_send, peer);
  1058. return off;
  1059. }
  1060. /**
  1061. * Compute the distance between have and target as a 32-bit value.
  1062. * Differences in the lower bits must count stronger than differences
  1063. * in the higher bits.
  1064. *
  1065. * @return 0 if have==target, otherwise a number
  1066. * that is larger as the distance between
  1067. * the two hash codes increases
  1068. */
  1069. static unsigned int
  1070. distance (const GNUNET_HashCode * target, const GNUNET_HashCode * have)
  1071. {
  1072. unsigned int bucket;
  1073. unsigned int msb;
  1074. unsigned int lsb;
  1075. unsigned int i;
  1076. /* We have to represent the distance between two 2^9 (=512)-bit
  1077. * numbers as a 2^5 (=32)-bit number with "0" being used for the
  1078. * two numbers being identical; furthermore, we need to
  1079. * guarantee that a difference in the number of matching
  1080. * bits is always represented in the result.
  1081. *
  1082. * We use 2^32/2^9 numerical values to distinguish between
  1083. * hash codes that have the same LSB bit distance and
  1084. * use the highest 2^9 bits of the result to signify the
  1085. * number of (mis)matching LSB bits; if we have 0 matching
  1086. * and hence 512 mismatching LSB bits we return -1 (since
  1087. * 512 itself cannot be represented with 9 bits) */
  1088. /* first, calculate the most significant 9 bits of our
  1089. * result, aka the number of LSBs */
  1090. bucket = GNUNET_CRYPTO_hash_matching_bits (target, have);
  1091. /* bucket is now a value between 0 and 512 */
  1092. if (bucket == 512)
  1093. return 0; /* perfect match */
  1094. if (bucket == 0)
  1095. return (unsigned int) -1; /* LSB differs; use max (if we did the bit-shifting
  1096. * below, we'd end up with max+1 (overflow)) */
  1097. /* calculate the most significant bits of the final result */
  1098. msb = (512 - bucket) << (32 - 9);
  1099. /* calculate the 32-9 least significant bits of the final result by
  1100. * looking at the differences in the 32-9 bits following the
  1101. * mismatching bit at 'bucket' */
  1102. lsb = 0;
  1103. for (i = bucket + 1;
  1104. (i < sizeof (GNUNET_HashCode) * 8) && (i < bucket + 1 + 32 - 9); i++)
  1105. {
  1106. if (GNUNET_CRYPTO_hash_get_bit (target, i) !=
  1107. GNUNET_CRYPTO_hash_get_bit (have, i))
  1108. lsb |= (1 << (bucket + 32 - 9 - i)); /* first bit set will be 10,
  1109. * last bit set will be 31 -- if
  1110. * i does not reach 512 first... */
  1111. }
  1112. return msb | lsb;
  1113. }
  1114. /**
  1115. * Return a number that is larger the closer the
  1116. * "have" GNUNET_hash code is to the "target".
  1117. *
  1118. * @return inverse distance metric, non-zero.
  1119. * Must fudge the value if NO bits match.
  1120. */
  1121. static unsigned int
  1122. inverse_distance (const GNUNET_HashCode * target, const GNUNET_HashCode * have)
  1123. {
  1124. if (GNUNET_CRYPTO_hash_matching_bits (target, have) == 0)
  1125. return 1; /* Never return 0! */
  1126. return ((unsigned int) -1) - distance (target, have);
  1127. }
  1128. /**
  1129. * Find the optimal bucket for this key, regardless
  1130. * of the current number of buckets in use.
  1131. *
  1132. * @param hc the hashcode to compare our identity to
  1133. *
  1134. * @return the proper bucket index, or GNUNET_SYSERR
  1135. * on error (same hashcode)
  1136. */
  1137. static int
  1138. find_bucket (const GNUNET_HashCode * hc)
  1139. {
  1140. unsigned int bits;
  1141. bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity.hashPubKey, hc);
  1142. if (bits == MAX_BUCKETS)
  1143. return GNUNET_SYSERR;
  1144. return MAX_BUCKETS - bits - 1;
  1145. }
  1146. /**
  1147. * Find which k-bucket this peer should go into,
  1148. * taking into account the size of the k-bucket
  1149. * array. This means that if more bits match than
  1150. * there are currently buckets, lowest_bucket will
  1151. * be returned.
  1152. *
  1153. * @param hc GNUNET_HashCode we are finding the bucket for.
  1154. *
  1155. * @return the proper bucket index for this key,
  1156. * or GNUNET_SYSERR on error (same hashcode)
  1157. */
  1158. static int
  1159. find_current_bucket (const GNUNET_HashCode * hc)
  1160. {
  1161. int actual_bucket;
  1162. actual_bucket = find_bucket (hc);
  1163. if (actual_bucket == GNUNET_SYSERR) /* hc and our peer identity match! */
  1164. return lowest_bucket;
  1165. if (actual_bucket < lowest_bucket) /* actual_bucket not yet used */
  1166. return lowest_bucket;
  1167. return actual_bucket;
  1168. }
  1169. #if EXTRA_CHECKS
  1170. /**
  1171. * Find a routing table entry from a peer identity
  1172. *
  1173. * @param peer the peer to look up
  1174. *
  1175. * @return the bucket number holding the peer, GNUNET_SYSERR if not found
  1176. */
  1177. static int
  1178. find_bucket_by_peer (const struct PeerInfo *peer)
  1179. {
  1180. int bucket;
  1181. struct PeerInfo *pos;
  1182. for (bucket = lowest_bucket; bucket < MAX_BUCKETS - 1; bucket++)
  1183. {
  1184. pos = k_buckets[bucket].head;
  1185. while (pos != NULL)
  1186. {
  1187. if (peer == pos)
  1188. return bucket;
  1189. pos = pos->next;
  1190. }
  1191. }
  1192. return GNUNET_SYSERR; /* No such peer. */
  1193. }
  1194. #endif
  1195. #if PRINT_TABLES
  1196. /**
  1197. * Print the complete routing table for this peer.
  1198. */
  1199. static void
  1200. print_routing_table ()
  1201. {
  1202. int bucket;
  1203. struct PeerInfo *pos;
  1204. char char_buf[30000];
  1205. int char_pos;
  1206. memset (char_buf, 0, sizeof (char_buf));
  1207. char_pos = 0;
  1208. char_pos +=
  1209. sprintf (&char_buf[char_pos], "Printing routing table for peer %s\n",
  1210. my_short_id);
  1211. //fprintf(stderr, "Printing routing table for peer %s\n", my_short_id);
  1212. for (bucket = lowest_bucket; bucket < MAX_BUCKETS; bucket++)
  1213. {
  1214. pos = k_buckets[bucket].head;
  1215. char_pos += sprintf (&char_buf[char_pos], "Bucket %d:\n", bucket);
  1216. //fprintf(stderr, "Bucket %d:\n", bucket);
  1217. while (pos != NULL)
  1218. {
  1219. //fprintf(stderr, "\tPeer %s, best bucket %d, %d bits match\n", GNUNET_i2s(&pos->id), find_bucket(&pos->id.hashPubKey), GNUNET_CRYPTO_hash_matching_bits(&pos->id.hashPubKey, &my_identity.hashPubKey));
  1220. char_pos +=
  1221. sprintf (&char_buf[char_pos],
  1222. "\tPeer %s, best bucket %d, %d bits match\n",
  1223. GNUNET_i2s (&pos->id), find_bucket (&pos->id.hashPubKey),
  1224. GNUNET_CRYPTO_hash_matching_bits (&pos->id.hashPubKey,
  1225. &my_identity.hashPubKey));
  1226. pos = pos->next;
  1227. }
  1228. }
  1229. fprintf (stderr, "%s", char_buf);
  1230. fflush (stderr);
  1231. }
  1232. #endif
  1233. /**
  1234. * Find a routing table entry from a peer identity
  1235. *
  1236. * @param peer the peer identity to look up
  1237. *
  1238. * @return the routing table entry, or NULL if not found
  1239. */
  1240. static struct PeerInfo *
  1241. find_peer_by_id (const struct GNUNET_PeerIdentity *peer)
  1242. {
  1243. int bucket;
  1244. struct PeerInfo *pos;
  1245. bucket = find_current_bucket (&peer->hashPubKey);
  1246. if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
  1247. return NULL;
  1248. pos = k_buckets[bucket].head;
  1249. while (pos != NULL)
  1250. {
  1251. if (0 == memcmp (&pos->id, peer, sizeof (struct GNUNET_PeerIdentity)))
  1252. return pos;
  1253. pos = pos->next;
  1254. }
  1255. return NULL; /* No such peer. */
  1256. }
  1257. /* Forward declaration */
  1258. static void
  1259. update_core_preference (void *cls,
  1260. const struct GNUNET_SCHEDULER_TaskContext *tc);
  1261. /**
  1262. * Function called with statistics about the given peer.
  1263. *
  1264. * @param cls closure
  1265. * @param peer identifies the peer
  1266. * @param bpm_out set to the current bandwidth limit (sending) for this peer
  1267. * @param amount set to the amount that was actually reserved or unreserved;
  1268. * either the full requested amount or zero (no partial reservations)
  1269. * @param res_delay if the reservation could not be satisfied (amount was 0), how
  1270. * long should the client wait until re-trying?
  1271. * @param preference current traffic preference for the given peer
  1272. */
  1273. static void
  1274. update_core_preference_finish (void *cls,
  1275. const struct GNUNET_PeerIdentity *peer,
  1276. struct GNUNET_BANDWIDTH_Value32NBO bpm_out,
  1277. int32_t amount,
  1278. struct GNUNET_TIME_Relative res_delay,
  1279. uint64_t preference)
  1280. {
  1281. struct PeerInfo *peer_info = cls;
  1282. peer_info->info_ctx = NULL;
  1283. GNUNET_SCHEDULER_add_delayed (DHT_DEFAULT_PREFERENCE_INTERVAL,
  1284. &update_core_preference, peer_info);
  1285. }
  1286. static void
  1287. update_core_preference (void *cls,
  1288. const struct GNUNET_SCHEDULER_TaskContext *tc)
  1289. {
  1290. struct PeerInfo *peer = cls;
  1291. uint64_t preference;
  1292. unsigned int matching;
  1293. if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
  1294. {
  1295. return;
  1296. }
  1297. matching =
  1298. GNUNET_CRYPTO_hash_matching_bits (&my_identity.hashPubKey,
  1299. &peer->id.hashPubKey);
  1300. if (matching >= 64)
  1301. {
  1302. #if DEBUG_DHT
  1303. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1304. "Peer identifier matches by %u bits, only shifting as much as we can!\n",
  1305. matching);
  1306. #endif
  1307. matching = 63;
  1308. }
  1309. preference = 1LL << matching;
  1310. peer->info_ctx =
  1311. GNUNET_CORE_peer_change_preference (coreAPI, &peer->id,
  1312. GNUNET_TIME_UNIT_FOREVER_REL,
  1313. GNUNET_BANDWIDTH_VALUE_MAX, 0,
  1314. preference,
  1315. &update_core_preference_finish, peer);
  1316. }
  1317. /**
  1318. * Given a peer and its corresponding bucket,
  1319. * remove it from that bucket. Does not free
  1320. * the PeerInfo struct, nor cancel messages
  1321. * or free messages waiting to be sent to this
  1322. * peer!
  1323. *
  1324. * @param peer the peer to remove
  1325. * @param bucket the bucket the peer belongs to
  1326. */
  1327. static void
  1328. remove_peer (struct PeerInfo *peer, unsigned int bucket)
  1329. {
  1330. GNUNET_assert (k_buckets[bucket].peers_size > 0);
  1331. GNUNET_CONTAINER_DLL_remove (k_buckets[bucket].head, k_buckets[bucket].tail,
  1332. peer);
  1333. k_buckets[bucket].peers_size--;
  1334. #if CHANGE_LOWEST
  1335. if ((bucket == lowest_bucket) && (k_buckets[lowest_bucket].peers_size == 0) &&
  1336. (lowest_bucket < MAX_BUCKETS - 1))
  1337. lowest_bucket++;
  1338. #endif
  1339. }
  1340. /**
  1341. * Removes peer from a bucket, then frees associated
  1342. * resources and frees peer.
  1343. *
  1344. * @param peer peer to be removed and freed
  1345. * @param bucket which bucket this peer belongs to
  1346. */
  1347. static void
  1348. delete_peer (struct PeerInfo *peer, unsigned int bucket)
  1349. {
  1350. struct P2PPendingMessage *pos;
  1351. struct P2PPendingMessage *next;
  1352. #if EXTRA_CHECKS
  1353. struct PeerInfo *peer_pos;
  1354. peer_pos = k_buckets[bucket].head;
  1355. while ((peer_pos != NULL) && (peer_pos != peer))
  1356. peer_pos = peer_pos->next;
  1357. if (peer_pos == NULL)
  1358. {
  1359. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1360. "%s:%s: Expected peer `%s' in bucket %d\n", my_short_id, "DHT",
  1361. GNUNET_i2s (&peer->id), bucket);
  1362. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1363. "%s:%s: Lowest bucket: %d, find_current_bucket: %d, peer resides in bucket: %d\n",
  1364. my_short_id, "DHT", lowest_bucket,
  1365. find_current_bucket (&peer->id.hashPubKey),
  1366. find_bucket_by_peer (peer));
  1367. }
  1368. GNUNET_assert (peer_pos != NULL);
  1369. #endif
  1370. remove_peer (peer, bucket); /* First remove the peer from its bucket */
  1371. if (peer->send_task != GNUNET_SCHEDULER_NO_TASK)
  1372. GNUNET_SCHEDULER_cancel (peer->send_task);
  1373. if ((peer->th != NULL) && (coreAPI != NULL))
  1374. GNUNET_CORE_notify_transmit_ready_cancel (peer->th);
  1375. pos = peer->head;
  1376. while (pos != NULL) /* Remove any pending messages for this peer */
  1377. {
  1378. increment_stats
  1379. ("# dht pending messages discarded (due to disconnect/shutdown)");
  1380. next = pos->next;
  1381. GNUNET_free (pos);
  1382. pos = next;
  1383. }
  1384. GNUNET_assert (GNUNET_CONTAINER_multihashmap_contains
  1385. (all_known_peers, &peer->id.hashPubKey));
  1386. GNUNET_assert (GNUNET_YES ==
  1387. GNUNET_CONTAINER_multihashmap_remove (all_known_peers,
  1388. &peer->id.hashPubKey,
  1389. peer));
  1390. GNUNET_free (peer);
  1391. decrement_stats (STAT_PEERS_KNOWN);
  1392. }
  1393. /**
  1394. * Iterator over hash map entries.
  1395. *
  1396. * @param cls closure
  1397. * @param key current key code
  1398. * @param value PeerInfo of the peer to move to new lowest bucket
  1399. * @return GNUNET_YES if we should continue to
  1400. * iterate,
  1401. * GNUNET_NO if not.
  1402. */
  1403. static int
  1404. move_lowest_bucket (void *cls, const GNUNET_HashCode * key, void *value)
  1405. {
  1406. struct PeerInfo *peer = value;
  1407. int new_bucket;
  1408. GNUNET_assert (lowest_bucket > 0);
  1409. new_bucket = lowest_bucket - 1;
  1410. remove_peer (peer, lowest_bucket);
  1411. GNUNET_CONTAINER_DLL_insert_after (k_buckets[new_bucket].head,
  1412. k_buckets[new_bucket].tail,
  1413. k_buckets[new_bucket].tail, peer);
  1414. k_buckets[new_bucket].peers_size++;
  1415. return GNUNET_YES;
  1416. }
  1417. /**
  1418. * The current lowest bucket is full, so change the lowest
  1419. * bucket to the next lower down, and move any appropriate
  1420. * entries in the current lowest bucket to the new bucket.
  1421. */
  1422. static void
  1423. enable_next_bucket ()
  1424. {
  1425. struct GNUNET_CONTAINER_MultiHashMap *to_remove;
  1426. struct PeerInfo *pos;
  1427. GNUNET_assert (lowest_bucket > 0);
  1428. to_remove = GNUNET_CONTAINER_multihashmap_create (bucket_size);
  1429. pos = k_buckets[lowest_bucket].head;
  1430. #if PRINT_TABLES
  1431. fprintf (stderr, "Printing RT before new bucket\n");
  1432. print_routing_table ();
  1433. #endif
  1434. /* Populate the array of peers which should be in the next lowest bucket */
  1435. while (pos != NULL)
  1436. {
  1437. if (find_bucket (&pos->id.hashPubKey) < lowest_bucket)
  1438. GNUNET_CONTAINER_multihashmap_put (to_remove, &pos->id.hashPubKey, pos,
  1439. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
  1440. pos = pos->next;
  1441. }
  1442. /* Remove peers from lowest bucket, insert into next lowest bucket */
  1443. GNUNET_CONTAINER_multihashmap_iterate (to_remove, &move_lowest_bucket, NULL);
  1444. GNUNET_CONTAINER_multihashmap_destroy (to_remove);
  1445. lowest_bucket = lowest_bucket - 1;
  1446. #if PRINT_TABLES
  1447. fprintf (stderr, "Printing RT after new bucket\n");
  1448. print_routing_table ();
  1449. #endif
  1450. }
  1451. /**
  1452. * Find the closest peer in our routing table to the
  1453. * given hashcode.
  1454. *
  1455. * @return The closest peer in our routing table to the
  1456. * key, or NULL on error.
  1457. */
  1458. static struct PeerInfo *
  1459. find_closest_peer (const GNUNET_HashCode * hc)
  1460. {
  1461. struct PeerInfo *pos;
  1462. struct PeerInfo *current_closest;
  1463. unsigned int lowest_distance;
  1464. unsigned int temp_distance;
  1465. int bucket;
  1466. int count;
  1467. lowest_distance = -1;
  1468. if (k_buckets[lowest_bucket].peers_size == 0)
  1469. return NULL;
  1470. current_closest = NULL;
  1471. for (bucket = lowest_bucket; bucket < MAX_BUCKETS; bucket++)
  1472. {
  1473. pos = k_buckets[bucket].head;
  1474. count = 0;
  1475. while ((pos != NULL) && (count < bucket_size))
  1476. {
  1477. temp_distance = distance (&pos->id.hashPubKey, hc);
  1478. if (temp_distance <= lowest_distance)
  1479. {
  1480. lowest_distance = temp_distance;
  1481. current_closest = pos;
  1482. }
  1483. pos = pos->next;
  1484. count++;
  1485. }
  1486. }
  1487. GNUNET_assert (current_closest != NULL);
  1488. return current_closest;
  1489. }
  1490. /**
  1491. * Function called to send a request out to another peer.
  1492. * Called both for locally initiated requests and those
  1493. * received from other peers.
  1494. *
  1495. * @param msg the encapsulated message
  1496. * @param peer the peer to forward the message to
  1497. * @param msg_ctx the context of the message (hop count, bloom, etc.)
  1498. */
  1499. static void
  1500. forward_message (const struct GNUNET_MessageHeader *msg, struct PeerInfo *peer,
  1501. struct DHT_MessageContext *msg_ctx)
  1502. {
  1503. struct GNUNET_DHT_P2PRouteMessage *route_message;
  1504. struct P2PPendingMessage *pending;
  1505. size_t msize;
  1506. size_t psize;
  1507. char *route_path;
  1508. increment_stats (STAT_ROUTE_FORWARDS);
  1509. GNUNET_assert (peer != NULL);
  1510. if ((msg_ctx->closest != GNUNET_YES) &&
  1511. (peer == find_closest_peer (&msg_ctx->key)))
  1512. increment_stats (STAT_ROUTE_FORWARDS_CLOSEST);
  1513. msize =
  1514. sizeof (struct GNUNET_DHT_P2PRouteMessage) + ntohs (msg->size) +
  1515. (msg_ctx->path_history_len * sizeof (struct GNUNET_PeerIdentity));
  1516. GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
  1517. psize = sizeof (struct P2PPendingMessage) + msize;
  1518. pending = GNUNET_malloc (psize);
  1519. pending->msg = (struct GNUNET_MessageHeader *) &pending[1];
  1520. pending->importance = msg_ctx->importance;
  1521. pending->timeout = msg_ctx->timeout;
  1522. route_message = (struct GNUNET_DHT_P2PRouteMessage *) pending->msg;
  1523. route_message->header.size = htons (msize);
  1524. route_message->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_ROUTE);
  1525. route_message->options = htonl (msg_ctx->msg_options);
  1526. route_message->hop_count = htonl (msg_ctx->hop_count + 1);
  1527. route_message->network_size = htonl (msg_ctx->network_size);
  1528. route_message->desired_replication_level = htonl (msg_ctx->replication);
  1529. route_message->unique_id = GNUNET_htonll (msg_ctx->unique_id);
  1530. if (msg_ctx->bloom != NULL)
  1531. GNUNET_assert (GNUNET_OK ==
  1532. GNUNET_CONTAINER_bloomfilter_get_raw_data (msg_ctx->bloom,
  1533. route_message->
  1534. bloomfilter,
  1535. DHT_BLOOM_SIZE));
  1536. memcpy (&route_message->key, &msg_ctx->key, sizeof (GNUNET_HashCode));
  1537. memcpy (&route_message[1], msg, ntohs (msg->size));
  1538. if (GNUNET_DHT_RO_RECORD_ROUTE ==
  1539. (msg_ctx->msg_options & GNUNET_DHT_RO_RECORD_ROUTE))
  1540. {
  1541. route_message->outgoing_path_length = htonl (msg_ctx->path_history_len);
  1542. /* Set pointer to start of enc_msg */
  1543. route_path = (char *) &route_message[1];
  1544. /* Offset to the end of the enc_msg */
  1545. route_path += ntohs (msg->size);
  1546. /* Copy the route_path after enc_msg */
  1547. memcpy (route_path, msg_ctx->path_history,
  1548. msg_ctx->path_history_len * sizeof (struct GNUNET_PeerIdentity));
  1549. }
  1550. #if DEBUG_DHT > 1
  1551. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1552. "%s:%s Adding pending message size %d for peer %s\n", my_short_id,
  1553. "DHT", msize, GNUNET_i2s (&peer->id));
  1554. #endif
  1555. peer->pending_count++;
  1556. increment_stats ("# pending messages scheduled");
  1557. GNUNET_CONTAINER_DLL_insert_after (peer->head, peer->tail, peer->tail,
  1558. pending);
  1559. if (peer->send_task == GNUNET_SCHEDULER_NO_TASK)
  1560. peer->send_task = GNUNET_SCHEDULER_add_now (&try_core_send, peer);
  1561. }
  1562. #if DO_PING
  1563. /**
  1564. * Task used to send ping messages to peers so that
  1565. * they don't get disconnected.
  1566. *
  1567. * @param cls the peer to send a ping message to
  1568. * @param tc context, reason, etc.
  1569. */
  1570. static void
  1571. periodic_ping_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  1572. {
  1573. struct PeerInfo *peer = cls;
  1574. struct GNUNET_MessageHeader ping_message;
  1575. struct DHT_MessageContext msg_ctx;
  1576. if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
  1577. return;
  1578. ping_message.size = htons (sizeof (struct GNUNET_MessageHeader));
  1579. ping_message.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PING);
  1580. memset (&msg_ctx, 0, sizeof (struct DHT_MessageContext));
  1581. #if DEBUG_PING
  1582. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s:%s Sending periodic ping to %s\n",
  1583. my_short_id, "DHT", GNUNET_i2s (&peer->id));
  1584. #endif
  1585. forward_message (&ping_message, peer, &msg_ctx);
  1586. peer->ping_task =
  1587. GNUNET_SCHEDULER_add_delayed (DHT_DEFAULT_PING_DELAY, &periodic_ping_task,
  1588. peer);
  1589. }
  1590. /**
  1591. * Schedule PING messages for the top X peers in each
  1592. * bucket of the routing table (so core won't disconnect them!)
  1593. */
  1594. void
  1595. schedule_ping_messages ()
  1596. {
  1597. unsigned int bucket;
  1598. unsigned int count;
  1599. struct PeerInfo *pos;
  1600. for (bucket = lowest_bucket; bucket < MAX_BUCKETS; bucket++)
  1601. {
  1602. pos = k_buckets[bucket].head;
  1603. count = 0;
  1604. while (pos != NULL)
  1605. {
  1606. if ((count < bucket_size) && (pos->ping_task == GNUNET_SCHEDULER_NO_TASK))
  1607. GNUNET_SCHEDULER_add_now (&periodic_ping_task, pos);
  1608. else if ((count >= bucket_size) &&
  1609. (pos->ping_task != GNUNET_SCHEDULER_NO_TASK))
  1610. {
  1611. GNUNET_SCHEDULER_cancel (pos->ping_task);
  1612. pos->ping_task = GNUNET_SCHEDULER_NO_TASK;
  1613. }
  1614. pos = pos->next;
  1615. count++;
  1616. }
  1617. }
  1618. }
  1619. #endif
  1620. /**
  1621. * Task run to check for messages that need to be sent to a client.
  1622. *
  1623. * @param client a ClientList, containing the client and any messages to be sent to it
  1624. */
  1625. static void
  1626. process_pending_messages (struct ClientList *client)
  1627. {
  1628. if (client->pending_head == NULL)
  1629. return;
  1630. if (client->transmit_handle != NULL)
  1631. return;
  1632. client->transmit_handle =
  1633. GNUNET_SERVER_notify_transmit_ready (client->client_handle,
  1634. ntohs (client->pending_head->
  1635. msg->size),
  1636. GNUNET_TIME_UNIT_FOREVER_REL,
  1637. &send_generic_reply, client);
  1638. }
  1639. /**
  1640. * Callback called as a result of issuing a GNUNET_SERVER_notify_transmit_ready
  1641. * request. A ClientList is passed as closure, take the head of the list
  1642. * and copy it into buf, which has the result of sending the message to the
  1643. * client.
  1644. *
  1645. * @param cls closure to this call
  1646. * @param size maximum number of bytes available to send
  1647. * @param buf where to copy the actual message to
  1648. *
  1649. * @return the number of bytes actually copied, 0 indicates failure
  1650. */
  1651. static size_t
  1652. send_generic_reply (void *cls, size_t size, void *buf)
  1653. {
  1654. struct ClientList *client = cls;
  1655. char *cbuf = buf;
  1656. struct PendingMessage *reply;
  1657. size_t off;
  1658. size_t msize;
  1659. client->transmit_handle = NULL;
  1660. if (buf == NULL)
  1661. {
  1662. /* client disconnected */
  1663. return 0;
  1664. }
  1665. off = 0;
  1666. while ((NULL != (reply = client->pending_head)) &&
  1667. (size >= off + (msize = ntohs (reply->msg->size))))
  1668. {
  1669. GNUNET_CONTAINER_DLL_remove (client->pending_head, client->pending_tail,
  1670. reply);
  1671. memcpy (&cbuf[off], reply->msg, msize);
  1672. GNUNET_free (reply);
  1673. off += msize;
  1674. }
  1675. process_pending_messages (client);
  1676. #if DEBUG_DHT
  1677. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1678. "Transmitted %u bytes of replies to client\n",
  1679. (unsigned int) off);
  1680. #endif
  1681. return off;
  1682. }
  1683. /**
  1684. * Add a PendingMessage to the clients list of messages to be sent
  1685. *
  1686. * @param client the active client to send the message to
  1687. * @param pending_message the actual message to send
  1688. */
  1689. static void
  1690. add_pending_message (struct ClientList *client,
  1691. struct PendingMessage *pending_message)
  1692. {
  1693. GNUNET_CONTAINER_DLL_insert_after (client->pending_head, client->pending_tail,
  1694. client->pending_tail, pending_message);
  1695. process_pending_messages (client);
  1696. }
  1697. /**
  1698. * Called when a reply needs to be sent to a client, as
  1699. * a result it found to a GET or FIND PEER request.
  1700. *
  1701. * @param client the client to send the reply to
  1702. * @param message the encapsulated message to send
  1703. * @param msg_ctx the context of the received message
  1704. */
  1705. static void
  1706. send_reply_to_client (struct ClientList *client,
  1707. const struct GNUNET_MessageHeader *message,
  1708. struct DHT_MessageContext *msg_ctx)
  1709. {
  1710. struct GNUNET_DHT_RouteResultMessage *reply;
  1711. struct PendingMessage *pending_message;
  1712. uint16_t msize;
  1713. size_t tsize;
  1714. char *reply_offset;
  1715. #if DEBUG_PATH
  1716. char *path_offset;
  1717. unsigned int i;
  1718. #endif
  1719. #if DEBUG_DHT
  1720. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s:%s': Sending reply to client.\n",
  1721. my_short_id, "DHT");
  1722. #endif
  1723. msize = ntohs (message->size);
  1724. tsize =
  1725. sizeof (struct GNUNET_DHT_RouteResultMessage) + msize +
  1726. (msg_ctx->path_history_len * sizeof (struct GNUNET_PeerIdentity));
  1727. if (tsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
  1728. {
  1729. GNUNET_break_op (0);
  1730. return;
  1731. }
  1732. pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + tsize);
  1733. pending_message->msg = (struct GNUNET_MessageHeader *) &pending_message[1];
  1734. reply = (struct GNUNET_DHT_RouteResultMessage *) &pending_message[1];
  1735. reply->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_LOCAL_ROUTE_RESULT);
  1736. reply->header.size = htons (tsize);
  1737. reply->outgoing_path_length = htonl (msg_ctx->path_history_len);
  1738. reply->unique_id = GNUNET_htonll (msg_ctx->unique_id);
  1739. memcpy (&reply->key, &msg_ctx->key, sizeof (GNUNET_HashCode));
  1740. reply_offset = (char *) &reply[1];
  1741. memcpy (&reply[1], message, msize);
  1742. if (msg_ctx->path_history_len > 0)
  1743. {
  1744. reply_offset += msize;
  1745. memcpy (reply_offset, msg_ctx->path_history,
  1746. msg_ctx->path_history_len * sizeof (struct GNUNET_PeerIdentity));
  1747. }
  1748. #if DEBUG_PATH
  1749. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1750. "Returning message with outgoing path length %d\n",
  1751. msg_ctx->path_history_len);
  1752. for (i = 0; i < msg_ctx->path_history_len; i++)
  1753. {
  1754. path_offset =
  1755. &msg_ctx->path_history[i * sizeof (struct GNUNET_PeerIdentity)];
  1756. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found peer %d:%s\n", i,
  1757. GNUNET_i2s ((struct GNUNET_PeerIdentity *) path_offset));
  1758. }
  1759. #endif
  1760. add_pending_message (client, pending_message);
  1761. }
  1762. /**
  1763. * Consider whether or not we would like to have this peer added to
  1764. * our routing table. Check whether bucket for this peer is full,
  1765. * if so return negative; if not return positive. Since peers are
  1766. * only added on CORE level connect, this doesn't actually add the
  1767. * peer to the routing table.
  1768. *
  1769. * @param peer the peer we are considering adding
  1770. *
  1771. * @return GNUNET_YES if we want this peer, GNUNET_NO if not (bucket
  1772. * already full)
  1773. */
  1774. static int
  1775. consider_peer (struct GNUNET_PeerIdentity *peer)
  1776. {
  1777. int bucket;
  1778. if ((GNUNET_YES ==
  1779. GNUNET_CONTAINER_multihashmap_contains (all_known_peers,
  1780. &peer->hashPubKey)) ||
  1781. (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))))
  1782. return GNUNET_NO; /* We already know this peer (are connected even!) */
  1783. bucket = find_current_bucket (&peer->hashPubKey);
  1784. if ((k_buckets[bucket].peers_size < bucket_size) ||
  1785. ((bucket == lowest_bucket) && (lowest_bucket > 0)))
  1786. return GNUNET_YES;
  1787. return GNUNET_NO;
  1788. }
  1789. /**
  1790. * Task used to remove forwarding entries, either
  1791. * after timeout, when full, or on shutdown.
  1792. *
  1793. * @param cls the entry to remove
  1794. * @param tc context, reason, etc.
  1795. */
  1796. static void
  1797. remove_forward_entry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  1798. {
  1799. struct DHTRouteSource *source_info = cls;
  1800. struct DHTQueryRecord *record;
  1801. source_info = GNUNET_CONTAINER_heap_remove_node (source_info->hnode);
  1802. record = source_info->record;
  1803. GNUNET_CONTAINER_DLL_remove (record->head, record->tail, source_info);
  1804. if (record->head == NULL) /* No more entries in DLL */
  1805. {
  1806. GNUNET_assert (GNUNET_YES ==
  1807. GNUNET_CONTAINER_multihashmap_remove (forward_list.hashmap,
  1808. &record->key, record));
  1809. GNUNET_free (record);
  1810. }
  1811. if (source_info->find_peers_responded != NULL)
  1812. GNUNET_CONTAINER_bloomfilter_free (source_info->find_peers_responded);
  1813. GNUNET_free (source_info);
  1814. }
  1815. /**
  1816. * Main function that handles whether or not to route a result
  1817. * message to other peers, or to send to our local client.
  1818. *
  1819. * @param msg the result message to be routed
  1820. * @param msg_ctx context of the message we are routing
  1821. *
  1822. * @return the number of peers the message was routed to,
  1823. * GNUNET_SYSERR on failure
  1824. */
  1825. static int
  1826. route_result_message (struct GNUNET_MessageHeader *msg,
  1827. struct DHT_MessageContext *msg_ctx)
  1828. {
  1829. struct GNUNET_PeerIdentity new_peer;
  1830. struct DHTQueryRecord *record;
  1831. struct DHTRouteSource *pos;
  1832. struct PeerInfo *peer_info;
  1833. const struct GNUNET_MessageHeader *hello_msg;
  1834. #if DEBUG_DHT > 1
  1835. unsigned int i;
  1836. #endif
  1837. increment_stats (STAT_RESULTS);
  1838. /**
  1839. * If a find peer result message is received and contains a valid
  1840. * HELLO for another peer, offer it to the transport service.
  1841. */
  1842. if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_DHT_FIND_PEER_RESULT)
  1843. {
  1844. if (ntohs (msg->size) <= sizeof (struct GNUNET_MessageHeader))
  1845. GNUNET_break_op (0);
  1846. hello_msg = &msg[1];
  1847. if ((ntohs (hello_msg->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
  1848. (GNUNET_SYSERR ==
  1849. GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) hello_msg,
  1850. &new_peer)))
  1851. {
  1852. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1853. "%s:%s Received non-HELLO message type in find peer result message!\n",
  1854. my_short_id, "DHT");
  1855. GNUNET_break_op (0);
  1856. return GNUNET_NO;
  1857. }
  1858. else /* We have a valid hello, and peer id stored in new_peer */
  1859. {
  1860. find_peer_context.count++;
  1861. increment_stats (STAT_FIND_PEER_REPLY);
  1862. if (GNUNET_YES == consider_peer (&new_peer))
  1863. {
  1864. increment_stats (STAT_HELLOS_PROVIDED);
  1865. GNUNET_TRANSPORT_offer_hello (transport_handle, hello_msg, NULL, NULL);
  1866. GNUNET_CORE_peer_request_connect (coreAPI, &new_peer, NULL, NULL);
  1867. }
  1868. }
  1869. }
  1870. if (malicious_dropper == GNUNET_YES)
  1871. record = NULL;
  1872. else
  1873. record =
  1874. GNUNET_CONTAINER_multihashmap_get (forward_list.hashmap, &msg_ctx->key);
  1875. if (record == NULL) /* No record of this message! */
  1876. {
  1877. #if DEBUG_DHT
  1878. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1879. "`%s:%s': Have no record of response key %s uid %llu\n",
  1880. my_short_id, "DHT", GNUNET_h2s (&msg_ctx->key),
  1881. msg_ctx->unique_id);
  1882. #endif
  1883. #if DEBUG_DHT_ROUTING
  1884. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  1885. {
  1886. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_RESULT,
  1887. msg_ctx->hop_count, GNUNET_SYSERR,
  1888. &my_identity, &msg_ctx->key, msg_ctx->peer,
  1889. NULL);
  1890. }
  1891. #endif
  1892. if (msg_ctx->bloom != NULL)
  1893. {
  1894. GNUNET_CONTAINER_bloomfilter_free (msg_ctx->bloom);
  1895. msg_ctx->bloom = NULL;
  1896. }
  1897. return 0;
  1898. }
  1899. pos = record->head;
  1900. while (pos != NULL)
  1901. {
  1902. #if STRICT_FORWARDING
  1903. if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_DHT_FIND_PEER_RESULT) /* If we have already forwarded this peer id, don't do it again! */
  1904. {
  1905. if (GNUNET_YES ==
  1906. GNUNET_CONTAINER_bloomfilter_test (pos->find_peers_responded,
  1907. &new_peer.hashPubKey))
  1908. {
  1909. increment_stats ("# find peer responses NOT forwarded (bloom match)");
  1910. pos = pos->next;
  1911. continue;
  1912. }
  1913. else
  1914. GNUNET_CONTAINER_bloomfilter_add (pos->find_peers_responded,
  1915. &new_peer.hashPubKey);
  1916. }
  1917. #endif
  1918. if (0 == memcmp (&pos->source, &my_identity, sizeof (struct GNUNET_PeerIdentity))) /* Local client (or DHT) initiated request! */
  1919. {
  1920. #if DEBUG_DHT
  1921. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1922. "`%s:%s': Sending response key %s uid %llu to client\n",
  1923. my_short_id, "DHT", GNUNET_h2s (&msg_ctx->key),
  1924. msg_ctx->unique_id);
  1925. #endif
  1926. #if DEBUG_DHT_ROUTING
  1927. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  1928. {
  1929. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_RESULT,
  1930. msg_ctx->hop_count, GNUNET_YES,
  1931. &my_identity, &msg_ctx->key, msg_ctx->peer,
  1932. NULL);
  1933. }
  1934. #endif
  1935. increment_stats (STAT_RESULTS_TO_CLIENT);
  1936. if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_DHT_GET_RESULT)
  1937. increment_stats (STAT_GET_REPLY);
  1938. #if DEBUG_DHT > 1
  1939. for (i = 0; i < msg_ctx->path_history_len; i++)
  1940. {
  1941. char *path_offset;
  1942. path_offset =
  1943. &msg_ctx->path_history[i * sizeof (struct GNUNET_PeerIdentity)];
  1944. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1945. "(before client) Key %s Found peer %d:%s\n",
  1946. GNUNET_h2s (&msg_ctx->key), i,
  1947. GNUNET_i2s ((struct GNUNET_PeerIdentity *) path_offset));
  1948. }
  1949. #endif
  1950. send_reply_to_client (pos->client, msg, msg_ctx);
  1951. }
  1952. else /* Send to peer */
  1953. {
  1954. peer_info = find_peer_by_id (&pos->source);
  1955. if (peer_info == NULL) /* Didn't find the peer in our routing table, perhaps peer disconnected! */
  1956. {
  1957. pos = pos->next;
  1958. continue;
  1959. }
  1960. if (msg_ctx->bloom == NULL)
  1961. msg_ctx->bloom =
  1962. GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE,
  1963. DHT_BLOOM_K);
  1964. GNUNET_CONTAINER_bloomfilter_add (msg_ctx->bloom,
  1965. &my_identity.hashPubKey);
  1966. if ((GNUNET_NO ==
  1967. GNUNET_CONTAINER_bloomfilter_test (msg_ctx->bloom,
  1968. &peer_info->id.hashPubKey)))
  1969. {
  1970. #if DEBUG_DHT
  1971. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1972. "`%s:%s': Forwarding response key %s uid %llu to peer %s\n",
  1973. my_short_id, "DHT", GNUNET_h2s (&msg_ctx->key),
  1974. msg_ctx->unique_id, GNUNET_i2s (&peer_info->id));
  1975. #endif
  1976. #if DEBUG_DHT_ROUTING
  1977. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  1978. {
  1979. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_RESULT,
  1980. msg_ctx->hop_count, GNUNET_NO,
  1981. &my_identity, &msg_ctx->key,
  1982. msg_ctx->peer, &pos->source);
  1983. }
  1984. #endif
  1985. forward_result_message (msg, peer_info, msg_ctx);
  1986. /* Try removing forward entries after sending once, only allows ONE response per request */
  1987. if (pos->delete_task != GNUNET_SCHEDULER_NO_TASK)
  1988. {
  1989. GNUNET_SCHEDULER_cancel (pos->delete_task);
  1990. pos->delete_task =
  1991. GNUNET_SCHEDULER_add_now (&remove_forward_entry, pos);
  1992. }
  1993. }
  1994. else
  1995. {
  1996. #if DEBUG_DHT
  1997. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1998. "`%s:%s': NOT Forwarding response (bloom match) key %s uid %llu to peer %s\n",
  1999. my_short_id, "DHT", GNUNET_h2s (&msg_ctx->key),
  2000. msg_ctx->unique_id, GNUNET_i2s (&peer_info->id));
  2001. #endif
  2002. }
  2003. }
  2004. pos = pos->next;
  2005. }
  2006. if (msg_ctx->bloom != NULL)
  2007. {
  2008. GNUNET_CONTAINER_bloomfilter_free (msg_ctx->bloom);
  2009. msg_ctx->bloom = NULL;
  2010. }
  2011. return 0;
  2012. }
  2013. /**
  2014. * Iterator for local get request results,
  2015. *
  2016. * @param cls closure for iterator, a DatacacheGetContext
  2017. * @param exp when does this value expire?
  2018. * @param key the key this data is stored under
  2019. * @param size the size of the data identified by key
  2020. * @param data the actual data
  2021. * @param type the type of the data
  2022. *
  2023. * @return GNUNET_OK to continue iteration, anything else
  2024. * to stop iteration.
  2025. */
  2026. static int
  2027. datacache_get_iterator (void *cls, struct GNUNET_TIME_Absolute exp,
  2028. const GNUNET_HashCode * key, size_t size,
  2029. const char *data, enum GNUNET_BLOCK_Type type)
  2030. {
  2031. struct DHT_MessageContext *msg_ctx = cls;
  2032. struct DHT_MessageContext *new_msg_ctx;
  2033. struct GNUNET_DHT_GetResultMessage *get_result;
  2034. enum GNUNET_BLOCK_EvaluationResult eval;
  2035. const struct DHTPutEntry *put_entry;
  2036. int get_size;
  2037. char *path_offset;
  2038. #if DEBUG_PATH
  2039. unsigned int i;
  2040. #endif
  2041. #if DEBUG_DHT
  2042. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2043. "`%s:%s': Received `%s' response from datacache\n", my_short_id,
  2044. "DHT", "GET");
  2045. #endif
  2046. put_entry = (const struct DHTPutEntry *) data;
  2047. if (size !=
  2048. sizeof (struct DHTPutEntry) + put_entry->data_size +
  2049. (put_entry->path_length * sizeof (struct GNUNET_PeerIdentity)))
  2050. {
  2051. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2052. "Path + data size doesn't add up for data inserted into datacache!\nData size %d, path length %d, expected %d, got %d\n",
  2053. put_entry->data_size, put_entry->path_length,
  2054. sizeof (struct DHTPutEntry) + put_entry->data_size +
  2055. (put_entry->path_length * sizeof (struct GNUNET_PeerIdentity)),
  2056. size);
  2057. msg_ctx->do_forward = GNUNET_NO;
  2058. return GNUNET_OK;
  2059. }
  2060. eval =
  2061. GNUNET_BLOCK_evaluate (block_context, type, key, &msg_ctx->reply_bf,
  2062. msg_ctx->reply_bf_mutator, msg_ctx->xquery,
  2063. msg_ctx->xquery_size, &put_entry[1],
  2064. put_entry->data_size);
  2065. switch (eval)
  2066. {
  2067. case GNUNET_BLOCK_EVALUATION_OK_LAST:
  2068. msg_ctx->do_forward = GNUNET_NO;
  2069. case GNUNET_BLOCK_EVALUATION_OK_MORE:
  2070. new_msg_ctx = GNUNET_malloc (sizeof (struct DHT_MessageContext));
  2071. memcpy (new_msg_ctx, msg_ctx, sizeof (struct DHT_MessageContext));
  2072. if (GNUNET_DHT_RO_RECORD_ROUTE ==
  2073. (msg_ctx->msg_options & GNUNET_DHT_RO_RECORD_ROUTE))
  2074. {
  2075. new_msg_ctx->msg_options = GNUNET_DHT_RO_RECORD_ROUTE;
  2076. new_msg_ctx->path_history_len = msg_ctx->path_history_len;
  2077. /* Assign to previous msg_ctx path history, caller should free after our return */
  2078. new_msg_ctx->path_history = msg_ctx->path_history;
  2079. #if DEBUG_PATH
  2080. for (i = 0; i < new_msg_ctx->path_history_len; i++)
  2081. {
  2082. path_offset =
  2083. &new_msg_ctx->path_history[i * sizeof (struct GNUNET_PeerIdentity)];
  2084. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2085. "(get_iterator) Key %s Found peer %d:%s\n",
  2086. GNUNET_h2s (&msg_ctx->key), i,
  2087. GNUNET_i2s ((struct GNUNET_PeerIdentity *) path_offset));
  2088. }
  2089. #endif
  2090. }
  2091. get_size =
  2092. sizeof (struct GNUNET_DHT_GetResultMessage) + put_entry->data_size +
  2093. (put_entry->path_length * sizeof (struct GNUNET_PeerIdentity));
  2094. get_result = GNUNET_malloc (get_size);
  2095. get_result->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_GET_RESULT);
  2096. get_result->header.size = htons (get_size);
  2097. get_result->expiration = GNUNET_TIME_absolute_hton (exp);
  2098. get_result->type = htons (type);
  2099. get_result->put_path_length = htons (put_entry->path_length);
  2100. path_offset = (char *) &put_entry[1];
  2101. path_offset += put_entry->data_size;
  2102. #if DEBUG_PATH
  2103. for (i = 0; i < put_entry->path_length; i++)
  2104. {
  2105. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2106. "(get_iterator PUT path) Key %s Found peer %d:%s\n",
  2107. GNUNET_h2s (&msg_ctx->key), i,
  2108. GNUNET_i2s ((struct GNUNET_PeerIdentity *)
  2109. &path_offset[i *
  2110. sizeof (struct
  2111. GNUNET_PeerIdentity)]));
  2112. }
  2113. #endif
  2114. /* Copy the actual data and the path_history to the end of the get result */
  2115. memcpy (&get_result[1], &put_entry[1],
  2116. put_entry->data_size +
  2117. (put_entry->path_length * sizeof (struct GNUNET_PeerIdentity)));
  2118. new_msg_ctx->peer = &my_identity;
  2119. new_msg_ctx->bloom =
  2120. GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K);
  2121. new_msg_ctx->hop_count = 0;
  2122. new_msg_ctx->importance = DHT_DEFAULT_P2P_IMPORTANCE + 2; /* Make result routing a higher priority */
  2123. new_msg_ctx->timeout = DHT_DEFAULT_P2P_TIMEOUT;
  2124. increment_stats (STAT_GET_RESPONSE_START);
  2125. route_result_message (&get_result->header, new_msg_ctx);
  2126. GNUNET_free (new_msg_ctx);
  2127. GNUNET_free (get_result);
  2128. break;
  2129. case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
  2130. #if DEBUG_DHT
  2131. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s:%s': Duplicate block error\n",
  2132. my_short_id, "DHT");
  2133. #endif
  2134. break;
  2135. case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
  2136. #if DEBUG_DHT
  2137. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "`%s:%s': Invalid request error\n",
  2138. my_short_id, "DHT");
  2139. #endif
  2140. break;
  2141. case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
  2142. #if DEBUG_DHT
  2143. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2144. "`%s:%s': Valid request, no results.\n", my_short_id, "DHT");
  2145. #endif
  2146. GNUNET_break (0);
  2147. break;
  2148. case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
  2149. GNUNET_break_op (0);
  2150. msg_ctx->do_forward = GNUNET_NO;
  2151. break;
  2152. case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
  2153. #if DEBUG_DHT
  2154. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2155. "`%s:%s': Unsupported block type (%u) in response!\n",
  2156. my_short_id, "DHT", type);
  2157. #endif
  2158. /* msg_ctx->do_forward = GNUNET_NO; // not sure... */
  2159. break;
  2160. }
  2161. return GNUNET_OK;
  2162. }
  2163. /**
  2164. * Main function that handles whether or not to route a message to other
  2165. * peers.
  2166. *
  2167. * @param msg the message to be routed
  2168. * @param msg_ctx the context containing all pertinent information about the message
  2169. */
  2170. static void
  2171. route_message (const struct GNUNET_MessageHeader *msg,
  2172. struct DHT_MessageContext *msg_ctx);
  2173. /**
  2174. * Server handler for all dht get requests, look for data,
  2175. * if found, send response either to clients or other peers.
  2176. *
  2177. * @param msg the actual get message
  2178. * @param msg_ctx struct containing pertinent information about the get request
  2179. *
  2180. * @return number of items found for GET request
  2181. */
  2182. static unsigned int
  2183. handle_dht_get (const struct GNUNET_MessageHeader *msg,
  2184. struct DHT_MessageContext *msg_ctx)
  2185. {
  2186. const struct GNUNET_DHT_GetMessage *get_msg;
  2187. uint16_t msize;
  2188. uint16_t bf_size;
  2189. unsigned int results;
  2190. const char *end;
  2191. enum GNUNET_BLOCK_Type type;
  2192. msize = ntohs (msg->size);
  2193. if (msize < sizeof (struct GNUNET_DHT_GetMessage))
  2194. {
  2195. GNUNET_break (0);
  2196. return 0;
  2197. }
  2198. get_msg = (const struct GNUNET_DHT_GetMessage *) msg;
  2199. bf_size = ntohs (get_msg->bf_size);
  2200. msg_ctx->xquery_size = ntohs (get_msg->xquery_size);
  2201. msg_ctx->reply_bf_mutator = get_msg->bf_mutator; /* FIXME: ntohl? */
  2202. if (msize !=
  2203. sizeof (struct GNUNET_DHT_GetMessage) + bf_size + msg_ctx->xquery_size)
  2204. {
  2205. GNUNET_break (0);
  2206. return 0;
  2207. }
  2208. end = (const char *) &get_msg[1];
  2209. if (msg_ctx->xquery_size == 0)
  2210. {
  2211. msg_ctx->xquery = NULL;
  2212. }
  2213. else
  2214. {
  2215. msg_ctx->xquery = (const void *) end;
  2216. end += msg_ctx->xquery_size;
  2217. }
  2218. if (bf_size == 0)
  2219. {
  2220. msg_ctx->reply_bf = NULL;
  2221. }
  2222. else
  2223. {
  2224. msg_ctx->reply_bf =
  2225. GNUNET_CONTAINER_bloomfilter_init (end, bf_size,
  2226. GNUNET_DHT_GET_BLOOMFILTER_K);
  2227. }
  2228. type = (enum GNUNET_BLOCK_Type) ntohl (get_msg->type);
  2229. #if DEBUG_DHT
  2230. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2231. "`%s:%s': Received `%s' request, message type %u, key %s, uid %llu\n",
  2232. my_short_id, "DHT", "GET", type, GNUNET_h2s (&msg_ctx->key),
  2233. msg_ctx->unique_id);
  2234. #endif
  2235. increment_stats (STAT_GETS);
  2236. results = 0;
  2237. #if HAVE_MALICIOUS
  2238. if (type == GNUNET_BLOCK_DHT_MALICIOUS_MESSAGE_TYPE)
  2239. {
  2240. GNUNET_CONTAINER_bloomfilter_free (msg_ctx->reply_bf);
  2241. return results;
  2242. }
  2243. #endif
  2244. msg_ctx->do_forward = GNUNET_YES;
  2245. if (datacache != NULL)
  2246. results =
  2247. GNUNET_DATACACHE_get (datacache, &msg_ctx->key, type,
  2248. &datacache_get_iterator, msg_ctx);
  2249. #if DEBUG_DHT
  2250. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2251. "`%s:%s': Found %d results for `%s' request uid %llu\n",
  2252. my_short_id, "DHT", results, "GET", msg_ctx->unique_id);
  2253. #endif
  2254. if (results >= 1)
  2255. {
  2256. #if DEBUG_DHT_ROUTING
  2257. if ((debug_routes) && (dhtlog_handle != NULL))
  2258. {
  2259. dhtlog_handle->insert_query (NULL, msg_ctx->unique_id, DHTLOG_GET,
  2260. msg_ctx->hop_count, GNUNET_YES, &my_identity,
  2261. &msg_ctx->key);
  2262. }
  2263. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  2264. {
  2265. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_ROUTE,
  2266. msg_ctx->hop_count, GNUNET_YES, &my_identity,
  2267. &msg_ctx->key, msg_ctx->peer, NULL);
  2268. }
  2269. #endif
  2270. }
  2271. else
  2272. {
  2273. /* check query valid */
  2274. if (GNUNET_BLOCK_EVALUATION_REQUEST_INVALID ==
  2275. GNUNET_BLOCK_evaluate (block_context, type, &msg_ctx->key,
  2276. &msg_ctx->reply_bf, msg_ctx->reply_bf_mutator,
  2277. msg_ctx->xquery, msg_ctx->xquery_size, NULL, 0))
  2278. {
  2279. GNUNET_break_op (0);
  2280. msg_ctx->do_forward = GNUNET_NO;
  2281. }
  2282. }
  2283. if (msg_ctx->hop_count == 0) /* Locally initiated request */
  2284. {
  2285. #if DEBUG_DHT_ROUTING
  2286. if ((debug_routes) && (dhtlog_handle != NULL))
  2287. {
  2288. dhtlog_handle->insert_query (NULL, msg_ctx->unique_id, DHTLOG_GET,
  2289. msg_ctx->hop_count, GNUNET_NO, &my_identity,
  2290. &msg_ctx->key);
  2291. }
  2292. #endif
  2293. }
  2294. if (msg_ctx->do_forward == GNUNET_YES)
  2295. route_message (msg, msg_ctx);
  2296. GNUNET_CONTAINER_bloomfilter_free (msg_ctx->reply_bf);
  2297. return results;
  2298. }
  2299. static void
  2300. remove_recent_find_peer (void *cls,
  2301. const struct GNUNET_SCHEDULER_TaskContext *tc)
  2302. {
  2303. GNUNET_HashCode *key = cls;
  2304. GNUNET_assert (GNUNET_YES ==
  2305. GNUNET_CONTAINER_multihashmap_remove
  2306. (recent_find_peer_requests, key, NULL));
  2307. GNUNET_free (key);
  2308. }
  2309. /**
  2310. * Server handler for initiating local dht find peer requests
  2311. *
  2312. * @param find_msg the actual find peer message
  2313. * @param msg_ctx struct containing pertinent information about the request
  2314. *
  2315. */
  2316. static void
  2317. handle_dht_find_peer (const struct GNUNET_MessageHeader *find_msg,
  2318. struct DHT_MessageContext *msg_ctx)
  2319. {
  2320. struct GNUNET_MessageHeader *find_peer_result;
  2321. struct GNUNET_DHT_FindPeerMessage *find_peer_message;
  2322. struct DHT_MessageContext *new_msg_ctx;
  2323. struct GNUNET_CONTAINER_BloomFilter *incoming_bloom;
  2324. size_t hello_size;
  2325. size_t tsize;
  2326. GNUNET_HashCode *recent_hash;
  2327. struct GNUNET_MessageHeader *other_hello;
  2328. size_t other_hello_size;
  2329. struct GNUNET_PeerIdentity peer_id;
  2330. find_peer_message = (struct GNUNET_DHT_FindPeerMessage *) find_msg;
  2331. GNUNET_break_op (ntohs (find_msg->size) >=
  2332. (sizeof (struct GNUNET_DHT_FindPeerMessage)));
  2333. if (ntohs (find_msg->size) < sizeof (struct GNUNET_DHT_FindPeerMessage))
  2334. return;
  2335. other_hello = NULL;
  2336. other_hello_size = 0;
  2337. if (ntohs (find_msg->size) > sizeof (struct GNUNET_DHT_FindPeerMessage))
  2338. {
  2339. other_hello_size =
  2340. ntohs (find_msg->size) - sizeof (struct GNUNET_DHT_FindPeerMessage);
  2341. other_hello = GNUNET_malloc (other_hello_size);
  2342. memcpy (other_hello, &find_peer_message[1], other_hello_size);
  2343. if ((GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) other_hello) == 0)
  2344. || (GNUNET_OK !=
  2345. GNUNET_HELLO_get_id ((struct GNUNET_HELLO_Message *) other_hello,
  2346. &peer_id)))
  2347. {
  2348. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  2349. "Received invalid HELLO message in find peer request!\n");
  2350. GNUNET_free (other_hello);
  2351. return;
  2352. }
  2353. #if FIND_PEER_WITH_HELLO
  2354. if (GNUNET_YES == consider_peer (&peer_id))
  2355. {
  2356. increment_stats (STAT_HELLOS_PROVIDED);
  2357. GNUNET_TRANSPORT_offer_hello (transport_handle, other_hello, NULL, NULL);
  2358. GNUNET_CORE_peer_request_connect (coreAPI, &peer_id, NULL, NULL);
  2359. route_message (find_msg, msg_ctx);
  2360. GNUNET_free (other_hello);
  2361. return;
  2362. }
  2363. else /* We don't want this peer! */
  2364. {
  2365. route_message (find_msg, msg_ctx);
  2366. GNUNET_free (other_hello);
  2367. return;
  2368. }
  2369. #endif
  2370. }
  2371. #if DEBUG_DHT
  2372. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2373. "`%s:%s': Received `%s' request from client, key %s (msg size %d, we expected %d)\n",
  2374. my_short_id, "DHT", "FIND PEER", GNUNET_h2s (&msg_ctx->key),
  2375. ntohs (find_msg->size), sizeof (struct GNUNET_MessageHeader));
  2376. #endif
  2377. if (my_hello == NULL)
  2378. {
  2379. #if DEBUG_DHT
  2380. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2381. "`%s': Our HELLO is null, can't return.\n", "DHT");
  2382. #endif
  2383. GNUNET_free_non_null (other_hello);
  2384. route_message (find_msg, msg_ctx);
  2385. return;
  2386. }
  2387. incoming_bloom =
  2388. GNUNET_CONTAINER_bloomfilter_init (find_peer_message->bloomfilter,
  2389. DHT_BLOOM_SIZE, DHT_BLOOM_K);
  2390. if (GNUNET_YES ==
  2391. GNUNET_CONTAINER_bloomfilter_test (incoming_bloom,
  2392. &my_identity.hashPubKey))
  2393. {
  2394. increment_stats (STAT_BLOOM_FIND_PEER);
  2395. GNUNET_CONTAINER_bloomfilter_free (incoming_bloom);
  2396. GNUNET_free_non_null (other_hello);
  2397. route_message (find_msg, msg_ctx);
  2398. return; /* We match the bloomfilter, do not send a response to this peer (they likely already know us!) */
  2399. }
  2400. GNUNET_CONTAINER_bloomfilter_free (incoming_bloom);
  2401. #if RESTRICT_FIND_PEER
  2402. /**
  2403. * Ignore any find peer requests from a peer we have seen very recently.
  2404. */
  2405. if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (recent_find_peer_requests, &msg_ctx->key)) /* We have recently responded to a find peer request for this peer! */
  2406. {
  2407. increment_stats ("# dht find peer requests ignored (recently seen!)");
  2408. GNUNET_free_non_null (other_hello);
  2409. return;
  2410. }
  2411. /**
  2412. * Use this check to only allow the peer to respond to find peer requests if
  2413. * it would be beneficial to have the requesting peer in this peers routing
  2414. * table. Can be used to thwart peers flooding the network with find peer
  2415. * requests that we don't care about. However, if a new peer is joining
  2416. * the network and has no other peers this is a problem (assume all buckets
  2417. * full, no one will respond!).
  2418. */
  2419. memcpy (&peer_id.hashPubKey, &msg_ctx->key, sizeof (GNUNET_HashCode));
  2420. if (GNUNET_NO == consider_peer (&peer_id))
  2421. {
  2422. increment_stats ("# dht find peer requests ignored (do not need!)");
  2423. GNUNET_free_non_null (other_hello);
  2424. route_message (find_msg, msg_ctx);
  2425. return;
  2426. }
  2427. #endif
  2428. recent_hash = GNUNET_malloc (sizeof (GNUNET_HashCode));
  2429. memcpy (recent_hash, &msg_ctx->key, sizeof (GNUNET_HashCode));
  2430. if (GNUNET_SYSERR !=
  2431. GNUNET_CONTAINER_multihashmap_put (recent_find_peer_requests,
  2432. &msg_ctx->key, NULL,
  2433. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
  2434. {
  2435. #if DEBUG_DHT
  2436. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2437. "Adding recent remove task for key `%s`!\n",
  2438. GNUNET_h2s (&msg_ctx->key));
  2439. #endif
  2440. /* Only add a task if there wasn't one for this key already! */
  2441. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
  2442. (GNUNET_TIME_UNIT_SECONDS, 30),
  2443. &remove_recent_find_peer, recent_hash);
  2444. }
  2445. else
  2446. {
  2447. GNUNET_free (recent_hash);
  2448. #if DEBUG_DHT
  2449. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2450. "Received duplicate find peer request too soon!\n");
  2451. #endif
  2452. }
  2453. /* Simplistic find_peer functionality, always return our hello */
  2454. hello_size = ntohs (my_hello->size);
  2455. tsize = hello_size + sizeof (struct GNUNET_MessageHeader);
  2456. if (tsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
  2457. {
  2458. GNUNET_break_op (0);
  2459. GNUNET_free_non_null (other_hello);
  2460. return;
  2461. }
  2462. find_peer_result = GNUNET_malloc (tsize);
  2463. find_peer_result->type = htons (GNUNET_MESSAGE_TYPE_DHT_FIND_PEER_RESULT);
  2464. find_peer_result->size = htons (tsize);
  2465. memcpy (&find_peer_result[1], my_hello, hello_size);
  2466. #if DEBUG_DHT
  2467. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2468. "`%s': Sending hello size %d to requesting peer.\n", "DHT",
  2469. hello_size);
  2470. #endif
  2471. new_msg_ctx = GNUNET_malloc (sizeof (struct DHT_MessageContext));
  2472. memcpy (new_msg_ctx, msg_ctx, sizeof (struct DHT_MessageContext));
  2473. new_msg_ctx->peer = &my_identity;
  2474. new_msg_ctx->bloom =
  2475. GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K);
  2476. new_msg_ctx->hop_count = 0;
  2477. new_msg_ctx->importance = DHT_DEFAULT_P2P_IMPORTANCE + 2; /* Make find peer requests a higher priority */
  2478. new_msg_ctx->timeout = DHT_DEFAULT_P2P_TIMEOUT;
  2479. increment_stats (STAT_FIND_PEER_ANSWER);
  2480. if (GNUNET_DHT_RO_RECORD_ROUTE ==
  2481. (msg_ctx->msg_options & GNUNET_DHT_RO_RECORD_ROUTE))
  2482. {
  2483. new_msg_ctx->msg_options = GNUNET_DHT_RO_RECORD_ROUTE;
  2484. new_msg_ctx->path_history_len = msg_ctx->path_history_len;
  2485. /* Assign to previous msg_ctx path history, caller should free after our return */
  2486. new_msg_ctx->path_history = msg_ctx->path_history;
  2487. }
  2488. route_result_message (find_peer_result, new_msg_ctx);
  2489. GNUNET_free (new_msg_ctx);
  2490. #if DEBUG_DHT_ROUTING
  2491. if ((debug_routes) && (dhtlog_handle != NULL))
  2492. {
  2493. dhtlog_handle->insert_query (NULL, msg_ctx->unique_id, DHTLOG_FIND_PEER,
  2494. msg_ctx->hop_count, GNUNET_YES, &my_identity,
  2495. &msg_ctx->key);
  2496. }
  2497. #endif
  2498. GNUNET_free_non_null (other_hello);
  2499. GNUNET_free (find_peer_result);
  2500. route_message (find_msg, msg_ctx);
  2501. }
  2502. /**
  2503. * Task used to republish data.
  2504. * Forward declaration; function call loop.
  2505. *
  2506. * @param cls closure (a struct RepublishContext)
  2507. * @param tc runtime context for this task
  2508. */
  2509. static void
  2510. republish_content (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
  2511. /**
  2512. * Server handler for initiating local dht put requests
  2513. *
  2514. * @param msg the actual put message
  2515. * @param msg_ctx struct containing pertinent information about the request
  2516. */
  2517. static void
  2518. handle_dht_put (const struct GNUNET_MessageHeader *msg,
  2519. struct DHT_MessageContext *msg_ctx)
  2520. {
  2521. const struct GNUNET_DHT_PutMessage *put_msg;
  2522. struct DHTPutEntry *put_entry;
  2523. unsigned int put_size;
  2524. char *path_offset;
  2525. enum GNUNET_BLOCK_Type put_type;
  2526. size_t data_size;
  2527. int ret;
  2528. struct RepublishContext *put_context;
  2529. GNUNET_HashCode key;
  2530. GNUNET_assert (ntohs (msg->size) >= sizeof (struct GNUNET_DHT_PutMessage));
  2531. put_msg = (const struct GNUNET_DHT_PutMessage *) msg;
  2532. put_type = (enum GNUNET_BLOCK_Type) ntohl (put_msg->type);
  2533. #if HAVE_MALICIOUS
  2534. if (put_type == GNUNET_BLOCK_DHT_MALICIOUS_MESSAGE_TYPE)
  2535. {
  2536. #if DEBUG_DHT_ROUTING
  2537. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  2538. {
  2539. /** Log routes that die due to high load! */
  2540. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_ROUTE,
  2541. msg_ctx->hop_count, GNUNET_SYSERR,
  2542. &my_identity, &msg_ctx->key, msg_ctx->peer,
  2543. NULL);
  2544. }
  2545. #endif
  2546. return;
  2547. }
  2548. #endif
  2549. data_size =
  2550. ntohs (put_msg->header.size) - sizeof (struct GNUNET_DHT_PutMessage);
  2551. ret =
  2552. GNUNET_BLOCK_get_key (block_context, put_type, &put_msg[1], data_size,
  2553. &key);
  2554. if (GNUNET_NO == ret)
  2555. {
  2556. #if DEBUG_DHT_ROUTING
  2557. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  2558. {
  2559. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_ROUTE,
  2560. msg_ctx->hop_count, GNUNET_SYSERR,
  2561. &my_identity, &msg_ctx->key, msg_ctx->peer,
  2562. NULL);
  2563. }
  2564. #endif
  2565. /* invalid reply */
  2566. GNUNET_break_op (0);
  2567. return;
  2568. }
  2569. if ((GNUNET_YES == ret) &&
  2570. (0 != memcmp (&key, &msg_ctx->key, sizeof (GNUNET_HashCode))))
  2571. {
  2572. #if DEBUG_DHT_ROUTING
  2573. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  2574. {
  2575. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_ROUTE,
  2576. msg_ctx->hop_count, GNUNET_SYSERR,
  2577. &my_identity, &msg_ctx->key, msg_ctx->peer,
  2578. NULL);
  2579. }
  2580. #endif
  2581. /* invalid wrapper: key mismatch! */
  2582. GNUNET_break_op (0);
  2583. return;
  2584. }
  2585. /* ret == GNUNET_SYSERR means that there is no known relationship between
  2586. * data and the key, so we cannot check it */
  2587. #if DEBUG_DHT
  2588. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2589. "`%s:%s': Received `%s' request (inserting data!), message type %d, key %s, uid %llu\n",
  2590. my_short_id, "DHT", "PUT", put_type, GNUNET_h2s (&msg_ctx->key),
  2591. msg_ctx->unique_id);
  2592. #endif
  2593. #if DEBUG_DHT_ROUTING
  2594. if (msg_ctx->hop_count == 0) /* Locally initiated request */
  2595. {
  2596. if ((debug_routes) && (dhtlog_handle != NULL))
  2597. {
  2598. dhtlog_handle->insert_query (NULL, msg_ctx->unique_id, DHTLOG_PUT,
  2599. msg_ctx->hop_count, GNUNET_NO, &my_identity,
  2600. &msg_ctx->key);
  2601. }
  2602. }
  2603. #endif
  2604. if (msg_ctx->closest != GNUNET_YES)
  2605. {
  2606. route_message (msg, msg_ctx);
  2607. return;
  2608. }
  2609. #if DEBUG_DHT
  2610. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2611. "`%s:%s': Received `%s' request (inserting data!), message type %d, key %s, uid %llu\n",
  2612. my_short_id, "DHT", "PUT", put_type, GNUNET_h2s (&msg_ctx->key),
  2613. msg_ctx->unique_id);
  2614. #endif
  2615. #if DEBUG_DHT_ROUTING
  2616. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  2617. {
  2618. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_ROUTE,
  2619. msg_ctx->hop_count, GNUNET_YES, &my_identity,
  2620. &msg_ctx->key, msg_ctx->peer, NULL);
  2621. }
  2622. if ((debug_routes) && (dhtlog_handle != NULL))
  2623. {
  2624. dhtlog_handle->insert_query (NULL, msg_ctx->unique_id, DHTLOG_PUT,
  2625. msg_ctx->hop_count, GNUNET_YES, &my_identity,
  2626. &msg_ctx->key);
  2627. }
  2628. #endif
  2629. increment_stats (STAT_PUTS_INSERTED);
  2630. if (datacache != NULL)
  2631. {
  2632. /* Put size is actual data size plus struct overhead plus path length (if any) */
  2633. put_size =
  2634. data_size + sizeof (struct DHTPutEntry) +
  2635. (msg_ctx->path_history_len * sizeof (struct GNUNET_PeerIdentity));
  2636. put_entry = GNUNET_malloc (put_size);
  2637. put_entry->data_size = data_size;
  2638. put_entry->path_length = msg_ctx->path_history_len;
  2639. /* Copy data to end of put entry */
  2640. memcpy (&put_entry[1], &put_msg[1], data_size);
  2641. if (msg_ctx->path_history_len > 0)
  2642. {
  2643. /* Copy path after data */
  2644. path_offset = (char *) &put_entry[1];
  2645. path_offset += data_size;
  2646. memcpy (path_offset, msg_ctx->path_history,
  2647. msg_ctx->path_history_len * sizeof (struct GNUNET_PeerIdentity));
  2648. }
  2649. ret =
  2650. GNUNET_DATACACHE_put (datacache, &msg_ctx->key, put_size,
  2651. (const char *) put_entry, put_type,
  2652. GNUNET_TIME_absolute_ntoh (put_msg->expiration));
  2653. GNUNET_free (put_entry);
  2654. if ((ret == GNUNET_YES) && (do_republish == GNUNET_YES))
  2655. {
  2656. put_context = GNUNET_malloc (sizeof (struct RepublishContext));
  2657. memcpy (&put_context->key, &msg_ctx->key, sizeof (GNUNET_HashCode));
  2658. put_context->type = put_type;
  2659. GNUNET_SCHEDULER_add_delayed (dht_republish_frequency, &republish_content,
  2660. put_context);
  2661. }
  2662. }
  2663. else
  2664. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2665. "`%s:%s': %s request received, but have no datacache!\n",
  2666. my_short_id, "DHT", "PUT");
  2667. if (stop_on_closest == GNUNET_NO)
  2668. route_message (msg, msg_ctx);
  2669. }
  2670. /**
  2671. * Estimate the diameter of the network based
  2672. * on how many buckets are currently in use.
  2673. * Concept here is that the diameter of the network
  2674. * is roughly the distance a message must travel in
  2675. * order to reach its intended destination. Since
  2676. * at each hop we expect to get one bit closer, and
  2677. * we have one bit per bucket, the number of buckets
  2678. * in use should be the largest number of hops for
  2679. * a successful message. (of course, this assumes we
  2680. * know all peers in the network!)
  2681. *
  2682. * @return ballpark diameter figure
  2683. */
  2684. static unsigned int
  2685. estimate_diameter ()
  2686. {
  2687. return MAX_BUCKETS - lowest_bucket;
  2688. }
  2689. /**
  2690. * To how many peers should we (on average)
  2691. * forward the request to obtain the desired
  2692. * target_replication count (on average).
  2693. *
  2694. * returns: target_replication / (est. hops) + (target_replication * hop_count)
  2695. * where est. hops is typically 2 * the routing table depth
  2696. *
  2697. * @param hop_count number of hops the message has traversed
  2698. * @param target_replication the number of total paths desired
  2699. *
  2700. * @return Some number of peers to forward the message to
  2701. */
  2702. static unsigned int
  2703. get_forward_count (unsigned int hop_count, size_t target_replication)
  2704. {
  2705. uint32_t random_value;
  2706. unsigned int forward_count;
  2707. float target_value;
  2708. unsigned int diameter;
  2709. diameter = estimate_diameter ();
  2710. if (GNUNET_NO == use_max_hops)
  2711. max_hops = (diameter + 1) * 2;
  2712. /**
  2713. * If we are behaving in strict kademlia mode, send multiple initial requests,
  2714. * but then only send to 1 or 0 peers based strictly on the number of hops.
  2715. */
  2716. if (strict_kademlia == GNUNET_YES)
  2717. {
  2718. if (hop_count == 0)
  2719. return kademlia_replication;
  2720. else if (hop_count < max_hops)
  2721. return 1;
  2722. else
  2723. return 0;
  2724. }
  2725. /* FIXME: the smaller we think the network is the more lenient we should be for
  2726. * routing right? The estimation below only works if we think we have reasonably
  2727. * full routing tables, which for our RR topologies may not be the case!
  2728. */
  2729. if (hop_count > max_hops)
  2730. {
  2731. #if DEBUG_DHT
  2732. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2733. "`%s:%s': Hop count too high (est %d, lowest %d), NOT Forwarding request\n",
  2734. my_short_id, "DHT", estimate_diameter (), lowest_bucket);
  2735. #endif
  2736. /* FIXME: does this work as intended, isn't the decision to forward or not made based on closeness as well? */
  2737. if (GNUNET_YES == paper_forwarding) /* Once we have reached our ideal number of hops, don't stop forwarding! */
  2738. {
  2739. return 1;
  2740. }
  2741. return 0;
  2742. }
  2743. if (GNUNET_YES == paper_forwarding)
  2744. {
  2745. /* FIXME: re-run replication trials with this formula */
  2746. target_value =
  2747. 1 + (target_replication - 1.0) / (diameter +
  2748. ((float) (target_replication - 1.0) *
  2749. hop_count));
  2750. /* Set forward count to floor of target_value */
  2751. forward_count = (unsigned int) target_value;
  2752. /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
  2753. target_value = target_value - forward_count;
  2754. random_value =
  2755. GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, UINT32_MAX);
  2756. if (random_value < (target_value * UINT32_MAX))
  2757. forward_count += 1;
  2758. }
  2759. else
  2760. {
  2761. random_value = 0;
  2762. forward_count = 1;
  2763. target_value =
  2764. target_replication / (diameter +
  2765. ((float) target_replication * hop_count));
  2766. if (target_value > 1)
  2767. {
  2768. /* Set forward count to floor of target_value */
  2769. forward_count = (unsigned int) target_value;
  2770. /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
  2771. target_value = target_value - forward_count;
  2772. }
  2773. else
  2774. random_value =
  2775. GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, UINT32_MAX);
  2776. if (random_value < (target_value * UINT32_MAX))
  2777. forward_count += 1;
  2778. }
  2779. return forward_count;
  2780. }
  2781. /*
  2782. * Check whether my identity is closer than any known peers.
  2783. * If a non-null bloomfilter is given, check if this is the closest
  2784. * peer that hasn't already been routed to.
  2785. *
  2786. * @param target hash code to check closeness to
  2787. * @param bloom bloomfilter, exclude these entries from the decision
  2788. *
  2789. * Return GNUNET_YES if node location is closest, GNUNET_NO
  2790. * otherwise.
  2791. */
  2792. int
  2793. am_closest_peer (const GNUNET_HashCode * target,
  2794. struct GNUNET_CONTAINER_BloomFilter *bloom)
  2795. {
  2796. int bits;
  2797. int other_bits;
  2798. int bucket_num;
  2799. int count;
  2800. struct PeerInfo *pos;
  2801. unsigned int my_distance;
  2802. if (0 == memcmp (&my_identity.hashPubKey, target, sizeof (GNUNET_HashCode)))
  2803. return GNUNET_YES;
  2804. bucket_num = find_current_bucket (target);
  2805. bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity.hashPubKey, target);
  2806. my_distance = distance (&my_identity.hashPubKey, target);
  2807. pos = k_buckets[bucket_num].head;
  2808. count = 0;
  2809. while ((pos != NULL) && (count < bucket_size))
  2810. {
  2811. if ((bloom != NULL) &&
  2812. (GNUNET_YES ==
  2813. GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey)))
  2814. {
  2815. pos = pos->next;
  2816. continue; /* Skip already checked entries */
  2817. }
  2818. other_bits = GNUNET_CRYPTO_hash_matching_bits (&pos->id.hashPubKey, target);
  2819. if (other_bits > bits)
  2820. return GNUNET_NO;
  2821. else if (other_bits == bits) /* We match the same number of bits */
  2822. {
  2823. if (strict_kademlia != GNUNET_YES) /* Return that we at as close as any other peer */
  2824. return GNUNET_YES;
  2825. else if (distance (&pos->id.hashPubKey, target) < my_distance) /* Check all known peers, only return if we are the true closest */
  2826. return GNUNET_NO;
  2827. }
  2828. pos = pos->next;
  2829. }
  2830. /* No peers closer, we are the closest! */
  2831. return GNUNET_YES;
  2832. }
  2833. /**
  2834. * Return this peers adjusted value based on the convergence
  2835. * function chosen. This is the key function for randomized
  2836. * routing decisions.
  2837. *
  2838. * @param target the key of the request
  2839. * @param peer the peer we would like the value of
  2840. * @param hops number of hops this message has already traveled
  2841. *
  2842. * @return bit distance from target to peer raised to an exponent
  2843. * adjusted based on the current routing convergence algorithm
  2844. *
  2845. */
  2846. static unsigned long long
  2847. converge_distance (const GNUNET_HashCode * target, struct PeerInfo *peer,
  2848. unsigned int hops)
  2849. {
  2850. unsigned long long ret;
  2851. unsigned int other_matching_bits;
  2852. double base_converge_modifier = .1; /* Value that "looks" good (when plotted), have to start somewhere */
  2853. double temp_modifier;
  2854. double calc_value;
  2855. double exponent;
  2856. int curr_max_hops;
  2857. if (use_max_hops)
  2858. curr_max_hops = max_hops;
  2859. else
  2860. curr_max_hops = (estimate_diameter () + 1) * 2;
  2861. if (converge_modifier > 0)
  2862. temp_modifier = converge_modifier * base_converge_modifier;
  2863. else
  2864. {
  2865. temp_modifier = base_converge_modifier;
  2866. base_converge_modifier = 0.0;
  2867. }
  2868. GNUNET_assert (temp_modifier > 0);
  2869. other_matching_bits =
  2870. GNUNET_CRYPTO_hash_matching_bits (target, &peer->id.hashPubKey);
  2871. switch (converge_option)
  2872. {
  2873. case DHT_CONVERGE_RANDOM:
  2874. return 1; /* Always return 1, choose equally among all peers */
  2875. case DHT_CONVERGE_LINEAR:
  2876. calc_value = hops * curr_max_hops * temp_modifier;
  2877. break;
  2878. case DHT_CONVERGE_SQUARE:
  2879. /**
  2880. * Simple square based curve.
  2881. */
  2882. calc_value =
  2883. (sqrt (hops) / sqrt (curr_max_hops)) * (curr_max_hops /
  2884. (curr_max_hops *
  2885. temp_modifier));
  2886. break;
  2887. case DHT_CONVERGE_EXPONENTIAL:
  2888. /**
  2889. * Simple exponential curve.
  2890. */
  2891. if (base_converge_modifier > 0)
  2892. calc_value = (temp_modifier * hops * hops) / curr_max_hops;
  2893. else
  2894. calc_value = (hops * hops) / curr_max_hops;
  2895. break;
  2896. case DHT_CONVERGE_BINARY:
  2897. /**
  2898. * If below the cutoff, route randomly (return 1),
  2899. * If above the cutoff, return the maximum possible
  2900. * value first (always route to closest, because
  2901. * they are sorted.)
  2902. */
  2903. if (hops >= converge_modifier) /* Past cutoff */
  2904. {
  2905. return ULLONG_MAX;
  2906. }
  2907. /* Fall through */
  2908. default:
  2909. return 1;
  2910. }
  2911. /* Take the log (base e) of the number of bits matching the other peer */
  2912. exponent = log (other_matching_bits);
  2913. /* Check if we would overflow; our largest possible value is 2^64 approx. e^44.361419555836498 */
  2914. if (exponent * calc_value >= 44.361419555836498)
  2915. return ULLONG_MAX;
  2916. /* Clear errno and all math exceptions */
  2917. errno = 0;
  2918. feclearexcept (FE_ALL_EXCEPT);
  2919. ret = (unsigned long long) pow (other_matching_bits, calc_value);
  2920. if ((errno != 0) ||
  2921. fetestexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW))
  2922. {
  2923. if (0 != fetestexcept (FE_OVERFLOW))
  2924. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "FE_OVERFLOW\n");
  2925. if (0 != fetestexcept (FE_INVALID))
  2926. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "FE_INVALID\n");
  2927. if (0 != fetestexcept (FE_UNDERFLOW))
  2928. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "FE_UNDERFLOW\n");
  2929. return 0;
  2930. }
  2931. else
  2932. return ret;
  2933. }
  2934. /**
  2935. * Comparison function for two struct PeerInfo's
  2936. * which have already had their matching bits to
  2937. * some target calculated.
  2938. *
  2939. * @param p1 a pointer pointer to a struct PeerInfo
  2940. * @param p2 a pointer pointer to a struct PeerInfo
  2941. *
  2942. * @return 0 if equidistant to target,
  2943. * -1 if p1 is closer,
  2944. * 1 if p2 is closer
  2945. */
  2946. static int
  2947. compare_peers (const void *p1, const void *p2)
  2948. {
  2949. struct PeerInfo **first = (struct PeerInfo **) p1;
  2950. struct PeerInfo **second = (struct PeerInfo **) p2;
  2951. if ((*first)->matching_bits > (*second)->matching_bits)
  2952. return -1;
  2953. if ((*first)->matching_bits < (*second)->matching_bits)
  2954. return 1;
  2955. else
  2956. return 0;
  2957. }
  2958. /**
  2959. * Select a peer from the routing table that would be a good routing
  2960. * destination for sending a message for "target". The resulting peer
  2961. * must not be in the set of blocked peers.<p>
  2962. *
  2963. * Note that we should not ALWAYS select the closest peer to the
  2964. * target, peers further away from the target should be chosen with
  2965. * exponentially declining probability.
  2966. *
  2967. * @param target the key we are selecting a peer to route to
  2968. * @param bloom a bloomfilter containing entries this request has seen already
  2969. * @param hops how many hops has this message traversed thus far
  2970. *
  2971. * @return Peer to route to, or NULL on error
  2972. */
  2973. static struct PeerInfo *
  2974. select_peer (const GNUNET_HashCode * target,
  2975. struct GNUNET_CONTAINER_BloomFilter *bloom, unsigned int hops)
  2976. {
  2977. unsigned int bc;
  2978. unsigned int i;
  2979. unsigned int count;
  2980. unsigned int offset;
  2981. int closest_bucket;
  2982. struct PeerInfo *pos;
  2983. struct PeerInfo *sorted_closest[bucket_size];
  2984. unsigned long long temp_converge_distance;
  2985. unsigned long long total_distance;
  2986. unsigned long long selected;
  2987. #if DEBUG_DHT > 1
  2988. unsigned long long stats_total_distance;
  2989. double sum;
  2990. #endif
  2991. /* For kademlia */
  2992. unsigned int distance;
  2993. unsigned int largest_distance;
  2994. struct PeerInfo *chosen;
  2995. total_distance = 0;
  2996. /** If we are doing kademlia routing, or converge is binary (saves some cycles) */
  2997. if ((strict_kademlia == GNUNET_YES) ||
  2998. ((converge_option == DHT_CONVERGE_BINARY) && (hops >= converge_modifier)))
  2999. {
  3000. largest_distance = 0;
  3001. chosen = NULL;
  3002. for (bc = lowest_bucket; bc < MAX_BUCKETS; bc++)
  3003. {
  3004. pos = k_buckets[bc].head;
  3005. count = 0;
  3006. while ((pos != NULL) && (count < bucket_size))
  3007. {
  3008. /* If we are doing strict Kademlia routing, then checking the bloomfilter is basically cheating! */
  3009. if (GNUNET_NO ==
  3010. GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
  3011. {
  3012. distance = inverse_distance (target, &pos->id.hashPubKey);
  3013. if (distance > largest_distance)
  3014. {
  3015. chosen = pos;
  3016. largest_distance = distance;
  3017. }
  3018. }
  3019. count++;
  3020. pos = pos->next;
  3021. }
  3022. }
  3023. if ((largest_distance > 0) && (chosen != NULL))
  3024. {
  3025. GNUNET_CONTAINER_bloomfilter_add (bloom, &chosen->id.hashPubKey);
  3026. return chosen;
  3027. }
  3028. else
  3029. {
  3030. return NULL;
  3031. }
  3032. }
  3033. /* GNUnet-style */
  3034. total_distance = 0;
  3035. /* Three steps: order peers in closest bucket (most matching bits).
  3036. * Then go over all LOWER buckets (matching same bits we do)
  3037. * Then go over all HIGHER buckets (matching less then we do)
  3038. */
  3039. closest_bucket = find_current_bucket (target);
  3040. GNUNET_assert (closest_bucket >= lowest_bucket);
  3041. pos = k_buckets[closest_bucket].head;
  3042. count = 0;
  3043. offset = 0; /* Need offset as well as count in case peers are bloomfiltered */
  3044. memset (sorted_closest, 0, sizeof (sorted_closest));
  3045. /* Put any peers in the closest bucket in the sorting array */
  3046. while ((pos != NULL) && (count < bucket_size))
  3047. {
  3048. if (GNUNET_YES ==
  3049. GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
  3050. {
  3051. count++;
  3052. pos = pos->next;
  3053. continue; /* Ignore bloomfiltered peers */
  3054. }
  3055. pos->matching_bits =
  3056. GNUNET_CRYPTO_hash_matching_bits (&pos->id.hashPubKey, target);
  3057. sorted_closest[offset] = pos;
  3058. pos = pos->next;
  3059. offset++;
  3060. count++;
  3061. }
  3062. /* Sort the peers in descending order */
  3063. qsort (&sorted_closest[0], offset, sizeof (struct PeerInfo *),
  3064. &compare_peers);
  3065. /* Put the sorted closest peers into the possible bins first, in case of overflow. */
  3066. for (i = 0; i < offset; i++)
  3067. {
  3068. temp_converge_distance =
  3069. converge_distance (target, sorted_closest[i], hops);
  3070. if (GNUNET_YES ==
  3071. GNUNET_CONTAINER_bloomfilter_test (bloom,
  3072. &sorted_closest[i]->id.hashPubKey))
  3073. break; /* Ignore bloomfiltered peers */
  3074. if (total_distance + temp_converge_distance > total_distance) /* Handle largest case and overflow */
  3075. total_distance += temp_converge_distance;
  3076. else
  3077. break; /* overflow case */
  3078. }
  3079. /* Now handle peers in lower buckets (matches same # of bits as target) */
  3080. for (bc = lowest_bucket; bc < closest_bucket; bc++)
  3081. {
  3082. pos = k_buckets[bc].head;
  3083. count = 0;
  3084. while ((pos != NULL) && (count < bucket_size))
  3085. {
  3086. if (GNUNET_YES ==
  3087. GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
  3088. {
  3089. count++;
  3090. pos = pos->next;
  3091. continue; /* Ignore bloomfiltered peers */
  3092. }
  3093. temp_converge_distance = converge_distance (target, pos, hops);
  3094. if (total_distance + temp_converge_distance > total_distance) /* Handle largest case and overflow */
  3095. total_distance += temp_converge_distance;
  3096. else
  3097. break; /* overflow case */
  3098. pos = pos->next;
  3099. count++;
  3100. }
  3101. }
  3102. /* Now handle all the further away peers */
  3103. for (bc = closest_bucket + 1; bc < MAX_BUCKETS; bc++)
  3104. {
  3105. pos = k_buckets[bc].head;
  3106. count = 0;
  3107. while ((pos != NULL) && (count < bucket_size))
  3108. {
  3109. if (GNUNET_YES ==
  3110. GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
  3111. {
  3112. count++;
  3113. pos = pos->next;
  3114. continue; /* Ignore bloomfiltered peers */
  3115. }
  3116. temp_converge_distance = converge_distance (target, pos, hops);
  3117. if (total_distance + temp_converge_distance > total_distance) /* Handle largest case and overflow */
  3118. total_distance += temp_converge_distance;
  3119. else
  3120. break; /* overflow case */
  3121. pos = pos->next;
  3122. count++;
  3123. }
  3124. }
  3125. if (total_distance == 0) /* No peers to select from! */
  3126. {
  3127. increment_stats ("# failed to select peer");
  3128. return NULL;
  3129. }
  3130. #if DEBUG_DHT_ROUTING > 1
  3131. sum = 0.0;
  3132. /* PRINT STATS */
  3133. /* Put the sorted closest peers into the possible bins first, in case of overflow. */
  3134. stats_total_distance = 0;
  3135. for (i = 0; i < offset; i++)
  3136. {
  3137. if (GNUNET_YES ==
  3138. GNUNET_CONTAINER_bloomfilter_test (bloom,
  3139. &sorted_closest[i]->id.hashPubKey))
  3140. break; /* Ignore bloomfiltered peers */
  3141. temp_converge_distance =
  3142. converge_distance (target, sorted_closest[i], hops);
  3143. if (stats_total_distance + temp_converge_distance > stats_total_distance) /* Handle largest case and overflow */
  3144. stats_total_distance += temp_converge_distance;
  3145. else
  3146. break; /* overflow case */
  3147. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3148. "Choose %d matching bits (%d bits match me) (%.2f percent) converge ret %llu\n",
  3149. GNUNET_CRYPTO_hash_matching_bits (&sorted_closest[i]->id.
  3150. hashPubKey, target),
  3151. GNUNET_CRYPTO_hash_matching_bits (&sorted_closest[i]->id.
  3152. hashPubKey,
  3153. &my_identity.hashPubKey),
  3154. (temp_converge_distance / (double) total_distance) * 100,
  3155. temp_converge_distance);
  3156. }
  3157. /* Now handle peers in lower buckets (matches same # of bits as target) */
  3158. for (bc = lowest_bucket; bc < closest_bucket; bc++)
  3159. {
  3160. pos = k_buckets[bc].head;
  3161. count = 0;
  3162. while ((pos != NULL) && (count < bucket_size))
  3163. {
  3164. if (GNUNET_YES ==
  3165. GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
  3166. {
  3167. count++;
  3168. pos = pos->next;
  3169. continue; /* Ignore bloomfiltered peers */
  3170. }
  3171. temp_converge_distance = converge_distance (target, pos, hops);
  3172. if (stats_total_distance + temp_converge_distance > stats_total_distance) /* Handle largest case and overflow */
  3173. stats_total_distance += temp_converge_distance;
  3174. else
  3175. break; /* overflow case */
  3176. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3177. "Choose %d matching bits (%d bits match me) (%.2f percent) converge ret %llu\n",
  3178. GNUNET_CRYPTO_hash_matching_bits (&pos->id.hashPubKey,
  3179. target),
  3180. GNUNET_CRYPTO_hash_matching_bits (&pos->id.hashPubKey,
  3181. &my_identity.hashPubKey),
  3182. (temp_converge_distance / (double) total_distance) * 100,
  3183. temp_converge_distance);
  3184. pos = pos->next;
  3185. count++;
  3186. }
  3187. }
  3188. /* Now handle all the further away peers */
  3189. for (bc = closest_bucket + 1; bc < MAX_BUCKETS; bc++)
  3190. {
  3191. pos = k_buckets[bc].head;
  3192. count = 0;
  3193. while ((pos != NULL) && (count < bucket_size))
  3194. {
  3195. if (GNUNET_YES ==
  3196. GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
  3197. {
  3198. count++;
  3199. pos = pos->next;
  3200. continue; /* Ignore bloomfiltered peers */
  3201. }
  3202. temp_converge_distance = converge_distance (target, pos, hops);
  3203. if (stats_total_distance + temp_converge_distance > stats_total_distance) /* Handle largest case and overflow */
  3204. stats_total_distance += temp_converge_distance;
  3205. else
  3206. break; /* overflow case */
  3207. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3208. "Choose %d matching bits (%d bits match me) (%.2f percent) converge ret %llu\n",
  3209. GNUNET_CRYPTO_hash_matching_bits (&pos->id.hashPubKey,
  3210. target),
  3211. GNUNET_CRYPTO_hash_matching_bits (&pos->id.hashPubKey,
  3212. &my_identity.hashPubKey),
  3213. (temp_converge_distance / (double) total_distance) * 100,
  3214. temp_converge_distance);
  3215. pos = pos->next;
  3216. count++;
  3217. }
  3218. }
  3219. /* END PRINT STATS */
  3220. #endif
  3221. /* Now actually choose a peer */
  3222. selected =
  3223. GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, total_distance);
  3224. /* Go over closest sorted peers. */
  3225. for (i = 0; i < offset; i++)
  3226. {
  3227. if (GNUNET_YES ==
  3228. GNUNET_CONTAINER_bloomfilter_test (bloom,
  3229. &sorted_closest[i]->id.hashPubKey))
  3230. break; /* Ignore bloomfiltered peers */
  3231. temp_converge_distance =
  3232. converge_distance (target, sorted_closest[i], hops);
  3233. if (temp_converge_distance >= selected)
  3234. return sorted_closest[i];
  3235. else
  3236. selected -= temp_converge_distance;
  3237. }
  3238. /* Now handle peers in lower buckets (matches same # of bits as target) */
  3239. for (bc = lowest_bucket; bc < closest_bucket; bc++)
  3240. {
  3241. pos = k_buckets[bc].head;
  3242. count = 0;
  3243. while ((pos != NULL) && (count < bucket_size))
  3244. {
  3245. if (GNUNET_YES ==
  3246. GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
  3247. {
  3248. count++;
  3249. pos = pos->next;
  3250. continue; /* Ignore bloomfiltered peers */
  3251. }
  3252. temp_converge_distance = converge_distance (target, pos, hops);
  3253. if (temp_converge_distance >= selected)
  3254. return pos;
  3255. else
  3256. selected -= temp_converge_distance;
  3257. pos = pos->next;
  3258. count++;
  3259. }
  3260. }
  3261. /* Now handle all the further away peers */
  3262. for (bc = closest_bucket + 1; bc < MAX_BUCKETS; bc++)
  3263. {
  3264. pos = k_buckets[bc].head;
  3265. count = 0;
  3266. while ((pos != NULL) && (count < bucket_size))
  3267. {
  3268. if (GNUNET_YES ==
  3269. GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
  3270. {
  3271. count++;
  3272. pos = pos->next;
  3273. continue; /* Ignore bloomfiltered peers */
  3274. }
  3275. temp_converge_distance = converge_distance (target, pos, hops);
  3276. if (temp_converge_distance >= selected)
  3277. return pos;
  3278. else
  3279. selected -= temp_converge_distance;
  3280. pos = pos->next;
  3281. count++;
  3282. }
  3283. }
  3284. increment_stats ("# failed to select peer");
  3285. return NULL;
  3286. }
  3287. /**
  3288. * Task used to remove recent entries, either
  3289. * after timeout, when full, or on shutdown.
  3290. *
  3291. * @param cls the entry to remove
  3292. * @param tc context, reason, etc.
  3293. */
  3294. static void
  3295. remove_recent (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  3296. {
  3297. struct RecentRequest *req = cls;
  3298. static GNUNET_HashCode hash;
  3299. GNUNET_assert (req != NULL);
  3300. hash_from_uid (req->uid, &hash);
  3301. GNUNET_assert (GNUNET_YES ==
  3302. GNUNET_CONTAINER_multihashmap_remove (recent.hashmap, &hash,
  3303. req));
  3304. GNUNET_CONTAINER_heap_remove_node (req->heap_node);
  3305. GNUNET_CONTAINER_bloomfilter_free (req->bloom);
  3306. GNUNET_free (req);
  3307. /*
  3308. * if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) && (0 == GNUNET_CONTAINER_multihashmap_size(recent.hashmap)) && (0 == GNUNET_CONTAINER_heap_get_size(recent.minHeap)))
  3309. * {
  3310. * GNUNET_CONTAINER_multihashmap_destroy(recent.hashmap);
  3311. * GNUNET_CONTAINER_heap_destroy(recent.minHeap);
  3312. * }
  3313. */
  3314. }
  3315. /**
  3316. * Remember this routing request so that if a reply is
  3317. * received we can either forward it to the correct peer
  3318. * or return the result locally.
  3319. *
  3320. * @param msg_ctx Context of the route request
  3321. *
  3322. * @return GNUNET_YES if this response was cached, GNUNET_NO if not
  3323. */
  3324. static int
  3325. cache_response (struct DHT_MessageContext *msg_ctx)
  3326. {
  3327. struct DHTQueryRecord *record;
  3328. struct DHTRouteSource *source_info;
  3329. struct DHTRouteSource *pos;
  3330. struct GNUNET_TIME_Absolute now;
  3331. unsigned int current_size;
  3332. current_size = GNUNET_CONTAINER_multihashmap_size (forward_list.hashmap);
  3333. #if DELETE_WHEN_FULL
  3334. while (current_size >= MAX_OUTSTANDING_FORWARDS)
  3335. {
  3336. source_info = GNUNET_CONTAINER_heap_remove_root (forward_list.minHeap);
  3337. GNUNET_assert (source_info != NULL);
  3338. record = source_info->record;
  3339. GNUNET_CONTAINER_DLL_remove (record->head, record->tail, source_info);
  3340. if (record->head == NULL) /* No more entries in DLL */
  3341. {
  3342. GNUNET_assert (GNUNET_YES ==
  3343. GNUNET_CONTAINER_multihashmap_remove (forward_list.hashmap,
  3344. &record->key,
  3345. record));
  3346. GNUNET_free (record);
  3347. }
  3348. if (source_info->delete_task != GNUNET_SCHEDULER_NO_TASK)
  3349. {
  3350. GNUNET_SCHEDULER_cancel (source_info->delete_task);
  3351. source_info->delete_task = GNUNET_SCHEDULER_NO_TASK;
  3352. }
  3353. if (source_info->find_peers_responded != NULL)
  3354. GNUNET_CONTAINER_bloomfilter_free (source_info->find_peers_responded);
  3355. GNUNET_free (source_info);
  3356. current_size = GNUNET_CONTAINER_multihashmap_size (forward_list.hashmap);
  3357. }
  3358. #endif
  3359. /** Non-local request and have too many outstanding forwards, discard! */
  3360. if ((current_size >= MAX_OUTSTANDING_FORWARDS) && (msg_ctx->client == NULL))
  3361. return GNUNET_NO;
  3362. now = GNUNET_TIME_absolute_get ();
  3363. record =
  3364. GNUNET_CONTAINER_multihashmap_get (forward_list.hashmap, &msg_ctx->key);
  3365. if (record != NULL) /* Already know this request! */
  3366. {
  3367. pos = record->head;
  3368. while (pos != NULL)
  3369. {
  3370. if (0 ==
  3371. memcmp (msg_ctx->peer, &pos->source,
  3372. sizeof (struct GNUNET_PeerIdentity)))
  3373. break; /* Already have this peer in reply list! */
  3374. pos = pos->next;
  3375. }
  3376. if ((pos != NULL) && (pos->client == msg_ctx->client)) /* Seen this already */
  3377. {
  3378. GNUNET_CONTAINER_heap_update_cost (forward_list.minHeap, pos->hnode,
  3379. now.abs_value);
  3380. return GNUNET_NO;
  3381. }
  3382. }
  3383. else
  3384. {
  3385. record = GNUNET_malloc (sizeof (struct DHTQueryRecord));
  3386. GNUNET_assert (GNUNET_OK ==
  3387. GNUNET_CONTAINER_multihashmap_put (forward_list.hashmap,
  3388. &msg_ctx->key, record,
  3389. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  3390. memcpy (&record->key, &msg_ctx->key, sizeof (GNUNET_HashCode));
  3391. }
  3392. source_info = GNUNET_malloc (sizeof (struct DHTRouteSource));
  3393. source_info->record = record;
  3394. source_info->delete_task =
  3395. GNUNET_SCHEDULER_add_delayed (DHT_FORWARD_TIMEOUT, &remove_forward_entry,
  3396. source_info);
  3397. source_info->find_peers_responded =
  3398. GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K);
  3399. memcpy (&source_info->source, msg_ctx->peer,
  3400. sizeof (struct GNUNET_PeerIdentity));
  3401. GNUNET_CONTAINER_DLL_insert_after (record->head, record->tail, record->tail,
  3402. source_info);
  3403. if (msg_ctx->client != NULL) /* For local request, set timeout so high it effectively never gets pushed out */
  3404. {
  3405. source_info->client = msg_ctx->client;
  3406. now = GNUNET_TIME_absolute_get_forever ();
  3407. }
  3408. source_info->hnode =
  3409. GNUNET_CONTAINER_heap_insert (forward_list.minHeap, source_info,
  3410. now.abs_value);
  3411. #if DEBUG_DHT > 1
  3412. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3413. "`%s:%s': Created new forward source info for %s uid %llu\n",
  3414. my_short_id, "DHT", GNUNET_h2s (&msg_ctx->key),
  3415. msg_ctx->unique_id);
  3416. #endif
  3417. return GNUNET_YES;
  3418. }
  3419. /**
  3420. * Main function that handles whether or not to route a message to other
  3421. * peers.
  3422. *
  3423. * @param msg the message to be routed
  3424. * @param msg_ctx the context containing all pertinent information about the message
  3425. */
  3426. static void
  3427. route_message (const struct GNUNET_MessageHeader *msg,
  3428. struct DHT_MessageContext *msg_ctx)
  3429. {
  3430. int i;
  3431. struct PeerInfo *selected;
  3432. #if DEBUG_DHT_ROUTING > 1
  3433. struct PeerInfo *nearest;
  3434. #endif
  3435. unsigned int target_forward_count;
  3436. unsigned int forward_count;
  3437. struct RecentRequest *recent_req;
  3438. GNUNET_HashCode unique_hash;
  3439. char *stat_forward_count;
  3440. char *temp_stat_str;
  3441. #if DEBUG_DHT_ROUTING
  3442. int ret;
  3443. #endif
  3444. if (malicious_dropper == GNUNET_YES)
  3445. {
  3446. #if DEBUG_DHT_ROUTING
  3447. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  3448. {
  3449. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_ROUTE,
  3450. msg_ctx->hop_count, GNUNET_SYSERR,
  3451. &my_identity, &msg_ctx->key, msg_ctx->peer,
  3452. NULL);
  3453. }
  3454. #endif
  3455. if (msg_ctx->bloom != NULL)
  3456. {
  3457. GNUNET_CONTAINER_bloomfilter_free (msg_ctx->bloom);
  3458. msg_ctx->bloom = NULL;
  3459. }
  3460. return;
  3461. }
  3462. increment_stats (STAT_ROUTES);
  3463. target_forward_count =
  3464. get_forward_count (msg_ctx->hop_count, msg_ctx->replication);
  3465. GNUNET_asprintf (&stat_forward_count, "# forward counts of %d",
  3466. target_forward_count);
  3467. increment_stats (stat_forward_count);
  3468. GNUNET_free (stat_forward_count);
  3469. if (msg_ctx->bloom == NULL)
  3470. msg_ctx->bloom =
  3471. GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K);
  3472. if ((stop_on_closest == GNUNET_YES) && (msg_ctx->closest == GNUNET_YES) &&
  3473. (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_DHT_PUT))
  3474. target_forward_count = 0;
  3475. /**
  3476. * NOTICE: In Kademlia, a find peer request goes no further if the peer doesn't return
  3477. * any closer peers (which is being checked for below). Since we are doing recursive
  3478. * routing we have no choice but to stop forwarding in this case. This means that at
  3479. * any given step the request may NOT be forwarded to alpha peers (because routes will
  3480. * stop and the parallel route will not be aware of it). Of course, assuming that we
  3481. * have fulfilled the Kademlia requirements for routing table fullness this will never
  3482. * ever ever be a problem.
  3483. *
  3484. * However, is this fair?
  3485. *
  3486. * Since we use these requests to build our routing tables (and we build them in the
  3487. * testing driver) we will ignore this restriction for FIND_PEER messages so that
  3488. * routing tables still get constructed.
  3489. */
  3490. if ((GNUNET_YES == strict_kademlia) && (msg_ctx->closest == GNUNET_YES) &&
  3491. (msg_ctx->hop_count > 0) &&
  3492. (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_DHT_FIND_PEER))
  3493. target_forward_count = 0;
  3494. GNUNET_CONTAINER_bloomfilter_add (msg_ctx->bloom, &my_identity.hashPubKey);
  3495. hash_from_uid (msg_ctx->unique_id, &unique_hash);
  3496. if (GNUNET_YES ==
  3497. GNUNET_CONTAINER_multihashmap_contains (recent.hashmap, &unique_hash))
  3498. {
  3499. recent_req =
  3500. GNUNET_CONTAINER_multihashmap_get (recent.hashmap, &unique_hash);
  3501. GNUNET_assert (recent_req != NULL);
  3502. if (0 != memcmp (&recent_req->key, &msg_ctx->key, sizeof (GNUNET_HashCode)))
  3503. increment_stats (STAT_DUPLICATE_UID);
  3504. else
  3505. {
  3506. increment_stats (STAT_RECENT_SEEN);
  3507. GNUNET_CONTAINER_bloomfilter_or2 (msg_ctx->bloom, recent_req->bloom,
  3508. DHT_BLOOM_SIZE);
  3509. }
  3510. }
  3511. else
  3512. {
  3513. recent_req = GNUNET_malloc (sizeof (struct RecentRequest));
  3514. recent_req->uid = msg_ctx->unique_id;
  3515. memcpy (&recent_req->key, &msg_ctx->key, sizeof (GNUNET_HashCode));
  3516. recent_req->remove_task =
  3517. GNUNET_SCHEDULER_add_delayed (DEFAULT_RECENT_REMOVAL, &remove_recent,
  3518. recent_req);
  3519. recent_req->heap_node =
  3520. GNUNET_CONTAINER_heap_insert (recent.minHeap, recent_req,
  3521. GNUNET_TIME_absolute_get ().abs_value);
  3522. recent_req->bloom =
  3523. GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K);
  3524. GNUNET_CONTAINER_multihashmap_put (recent.hashmap, &unique_hash, recent_req,
  3525. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
  3526. }
  3527. if (GNUNET_CONTAINER_multihashmap_size (recent.hashmap) > DHT_MAX_RECENT)
  3528. {
  3529. recent_req = GNUNET_CONTAINER_heap_peek (recent.minHeap);
  3530. GNUNET_assert (recent_req != NULL);
  3531. GNUNET_SCHEDULER_cancel (recent_req->remove_task);
  3532. GNUNET_SCHEDULER_add_now (&remove_recent, recent_req);
  3533. }
  3534. forward_count = 0;
  3535. for (i = 0; i < target_forward_count; i++)
  3536. {
  3537. selected = select_peer (&msg_ctx->key, msg_ctx->bloom, msg_ctx->hop_count);
  3538. if (selected != NULL)
  3539. {
  3540. forward_count++;
  3541. if (GNUNET_CRYPTO_hash_matching_bits
  3542. (&selected->id.hashPubKey,
  3543. &msg_ctx->key) >=
  3544. GNUNET_CRYPTO_hash_matching_bits (&my_identity.hashPubKey,
  3545. &msg_ctx->key))
  3546. GNUNET_asprintf (&temp_stat_str,
  3547. "# requests routed to close(r) peer hop %u",
  3548. msg_ctx->hop_count);
  3549. else
  3550. GNUNET_asprintf (&temp_stat_str,
  3551. "# requests routed to less close peer hop %u",
  3552. msg_ctx->hop_count);
  3553. if (temp_stat_str != NULL)
  3554. {
  3555. increment_stats (temp_stat_str);
  3556. GNUNET_free (temp_stat_str);
  3557. }
  3558. GNUNET_CONTAINER_bloomfilter_add (msg_ctx->bloom,
  3559. &selected->id.hashPubKey);
  3560. #if DEBUG_DHT_ROUTING > 1
  3561. nearest = find_closest_peer (&msg_ctx->key);
  3562. nearest_buf = GNUNET_strdup (GNUNET_i2s (&nearest->id));
  3563. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3564. "`%s:%s': Forwarding request key %s uid %llu to peer %s (closest %s, bits %d, distance %u)\n",
  3565. my_short_id, "DHT", GNUNET_h2s (&msg_ctx->key),
  3566. msg_ctx->unique_id, GNUNET_i2s (&selected->id), nearest_buf,
  3567. GNUNET_CRYPTO_hash_matching_bits (&nearest->id.hashPubKey,
  3568. msg_ctx->key),
  3569. distance (&nearest->id.hashPubKey, msg_ctx->key));
  3570. GNUNET_free (nearest_buf);
  3571. #endif
  3572. #if DEBUG_DHT_ROUTING
  3573. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  3574. {
  3575. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_ROUTE,
  3576. msg_ctx->hop_count, GNUNET_NO,
  3577. &my_identity, &msg_ctx->key, msg_ctx->peer,
  3578. &selected->id);
  3579. }
  3580. #endif
  3581. forward_message (msg, selected, msg_ctx);
  3582. }
  3583. }
  3584. if (msg_ctx->bloom != NULL)
  3585. {
  3586. GNUNET_CONTAINER_bloomfilter_or2 (recent_req->bloom, msg_ctx->bloom,
  3587. DHT_BLOOM_SIZE);
  3588. GNUNET_CONTAINER_bloomfilter_free (msg_ctx->bloom);
  3589. msg_ctx->bloom = NULL;
  3590. }
  3591. #if DEBUG_DHT_ROUTING
  3592. if (forward_count == 0)
  3593. ret = GNUNET_SYSERR;
  3594. else
  3595. ret = GNUNET_NO;
  3596. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  3597. {
  3598. dhtlog_handle->insert_route (NULL, msg_ctx->unique_id, DHTLOG_ROUTE,
  3599. msg_ctx->hop_count, ret, &my_identity,
  3600. &msg_ctx->key, msg_ctx->peer, NULL);
  3601. }
  3602. #endif
  3603. }
  3604. /**
  3605. * Main function that handles whether or not to route a message to other
  3606. * peers.
  3607. *
  3608. * @param msg the message to be routed
  3609. * @param msg_ctx the context containing all pertinent information about the message
  3610. */
  3611. static void
  3612. demultiplex_message (const struct GNUNET_MessageHeader *msg,
  3613. struct DHT_MessageContext *msg_ctx)
  3614. {
  3615. /* FIXME: Should we use closest excluding those we won't route to (the bloomfilter problem)? */
  3616. msg_ctx->closest = am_closest_peer (&msg_ctx->key, msg_ctx->bloom);
  3617. switch (ntohs (msg->type))
  3618. {
  3619. case GNUNET_MESSAGE_TYPE_DHT_GET: /* Add to hashmap of requests seen, search for data (always) */
  3620. cache_response (msg_ctx);
  3621. handle_dht_get (msg, msg_ctx);
  3622. break;
  3623. case GNUNET_MESSAGE_TYPE_DHT_PUT: /* Check if closest, if so insert data. */
  3624. increment_stats (STAT_PUTS);
  3625. handle_dht_put (msg, msg_ctx);
  3626. break;
  3627. case GNUNET_MESSAGE_TYPE_DHT_FIND_PEER: /* Check if closest and not started by us, check options, add to requests seen */
  3628. increment_stats (STAT_FIND_PEER);
  3629. if (((msg_ctx->hop_count > 0) &&
  3630. (0 !=
  3631. memcmp (msg_ctx->peer, &my_identity,
  3632. sizeof (struct GNUNET_PeerIdentity)))) ||
  3633. (msg_ctx->client != NULL))
  3634. {
  3635. cache_response (msg_ctx);
  3636. if ((msg_ctx->closest == GNUNET_YES) ||
  3637. (msg_ctx->msg_options == GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE))
  3638. handle_dht_find_peer (msg, msg_ctx);
  3639. }
  3640. else
  3641. route_message (msg, msg_ctx);
  3642. #if DEBUG_DHT_ROUTING
  3643. if (msg_ctx->hop_count == 0) /* Locally initiated request */
  3644. {
  3645. if ((debug_routes) && (dhtlog_handle != NULL))
  3646. {
  3647. dhtlog_handle->insert_dhtkey (NULL, &msg_ctx->key);
  3648. dhtlog_handle->insert_query (NULL, msg_ctx->unique_id, DHTLOG_FIND_PEER,
  3649. msg_ctx->hop_count, GNUNET_NO,
  3650. &my_identity, &msg_ctx->key);
  3651. }
  3652. }
  3653. #endif
  3654. break;
  3655. default:
  3656. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  3657. "`%s': Message type (%d) not handled, forwarding anyway!\n",
  3658. "DHT", ntohs (msg->type));
  3659. route_message (msg, msg_ctx);
  3660. }
  3661. }
  3662. /**
  3663. * Iterator for local get request results,
  3664. *
  3665. * @param cls closure for iterator, NULL
  3666. * @param exp when does this value expire?
  3667. * @param key the key this data is stored under
  3668. * @param size the size of the data identified by key
  3669. * @param data the actual data
  3670. * @param type the type of the data
  3671. *
  3672. * @return GNUNET_OK to continue iteration, anything else
  3673. * to stop iteration.
  3674. */
  3675. static int
  3676. republish_content_iterator (void *cls, struct GNUNET_TIME_Absolute exp,
  3677. const GNUNET_HashCode * key, size_t size,
  3678. const char *data, uint32_t type)
  3679. {
  3680. struct DHT_MessageContext *new_msg_ctx;
  3681. struct GNUNET_DHT_PutMessage *put_msg;
  3682. #if DEBUG_DHT
  3683. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3684. "`%s:%s': Received `%s' response from datacache\n", my_short_id,
  3685. "DHT", "GET");
  3686. #endif
  3687. new_msg_ctx = GNUNET_malloc (sizeof (struct DHT_MessageContext));
  3688. put_msg = GNUNET_malloc (sizeof (struct GNUNET_DHT_PutMessage) + size);
  3689. put_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_PUT);
  3690. put_msg->header.size = htons (sizeof (struct GNUNET_DHT_PutMessage) + size);
  3691. put_msg->expiration = GNUNET_TIME_absolute_hton (exp);
  3692. put_msg->type = htons (type);
  3693. memcpy (&put_msg[1], data, size);
  3694. new_msg_ctx->unique_id =
  3695. GNUNET_ntohll (GNUNET_CRYPTO_random_u64
  3696. (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX));
  3697. new_msg_ctx->replication = ntohl (DEFAULT_PUT_REPLICATION);
  3698. new_msg_ctx->msg_options = ntohl (0);
  3699. new_msg_ctx->network_size = estimate_diameter ();
  3700. new_msg_ctx->peer = &my_identity;
  3701. new_msg_ctx->bloom =
  3702. GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K);
  3703. new_msg_ctx->hop_count = 0;
  3704. new_msg_ctx->importance = DHT_DEFAULT_P2P_IMPORTANCE;
  3705. new_msg_ctx->timeout = DHT_DEFAULT_P2P_TIMEOUT;
  3706. increment_stats (STAT_PUT_START);
  3707. demultiplex_message (&put_msg->header, new_msg_ctx);
  3708. GNUNET_free (new_msg_ctx);
  3709. GNUNET_free (put_msg);
  3710. return GNUNET_OK;
  3711. }
  3712. /**
  3713. * Task used to republish data.
  3714. *
  3715. * @param cls closure (a struct RepublishContext)
  3716. * @param tc runtime context for this task
  3717. */
  3718. static void
  3719. republish_content (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  3720. {
  3721. struct RepublishContext *put_context = cls;
  3722. unsigned int results;
  3723. if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
  3724. {
  3725. GNUNET_free (put_context);
  3726. return;
  3727. }
  3728. GNUNET_assert (datacache != NULL); /* If we have no datacache we never should have scheduled this! */
  3729. results =
  3730. GNUNET_DATACACHE_get (datacache, &put_context->key, put_context->type,
  3731. &republish_content_iterator, NULL);
  3732. if (results == 0) /* Data must have expired */
  3733. GNUNET_free (put_context);
  3734. else /* Reschedule task for next time period */
  3735. GNUNET_SCHEDULER_add_delayed (dht_republish_frequency, &republish_content,
  3736. put_context);
  3737. }
  3738. /**
  3739. * Iterator over hash map entries.
  3740. *
  3741. * @param cls client to search for in source routes
  3742. * @param key current key code (ignored)
  3743. * @param value value in the hash map, a DHTQueryRecord
  3744. * @return GNUNET_YES if we should continue to
  3745. * iterate,
  3746. * GNUNET_NO if not.
  3747. */
  3748. static int
  3749. find_client_records (void *cls, const GNUNET_HashCode * key, void *value)
  3750. {
  3751. struct ClientList *client = cls;
  3752. struct DHTQueryRecord *record = value;
  3753. struct DHTRouteSource *pos;
  3754. pos = record->head;
  3755. while (pos != NULL)
  3756. {
  3757. if (pos->client == client)
  3758. break;
  3759. pos = pos->next;
  3760. }
  3761. if (pos != NULL)
  3762. {
  3763. GNUNET_CONTAINER_DLL_remove (record->head, record->tail, pos);
  3764. GNUNET_CONTAINER_heap_remove_node (pos->hnode);
  3765. if (pos->delete_task != GNUNET_SCHEDULER_NO_TASK)
  3766. {
  3767. GNUNET_SCHEDULER_cancel (pos->delete_task);
  3768. pos->delete_task = GNUNET_SCHEDULER_NO_TASK;
  3769. }
  3770. if (pos->find_peers_responded != NULL)
  3771. GNUNET_CONTAINER_bloomfilter_free (pos->find_peers_responded);
  3772. GNUNET_free (pos);
  3773. }
  3774. if (record->head == NULL) /* No more entries in DLL */
  3775. {
  3776. GNUNET_assert (GNUNET_YES ==
  3777. GNUNET_CONTAINER_multihashmap_remove (forward_list.hashmap,
  3778. &record->key, record));
  3779. GNUNET_free (record);
  3780. }
  3781. return GNUNET_YES;
  3782. }
  3783. /**
  3784. * Functions with this signature are called whenever a client
  3785. * is disconnected on the network level.
  3786. *
  3787. * @param cls closure (NULL for dht)
  3788. * @param client identification of the client; NULL
  3789. * for the last call when the server is destroyed
  3790. */
  3791. static void
  3792. handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
  3793. {
  3794. struct ClientList *pos = client_list;
  3795. struct ClientList *prev;
  3796. struct ClientList *found;
  3797. struct PendingMessage *reply;
  3798. prev = NULL;
  3799. found = NULL;
  3800. while (pos != NULL)
  3801. {
  3802. if (pos->client_handle == client)
  3803. {
  3804. if (prev != NULL)
  3805. prev->next = pos->next;
  3806. else
  3807. client_list = pos->next;
  3808. found = pos;
  3809. break;
  3810. }
  3811. prev = pos;
  3812. pos = pos->next;
  3813. }
  3814. if (found != NULL)
  3815. {
  3816. if (found->transmit_handle != NULL)
  3817. GNUNET_CONNECTION_notify_transmit_ready_cancel (found->transmit_handle);
  3818. while (NULL != (reply = found->pending_head))
  3819. {
  3820. GNUNET_CONTAINER_DLL_remove (found->pending_head, found->pending_tail,
  3821. reply);
  3822. GNUNET_free (reply);
  3823. }
  3824. GNUNET_CONTAINER_multihashmap_iterate (forward_list.hashmap,
  3825. &find_client_records, found);
  3826. GNUNET_free (found);
  3827. }
  3828. }
  3829. /**
  3830. * Find a client if it exists, add it otherwise.
  3831. *
  3832. * @param client the server handle to the client
  3833. *
  3834. * @return the client if found, a new client otherwise
  3835. */
  3836. static struct ClientList *
  3837. find_active_client (struct GNUNET_SERVER_Client *client)
  3838. {
  3839. struct ClientList *pos = client_list;
  3840. struct ClientList *ret;
  3841. while (pos != NULL)
  3842. {
  3843. if (pos->client_handle == client)
  3844. return pos;
  3845. pos = pos->next;
  3846. }
  3847. ret = GNUNET_malloc (sizeof (struct ClientList));
  3848. ret->client_handle = client;
  3849. ret->next = client_list;
  3850. client_list = ret;
  3851. return ret;
  3852. }
  3853. #if HAVE_MALICIOUS
  3854. /**
  3855. * Task to send a malicious put message across the network.
  3856. *
  3857. * @param cls closure for this task
  3858. * @param tc the context under which the task is running
  3859. */
  3860. static void
  3861. malicious_put_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  3862. {
  3863. static struct GNUNET_DHT_PutMessage put_message;
  3864. static struct DHT_MessageContext msg_ctx;
  3865. static GNUNET_HashCode key;
  3866. uint32_t random_key;
  3867. if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
  3868. return;
  3869. put_message.header.size = htons (sizeof (struct GNUNET_DHT_PutMessage));
  3870. put_message.header.type = htons (GNUNET_MESSAGE_TYPE_DHT_PUT);
  3871. put_message.type = htonl (GNUNET_BLOCK_DHT_MALICIOUS_MESSAGE_TYPE);
  3872. put_message.expiration =
  3873. GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_forever ());
  3874. memset (&msg_ctx, 0, sizeof (struct DHT_MessageContext));
  3875. random_key =
  3876. GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
  3877. GNUNET_CRYPTO_hash (&random_key, sizeof (uint32_t), &key);
  3878. memcpy (&msg_ctx.key, &key, sizeof (GNUNET_HashCode));
  3879. msg_ctx.unique_id =
  3880. GNUNET_ntohll (GNUNET_CRYPTO_random_u64
  3881. (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX));
  3882. msg_ctx.replication = ntohl (DHT_DEFAULT_FIND_PEER_REPLICATION);
  3883. msg_ctx.msg_options = ntohl (0);
  3884. msg_ctx.network_size = estimate_diameter ();
  3885. msg_ctx.peer = &my_identity;
  3886. msg_ctx.importance = DHT_DEFAULT_P2P_IMPORTANCE;
  3887. msg_ctx.timeout = DHT_DEFAULT_P2P_TIMEOUT;
  3888. #if DEBUG_DHT_ROUTING
  3889. if (dhtlog_handle != NULL)
  3890. dhtlog_handle->insert_dhtkey (NULL, &key);
  3891. #endif
  3892. increment_stats (STAT_PUT_START);
  3893. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3894. "%s:%s Sending malicious PUT message with hash %s\n", my_short_id,
  3895. "DHT", GNUNET_h2s (&key));
  3896. demultiplex_message (&put_message.header, &msg_ctx);
  3897. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
  3898. (GNUNET_TIME_UNIT_MILLISECONDS,
  3899. malicious_put_frequency), &malicious_put_task,
  3900. NULL);
  3901. }
  3902. /**
  3903. * Task to send a malicious put message across the network.
  3904. *
  3905. * @param cls closure for this task
  3906. * @param tc the context under which the task is running
  3907. */
  3908. static void
  3909. malicious_get_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  3910. {
  3911. static struct GNUNET_DHT_GetMessage get_message;
  3912. struct DHT_MessageContext msg_ctx;
  3913. static GNUNET_HashCode key;
  3914. uint32_t random_key;
  3915. if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
  3916. return;
  3917. get_message.header.size = htons (sizeof (struct GNUNET_DHT_GetMessage));
  3918. get_message.header.type = htons (GNUNET_MESSAGE_TYPE_DHT_GET);
  3919. get_message.type = htonl (GNUNET_BLOCK_DHT_MALICIOUS_MESSAGE_TYPE);
  3920. memset (&msg_ctx, 0, sizeof (struct DHT_MessageContext));
  3921. random_key =
  3922. GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
  3923. GNUNET_CRYPTO_hash (&random_key, sizeof (uint32_t), &key);
  3924. memcpy (&msg_ctx.key, &key, sizeof (GNUNET_HashCode));
  3925. msg_ctx.unique_id =
  3926. GNUNET_ntohll (GNUNET_CRYPTO_random_u64
  3927. (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX));
  3928. msg_ctx.replication = ntohl (DHT_DEFAULT_FIND_PEER_REPLICATION);
  3929. msg_ctx.msg_options = ntohl (0);
  3930. msg_ctx.network_size = estimate_diameter ();
  3931. msg_ctx.peer = &my_identity;
  3932. msg_ctx.importance = DHT_DEFAULT_P2P_IMPORTANCE;
  3933. msg_ctx.timeout = DHT_DEFAULT_P2P_TIMEOUT;
  3934. #if DEBUG_DHT_ROUTING
  3935. if (dhtlog_handle != NULL)
  3936. dhtlog_handle->insert_dhtkey (NULL, &key);
  3937. #endif
  3938. increment_stats (STAT_GET_START);
  3939. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  3940. "%s:%s Sending malicious GET message with hash %s\n", my_short_id,
  3941. "DHT", GNUNET_h2s (&key));
  3942. demultiplex_message (&get_message.header, &msg_ctx);
  3943. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
  3944. (GNUNET_TIME_UNIT_MILLISECONDS,
  3945. malicious_get_frequency), &malicious_get_task,
  3946. NULL);
  3947. }
  3948. #endif
  3949. /**
  3950. * Iterator over hash map entries.
  3951. *
  3952. * @param cls closure
  3953. * @param key current key code
  3954. * @param value value in the hash map
  3955. * @return GNUNET_YES if we should continue to
  3956. * iterate,
  3957. * GNUNET_NO if not.
  3958. */
  3959. static int
  3960. add_known_to_bloom (void *cls, const GNUNET_HashCode * key, void *value)
  3961. {
  3962. struct GNUNET_CONTAINER_BloomFilter *bloom = cls;
  3963. GNUNET_CONTAINER_bloomfilter_add (bloom, key);
  3964. return GNUNET_YES;
  3965. }
  3966. /**
  3967. * Task to send a find peer message for our own peer identifier
  3968. * so that we can find the closest peers in the network to ourselves
  3969. * and attempt to connect to them.
  3970. *
  3971. * @param cls closure for this task
  3972. * @param tc the context under which the task is running
  3973. */
  3974. static void
  3975. send_find_peer_message (void *cls,
  3976. const struct GNUNET_SCHEDULER_TaskContext *tc)
  3977. {
  3978. struct GNUNET_DHT_FindPeerMessage *find_peer_msg;
  3979. struct DHT_MessageContext msg_ctx;
  3980. struct GNUNET_TIME_Relative next_send_time;
  3981. struct GNUNET_CONTAINER_BloomFilter *temp_bloom;
  3982. #if COUNT_INTERVAL
  3983. struct GNUNET_TIME_Relative time_diff;
  3984. struct GNUNET_TIME_Absolute end;
  3985. double multiplier;
  3986. double count_per_interval;
  3987. #endif
  3988. if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
  3989. return;
  3990. if ((newly_found_peers > bucket_size) && (GNUNET_YES == do_find_peer)) /* If we are finding peers already, no need to send out our request right now! */
  3991. {
  3992. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  3993. "Have %d newly found peers since last find peer message sent!\n",
  3994. newly_found_peers);
  3995. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
  3996. &send_find_peer_message, NULL);
  3997. newly_found_peers = 0;
  3998. return;
  3999. }
  4000. increment_stats (STAT_FIND_PEER_START);
  4001. #if COUNT_INTERVAL
  4002. end = GNUNET_TIME_absolute_get ();
  4003. time_diff =
  4004. GNUNET_TIME_absolute_get_difference (find_peer_context.start, end);
  4005. if (time_diff.abs_value > FIND_PEER_CALC_INTERVAL.abs_value)
  4006. {
  4007. multiplier = time_diff.abs_value / FIND_PEER_CALC_INTERVAL.abs_value;
  4008. count_per_interval = find_peer_context.count / multiplier;
  4009. }
  4010. else
  4011. {
  4012. multiplier = FIND_PEER_CALC_INTERVAL.abs_value / time_diff.abs_value;
  4013. count_per_interval = find_peer_context.count * multiplier;
  4014. }
  4015. #endif
  4016. #if FIND_PEER_WITH_HELLO
  4017. find_peer_msg =
  4018. GNUNET_malloc (sizeof (struct GNUNET_DHT_FindPeerMessage) +
  4019. GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *)
  4020. my_hello));
  4021. find_peer_msg->header.size =
  4022. htons (sizeof (struct GNUNET_DHT_FindPeerMessage) +
  4023. GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) my_hello));
  4024. memcpy (&find_peer_msg[1], my_hello,
  4025. GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) my_hello));
  4026. #else
  4027. find_peer_msg = GNUNET_malloc (sizeof (struct GNUNET_DHT_FindPeerMessage));
  4028. find_peer_msg->header.size =
  4029. htons (sizeof (struct GNUNET_DHT_FindPeerMessage));
  4030. #endif
  4031. find_peer_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_FIND_PEER);
  4032. temp_bloom =
  4033. GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K);
  4034. GNUNET_CONTAINER_multihashmap_iterate (all_known_peers, &add_known_to_bloom,
  4035. temp_bloom);
  4036. GNUNET_assert (GNUNET_OK ==
  4037. GNUNET_CONTAINER_bloomfilter_get_raw_data (temp_bloom,
  4038. find_peer_msg->
  4039. bloomfilter,
  4040. DHT_BLOOM_SIZE));
  4041. GNUNET_CONTAINER_bloomfilter_free (temp_bloom);
  4042. memset (&msg_ctx, 0, sizeof (struct DHT_MessageContext));
  4043. memcpy (&msg_ctx.key, &my_identity.hashPubKey, sizeof (GNUNET_HashCode));
  4044. msg_ctx.unique_id =
  4045. GNUNET_ntohll (GNUNET_CRYPTO_random_u64
  4046. (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX));
  4047. msg_ctx.replication = DHT_DEFAULT_FIND_PEER_REPLICATION;
  4048. msg_ctx.msg_options = DHT_DEFAULT_FIND_PEER_OPTIONS;
  4049. msg_ctx.network_size = estimate_diameter ();
  4050. msg_ctx.peer = &my_identity;
  4051. msg_ctx.importance = DHT_DEFAULT_FIND_PEER_IMPORTANCE;
  4052. msg_ctx.timeout = DHT_DEFAULT_FIND_PEER_TIMEOUT;
  4053. demultiplex_message (&find_peer_msg->header, &msg_ctx);
  4054. GNUNET_free (find_peer_msg);
  4055. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4056. "`%s:%s': Sent `%s' request to some (?) peers\n", my_short_id,
  4057. "DHT", "FIND PEER");
  4058. if (newly_found_peers < bucket_size)
  4059. {
  4060. next_send_time.rel_value =
  4061. (DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value / 2) +
  4062. GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
  4063. DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value / 2);
  4064. }
  4065. else
  4066. {
  4067. next_send_time.rel_value =
  4068. DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value +
  4069. GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
  4070. DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value -
  4071. DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value);
  4072. }
  4073. GNUNET_assert (next_send_time.rel_value != 0);
  4074. find_peer_context.count = 0;
  4075. newly_found_peers = 0;
  4076. find_peer_context.start = GNUNET_TIME_absolute_get ();
  4077. if (GNUNET_YES == do_find_peer)
  4078. {
  4079. GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_peer_message,
  4080. NULL);
  4081. }
  4082. }
  4083. /**
  4084. * Handler for any generic DHT messages, calls the appropriate handler
  4085. * depending on message type, sends confirmation if responses aren't otherwise
  4086. * expected.
  4087. *
  4088. * @param cls closure for the service
  4089. * @param client the client we received this message from
  4090. * @param message the actual message received
  4091. */
  4092. static void
  4093. handle_dht_local_route_request (void *cls, struct GNUNET_SERVER_Client *client,
  4094. const struct GNUNET_MessageHeader *message)
  4095. {
  4096. const struct GNUNET_DHT_RouteMessage *dht_msg =
  4097. (const struct GNUNET_DHT_RouteMessage *) message;
  4098. const struct GNUNET_MessageHeader *enc_msg;
  4099. struct DHT_MessageContext msg_ctx;
  4100. enc_msg = (const struct GNUNET_MessageHeader *) &dht_msg[1];
  4101. #if DEBUG_DHT
  4102. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4103. "`%s:%s': Received `%s' request from client, message type %d, key %s, uid %llu\n",
  4104. my_short_id, "DHT", "GENERIC", ntohs (message->type),
  4105. GNUNET_h2s (&dht_msg->key), GNUNET_ntohll (dht_msg->unique_id));
  4106. #endif
  4107. #if DEBUG_DHT_ROUTING
  4108. if (dhtlog_handle != NULL)
  4109. dhtlog_handle->insert_dhtkey (NULL, &dht_msg->key);
  4110. #endif
  4111. memset (&msg_ctx, 0, sizeof (struct DHT_MessageContext));
  4112. msg_ctx.client = find_active_client (client);
  4113. memcpy (&msg_ctx.key, &dht_msg->key, sizeof (GNUNET_HashCode));
  4114. msg_ctx.unique_id = GNUNET_ntohll (dht_msg->unique_id);
  4115. msg_ctx.replication = ntohl (dht_msg->desired_replication_level);
  4116. msg_ctx.msg_options = ntohl (dht_msg->options);
  4117. if (GNUNET_DHT_RO_RECORD_ROUTE ==
  4118. (msg_ctx.msg_options & GNUNET_DHT_RO_RECORD_ROUTE))
  4119. {
  4120. msg_ctx.path_history = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
  4121. memcpy (msg_ctx.path_history, &my_identity,
  4122. sizeof (struct GNUNET_PeerIdentity));
  4123. msg_ctx.path_history_len = 1;
  4124. }
  4125. msg_ctx.network_size = estimate_diameter ();
  4126. msg_ctx.peer = &my_identity;
  4127. msg_ctx.importance = DHT_DEFAULT_P2P_IMPORTANCE + 4; /* Make local routing a higher priority */
  4128. msg_ctx.timeout = DHT_DEFAULT_P2P_TIMEOUT;
  4129. if (ntohs (enc_msg->type) == GNUNET_MESSAGE_TYPE_DHT_GET)
  4130. increment_stats (STAT_GET_START);
  4131. else if (ntohs (enc_msg->type) == GNUNET_MESSAGE_TYPE_DHT_PUT)
  4132. increment_stats (STAT_PUT_START);
  4133. else if (ntohs (enc_msg->type) == GNUNET_MESSAGE_TYPE_DHT_FIND_PEER)
  4134. increment_stats (STAT_FIND_PEER_START);
  4135. if (GNUNET_YES == malicious_dropper)
  4136. {
  4137. if (ntohs (enc_msg->type) == GNUNET_MESSAGE_TYPE_DHT_GET)
  4138. {
  4139. #if DEBUG_DHT_ROUTING
  4140. if ((debug_routes) && (dhtlog_handle != NULL))
  4141. {
  4142. dhtlog_handle->insert_query (NULL, msg_ctx.unique_id, DHTLOG_GET,
  4143. msg_ctx.hop_count, GNUNET_NO, &my_identity,
  4144. &msg_ctx.key);
  4145. }
  4146. #endif
  4147. }
  4148. else if (ntohs (enc_msg->type) == GNUNET_MESSAGE_TYPE_DHT_PUT)
  4149. {
  4150. #if DEBUG_DHT_ROUTING
  4151. if ((debug_routes) && (dhtlog_handle != NULL))
  4152. {
  4153. dhtlog_handle->insert_query (NULL, msg_ctx.unique_id, DHTLOG_PUT,
  4154. msg_ctx.hop_count, GNUNET_NO, &my_identity,
  4155. &msg_ctx.key);
  4156. }
  4157. #endif
  4158. }
  4159. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  4160. GNUNET_free_non_null (msg_ctx.path_history);
  4161. return;
  4162. }
  4163. demultiplex_message (enc_msg, &msg_ctx);
  4164. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  4165. }
  4166. /**
  4167. * Handler for any locally received DHT control messages,
  4168. * sets malicious flags mostly for now.
  4169. *
  4170. * @param cls closure for the service
  4171. * @param client the client we received this message from
  4172. * @param message the actual message received
  4173. *
  4174. */
  4175. static void
  4176. handle_dht_control_message (void *cls, struct GNUNET_SERVER_Client *client,
  4177. const struct GNUNET_MessageHeader *message)
  4178. {
  4179. const struct GNUNET_DHT_ControlMessage *dht_control_msg =
  4180. (const struct GNUNET_DHT_ControlMessage *) message;
  4181. #if DEBUG_DHT
  4182. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4183. "`%s:%s': Received `%s' request from client, command %d\n",
  4184. my_short_id, "DHT", "CONTROL", ntohs (dht_control_msg->command));
  4185. #endif
  4186. switch (ntohs (dht_control_msg->command))
  4187. {
  4188. case GNUNET_MESSAGE_TYPE_DHT_FIND_PEER:
  4189. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4190. "Sending self seeking find peer request!\n");
  4191. GNUNET_SCHEDULER_add_now (&send_find_peer_message, NULL);
  4192. break;
  4193. #if HAVE_MALICIOUS
  4194. case GNUNET_MESSAGE_TYPE_DHT_MALICIOUS_GET:
  4195. if (ntohs (dht_control_msg->variable) > 0)
  4196. malicious_get_frequency = ntohs (dht_control_msg->variable);
  4197. if (malicious_get_frequency == 0)
  4198. malicious_get_frequency = DEFAULT_MALICIOUS_GET_FREQUENCY;
  4199. if (malicious_getter != GNUNET_YES)
  4200. GNUNET_SCHEDULER_add_now (&malicious_get_task, NULL);
  4201. malicious_getter = GNUNET_YES;
  4202. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4203. "%s:%s Initiating malicious GET behavior, frequency %d\n",
  4204. my_short_id, "DHT", malicious_get_frequency);
  4205. break;
  4206. case GNUNET_MESSAGE_TYPE_DHT_MALICIOUS_PUT:
  4207. if (ntohs (dht_control_msg->variable) > 0)
  4208. malicious_put_frequency = ntohs (dht_control_msg->variable);
  4209. if (malicious_put_frequency == 0)
  4210. malicious_put_frequency = DEFAULT_MALICIOUS_PUT_FREQUENCY;
  4211. if (malicious_putter != GNUNET_YES)
  4212. GNUNET_SCHEDULER_add_now (&malicious_put_task, NULL);
  4213. malicious_putter = GNUNET_YES;
  4214. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4215. "%s:%s Initiating malicious PUT behavior, frequency %d\n",
  4216. my_short_id, "DHT", malicious_put_frequency);
  4217. break;
  4218. case GNUNET_MESSAGE_TYPE_DHT_MALICIOUS_DROP:
  4219. #if DEBUG_DHT_ROUTING
  4220. if ((malicious_dropper != GNUNET_YES) && (dhtlog_handle != NULL))
  4221. dhtlog_handle->set_malicious (&my_identity);
  4222. #endif
  4223. malicious_dropper = GNUNET_YES;
  4224. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4225. "%s:%s Initiating malicious DROP behavior\n", my_short_id,
  4226. "DHT");
  4227. break;
  4228. #endif
  4229. default:
  4230. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  4231. "%s:%s Unknown control command type `%d'!\n", my_short_id,
  4232. "DHT", ntohs (dht_control_msg->command));
  4233. break;
  4234. }
  4235. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  4236. }
  4237. /**
  4238. * Handler for any generic DHT stop messages, calls the appropriate handler
  4239. * depending on message type (if processed locally)
  4240. *
  4241. * @param cls closure for the service
  4242. * @param client the client we received this message from
  4243. * @param message the actual message received
  4244. *
  4245. */
  4246. static void
  4247. handle_dht_local_route_stop (void *cls, struct GNUNET_SERVER_Client *client,
  4248. const struct GNUNET_MessageHeader *message)
  4249. {
  4250. const struct GNUNET_DHT_StopMessage *dht_stop_msg =
  4251. (const struct GNUNET_DHT_StopMessage *) message;
  4252. struct DHTQueryRecord *record;
  4253. struct DHTRouteSource *pos;
  4254. #if DEBUG_DHT
  4255. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4256. "`%s:%s': Received `%s' request from client, uid %llu\n",
  4257. my_short_id, "DHT", "GENERIC STOP",
  4258. GNUNET_ntohll (dht_stop_msg->unique_id));
  4259. #endif
  4260. record =
  4261. GNUNET_CONTAINER_multihashmap_get (forward_list.hashmap,
  4262. &dht_stop_msg->key);
  4263. if (record != NULL)
  4264. {
  4265. pos = record->head;
  4266. while (pos != NULL)
  4267. {
  4268. /* If the client is non-null (local request) and the client matches the requesting client, remove the entry. */
  4269. if ((pos->client != NULL) && (pos->client->client_handle == client))
  4270. {
  4271. if (pos->delete_task != GNUNET_SCHEDULER_NO_TASK)
  4272. GNUNET_SCHEDULER_cancel (pos->delete_task);
  4273. pos->delete_task =
  4274. GNUNET_SCHEDULER_add_now (&remove_forward_entry, pos);
  4275. }
  4276. pos = pos->next;
  4277. }
  4278. }
  4279. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  4280. }
  4281. /**
  4282. * Core handler for p2p route requests.
  4283. *
  4284. * @param cls closure
  4285. * @param message message
  4286. * @param peer peer identity this notification is about
  4287. * @param atsi performance data
  4288. *
  4289. */
  4290. static int
  4291. handle_dht_p2p_route_request (void *cls, const struct GNUNET_PeerIdentity *peer,
  4292. const struct GNUNET_MessageHeader *message,
  4293. const struct GNUNET_TRANSPORT_ATS_Information
  4294. *atsi)
  4295. {
  4296. #if DEBUG_DHT
  4297. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4298. "`%s:%s': Received P2P request from peer %s\n", my_short_id,
  4299. "DHT", GNUNET_i2s (peer));
  4300. #endif
  4301. struct GNUNET_DHT_P2PRouteMessage *incoming =
  4302. (struct GNUNET_DHT_P2PRouteMessage *) message;
  4303. struct GNUNET_MessageHeader *enc_msg =
  4304. (struct GNUNET_MessageHeader *) &incoming[1];
  4305. struct DHT_MessageContext *msg_ctx;
  4306. char *route_path;
  4307. int path_size;
  4308. if (ntohs (enc_msg->type) == GNUNET_MESSAGE_TYPE_DHT_P2P_PING) /* Throw these away. FIXME: Don't throw these away? (reply) */
  4309. {
  4310. #if DEBUG_PING
  4311. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s:%s Received P2P Ping message.\n",
  4312. my_short_id, "DHT");
  4313. #endif
  4314. return GNUNET_YES;
  4315. }
  4316. if (ntohs (enc_msg->size) >= GNUNET_SERVER_MAX_MESSAGE_SIZE - 1)
  4317. {
  4318. GNUNET_break_op (0);
  4319. return GNUNET_YES;
  4320. }
  4321. if (malicious_dropper == GNUNET_YES)
  4322. {
  4323. #if DEBUG_DHT_ROUTING
  4324. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  4325. {
  4326. /** Log routes that die due to high load! */
  4327. dhtlog_handle->insert_route (NULL, GNUNET_ntohll (incoming->unique_id),
  4328. DHTLOG_ROUTE, ntohl (incoming->hop_count),
  4329. GNUNET_SYSERR, &my_identity, &incoming->key,
  4330. peer, NULL);
  4331. }
  4332. #endif
  4333. return GNUNET_YES;
  4334. }
  4335. if (get_max_send_delay ().rel_value > MAX_REQUEST_TIME.rel_value)
  4336. {
  4337. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4338. "Sending of previous replies took too long, backing off!\n");
  4339. increment_stats ("# route requests dropped due to high load");
  4340. decrease_max_send_delay (get_max_send_delay ());
  4341. #if DEBUG_DHT_ROUTING
  4342. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  4343. {
  4344. /** Log routes that die due to high load! */
  4345. dhtlog_handle->insert_route (NULL, GNUNET_ntohll (incoming->unique_id),
  4346. DHTLOG_ROUTE, ntohl (incoming->hop_count),
  4347. GNUNET_SYSERR, &my_identity, &incoming->key,
  4348. peer, NULL);
  4349. }
  4350. #endif
  4351. return GNUNET_YES;
  4352. }
  4353. msg_ctx = GNUNET_malloc (sizeof (struct DHT_MessageContext));
  4354. msg_ctx->bloom =
  4355. GNUNET_CONTAINER_bloomfilter_init (incoming->bloomfilter, DHT_BLOOM_SIZE,
  4356. DHT_BLOOM_K);
  4357. GNUNET_assert (msg_ctx->bloom != NULL);
  4358. msg_ctx->hop_count = ntohl (incoming->hop_count);
  4359. memcpy (&msg_ctx->key, &incoming->key, sizeof (GNUNET_HashCode));
  4360. msg_ctx->replication = ntohl (incoming->desired_replication_level);
  4361. msg_ctx->unique_id = GNUNET_ntohll (incoming->unique_id);
  4362. msg_ctx->msg_options = ntohl (incoming->options);
  4363. if (GNUNET_DHT_RO_RECORD_ROUTE ==
  4364. (msg_ctx->msg_options & GNUNET_DHT_RO_RECORD_ROUTE))
  4365. {
  4366. path_size =
  4367. ntohl (incoming->outgoing_path_length) *
  4368. sizeof (struct GNUNET_PeerIdentity);
  4369. GNUNET_assert (ntohs (message->size) ==
  4370. (sizeof (struct GNUNET_DHT_P2PRouteMessage) +
  4371. ntohs (enc_msg->size) + path_size));
  4372. route_path = (char *) &incoming[1];
  4373. route_path = route_path + ntohs (enc_msg->size);
  4374. msg_ctx->path_history =
  4375. GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) + path_size);
  4376. memcpy (msg_ctx->path_history, route_path, path_size);
  4377. memcpy (&msg_ctx->path_history[path_size], &my_identity,
  4378. sizeof (struct GNUNET_PeerIdentity));
  4379. msg_ctx->path_history_len = ntohl (incoming->outgoing_path_length) + 1;
  4380. }
  4381. msg_ctx->network_size = ntohl (incoming->network_size);
  4382. msg_ctx->peer = peer;
  4383. msg_ctx->importance = DHT_DEFAULT_P2P_IMPORTANCE;
  4384. msg_ctx->timeout = DHT_DEFAULT_P2P_TIMEOUT;
  4385. demultiplex_message (enc_msg, msg_ctx);
  4386. if (msg_ctx->bloom != NULL)
  4387. {
  4388. GNUNET_CONTAINER_bloomfilter_free (msg_ctx->bloom);
  4389. msg_ctx->bloom = NULL;
  4390. }
  4391. GNUNET_free (msg_ctx);
  4392. return GNUNET_YES;
  4393. }
  4394. /**
  4395. * Core handler for p2p route results.
  4396. *
  4397. * @param cls closure
  4398. * @param message message
  4399. * @param peer peer identity this notification is about
  4400. * @param atsi performance data
  4401. *
  4402. */
  4403. static int
  4404. handle_dht_p2p_route_result (void *cls, const struct GNUNET_PeerIdentity *peer,
  4405. const struct GNUNET_MessageHeader *message,
  4406. const struct GNUNET_TRANSPORT_ATS_Information
  4407. *atsi)
  4408. {
  4409. #if DEBUG_DHT
  4410. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4411. "`%s:%s': Received request from peer %s\n", my_short_id, "DHT",
  4412. GNUNET_i2s (peer));
  4413. #endif
  4414. struct GNUNET_DHT_P2PRouteResultMessage *incoming =
  4415. (struct GNUNET_DHT_P2PRouteResultMessage *) message;
  4416. struct GNUNET_MessageHeader *enc_msg =
  4417. (struct GNUNET_MessageHeader *) &incoming[1];
  4418. struct DHT_MessageContext msg_ctx;
  4419. #if DEBUG_PATH
  4420. char *path_offset;
  4421. unsigned int i;
  4422. #endif
  4423. if (ntohs (enc_msg->size) >= GNUNET_SERVER_MAX_MESSAGE_SIZE - 1)
  4424. {
  4425. GNUNET_break_op (0);
  4426. return GNUNET_YES;
  4427. }
  4428. if (malicious_dropper == GNUNET_YES)
  4429. {
  4430. #if DEBUG_DHT_ROUTING
  4431. if ((debug_routes_extended) && (dhtlog_handle != NULL))
  4432. {
  4433. /** Log routes that die due to high load! */
  4434. dhtlog_handle->insert_route (NULL, GNUNET_ntohll (incoming->unique_id),
  4435. DHTLOG_ROUTE, ntohl (incoming->hop_count),
  4436. GNUNET_SYSERR, &my_identity, &incoming->key,
  4437. peer, NULL);
  4438. }
  4439. #endif
  4440. return GNUNET_YES;
  4441. }
  4442. memset (&msg_ctx, 0, sizeof (struct DHT_MessageContext));
  4443. // FIXME: call GNUNET_BLOCK_evaluate (...) -- instead of doing your own bloomfilter!
  4444. memcpy (&msg_ctx.key, &incoming->key, sizeof (GNUNET_HashCode));
  4445. msg_ctx.unique_id = GNUNET_ntohll (incoming->unique_id);
  4446. msg_ctx.msg_options = ntohl (incoming->options);
  4447. msg_ctx.hop_count = ntohl (incoming->hop_count);
  4448. msg_ctx.peer = peer;
  4449. msg_ctx.importance = DHT_DEFAULT_P2P_IMPORTANCE + 2; /* Make result routing a higher priority */
  4450. msg_ctx.timeout = DHT_DEFAULT_P2P_TIMEOUT;
  4451. if ((GNUNET_DHT_RO_RECORD_ROUTE ==
  4452. (msg_ctx.msg_options & GNUNET_DHT_RO_RECORD_ROUTE)) &&
  4453. (ntohl (incoming->outgoing_path_length) > 0))
  4454. {
  4455. if (ntohs (message->size) -
  4456. sizeof (struct GNUNET_DHT_P2PRouteResultMessage) -
  4457. ntohs (enc_msg->size) !=
  4458. ntohl (incoming->outgoing_path_length) *
  4459. sizeof (struct GNUNET_PeerIdentity))
  4460. {
  4461. #if DEBUG_DHT
  4462. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4463. "Return message indicated a path was included, but sizes are wrong: Total size %d, enc size %d, left %d, expected %d\n",
  4464. ntohs (message->size), ntohs (enc_msg->size),
  4465. ntohs (message->size) -
  4466. sizeof (struct GNUNET_DHT_P2PRouteResultMessage) -
  4467. ntohs (enc_msg->size),
  4468. ntohl (incoming->outgoing_path_length) *
  4469. sizeof (struct GNUNET_PeerIdentity));
  4470. #endif
  4471. GNUNET_break_op (0);
  4472. return GNUNET_NO;
  4473. }
  4474. msg_ctx.path_history = (char *) &incoming[1];
  4475. msg_ctx.path_history += ntohs (enc_msg->size);
  4476. msg_ctx.path_history_len = ntohl (incoming->outgoing_path_length);
  4477. #if DEBUG_PATH
  4478. for (i = 0; i < msg_ctx.path_history_len; i++)
  4479. {
  4480. path_offset =
  4481. &msg_ctx.path_history[i * sizeof (struct GNUNET_PeerIdentity)];
  4482. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4483. "(handle_p2p_route_result) Key %s Found peer %d:%s\n",
  4484. GNUNET_h2s (&msg_ctx.key), i,
  4485. GNUNET_i2s ((struct GNUNET_PeerIdentity *) path_offset));
  4486. }
  4487. #endif
  4488. }
  4489. msg_ctx.bloom =
  4490. GNUNET_CONTAINER_bloomfilter_init (incoming->bloomfilter, DHT_BLOOM_SIZE,
  4491. DHT_BLOOM_K);
  4492. GNUNET_assert (msg_ctx.bloom != NULL);
  4493. route_result_message (enc_msg, &msg_ctx);
  4494. return GNUNET_YES;
  4495. }
  4496. /**
  4497. * Receive the HELLO from transport service,
  4498. * free current and replace if necessary.
  4499. *
  4500. * @param cls NULL
  4501. * @param message HELLO message of peer
  4502. */
  4503. static void
  4504. process_hello (void *cls, const struct GNUNET_MessageHeader *message)
  4505. {
  4506. #if DEBUG_DHT
  4507. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4508. "Received our `%s' from transport service\n", "HELLO");
  4509. #endif
  4510. GNUNET_assert (message != NULL);
  4511. GNUNET_free_non_null (my_hello);
  4512. my_hello = GNUNET_malloc (ntohs (message->size));
  4513. memcpy (my_hello, message, ntohs (message->size));
  4514. }
  4515. /**
  4516. * Task run during shutdown.
  4517. *
  4518. * @param cls unused
  4519. * @param tc unused
  4520. */
  4521. static void
  4522. shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  4523. {
  4524. int bucket_count;
  4525. struct PeerInfo *pos;
  4526. if (transport_handle != NULL)
  4527. {
  4528. GNUNET_free_non_null (my_hello);
  4529. GNUNET_TRANSPORT_get_hello_cancel (transport_handle, &process_hello, NULL);
  4530. GNUNET_TRANSPORT_disconnect (transport_handle);
  4531. }
  4532. if (coreAPI != NULL)
  4533. {
  4534. #if DEBUG_DHT
  4535. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s:%s Disconnecting core!\n",
  4536. my_short_id, "DHT");
  4537. #endif
  4538. GNUNET_CORE_disconnect (coreAPI);
  4539. coreAPI = NULL;
  4540. }
  4541. for (bucket_count = lowest_bucket; bucket_count < MAX_BUCKETS; bucket_count++)
  4542. {
  4543. while (k_buckets[bucket_count].head != NULL)
  4544. {
  4545. pos = k_buckets[bucket_count].head;
  4546. #if DEBUG_DHT
  4547. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4548. "%s:%s Removing peer %s from bucket %d!\n", my_short_id,
  4549. "DHT", GNUNET_i2s (&pos->id), bucket_count);
  4550. #endif
  4551. delete_peer (pos, bucket_count);
  4552. }
  4553. }
  4554. if (datacache != NULL)
  4555. {
  4556. #if DEBUG_DHT
  4557. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s:%s Destroying datacache!\n",
  4558. my_short_id, "DHT");
  4559. #endif
  4560. GNUNET_DATACACHE_destroy (datacache);
  4561. datacache = NULL;
  4562. }
  4563. if (stats != NULL)
  4564. {
  4565. GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
  4566. stats = NULL;
  4567. }
  4568. if (dhtlog_handle != NULL)
  4569. {
  4570. GNUNET_DHTLOG_disconnect (dhtlog_handle);
  4571. dhtlog_handle = NULL;
  4572. }
  4573. if (block_context != NULL)
  4574. {
  4575. GNUNET_BLOCK_context_destroy (block_context);
  4576. block_context = NULL;
  4577. }
  4578. GNUNET_free_non_null (my_short_id);
  4579. my_short_id = NULL;
  4580. }
  4581. /**
  4582. * To be called on core init/fail.
  4583. *
  4584. * @param cls service closure
  4585. * @param server handle to the server for this service
  4586. * @param identity the public identity of this peer
  4587. * @param publicKey the public key of this peer
  4588. */
  4589. void
  4590. core_init (void *cls, struct GNUNET_CORE_Handle *server,
  4591. const struct GNUNET_PeerIdentity *identity,
  4592. const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
  4593. {
  4594. if (server == NULL)
  4595. {
  4596. #if DEBUG_DHT
  4597. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s: Connection to core FAILED!\n",
  4598. "dht", GNUNET_i2s (identity));
  4599. #endif
  4600. GNUNET_SCHEDULER_cancel (cleanup_task);
  4601. GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
  4602. return;
  4603. }
  4604. #if DEBUG_DHT
  4605. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4606. "%s: Core connection initialized, I am peer: %s\n", "dht",
  4607. GNUNET_i2s (identity));
  4608. #endif
  4609. /* Copy our identity so we can use it */
  4610. memcpy (&my_identity, identity, sizeof (struct GNUNET_PeerIdentity));
  4611. if (my_short_id != NULL)
  4612. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  4613. "%s Receive CORE INIT message but have already been initialized! Did CORE fail?\n",
  4614. "DHT SERVICE");
  4615. my_short_id = GNUNET_strdup (GNUNET_i2s (&my_identity));
  4616. /* Set the server to local variable */
  4617. coreAPI = server;
  4618. if (dhtlog_handle != NULL)
  4619. dhtlog_handle->insert_node (NULL, &my_identity);
  4620. }
  4621. static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
  4622. {&handle_dht_local_route_request, NULL, GNUNET_MESSAGE_TYPE_DHT_LOCAL_ROUTE,
  4623. 0},
  4624. {&handle_dht_local_route_stop, NULL,
  4625. GNUNET_MESSAGE_TYPE_DHT_LOCAL_ROUTE_STOP, 0},
  4626. {&handle_dht_control_message, NULL, GNUNET_MESSAGE_TYPE_DHT_CONTROL, 0},
  4627. {NULL, NULL, 0, 0}
  4628. };
  4629. static struct GNUNET_CORE_MessageHandler core_handlers[] = {
  4630. {&handle_dht_p2p_route_request, GNUNET_MESSAGE_TYPE_DHT_P2P_ROUTE, 0},
  4631. {&handle_dht_p2p_route_result, GNUNET_MESSAGE_TYPE_DHT_P2P_ROUTE_RESULT, 0},
  4632. {NULL, 0, 0}
  4633. };
  4634. /**
  4635. * Method called whenever a peer connects.
  4636. *
  4637. * @param cls closure
  4638. * @param peer peer identity this notification is about
  4639. * @param atsi performance data
  4640. */
  4641. static void
  4642. handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
  4643. const struct GNUNET_TRANSPORT_ATS_Information *atsi)
  4644. {
  4645. struct PeerInfo *ret;
  4646. struct DHTPutEntry *put_entry;
  4647. int peer_bucket;
  4648. /* Check for connect to self message */
  4649. if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
  4650. return;
  4651. #if DEBUG_DHT
  4652. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4653. "%s:%s Receives core connect message for peer %s distance %d!\n",
  4654. my_short_id, "dht", GNUNET_i2s (peer), distance);
  4655. #endif
  4656. if (GNUNET_YES ==
  4657. GNUNET_CONTAINER_multihashmap_contains (all_known_peers,
  4658. &peer->hashPubKey))
  4659. {
  4660. #if DEBUG_DHT
  4661. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4662. "%s:%s Received %s message for peer %s, but already have peer in RT!",
  4663. my_short_id, "DHT", "CORE CONNECT", GNUNET_i2s (peer));
  4664. #endif
  4665. GNUNET_break (0);
  4666. return;
  4667. }
  4668. if ((datacache != NULL) && (GNUNET_YES == put_peer_identities))
  4669. {
  4670. put_entry =
  4671. GNUNET_malloc (sizeof (struct DHTPutEntry) +
  4672. sizeof (struct GNUNET_PeerIdentity));
  4673. put_entry->path_length = 0;
  4674. put_entry->data_size = sizeof (struct GNUNET_PeerIdentity);
  4675. memcpy (&put_entry[1], peer, sizeof (struct GNUNET_PeerIdentity));
  4676. GNUNET_DATACACHE_put (datacache, &peer->hashPubKey,
  4677. sizeof (struct DHTPutEntry) +
  4678. sizeof (struct GNUNET_PeerIdentity),
  4679. (char *) put_entry, GNUNET_BLOCK_TYPE_DHT_HELLO,
  4680. GNUNET_TIME_absolute_get_forever ());
  4681. GNUNET_free (put_entry);
  4682. }
  4683. else if (datacache == NULL)
  4684. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  4685. "DHT has no connection to datacache!\n");
  4686. peer_bucket = find_current_bucket (&peer->hashPubKey);
  4687. GNUNET_assert (peer_bucket >= lowest_bucket);
  4688. GNUNET_assert (peer_bucket < MAX_BUCKETS);
  4689. ret = GNUNET_malloc (sizeof (struct PeerInfo));
  4690. #if 0
  4691. ret->latency = latency;
  4692. ret->distance = distance;
  4693. #endif
  4694. ret->id = *peer;
  4695. GNUNET_CONTAINER_DLL_insert_after (k_buckets[peer_bucket].head,
  4696. k_buckets[peer_bucket].tail,
  4697. k_buckets[peer_bucket].tail, ret);
  4698. k_buckets[peer_bucket].peers_size++;
  4699. #if DO_UPDATE_PREFERENCE
  4700. if ((GNUNET_CRYPTO_hash_matching_bits
  4701. (&my_identity.hashPubKey, &peer->hashPubKey) > 0) &&
  4702. (k_buckets[peer_bucket].peers_size <= bucket_size))
  4703. ret->preference_task =
  4704. GNUNET_SCHEDULER_add_now (&update_core_preference, ret);
  4705. #endif
  4706. if ((k_buckets[lowest_bucket].peers_size) >= bucket_size)
  4707. enable_next_bucket ();
  4708. #if DO_PING
  4709. schedule_ping_messages ();
  4710. #endif
  4711. newly_found_peers++;
  4712. GNUNET_CONTAINER_multihashmap_put (all_known_peers, &peer->hashPubKey, ret,
  4713. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
  4714. increment_stats (STAT_PEERS_KNOWN);
  4715. #if DEBUG_DHT
  4716. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4717. "%s:%s Adding peer to routing list: %s\n", my_short_id, "DHT",
  4718. ret == NULL ? "NOT ADDED" : "PEER ADDED");
  4719. #endif
  4720. }
  4721. /**
  4722. * Method called whenever a peer disconnects.
  4723. *
  4724. * @param cls closure
  4725. * @param peer peer identity this notification is about
  4726. */
  4727. static void
  4728. handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
  4729. {
  4730. struct PeerInfo *to_remove;
  4731. int current_bucket;
  4732. /* Check for disconnect from self message */
  4733. if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
  4734. return;
  4735. #if DEBUG_DHT
  4736. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4737. "%s:%s: Received peer disconnect message for peer `%s' from %s\n",
  4738. my_short_id, "DHT", GNUNET_i2s (peer), "CORE");
  4739. #endif
  4740. if (GNUNET_YES !=
  4741. GNUNET_CONTAINER_multihashmap_contains (all_known_peers,
  4742. &peer->hashPubKey))
  4743. {
  4744. GNUNET_break (0);
  4745. #if DEBUG_DHT
  4746. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  4747. "%s:%s: do not have peer `%s' in RT, can't disconnect!\n",
  4748. my_short_id, "DHT", GNUNET_i2s (peer));
  4749. #endif
  4750. return;
  4751. }
  4752. increment_stats (STAT_DISCONNECTS);
  4753. GNUNET_assert (GNUNET_CONTAINER_multihashmap_contains
  4754. (all_known_peers, &peer->hashPubKey));
  4755. to_remove =
  4756. GNUNET_CONTAINER_multihashmap_get (all_known_peers, &peer->hashPubKey);
  4757. GNUNET_assert (to_remove != NULL);
  4758. if (NULL != to_remove->info_ctx)
  4759. {
  4760. GNUNET_CORE_peer_change_preference_cancel (to_remove->info_ctx);
  4761. to_remove->info_ctx = NULL;
  4762. }
  4763. GNUNET_assert (0 ==
  4764. memcmp (peer, &to_remove->id,
  4765. sizeof (struct GNUNET_PeerIdentity)));
  4766. current_bucket = find_current_bucket (&to_remove->id.hashPubKey);
  4767. delete_peer (to_remove, current_bucket);
  4768. }
  4769. /**
  4770. * Process dht requests.
  4771. *
  4772. * @param cls closure
  4773. * @param server the initialized server
  4774. * @param c configuration to use
  4775. */
  4776. static void
  4777. run (void *cls, struct GNUNET_SERVER_Handle *server,
  4778. const struct GNUNET_CONFIGURATION_Handle *c)
  4779. {
  4780. struct GNUNET_TIME_Relative next_send_time;
  4781. unsigned long long temp_config_num;
  4782. char *converge_modifier_buf;
  4783. cfg = c;
  4784. datacache = GNUNET_DATACACHE_create (cfg, "dhtcache");
  4785. GNUNET_SERVER_add_handlers (server, plugin_handlers);
  4786. GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
  4787. coreAPI = GNUNET_CORE_connect (cfg, /* Main configuration */
  4788. DEFAULT_CORE_QUEUE_SIZE, /* queue size */
  4789. NULL, /* Closure passed to DHT functions */
  4790. &core_init, /* Call core_init once connected */
  4791. &handle_core_connect, /* Handle connects */
  4792. &handle_core_disconnect, /* remove peers on disconnects */
  4793. NULL, /* Do we care about "status" updates? */
  4794. NULL, /* Don't want notified about all incoming messages */
  4795. GNUNET_NO, /* For header only inbound notification */
  4796. NULL, /* Don't want notified about all outbound messages */
  4797. GNUNET_NO, /* For header only outbound notification */
  4798. core_handlers); /* Register these handlers */
  4799. if (coreAPI == NULL)
  4800. return;
  4801. transport_handle =
  4802. GNUNET_TRANSPORT_connect (cfg, NULL, NULL, NULL, NULL, NULL);
  4803. if (transport_handle != NULL)
  4804. GNUNET_TRANSPORT_get_hello (transport_handle, &process_hello, NULL);
  4805. else
  4806. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  4807. "Failed to connect to transport service!\n");
  4808. block_context = GNUNET_BLOCK_context_create (cfg);
  4809. lowest_bucket = MAX_BUCKETS - 1;
  4810. forward_list.hashmap =
  4811. GNUNET_CONTAINER_multihashmap_create (MAX_OUTSTANDING_FORWARDS / 10);
  4812. forward_list.minHeap =
  4813. GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
  4814. all_known_peers = GNUNET_CONTAINER_multihashmap_create (MAX_BUCKETS / 8);
  4815. recent_find_peer_requests =
  4816. GNUNET_CONTAINER_multihashmap_create (MAX_BUCKETS / 8);
  4817. GNUNET_assert (all_known_peers != NULL);
  4818. if (GNUNET_YES ==
  4819. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht_testing",
  4820. "mysql_logging"))
  4821. {
  4822. debug_routes = GNUNET_YES;
  4823. }
  4824. if (GNUNET_YES ==
  4825. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "strict_kademlia"))
  4826. {
  4827. strict_kademlia = GNUNET_YES;
  4828. }
  4829. if (GNUNET_YES ==
  4830. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "stop_on_closest"))
  4831. {
  4832. stop_on_closest = GNUNET_YES;
  4833. }
  4834. if (GNUNET_YES ==
  4835. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "stop_found"))
  4836. {
  4837. stop_on_found = GNUNET_YES;
  4838. }
  4839. if (GNUNET_YES ==
  4840. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "malicious_getter"))
  4841. {
  4842. malicious_getter = GNUNET_YES;
  4843. if (GNUNET_NO ==
  4844. GNUNET_CONFIGURATION_get_value_number (cfg, "DHT",
  4845. "MALICIOUS_GET_FREQUENCY",
  4846. &malicious_get_frequency))
  4847. malicious_get_frequency = DEFAULT_MALICIOUS_GET_FREQUENCY;
  4848. }
  4849. if (GNUNET_YES !=
  4850. GNUNET_CONFIGURATION_get_value_number (cfg, "DHT", "MAX_HOPS", &max_hops))
  4851. {
  4852. max_hops = DEFAULT_MAX_HOPS;
  4853. }
  4854. if (GNUNET_YES ==
  4855. GNUNET_CONFIGURATION_get_value_yesno (cfg, "DHT", "USE_MAX_HOPS"))
  4856. {
  4857. use_max_hops = GNUNET_YES;
  4858. }
  4859. if (GNUNET_YES ==
  4860. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "malicious_putter"))
  4861. {
  4862. malicious_putter = GNUNET_YES;
  4863. if (GNUNET_NO ==
  4864. GNUNET_CONFIGURATION_get_value_number (cfg, "DHT",
  4865. "MALICIOUS_PUT_FREQUENCY",
  4866. &malicious_put_frequency))
  4867. malicious_put_frequency = DEFAULT_MALICIOUS_PUT_FREQUENCY;
  4868. }
  4869. dht_republish_frequency = GNUNET_DHT_DEFAULT_REPUBLISH_FREQUENCY;
  4870. if (GNUNET_OK ==
  4871. GNUNET_CONFIGURATION_get_value_number (cfg, "DHT",
  4872. "REPLICATION_FREQUENCY",
  4873. &temp_config_num))
  4874. {
  4875. dht_republish_frequency =
  4876. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES,
  4877. temp_config_num);
  4878. }
  4879. if (GNUNET_OK ==
  4880. GNUNET_CONFIGURATION_get_value_number (cfg, "DHT", "bucket_size",
  4881. &temp_config_num))
  4882. {
  4883. bucket_size = (unsigned int) temp_config_num;
  4884. }
  4885. if (GNUNET_OK !=
  4886. GNUNET_CONFIGURATION_get_value_number (cfg, "DHT", "kad_alpha",
  4887. &kademlia_replication))
  4888. {
  4889. kademlia_replication = DEFAULT_KADEMLIA_REPLICATION;
  4890. }
  4891. if (GNUNET_YES ==
  4892. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "malicious_dropper"))
  4893. {
  4894. malicious_dropper = GNUNET_YES;
  4895. }
  4896. if (GNUNET_YES ==
  4897. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "republish"))
  4898. do_republish = GNUNET_NO;
  4899. if (GNUNET_NO ==
  4900. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "do_find_peer"))
  4901. {
  4902. do_find_peer = GNUNET_NO;
  4903. }
  4904. else
  4905. do_find_peer = GNUNET_YES;
  4906. if (GNUNET_YES ==
  4907. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "use_real_distance"))
  4908. use_real_distance = GNUNET_YES;
  4909. if (GNUNET_YES ==
  4910. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht_testing",
  4911. "mysql_logging_extended"))
  4912. {
  4913. debug_routes = GNUNET_YES;
  4914. debug_routes_extended = GNUNET_YES;
  4915. }
  4916. #if DEBUG_DHT_ROUTING
  4917. if (GNUNET_YES == debug_routes)
  4918. {
  4919. dhtlog_handle = GNUNET_DHTLOG_connect (cfg);
  4920. if (dhtlog_handle == NULL)
  4921. {
  4922. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  4923. "Could not connect to mysql logging server, logging will not happen!");
  4924. }
  4925. }
  4926. #endif
  4927. converge_option = DHT_CONVERGE_BINARY;
  4928. if (GNUNET_YES ==
  4929. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "converge_linear"))
  4930. {
  4931. converge_option = DHT_CONVERGE_LINEAR;
  4932. }
  4933. else if (GNUNET_YES ==
  4934. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht",
  4935. "converge_exponential"))
  4936. {
  4937. converge_option = DHT_CONVERGE_EXPONENTIAL;
  4938. }
  4939. else if (GNUNET_YES ==
  4940. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "converge_random"))
  4941. {
  4942. converge_option = DHT_CONVERGE_RANDOM;
  4943. }
  4944. else if (GNUNET_YES ==
  4945. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "converge_binary"))
  4946. {
  4947. converge_option = DHT_CONVERGE_BINARY;
  4948. }
  4949. converge_modifier = 4.0;
  4950. if (GNUNET_OK ==
  4951. GNUNET_CONFIGURATION_get_value_string (cfg, "dht", "converge_modifier",
  4952. &converge_modifier_buf))
  4953. {
  4954. if (1 != sscanf (converge_modifier_buf, "%f", &converge_modifier))
  4955. {
  4956. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  4957. "Failed to read decimal value for %s from `%s'\n",
  4958. "CONVERGE_MODIFIER", converge_modifier_buf);
  4959. converge_modifier = 0.0;
  4960. }
  4961. GNUNET_free (converge_modifier_buf);
  4962. }
  4963. if (GNUNET_YES ==
  4964. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "paper_forwarding"))
  4965. paper_forwarding = GNUNET_YES;
  4966. if (GNUNET_YES ==
  4967. GNUNET_CONFIGURATION_get_value_yesno (cfg, "dht", "put_peer_identities"))
  4968. put_peer_identities = GNUNET_YES;
  4969. stats = GNUNET_STATISTICS_create ("dht", cfg);
  4970. if (stats != NULL)
  4971. {
  4972. GNUNET_STATISTICS_set (stats, STAT_ROUTES, 0, GNUNET_NO);
  4973. GNUNET_STATISTICS_set (stats, STAT_ROUTE_FORWARDS, 0, GNUNET_NO);
  4974. GNUNET_STATISTICS_set (stats, STAT_ROUTE_FORWARDS_CLOSEST, 0, GNUNET_NO);
  4975. GNUNET_STATISTICS_set (stats, STAT_RESULTS, 0, GNUNET_NO);
  4976. GNUNET_STATISTICS_set (stats, STAT_RESULTS_TO_CLIENT, 0, GNUNET_NO);
  4977. GNUNET_STATISTICS_set (stats, STAT_RESULT_FORWARDS, 0, GNUNET_NO);
  4978. GNUNET_STATISTICS_set (stats, STAT_GETS, 0, GNUNET_NO);
  4979. GNUNET_STATISTICS_set (stats, STAT_PUTS, 0, GNUNET_NO);
  4980. GNUNET_STATISTICS_set (stats, STAT_PUTS_INSERTED, 0, GNUNET_NO);
  4981. GNUNET_STATISTICS_set (stats, STAT_FIND_PEER, 0, GNUNET_NO);
  4982. GNUNET_STATISTICS_set (stats, STAT_FIND_PEER_START, 0, GNUNET_NO);
  4983. GNUNET_STATISTICS_set (stats, STAT_GET_START, 0, GNUNET_NO);
  4984. GNUNET_STATISTICS_set (stats, STAT_PUT_START, 0, GNUNET_NO);
  4985. GNUNET_STATISTICS_set (stats, STAT_FIND_PEER_REPLY, 0, GNUNET_NO);
  4986. GNUNET_STATISTICS_set (stats, STAT_FIND_PEER_ANSWER, 0, GNUNET_NO);
  4987. GNUNET_STATISTICS_set (stats, STAT_BLOOM_FIND_PEER, 0, GNUNET_NO);
  4988. GNUNET_STATISTICS_set (stats, STAT_GET_REPLY, 0, GNUNET_NO);
  4989. GNUNET_STATISTICS_set (stats, STAT_GET_RESPONSE_START, 0, GNUNET_NO);
  4990. GNUNET_STATISTICS_set (stats, STAT_HELLOS_PROVIDED, 0, GNUNET_NO);
  4991. GNUNET_STATISTICS_set (stats, STAT_DISCONNECTS, 0, GNUNET_NO);
  4992. }
  4993. /* FIXME: if there are no recent requests then these never get freed, but alternative is _annoying_! */
  4994. recent.hashmap = GNUNET_CONTAINER_multihashmap_create (DHT_MAX_RECENT / 2);
  4995. recent.minHeap =
  4996. GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
  4997. if (GNUNET_YES == do_find_peer)
  4998. {
  4999. next_send_time.rel_value =
  5000. DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value +
  5001. GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
  5002. (DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value /
  5003. 2) -
  5004. DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value);
  5005. find_peer_context.start = GNUNET_TIME_absolute_get ();
  5006. GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_peer_message,
  5007. &find_peer_context);
  5008. }
  5009. /* Scheduled the task to clean up when shutdown is called */
  5010. cleanup_task =
  5011. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
  5012. &shutdown_task, NULL);
  5013. }
  5014. /**
  5015. * The main function for the dht service.
  5016. *
  5017. * @param argc number of arguments from the command line
  5018. * @param argv command line arguments
  5019. * @return 0 ok, 1 on error
  5020. */
  5021. int
  5022. main (int argc, char *const *argv)
  5023. {
  5024. int ret;
  5025. ret =
  5026. (GNUNET_OK ==
  5027. GNUNET_SERVICE_run (argc, argv, "dht", GNUNET_SERVICE_OPTION_NONE, &run,
  5028. NULL)) ? 0 : 1;
  5029. if (NULL != recent.hashmap)
  5030. {
  5031. GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (recent.hashmap));
  5032. GNUNET_CONTAINER_multihashmap_destroy (recent.hashmap);
  5033. recent.hashmap = NULL;
  5034. }
  5035. if (NULL != recent.minHeap)
  5036. {
  5037. GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (recent.minHeap));
  5038. GNUNET_CONTAINER_heap_destroy (recent.minHeap);
  5039. recent.minHeap = NULL;
  5040. }
  5041. if (NULL != recent_find_peer_requests)
  5042. {
  5043. GNUNET_CONTAINER_multihashmap_destroy (recent_find_peer_requests);
  5044. recent_find_peer_requests = NULL;
  5045. }
  5046. return ret;
  5047. }