plugin_transport_tcp.c 123 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2002--2015 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your 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. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file transport/plugin_transport_tcp.c
  18. * @brief Implementation of the TCP transport service
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_hello_lib.h"
  23. #include "gnunet_constants.h"
  24. #include "gnunet_util_lib.h"
  25. #include "gnunet_nat_service.h"
  26. #include "gnunet_protocols.h"
  27. #include "gnunet_resolver_service.h"
  28. #include "gnunet_signatures.h"
  29. #include "gnunet_statistics_service.h"
  30. #include "gnunet_transport_service.h"
  31. #include "gnunet_transport_plugin.h"
  32. #include "transport.h"
  33. #define LOG(kind,...) GNUNET_log_from (kind, "transport-tcp",__VA_ARGS__)
  34. #define PLUGIN_NAME "tcp"
  35. /**
  36. * How long until we give up on establishing an NAT connection?
  37. * Must be > 4 RTT
  38. */
  39. #define NAT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
  40. /**
  41. * Opaque handle that can be used to cancel
  42. * a transmit-ready notification.
  43. */
  44. struct GNUNET_CONNECTION_TransmitHandle;
  45. /**
  46. * @brief handle for a server
  47. */
  48. struct GNUNET_SERVER_Handle;
  49. /**
  50. * @brief opaque handle for a client of the server
  51. */
  52. struct GNUNET_SERVER_Client;
  53. /**
  54. * @brief opaque handle server returns for aborting transmission to a client.
  55. */
  56. struct GNUNET_SERVER_TransmitHandle;
  57. /**
  58. * @brief handle for a network connection
  59. */
  60. struct GNUNET_CONNECTION_Handle;
  61. /**
  62. * @brief handle for a network service
  63. */
  64. struct LEGACY_SERVICE_Context;
  65. /**
  66. * Stops a service that was started with #GNUNET_SERVICE_start().
  67. *
  68. * @param srv service to stop
  69. */
  70. void
  71. LEGACY_SERVICE_stop (struct LEGACY_SERVICE_Context *srv);
  72. /**
  73. * Function called to notify a client about the connection begin ready
  74. * to queue more data. @a buf will be NULL and @a size zero if the
  75. * connection was closed for writing in the meantime.
  76. *
  77. * @param cls closure
  78. * @param size number of bytes available in @a buf
  79. * @param buf where the callee should write the message
  80. * @return number of bytes written to @a buf
  81. */
  82. typedef size_t
  83. (*GNUNET_CONNECTION_TransmitReadyNotify) (void *cls,
  84. size_t size,
  85. void *buf);
  86. /**
  87. * Credentials for UNIX domain sockets.
  88. */
  89. struct GNUNET_CONNECTION_Credentials
  90. {
  91. /**
  92. * UID of the other end of the connection.
  93. */
  94. uid_t uid;
  95. /**
  96. * GID of the other end of the connection.
  97. */
  98. gid_t gid;
  99. };
  100. /**
  101. * Functions with this signature are called whenever a client
  102. * is disconnected on the network level.
  103. *
  104. * @param cls closure
  105. * @param client identification of the client; NULL
  106. * for the last call when the server is destroyed
  107. */
  108. typedef void
  109. (*GNUNET_SERVER_DisconnectCallback) (void *cls,
  110. struct GNUNET_SERVER_Client *client);
  111. /**
  112. * Functions with this signature are called whenever a client
  113. * is connected on the network level.
  114. *
  115. * @param cls closure
  116. * @param client identification of the client
  117. */
  118. typedef void
  119. (*GNUNET_SERVER_ConnectCallback) (void *cls,
  120. struct GNUNET_SERVER_Client *client);
  121. /**
  122. * Function to call for access control checks.
  123. *
  124. * @param cls closure
  125. * @param ucred credentials, if available, otherwise NULL
  126. * @param addr address
  127. * @param addrlen length of address
  128. * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR
  129. * for unknown address family (will be denied).
  130. */
  131. typedef int
  132. (*GNUNET_CONNECTION_AccessCheck) (void *cls,
  133. const struct
  134. GNUNET_CONNECTION_Credentials *
  135. ucred,
  136. const struct sockaddr * addr,
  137. socklen_t addrlen);
  138. /**
  139. * Callback function for data received from the network. Note that
  140. * both "available" and "err" would be 0 if the read simply timed out.
  141. *
  142. * @param cls closure
  143. * @param buf pointer to received data
  144. * @param available number of bytes availabe in "buf",
  145. * possibly 0 (on errors)
  146. * @param addr address of the sender
  147. * @param addrlen size of addr
  148. * @param errCode value of errno (on errors receiving)
  149. */
  150. typedef void
  151. (*GNUNET_CONNECTION_Receiver) (void *cls, const void *buf,
  152. size_t available,
  153. const struct sockaddr * addr,
  154. socklen_t addrlen, int errCode);
  155. /**
  156. * Close the connection and free associated resources. There must
  157. * not be any pending requests for reading or writing to the
  158. * connection at this time.
  159. *
  160. * @param connection connection to destroy
  161. */
  162. void
  163. GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection);
  164. /**
  165. * Signature of a function to create a custom tokenizer.
  166. *
  167. * @param cls closure from #GNUNET_SERVER_set_callbacks
  168. * @param client handle to client the tokenzier will be used for
  169. * @return handle to custom tokenizer ('mst')
  170. */
  171. typedef void*
  172. (*GNUNET_SERVER_MstCreateCallback) (void *cls,
  173. struct GNUNET_SERVER_Client *client);
  174. /**
  175. * Signature of a function to destroy a custom tokenizer.
  176. *
  177. * @param cls closure from #GNUNET_SERVER_set_callbacks
  178. * @param mst custom tokenizer handle
  179. */
  180. typedef void
  181. (*GNUNET_SERVER_MstDestroyCallback) (void *cls,
  182. void *mst);
  183. /**
  184. * Signature of a function to receive data for a custom tokenizer.
  185. *
  186. * @param cls closure from #GNUNET_SERVER_set_callbacks
  187. * @param mst custom tokenizer handle
  188. * @param client_identity ID of client for which this is a buffer,
  189. * can be NULL (will be passed back to 'cb')
  190. * @param buf input data to add
  191. * @param size number of bytes in @a buf
  192. * @param purge should any excess bytes in the buffer be discarded
  193. * (i.e. for packet-based services like UDP)
  194. * @param one_shot only call callback once, keep rest of message in buffer
  195. * @return #GNUNET_OK if we are done processing (need more data)
  196. * #GNUNET_NO if one_shot was set and we have another message ready
  197. * #GNUNET_SYSERR if the data stream is corrupt
  198. */
  199. typedef int
  200. (*GNUNET_SERVER_MstReceiveCallback) (void *cls, void *mst,
  201. struct GNUNET_SERVER_Client *client,
  202. const char *buf,
  203. size_t size,
  204. int purge,
  205. int one_shot);
  206. /**
  207. * Functions with this signature are called whenever a message is
  208. * received.
  209. *
  210. * @param cls closure
  211. * @param client identification of the client
  212. * @param message the actual message
  213. */
  214. typedef void
  215. (*GNUNET_SERVER_MessageCallback) (void *cls,
  216. struct GNUNET_SERVER_Client *client,
  217. const struct GNUNET_MessageHeader *message);
  218. /**
  219. * Message handler. Each struct specifies how to handle on particular
  220. * type of message received.
  221. */
  222. struct GNUNET_SERVER_MessageHandler
  223. {
  224. /**
  225. * Function to call for messages of "type".
  226. */
  227. GNUNET_SERVER_MessageCallback callback;
  228. /**
  229. * Closure argument for @e callback.
  230. */
  231. void *callback_cls;
  232. /**
  233. * Type of the message this handler covers.
  234. */
  235. uint16_t type;
  236. /**
  237. * Expected size of messages of this type. Use 0 for
  238. * variable-size. If non-zero, messages of the given
  239. * type will be discarded (and the connection closed)
  240. * if they do not have the right size.
  241. */
  242. uint16_t expected_size;
  243. };
  244. /**
  245. * Options for the service (bitmask).
  246. */
  247. enum LEGACY_SERVICE_Options
  248. {
  249. /**
  250. * Use defaults. Terminates all client connections and the listen
  251. * sockets immediately upon receiving the shutdown signal.
  252. */
  253. LEGACY_SERVICE_OPTION_NONE = 0,
  254. /**
  255. * Do not trigger server shutdown on signal at all; instead, allow
  256. * for the user to terminate the server explicitly when needed
  257. * by calling #LEGACY_SERVICE_shutdown().
  258. */
  259. LEGACY_SERVICE_OPTION_MANUAL_SHUTDOWN = 1,
  260. /**
  261. * Trigger a SOFT server shutdown on signals, allowing active
  262. * non-monitor clients to complete their transactions.
  263. */
  264. LEGACY_SERVICE_OPTION_SOFT_SHUTDOWN = 2
  265. };
  266. /**
  267. * Ask the server to disconnect from the given client. This is the
  268. * same as passing #GNUNET_SYSERR to #GNUNET_SERVER_receive_done,
  269. * except that it allows dropping of a client even when not handling a
  270. * message from that client.
  271. *
  272. * @param client the client to disconnect from
  273. */
  274. void
  275. GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client);
  276. /**
  277. * Return user context associated with the given client.
  278. * Note: you should probably use the macro (call without the underscore).
  279. *
  280. * @param client client to query
  281. * @param size number of bytes in user context struct (for verification only)
  282. * @return pointer to user context
  283. */
  284. void *
  285. GNUNET_SERVER_client_get_user_context_ (struct GNUNET_SERVER_Client *client,
  286. size_t size);
  287. /**
  288. * Functions with this signature are called whenever a
  289. * complete message is received by the tokenizer.
  290. *
  291. * Do not call #GNUNET_SERVER_mst_destroy from within
  292. * the scope of this callback.
  293. *
  294. * @param cls closure
  295. * @param client identification of the client
  296. * @param message the actual message
  297. * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
  298. */
  299. typedef int
  300. (*GNUNET_SERVER_MessageTokenizerCallback) (void *cls,
  301. void *client,
  302. const struct GNUNET_MessageHeader *message);
  303. /**
  304. * Create a message stream tokenizer.
  305. *
  306. * @param cb function to call on completed messages
  307. * @param cb_cls closure for @a cb
  308. * @return handle to tokenizer
  309. */
  310. struct GNUNET_SERVER_MessageStreamTokenizer *
  311. GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb,
  312. void *cb_cls);
  313. /**
  314. * Add incoming data to the receive buffer and call the
  315. * callback for all complete messages.
  316. *
  317. * @param mst tokenizer to use
  318. * @param client_identity ID of client for which this is a buffer,
  319. * can be NULL (will be passed back to 'cb')
  320. * @param buf input data to add
  321. * @param size number of bytes in @a buf
  322. * @param purge should any excess bytes in the buffer be discarded
  323. * (i.e. for packet-based services like UDP)
  324. * @param one_shot only call callback once, keep rest of message in buffer
  325. * @return #GNUNET_OK if we are done processing (need more data)
  326. * #GNUNET_NO if one_shot was set and we have another message ready
  327. * #GNUNET_SYSERR if the data stream is corrupt
  328. */
  329. int
  330. GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
  331. void *client_identity,
  332. const char *buf, size_t size,
  333. int purge, int one_shot);
  334. /**
  335. * Destroys a tokenizer.
  336. *
  337. * @param mst tokenizer to destroy
  338. */
  339. void
  340. GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst);
  341. /**
  342. * Set user context to be associated with the given client.
  343. * Note: you should probably use the macro (call without the underscore).
  344. *
  345. * @param client client to query
  346. * @param ptr pointer to user context
  347. * @param size number of bytes in user context struct (for verification only)
  348. */
  349. void
  350. GNUNET_SERVER_client_set_user_context_ (struct GNUNET_SERVER_Client *client,
  351. void *ptr,
  352. size_t size);
  353. /**
  354. * Return user context associated with the given client.
  355. *
  356. * @param client client to query
  357. * @param type expected return type (i.e. 'struct Foo')
  358. * @return pointer to user context of type 'type *'.
  359. */
  360. #define GNUNET_SERVER_client_get_user_context(client,type) \
  361. (type *) GNUNET_SERVER_client_get_user_context_ (client, sizeof (type))
  362. /**
  363. * Set user context to be associated with the given client.
  364. *
  365. * @param client client to query
  366. * @param value pointer to user context
  367. */
  368. #define GNUNET_SERVER_client_set_user_context(client,value) \
  369. GNUNET_SERVER_client_set_user_context_ (client, value, sizeof (*value))
  370. /**
  371. * Notify us when the server has enough space to transmit
  372. * a message of the given size to the given client.
  373. *
  374. * @param client client to transmit message to
  375. * @param size requested amount of buffer space
  376. * @param timeout after how long should we give up (and call
  377. * notify with buf NULL and size 0)?
  378. * @param callback function to call when space is available
  379. * @param callback_cls closure for @a callback
  380. * @return non-NULL if the notify callback was queued; can be used
  381. * to cancel the request using
  382. * #GNUNET_SERVER_notify_transmit_ready_cancel.
  383. * NULL if we are already going to notify someone else (busy)
  384. */
  385. struct GNUNET_SERVER_TransmitHandle *
  386. GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
  387. size_t size,
  388. struct GNUNET_TIME_Relative timeout,
  389. GNUNET_CONNECTION_TransmitReadyNotify callback,
  390. void *callback_cls);
  391. /**
  392. * Abort transmission request.
  393. *
  394. * @param th request to abort
  395. */
  396. void
  397. GNUNET_SERVER_notify_transmit_ready_cancel (struct GNUNET_SERVER_TransmitHandle *th);
  398. /**
  399. * Notify the server that the given client handle should
  400. * be kept (keeps the connection up if possible, increments
  401. * the internal reference counter).
  402. *
  403. * @param client the client to keep
  404. */
  405. void
  406. GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client);
  407. /**
  408. * Notify the server that the given client handle is no
  409. * longer required. Decrements the reference counter. If
  410. * that counter reaches zero an inactive connection maybe
  411. * closed.
  412. *
  413. * @param client the client to drop
  414. */
  415. void
  416. GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client);
  417. /**
  418. * Function called by the service's run
  419. * method to run service-specific setup code.
  420. *
  421. * @param cls closure
  422. * @param server the initialized server
  423. * @param cfg configuration to use
  424. */
  425. typedef void
  426. (*LEGACY_SERVICE_Main) (void *cls,
  427. struct GNUNET_SERVER_Handle *server,
  428. const struct GNUNET_CONFIGURATION_Handle *cfg);
  429. /**
  430. * Suspend accepting connections from the listen socket temporarily.
  431. * Resume activity using #GNUNET_SERVER_resume.
  432. *
  433. * @param server server to stop accepting connections.
  434. */
  435. void
  436. GNUNET_SERVER_suspend (struct GNUNET_SERVER_Handle *server);
  437. /**
  438. * Notify us when the server has enough space to transmit
  439. * a message of the given size to the given client.
  440. *
  441. * @param client client to transmit message to
  442. * @param size requested amount of buffer space
  443. * @param timeout after how long should we give up (and call
  444. * notify with buf NULL and size 0)?
  445. * @param callback function to call when space is available
  446. * @param callback_cls closure for @a callback
  447. * @return non-NULL if the notify callback was queued; can be used
  448. * to cancel the request using
  449. * #GNUNET_SERVER_notify_transmit_ready_cancel.
  450. * NULL if we are already going to notify someone else (busy)
  451. */
  452. struct GNUNET_SERVER_TransmitHandle *
  453. GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
  454. size_t size,
  455. struct GNUNET_TIME_Relative timeout,
  456. GNUNET_CONNECTION_TransmitReadyNotify callback,
  457. void *callback_cls);
  458. /**
  459. * Add a TCP socket-based connection to the set of handles managed by
  460. * this server. Use this function for outgoing (P2P) connections that
  461. * we initiated (and where this server should process incoming
  462. * messages).
  463. *
  464. * @param server the server to use
  465. * @param connection the connection to manage (client must
  466. * stop using this connection from now on)
  467. * @return the client handle
  468. */
  469. struct GNUNET_SERVER_Client *
  470. GNUNET_SERVER_connect_socket (struct GNUNET_SERVER_Handle *server,
  471. struct GNUNET_CONNECTION_Handle *connection);
  472. /**
  473. * Resume accepting connections from the listen socket.
  474. *
  475. * @param server server to resume accepting connections.
  476. */
  477. void
  478. GNUNET_SERVER_resume (struct GNUNET_SERVER_Handle *server);
  479. /**
  480. * Free resources held by this server.
  481. *
  482. * @param server server to destroy
  483. */
  484. void
  485. GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *server);
  486. #include "tcp_connection_legacy.c"
  487. #include "tcp_server_mst_legacy.c"
  488. #include "tcp_server_legacy.c"
  489. #include "tcp_service_legacy.c"
  490. GNUNET_NETWORK_STRUCT_BEGIN
  491. /**
  492. * Initial handshake message for a session.
  493. */
  494. struct WelcomeMessage
  495. {
  496. /**
  497. * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME.
  498. */
  499. struct GNUNET_MessageHeader header;
  500. /**
  501. * Identity of the node connecting (TCP client)
  502. */
  503. struct GNUNET_PeerIdentity clientIdentity;
  504. };
  505. /**
  506. * Basically a WELCOME message, but with the purpose
  507. * of giving the waiting peer a client handle to use
  508. */
  509. struct TCP_NAT_ProbeMessage
  510. {
  511. /**
  512. * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE.
  513. */
  514. struct GNUNET_MessageHeader header;
  515. /**
  516. * Identity of the sender of the message.
  517. */
  518. struct GNUNET_PeerIdentity clientIdentity;
  519. };
  520. GNUNET_NETWORK_STRUCT_END
  521. /**
  522. * Context for sending a NAT probe via TCP.
  523. */
  524. struct TCPProbeContext
  525. {
  526. /**
  527. * Active probes are kept in a DLL.
  528. */
  529. struct TCPProbeContext *next;
  530. /**
  531. * Active probes are kept in a DLL.
  532. */
  533. struct TCPProbeContext *prev;
  534. /**
  535. * Probe connection.
  536. */
  537. struct GNUNET_CONNECTION_Handle *sock;
  538. /**
  539. * Message to be sent.
  540. */
  541. struct TCP_NAT_ProbeMessage message;
  542. /**
  543. * Handle to the transmission.
  544. */
  545. struct GNUNET_CONNECTION_TransmitHandle *transmit_handle;
  546. /**
  547. * Transport plugin handle.
  548. */
  549. struct Plugin *plugin;
  550. };
  551. /**
  552. * Bits in the `options` field of TCP addresses.
  553. */
  554. enum TcpAddressOptions
  555. {
  556. /**
  557. * No bits set.
  558. */
  559. TCP_OPTIONS_NONE = 0,
  560. /**
  561. * See #HTTP_OPTIONS_VERIFY_CERTIFICATE.
  562. */
  563. TCP_OPTIONS_RESERVED = 1,
  564. /**
  565. * Enable TCP Stealth-style port knocking.
  566. */
  567. TCP_OPTIONS_TCP_STEALTH = 2
  568. };
  569. GNUNET_NETWORK_STRUCT_BEGIN
  570. /**
  571. * Network format for IPv4 addresses.
  572. */
  573. struct IPv4TcpAddress
  574. {
  575. /**
  576. * Optional options and flags for this address,
  577. * see `enum TcpAddressOptions`
  578. */
  579. uint32_t options GNUNET_PACKED;
  580. /**
  581. * IPv4 address, in network byte order.
  582. */
  583. uint32_t ipv4_addr GNUNET_PACKED;
  584. /**
  585. * Port number, in network byte order.
  586. */
  587. uint16_t t4_port GNUNET_PACKED;
  588. };
  589. /**
  590. * Network format for IPv6 addresses.
  591. */
  592. struct IPv6TcpAddress
  593. {
  594. /**
  595. * Optional flags for this address
  596. * see `enum TcpAddressOptions`
  597. */
  598. uint32_t options GNUNET_PACKED;
  599. /**
  600. * IPv6 address.
  601. */
  602. struct in6_addr ipv6_addr GNUNET_PACKED;
  603. /**
  604. * Port number, in network byte order.
  605. */
  606. uint16_t t6_port GNUNET_PACKED;
  607. };
  608. GNUNET_NETWORK_STRUCT_END
  609. /**
  610. * Encapsulation of all of the state of the plugin.
  611. */
  612. struct Plugin;
  613. /**
  614. * Information kept for each message that is yet to
  615. * be transmitted.
  616. */
  617. struct PendingMessage
  618. {
  619. /**
  620. * This is a doubly-linked list.
  621. */
  622. struct PendingMessage *next;
  623. /**
  624. * This is a doubly-linked list.
  625. */
  626. struct PendingMessage *prev;
  627. /**
  628. * The pending message
  629. */
  630. const char *msg;
  631. /**
  632. * Continuation function to call once the message
  633. * has been sent. Can be NULL if there is no
  634. * continuation to call.
  635. */
  636. GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
  637. /**
  638. * Closure for @e transmit_cont.
  639. */
  640. void *transmit_cont_cls;
  641. /**
  642. * Timeout value for the pending message.
  643. */
  644. struct GNUNET_TIME_Absolute timeout;
  645. /**
  646. * So that the gnunet-service-transport can group messages together,
  647. * these pending messages need to accept a message buffer and size
  648. * instead of just a `struct GNUNET_MessageHeader`.
  649. */
  650. size_t message_size;
  651. };
  652. /**
  653. * Session handle for TCP connections.
  654. */
  655. struct GNUNET_ATS_Session
  656. {
  657. /**
  658. * To whom are we talking to (set to our identity
  659. * if we are still waiting for the welcome message)
  660. */
  661. struct GNUNET_PeerIdentity target;
  662. /**
  663. * Pointer to the global plugin struct.
  664. */
  665. struct Plugin *plugin;
  666. /**
  667. * The client (used to identify this connection)
  668. */
  669. struct GNUNET_SERVER_Client *client;
  670. /**
  671. * Task cleaning up a NAT client connection establishment attempt;
  672. */
  673. struct GNUNET_SCHEDULER_Task *nat_connection_timeout;
  674. /**
  675. * Messages currently pending for transmission
  676. * to this peer, if any.
  677. */
  678. struct PendingMessage *pending_messages_head;
  679. /**
  680. * Messages currently pending for transmission
  681. * to this peer, if any.
  682. */
  683. struct PendingMessage *pending_messages_tail;
  684. /**
  685. * Handle for pending transmission request.
  686. */
  687. struct GNUNET_SERVER_TransmitHandle *transmit_handle;
  688. /**
  689. * Address of the other peer.
  690. */
  691. struct GNUNET_HELLO_Address *address;
  692. /**
  693. * ID of task used to delay receiving more to throttle sender.
  694. */
  695. struct GNUNET_SCHEDULER_Task *receive_delay_task;
  696. /**
  697. * Session timeout task
  698. */
  699. struct GNUNET_SCHEDULER_Task *timeout_task;
  700. /**
  701. * When will this session time out?
  702. */
  703. struct GNUNET_TIME_Absolute timeout;
  704. /**
  705. * When will we continue to read from the socket?
  706. * (used to enforce inbound quota).
  707. */
  708. struct GNUNET_TIME_Absolute receive_delay;
  709. /**
  710. * Last activity on this connection. Used to select preferred
  711. * connection.
  712. */
  713. struct GNUNET_TIME_Absolute last_activity;
  714. /**
  715. * Number of bytes waiting for transmission to this peer.
  716. */
  717. unsigned long long bytes_in_queue;
  718. /**
  719. * Number of messages waiting for transmission to this peer.
  720. */
  721. unsigned int msgs_in_queue;
  722. /**
  723. * Network type of the address.
  724. */
  725. enum GNUNET_NetworkType scope;
  726. /**
  727. * Are we still expecting the welcome message? (#GNUNET_YES/#GNUNET_NO)
  728. */
  729. int expecting_welcome;
  730. /**
  731. * Was this session created using NAT traversal?
  732. */
  733. int is_nat;
  734. };
  735. /**
  736. * Context for address to string conversion, closure
  737. * for #append_port().
  738. */
  739. struct PrettyPrinterContext
  740. {
  741. /**
  742. * DLL
  743. */
  744. struct PrettyPrinterContext *next;
  745. /**
  746. * DLL
  747. */
  748. struct PrettyPrinterContext *prev;
  749. /**
  750. * Our plugin.
  751. */
  752. struct Plugin *plugin;
  753. /**
  754. * Timeout task
  755. */
  756. struct GNUNET_SCHEDULER_Task *timeout_task;
  757. /**
  758. * Resolver handle
  759. */
  760. struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
  761. /**
  762. * Function to call with the result.
  763. */
  764. GNUNET_TRANSPORT_AddressStringCallback asc;
  765. /**
  766. * Clsoure for @e asc.
  767. */
  768. void *asc_cls;
  769. /**
  770. * IPv6 address
  771. */
  772. int ipv6;
  773. /**
  774. * Options
  775. */
  776. uint32_t options;
  777. /**
  778. * Port to add after the IP address.
  779. */
  780. uint16_t port;
  781. };
  782. /**
  783. * Encapsulation of all of the state of the plugin.
  784. */
  785. struct Plugin
  786. {
  787. /**
  788. * Our environment.
  789. */
  790. struct GNUNET_TRANSPORT_PluginEnvironment *env;
  791. /**
  792. * The listen socket.
  793. */
  794. struct GNUNET_CONNECTION_Handle *lsock;
  795. /**
  796. * Our handle to the NAT module.
  797. */
  798. struct GNUNET_NAT_Handle *nat;
  799. /**
  800. * Map from peer identities to sessions for the given peer.
  801. */
  802. struct GNUNET_CONTAINER_MultiPeerMap *sessionmap;
  803. /**
  804. * Handle to the network service.
  805. */
  806. struct LEGACY_SERVICE_Context *service;
  807. /**
  808. * Handle to the server for this service.
  809. */
  810. struct GNUNET_SERVER_Handle *server;
  811. /**
  812. * Copy of the handler array where the closures are
  813. * set to this struct's instance.
  814. */
  815. struct GNUNET_SERVER_MessageHandler *handlers;
  816. /**
  817. * Map of peers we have tried to contact behind a NAT
  818. */
  819. struct GNUNET_CONTAINER_MultiPeerMap *nat_wait_conns;
  820. /**
  821. * List of active TCP probes.
  822. */
  823. struct TCPProbeContext *probe_head;
  824. /**
  825. * List of active TCP probes.
  826. */
  827. struct TCPProbeContext *probe_tail;
  828. /**
  829. * Function to call about session status changes.
  830. */
  831. GNUNET_TRANSPORT_SessionInfoCallback sic;
  832. /**
  833. * Closure for @e sic.
  834. */
  835. void *sic_cls;
  836. /**
  837. * ID of task used to update our addresses when one expires.
  838. */
  839. struct GNUNET_SCHEDULER_Task *address_update_task;
  840. /**
  841. * Running pretty printers: head
  842. */
  843. struct PrettyPrinterContext *ppc_dll_head;
  844. /**
  845. * Running pretty printers: tail
  846. */
  847. struct PrettyPrinterContext *ppc_dll_tail;
  848. /**
  849. * Welcome message used by this peer.
  850. */
  851. struct WelcomeMessage my_welcome;
  852. /**
  853. * How many more TCP sessions are we allowed to open right now?
  854. */
  855. unsigned long long max_connections;
  856. /**
  857. * How many more TCP sessions do we have right now?
  858. */
  859. unsigned long long cur_connections;
  860. /**
  861. * Address options
  862. */
  863. uint32_t myoptions;
  864. /**
  865. * Port that we are actually listening on.
  866. */
  867. uint16_t open_port;
  868. /**
  869. * Port that the user said we would have visible to the
  870. * rest of the world.
  871. */
  872. uint16_t adv_port;
  873. };
  874. /**
  875. * Get the list of addresses that a server for the given service
  876. * should bind to.
  877. *
  878. * @param service_name name of the service
  879. * @param cfg configuration (which specifies the addresses)
  880. * @param addrs set (call by reference) to an array of pointers to the
  881. * addresses the server should bind to and listen on; the
  882. * array will be NULL-terminated (on success)
  883. * @param addr_lens set (call by reference) to an array of the lengths
  884. * of the respective `struct sockaddr` struct in the @a addrs
  885. * array (on success)
  886. * @return number of addresses found on success,
  887. * #GNUNET_SYSERR if the configuration
  888. * did not specify reasonable finding information or
  889. * if it specified a hostname that could not be resolved;
  890. * #GNUNET_NO if the number of addresses configured is
  891. * zero (in this case, `*addrs` and `*addr_lens` will be
  892. * set to NULL).
  893. */
  894. static int
  895. get_server_addresses (const char *service_name,
  896. const struct GNUNET_CONFIGURATION_Handle *cfg,
  897. struct sockaddr ***addrs,
  898. socklen_t ** addr_lens)
  899. {
  900. int disablev6;
  901. struct GNUNET_NETWORK_Handle *desc;
  902. unsigned long long port;
  903. char *unixpath;
  904. struct addrinfo hints;
  905. struct addrinfo *res;
  906. struct addrinfo *pos;
  907. struct addrinfo *next;
  908. unsigned int i;
  909. int resi;
  910. int ret;
  911. int abstract;
  912. struct sockaddr **saddrs;
  913. socklen_t *saddrlens;
  914. char *hostname;
  915. *addrs = NULL;
  916. *addr_lens = NULL;
  917. desc = NULL;
  918. if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
  919. {
  920. if (GNUNET_SYSERR ==
  921. (disablev6 =
  922. GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
  923. return GNUNET_SYSERR;
  924. }
  925. else
  926. disablev6 = GNUNET_NO;
  927. if (! disablev6)
  928. {
  929. /* probe IPv6 support */
  930. desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
  931. if (NULL == desc)
  932. {
  933. if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
  934. (EACCES == errno))
  935. {
  936. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
  937. return GNUNET_SYSERR;
  938. }
  939. LOG (GNUNET_ERROR_TYPE_INFO,
  940. _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
  941. service_name, STRERROR (errno));
  942. disablev6 = GNUNET_YES;
  943. }
  944. else
  945. {
  946. GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
  947. desc = NULL;
  948. }
  949. }
  950. port = 0;
  951. if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
  952. {
  953. if (GNUNET_OK !=
  954. GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
  955. "PORT", &port))
  956. {
  957. LOG (GNUNET_ERROR_TYPE_ERROR,
  958. _("Require valid port number for service `%s' in configuration!\n"),
  959. service_name);
  960. }
  961. if (port > 65535)
  962. {
  963. LOG (GNUNET_ERROR_TYPE_ERROR,
  964. _("Require valid port number for service `%s' in configuration!\n"),
  965. service_name);
  966. return GNUNET_SYSERR;
  967. }
  968. }
  969. if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
  970. {
  971. GNUNET_break (GNUNET_OK ==
  972. GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
  973. "BINDTO", &hostname));
  974. }
  975. else
  976. hostname = NULL;
  977. unixpath = NULL;
  978. abstract = GNUNET_NO;
  979. #ifdef AF_UNIX
  980. if ((GNUNET_YES ==
  981. GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
  982. (GNUNET_OK ==
  983. GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
  984. &unixpath)) &&
  985. (0 < strlen (unixpath)))
  986. {
  987. /* probe UNIX support */
  988. struct sockaddr_un s_un;
  989. if (strlen (unixpath) >= sizeof (s_un.sun_path))
  990. {
  991. LOG (GNUNET_ERROR_TYPE_WARNING,
  992. _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
  993. (unsigned long long) sizeof (s_un.sun_path));
  994. unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
  995. LOG (GNUNET_ERROR_TYPE_INFO,
  996. _("Using `%s' instead\n"),
  997. unixpath);
  998. }
  999. #ifdef LINUX
  1000. abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1001. "TESTING",
  1002. "USE_ABSTRACT_SOCKETS");
  1003. if (GNUNET_SYSERR == abstract)
  1004. abstract = GNUNET_NO;
  1005. #endif
  1006. if ((GNUNET_YES != abstract)
  1007. && (GNUNET_OK !=
  1008. GNUNET_DISK_directory_create_for_file (unixpath)))
  1009. GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
  1010. "mkdir",
  1011. unixpath);
  1012. }
  1013. if (NULL != unixpath)
  1014. {
  1015. desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
  1016. if (NULL == desc)
  1017. {
  1018. if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
  1019. (EACCES == errno))
  1020. {
  1021. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
  1022. GNUNET_free_non_null (hostname);
  1023. GNUNET_free (unixpath);
  1024. return GNUNET_SYSERR;
  1025. }
  1026. LOG (GNUNET_ERROR_TYPE_INFO,
  1027. _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
  1028. service_name,
  1029. STRERROR (errno));
  1030. GNUNET_free (unixpath);
  1031. unixpath = NULL;
  1032. }
  1033. else
  1034. {
  1035. GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
  1036. desc = NULL;
  1037. }
  1038. }
  1039. #endif
  1040. if ((0 == port) && (NULL == unixpath))
  1041. {
  1042. LOG (GNUNET_ERROR_TYPE_ERROR,
  1043. _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
  1044. service_name);
  1045. GNUNET_free_non_null (hostname);
  1046. return GNUNET_SYSERR;
  1047. }
  1048. if (0 == port)
  1049. {
  1050. saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
  1051. saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
  1052. add_unixpath (saddrs, saddrlens, unixpath, abstract);
  1053. GNUNET_free_non_null (unixpath);
  1054. GNUNET_free_non_null (hostname);
  1055. *addrs = saddrs;
  1056. *addr_lens = saddrlens;
  1057. return 1;
  1058. }
  1059. if (NULL != hostname)
  1060. {
  1061. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1062. "Resolving `%s' since that is where `%s' will bind to.\n",
  1063. hostname,
  1064. service_name);
  1065. memset (&hints, 0, sizeof (struct addrinfo));
  1066. if (disablev6)
  1067. hints.ai_family = AF_INET;
  1068. hints.ai_protocol = IPPROTO_TCP;
  1069. if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
  1070. (NULL == res))
  1071. {
  1072. LOG (GNUNET_ERROR_TYPE_ERROR,
  1073. _("Failed to resolve `%s': %s\n"),
  1074. hostname,
  1075. gai_strerror (ret));
  1076. GNUNET_free (hostname);
  1077. GNUNET_free_non_null (unixpath);
  1078. return GNUNET_SYSERR;
  1079. }
  1080. next = res;
  1081. i = 0;
  1082. while (NULL != (pos = next))
  1083. {
  1084. next = pos->ai_next;
  1085. if ((disablev6) && (pos->ai_family == AF_INET6))
  1086. continue;
  1087. i++;
  1088. }
  1089. if (0 == i)
  1090. {
  1091. LOG (GNUNET_ERROR_TYPE_ERROR,
  1092. _("Failed to find %saddress for `%s'.\n"),
  1093. disablev6 ? "IPv4 " : "",
  1094. hostname);
  1095. freeaddrinfo (res);
  1096. GNUNET_free (hostname);
  1097. GNUNET_free_non_null (unixpath);
  1098. return GNUNET_SYSERR;
  1099. }
  1100. resi = i;
  1101. if (NULL != unixpath)
  1102. resi++;
  1103. saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
  1104. saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
  1105. i = 0;
  1106. if (NULL != unixpath)
  1107. {
  1108. add_unixpath (saddrs, saddrlens, unixpath, abstract);
  1109. i++;
  1110. }
  1111. next = res;
  1112. while (NULL != (pos = next))
  1113. {
  1114. next = pos->ai_next;
  1115. if ((disablev6) && (AF_INET6 == pos->ai_family))
  1116. continue;
  1117. if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
  1118. continue; /* not TCP */
  1119. if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
  1120. continue; /* huh? */
  1121. LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
  1122. service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
  1123. if (AF_INET == pos->ai_family)
  1124. {
  1125. GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
  1126. saddrlens[i] = pos->ai_addrlen;
  1127. saddrs[i] = GNUNET_malloc (saddrlens[i]);
  1128. GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
  1129. ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
  1130. }
  1131. else
  1132. {
  1133. GNUNET_assert (AF_INET6 == pos->ai_family);
  1134. GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
  1135. saddrlens[i] = pos->ai_addrlen;
  1136. saddrs[i] = GNUNET_malloc (saddrlens[i]);
  1137. GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
  1138. ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
  1139. }
  1140. i++;
  1141. }
  1142. GNUNET_free (hostname);
  1143. freeaddrinfo (res);
  1144. resi = i;
  1145. }
  1146. else
  1147. {
  1148. /* will bind against everything, just set port */
  1149. if (disablev6)
  1150. {
  1151. /* V4-only */
  1152. resi = 1;
  1153. if (NULL != unixpath)
  1154. resi++;
  1155. i = 0;
  1156. saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
  1157. saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
  1158. if (NULL != unixpath)
  1159. {
  1160. add_unixpath (saddrs, saddrlens, unixpath, abstract);
  1161. i++;
  1162. }
  1163. saddrlens[i] = sizeof (struct sockaddr_in);
  1164. saddrs[i] = GNUNET_malloc (saddrlens[i]);
  1165. #if HAVE_SOCKADDR_IN_SIN_LEN
  1166. ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
  1167. #endif
  1168. ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
  1169. ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
  1170. }
  1171. else
  1172. {
  1173. /* dual stack */
  1174. resi = 2;
  1175. if (NULL != unixpath)
  1176. resi++;
  1177. saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
  1178. saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
  1179. i = 0;
  1180. if (NULL != unixpath)
  1181. {
  1182. add_unixpath (saddrs, saddrlens, unixpath, abstract);
  1183. i++;
  1184. }
  1185. saddrlens[i] = sizeof (struct sockaddr_in6);
  1186. saddrs[i] = GNUNET_malloc (saddrlens[i]);
  1187. #if HAVE_SOCKADDR_IN_SIN_LEN
  1188. ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
  1189. #endif
  1190. ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
  1191. ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
  1192. i++;
  1193. saddrlens[i] = sizeof (struct sockaddr_in);
  1194. saddrs[i] = GNUNET_malloc (saddrlens[i]);
  1195. #if HAVE_SOCKADDR_IN_SIN_LEN
  1196. ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
  1197. #endif
  1198. ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
  1199. ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
  1200. }
  1201. }
  1202. GNUNET_free_non_null (unixpath);
  1203. *addrs = saddrs;
  1204. *addr_lens = saddrlens;
  1205. return resi;
  1206. }
  1207. /* end ancient copy-and-paste */
  1208. /**
  1209. * If a session monitor is attached, notify it about the new
  1210. * session state.
  1211. *
  1212. * @param plugin our plugin
  1213. * @param session session that changed state
  1214. * @param state new state of the session
  1215. */
  1216. static void
  1217. notify_session_monitor (struct Plugin *plugin,
  1218. struct GNUNET_ATS_Session *session,
  1219. enum GNUNET_TRANSPORT_SessionState state)
  1220. {
  1221. struct GNUNET_TRANSPORT_SessionInfo info;
  1222. if (NULL == plugin->sic)
  1223. return;
  1224. memset (&info, 0, sizeof (info));
  1225. info.state = state;
  1226. info.is_inbound = GNUNET_HELLO_address_check_option (session->address,
  1227. GNUNET_HELLO_ADDRESS_INFO_INBOUND);
  1228. info.num_msg_pending = session->msgs_in_queue;
  1229. info.num_bytes_pending = session->bytes_in_queue;
  1230. if (NULL != session->receive_delay_task)
  1231. info.receive_delay = session->receive_delay;
  1232. info.session_timeout = session->timeout;
  1233. info.address = session->address;
  1234. plugin->sic (plugin->sic_cls,
  1235. session,
  1236. &info);
  1237. }
  1238. /**
  1239. * Our external IP address/port mapping has changed.
  1240. *
  1241. * @param cls closure, the `struct Plugin`
  1242. * @param app_ctx[in,out] location where the app can store stuff
  1243. * on add and retrieve it on remove
  1244. * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
  1245. * the previous (now invalid) one
  1246. * @param ac address class the address belongs to
  1247. * @param addr either the previous or the new public IP address
  1248. * @param addrlen actual length of @a addr
  1249. */
  1250. static void
  1251. tcp_nat_port_map_callback (void *cls,
  1252. void **app_ctx,
  1253. int add_remove,
  1254. enum GNUNET_NAT_AddressClass ac,
  1255. const struct sockaddr *addr,
  1256. socklen_t addrlen)
  1257. {
  1258. struct Plugin *plugin = cls;
  1259. struct GNUNET_HELLO_Address *address;
  1260. struct IPv4TcpAddress t4;
  1261. struct IPv6TcpAddress t6;
  1262. void *arg;
  1263. size_t args;
  1264. (void) app_ctx;
  1265. LOG (GNUNET_ERROR_TYPE_INFO,
  1266. "NAT notification to %s address `%s'\n",
  1267. (GNUNET_YES == add_remove) ? "add" : "remove",
  1268. GNUNET_a2s (addr, addrlen));
  1269. /* convert 'addr' to our internal format */
  1270. switch (addr->sa_family)
  1271. {
  1272. case AF_INET:
  1273. GNUNET_assert(addrlen == sizeof(struct sockaddr_in));
  1274. memset (&t4, 0, sizeof(t4));
  1275. t4.options = htonl (plugin->myoptions);
  1276. t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
  1277. t4.t4_port = ((struct sockaddr_in *) addr)->sin_port;
  1278. arg = &t4;
  1279. args = sizeof (t4);
  1280. break;
  1281. case AF_INET6:
  1282. if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
  1283. {
  1284. /* skip link local, we don't allow them in
  1285. #tcp_plugin_check_address() */
  1286. return;
  1287. }
  1288. GNUNET_assert(addrlen == sizeof(struct sockaddr_in6));
  1289. memset (&t6, 0, sizeof(t6));
  1290. GNUNET_memcpy (&t6.ipv6_addr,
  1291. &((struct sockaddr_in6 *) addr)->sin6_addr,
  1292. sizeof(struct in6_addr));
  1293. t6.options = htonl (plugin->myoptions);
  1294. t6.t6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
  1295. arg = &t6;
  1296. args = sizeof (t6);
  1297. break;
  1298. default:
  1299. GNUNET_break(0);
  1300. return;
  1301. }
  1302. /* modify our published address list */
  1303. GNUNET_assert ((args == sizeof (struct IPv4TcpAddress)) ||
  1304. (args == sizeof (struct IPv6TcpAddress)));
  1305. /* TODO: use 'ac' here in the future... */
  1306. address = GNUNET_HELLO_address_allocate (plugin->env->my_identity,
  1307. PLUGIN_NAME,
  1308. arg,
  1309. args,
  1310. GNUNET_HELLO_ADDRESS_INFO_NONE);
  1311. plugin->env->notify_address (plugin->env->cls,
  1312. add_remove,
  1313. address);
  1314. GNUNET_HELLO_address_free (address);
  1315. }
  1316. /**
  1317. * Function called for a quick conversion of the binary address to
  1318. * a numeric address. Note that the caller must not free the
  1319. * address and that the next call to this function is allowed
  1320. * to override the address again.
  1321. *
  1322. * @param cls closure (`struct Plugin*`)
  1323. * @param addr binary address
  1324. * @param addrlen length of @a addr
  1325. * @return string representing the same address
  1326. */
  1327. static const char *
  1328. tcp_plugin_address_to_string (void *cls,
  1329. const void *addr,
  1330. size_t addrlen)
  1331. {
  1332. static char rbuf[INET6_ADDRSTRLEN + 12];
  1333. char buf[INET6_ADDRSTRLEN];
  1334. const void *sb;
  1335. struct in_addr a4;
  1336. struct in6_addr a6;
  1337. const struct IPv4TcpAddress *t4;
  1338. const struct IPv6TcpAddress *t6;
  1339. int af;
  1340. uint16_t port;
  1341. uint32_t options;
  1342. switch (addrlen)
  1343. {
  1344. case sizeof(struct IPv6TcpAddress):
  1345. t6 = addr;
  1346. af = AF_INET6;
  1347. port = ntohs (t6->t6_port);
  1348. options = ntohl (t6->options);
  1349. GNUNET_memcpy (&a6, &t6->ipv6_addr, sizeof(a6));
  1350. sb = &a6;
  1351. break;
  1352. case sizeof(struct IPv4TcpAddress):
  1353. t4 = addr;
  1354. af = AF_INET;
  1355. port = ntohs (t4->t4_port);
  1356. options = ntohl (t4->options);
  1357. GNUNET_memcpy (&a4, &t4->ipv4_addr, sizeof(a4));
  1358. sb = &a4;
  1359. break;
  1360. default:
  1361. LOG (GNUNET_ERROR_TYPE_WARNING,
  1362. _("Unexpected address length: %u bytes\n"),
  1363. (unsigned int) addrlen);
  1364. return NULL ;
  1365. }
  1366. if (NULL == inet_ntop (af, sb, buf, INET6_ADDRSTRLEN))
  1367. {
  1368. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
  1369. "inet_ntop");
  1370. return NULL ;
  1371. }
  1372. GNUNET_snprintf (rbuf, sizeof(rbuf),
  1373. (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u",
  1374. PLUGIN_NAME,
  1375. options,
  1376. buf,
  1377. port);
  1378. return rbuf;
  1379. }
  1380. /**
  1381. * Function called to convert a string address to
  1382. * a binary address.
  1383. *
  1384. * @param cls closure (`struct Plugin*`)
  1385. * @param addr string address
  1386. * @param addrlen length of the address
  1387. * @param buf location to store the buffer
  1388. * @param added location to store the number of bytes in the buffer.
  1389. * If the function returns #GNUNET_SYSERR, its contents are undefined.
  1390. * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  1391. */
  1392. static int
  1393. tcp_plugin_string_to_address (void *cls,
  1394. const char *addr,
  1395. uint16_t addrlen,
  1396. void **buf,
  1397. size_t *added)
  1398. {
  1399. struct sockaddr_storage socket_address;
  1400. char *address;
  1401. char *plugin;
  1402. char *optionstr;
  1403. uint32_t options;
  1404. /* Format tcp.options.address:port */
  1405. address = NULL;
  1406. plugin = NULL;
  1407. optionstr = NULL;
  1408. if ((NULL == addr) || (0 == addrlen))
  1409. {
  1410. GNUNET_break(0);
  1411. return GNUNET_SYSERR;
  1412. }
  1413. if ('\0' != addr[addrlen - 1])
  1414. {
  1415. GNUNET_break(0);
  1416. return GNUNET_SYSERR;
  1417. }
  1418. if (strlen (addr) != addrlen - 1)
  1419. {
  1420. GNUNET_break(0);
  1421. return GNUNET_SYSERR;
  1422. }
  1423. plugin = GNUNET_strdup (addr);
  1424. optionstr = strchr (plugin, '.');
  1425. if (NULL == optionstr)
  1426. {
  1427. GNUNET_break(0);
  1428. GNUNET_free(plugin);
  1429. return GNUNET_SYSERR;
  1430. }
  1431. optionstr[0] = '\0';
  1432. optionstr++;
  1433. options = atol (optionstr);
  1434. address = strchr (optionstr, '.');
  1435. if (NULL == address)
  1436. {
  1437. GNUNET_break(0);
  1438. GNUNET_free(plugin);
  1439. return GNUNET_SYSERR;
  1440. }
  1441. address[0] = '\0';
  1442. address++;
  1443. if (GNUNET_OK !=
  1444. GNUNET_STRINGS_to_address_ip (address,
  1445. strlen (address),
  1446. &socket_address))
  1447. {
  1448. GNUNET_break(0);
  1449. GNUNET_free(plugin);
  1450. return GNUNET_SYSERR;
  1451. }
  1452. GNUNET_free(plugin);
  1453. switch (socket_address.ss_family)
  1454. {
  1455. case AF_INET:
  1456. {
  1457. struct IPv4TcpAddress *t4;
  1458. struct sockaddr_in *in4 = (struct sockaddr_in *) &socket_address;
  1459. t4 = GNUNET_new (struct IPv4TcpAddress);
  1460. t4->options = htonl (options);
  1461. t4->ipv4_addr = in4->sin_addr.s_addr;
  1462. t4->t4_port = in4->sin_port;
  1463. *buf = t4;
  1464. *added = sizeof(struct IPv4TcpAddress);
  1465. return GNUNET_OK;
  1466. }
  1467. case AF_INET6:
  1468. {
  1469. struct IPv6TcpAddress *t6;
  1470. struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &socket_address;
  1471. t6 = GNUNET_new (struct IPv6TcpAddress);
  1472. t6->options = htonl (options);
  1473. t6->ipv6_addr = in6->sin6_addr;
  1474. t6->t6_port = in6->sin6_port;
  1475. *buf = t6;
  1476. *added = sizeof(struct IPv6TcpAddress);
  1477. return GNUNET_OK;
  1478. }
  1479. default:
  1480. return GNUNET_SYSERR;
  1481. }
  1482. }
  1483. /**
  1484. * Find the session handle for the given client.
  1485. * Currently uses both the hashmap and the client
  1486. * context, as the client context is new and the
  1487. * logic still needs to be tested.
  1488. *
  1489. * @param plugin the plugin
  1490. * @param client which client to find the session handle for
  1491. * @return NULL if no matching session exists
  1492. */
  1493. static struct GNUNET_ATS_Session *
  1494. lookup_session_by_client (struct Plugin *plugin,
  1495. struct GNUNET_SERVER_Client *client)
  1496. {
  1497. return GNUNET_SERVER_client_get_user_context (client,
  1498. struct GNUNET_ATS_Session);
  1499. }
  1500. /**
  1501. * Functions with this signature are called whenever we need
  1502. * to close a session due to a disconnect or failure to
  1503. * establish a connection.
  1504. *
  1505. * @param cls the `struct Plugin`
  1506. * @param session session to close down
  1507. * @return #GNUNET_OK on success
  1508. */
  1509. static int
  1510. tcp_plugin_disconnect_session (void *cls,
  1511. struct GNUNET_ATS_Session *session)
  1512. {
  1513. struct Plugin *plugin = cls;
  1514. struct PendingMessage *pm;
  1515. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1516. "Disconnecting session of peer `%s' address `%s'\n",
  1517. GNUNET_i2s (&session->target),
  1518. tcp_plugin_address_to_string (session->plugin,
  1519. session->address->address,
  1520. session->address->address_length));
  1521. if (NULL != session->timeout_task)
  1522. {
  1523. GNUNET_SCHEDULER_cancel (session->timeout_task);
  1524. session->timeout_task = NULL;
  1525. session->timeout = GNUNET_TIME_UNIT_ZERO_ABS;
  1526. }
  1527. if (GNUNET_YES ==
  1528. GNUNET_CONTAINER_multipeermap_remove (plugin->sessionmap,
  1529. &session->target,
  1530. session))
  1531. {
  1532. GNUNET_STATISTICS_update (session->plugin->env->stats,
  1533. gettext_noop ("# TCP sessions active"),
  1534. -1,
  1535. GNUNET_NO);
  1536. }
  1537. else
  1538. {
  1539. GNUNET_assert (GNUNET_YES ==
  1540. GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns,
  1541. &session->target,
  1542. session));
  1543. }
  1544. if (NULL != session->client)
  1545. GNUNET_SERVER_client_set_user_context (session->client,
  1546. NULL);
  1547. /* clean up state */
  1548. if (NULL != session->transmit_handle)
  1549. {
  1550. GNUNET_SERVER_notify_transmit_ready_cancel (session->transmit_handle);
  1551. session->transmit_handle = NULL;
  1552. }
  1553. session->plugin->env->session_end (session->plugin->env->cls,
  1554. session->address,
  1555. session);
  1556. if (NULL != session->nat_connection_timeout)
  1557. {
  1558. GNUNET_SCHEDULER_cancel (session->nat_connection_timeout);
  1559. session->nat_connection_timeout = NULL;
  1560. }
  1561. while (NULL != (pm = session->pending_messages_head))
  1562. {
  1563. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1564. (NULL != pm->transmit_cont)
  1565. ? "Could not deliver message to `%s' at %s.\n"
  1566. : "Could not deliver message to `%s' at %s, notifying.\n",
  1567. GNUNET_i2s (&session->target),
  1568. tcp_plugin_address_to_string (session->plugin,
  1569. session->address->address,
  1570. session->address->address_length));
  1571. GNUNET_STATISTICS_update (session->plugin->env->stats,
  1572. gettext_noop ("# bytes currently in TCP buffers"),
  1573. -(int64_t) pm->message_size, GNUNET_NO);
  1574. GNUNET_STATISTICS_update (session->plugin->env->stats,
  1575. gettext_noop ("# bytes discarded by TCP (disconnect)"),
  1576. pm->message_size,
  1577. GNUNET_NO);
  1578. GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
  1579. session->pending_messages_tail,
  1580. pm);
  1581. GNUNET_assert (0 < session->msgs_in_queue);
  1582. session->msgs_in_queue--;
  1583. GNUNET_assert (pm->message_size <= session->bytes_in_queue);
  1584. session->bytes_in_queue -= pm->message_size;
  1585. if (NULL != pm->transmit_cont)
  1586. pm->transmit_cont (pm->transmit_cont_cls,
  1587. &session->target,
  1588. GNUNET_SYSERR,
  1589. pm->message_size,
  1590. 0);
  1591. GNUNET_free (pm);
  1592. }
  1593. GNUNET_assert (0 == session->msgs_in_queue);
  1594. GNUNET_assert (0 == session->bytes_in_queue);
  1595. notify_session_monitor (session->plugin,
  1596. session,
  1597. GNUNET_TRANSPORT_SS_DONE);
  1598. if (NULL != session->receive_delay_task)
  1599. {
  1600. GNUNET_SCHEDULER_cancel (session->receive_delay_task);
  1601. session->receive_delay_task = NULL;
  1602. }
  1603. if (NULL != session->client)
  1604. {
  1605. GNUNET_SERVER_client_disconnect (session->client);
  1606. session->client = NULL;
  1607. }
  1608. GNUNET_HELLO_address_free (session->address);
  1609. GNUNET_assert (NULL == session->transmit_handle);
  1610. GNUNET_free (session);
  1611. return GNUNET_OK;
  1612. }
  1613. /**
  1614. * Function that is called to get the keepalive factor.
  1615. * #GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to
  1616. * calculate the interval between keepalive packets.
  1617. *
  1618. * @param cls closure with the `struct Plugin`
  1619. * @return keepalive factor
  1620. */
  1621. static unsigned int
  1622. tcp_plugin_query_keepalive_factor (void *cls)
  1623. {
  1624. return 3;
  1625. }
  1626. /**
  1627. * Session was idle for too long, so disconnect it
  1628. *
  1629. * @param cls the `struct GNUNET_ATS_Session` of the idle session
  1630. */
  1631. static void
  1632. session_timeout (void *cls)
  1633. {
  1634. struct GNUNET_ATS_Session *s = cls;
  1635. struct GNUNET_TIME_Relative left;
  1636. s->timeout_task = NULL;
  1637. left = GNUNET_TIME_absolute_get_remaining (s->timeout);
  1638. if (0 != left.rel_value_us)
  1639. {
  1640. /* not actually our turn yet, but let's at least update
  1641. the monitor, it may think we're about to die ... */
  1642. notify_session_monitor (s->plugin,
  1643. s,
  1644. GNUNET_TRANSPORT_SS_UPDATE);
  1645. s->timeout_task = GNUNET_SCHEDULER_add_delayed (left,
  1646. &session_timeout,
  1647. s);
  1648. return;
  1649. }
  1650. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1651. "Session %p was idle for %s, disconnecting\n",
  1652. s,
  1653. GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
  1654. GNUNET_YES));
  1655. /* call session destroy function */
  1656. tcp_plugin_disconnect_session (s->plugin,
  1657. s);
  1658. }
  1659. /**
  1660. * Increment session timeout due to activity.
  1661. *
  1662. * @param s session to increment timeout for
  1663. */
  1664. static void
  1665. reschedule_session_timeout (struct GNUNET_ATS_Session *s)
  1666. {
  1667. GNUNET_assert (NULL != s->timeout_task);
  1668. s->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
  1669. }
  1670. /**
  1671. * Create a new session. Also queues a welcome message.
  1672. *
  1673. * @param plugin the plugin
  1674. * @param address the address to create the session for
  1675. * @param scope network scope the address is from
  1676. * @param client client to use, reference counter must have already been increased
  1677. * @param is_nat this a NAT session, we should wait for a client to
  1678. * connect to us from an address, then assign that to
  1679. * the session
  1680. * @return new session object
  1681. */
  1682. static struct GNUNET_ATS_Session *
  1683. create_session (struct Plugin *plugin,
  1684. const struct GNUNET_HELLO_Address *address,
  1685. enum GNUNET_NetworkType scope,
  1686. struct GNUNET_SERVER_Client *client,
  1687. int is_nat)
  1688. {
  1689. struct GNUNET_ATS_Session *session;
  1690. struct PendingMessage *pm;
  1691. if (GNUNET_YES != is_nat)
  1692. GNUNET_assert (NULL != client);
  1693. else
  1694. GNUNET_assert (NULL == client);
  1695. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1696. "Creating new session for peer `%s' at address %s\n",
  1697. GNUNET_i2s (&address->peer),
  1698. tcp_plugin_address_to_string (plugin,
  1699. address->address,
  1700. address->address_length));
  1701. session = GNUNET_new (struct GNUNET_ATS_Session);
  1702. session->last_activity = GNUNET_TIME_absolute_get ();
  1703. session->plugin = plugin;
  1704. session->is_nat = is_nat;
  1705. if (NULL != client)
  1706. {
  1707. session->client = client;
  1708. GNUNET_SERVER_client_set_user_context (client,
  1709. session);
  1710. }
  1711. session->address = GNUNET_HELLO_address_copy (address);
  1712. session->target = address->peer;
  1713. session->expecting_welcome = GNUNET_YES;
  1714. session->scope = scope;
  1715. pm = GNUNET_malloc (sizeof (struct PendingMessage) +
  1716. sizeof (struct WelcomeMessage));
  1717. pm->msg = (const char *) &pm[1];
  1718. pm->message_size = sizeof(struct WelcomeMessage);
  1719. GNUNET_memcpy (&pm[1],
  1720. &plugin->my_welcome,
  1721. sizeof(struct WelcomeMessage));
  1722. pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
  1723. GNUNET_STATISTICS_update (plugin->env->stats,
  1724. gettext_noop ("# bytes currently in TCP buffers"),
  1725. pm->message_size,
  1726. GNUNET_NO);
  1727. GNUNET_CONTAINER_DLL_insert (session->pending_messages_head,
  1728. session->pending_messages_tail,
  1729. pm);
  1730. session->msgs_in_queue++;
  1731. session->bytes_in_queue += pm->message_size;
  1732. session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
  1733. session->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
  1734. &session_timeout,
  1735. session);
  1736. notify_session_monitor (session->plugin,
  1737. session,
  1738. GNUNET_TRANSPORT_SS_INIT);
  1739. if (GNUNET_YES != is_nat)
  1740. {
  1741. GNUNET_STATISTICS_update (plugin->env->stats,
  1742. gettext_noop ("# TCP sessions active"),
  1743. 1,
  1744. GNUNET_NO);
  1745. notify_session_monitor (session->plugin,
  1746. session,
  1747. GNUNET_TRANSPORT_SS_UP);
  1748. }
  1749. else
  1750. {
  1751. notify_session_monitor (session->plugin,
  1752. session,
  1753. GNUNET_TRANSPORT_SS_HANDSHAKE);
  1754. }
  1755. return session;
  1756. }
  1757. /**
  1758. * If we have pending messages, ask the server to
  1759. * transmit them (schedule the respective tasks, etc.)
  1760. *
  1761. * @param session for which session should we do this
  1762. */
  1763. static void
  1764. process_pending_messages (struct GNUNET_ATS_Session *session);
  1765. /**
  1766. * Function called to notify a client about the socket
  1767. * being ready to queue more data. "buf" will be
  1768. * NULL and "size" zero if the socket was closed for
  1769. * writing in the meantime.
  1770. *
  1771. * @param cls closure
  1772. * @param size number of bytes available in @a buf
  1773. * @param buf where the callee should write the message
  1774. * @return number of bytes written to @a buf
  1775. */
  1776. static size_t
  1777. do_transmit (void *cls,
  1778. size_t size,
  1779. void *buf)
  1780. {
  1781. struct GNUNET_ATS_Session *session = cls;
  1782. struct GNUNET_PeerIdentity pid;
  1783. struct Plugin *plugin;
  1784. struct PendingMessage *pos;
  1785. struct PendingMessage *hd;
  1786. struct PendingMessage *tl;
  1787. struct GNUNET_TIME_Absolute now;
  1788. char *cbuf;
  1789. size_t ret;
  1790. session->transmit_handle = NULL;
  1791. plugin = session->plugin;
  1792. if (NULL == buf)
  1793. {
  1794. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1795. "Timeout trying to transmit to peer `%s', discarding message queue.\n",
  1796. GNUNET_i2s (&session->target));
  1797. /* timeout; cancel all messages that have already expired */
  1798. hd = NULL;
  1799. tl = NULL;
  1800. ret = 0;
  1801. now = GNUNET_TIME_absolute_get ();
  1802. while ( (NULL != (pos = session->pending_messages_head)) &&
  1803. (pos->timeout.abs_value_us <= now.abs_value_us) )
  1804. {
  1805. GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
  1806. session->pending_messages_tail,
  1807. pos);
  1808. GNUNET_assert (0 < session->msgs_in_queue);
  1809. session->msgs_in_queue--;
  1810. GNUNET_assert (pos->message_size <= session->bytes_in_queue);
  1811. session->bytes_in_queue -= pos->message_size;
  1812. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1813. "Failed to transmit %u byte message to `%s'.\n",
  1814. pos->message_size,
  1815. GNUNET_i2s (&session->target));
  1816. ret += pos->message_size;
  1817. GNUNET_CONTAINER_DLL_insert_after (hd,
  1818. tl,
  1819. tl,
  1820. pos);
  1821. }
  1822. /* do this call before callbacks (so that if callbacks destroy
  1823. * session, they have a chance to cancel actions done by this
  1824. * call) */
  1825. process_pending_messages (session);
  1826. pid = session->target;
  1827. /* no do callbacks and do not use session again since
  1828. * the callbacks may abort the session */
  1829. while (NULL != (pos = hd))
  1830. {
  1831. GNUNET_CONTAINER_DLL_remove (hd,
  1832. tl,
  1833. pos);
  1834. if (NULL != pos->transmit_cont)
  1835. pos->transmit_cont (pos->transmit_cont_cls,
  1836. &pid,
  1837. GNUNET_SYSERR,
  1838. pos->message_size,
  1839. 0);
  1840. GNUNET_free (pos);
  1841. }
  1842. GNUNET_STATISTICS_update (plugin->env->stats,
  1843. gettext_noop ("# bytes currently in TCP buffers"), -(int64_t) ret,
  1844. GNUNET_NO);
  1845. GNUNET_STATISTICS_update (plugin->env->stats,
  1846. gettext_noop ("# bytes discarded by TCP (timeout)"),
  1847. ret,
  1848. GNUNET_NO);
  1849. if (0 < ret)
  1850. notify_session_monitor (session->plugin,
  1851. session,
  1852. GNUNET_TRANSPORT_SS_UPDATE);
  1853. return 0;
  1854. }
  1855. /* copy all pending messages that would fit */
  1856. ret = 0;
  1857. cbuf = buf;
  1858. hd = NULL;
  1859. tl = NULL;
  1860. while (NULL != (pos = session->pending_messages_head))
  1861. {
  1862. if (ret + pos->message_size > size)
  1863. break;
  1864. GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
  1865. session->pending_messages_tail,
  1866. pos);
  1867. GNUNET_assert (0 < session->msgs_in_queue);
  1868. session->msgs_in_queue--;
  1869. GNUNET_assert (pos->message_size <= session->bytes_in_queue);
  1870. session->bytes_in_queue -= pos->message_size;
  1871. GNUNET_assert(size >= pos->message_size);
  1872. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1873. "Transmitting message of type %u size %u to peer %s at %s\n",
  1874. ntohs (((struct GNUNET_MessageHeader *) pos->msg)->type),
  1875. pos->message_size,
  1876. GNUNET_i2s (&session->target),
  1877. tcp_plugin_address_to_string (session->plugin,
  1878. session->address->address,
  1879. session->address->address_length));
  1880. /* FIXME: this GNUNET_memcpy can be up to 7% of our total runtime */
  1881. GNUNET_memcpy (cbuf,
  1882. pos->msg,
  1883. pos->message_size);
  1884. cbuf += pos->message_size;
  1885. ret += pos->message_size;
  1886. size -= pos->message_size;
  1887. GNUNET_CONTAINER_DLL_insert_tail (hd,
  1888. tl,
  1889. pos);
  1890. }
  1891. notify_session_monitor (session->plugin,
  1892. session,
  1893. GNUNET_TRANSPORT_SS_UPDATE);
  1894. /* schedule 'continuation' before callbacks so that callbacks that
  1895. * cancel everything don't cause us to use a session that no longer
  1896. * exists... */
  1897. process_pending_messages (session);
  1898. session->last_activity = GNUNET_TIME_absolute_get ();
  1899. pid = session->target;
  1900. /* we'll now call callbacks that may cancel the session; hence
  1901. * we should not use 'session' after this point */
  1902. while (NULL != (pos = hd))
  1903. {
  1904. GNUNET_CONTAINER_DLL_remove (hd, tl, pos);
  1905. if (NULL != pos->transmit_cont)
  1906. pos->transmit_cont (pos->transmit_cont_cls,
  1907. &pid,
  1908. GNUNET_OK,
  1909. pos->message_size,
  1910. pos->message_size); /* FIXME: include TCP overhead */
  1911. GNUNET_free (pos);
  1912. }
  1913. GNUNET_assert (NULL == hd);
  1914. GNUNET_assert (NULL == tl);
  1915. GNUNET_STATISTICS_update (plugin->env->stats,
  1916. gettext_noop ("# bytes currently in TCP buffers"),
  1917. - (int64_t) ret,
  1918. GNUNET_NO);
  1919. GNUNET_STATISTICS_update (plugin->env->stats,
  1920. gettext_noop ("# bytes transmitted via TCP"),
  1921. ret,
  1922. GNUNET_NO);
  1923. return ret;
  1924. }
  1925. /**
  1926. * If we have pending messages, ask the server to
  1927. * transmit them (schedule the respective tasks, etc.)
  1928. *
  1929. * @param session for which session should we do this
  1930. */
  1931. static void
  1932. process_pending_messages (struct GNUNET_ATS_Session *session)
  1933. {
  1934. struct PendingMessage *pm;
  1935. GNUNET_assert (NULL != session->client);
  1936. if (NULL != session->transmit_handle)
  1937. return;
  1938. if (NULL == (pm = session->pending_messages_head))
  1939. return;
  1940. session->transmit_handle
  1941. = GNUNET_SERVER_notify_transmit_ready (session->client,
  1942. pm->message_size,
  1943. GNUNET_TIME_absolute_get_remaining (pm->timeout),
  1944. &do_transmit,
  1945. session);
  1946. }
  1947. /**
  1948. * Function that can be used by the transport service to transmit
  1949. * a message using the plugin. Note that in the case of a
  1950. * peer disconnecting, the continuation MUST be called
  1951. * prior to the disconnect notification itself. This function
  1952. * will be called with this peer's HELLO message to initiate
  1953. * a fresh connection to another peer.
  1954. *
  1955. * @param cls closure
  1956. * @param session which session must be used
  1957. * @param msgbuf the message to transmit
  1958. * @param msgbuf_size number of bytes in @a msgbuf
  1959. * @param priority how important is the message (most plugins will
  1960. * ignore message priority and just FIFO)
  1961. * @param to how long to wait at most for the transmission (does not
  1962. * require plugins to discard the message after the timeout,
  1963. * just advisory for the desired delay; most plugins will ignore
  1964. * this as well)
  1965. * @param cont continuation to call once the message has
  1966. * been transmitted (or if the transport is ready
  1967. * for the next transmission call; or if the
  1968. * peer disconnected...); can be NULL
  1969. * @param cont_cls closure for @a cont
  1970. * @return number of bytes used (on the physical network, with overheads);
  1971. * -1 on hard errors (i.e. address invalid); 0 is a legal value
  1972. * and does NOT mean that the message was not transmitted (DV)
  1973. */
  1974. static ssize_t
  1975. tcp_plugin_send (void *cls,
  1976. struct GNUNET_ATS_Session *session,
  1977. const char *msgbuf,
  1978. size_t msgbuf_size,
  1979. unsigned int priority,
  1980. struct GNUNET_TIME_Relative to,
  1981. GNUNET_TRANSPORT_TransmitContinuation cont,
  1982. void *cont_cls)
  1983. {
  1984. struct Plugin * plugin = cls;
  1985. struct PendingMessage *pm;
  1986. /* create new message entry */
  1987. pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size);
  1988. pm->msg = (const char *) &pm[1];
  1989. GNUNET_memcpy (&pm[1], msgbuf, msgbuf_size);
  1990. pm->message_size = msgbuf_size;
  1991. pm->timeout = GNUNET_TIME_relative_to_absolute (to);
  1992. pm->transmit_cont = cont;
  1993. pm->transmit_cont_cls = cont_cls;
  1994. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1995. "Asked to transmit %u bytes to `%s', added message to list.\n",
  1996. msgbuf_size,
  1997. GNUNET_i2s (&session->target));
  1998. if (GNUNET_YES ==
  1999. GNUNET_CONTAINER_multipeermap_contains_value (plugin->sessionmap,
  2000. &session->target,
  2001. session))
  2002. {
  2003. GNUNET_assert (NULL != session->client);
  2004. GNUNET_SERVER_client_set_timeout (session->client,
  2005. GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
  2006. GNUNET_STATISTICS_update (plugin->env->stats,
  2007. gettext_noop ("# bytes currently in TCP buffers"),
  2008. msgbuf_size,
  2009. GNUNET_NO);
  2010. /* append pm to pending_messages list */
  2011. GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head,
  2012. session->pending_messages_tail,
  2013. pm);
  2014. notify_session_monitor (session->plugin,
  2015. session,
  2016. GNUNET_TRANSPORT_SS_UPDATE);
  2017. session->msgs_in_queue++;
  2018. session->bytes_in_queue += pm->message_size;
  2019. process_pending_messages (session);
  2020. return msgbuf_size;
  2021. }
  2022. if (GNUNET_YES ==
  2023. GNUNET_CONTAINER_multipeermap_contains_value (plugin->nat_wait_conns,
  2024. &session->target,
  2025. session))
  2026. {
  2027. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2028. "This NAT WAIT session for peer `%s' is not yet ready!\n",
  2029. GNUNET_i2s (&session->target));
  2030. GNUNET_STATISTICS_update (plugin->env->stats,
  2031. gettext_noop ("# bytes currently in TCP buffers"), msgbuf_size,
  2032. GNUNET_NO);
  2033. /* append pm to pending_messages list */
  2034. GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head,
  2035. session->pending_messages_tail,
  2036. pm);
  2037. session->msgs_in_queue++;
  2038. session->bytes_in_queue += pm->message_size;
  2039. notify_session_monitor (session->plugin,
  2040. session,
  2041. GNUNET_TRANSPORT_SS_HANDSHAKE);
  2042. return msgbuf_size;
  2043. }
  2044. LOG (GNUNET_ERROR_TYPE_ERROR,
  2045. "Invalid session %p\n",
  2046. session);
  2047. if (NULL != cont)
  2048. cont (cont_cls,
  2049. &session->target,
  2050. GNUNET_SYSERR,
  2051. pm->message_size,
  2052. 0);
  2053. GNUNET_break (0);
  2054. GNUNET_free (pm);
  2055. return GNUNET_SYSERR; /* session does not exist here */
  2056. }
  2057. /**
  2058. * Closure for #session_lookup_it().
  2059. */
  2060. struct GNUNET_ATS_SessionItCtx
  2061. {
  2062. /**
  2063. * Address we are looking for.
  2064. */
  2065. const struct GNUNET_HELLO_Address *address;
  2066. /**
  2067. * Where to store the session (if we found it).
  2068. */
  2069. struct GNUNET_ATS_Session *result;
  2070. };
  2071. /**
  2072. * Look for a session by address.
  2073. *
  2074. * @param cls the `struct GNUNET_ATS_SessionItCtx`
  2075. * @param key unused
  2076. * @param value a `struct GNUNET_ATS_Session`
  2077. * @return #GNUNET_YES to continue looking, #GNUNET_NO if we found the session
  2078. */
  2079. static int
  2080. session_lookup_it (void *cls,
  2081. const struct GNUNET_PeerIdentity *key,
  2082. void *value)
  2083. {
  2084. struct GNUNET_ATS_SessionItCtx *si_ctx = cls;
  2085. struct GNUNET_ATS_Session *session = value;
  2086. if (0 !=
  2087. GNUNET_HELLO_address_cmp (si_ctx->address,
  2088. session->address))
  2089. return GNUNET_YES;
  2090. si_ctx->result = session;
  2091. return GNUNET_NO;
  2092. }
  2093. /**
  2094. * Task cleaning up a NAT connection attempt after timeout
  2095. *
  2096. * @param cls the `struct GNUNET_ATS_Session`
  2097. */
  2098. static void
  2099. nat_connect_timeout (void *cls)
  2100. {
  2101. struct GNUNET_ATS_Session *session = cls;
  2102. session->nat_connection_timeout = NULL;
  2103. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2104. "NAT WAIT connection to `%4s' at `%s' could not be established, removing session\n",
  2105. GNUNET_i2s (&session->target),
  2106. tcp_plugin_address_to_string (session->plugin,
  2107. session->address->address,
  2108. session->address->address_length));
  2109. tcp_plugin_disconnect_session (session->plugin,
  2110. session);
  2111. }
  2112. /**
  2113. * Function that will be called whenever the transport service wants to
  2114. * notify the plugin that a session is still active and in use and
  2115. * therefore the session timeout for this session has to be updated
  2116. *
  2117. * @param cls closure
  2118. * @param peer which peer was the session for
  2119. * @param session which session is being updated
  2120. */
  2121. static void
  2122. tcp_plugin_update_session_timeout (void *cls,
  2123. const struct GNUNET_PeerIdentity *peer,
  2124. struct GNUNET_ATS_Session *session)
  2125. {
  2126. reschedule_session_timeout (session);
  2127. }
  2128. /**
  2129. * Task to signal the server that we can continue
  2130. * receiving from the TCP client now.
  2131. *
  2132. * @param cls the `struct GNUNET_ATS_Session *`
  2133. */
  2134. static void
  2135. delayed_done (void *cls)
  2136. {
  2137. struct GNUNET_ATS_Session *session = cls;
  2138. session->receive_delay_task = NULL;
  2139. reschedule_session_timeout (session);
  2140. GNUNET_SERVER_receive_done (session->client,
  2141. GNUNET_OK);
  2142. }
  2143. /**
  2144. * Function that will be called whenever the transport service wants to
  2145. * notify the plugin that the inbound quota changed and that the plugin
  2146. * should update it's delay for the next receive value
  2147. *
  2148. * @param cls closure
  2149. * @param peer which peer was the session for
  2150. * @param session which session is being updated
  2151. * @param delay new delay to use for receiving
  2152. */
  2153. static void
  2154. tcp_plugin_update_inbound_delay (void *cls,
  2155. const struct GNUNET_PeerIdentity *peer,
  2156. struct GNUNET_ATS_Session *session,
  2157. struct GNUNET_TIME_Relative delay)
  2158. {
  2159. if (NULL == session->receive_delay_task)
  2160. return;
  2161. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2162. "New inbound delay %s\n",
  2163. GNUNET_STRINGS_relative_time_to_string (delay,
  2164. GNUNET_NO));
  2165. session->receive_delay = GNUNET_TIME_relative_to_absolute (delay);
  2166. GNUNET_SCHEDULER_cancel (session->receive_delay_task);
  2167. session->receive_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
  2168. &delayed_done,
  2169. session);
  2170. }
  2171. /**
  2172. * Create a new session to transmit data to the target
  2173. * This session will used to send data to this peer and the plugin will
  2174. * notify us by calling the env->session_end function
  2175. *
  2176. * @param cls closure
  2177. * @param address the address to use
  2178. * @return the session if the address is valid, NULL otherwise
  2179. */
  2180. static struct GNUNET_ATS_Session *
  2181. tcp_plugin_get_session (void *cls,
  2182. const struct GNUNET_HELLO_Address *address)
  2183. {
  2184. struct Plugin *plugin = cls;
  2185. struct GNUNET_ATS_Session *session = NULL;
  2186. int af;
  2187. const void *sb;
  2188. size_t sbs;
  2189. struct GNUNET_CONNECTION_Handle *sa;
  2190. struct sockaddr_in a4;
  2191. struct sockaddr_in6 a6;
  2192. const struct IPv4TcpAddress *t4;
  2193. const struct IPv6TcpAddress *t6;
  2194. unsigned int options;
  2195. enum GNUNET_NetworkType net_type;
  2196. unsigned int is_natd = GNUNET_NO;
  2197. size_t addrlen;
  2198. #ifdef TCP_STEALTH
  2199. struct GNUNET_NETWORK_Handle *s;
  2200. #endif
  2201. addrlen = address->address_length;
  2202. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2203. "Trying to get session for `%s' address of peer `%s'\n",
  2204. tcp_plugin_address_to_string (plugin,
  2205. address->address,
  2206. address->address_length),
  2207. GNUNET_i2s (&address->peer));
  2208. if (GNUNET_HELLO_address_check_option (address,
  2209. GNUNET_HELLO_ADDRESS_INFO_INBOUND))
  2210. {
  2211. GNUNET_break (0);
  2212. return NULL;
  2213. }
  2214. /* look for existing session */
  2215. if (GNUNET_YES ==
  2216. GNUNET_CONTAINER_multipeermap_contains (plugin->sessionmap,
  2217. &address->peer))
  2218. {
  2219. struct GNUNET_ATS_SessionItCtx si_ctx;
  2220. si_ctx.address = address;
  2221. si_ctx.result = NULL;
  2222. GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap,
  2223. &address->peer,
  2224. &session_lookup_it,
  2225. &si_ctx);
  2226. if (NULL != si_ctx.result)
  2227. {
  2228. session = si_ctx.result;
  2229. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2230. "Found existing session for `%s' address `%s'\n",
  2231. GNUNET_i2s (&address->peer),
  2232. tcp_plugin_address_to_string (plugin,
  2233. address->address,
  2234. address->address_length));
  2235. return session;
  2236. }
  2237. /* This is a bit of a hack, limiting TCP to never allow more than
  2238. one TCP connection to any given peer at the same time.
  2239. Without this, peers sometimes disagree about which of the TCP
  2240. connections they should use, causing one side to believe that
  2241. they transmit successfully, while the other receives nothing. */
  2242. return NULL; /* Refuse to have more than one TCP connection per
  2243. peer pair at the same time. */
  2244. }
  2245. if (addrlen == sizeof(struct IPv6TcpAddress))
  2246. {
  2247. GNUNET_assert (NULL != address->address); /* make static analysis happy */
  2248. t6 = address->address;
  2249. options = t6->options;
  2250. af = AF_INET6;
  2251. memset (&a6, 0, sizeof(a6));
  2252. #if HAVE_SOCKADDR_IN_SIN_LEN
  2253. a6.sin6_len = sizeof (a6);
  2254. #endif
  2255. a6.sin6_family = AF_INET6;
  2256. a6.sin6_port = t6->t6_port;
  2257. if (t6->t6_port == 0)
  2258. is_natd = GNUNET_YES;
  2259. GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
  2260. sb = &a6;
  2261. sbs = sizeof(a6);
  2262. }
  2263. else if (addrlen == sizeof(struct IPv4TcpAddress))
  2264. {
  2265. GNUNET_assert(NULL != address->address); /* make static analysis happy */
  2266. t4 = address->address;
  2267. options = t4->options;
  2268. af = AF_INET;
  2269. memset (&a4, 0, sizeof(a4));
  2270. #if HAVE_SOCKADDR_IN_SIN_LEN
  2271. a4.sin_len = sizeof (a4);
  2272. #endif
  2273. a4.sin_family = AF_INET;
  2274. a4.sin_port = t4->t4_port;
  2275. if (t4->t4_port == 0)
  2276. is_natd = GNUNET_YES;
  2277. a4.sin_addr.s_addr = t4->ipv4_addr;
  2278. sb = &a4;
  2279. sbs = sizeof(a4);
  2280. }
  2281. else
  2282. {
  2283. GNUNET_STATISTICS_update (plugin->env->stats,
  2284. gettext_noop ("# requests to create session with invalid address"),
  2285. 1,
  2286. GNUNET_NO);
  2287. return NULL;
  2288. }
  2289. net_type = plugin->env->get_address_type (plugin->env->cls,
  2290. sb,
  2291. sbs);
  2292. GNUNET_break (net_type != GNUNET_NT_UNSPECIFIED);
  2293. if ( (is_natd == GNUNET_YES) &&
  2294. (addrlen == sizeof(struct IPv6TcpAddress)) )
  2295. {
  2296. /* NAT client only works with IPv4 addresses */
  2297. return NULL;
  2298. }
  2299. if (plugin->cur_connections >= plugin->max_connections)
  2300. {
  2301. /* saturated */
  2302. return NULL;
  2303. }
  2304. if ( (is_natd == GNUNET_YES) &&
  2305. (GNUNET_YES ==
  2306. GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns,
  2307. &address->peer)))
  2308. {
  2309. /* Only do one NAT punch attempt per peer identity */
  2310. return NULL;
  2311. }
  2312. if ( (is_natd == GNUNET_YES) &&
  2313. (NULL != plugin->nat) &&
  2314. (GNUNET_NO ==
  2315. GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns,
  2316. &address->peer)))
  2317. {
  2318. struct sockaddr_in local_sa;
  2319. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2320. "Found valid IPv4 NAT address (creating session)!\n");
  2321. session = create_session (plugin,
  2322. address,
  2323. net_type,
  2324. NULL,
  2325. GNUNET_YES);
  2326. session->nat_connection_timeout = GNUNET_SCHEDULER_add_delayed (NAT_TIMEOUT,
  2327. &nat_connect_timeout,
  2328. session);
  2329. GNUNET_assert (GNUNET_OK ==
  2330. GNUNET_CONTAINER_multipeermap_put (plugin->nat_wait_conns,
  2331. &session->target,
  2332. session,
  2333. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  2334. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2335. "Created NAT WAIT connection to `%s' at `%s'\n",
  2336. GNUNET_i2s (&session->target),
  2337. GNUNET_a2s (sb, sbs));
  2338. memset (&local_sa,
  2339. 0,
  2340. sizeof (local_sa));
  2341. local_sa.sin_family = AF_INET;
  2342. local_sa.sin_port = htons (plugin->open_port);
  2343. /* We leave sin_address at 0, let the kernel figure it out,
  2344. even if our bind() is more specific. (May want to reconsider
  2345. later.) */
  2346. if (GNUNET_OK ==
  2347. GNUNET_NAT_request_reversal (plugin->nat,
  2348. &local_sa,
  2349. &a4))
  2350. return session;
  2351. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2352. "Running NAT client for `%s' at `%s' failed\n",
  2353. GNUNET_i2s (&session->target),
  2354. GNUNET_a2s (sb, sbs));
  2355. tcp_plugin_disconnect_session (plugin,
  2356. session);
  2357. return NULL;
  2358. }
  2359. /* create new outbound session */
  2360. if (0 != (options & TCP_OPTIONS_TCP_STEALTH))
  2361. {
  2362. #ifdef TCP_STEALTH
  2363. s = GNUNET_NETWORK_socket_create (af, SOCK_STREAM, 0);
  2364. if (NULL == s)
  2365. {
  2366. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
  2367. "socket");
  2368. sa = NULL;
  2369. }
  2370. else
  2371. {
  2372. if ( (GNUNET_OK !=
  2373. GNUNET_NETWORK_socket_setsockopt (s,
  2374. IPPROTO_TCP,
  2375. TCP_STEALTH,
  2376. &session->target,
  2377. sizeof (struct GNUNET_PeerIdentity))) ||
  2378. (GNUNET_OK !=
  2379. GNUNET_NETWORK_socket_setsockopt (s,
  2380. IPPROTO_TCP,
  2381. TCP_STEALTH_INTEGRITY,
  2382. &plugin->my_welcome,
  2383. sizeof (struct WelcomeMessage))) )
  2384. {
  2385. /* TCP STEALTH not supported by kernel */
  2386. GNUNET_break (GNUNET_OK ==
  2387. GNUNET_NETWORK_socket_close (s));
  2388. sa = NULL;
  2389. }
  2390. else
  2391. {
  2392. sa = GNUNET_CONNECTION_connect_socket (s, sb, sbs);
  2393. }
  2394. }
  2395. #else
  2396. sa = NULL;
  2397. #endif
  2398. }
  2399. else
  2400. {
  2401. sa = GNUNET_CONNECTION_create_from_sockaddr (af, sb, sbs);
  2402. }
  2403. if (NULL == sa)
  2404. {
  2405. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2406. "Failed to create connection to `%s' at `%s'\n",
  2407. GNUNET_i2s (&address->peer),
  2408. GNUNET_a2s (sb, sbs));
  2409. return NULL;
  2410. }
  2411. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2412. "Asked to transmit to `%s', creating fresh session using address `%s'.\n",
  2413. GNUNET_i2s (&address->peer),
  2414. GNUNET_a2s (sb, sbs));
  2415. session = create_session (plugin,
  2416. address,
  2417. net_type,
  2418. GNUNET_SERVER_connect_socket (plugin->server,
  2419. sa),
  2420. GNUNET_NO);
  2421. (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap,
  2422. &session->target,
  2423. session,
  2424. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  2425. /* Send TCP Welcome */
  2426. process_pending_messages (session);
  2427. return session;
  2428. }
  2429. /**
  2430. * We have been asked to destroy all connections to a particular peer.
  2431. * This function is called on each applicable session and must tear it
  2432. * down.
  2433. *
  2434. * @param cls the `struct Plugin *`
  2435. * @param key the peer which the session belongs to (unused)
  2436. * @param value the `struct GNUNET_ATS_Session`
  2437. * @return #GNUNET_YES (continue to iterate)
  2438. */
  2439. static int
  2440. session_disconnect_it (void *cls,
  2441. const struct GNUNET_PeerIdentity *key,
  2442. void *value)
  2443. {
  2444. struct Plugin *plugin = cls;
  2445. struct GNUNET_ATS_Session *session = value;
  2446. GNUNET_STATISTICS_update (session->plugin->env->stats,
  2447. gettext_noop ("# transport-service disconnect requests for TCP"),
  2448. 1,
  2449. GNUNET_NO);
  2450. tcp_plugin_disconnect_session (plugin,
  2451. session);
  2452. return GNUNET_YES;
  2453. }
  2454. /**
  2455. * Function that can be called to force a disconnect from the
  2456. * specified neighbour. This should also cancel all previously
  2457. * scheduled transmissions. Obviously the transmission may have been
  2458. * partially completed already, which is OK. The plugin is supposed
  2459. * to close the connection (if applicable) and no longer call the
  2460. * transmit continuation(s).
  2461. *
  2462. * Finally, plugin MUST NOT call the services's receive function to
  2463. * notify the service that the connection to the specified target was
  2464. * closed after a getting this call.
  2465. *
  2466. * @param cls closure
  2467. * @param target peer for which the last transmission is
  2468. * to be cancelled
  2469. */
  2470. static void
  2471. tcp_plugin_disconnect (void *cls,
  2472. const struct GNUNET_PeerIdentity *target)
  2473. {
  2474. struct Plugin *plugin = cls;
  2475. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2476. "Disconnecting peer `%s'\n",
  2477. GNUNET_i2s (target));
  2478. GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap,
  2479. target,
  2480. &session_disconnect_it,
  2481. plugin);
  2482. GNUNET_CONTAINER_multipeermap_get_multiple (plugin->nat_wait_conns,
  2483. target,
  2484. &session_disconnect_it,
  2485. plugin);
  2486. }
  2487. /**
  2488. * We are processing an address pretty printing request and finished
  2489. * the IP resolution (if applicable). Append our port and forward the
  2490. * result. If called with @a hostname NULL, we are done and should
  2491. * clean up the pretty printer (otherwise, there might be multiple
  2492. * hostnames for the IP address and we might receive more).
  2493. *
  2494. * @param cls the `struct PrettyPrinterContext *`
  2495. * @param hostname hostname part of the address
  2496. */
  2497. static void
  2498. append_port (void *cls,
  2499. const char *hostname)
  2500. {
  2501. struct PrettyPrinterContext *ppc = cls;
  2502. struct Plugin *plugin = ppc->plugin;
  2503. char *ret;
  2504. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2505. "append_port called with hostname `%s'\n",
  2506. hostname);
  2507. if (NULL == hostname)
  2508. {
  2509. /* Final call, done */
  2510. ppc->resolver_handle = NULL;
  2511. GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
  2512. plugin->ppc_dll_tail,
  2513. ppc);
  2514. ppc->asc (ppc->asc_cls,
  2515. NULL,
  2516. GNUNET_OK);
  2517. GNUNET_free (ppc);
  2518. return;
  2519. }
  2520. if (GNUNET_YES == ppc->ipv6)
  2521. GNUNET_asprintf (&ret,
  2522. "%s.%u.[%s]:%d",
  2523. PLUGIN_NAME,
  2524. ppc->options,
  2525. hostname,
  2526. ppc->port);
  2527. else
  2528. GNUNET_asprintf (&ret,
  2529. "%s.%u.%s:%d",
  2530. PLUGIN_NAME,
  2531. ppc->options,
  2532. hostname,
  2533. ppc->port);
  2534. ppc->asc (ppc->asc_cls,
  2535. ret,
  2536. GNUNET_OK);
  2537. GNUNET_free (ret);
  2538. }
  2539. /**
  2540. * Convert the transports address to a nice, human-readable format.
  2541. *
  2542. * @param cls closure with the `struct Plugin`
  2543. * @param type name of the transport that generated the address
  2544. * @param addr one of the addresses of the host, NULL for the last address
  2545. * the specific address format depends on the transport
  2546. * @param addrlen length of the @a addr
  2547. * @param numeric should (IP) addresses be displayed in numeric form?
  2548. * @param timeout after how long should we give up?
  2549. * @param asc function to call on each string
  2550. * @param asc_cls closure for @a asc
  2551. */
  2552. static void
  2553. tcp_plugin_address_pretty_printer (void *cls,
  2554. const char *type,
  2555. const void *addr,
  2556. size_t addrlen,
  2557. int numeric,
  2558. struct GNUNET_TIME_Relative timeout,
  2559. GNUNET_TRANSPORT_AddressStringCallback asc,
  2560. void *asc_cls)
  2561. {
  2562. struct Plugin *plugin = cls;
  2563. struct PrettyPrinterContext *ppc;
  2564. const void *sb;
  2565. size_t sbs;
  2566. struct sockaddr_in a4;
  2567. struct sockaddr_in6 a6;
  2568. const struct IPv4TcpAddress *t4;
  2569. const struct IPv6TcpAddress *t6;
  2570. uint16_t port;
  2571. uint32_t options;
  2572. if (sizeof(struct IPv6TcpAddress) == addrlen)
  2573. {
  2574. t6 = addr;
  2575. memset (&a6, 0, sizeof(a6));
  2576. a6.sin6_family = AF_INET6;
  2577. a6.sin6_port = t6->t6_port;
  2578. GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
  2579. port = ntohs (t6->t6_port);
  2580. options = ntohl (t6->options);
  2581. sb = &a6;
  2582. sbs = sizeof(a6);
  2583. }
  2584. else if (sizeof(struct IPv4TcpAddress) == addrlen)
  2585. {
  2586. t4 = addr;
  2587. memset (&a4, 0, sizeof(a4));
  2588. a4.sin_family = AF_INET;
  2589. a4.sin_port = t4->t4_port;
  2590. a4.sin_addr.s_addr = t4->ipv4_addr;
  2591. port = ntohs (t4->t4_port);
  2592. options = ntohl (t4->options);
  2593. sb = &a4;
  2594. sbs = sizeof(a4);
  2595. }
  2596. else
  2597. {
  2598. /* invalid address */
  2599. LOG (GNUNET_ERROR_TYPE_WARNING,
  2600. _("Unexpected address length: %u bytes\n"),
  2601. (unsigned int) addrlen);
  2602. asc (asc_cls, NULL, GNUNET_SYSERR);
  2603. asc (asc_cls, NULL, GNUNET_OK);
  2604. return;
  2605. }
  2606. ppc = GNUNET_new (struct PrettyPrinterContext);
  2607. ppc->plugin = plugin;
  2608. if (addrlen == sizeof(struct IPv6TcpAddress))
  2609. ppc->ipv6 = GNUNET_YES;
  2610. else
  2611. ppc->ipv6 = GNUNET_NO;
  2612. ppc->asc = asc;
  2613. ppc->asc_cls = asc_cls;
  2614. ppc->port = port;
  2615. ppc->options = options;
  2616. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2617. "Starting DNS reverse lookup\n");
  2618. ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sb,
  2619. sbs,
  2620. ! numeric,
  2621. timeout,
  2622. &append_port,
  2623. ppc);
  2624. if (NULL == ppc->resolver_handle)
  2625. {
  2626. GNUNET_break (0);
  2627. GNUNET_free (ppc);
  2628. return;
  2629. }
  2630. GNUNET_CONTAINER_DLL_insert (plugin->ppc_dll_head,
  2631. plugin->ppc_dll_tail,
  2632. ppc);
  2633. }
  2634. /**
  2635. * Function that will be called to check if a binary address for this
  2636. * plugin is well-formed and corresponds to an address for THIS peer
  2637. * (as per our configuration). Naturally, if absolutely necessary,
  2638. * plugins can be a bit conservative in their answer, but in general
  2639. * plugins should make sure that the address does not redirect
  2640. * traffic to a 3rd party that might try to man-in-the-middle our
  2641. * traffic.
  2642. *
  2643. * @param cls closure, our `struct Plugin *`
  2644. * @param addr pointer to the address
  2645. * @param addrlen length of @a addr
  2646. * @return #GNUNET_OK if this is a plausible address for this peer
  2647. * and transport, #GNUNET_SYSERR if not
  2648. */
  2649. static int
  2650. tcp_plugin_check_address (void *cls,
  2651. const void *addr,
  2652. size_t addrlen)
  2653. {
  2654. struct Plugin *plugin = cls;
  2655. const struct IPv4TcpAddress *v4;
  2656. const struct IPv6TcpAddress *v6;
  2657. if ( (addrlen != sizeof(struct IPv4TcpAddress)) &&
  2658. (addrlen != sizeof(struct IPv6TcpAddress)) )
  2659. {
  2660. GNUNET_break_op (0);
  2661. return GNUNET_SYSERR;
  2662. }
  2663. if (addrlen == sizeof(struct IPv4TcpAddress))
  2664. {
  2665. struct sockaddr_in s4;
  2666. v4 = (const struct IPv4TcpAddress *) addr;
  2667. if (0 != memcmp (&v4->options,
  2668. &plugin->myoptions,
  2669. sizeof(uint32_t)))
  2670. {
  2671. GNUNET_break (0);
  2672. return GNUNET_SYSERR;
  2673. }
  2674. memset (&s4, 0, sizeof (s4));
  2675. s4.sin_family = AF_INET;
  2676. #if HAVE_SOCKADDR_IN_SIN_LEN
  2677. s4.sin_len = sizeof (s4);
  2678. #endif
  2679. s4.sin_port = v4->t4_port;
  2680. s4.sin_addr.s_addr = v4->ipv4_addr;
  2681. if (GNUNET_OK !=
  2682. GNUNET_NAT_test_address (plugin->nat,
  2683. &s4,
  2684. sizeof (struct sockaddr_in)))
  2685. return GNUNET_SYSERR;
  2686. }
  2687. else
  2688. {
  2689. struct sockaddr_in6 s6;
  2690. v6 = (const struct IPv6TcpAddress *) addr;
  2691. if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
  2692. {
  2693. GNUNET_break_op (0);
  2694. return GNUNET_SYSERR;
  2695. }
  2696. if (0 != memcmp (&v6->options,
  2697. &plugin->myoptions,
  2698. sizeof (uint32_t)))
  2699. {
  2700. GNUNET_break (0);
  2701. return GNUNET_SYSERR;
  2702. }
  2703. memset (&s6, 0, sizeof (s6));
  2704. s6.sin6_family = AF_INET6;
  2705. #if HAVE_SOCKADDR_IN_SIN_LEN
  2706. s6.sin6_len = sizeof (s6);
  2707. #endif
  2708. s6.sin6_port = v6->t6_port;
  2709. s6.sin6_addr = v6->ipv6_addr;
  2710. if (GNUNET_OK !=
  2711. GNUNET_NAT_test_address (plugin->nat,
  2712. &s6,
  2713. sizeof(struct sockaddr_in6)))
  2714. return GNUNET_SYSERR;
  2715. }
  2716. return GNUNET_OK;
  2717. }
  2718. /**
  2719. * We've received a nat probe from this peer via TCP. Finish
  2720. * creating the client session and resume sending of queued
  2721. * messages.
  2722. *
  2723. * @param cls closure
  2724. * @param client identification of the client
  2725. * @param message the actual message
  2726. */
  2727. static void
  2728. handle_tcp_nat_probe (void *cls,
  2729. struct GNUNET_SERVER_Client *client,
  2730. const struct GNUNET_MessageHeader *message)
  2731. {
  2732. struct Plugin *plugin = cls;
  2733. struct GNUNET_ATS_Session *session;
  2734. const struct TCP_NAT_ProbeMessage *tcp_nat_probe;
  2735. size_t alen;
  2736. void *vaddr;
  2737. struct IPv4TcpAddress *t4;
  2738. struct IPv6TcpAddress *t6;
  2739. const struct sockaddr_in *s4;
  2740. const struct sockaddr_in6 *s6;
  2741. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2742. "Received NAT probe\n");
  2743. /* We have received a TCP NAT probe, meaning we (hopefully) initiated
  2744. * a connection to this peer by running gnunet-nat-client. This peer
  2745. * received the punch message and now wants us to use the new connection
  2746. * as the default for that peer. Do so and then send a WELCOME message
  2747. * so we can really be connected!
  2748. */
  2749. if (ntohs (message->size) != sizeof(struct TCP_NAT_ProbeMessage))
  2750. {
  2751. GNUNET_break_op(0);
  2752. GNUNET_SERVER_receive_done (client,
  2753. GNUNET_SYSERR);
  2754. return;
  2755. }
  2756. tcp_nat_probe = (const struct TCP_NAT_ProbeMessage *) message;
  2757. if (0 == memcmp (&tcp_nat_probe->clientIdentity, plugin->env->my_identity,
  2758. sizeof(struct GNUNET_PeerIdentity)))
  2759. {
  2760. /* refuse connections from ourselves */
  2761. GNUNET_SERVER_receive_done (client,
  2762. GNUNET_SYSERR);
  2763. return;
  2764. }
  2765. session = GNUNET_CONTAINER_multipeermap_get (plugin->nat_wait_conns,
  2766. &tcp_nat_probe->clientIdentity);
  2767. if (NULL == session)
  2768. {
  2769. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2770. "Did NOT find session for NAT probe!\n");
  2771. GNUNET_SERVER_receive_done (client,
  2772. GNUNET_OK);
  2773. return;
  2774. }
  2775. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2776. "Found session for NAT probe!\n");
  2777. if (NULL != session->nat_connection_timeout)
  2778. {
  2779. GNUNET_SCHEDULER_cancel (session->nat_connection_timeout);
  2780. session->nat_connection_timeout = NULL;
  2781. }
  2782. if (GNUNET_OK !=
  2783. GNUNET_SERVER_client_get_address (client,
  2784. &vaddr,
  2785. &alen))
  2786. {
  2787. GNUNET_break(0);
  2788. GNUNET_SERVER_receive_done (client,
  2789. GNUNET_SYSERR);
  2790. tcp_plugin_disconnect_session (plugin,
  2791. session);
  2792. return;
  2793. }
  2794. GNUNET_assert (GNUNET_YES ==
  2795. GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns,
  2796. &tcp_nat_probe->clientIdentity,
  2797. session));
  2798. GNUNET_SERVER_client_set_user_context (client,
  2799. session);
  2800. (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap,
  2801. &session->target,
  2802. session,
  2803. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  2804. session->last_activity = GNUNET_TIME_absolute_get ();
  2805. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2806. "Found address `%s' for incoming connection\n",
  2807. GNUNET_a2s (vaddr, alen));
  2808. switch (((const struct sockaddr *) vaddr)->sa_family)
  2809. {
  2810. case AF_INET:
  2811. s4 = vaddr;
  2812. t4 = GNUNET_new (struct IPv4TcpAddress);
  2813. t4->options = htonl (TCP_OPTIONS_NONE);
  2814. t4->t4_port = s4->sin_port;
  2815. t4->ipv4_addr = s4->sin_addr.s_addr;
  2816. session->address = GNUNET_HELLO_address_allocate (&tcp_nat_probe->clientIdentity,
  2817. PLUGIN_NAME,
  2818. &t4,
  2819. sizeof(struct IPv4TcpAddress),
  2820. GNUNET_HELLO_ADDRESS_INFO_NONE);
  2821. break;
  2822. case AF_INET6:
  2823. s6 = vaddr;
  2824. t6 = GNUNET_new (struct IPv6TcpAddress);
  2825. t6->options = htonl (TCP_OPTIONS_NONE);
  2826. t6->t6_port = s6->sin6_port;
  2827. GNUNET_memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
  2828. session->address = GNUNET_HELLO_address_allocate (&tcp_nat_probe->clientIdentity,
  2829. PLUGIN_NAME,
  2830. &t6,
  2831. sizeof(struct IPv6TcpAddress),
  2832. GNUNET_HELLO_ADDRESS_INFO_NONE);
  2833. break;
  2834. default:
  2835. GNUNET_break_op(0);
  2836. LOG(GNUNET_ERROR_TYPE_DEBUG,
  2837. "Bad address for incoming connection!\n");
  2838. GNUNET_free(vaddr);
  2839. GNUNET_SERVER_receive_done (client,
  2840. GNUNET_SYSERR);
  2841. tcp_plugin_disconnect_session (plugin,
  2842. session);
  2843. return;
  2844. }
  2845. GNUNET_free (vaddr);
  2846. GNUNET_break (NULL == session->client);
  2847. session->client = client;
  2848. GNUNET_STATISTICS_update (plugin->env->stats,
  2849. gettext_noop ("# TCP sessions active"),
  2850. 1,
  2851. GNUNET_NO);
  2852. process_pending_messages (session);
  2853. GNUNET_SERVER_receive_done (client,
  2854. GNUNET_OK);
  2855. }
  2856. /**
  2857. * We've received a welcome from this peer via TCP. Possibly create a
  2858. * fresh client record and send back our welcome.
  2859. *
  2860. * @param cls closure
  2861. * @param client identification of the client
  2862. * @param message the actual message
  2863. */
  2864. static void
  2865. handle_tcp_welcome (void *cls,
  2866. struct GNUNET_SERVER_Client *client,
  2867. const struct GNUNET_MessageHeader *message)
  2868. {
  2869. struct Plugin *plugin = cls;
  2870. const struct WelcomeMessage *wm = (const struct WelcomeMessage *) message;
  2871. struct GNUNET_HELLO_Address *address;
  2872. struct GNUNET_ATS_Session *session;
  2873. size_t alen;
  2874. void *vaddr;
  2875. struct IPv4TcpAddress t4;
  2876. struct IPv6TcpAddress t6;
  2877. const struct sockaddr_in *s4;
  2878. const struct sockaddr_in6 *s6;
  2879. if (0 == memcmp (&wm->clientIdentity,
  2880. plugin->env->my_identity,
  2881. sizeof(struct GNUNET_PeerIdentity)))
  2882. {
  2883. /* refuse connections from ourselves */
  2884. if (GNUNET_OK ==
  2885. GNUNET_SERVER_client_get_address (client,
  2886. &vaddr,
  2887. &alen))
  2888. {
  2889. LOG (GNUNET_ERROR_TYPE_INFO,
  2890. "Received WELCOME message from my own identity `%s' on address `%s'\n",
  2891. GNUNET_i2s (&wm->clientIdentity),
  2892. GNUNET_a2s (vaddr, alen));
  2893. GNUNET_free (vaddr);
  2894. }
  2895. GNUNET_SERVER_receive_done (client,
  2896. GNUNET_SYSERR);
  2897. return;
  2898. }
  2899. if (GNUNET_OK ==
  2900. GNUNET_SERVER_client_get_address (client,
  2901. &vaddr,
  2902. &alen))
  2903. {
  2904. LOG(GNUNET_ERROR_TYPE_DEBUG,
  2905. "Received WELCOME message from `%s' on address `%s'\n",
  2906. GNUNET_i2s (&wm->clientIdentity),
  2907. GNUNET_a2s (vaddr, alen));
  2908. GNUNET_free (vaddr);
  2909. }
  2910. GNUNET_STATISTICS_update (plugin->env->stats,
  2911. gettext_noop ("# TCP WELCOME messages received"),
  2912. 1,
  2913. GNUNET_NO);
  2914. session = lookup_session_by_client (plugin,
  2915. client);
  2916. if (NULL != session)
  2917. {
  2918. if (GNUNET_OK ==
  2919. GNUNET_SERVER_client_get_address (client,
  2920. &vaddr,
  2921. &alen))
  2922. {
  2923. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2924. "Found existing session %p for peer `%s'\n",
  2925. session,
  2926. GNUNET_a2s (vaddr, alen));
  2927. GNUNET_free (vaddr);
  2928. }
  2929. }
  2930. else
  2931. {
  2932. if (GNUNET_OK ==
  2933. GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
  2934. {
  2935. if (alen == sizeof(struct sockaddr_in))
  2936. {
  2937. s4 = vaddr;
  2938. memset (&t4, '\0', sizeof (t4));
  2939. t4.options = htonl (TCP_OPTIONS_NONE);
  2940. t4.t4_port = s4->sin_port;
  2941. t4.ipv4_addr = s4->sin_addr.s_addr;
  2942. address = GNUNET_HELLO_address_allocate (&wm->clientIdentity,
  2943. PLUGIN_NAME,
  2944. &t4,
  2945. sizeof(t4),
  2946. GNUNET_HELLO_ADDRESS_INFO_INBOUND);
  2947. }
  2948. else if (alen == sizeof(struct sockaddr_in6))
  2949. {
  2950. s6 = vaddr;
  2951. memset (&t6, '\0', sizeof (t6));
  2952. t6.options = htonl (TCP_OPTIONS_NONE);
  2953. t6.t6_port = s6->sin6_port;
  2954. GNUNET_memcpy (&t6.ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
  2955. address = GNUNET_HELLO_address_allocate (&wm->clientIdentity,
  2956. PLUGIN_NAME,
  2957. &t6,
  2958. sizeof (t6),
  2959. GNUNET_HELLO_ADDRESS_INFO_INBOUND);
  2960. }
  2961. else
  2962. {
  2963. GNUNET_break (0);
  2964. GNUNET_free_non_null (vaddr);
  2965. GNUNET_SERVER_receive_done (client,
  2966. GNUNET_SYSERR);
  2967. return;
  2968. }
  2969. session = create_session (plugin,
  2970. address,
  2971. plugin->env->get_address_type (plugin->env->cls,
  2972. vaddr,
  2973. alen),
  2974. client,
  2975. GNUNET_NO);
  2976. GNUNET_break (GNUNET_NT_UNSPECIFIED != session->scope);
  2977. GNUNET_HELLO_address_free (address);
  2978. LOG (GNUNET_ERROR_TYPE_DEBUG,
  2979. "Creating new%s session %p for peer `%s' client %p\n",
  2980. GNUNET_HELLO_address_check_option (session->address,
  2981. GNUNET_HELLO_ADDRESS_INFO_INBOUND)
  2982. ? " inbound" : "",
  2983. session,
  2984. tcp_plugin_address_to_string (plugin,
  2985. session->address->address,
  2986. session->address->address_length),
  2987. client);
  2988. GNUNET_free (vaddr);
  2989. (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap,
  2990. &session->target,
  2991. session,
  2992. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  2993. /* Notify transport and ATS about new session */
  2994. plugin->env->session_start (plugin->env->cls,
  2995. session->address,
  2996. session,
  2997. session->scope);
  2998. }
  2999. else
  3000. {
  3001. LOG(GNUNET_ERROR_TYPE_DEBUG,
  3002. "Did not obtain TCP socket address for incoming connection\n");
  3003. GNUNET_break(0);
  3004. GNUNET_SERVER_receive_done (client,
  3005. GNUNET_SYSERR);
  3006. return;
  3007. }
  3008. }
  3009. if (GNUNET_YES != session->expecting_welcome)
  3010. {
  3011. GNUNET_break_op (0);
  3012. GNUNET_SERVER_receive_done (client,
  3013. GNUNET_SYSERR);
  3014. return;
  3015. }
  3016. session->last_activity = GNUNET_TIME_absolute_get ();
  3017. session->expecting_welcome = GNUNET_NO;
  3018. process_pending_messages (session);
  3019. GNUNET_SERVER_client_set_timeout (client,
  3020. GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
  3021. GNUNET_SERVER_receive_done (client,
  3022. GNUNET_OK);
  3023. }
  3024. /**
  3025. * We've received data for this peer via TCP. Unbox,
  3026. * compute latency and forward.
  3027. *
  3028. * @param cls closure
  3029. * @param client identification of the client
  3030. * @param message the actual message
  3031. */
  3032. static void
  3033. handle_tcp_data (void *cls,
  3034. struct GNUNET_SERVER_Client *client,
  3035. const struct GNUNET_MessageHeader *message)
  3036. {
  3037. struct Plugin *plugin = cls;
  3038. struct GNUNET_ATS_Session *session;
  3039. struct GNUNET_TIME_Relative delay;
  3040. uint16_t type;
  3041. type = ntohs (message->type);
  3042. if ( (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == type) ||
  3043. (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE == type) )
  3044. {
  3045. /* We don't want to propagate WELCOME and NAT Probe messages up! */
  3046. GNUNET_SERVER_receive_done (client,
  3047. GNUNET_OK);
  3048. return;
  3049. }
  3050. session = lookup_session_by_client (plugin, client);
  3051. if (NULL == session)
  3052. {
  3053. /* No inbound session found */
  3054. void *vaddr = NULL;
  3055. size_t alen;
  3056. GNUNET_assert (GNUNET_OK ==
  3057. GNUNET_SERVER_client_get_address (client,
  3058. &vaddr,
  3059. &alen));
  3060. LOG (GNUNET_ERROR_TYPE_ERROR,
  3061. "Received unexpected %u bytes of type %u from `%s'\n",
  3062. (unsigned int) ntohs (message->size),
  3063. (unsigned int) ntohs (message->type),
  3064. GNUNET_a2s (vaddr,
  3065. alen));
  3066. GNUNET_break_op(0);
  3067. GNUNET_SERVER_receive_done (client,
  3068. GNUNET_SYSERR);
  3069. GNUNET_free_non_null (vaddr);
  3070. return;
  3071. }
  3072. if (GNUNET_YES == session->expecting_welcome)
  3073. {
  3074. /* Session is expecting WELCOME message */
  3075. void *vaddr = NULL;
  3076. size_t alen;
  3077. GNUNET_SERVER_client_get_address (client,
  3078. &vaddr,
  3079. &alen);
  3080. LOG (GNUNET_ERROR_TYPE_ERROR,
  3081. "Received unexpected %u bytes of type %u from `%s'\n",
  3082. (unsigned int) ntohs (message->size),
  3083. (unsigned int) ntohs (message->type),
  3084. GNUNET_a2s (vaddr, alen));
  3085. GNUNET_break_op(0);
  3086. GNUNET_SERVER_receive_done (client,
  3087. GNUNET_SYSERR);
  3088. GNUNET_free_non_null (vaddr);
  3089. return;
  3090. }
  3091. session->last_activity = GNUNET_TIME_absolute_get ();
  3092. {
  3093. void *vaddr = NULL;
  3094. size_t alen;
  3095. GNUNET_SERVER_client_get_address (client,
  3096. &vaddr,
  3097. &alen);
  3098. LOG (GNUNET_ERROR_TYPE_DEBUG,
  3099. "Passing %u bytes of type %u from `%s' at %s to transport service.\n",
  3100. (unsigned int) ntohs (message->size),
  3101. (unsigned int) ntohs (message->type),
  3102. GNUNET_i2s (&session->target),
  3103. GNUNET_a2s (vaddr, alen));
  3104. GNUNET_free_non_null (vaddr);
  3105. }
  3106. GNUNET_STATISTICS_update (plugin->env->stats,
  3107. gettext_noop ("# bytes received via TCP"),
  3108. ntohs (message->size),
  3109. GNUNET_NO);
  3110. GNUNET_assert (GNUNET_CONTAINER_multipeermap_contains_value (plugin->sessionmap,
  3111. &session->target,
  3112. session));
  3113. delay = plugin->env->receive (plugin->env->cls,
  3114. session->address,
  3115. session,
  3116. message);
  3117. reschedule_session_timeout (session);
  3118. if (0 == delay.rel_value_us)
  3119. {
  3120. GNUNET_SERVER_receive_done (client,
  3121. GNUNET_OK);
  3122. }
  3123. else
  3124. {
  3125. LOG (GNUNET_ERROR_TYPE_DEBUG,
  3126. "Throttling receiving from `%s' for %s\n",
  3127. GNUNET_i2s (&session->target),
  3128. GNUNET_STRINGS_relative_time_to_string (delay,
  3129. GNUNET_YES));
  3130. GNUNET_SERVER_disable_receive_done_warning (client);
  3131. GNUNET_assert (NULL == session->receive_delay_task);
  3132. session->receive_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
  3133. &delayed_done,
  3134. session);
  3135. }
  3136. }
  3137. /**
  3138. * Function called whenever a peer is connected on the "SERVER" level.
  3139. * Increments number of active connections and suspends server if we
  3140. * have reached the limit.
  3141. *
  3142. * @param cls closure
  3143. * @param client identification of the client
  3144. */
  3145. static void
  3146. connect_notify (void *cls,
  3147. struct GNUNET_SERVER_Client *client)
  3148. {
  3149. struct Plugin *plugin = cls;
  3150. if (NULL == client)
  3151. return;
  3152. plugin->cur_connections++;
  3153. GNUNET_STATISTICS_set (plugin->env->stats,
  3154. gettext_noop ("# TCP server connections active"),
  3155. plugin->cur_connections,
  3156. GNUNET_NO);
  3157. GNUNET_STATISTICS_update (plugin->env->stats,
  3158. gettext_noop ("# TCP server connect events"),
  3159. 1,
  3160. GNUNET_NO);
  3161. if (plugin->cur_connections != plugin->max_connections)
  3162. return;
  3163. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  3164. _("TCP connection limit reached, suspending server\n"));
  3165. GNUNET_STATISTICS_update (plugin->env->stats,
  3166. gettext_noop ("# TCP service suspended"),
  3167. 1,
  3168. GNUNET_NO);
  3169. GNUNET_SERVER_suspend (plugin->server); /* Maximum number of connections rechead */
  3170. }
  3171. /**
  3172. * Function called whenever a peer is disconnected on the "SERVER"
  3173. * level. Cleans up the connection, decrements number of active
  3174. * connections and if applicable resumes listening.
  3175. *
  3176. * @param cls closure
  3177. * @param client identification of the client
  3178. */
  3179. static void
  3180. disconnect_notify (void *cls,
  3181. struct GNUNET_SERVER_Client *client)
  3182. {
  3183. struct Plugin *plugin = cls;
  3184. struct GNUNET_ATS_Session *session;
  3185. if (NULL == client)
  3186. return;
  3187. GNUNET_assert (plugin->cur_connections >= 1);
  3188. plugin->cur_connections--;
  3189. session = lookup_session_by_client (plugin,
  3190. client);
  3191. if (NULL == session)
  3192. return; /* unknown, nothing to do */
  3193. LOG (GNUNET_ERROR_TYPE_DEBUG,
  3194. "Destroying session of `%s' with %s due to network-level disconnect.\n",
  3195. GNUNET_i2s (&session->target),
  3196. tcp_plugin_address_to_string (session->plugin,
  3197. session->address->address,
  3198. session->address->address_length));
  3199. if (plugin->cur_connections == plugin->max_connections)
  3200. {
  3201. GNUNET_STATISTICS_update (session->plugin->env->stats,
  3202. gettext_noop ("# TCP service resumed"),
  3203. 1,
  3204. GNUNET_NO);
  3205. GNUNET_SERVER_resume (plugin->server); /* Resume server */
  3206. }
  3207. GNUNET_STATISTICS_set (plugin->env->stats,
  3208. gettext_noop ("# TCP server connections active"),
  3209. plugin->cur_connections,
  3210. GNUNET_NO);
  3211. GNUNET_STATISTICS_update (session->plugin->env->stats,
  3212. gettext_noop ("# network-level TCP disconnect events"),
  3213. 1,
  3214. GNUNET_NO);
  3215. tcp_plugin_disconnect_session (plugin,
  3216. session);
  3217. }
  3218. /**
  3219. * We can now send a probe message, copy into buffer to really send.
  3220. *
  3221. * @param cls closure, a `struct TCPProbeContext`
  3222. * @param size max size to copy
  3223. * @param buf buffer to copy message to
  3224. * @return number of bytes copied into @a buf
  3225. */
  3226. static size_t
  3227. notify_send_probe (void *cls,
  3228. size_t size,
  3229. void *buf)
  3230. {
  3231. struct TCPProbeContext *tcp_probe_ctx = cls;
  3232. struct Plugin *plugin = tcp_probe_ctx->plugin;
  3233. size_t ret;
  3234. tcp_probe_ctx->transmit_handle = NULL;
  3235. GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
  3236. plugin->probe_tail,
  3237. tcp_probe_ctx);
  3238. if (NULL == buf)
  3239. {
  3240. GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock);
  3241. GNUNET_free(tcp_probe_ctx);
  3242. return 0;
  3243. }
  3244. GNUNET_assert(size >= sizeof(tcp_probe_ctx->message));
  3245. GNUNET_memcpy (buf,
  3246. &tcp_probe_ctx->message,
  3247. sizeof(tcp_probe_ctx->message));
  3248. GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server,
  3249. tcp_probe_ctx->sock);
  3250. ret = sizeof(tcp_probe_ctx->message);
  3251. GNUNET_free (tcp_probe_ctx);
  3252. return ret;
  3253. }
  3254. /**
  3255. * Function called by the NAT subsystem suggesting another peer wants
  3256. * to connect to us via connection reversal. Try to connect back to the
  3257. * given IP.
  3258. *
  3259. * @param cls closure
  3260. * @param addr address to try
  3261. * @param addrlen number of bytes in @a addr
  3262. */
  3263. static void
  3264. try_connection_reversal (void *cls,
  3265. const struct sockaddr *addr,
  3266. socklen_t addrlen)
  3267. {
  3268. struct Plugin *plugin = cls;
  3269. struct GNUNET_CONNECTION_Handle *sock;
  3270. struct TCPProbeContext *tcp_probe_ctx;
  3271. /**
  3272. * We have received an ICMP response, ostensibly from a peer
  3273. * that wants to connect to us! Send a message to establish a connection.
  3274. */
  3275. sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET,
  3276. addr,
  3277. addrlen);
  3278. if (NULL == sock)
  3279. {
  3280. /* failed for some odd reason (out of sockets?); ignore attempt */
  3281. return;
  3282. }
  3283. tcp_probe_ctx = GNUNET_new (struct TCPProbeContext);
  3284. tcp_probe_ctx->message.header.size
  3285. = htons (sizeof (struct TCP_NAT_ProbeMessage));
  3286. tcp_probe_ctx->message.header.type
  3287. = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE);
  3288. tcp_probe_ctx->message.clientIdentity
  3289. = *plugin->env->my_identity;
  3290. tcp_probe_ctx->plugin = plugin;
  3291. tcp_probe_ctx->sock = sock;
  3292. GNUNET_CONTAINER_DLL_insert (plugin->probe_head,
  3293. plugin->probe_tail,
  3294. tcp_probe_ctx);
  3295. tcp_probe_ctx->transmit_handle
  3296. = GNUNET_CONNECTION_notify_transmit_ready (sock,
  3297. ntohs (tcp_probe_ctx->message.header.size),
  3298. GNUNET_TIME_UNIT_FOREVER_REL,
  3299. &notify_send_probe,
  3300. tcp_probe_ctx);
  3301. }
  3302. /**
  3303. * Function obtain the network type for a session
  3304. *
  3305. * @param cls closure (`struct Plugin *`)
  3306. * @param session the session
  3307. * @return the network type in HBO or #GNUNET_SYSERR
  3308. */
  3309. static enum GNUNET_NetworkType
  3310. tcp_plugin_get_network (void *cls,
  3311. struct GNUNET_ATS_Session *session)
  3312. {
  3313. return session->scope;
  3314. }
  3315. /**
  3316. * Function obtain the network type for an address.
  3317. *
  3318. * @param cls closure (`struct Plugin *`)
  3319. * @param address the address
  3320. * @return the network type
  3321. */
  3322. static enum GNUNET_NetworkType
  3323. tcp_plugin_get_network_for_address (void *cls,
  3324. const struct GNUNET_HELLO_Address *address)
  3325. {
  3326. struct Plugin *plugin = cls;
  3327. size_t addrlen;
  3328. struct sockaddr_in a4;
  3329. struct sockaddr_in6 a6;
  3330. const struct IPv4TcpAddress *t4;
  3331. const struct IPv6TcpAddress *t6;
  3332. const void *sb;
  3333. size_t sbs;
  3334. addrlen = address->address_length;
  3335. if (addrlen == sizeof(struct IPv6TcpAddress))
  3336. {
  3337. GNUNET_assert (NULL != address->address); /* make static analysis happy */
  3338. t6 = address->address;
  3339. memset (&a6, 0, sizeof(a6));
  3340. #if HAVE_SOCKADDR_IN_SIN_LEN
  3341. a6.sin6_len = sizeof (a6);
  3342. #endif
  3343. a6.sin6_family = AF_INET6;
  3344. a6.sin6_port = t6->t6_port;
  3345. GNUNET_memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr));
  3346. sb = &a6;
  3347. sbs = sizeof(a6);
  3348. }
  3349. else if (addrlen == sizeof(struct IPv4TcpAddress))
  3350. {
  3351. GNUNET_assert (NULL != address->address); /* make static analysis happy */
  3352. t4 = address->address;
  3353. memset (&a4, 0, sizeof(a4));
  3354. #if HAVE_SOCKADDR_IN_SIN_LEN
  3355. a4.sin_len = sizeof (a4);
  3356. #endif
  3357. a4.sin_family = AF_INET;
  3358. a4.sin_port = t4->t4_port;
  3359. a4.sin_addr.s_addr = t4->ipv4_addr;
  3360. sb = &a4;
  3361. sbs = sizeof(a4);
  3362. }
  3363. else
  3364. {
  3365. GNUNET_break (0);
  3366. return GNUNET_NT_UNSPECIFIED;
  3367. }
  3368. return plugin->env->get_address_type (plugin->env->cls,
  3369. sb,
  3370. sbs);
  3371. }
  3372. /**
  3373. * Return information about the given session to the
  3374. * monitor callback.
  3375. *
  3376. * @param cls the `struct Plugin` with the monitor callback (`sic`)
  3377. * @param peer peer we send information about
  3378. * @param value our `struct GNUNET_ATS_Session` to send information about
  3379. * @return #GNUNET_OK (continue to iterate)
  3380. */
  3381. static int
  3382. send_session_info_iter (void *cls,
  3383. const struct GNUNET_PeerIdentity *peer,
  3384. void *value)
  3385. {
  3386. struct Plugin *plugin = cls;
  3387. struct GNUNET_ATS_Session *session = value;
  3388. notify_session_monitor (plugin,
  3389. session,
  3390. GNUNET_TRANSPORT_SS_INIT);
  3391. /* FIXME: cannot tell if this is up or not from current
  3392. session state... */
  3393. notify_session_monitor (plugin,
  3394. session,
  3395. GNUNET_TRANSPORT_SS_UP);
  3396. return GNUNET_OK;
  3397. }
  3398. /**
  3399. * Begin monitoring sessions of a plugin. There can only
  3400. * be one active monitor per plugin (i.e. if there are
  3401. * multiple monitors, the transport service needs to
  3402. * multiplex the generated events over all of them).
  3403. *
  3404. * @param cls closure of the plugin
  3405. * @param sic callback to invoke, NULL to disable monitor;
  3406. * plugin will being by iterating over all active
  3407. * sessions immediately and then enter monitor mode
  3408. * @param sic_cls closure for @a sic
  3409. */
  3410. static void
  3411. tcp_plugin_setup_monitor (void *cls,
  3412. GNUNET_TRANSPORT_SessionInfoCallback sic,
  3413. void *sic_cls)
  3414. {
  3415. struct Plugin *plugin = cls;
  3416. plugin->sic = sic;
  3417. plugin->sic_cls = sic_cls;
  3418. if (NULL != sic)
  3419. {
  3420. GNUNET_CONTAINER_multipeermap_iterate (plugin->sessionmap,
  3421. &send_session_info_iter,
  3422. plugin);
  3423. /* signal end of first iteration */
  3424. sic (sic_cls, NULL, NULL);
  3425. }
  3426. }
  3427. /**
  3428. * Entry point for the plugin.
  3429. *
  3430. * @param cls closure, the `struct GNUNET_TRANSPORT_PluginEnvironment *`
  3431. * @return the `struct GNUNET_TRANSPORT_PluginFunctions *` or NULL on error
  3432. */
  3433. void *
  3434. libgnunet_plugin_transport_tcp_init (void *cls)
  3435. {
  3436. static const struct GNUNET_SERVER_MessageHandler my_handlers[] = {
  3437. { &handle_tcp_welcome, NULL,
  3438. GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME,
  3439. sizeof(struct WelcomeMessage) },
  3440. { &handle_tcp_nat_probe, NULL,
  3441. GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE,
  3442. sizeof(struct TCP_NAT_ProbeMessage) },
  3443. { &handle_tcp_data, NULL,
  3444. GNUNET_MESSAGE_TYPE_ALL, 0 },
  3445. { NULL, NULL, 0, 0 }
  3446. };
  3447. struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
  3448. struct GNUNET_TRANSPORT_PluginFunctions *api;
  3449. struct Plugin *plugin;
  3450. struct LEGACY_SERVICE_Context *service;
  3451. unsigned long long aport;
  3452. unsigned long long bport;
  3453. unsigned long long max_connections;
  3454. unsigned int i;
  3455. struct GNUNET_TIME_Relative idle_timeout;
  3456. #ifdef TCP_STEALTH
  3457. struct GNUNET_NETWORK_Handle *const*lsocks;
  3458. #endif
  3459. int ret;
  3460. int ret_s;
  3461. struct sockaddr **addrs;
  3462. socklen_t *addrlens;
  3463. if (NULL == env->receive)
  3464. {
  3465. /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
  3466. initialze the plugin or the API */
  3467. api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
  3468. api->cls = NULL;
  3469. api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
  3470. api->address_to_string = &tcp_plugin_address_to_string;
  3471. api->string_to_address = &tcp_plugin_string_to_address;
  3472. return api;
  3473. }
  3474. GNUNET_assert (NULL != env->cfg);
  3475. if (GNUNET_OK !=
  3476. GNUNET_CONFIGURATION_get_value_number (env->cfg,
  3477. "transport-tcp",
  3478. "MAX_CONNECTIONS",
  3479. &max_connections))
  3480. max_connections = 128;
  3481. aport = 0;
  3482. if ((GNUNET_OK !=
  3483. GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
  3484. "PORT", &bport)) ||
  3485. (bport > 65535) ||
  3486. ((GNUNET_OK ==
  3487. GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
  3488. "ADVERTISED-PORT", &aport)) &&
  3489. (aport > 65535) ))
  3490. {
  3491. LOG(GNUNET_ERROR_TYPE_ERROR,
  3492. _("Require valid port number for service `%s' in configuration!\n"),
  3493. "transport-tcp");
  3494. return NULL ;
  3495. }
  3496. if (0 == aport)
  3497. aport = bport;
  3498. if (0 == bport)
  3499. aport = 0;
  3500. if (0 != bport)
  3501. {
  3502. service = LEGACY_SERVICE_start ("transport-tcp",
  3503. env->cfg,
  3504. LEGACY_SERVICE_OPTION_NONE);
  3505. if (NULL == service)
  3506. {
  3507. LOG (GNUNET_ERROR_TYPE_WARNING,
  3508. _("Failed to start service.\n"));
  3509. return NULL;
  3510. }
  3511. }
  3512. else
  3513. service = NULL;
  3514. api = NULL;
  3515. plugin = GNUNET_new (struct Plugin);
  3516. plugin->sessionmap = GNUNET_CONTAINER_multipeermap_create (max_connections,
  3517. GNUNET_YES);
  3518. plugin->max_connections = max_connections;
  3519. plugin->open_port = bport;
  3520. plugin->adv_port = aport;
  3521. plugin->env = env;
  3522. plugin->my_welcome.header.size = htons (sizeof(struct WelcomeMessage));
  3523. plugin->my_welcome.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME);
  3524. plugin->my_welcome.clientIdentity = *plugin->env->my_identity;
  3525. if ( (NULL != service) &&
  3526. (GNUNET_YES ==
  3527. GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
  3528. "transport-tcp",
  3529. "TCP_STEALTH")) )
  3530. {
  3531. #ifdef TCP_STEALTH
  3532. plugin->myoptions |= TCP_OPTIONS_TCP_STEALTH;
  3533. lsocks = LEGACY_SERVICE_get_listen_sockets (service);
  3534. if (NULL != lsocks)
  3535. {
  3536. uint32_t len = sizeof (struct WelcomeMessage);
  3537. for (i=0;NULL!=lsocks[i];i++)
  3538. {
  3539. if ( (GNUNET_OK !=
  3540. GNUNET_NETWORK_socket_setsockopt (lsocks[i],
  3541. IPPROTO_TCP,
  3542. TCP_STEALTH,
  3543. env->my_identity,
  3544. sizeof (struct GNUNET_PeerIdentity))) ||
  3545. (GNUNET_OK !=
  3546. GNUNET_NETWORK_socket_setsockopt (lsocks[i],
  3547. IPPROTO_TCP,
  3548. TCP_STEALTH_INTEGRITY_LEN,
  3549. &len,
  3550. sizeof (len))) )
  3551. {
  3552. /* TCP STEALTH not supported by kernel */
  3553. GNUNET_assert (0 == i);
  3554. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  3555. _("TCP_STEALTH not supported on this platform.\n"));
  3556. goto die;
  3557. }
  3558. }
  3559. }
  3560. #else
  3561. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  3562. _("TCP_STEALTH not supported on this platform.\n"));
  3563. goto die;
  3564. #endif
  3565. }
  3566. if ( (NULL != service) &&
  3567. (GNUNET_SYSERR !=
  3568. (ret_s =
  3569. get_server_addresses ("transport-tcp",
  3570. env->cfg,
  3571. &addrs,
  3572. &addrlens))))
  3573. {
  3574. for (ret = ret_s-1; ret >= 0; ret--)
  3575. LOG (GNUNET_ERROR_TYPE_INFO,
  3576. "Binding to address `%s'\n",
  3577. GNUNET_a2s (addrs[ret], addrlens[ret]));
  3578. plugin->nat
  3579. = GNUNET_NAT_register (env->cfg,
  3580. "transport-tcp",
  3581. IPPROTO_TCP,
  3582. (unsigned int) ret_s,
  3583. (const struct sockaddr **) addrs,
  3584. addrlens,
  3585. &tcp_nat_port_map_callback,
  3586. &try_connection_reversal,
  3587. plugin);
  3588. for (ret = ret_s -1; ret >= 0; ret--)
  3589. GNUNET_free (addrs[ret]);
  3590. GNUNET_free_non_null (addrs);
  3591. GNUNET_free_non_null (addrlens);
  3592. }
  3593. else
  3594. {
  3595. plugin->nat = GNUNET_NAT_register (plugin->env->cfg,
  3596. "transport-tcp",
  3597. IPPROTO_TCP,
  3598. 0,
  3599. NULL,
  3600. NULL,
  3601. NULL,
  3602. &try_connection_reversal,
  3603. plugin);
  3604. }
  3605. api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
  3606. api->cls = plugin;
  3607. api->send = &tcp_plugin_send;
  3608. api->get_session = &tcp_plugin_get_session;
  3609. api->disconnect_session = &tcp_plugin_disconnect_session;
  3610. api->query_keepalive_factor = &tcp_plugin_query_keepalive_factor;
  3611. api->disconnect_peer = &tcp_plugin_disconnect;
  3612. api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
  3613. api->check_address = &tcp_plugin_check_address;
  3614. api->address_to_string = &tcp_plugin_address_to_string;
  3615. api->string_to_address = &tcp_plugin_string_to_address;
  3616. api->get_network = &tcp_plugin_get_network;
  3617. api->get_network_for_address = &tcp_plugin_get_network_for_address;
  3618. api->update_session_timeout = &tcp_plugin_update_session_timeout;
  3619. api->update_inbound_delay = &tcp_plugin_update_inbound_delay;
  3620. api->setup_monitor = &tcp_plugin_setup_monitor;
  3621. plugin->service = service;
  3622. if (NULL != service)
  3623. {
  3624. plugin->server = LEGACY_SERVICE_get_server (service);
  3625. }
  3626. else
  3627. {
  3628. if (GNUNET_OK !=
  3629. GNUNET_CONFIGURATION_get_value_time (env->cfg,
  3630. "transport-tcp",
  3631. "TIMEOUT",
  3632. &idle_timeout))
  3633. {
  3634. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
  3635. "transport-tcp",
  3636. "TIMEOUT");
  3637. goto die;
  3638. }
  3639. plugin->server
  3640. = GNUNET_SERVER_create_with_sockets (NULL,
  3641. plugin,
  3642. NULL,
  3643. idle_timeout,
  3644. GNUNET_YES);
  3645. }
  3646. plugin->handlers = GNUNET_malloc (sizeof (my_handlers));
  3647. GNUNET_memcpy (plugin->handlers,
  3648. my_handlers,
  3649. sizeof(my_handlers));
  3650. for (i = 0;i < sizeof(my_handlers) / sizeof(struct GNUNET_SERVER_MessageHandler);i++)
  3651. plugin->handlers[i].callback_cls = plugin;
  3652. GNUNET_SERVER_add_handlers (plugin->server,
  3653. plugin->handlers);
  3654. GNUNET_SERVER_connect_notify (plugin->server,
  3655. &connect_notify,
  3656. plugin);
  3657. GNUNET_SERVER_disconnect_notify (plugin->server,
  3658. &disconnect_notify,
  3659. plugin);
  3660. plugin->nat_wait_conns = GNUNET_CONTAINER_multipeermap_create (16,
  3661. GNUNET_YES);
  3662. if (0 != bport)
  3663. LOG (GNUNET_ERROR_TYPE_INFO,
  3664. _("TCP transport listening on port %llu\n"),
  3665. bport);
  3666. else
  3667. LOG (GNUNET_ERROR_TYPE_INFO,
  3668. _("TCP transport not listening on any port (client only)\n"));
  3669. if ( (aport != bport) &&
  3670. (0 != bport) )
  3671. LOG (GNUNET_ERROR_TYPE_INFO,
  3672. _("TCP transport advertises itself as being on port %llu\n"),
  3673. aport);
  3674. /* Initially set connections to 0 */
  3675. GNUNET_STATISTICS_set (plugin->env->stats,
  3676. gettext_noop ("# TCP sessions active"),
  3677. 0,
  3678. GNUNET_NO);
  3679. return api;
  3680. die:
  3681. if (NULL != plugin->nat)
  3682. GNUNET_NAT_unregister (plugin->nat);
  3683. GNUNET_CONTAINER_multipeermap_destroy (plugin->sessionmap);
  3684. if (NULL != service)
  3685. LEGACY_SERVICE_stop (service);
  3686. GNUNET_free (plugin);
  3687. GNUNET_free_non_null (api);
  3688. return NULL;
  3689. }
  3690. /**
  3691. * Exit point from the plugin.
  3692. *
  3693. * @param cls the `struct GNUNET_TRANSPORT_PluginFunctions`
  3694. * @return NULL
  3695. */
  3696. void *
  3697. libgnunet_plugin_transport_tcp_done (void *cls)
  3698. {
  3699. struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
  3700. struct Plugin *plugin = api->cls;
  3701. struct TCPProbeContext *tcp_probe;
  3702. struct PrettyPrinterContext *cur;
  3703. struct PrettyPrinterContext *next;
  3704. if (NULL == plugin)
  3705. {
  3706. GNUNET_free(api);
  3707. return NULL ;
  3708. }
  3709. LOG (GNUNET_ERROR_TYPE_DEBUG,
  3710. "Shutting down TCP plugin\n");
  3711. /* Removing leftover sessions */
  3712. GNUNET_CONTAINER_multipeermap_iterate (plugin->sessionmap,
  3713. &session_disconnect_it,
  3714. plugin);
  3715. /* Removing leftover NAT sessions */
  3716. GNUNET_CONTAINER_multipeermap_iterate (plugin->nat_wait_conns,
  3717. &session_disconnect_it,
  3718. plugin);
  3719. for (cur = plugin->ppc_dll_head; NULL != cur; cur = next)
  3720. {
  3721. next = cur->next;
  3722. GNUNET_CONTAINER_DLL_remove (plugin->ppc_dll_head,
  3723. plugin->ppc_dll_tail,
  3724. cur);
  3725. GNUNET_RESOLVER_request_cancel (cur->resolver_handle);
  3726. cur->asc (cur->asc_cls,
  3727. NULL,
  3728. GNUNET_OK);
  3729. GNUNET_free (cur);
  3730. }
  3731. if (NULL != plugin->service)
  3732. LEGACY_SERVICE_stop (plugin->service);
  3733. else
  3734. GNUNET_SERVER_destroy (plugin->server);
  3735. GNUNET_free (plugin->handlers);
  3736. if (NULL != plugin->nat)
  3737. GNUNET_NAT_unregister (plugin->nat);
  3738. while (NULL != (tcp_probe = plugin->probe_head))
  3739. {
  3740. GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
  3741. plugin->probe_tail,
  3742. tcp_probe);
  3743. GNUNET_CONNECTION_destroy (tcp_probe->sock);
  3744. GNUNET_free (tcp_probe);
  3745. }
  3746. GNUNET_CONTAINER_multipeermap_destroy (plugin->nat_wait_conns);
  3747. GNUNET_CONTAINER_multipeermap_destroy (plugin->sessionmap);
  3748. GNUNET_break (0 == plugin->cur_connections);
  3749. GNUNET_free (plugin);
  3750. GNUNET_free (api);
  3751. return NULL;
  3752. }
  3753. /* end of plugin_transport_tcp.c */