jsocket.cpp 204 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. // New IPv6 Version - IN PROGRESS
  14. /*
  15. TBD IPv6 connect
  16. multicast
  17. look at loopback
  18. */
  19. #include <string>
  20. #include <unordered_set>
  21. #include <functional>
  22. #include "platform.h"
  23. #ifdef _VER_C5
  24. #include <clwclib.h>
  25. #else
  26. #include "platform.h"
  27. #include <stdio.h>
  28. #endif
  29. #include <algorithm>
  30. #ifdef _WIN32
  31. #define WIN32_LEAN_AND_MEAN
  32. #include <windows.h>
  33. #include <winsock2.h>
  34. #include <ws2tcpip.h>
  35. #include <signal.h>
  36. #else
  37. #include <sys/types.h>
  38. #include <sys/socket.h>
  39. #include <netinet/tcp.h>
  40. #include <netinet/in.h>
  41. #include <arpa/inet.h>
  42. #include <stddef.h>
  43. #include <errno.h>
  44. #include <net/if.h>
  45. #include <poll.h>
  46. #endif
  47. #include <limits.h>
  48. #include "jmutex.hpp"
  49. #include "jsocket.hpp"
  50. #include "jexcept.hpp"
  51. #include "jio.hpp"
  52. #include "jmisc.hpp"
  53. #include "jthread.hpp"
  54. #include "jqueue.tpp"
  55. #include "jtime.hpp"
  56. #include "jprop.hpp"
  57. #include "jregexp.hpp"
  58. #include "jdebug.hpp"
  59. // epoll only with linux
  60. #ifndef __linux__
  61. # undef _HAS_EPOLL_SUPPORT
  62. #else
  63. # define _HAS_EPOLL_SUPPORT
  64. # ifdef _HAS_EPOLL_SUPPORT
  65. # include <unistd.h>
  66. # include <sys/epoll.h>
  67. # ifndef EPOLLRDHUP
  68. // Centos 5.x bug - epoll.h does not define but its in the kernel
  69. # define EPOLLRDHUP 0x2000
  70. # endif
  71. # define MAX_RET_EVENTS 5000 // max events returned from epoll_wait() call
  72. static unsigned epoll_hdlPerThrd = UINT_MAX;
  73. # endif
  74. #endif
  75. // various options
  76. #define CONNECT_TIMEOUT_REFUSED_WAIT 1000 // maximum to sleep on connect_timeout
  77. #define TRACE_SLOW_BLOCK_TRANSFER
  78. #define DEFAULT_CONNECT_TIME (100*1000) // for connect_wait
  79. #ifdef _DEBUG
  80. // #define SIMULATE_LOST_UDP_PACKETS
  81. #endif
  82. #ifdef SIMULATE_LOST_UDP_PACKETS
  83. static const int dropThreshold = 10000;
  84. static int dropCounter = 0;
  85. #endif
  86. #ifdef _DEBUG
  87. //#define SOCKTRACE
  88. //#define EPOLLTRACE
  89. #endif
  90. #ifdef _TESTING
  91. #define _TRACE
  92. #endif
  93. #ifdef _TRACE
  94. #define THROWJSOCKEXCEPTION(exc) \
  95. { StringBuffer msg; \
  96. msg.appendf("Target: %s, Raised in: %s, line %d",tracename ,sanitizeSourceFile(__FILE__), __LINE__); \
  97. IJSOCK_Exception *e = new SocketException(exc,msg.str());\
  98. throw e; }
  99. #define THROWJSOCKEXCEPTION2(exc) \
  100. { StringBuffer msg; \
  101. msg.appendf("Raised in: %s, line %d",sanitizeSourceFile(__FILE__), __LINE__); \
  102. IJSOCK_Exception *e = new SocketException(exc,msg.str());\
  103. throw e; }
  104. #define LOGERR(err,ref,info) LogErr(err,ref,info,__LINE__,NULL)
  105. #define LOGERR2(err,ref,info) LogErr(err,ref,info,__LINE__,tracename)
  106. #else
  107. #define THROWJSOCKEXCEPTION(exc) \
  108. { IJSOCK_Exception *e = new SocketException(exc);\
  109. throw e; }
  110. #define THROWJSOCKEXCEPTION2(exc) THROWJSOCKEXCEPTION(exc)
  111. #define LOGERR(err,ref,info)
  112. #define LOGERR2(err,ref,info)
  113. #endif
  114. JSocketStatistics STATS;
  115. static const bool IP4only=false; // slighly faster if we know no IPv6
  116. static bool IP6preferred=false; // e.g. for DNS and socket create
  117. IpSubNet PreferredSubnet(NULL,NULL); // set this if you prefer a particular subnet for debugging etc
  118. // e.g. PreferredSubnet("192.168.16.0", "255.255.255.0")
  119. static RelaxedAtomic<unsigned> pre_conn_unreach_cnt{0}; // global count of pre_connect() JSE_NETUNREACH error
  120. #define IPV6_SERIALIZE_PREFIX (0x00ff00ff)
  121. class jlib_thrown_decl SocketException: public IJSOCK_Exception, public CInterface
  122. {
  123. public:
  124. IMPLEMENT_IINTERFACE;
  125. SocketException(int code,const char *_msg=NULL) : errcode(code)
  126. {
  127. if (_msg)
  128. msg = strdup(_msg);
  129. else
  130. msg = NULL;
  131. };
  132. ~SocketException() { free(msg); }
  133. int errorCode() const { return errcode; }
  134. static StringBuffer & geterrormessage(int err,StringBuffer &str)
  135. {
  136. switch (err) {
  137. case JSOCKERR_ok: return str.append("ok");
  138. case JSOCKERR_not_opened: return str.append("socket not opened");
  139. case JSOCKERR_bad_address: return str.append("bad address");
  140. case JSOCKERR_connection_failed: return str.append("connection failed");
  141. case JSOCKERR_broken_pipe: return str.append("connection is broken");
  142. case JSOCKERR_graceful_close: return str.append("connection closed other end");
  143. case JSOCKERR_invalid_access_mode: return str.append("invalid access mode");
  144. case JSOCKERR_timeout_expired: return str.append("timeout expired");
  145. case JSOCKERR_port_in_use: return str.append("port in use");
  146. case JSOCKERR_cancel_accept: return str.append("cancel accept");
  147. case JSOCKERR_connectionless_socket: return str.append("connectionless socket");
  148. case JSOCKERR_handle_too_large: return str.append("handle too large");
  149. case JSOCKERR_bad_netaddr: return str.append("bad net addr");
  150. case JSOCKERR_ipv6_not_implemented: return str.append("IPv6 not implemented");
  151. // OS errors
  152. #ifdef _WIN32
  153. case WSAEINTR: return str.append("WSAEINTR(10004) - Interrupted system call.");
  154. case WSAEBADF: return str.append("WSAEBADF(10009) - Bad file number.");
  155. case WSAEACCES: return str.append("WSAEACCES(10013) - Permission denied.");
  156. case WSAEFAULT: return str.append("WSAEFAULT(10014) - Bad address.");
  157. case WSAEINVAL: return str.append("WSAEINVAL(10022) - Invalid argument.");
  158. case WSAEMFILE: return str.append("WSAEMFILE(10024) - Too many open files.");
  159. case WSAEWOULDBLOCK: return str.append("WSAEWOULDBLOCK(10035) - Operation would block.");
  160. case WSAEINPROGRESS: return str.append("WSAEINPROGRESS(10036) - Operation now in progress.");
  161. case WSAEALREADY: return str.append("WSAEALREADY(10037) - Operation already in progress.");
  162. case WSAENOTSOCK: return str.append("WSAENOTSOCK(10038) - Socket operation on nonsocket.");
  163. case WSAEDESTADDRREQ: return str.append("WSAEDESTADDRREQ(10039) - Destination address required.");
  164. case WSAEMSGSIZE: return str.append("WSAEMSGSIZE(10040) - Message too long.");
  165. case WSAEPROTOTYPE: return str.append("WSAEPROTOTYPE(10041) - Protocol wrong type for socket.");
  166. case WSAENOPROTOOPT: return str.append("WSAENOPROTOOPT(10042) - Protocol not available.");
  167. case WSAEPROTONOSUPPORT: return str.append("WSAEPROTONOSUPPORT(10043) - Protocol not supported.");
  168. case WSAESOCKTNOSUPPORT: return str.append("WSAESOCKTNOSUPPORT(10044) - Socket type not supported.");
  169. case WSAEOPNOTSUPP: return str.append("WSAEOPNOTSUPP(10045) - Operation not supported on socket.");
  170. case WSAEPFNOSUPPORT: return str.append("WSAEPFNOSUPPORT(10046) - Protocol family not supported.");
  171. case WSAEAFNOSUPPORT: return str.append("WSAEAFNOSUPPORT(10047) - Address family not supported by protocol family.");
  172. case WSAEADDRINUSE: return str.append("WSAEADDRINUSE(10048) - Address already in use.");
  173. case WSAEADDRNOTAVAIL: return str.append("WSAEADDRNOTAVAIL(10049) - Cannot assign requested address.");
  174. case WSAENETDOWN: return str.append("WSAENETDOWN(10050) - Network is down.");
  175. case WSAENETUNREACH: return str.append("WSAENETUNREACH(10051) - Network is unreachable.");
  176. case WSAENETRESET: return str.append("WSAENETRESET(10052) - Network dropped connection on reset.");
  177. case WSAECONNABORTED: return str.append("WSAECONNABORTED(10053) - Software caused connection abort.");
  178. case WSAECONNRESET: return str.append("WSAECONNRESET(10054) - Connection reset by peer.");
  179. case WSAENOBUFS: return str.append("WSAENOBUFS(10055) - No buffer space available.");
  180. case WSAEISCONN: return str.append("WSAEISCONN(10056) - Socket is already connected.");
  181. case WSAENOTCONN: return str.append("WSAENOTCONN(10057) - Socket is not connected.");
  182. case WSAESHUTDOWN: return str.append("WSAESHUTDOWN(10058) - Cannot send after socket shutdown.");
  183. case WSAETOOMANYREFS: return str.append("WSAETOOMANYREFS(10059) - Too many references: cannot splice.");
  184. case WSAETIMEDOUT: return str.append("WSAETIMEDOUT(10060) - Connection timed out.");
  185. case WSAECONNREFUSED: return str.append("WSAECONNREFUSED(10061) - Connection refused.");
  186. case WSAELOOP: return str.append("WSAELOOP(10062) - Too many levels of symbolic links.");
  187. case WSAENAMETOOLONG: return str.append("WSAENAMETOOLONG(10063) - File name too long.");
  188. case WSAEHOSTDOWN: return str.append("WSAEHOSTDOWN(10064) - Host is down.");
  189. case WSAEHOSTUNREACH: return str.append("WSAEHOSTUNREACH(10065) - No route to host.");
  190. case WSASYSNOTREADY: return str.append("WSASYSNOTREADY(10091) - The network subsystem is unusable.");
  191. case WSAVERNOTSUPPORTED: return str.append("WSAVERNOTSUPPORTED(10092) - The Windows Sockets DLL cannot support this application.");
  192. case WSANOTINITIALISED: return str.append("WSANOTINITIALISED(10093) - Winsock not initialized.");
  193. case WSAEDISCON: return str.append("WSAEDISCON(10101) - Disconnect.");
  194. case WSAHOST_NOT_FOUND: return str.append("WSAHOST_NOT_FOUND(11001) - Host not found.");
  195. case WSATRY_AGAIN: return str.append("WSATRY_AGAIN(11002) - Nonauthoritative host not found.");
  196. case WSANO_RECOVERY: return str.append("WSANO_RECOVERY(11003) - Nonrecoverable error.");
  197. case WSANO_DATA: return str.append("WSANO_DATA(11004) - Valid name, no data record of requested type.");
  198. #else
  199. case ENOTSOCK: return str.append("ENOTSOCK - Socket operation on non-socket ");
  200. case EDESTADDRREQ: return str.append("EDESTADDRREQ - Destination address required ");
  201. case EMSGSIZE: return str.append("EMSGSIZE - Message too long ");
  202. case EPROTOTYPE: return str.append("EPROTOTYPE - Protocol wrong type for socket ");
  203. case ENOPROTOOPT: return str.append("ENOPROTOOPT - Protocol not available ");
  204. case EPROTONOSUPPORT: return str.append("EPROTONOSUPPORT - Protocol not supported ");
  205. case ESOCKTNOSUPPORT: return str.append("ESOCKTNOSUPPORT - Socket type not supported ");
  206. case EOPNOTSUPP: return str.append("EOPNOTSUPP - Operation not supported on socket ");
  207. case EPFNOSUPPORT: return str.append("EPFNOSUPPORT - Protocol family not supported ");
  208. case EAFNOSUPPORT: return str.append("EAFNOSUPPORT - Address family not supported by protocol family ");
  209. case EADDRINUSE: return str.append("EADDRINUSE - Address already in use ");
  210. case EADDRNOTAVAIL: return str.append("EADDRNOTAVAIL - Can't assign requested address ");
  211. case ENETDOWN: return str.append("ENETDOWN - Network is down ");
  212. case ENETUNREACH: return str.append("ENETUNREACH - Network is unreachable ");
  213. case ENETRESET: return str.append("ENETRESET - Network dropped connection because of reset ");
  214. case ECONNABORTED: return str.append("ECONNABORTED - Software caused connection abort ");
  215. case ECONNRESET: return str.append("ECONNRESET - Connection reset by peer ");
  216. case ENOBUFS: return str.append("ENOBUFS - No buffer space available ");
  217. case EISCONN: return str.append("EISCONN - Socket is already connected ");
  218. case ENOTCONN: return str.append("ENOTCONN - Socket is not connected ");
  219. case ESHUTDOWN: return str.append("ESHUTDOWN - Can't send after socket shutdown ");
  220. case ETOOMANYREFS: return str.append("ETOOMANYREFS - Too many references: can't splice ");
  221. case ETIMEDOUT: return str.append("ETIMEDOUT - Connection timed out ");
  222. case ECONNREFUSED: return str.append("ECONNREFUSED - Connection refused ");
  223. case EHOSTDOWN: return str.append("EHOSTDOWN - Host is down ");
  224. case EHOSTUNREACH: return str.append("EHOSTUNREACH - No route to host ");
  225. case EWOULDBLOCK: return str.append("EWOULDBLOCK - operation already in progress");
  226. case EINPROGRESS: return str.append("EINPROGRESS - operation now in progress ");
  227. #endif
  228. }
  229. IException *ose = makeOsException(err);
  230. ose->errorMessage(str);
  231. ose->Release();
  232. return str;
  233. }
  234. StringBuffer & errorMessage(StringBuffer &str) const
  235. {
  236. if (msg)
  237. return geterrormessage(errcode,str).append('\n').append(msg);
  238. return geterrormessage(errcode,str);
  239. }
  240. MessageAudience errorAudience() const
  241. {
  242. switch (errcode) {
  243. case JSOCKERR_port_in_use:
  244. return MSGAUD_operator;
  245. }
  246. return MSGAUD_user;
  247. }
  248. private:
  249. int errcode;
  250. char *msg;
  251. };
  252. IJSOCK_Exception *IPv6NotImplementedException(const char *filename,unsigned lineno)
  253. {
  254. StringBuffer msg;
  255. msg.appendf("%s(%d)",filename,lineno);
  256. return new SocketException(JSOCKERR_ipv6_not_implemented,msg.str());
  257. }
  258. struct MCASTREQ
  259. {
  260. struct in_addr imr_multiaddr; /* multicast group to join */
  261. struct in_addr imr_interface; /* interface to join on */
  262. MCASTREQ(const char *mcip)
  263. {
  264. imr_multiaddr.s_addr = inet_addr(mcip);
  265. imr_interface.s_addr = htonl(INADDR_ANY);
  266. }
  267. };
  268. #ifdef __APPLE__
  269. #ifndef MSG_NOSIGNAL
  270. #define MSG_NOSIGNAL 0x4000
  271. #endif
  272. #endif
  273. #if defined( _WIN32)
  274. #define T_SOCKET SOCKET
  275. #define T_FD_SET fd_set
  276. #define XFD_SETSIZE FD_SETSIZE
  277. //Following are defined in more modern headers
  278. #define XFD_ZERO(s) FD_ZERO(s)
  279. #define SEND_FLAGS 0
  280. #define CHECKSOCKRANGE(s)
  281. #define _USE_SELECT // Windows bug 309411 - WSAPoll does not report failed connections - wont fix
  282. // #define poll(a, b, c) WSAPoll((a), (b), (c))
  283. #elif defined(__FreeBSD__) || defined(__APPLE__)
  284. #define XFD_SETSIZE FD_SETSIZE
  285. #define T_FD_SET fd_set
  286. #define XFD_ZERO(s) FD_ZERO(s)
  287. #define T_SOCKET int
  288. #define SEND_FLAGS (MSG_NOSIGNAL)
  289. #define CHECKSOCKRANGE(s)
  290. #else
  291. #define XFD_SETSIZE 32768
  292. struct xfd_set { __fd_mask fds_bits[XFD_SETSIZE / __NFDBITS]; }; // define our own
  293. // linux 64 bit
  294. #ifdef __linux__
  295. #ifdef __64BIT__
  296. #undef __FDMASK
  297. #define __FDMASK(d) (1UL << ((d) % __NFDBITS))
  298. #undef __FDELT
  299. #define __FDELT(d) ((d) / __NFDBITS)
  300. #undef __FD_SET
  301. #define __FD_SET(d, s) (__FDS_BITS (s)[__FDELT(d)] |= __FDMASK(d))
  302. #undef __FD_ISSET
  303. #define __FD_ISSET(d, s) ((__FDS_BITS (s)[__FDELT(d)] & __FDMASK(d)) != 0)
  304. #endif
  305. #define CHECKSOCKRANGE(s) { if (s>=XFD_SETSIZE) THROWJSOCKEXCEPTION2(JSOCKERR_handle_too_large); }
  306. #endif
  307. // end 64 bit
  308. #define T_FD_SET xfd_set
  309. #define XFD_ZERO(s) memset(s,0,sizeof(xfd_set))
  310. #define T_SOCKET int
  311. #define SEND_FLAGS (MSG_NOSIGNAL)
  312. #endif
  313. #ifdef CENTRAL_NODE_RANDOM_DELAY
  314. static SocketEndpointArray CentralNodeArray;
  315. #endif
  316. enum SOCKETMODE { sm_tcp_server, sm_tcp, sm_udp_server, sm_udp, sm_multicast_server, sm_multicast};
  317. #define BADSOCKERR(err) ((err==JSE_BADF)||(err==JSE_NOTSOCK))
  318. #ifdef POLLRDHUP
  319. # define POLLINX (POLLIN | POLLRDHUP)
  320. #else
  321. # define POLLINX POLLIN
  322. #endif
  323. #ifdef _HAS_EPOLL_SUPPORT
  324. # ifdef EPOLLRDHUP
  325. # define EPOLLINX (EPOLLIN | EPOLLRDHUP)
  326. # else
  327. # define EPOLLINX EPOLLIN
  328. # endif
  329. #endif
  330. class CSocket: public ISocket, public CInterface
  331. {
  332. public:
  333. IMPLEMENT_IINTERFACE;
  334. static CriticalSection crit;
  335. protected:
  336. friend class CSocketConnectWait;
  337. enum { ss_open, ss_shutdown, ss_close, ss_pre_open } state;
  338. T_SOCKET sock;
  339. char* hostname; // host address
  340. unsigned short hostport; // host port
  341. unsigned short localPort;
  342. SOCKETMODE sockmode;
  343. IpAddress targetip;
  344. SocketEndpoint returnep; // set by set_return_addr
  345. MCASTREQ * mcastreq;
  346. size32_t nextblocksize;
  347. unsigned blockflags = BF_ASYNC_TRANSFER;
  348. unsigned blocktimeoutms = WAIT_FOREVER;
  349. bool owned;
  350. enum {accept_not_cancelled, accept_cancel_pending, accept_cancelled} accept_cancel_state;
  351. bool in_accept;
  352. bool nonblocking;
  353. bool nagling;
  354. static unsigned connectingcount;
  355. #ifdef USERECVSEM
  356. static Semaphore receiveblocksem;
  357. bool receiveblocksemowned; // owned by this socket
  358. #endif
  359. #ifdef _TRACE
  360. char * tracename;
  361. #endif
  362. public:
  363. void open(int listen_queue_size,bool reuseports=false);
  364. bool connect_timeout( unsigned timeout, bool noexception);
  365. void connect_wait( unsigned timems);
  366. void udpconnect();
  367. void read(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read,unsigned timeoutsecs);
  368. void readtms(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read, unsigned timedelaysecs);
  369. void read(void* buf, size32_t size);
  370. size32_t write(void const* buf, size32_t size);
  371. size32_t writetms(void const* buf, size32_t size, unsigned timeoutms=WAIT_FOREVER);
  372. size32_t write_multiple(unsigned num,void const**buf, size32_t *size);
  373. size32_t udp_write_to(const SocketEndpoint &ep,void const* buf, size32_t size);
  374. void close();
  375. void errclose();
  376. bool connectionless() { return (sockmode!=sm_tcp)&&(sockmode!=sm_tcp_server); }
  377. void shutdown(unsigned mode=SHUTDOWN_READWRITE);
  378. void shutdownNoThrow(unsigned mode);
  379. ISocket* accept(bool allowcancel, SocketEndpoint *peerEp=nullptr);
  380. int wait_read(unsigned timeout);
  381. int logPollError(unsigned revents, const char *rwstr);
  382. int wait_write(unsigned timeout);
  383. int name(char *name,size32_t namemax);
  384. int peer_name(char *name,size32_t namemax);
  385. SocketEndpoint &getPeerEndpoint(SocketEndpoint &ep);
  386. IpAddress & getPeerAddress(IpAddress &addr);
  387. SocketEndpoint &getEndpoint(SocketEndpoint &ep) const override;
  388. void set_return_addr(int port,const char *name); // sets returnep
  389. void cancel_accept();
  390. size32_t get_max_send_size();
  391. bool set_nonblock(bool on=true);
  392. bool set_nagle(bool on);
  393. void set_linger(int lingersecs);
  394. void set_keep_alive(bool set);
  395. void logConnectionInfo(unsigned timeoutms, unsigned conn_mstime);
  396. virtual void set_inherit(bool inherit=false);
  397. virtual bool check_connection();
  398. virtual bool isSecure() const override;
  399. // Block functions
  400. void set_block_mode(unsigned flags,size32_t recsize=0,unsigned timeoutms=0);
  401. bool send_block(const void *blk,size32_t sz);
  402. size32_t receive_block_size();
  403. size32_t receive_block(void *blk,size32_t sz);
  404. size32_t get_send_buffer_size();
  405. void set_send_buffer_size(size32_t sz);
  406. bool join_multicast_group(SocketEndpoint &ep); // for udp multicast
  407. bool leave_multicast_group(SocketEndpoint &ep); // for udp multicast
  408. void set_ttl(unsigned _ttl);
  409. size32_t get_receive_buffer_size();
  410. void set_receive_buffer_size(size32_t sz);
  411. size32_t avail_read();
  412. int pre_connect(bool block);
  413. int post_connect();
  414. void setTraceName(const char * prefix, const char * name);
  415. void setTraceName();
  416. CSocket(const SocketEndpoint &_ep,SOCKETMODE smode,const char *name);
  417. CSocket(T_SOCKET new_sock,SOCKETMODE smode,bool _owned);
  418. virtual ~CSocket();
  419. virtual unsigned OShandle() const
  420. {
  421. return (unsigned)sock;
  422. }
  423. virtual bool isValid() const
  424. {
  425. return sock != INVALID_SOCKET;
  426. }
  427. private:
  428. int closesock()
  429. {
  430. if (sock!=INVALID_SOCKET) {
  431. T_SOCKET s = sock;
  432. sock = INVALID_SOCKET;
  433. STATS.activesockets--;
  434. #ifdef SOCKTRACE
  435. PROGLOG("SOCKTRACE: Closing socket %x %d (%p)", s, s, this);
  436. #endif
  437. #ifdef _WIN32
  438. return ::closesocket(s);
  439. #else
  440. ::shutdown(s, SHUT_WR);
  441. return ::close(s);
  442. #endif
  443. }
  444. else
  445. return 0;
  446. }
  447. };
  448. CriticalSection CSocket::crit;
  449. unsigned CSocket::connectingcount=0;
  450. #ifdef USERECVSEM
  451. Semaphore CSocket::receiveblocksem(2);
  452. #endif
  453. #ifdef _WIN32
  454. class win_socket_library
  455. {
  456. static bool initdone; // to prevent dependancy probs very early on (e.g. jlog)
  457. public:
  458. win_socket_library() { init(); }
  459. bool init()
  460. {
  461. if (initdone)
  462. return true;
  463. WSADATA wsa;
  464. if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
  465. if (WSAStartup(MAKEWORD(1, 1), &wsa) != 0) {
  466. MessageBox(NULL,"Failed to initialize windows sockets","JLib Socket Error",MB_OK);
  467. return false;
  468. }
  469. }
  470. initdone = true;
  471. return true;
  472. }
  473. ~win_socket_library()
  474. {
  475. WSACleanup();
  476. }
  477. };
  478. bool win_socket_library::initdone = false;
  479. static win_socket_library ws32_lib;
  480. #define ERRNO() WSAGetLastError()
  481. #define JSE_ADDRINUSE WSAEADDRINUSE
  482. #define JSE_CONNRESET WSAECONNRESET
  483. #define JSE_CONNABORTED WSAECONNABORTED
  484. #define JSE_NOTCONN WSAENOTCONN
  485. #define JSE_WOULDBLOCK WSAEWOULDBLOCK
  486. #define JSE_INPROGRESS WSAEINPROGRESS
  487. #define JSE_NETUNREACH WSAENETUNREACH
  488. #define JSE_NOTSOCK WSAENOTSOCK
  489. #define JSE_TIMEDOUT WSAETIMEDOUT
  490. #define JSE_CONNREFUSED WSAECONNREFUSED
  491. #define JSE_BADF WSAEBADF
  492. #define JSE_INTR WSAEINTR
  493. struct j_sockaddr_in6 {
  494. short sin6_family; /* AF_INET6 */
  495. u_short sin6_port; /* Transport level port number */
  496. u_long sin6_flowinfo; /* IPv6 flow information */
  497. struct in_addr6 sin6_addr; /* IPv6 address */
  498. u_long sin6_scope_id; /* set of interfaces for a scope */
  499. };
  500. typedef union {
  501. struct sockaddr sa;
  502. struct j_sockaddr_in6 sin6;
  503. struct sockaddr_in sin;
  504. } J_SOCKADDR;
  505. #define DEFINE_SOCKADDR(name) J_SOCKADDR name; memset(&name,0,sizeof(J_SOCKADDR))
  506. static int _inet_pton(int af, const char* src, void* dst)
  507. {
  508. DEFINE_SOCKADDR(u);
  509. int address_length;
  510. switch (af) {
  511. case AF_INET:
  512. u.sin.sin_family = AF_INET;
  513. address_length = sizeof (u.sin);
  514. break;
  515. case AF_INET6:
  516. u.sin6.sin6_family = AF_INET6;
  517. address_length = sizeof (u.sin6);
  518. break;
  519. default:
  520. #ifdef EAFNOSUPPORT
  521. errno = EAFNOSUPPORT;
  522. #else
  523. errno = 52;
  524. #endif
  525. return -1;
  526. }
  527. ws32_lib.init();
  528. int ret = WSAStringToAddress ((LPTSTR) src, af, NULL, &u.sa, &address_length);
  529. if (ret == 0) {
  530. switch (af) {
  531. case AF_INET:
  532. memcpy (dst, &u.sin.sin_addr, sizeof (struct in_addr));
  533. break;
  534. case AF_INET6:
  535. memcpy (dst, &u.sin6.sin6_addr, sizeof (u.sin6.sin6_addr));
  536. break;
  537. }
  538. return 1;
  539. }
  540. errno = WSAGetLastError();
  541. // PROGLOG("errno = %d",errno);
  542. return 0;
  543. }
  544. static const char * _inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
  545. {
  546. /* struct sockaddr can't accomodate struct sockaddr_in6. */
  547. DEFINE_SOCKADDR(u);
  548. DWORD dstlen = cnt;
  549. size_t srcsize;
  550. memset(&u,0,sizeof(u));
  551. switch (af) {
  552. case AF_INET:
  553. u.sin.sin_family = AF_INET;
  554. u.sin.sin_addr = *(struct in_addr *) src;
  555. srcsize = sizeof (u.sin);
  556. break;
  557. case AF_INET6:
  558. u.sin6.sin6_family = AF_INET6;
  559. memcpy(&u.sin6.sin6_addr,src,sizeof(in_addr6));
  560. srcsize = sizeof (u.sin6);
  561. break;
  562. default:
  563. return NULL;
  564. }
  565. ws32_lib.init();
  566. if (WSAAddressToString (&u.sa, srcsize, NULL, dst, &dstlen) != 0) {
  567. errno = WSAGetLastError();
  568. return NULL;
  569. }
  570. return (const char *) dst;
  571. }
  572. int inet_aton (const char *name, struct in_addr *addr)
  573. {
  574. addr->s_addr = inet_addr (name);
  575. return (addr->s_addr == (u_long)-1)?1:0; // 255.255.255.255 has had it here
  576. }
  577. #else
  578. #define JSE_ADDRINUSE EADDRINUSE
  579. #define JSE_CONNRESET ECONNRESET
  580. #define JSE_CONNABORTED ECONNABORTED
  581. #define JSE_NOTCONN ENOTCONN
  582. #define JSE_WOULDBLOCK EWOULDBLOCK
  583. #define JSE_INPROGRESS EINPROGRESS
  584. #define JSE_NETUNREACH ENETUNREACH
  585. #define JSE_NOTSOCK ENOTSOCK
  586. #define JSE_TIMEDOUT ETIMEDOUT
  587. #define JSE_CONNREFUSED ECONNREFUSED
  588. #define JSE_BADF EBADF
  589. #define _inet_ntop inet_ntop
  590. #define _inet_pton inet_pton
  591. #define in_addr6 in6_addr
  592. typedef union {
  593. struct sockaddr sa;
  594. struct sockaddr_in6 sin6;
  595. struct sockaddr_in sin;
  596. } J_SOCKADDR;
  597. #define DEFINE_SOCKADDR(name) J_SOCKADDR name; memset(&name,0,sizeof(J_SOCKADDR))
  598. #define JSE_INTR EINTR
  599. #define ERRNO() (errno)
  600. #ifndef INADDR_NONE
  601. #define INADDR_NONE (-1)
  602. #endif
  603. #endif
  604. #ifndef INET6_ADDRSTRLEN
  605. #define INET6_ADDRSTRLEN 65
  606. #endif
  607. extern jlib_decl void throwJSocketException(int jsockErr)
  608. {
  609. THROWJSOCKEXCEPTION2(jsockErr);
  610. }
  611. extern jlib_decl IJSOCK_Exception* createJSocketException(int jsockErr, const char *_msg)
  612. {
  613. return new SocketException(jsockErr, _msg);
  614. }
  615. inline void LogErr(unsigned err,unsigned ref,const char *info,unsigned lineno,const char *tracename)
  616. {
  617. if (err)
  618. {
  619. PROGLOG("jsocket(%d,%d)%s%s err = %d%s%s",ref,lineno,
  620. (info&&*info)?" ":"",(info&&*info)?info:"",err,
  621. (tracename&&*tracename)?" : ":"",(tracename&&*tracename)?tracename:"");
  622. #ifdef _TRACELINKCLOSED
  623. if ((JSE_NOTCONN == err) || (JSE_CONNRESET == err) || (JSE_CONNABORTED == err))
  624. {
  625. PROGLOG("Socket not connected, stack:");
  626. PrintStackReport();
  627. }
  628. #endif
  629. }
  630. }
  631. inline socklen_t setSockAddr(J_SOCKADDR &u, const IpAddress &ip,unsigned short port)
  632. {
  633. if (!IP6preferred) {
  634. if (ip.getNetAddress(sizeof(in_addr),&u.sin.sin_addr)==sizeof(in_addr)) {
  635. u.sin.sin_family = AF_INET;
  636. u.sin.sin_port = htons(port);
  637. return sizeof(u.sin);
  638. }
  639. }
  640. if (IP4only)
  641. IPV6_NOT_IMPLEMENTED();
  642. ip.getNetAddress(sizeof(in_addr6),&u.sin6.sin6_addr);
  643. u.sin6.sin6_family = AF_INET6;
  644. u.sin6.sin6_port = htons(port);
  645. return sizeof(u.sin6);
  646. }
  647. inline socklen_t setSockAddrAny(J_SOCKADDR &u, unsigned short port)
  648. {
  649. if (IP6preferred) {
  650. #ifdef _WIN32
  651. IN6ADDR_SETANY((PSOCKADDR_IN6)&u.sin6.sin6_addr);
  652. #else
  653. memcpy(&u.sin6.sin6_addr,&in6addr_any,sizeof(in_addr6));
  654. #endif
  655. u.sin6.sin6_family= AF_INET6;
  656. u.sin6.sin6_port = htons(port);
  657. return sizeof(u.sin6);
  658. }
  659. u.sin.sin_addr.s_addr = htonl(INADDR_ANY);
  660. u.sin.sin_family= AF_INET;
  661. u.sin.sin_port = htons(port);
  662. return sizeof(u.sin);
  663. }
  664. inline void getSockAddrEndpoint(const J_SOCKADDR &u, socklen_t ul, SocketEndpoint &ep)
  665. {
  666. if (ul==sizeof(u.sin)) {
  667. ep.setNetAddress(sizeof(in_addr),&u.sin.sin_addr);
  668. ep.port = htons(u.sin.sin_port);
  669. }
  670. else {
  671. ep.setNetAddress(sizeof(in_addr6),&u.sin6.sin6_addr);
  672. ep.port = htons(u.sin6.sin6_port);
  673. }
  674. }
  675. /* might need fcntl(F_SETFL), or ioctl(FIONBIO) */
  676. /* Posix.1g says fcntl */
  677. #if defined(O_NONBLOCK)
  678. bool CSocket::set_nonblock(bool on)
  679. {
  680. int flags = fcntl(sock, F_GETFL, 0);
  681. if (flags == -1)
  682. return nonblocking;
  683. if (on)
  684. flags |= O_NONBLOCK;
  685. else
  686. flags &= ~O_NONBLOCK;
  687. if (fcntl(sock, F_SETFL, flags)==0) {
  688. bool wasNonBlocking = nonblocking;
  689. nonblocking = on;
  690. return wasNonBlocking;
  691. }
  692. return nonblocking;
  693. }
  694. #else
  695. bool CSocket::set_nonblock(bool on)
  696. {
  697. #ifdef _WIN32
  698. u_long yes = on?1:0;
  699. if (ioctlsocket(sock, FIONBIO, &yes)==0) {
  700. #else
  701. int yes = on?1:0;
  702. if (ioctl(sock, FIONBIO, &yes)==0) {
  703. #endif
  704. bool wasNonBlocking = nonblocking;
  705. nonblocking = on;
  706. return wasNonBlocking;
  707. }
  708. return nonblocking;
  709. }
  710. #endif
  711. bool CSocket::set_nagle(bool on)
  712. {
  713. bool ret = nagling;
  714. nagling = on;
  715. int enabled = !on;
  716. if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&enabled, sizeof(enabled)) != 0) {
  717. nagling = !on;
  718. }
  719. return ret;
  720. }
  721. void CSocket::set_inherit(bool inherit)
  722. {
  723. #ifndef _WIN32
  724. long flag = fcntl(sock, F_GETFD);
  725. if(inherit)
  726. flag &= ~FD_CLOEXEC;
  727. else
  728. flag |= FD_CLOEXEC;
  729. fcntl(sock, F_SETFD, flag);
  730. #endif
  731. }
  732. size32_t CSocket::avail_read()
  733. {
  734. #ifdef _WIN32
  735. u_long avail;
  736. if (ioctlsocket(sock, FIONREAD, &avail)==0)
  737. #else
  738. int avail;
  739. if (ioctl(sock, FIONREAD, &avail)==0)
  740. #endif
  741. return (size32_t)avail;
  742. int err = ERRNO();
  743. LOGERR2(err,1,"avail_read");
  744. return 0;
  745. }
  746. #define PRE_CONN_UNREACH_ELIM 100
  747. int CSocket::pre_connect (bool block)
  748. {
  749. if (NULL == hostname || '\0' == (*hostname))
  750. {
  751. StringBuffer err;
  752. err.appendf("CSocket::pre_connect - Invalid/missing host IP address raised in : %s, line %d",sanitizeSourceFile(__FILE__), __LINE__);
  753. IJSOCK_Exception *e = new SocketException(JSOCKERR_bad_netaddr,err.str());
  754. throw e;
  755. }
  756. DEFINE_SOCKADDR(u);
  757. if (targetip.isNull()) {
  758. set_return_addr(hostport,hostname);
  759. targetip.ipset(returnep);
  760. }
  761. socklen_t ul = setSockAddr(u,targetip,hostport);
  762. sock = ::socket(u.sa.sa_family, SOCK_STREAM, targetip.isIp4()?0:PF_INET6);
  763. owned = true;
  764. state = ss_pre_open; // will be set to open by post_connect
  765. if (sock == INVALID_SOCKET) {
  766. int err = ERRNO();
  767. THROWJSOCKEXCEPTION(err);
  768. }
  769. STATS.activesockets++;
  770. int err = 0;
  771. set_nonblock(!block);
  772. int rc = ::connect(sock, &u.sa, ul);
  773. if (rc==SOCKET_ERROR) {
  774. err = ERRNO();
  775. if ((err != JSE_INPROGRESS)&&(err != JSE_WOULDBLOCK)&&(err != JSE_TIMEDOUT)&&(err!=JSE_CONNREFUSED)) { // handled by caller
  776. if (err != JSE_NETUNREACH) {
  777. pre_conn_unreach_cnt.store(0);
  778. LOGERR2(err,1,"pre_connect");
  779. } else {
  780. int ecnt = pre_conn_unreach_cnt.load();
  781. if (ecnt <= PRE_CONN_UNREACH_ELIM) {
  782. pre_conn_unreach_cnt.fetch_add(1);
  783. LOGERR2(err,1,"pre_connect network unreachable");
  784. }
  785. }
  786. } else
  787. pre_conn_unreach_cnt.store(0);
  788. } else
  789. pre_conn_unreach_cnt.store(0);
  790. #ifdef SOCKTRACE
  791. PROGLOG("SOCKTRACE: pre-connected socket%s %x %d (%p) err=%d", block?"(block)":"", sock, sock, this, err);
  792. #endif
  793. return err;
  794. }
  795. int CSocket::post_connect ()
  796. {
  797. set_nonblock(false);
  798. int err = 0;
  799. socklen_t errlen = sizeof(err);
  800. int rc = getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); // check for error
  801. if ((rc!=0)&&!err)
  802. err = ERRNO(); // some implementations of getsockopt duff
  803. if (err==0) {
  804. nagling = true;
  805. set_nagle(false);
  806. state = ss_open;
  807. SocketEndpoint ep;
  808. localPort = getEndpoint(ep).port;
  809. }
  810. else if ((err!=JSE_TIMEDOUT)&&(err!=JSE_CONNREFUSED)) // handled by caller
  811. LOGERR2(err,1,"post_connect");
  812. return err;
  813. }
  814. void CSocket::open(int listen_queue_size,bool reuseports)
  815. {
  816. // If listen_queue_size==0 then bind port to address but
  817. // do not actually listen() for accepting connections.
  818. // This is used when a unique IP:port is needed for MP client
  819. // INode/IGroup internals, but client never actually accepts connections.
  820. if (IP6preferred)
  821. sock = ::socket(AF_INET6, connectionless()?SOCK_DGRAM:SOCK_STREAM, PF_INET6);
  822. else
  823. sock = ::socket(AF_INET, connectionless()?SOCK_DGRAM:SOCK_STREAM, 0);
  824. if (sock == INVALID_SOCKET) {
  825. THROWJSOCKEXCEPTION(ERRNO());
  826. }
  827. STATS.activesockets++;
  828. #ifdef SOCKTRACE
  829. PROGLOG("SOCKTRACE: opened socket %x %d (%p)", sock,sock,this);
  830. #endif
  831. if ((hostport==0)&&(sockmode==sm_udp)) {
  832. state = ss_open;
  833. #ifdef SOCKTRACE
  834. PROGLOG("SOCKTRACE: opened socket return udp");
  835. #endif
  836. set_inherit(false);
  837. return;
  838. }
  839. #ifndef _WIN32
  840. reuseports = true; // for some reason linux requires reuse ports
  841. #endif
  842. if (reuseports && listen_queue_size) {
  843. int on = 1;
  844. setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
  845. }
  846. DEFINE_SOCKADDR(u);
  847. socklen_t ul;
  848. if (hostname) {
  849. if (targetip.isNull()) {
  850. set_return_addr(hostport,hostname);
  851. targetip.ipset(returnep);
  852. }
  853. ul = setSockAddr(u,targetip,hostport);
  854. }
  855. else
  856. ul = setSockAddrAny(u,hostport);
  857. int saverr;
  858. if (::bind(sock, &u.sa, ul) != 0) {
  859. saverr = ERRNO();
  860. if (saverr==JSE_ADDRINUSE) { // don't log as error (some usages probe ports)
  861. ErrPortInUse:
  862. closesock();
  863. char msg[1024];
  864. sprintf(msg,"Target: %s, port = %d, Raised in: %s, line %d",tracename,(int)hostport,sanitizeSourceFile(__FILE__), __LINE__);
  865. IJSOCK_Exception *e = new SocketException(JSOCKERR_port_in_use,msg);
  866. throw e;
  867. }
  868. else {
  869. closesock();
  870. THROWJSOCKEXCEPTION(saverr);
  871. }
  872. }
  873. if (!connectionless() && listen_queue_size) {
  874. if (::listen(sock, listen_queue_size) != 0) {
  875. saverr = ERRNO();
  876. if (saverr==JSE_ADDRINUSE)
  877. goto ErrPortInUse;
  878. closesock();
  879. THROWJSOCKEXCEPTION(saverr);
  880. }
  881. }
  882. if (mcastreq) {
  883. if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char*)mcastreq, sizeof(*mcastreq))!=0) {
  884. saverr = ERRNO();
  885. closesock();
  886. THROWJSOCKEXCEPTION(saverr);
  887. }
  888. }
  889. state = ss_open;
  890. #ifdef SOCKTRACE
  891. PROGLOG("SOCKTRACE: opened socket return");
  892. #endif
  893. set_inherit(false);
  894. }
  895. ISocket* CSocket::accept(bool allowcancel, SocketEndpoint *peerEp)
  896. {
  897. if ((accept_cancel_state!=accept_not_cancelled) && allowcancel) {
  898. accept_cancel_state=accept_cancelled;
  899. return NULL;
  900. }
  901. if (state != ss_open) {
  902. IERRLOG("invalid accept, state = %d",(int)state);
  903. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  904. }
  905. if (connectionless()) {
  906. THROWJSOCKEXCEPTION(JSOCKERR_connectionless_socket);
  907. }
  908. DEFINE_SOCKADDR(peerSockAddr); // used if peerIp
  909. socklen_t peerSockAddrLen = sizeof(peerSockAddr);
  910. T_SOCKET newsock;
  911. for (;;) {
  912. in_accept = true;
  913. newsock = (sock!=INVALID_SOCKET)?::accept(sock, &peerSockAddr.sa, &peerSockAddrLen):INVALID_SOCKET;
  914. in_accept = false;
  915. #ifdef SOCKTRACE
  916. PROGLOG("SOCKTRACE: accept created socket %x %d (%p)", newsock,newsock,this);
  917. #endif
  918. if (newsock!=INVALID_SOCKET) {
  919. if ((sock==INVALID_SOCKET)||(accept_cancel_state==accept_cancel_pending)) {
  920. ::close(newsock);
  921. newsock=INVALID_SOCKET;
  922. }
  923. else {
  924. accept_cancel_state = accept_not_cancelled;
  925. break;
  926. }
  927. }
  928. int saverr;
  929. saverr = ERRNO();
  930. if ((sock==INVALID_SOCKET)||(accept_cancel_state==accept_cancel_pending)) {
  931. accept_cancel_state = accept_cancelled;
  932. if (allowcancel)
  933. return NULL;
  934. THROWJSOCKEXCEPTION(JSOCKERR_cancel_accept);
  935. }
  936. if (saverr != JSE_INTR) {
  937. accept_cancel_state = accept_not_cancelled;
  938. THROWJSOCKEXCEPTION(saverr);
  939. }
  940. }
  941. if (state != ss_open) {
  942. accept_cancel_state = accept_cancelled;
  943. if (allowcancel)
  944. return NULL;
  945. THROWJSOCKEXCEPTION(JSOCKERR_cancel_accept);
  946. }
  947. if (peerEp)
  948. getSockAddrEndpoint(peerSockAddr, peerSockAddrLen, *peerEp);
  949. CSocket *ret = new CSocket(newsock,sm_tcp,true);
  950. ret->set_inherit(false);
  951. return ret;
  952. }
  953. void CSocket::set_linger(int lingertime)
  954. {
  955. struct linger l;
  956. l.l_onoff = (lingertime>=0)?1:0;
  957. l.l_linger = (lingertime>=0)?lingertime:0;
  958. if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(l)) != 0) {
  959. IWARNLOG("Linger not set");
  960. }
  961. }
  962. void CSocket::set_keep_alive(bool set)
  963. {
  964. int on=set?1:0;
  965. if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on)) != 0) {
  966. IWARNLOG("KeepAlive not set");
  967. }
  968. }
  969. int CSocket::name(char *retname,size32_t namemax)
  970. {
  971. SocketEndpoint ep;
  972. getEndpoint(ep);
  973. if (retname && namemax)
  974. {
  975. StringBuffer s;
  976. ep.getIpText(s);
  977. if (namemax-1<s.length())
  978. s.setLength(namemax-1);
  979. memcpy(retname,s.str(),s.length()+1);
  980. }
  981. return ep.port;
  982. }
  983. int CSocket::peer_name(char *retname,size32_t namemax)
  984. {
  985. // should not raise exceptions
  986. int ret = 0;
  987. if (!retname)
  988. namemax = 0;
  989. if (namemax)
  990. retname[0] = 0;
  991. if (state != ss_open) {
  992. return -1; // don't log as used to test socket
  993. }
  994. StringBuffer s;
  995. if (sockmode==sm_udp_server) { // udp server
  996. returnep.getIpText(s);
  997. ret = returnep.port;
  998. }
  999. else {
  1000. DEFINE_SOCKADDR(u);
  1001. socklen_t ul = sizeof(u);
  1002. if (::getpeername(sock,&u.sa, &ul)<0)
  1003. return -1; // don't log as used to test socket
  1004. SocketEndpoint ep;
  1005. getSockAddrEndpoint(u,ul,ep);
  1006. ep.getIpText(s);
  1007. ret = ep.port;
  1008. }
  1009. if (namemax>1) {
  1010. if (namemax-1<s.length())
  1011. s.setLength(namemax-1);
  1012. memcpy(retname,s.str(),s.length()+1);
  1013. }
  1014. return ret;
  1015. }
  1016. SocketEndpoint &CSocket::getPeerEndpoint(SocketEndpoint &ep)
  1017. {
  1018. if (state != ss_open) {
  1019. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  1020. }
  1021. StringBuffer s;
  1022. if (sockmode==sm_udp_server) { // udp server
  1023. ep.set(returnep);
  1024. }
  1025. else {
  1026. DEFINE_SOCKADDR(u);
  1027. socklen_t ul = sizeof(u);
  1028. if (::getpeername(sock,&u.sa, &ul)<0) {
  1029. DBGLOG("getpeername failed %d",ERRNO());
  1030. ep.set(NULL, 0);
  1031. }
  1032. else
  1033. getSockAddrEndpoint(u,ul,ep);
  1034. }
  1035. return ep;
  1036. }
  1037. IpAddress & CSocket::getPeerAddress(IpAddress &addr)
  1038. {
  1039. SocketEndpoint ep;
  1040. getPeerEndpoint(ep);
  1041. addr = ep;
  1042. return addr;
  1043. }
  1044. void CSocket::set_return_addr(int port,const char *retname)
  1045. {
  1046. if (!returnep.ipset(retname)) {
  1047. IJSOCK_Exception *e = new SocketException(JSOCKERR_bad_address); // don't use THROWJSOCKEXCEPTION here
  1048. throw e;
  1049. }
  1050. returnep.port = port;
  1051. }
  1052. SocketEndpoint &CSocket::getEndpoint(SocketEndpoint &ep) const
  1053. {
  1054. if (state != ss_open) {
  1055. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  1056. }
  1057. DEFINE_SOCKADDR(u);
  1058. socklen_t ul = sizeof(u);
  1059. if (::getsockname(sock,&u.sa, &ul)<0) {
  1060. THROWJSOCKEXCEPTION(ERRNO());
  1061. }
  1062. getSockAddrEndpoint(u,ul,ep);
  1063. return ep;
  1064. }
  1065. void CSocket::cancel_accept()
  1066. {
  1067. if (connectionless()) {
  1068. THROWJSOCKEXCEPTION(JSOCKERR_connectionless_socket);
  1069. }
  1070. #ifdef SOCKTRACE
  1071. PROGLOG("SOCKTRACE: Cancel accept socket %x %d (%p)", sock, sock, this);
  1072. #endif
  1073. if (!in_accept) {
  1074. accept_cancel_state = accept_cancelled;
  1075. shutdown();
  1076. errclose();
  1077. return;
  1078. }
  1079. accept_cancel_state = accept_cancel_pending;
  1080. errclose(); // this should cause accept to terminate (not supported on all linux though)
  1081. #ifdef _WIN32
  1082. for (unsigned i=0;i<5;i++) { // windows closes on different lower priority thread
  1083. Sleep(i);
  1084. if (accept_cancel_state==accept_cancelled)
  1085. return;
  1086. }
  1087. #else
  1088. Sleep(0);
  1089. if (accept_cancel_state==accept_cancelled)
  1090. return;
  1091. #endif
  1092. // Wakeup listener using a connection
  1093. SocketEndpoint ep(hostport,queryHostIP());
  1094. Owned<CSocket> sock = new CSocket(ep,sm_tcp,NULL);
  1095. try {
  1096. sock->connect_timeout(100,true);
  1097. }
  1098. catch (IJSOCK_Exception *e) {
  1099. EXCLOG(e,"CSocket::cancel_eccept");
  1100. e->Release();
  1101. }
  1102. }
  1103. // ================================================================================
  1104. // connect versions
  1105. ISocket* ISocket::connect( const SocketEndpoint &ep )
  1106. {
  1107. // general connect
  1108. return ISocket::connect_wait(ep,DEFAULT_CONNECT_TIME);
  1109. }
  1110. inline void refused_sleep(CTimeMon &tm, unsigned &refuseddelay)
  1111. {
  1112. unsigned remaining;
  1113. if (!tm.timedout(&remaining)) {
  1114. if (refuseddelay<remaining/4) {
  1115. Sleep(refuseddelay);
  1116. if (refuseddelay<CONNECT_TIMEOUT_REFUSED_WAIT/2)
  1117. refuseddelay *=2;
  1118. else
  1119. refuseddelay = CONNECT_TIMEOUT_REFUSED_WAIT;
  1120. }
  1121. else
  1122. Sleep(remaining/4); // towards end of timeout approach gradually
  1123. }
  1124. }
  1125. bool CSocket::connect_timeout( unsigned timeout, bool noexception)
  1126. {
  1127. // simple connect with timeout (no fancy stuff!)
  1128. unsigned startt = usTick();
  1129. CTimeMon tm(timeout);
  1130. unsigned remaining;
  1131. unsigned refuseddelay = 1;
  1132. int err;
  1133. while (!tm.timedout(&remaining))
  1134. {
  1135. err = pre_connect(false);
  1136. if ((err == JSE_INPROGRESS)||(err == JSE_WOULDBLOCK))
  1137. {
  1138. #ifdef _USE_SELECT
  1139. T_FD_SET fds;
  1140. struct timeval tv;
  1141. CHECKSOCKRANGE(sock);
  1142. XFD_ZERO(&fds);
  1143. FD_SET((unsigned)sock, &fds);
  1144. T_FD_SET except;
  1145. XFD_ZERO(&except);
  1146. FD_SET((unsigned)sock, &except);
  1147. tv.tv_sec = remaining / 1000;
  1148. tv.tv_usec = (remaining % 1000)*1000;
  1149. int rc = ::select( sock + 1, NULL, (fd_set *)&fds, (fd_set *)&except, &tv );
  1150. #else
  1151. struct pollfd fds[1];
  1152. fds[0].fd = sock;
  1153. fds[0].events = POLLOUT;
  1154. fds[0].revents = 0;
  1155. int rc = ::poll(fds, 1, remaining);
  1156. #endif
  1157. if (rc>0)
  1158. {
  1159. // select/poll succeeded - return error from socket (0 if connected)
  1160. socklen_t errlen = sizeof(err);
  1161. rc = getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); // check for error
  1162. if ((rc!=0)&&!err)
  1163. err = ERRNO(); // some implementations of getsockopt duff
  1164. if (err) // probably ECONNREFUSED but treat all errors same
  1165. refused_sleep(tm,refuseddelay);
  1166. }
  1167. else if (rc<0)
  1168. {
  1169. err = ERRNO();
  1170. if (err != JSE_INTR)
  1171. {
  1172. LOGERR2(err,2,"::select/poll");
  1173. errclose();
  1174. break;
  1175. }
  1176. }
  1177. }
  1178. else if (err)
  1179. refused_sleep(tm, refuseddelay); // this stops becoming cpu bound
  1180. if (err==0)
  1181. {
  1182. err = post_connect();
  1183. if (err==0)
  1184. {
  1185. STATS.connects++;
  1186. STATS.connecttime+=usTick()-startt;
  1187. #ifdef _TRACE
  1188. setTraceName();
  1189. #endif
  1190. #ifdef SOCKTRACE
  1191. unsigned conn_mstime = (usTick() - startt) / 1000;
  1192. logConnectionInfo(timeout, conn_mstime);
  1193. #endif
  1194. return true;
  1195. }
  1196. }
  1197. errclose();
  1198. }
  1199. #ifdef SOCKTRACE
  1200. PROGLOG("connect_timeout: failed %d",err);
  1201. #endif
  1202. STATS.failedconnects++;
  1203. STATS.failedconnecttime+=usTick()-startt;
  1204. if (!noexception)
  1205. THROWJSOCKEXCEPTION(JSOCKERR_connection_failed);
  1206. return false;
  1207. }
  1208. ISocket* ISocket::connect_timeout(const SocketEndpoint &ep,unsigned timeout)
  1209. {
  1210. if (ep.isNull()||(ep.port==0))
  1211. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  1212. Owned<CSocket> sock = new CSocket(ep,sm_tcp,NULL);
  1213. sock->connect_timeout(timeout,false);
  1214. return sock.getClear();
  1215. }
  1216. #define POLLTIME 50
  1217. void CSocket::connect_wait(unsigned timems)
  1218. {
  1219. // simple connect with timeout (no fancy stuff!)
  1220. unsigned startt = usTick();
  1221. CTimeMon tm(timems);
  1222. bool exit = false;
  1223. int err;
  1224. unsigned refuseddelay = 1;
  1225. while (!exit) {
  1226. #ifdef CENTRAL_NODE_RANDOM_DELAY
  1227. ForEachItemIn(cn,CentralNodeArray) {
  1228. const SocketEndpoint &ep=CentralNodeArray.item(cn);
  1229. if (ep.ipequals(targetip)) {
  1230. unsigned sleeptime = getRandom() % 1000;
  1231. StringBuffer s;
  1232. ep.getIpText(s);
  1233. DBGLOG("Connection to central node %s - sleeping %d milliseconds", s.str(), sleeptime);
  1234. Sleep(sleeptime);
  1235. break;
  1236. }
  1237. }
  1238. #endif
  1239. unsigned remaining;
  1240. exit = tm.timedout(&remaining);
  1241. bool blockselect = exit; // if last time round block
  1242. {
  1243. CriticalBlock block(crit);
  1244. if (++connectingcount>4)
  1245. blockselect = true;
  1246. }
  1247. err = pre_connect(blockselect);
  1248. if (blockselect)
  1249. {
  1250. if (err&&!exit)
  1251. refused_sleep(tm,refuseddelay); // probably ECONNREFUSED but treat all errors same
  1252. }
  1253. else
  1254. {
  1255. unsigned timeoutms = (exit||(remaining<10000))?10000:remaining;
  1256. #ifndef BLOCK_POLLED_SINGLE_CONNECTS
  1257. unsigned polltime = 1;
  1258. #endif
  1259. while (!blockselect && ((err == JSE_INPROGRESS)||(err == JSE_WOULDBLOCK)))
  1260. {
  1261. #ifdef _USE_SELECT
  1262. T_FD_SET fds;
  1263. struct timeval tv;
  1264. CHECKSOCKRANGE(sock);
  1265. XFD_ZERO(&fds);
  1266. FD_SET((unsigned)sock, &fds);
  1267. T_FD_SET except;
  1268. XFD_ZERO(&except);
  1269. FD_SET((unsigned)sock, &except);
  1270. #ifdef BLOCK_POLLED_SINGLE_CONNECTS
  1271. tv.tv_sec = timeoutms / 1000;
  1272. tv.tv_usec = (timeoutms % 1000)*1000;
  1273. #else
  1274. tv.tv_sec = 0;
  1275. tv.tv_usec = 0;
  1276. #endif
  1277. int rc = ::select( sock + 1, NULL, (fd_set *)&fds, (fd_set *)&except, &tv );
  1278. #else
  1279. struct pollfd fds[1];
  1280. fds[0].fd = sock;
  1281. fds[0].events = POLLOUT;
  1282. fds[0].revents = 0;
  1283. #ifdef BLOCK_POLLED_SINGLE_CONNECTS
  1284. int pollTimeOut = timeoutms;
  1285. #else
  1286. int pollTimeOut = 0;
  1287. #endif
  1288. int rc = ::poll(fds, 1, pollTimeOut);
  1289. #endif
  1290. if (rc>0)
  1291. {
  1292. // select/poll succeeded - return error from socket (0 if connected)
  1293. socklen_t errlen = sizeof(err);
  1294. rc = getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); // check for error
  1295. if ((rc!=0)&&!err)
  1296. err = ERRNO(); // some implementations of getsockopt duff
  1297. if (err)
  1298. refused_sleep(tm,refuseddelay); // probably ECONNREFUSED but treat all errors same
  1299. break;
  1300. }
  1301. if (rc<0)
  1302. {
  1303. err = ERRNO();
  1304. if (err != JSE_INTR)
  1305. {
  1306. LOGERR2(err,2,"::select/poll");
  1307. break;
  1308. }
  1309. }
  1310. if (!timeoutms)
  1311. {
  1312. #ifdef SOCKTRACE
  1313. PROGLOG("connecttimeout: timed out");
  1314. #endif
  1315. err = -1;
  1316. break;
  1317. }
  1318. #ifdef BLOCK_POLLED_SINGLE_CONNECTS
  1319. break;
  1320. #else
  1321. if (timeoutms<polltime)
  1322. polltime = timeoutms;
  1323. Sleep(polltime); // sleeps 1-50ms (to let other threads run)
  1324. timeoutms -= polltime;
  1325. if (polltime>POLLTIME/2)
  1326. polltime = POLLTIME;
  1327. else
  1328. polltime *= 2;
  1329. #endif
  1330. }
  1331. }
  1332. {
  1333. CriticalBlock block(crit);
  1334. --connectingcount;
  1335. }
  1336. if (err==0)
  1337. {
  1338. err = post_connect();
  1339. if (err==0)
  1340. {
  1341. STATS.connects++;
  1342. STATS.connecttime+=usTick()-startt;
  1343. #ifdef _TRACE
  1344. setTraceName();
  1345. #endif
  1346. #ifdef SOCKTRACE
  1347. unsigned conn_mstime = (usTick() - startt) / 1000;
  1348. logConnectionInfo(timems, conn_mstime);
  1349. #endif
  1350. return;
  1351. }
  1352. }
  1353. errclose();
  1354. }
  1355. #ifdef SOCKTRACE
  1356. PROGLOG("connect_wait: failed %d",err);
  1357. #endif
  1358. STATS.failedconnects++;
  1359. STATS.failedconnecttime+=usTick()-startt;
  1360. THROWJSOCKEXCEPTION(JSOCKERR_connection_failed);
  1361. }
  1362. void CSocket::setTraceName(const char * prefix, const char * name)
  1363. {
  1364. #ifdef _TRACE
  1365. StringBuffer peer;
  1366. peer.append(prefix);
  1367. if (state == ss_open)
  1368. peer.append(":").append(localPort).append(" -> ");
  1369. peer.append(name?name:"(NULL)");
  1370. peer.append(":").append(hostport);
  1371. if (sock != INVALID_SOCKET)
  1372. peer.append(" (").append(sock).append(")");
  1373. free(tracename);
  1374. tracename = peer.detach();
  1375. #endif
  1376. }
  1377. void CSocket::setTraceName()
  1378. {
  1379. #ifdef _TRACE
  1380. setTraceName("C!", hostname);
  1381. #endif
  1382. }
  1383. ISocket* ISocket::connect_wait( const SocketEndpoint &ep, unsigned timems)
  1384. {
  1385. if (ep.isNull()||(ep.port==0))
  1386. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  1387. Owned<CSocket> sock = new CSocket(ep,sm_tcp,NULL);
  1388. sock->connect_wait(timems);
  1389. return sock.getClear();
  1390. }
  1391. void CSocket::udpconnect()
  1392. {
  1393. DEFINE_SOCKADDR(u);
  1394. if (targetip.isNull()) {
  1395. set_return_addr(hostport,hostname);
  1396. targetip.ipset(returnep);
  1397. }
  1398. socklen_t ul = setSockAddr(u,targetip,hostport);
  1399. sock = ::socket(u.sa.sa_family, SOCK_DGRAM, targetip.isIp4()?0:PF_INET6);
  1400. #ifdef SOCKTRACE
  1401. PROGLOG("SOCKTRACE: udp connected socket %x %d (%p)", sock, sock, this);
  1402. #endif
  1403. STATS.activesockets++;
  1404. if (sock == INVALID_SOCKET) {
  1405. THROWJSOCKEXCEPTION(ERRNO());
  1406. }
  1407. int res = ::connect(sock, &u.sa, ul);
  1408. if (res != 0) { // works for UDP
  1409. closesock();
  1410. THROWJSOCKEXCEPTION(JSOCKERR_connection_failed);
  1411. }
  1412. nagling = false; // means nothing for UDP
  1413. state = ss_open;
  1414. #ifdef _TRACE
  1415. setTraceName();
  1416. #endif
  1417. }
  1418. int CSocket::logPollError(unsigned revents, const char *rwstr)
  1419. {
  1420. // return appropriate errno as caller will probably throw/log it
  1421. int retcode = EINVAL;
  1422. if (revents & POLLERR)
  1423. {
  1424. StringBuffer errStr;
  1425. errStr.appendf("%s POLLERR %u l:%d r:%s:%d", rwstr, sock, localPort, (hostname?hostname:"NULL"), hostport);
  1426. int serror = 0;
  1427. socklen_t serrlen = sizeof(serror);
  1428. int srtn = getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&serror, &serrlen);
  1429. if (srtn != 0)
  1430. serror = ERRNO();
  1431. LOGERR2(serror,2,errStr.str());
  1432. retcode = serror;
  1433. }
  1434. else if (revents & POLLNVAL)
  1435. {
  1436. // These are typically expected - when closing a socket in order to interrupt a thread that waits on it, for example
  1437. }
  1438. else
  1439. {
  1440. StringBuffer errStr;
  1441. errStr.appendf("%s unknown poll() revents: 0x%x", rwstr, revents);
  1442. LOGERR2(999,4,errStr.str());
  1443. }
  1444. return retcode;
  1445. }
  1446. int CSocket::wait_read(unsigned timeout)
  1447. {
  1448. int ret = 0;
  1449. int retrycount = 100;
  1450. while (sock!=INVALID_SOCKET)
  1451. {
  1452. #ifdef _USE_SELECT
  1453. T_FD_SET fds;
  1454. CHECKSOCKRANGE(sock);
  1455. XFD_ZERO(&fds);
  1456. FD_SET((unsigned)sock, &fds);
  1457. if (timeout==WAIT_FOREVER)
  1458. {
  1459. ret = ::select( sock + 1, (fd_set *)&fds, NULL, NULL, NULL );
  1460. }
  1461. else
  1462. {
  1463. struct timeval tv;
  1464. tv.tv_sec = timeout / 1000;
  1465. tv.tv_usec = (timeout % 1000)*1000;
  1466. ret = ::select( sock + 1, (fd_set *)&fds, NULL, NULL, &tv );
  1467. }
  1468. #else
  1469. struct pollfd fds[1];
  1470. fds[0].fd = sock;
  1471. fds[0].events = POLLINX;
  1472. fds[0].revents = 0;
  1473. ret = ::poll(fds, 1, timeout);
  1474. #endif
  1475. if (ret == SOCKET_ERROR)
  1476. { // error
  1477. int err = ERRNO();
  1478. if (err!=JSE_INTR)
  1479. { // else retry (should adjust time but for our usage don't think it matters that much)
  1480. LOGERR2(err,1,"wait_read");
  1481. break;
  1482. }
  1483. else
  1484. {
  1485. if (retrycount-- <= 0)
  1486. break;
  1487. }
  1488. }
  1489. else if (ret == 0)
  1490. { // timeout, no error (timeout can be 0 for a fast check)
  1491. break;
  1492. }
  1493. else
  1494. { // ret > 0 - ready or error
  1495. // if returning < 0 also set errno as caller will probably throw/log it
  1496. #ifdef _USE_SELECT
  1497. if (!FD_ISSET(sock, &fds))
  1498. {
  1499. LOGERR2(998,7,"wait_read");
  1500. errno = EBADF;
  1501. ret = -1;
  1502. }
  1503. #else
  1504. if ( (fds[0].revents & (POLLERR | POLLNVAL)) || (!(fds[0].revents & (POLLINX | POLLHUP))) )
  1505. {
  1506. errno = logPollError(fds[0].revents, "wait_read");
  1507. ret = -1;
  1508. }
  1509. else
  1510. {
  1511. // cannot error out on POLLRDHUP or POLLHUP as there can still be data to read
  1512. // POLLIN | POLLRDHUP | POLLHUP ok
  1513. break;
  1514. }
  1515. #endif
  1516. break;
  1517. }
  1518. }
  1519. return ret;
  1520. }
  1521. int CSocket::wait_write(unsigned timeout)
  1522. {
  1523. int ret = 0;
  1524. while (sock!=INVALID_SOCKET) {
  1525. #ifdef _USE_SELECT
  1526. T_FD_SET fds;
  1527. CHECKSOCKRANGE(sock);
  1528. XFD_ZERO(&fds);
  1529. FD_SET((unsigned)sock, &fds);
  1530. if (timeout==WAIT_FOREVER) {
  1531. ret = ::select( sock + 1, NULL, (fd_set *)&fds, NULL, NULL );
  1532. }
  1533. else {
  1534. struct timeval tv;
  1535. tv.tv_sec = timeout / 1000;
  1536. tv.tv_usec = (timeout % 1000)*1000;
  1537. ret = ::select( sock + 1, NULL, (fd_set *)&fds, NULL, &tv );
  1538. }
  1539. #else
  1540. struct pollfd fds[1];
  1541. fds[0].fd = sock;
  1542. fds[0].events = POLLOUT;
  1543. fds[0].revents = 0;
  1544. ret = ::poll(fds, 1, timeout);
  1545. #endif
  1546. if (ret==SOCKET_ERROR)
  1547. {
  1548. int err = ERRNO();
  1549. if (err!=JSE_INTR)
  1550. { // else retry (should adjust time but for our usage don't think it matters that much)
  1551. LOGERR2(err,1,"wait_write");
  1552. break;
  1553. }
  1554. }
  1555. else if (ret == 0)
  1556. { // timeout
  1557. break;
  1558. }
  1559. else
  1560. { // ret > 0 - ready or error
  1561. // if returning < 0 also set errno as caller will probably throw/log it
  1562. #ifdef _USE_SELECT
  1563. if (!FD_ISSET(sock, &fds))
  1564. {
  1565. LOGERR2(998,7,"wait_write");
  1566. errno = EBADF;
  1567. ret = -1;
  1568. }
  1569. #else
  1570. if ( (fds[0].revents & (POLLERR | POLLNVAL)) || (!(fds[0].revents & (POLLOUT | POLLHUP))) )
  1571. {
  1572. errno = logPollError(fds[0].revents, "wait_write");
  1573. ret = -1;
  1574. }
  1575. else if (fds[0].revents & POLLHUP)
  1576. {
  1577. LOGERR2(998,5,"wait_write POLLHUP");
  1578. errno = EPIPE;
  1579. ret = -1;
  1580. }
  1581. else
  1582. {
  1583. // POLLOUT ok
  1584. break;
  1585. }
  1586. #endif
  1587. break;
  1588. }
  1589. }
  1590. return ret;
  1591. }
  1592. void CSocket::readtms(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read,
  1593. unsigned timeoutms)
  1594. {
  1595. if (timeoutms == WAIT_FOREVER) {
  1596. read(buf,min_size, max_size, size_read,WAIT_FOREVER);
  1597. return;
  1598. }
  1599. unsigned startt=usTick();
  1600. size_read = 0;
  1601. if (state != ss_open) {
  1602. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  1603. }
  1604. unsigned start;
  1605. unsigned timeleft;
  1606. start = msTick();
  1607. timeleft = timeoutms;
  1608. do {
  1609. int rc = wait_read(timeleft);
  1610. if (rc < 0) {
  1611. THROWJSOCKEXCEPTION(ERRNO());
  1612. }
  1613. if (rc == 0) {
  1614. THROWJSOCKEXCEPTION(JSOCKERR_timeout_expired);
  1615. }
  1616. unsigned elapsed = (msTick()-start);
  1617. if (elapsed<timeoutms)
  1618. timeleft = timeoutms-elapsed;
  1619. else
  1620. timeleft = 0;
  1621. unsigned retrycount=100;
  1622. EintrRetry:
  1623. if (sockmode==sm_udp_server) { // udp server
  1624. DEFINE_SOCKADDR(u);
  1625. socklen_t ul=sizeof(u);
  1626. rc = recvfrom(sock, (char*)buf + size_read, max_size - size_read, 0, &u.sa,&ul);
  1627. getSockAddrEndpoint(u,ul,returnep);
  1628. }
  1629. else {
  1630. rc = recv(sock, (char*)buf + size_read, max_size - size_read, 0);
  1631. }
  1632. if (rc < 0) {
  1633. int err = ERRNO();
  1634. if (BADSOCKERR(err)) {
  1635. // don't think this should happen but convert to same as shutdown while investigation
  1636. LOGERR2(err,1,"Socket closed during read");
  1637. rc = 0;
  1638. }
  1639. else if ((err==JSE_INTR)&&(retrycount--!=0)) {
  1640. LOGERR2(err,1,"EINTR retrying");
  1641. goto EintrRetry;
  1642. }
  1643. else {
  1644. VStringBuffer errMsg("readtms(timeoutms=%d)", timeoutms);
  1645. LOGERR2(err,1,errMsg.str());
  1646. if ((err==JSE_CONNRESET)||(err==JSE_INTR)||(err==JSE_CONNABORTED)) {
  1647. errclose();
  1648. err = JSOCKERR_broken_pipe;
  1649. }
  1650. THROWJSOCKEXCEPTION(err);
  1651. }
  1652. }
  1653. if (rc == 0) {
  1654. state = ss_shutdown;
  1655. if (min_size==0)
  1656. break; // if min_read is 0 return 0 if socket closed
  1657. THROWJSOCKEXCEPTION(JSOCKERR_graceful_close);
  1658. }
  1659. size_read += rc;
  1660. } while (size_read < min_size);
  1661. STATS.reads++;
  1662. STATS.readsize += size_read;
  1663. STATS.readtime+=usTick()-startt;
  1664. }
  1665. void CSocket::read(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read,
  1666. unsigned timeoutsecs)
  1667. {
  1668. unsigned startt=usTick();
  1669. size_read = 0;
  1670. unsigned start = 0;
  1671. unsigned timeleft = 0;
  1672. if (state != ss_open) {
  1673. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  1674. }
  1675. if (timeoutsecs != WAIT_FOREVER) {
  1676. start = (unsigned)time(NULL);
  1677. timeleft = timeoutsecs;
  1678. }
  1679. do {
  1680. int rc;
  1681. if (timeoutsecs != WAIT_FOREVER) {
  1682. rc = wait_read(timeleft*1000);
  1683. if (rc < 0) {
  1684. THROWJSOCKEXCEPTION(ERRNO());
  1685. }
  1686. if (rc == 0) {
  1687. THROWJSOCKEXCEPTION(JSOCKERR_timeout_expired);
  1688. }
  1689. unsigned elapsed = ((unsigned)time(NULL))-start;
  1690. if (elapsed<timeoutsecs)
  1691. timeleft = timeoutsecs-elapsed;
  1692. else
  1693. timeleft = 0;
  1694. }
  1695. unsigned retrycount=100;
  1696. EintrRetry:
  1697. if (sockmode==sm_udp_server) { // udp server
  1698. DEFINE_SOCKADDR(u);
  1699. socklen_t ul=sizeof(u.sin);
  1700. rc = recvfrom(sock, (char*)buf + size_read, max_size - size_read, 0, &u.sa,&ul);
  1701. getSockAddrEndpoint(u,ul,returnep);
  1702. }
  1703. else {
  1704. rc = recv(sock, (char*)buf + size_read, max_size - size_read, 0);
  1705. }
  1706. if (rc < 0) {
  1707. int err = ERRNO();
  1708. if (BADSOCKERR(err)) {
  1709. // don't think this should happen but convert to same as shutdown while investigation
  1710. LOGERR2(err,3,"Socket closed during read");
  1711. rc = 0;
  1712. }
  1713. else if ((err==JSE_INTR)&&(retrycount--!=0)) {
  1714. if (sock==INVALID_SOCKET)
  1715. rc = 0; // convert an EINTR after closed to a graceful close
  1716. else {
  1717. LOGERR2(err,3,"EINTR retrying");
  1718. goto EintrRetry;
  1719. }
  1720. }
  1721. else {
  1722. LOGERR2(err,3,"read");
  1723. if ((err==JSE_CONNRESET)||(err==JSE_INTR)||(err==JSE_CONNABORTED)) {
  1724. errclose();
  1725. err = JSOCKERR_broken_pipe;
  1726. }
  1727. THROWJSOCKEXCEPTION(err);
  1728. }
  1729. }
  1730. if (rc == 0) {
  1731. state = ss_shutdown;
  1732. if (min_size==0)
  1733. break; // if min_read is 0 return 0 if socket closed
  1734. THROWJSOCKEXCEPTION(JSOCKERR_graceful_close);
  1735. }
  1736. size_read += rc;
  1737. } while (size_read < min_size);
  1738. STATS.reads++;
  1739. STATS.readsize += size_read;
  1740. STATS.readtime+=usTick()-startt;
  1741. }
  1742. void CSocket::read(void* buf, size32_t size)
  1743. {
  1744. if (!size)
  1745. return;
  1746. unsigned startt=usTick();
  1747. size32_t size_read=size;
  1748. if (state != ss_open) {
  1749. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  1750. }
  1751. do {
  1752. unsigned retrycount=100;
  1753. EintrRetry:
  1754. int rc;
  1755. if (sockmode==sm_udp_server) { // udp server
  1756. DEFINE_SOCKADDR(u);
  1757. socklen_t ul=sizeof(u.sin);
  1758. rc = recvfrom(sock, (char*)buf, size, 0, &u.sa,&ul);
  1759. getSockAddrEndpoint(u,ul,returnep);
  1760. }
  1761. else {
  1762. rc = recv(sock, (char*)buf, size, 0);
  1763. }
  1764. if (rc < 0) {
  1765. int err = ERRNO();
  1766. if (BADSOCKERR(err)) {
  1767. // don't think this should happen but convert to same as shutdown while investigation
  1768. LOGERR2(err,5,"Socket closed during read");
  1769. rc = 0;
  1770. }
  1771. else if ((err==JSE_INTR)&&(retrycount--!=0)) {
  1772. LOGERR2(err,5,"EINTR retrying");
  1773. goto EintrRetry;
  1774. }
  1775. else {
  1776. LOGERR2(err,5,"read");
  1777. if ((err==JSE_CONNRESET)||(err==JSE_INTR)||(err==JSE_CONNABORTED)) {
  1778. errclose();
  1779. err = JSOCKERR_broken_pipe;
  1780. }
  1781. THROWJSOCKEXCEPTION(err);
  1782. }
  1783. }
  1784. if (rc == 0) {
  1785. state = ss_shutdown;
  1786. THROWJSOCKEXCEPTION(JSOCKERR_graceful_close);
  1787. }
  1788. buf = (char*)buf + rc;
  1789. size -= rc;
  1790. } while (size != 0);
  1791. STATS.reads++;
  1792. STATS.readsize += size_read;
  1793. STATS.readtime+=usTick()-startt;
  1794. }
  1795. size32_t CSocket::write(void const* buf, size32_t size)
  1796. {
  1797. if (size==0)
  1798. return 0;
  1799. unsigned startt=usTick();
  1800. size32_t size_writ = size;
  1801. if (state != ss_open) {
  1802. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  1803. }
  1804. size32_t res=0;
  1805. do {
  1806. unsigned retrycount=100;
  1807. EintrRetry:
  1808. int rc;
  1809. if (sockmode==sm_udp_server) { // udp server
  1810. DEFINE_SOCKADDR(u);
  1811. socklen_t ul = setSockAddr(u,returnep,returnep.port);
  1812. rc = sendto(sock, (char*)buf, size, 0, &u.sa, ul);
  1813. }
  1814. #ifdef SIMULATE_LOST_UDP_PACKETS
  1815. else if (sockmode==sm_udp && size <= 24 && dropCounter++ >= dropThreshold)
  1816. {
  1817. DBGLOG("Drop size %d cmd %d", size, *(unsigned short *)buf);
  1818. dropCounter = 0;
  1819. rc = size;
  1820. }
  1821. #endif
  1822. else {
  1823. rc = send(sock, (char*)buf, size, SEND_FLAGS);
  1824. }
  1825. if (rc < 0) {
  1826. int err=ERRNO();
  1827. if (BADSOCKERR(err)) {
  1828. LOGERR2(err,7,"Socket closed during write");
  1829. rc = 0;
  1830. }
  1831. else if ((err==JSE_INTR)&&(retrycount--!=0)) {
  1832. LOGERR2(err,7,"EINTR retrying");
  1833. goto EintrRetry;
  1834. }
  1835. else {
  1836. if (((sockmode==sm_multicast)||(sockmode==sm_udp))&&(err==JSE_CONNREFUSED))
  1837. break; // ignore
  1838. LOGERR2(err,7,"write");
  1839. if ((err==JSE_CONNRESET)||(err==JSE_INTR)||(err==JSE_CONNABORTED)
  1840. #ifndef _WIN32
  1841. ||(err==EPIPE)||(err==JSE_TIMEDOUT) // linux can raise these on broken pipe
  1842. #endif
  1843. ) {
  1844. errclose();
  1845. err = JSOCKERR_broken_pipe;
  1846. }
  1847. if ((err == JSE_WOULDBLOCK) && nonblocking)
  1848. break;
  1849. THROWJSOCKEXCEPTION(err);
  1850. }
  1851. }
  1852. res += rc;
  1853. if (rc == 0) {
  1854. state = ss_shutdown;
  1855. THROWJSOCKEXCEPTION(JSOCKERR_graceful_close);
  1856. }
  1857. if (nonblocking)
  1858. break;
  1859. buf = (char*)buf + rc;
  1860. size -= rc;
  1861. } while (size != 0);
  1862. STATS.writes++;
  1863. STATS.writesize += size_writ;
  1864. STATS.writetime+=usTick()-startt;
  1865. return res;
  1866. }
  1867. size32_t CSocket::writetms(void const* buf, size32_t size, unsigned timeoutms)
  1868. {
  1869. if (size==0)
  1870. return 0;
  1871. if (state != ss_open)
  1872. {
  1873. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  1874. }
  1875. if (timeoutms == WAIT_FOREVER)
  1876. return write(buf, size);
  1877. const char *p = (const char *)buf;
  1878. unsigned start, elapsed;
  1879. start = msTick();
  1880. elapsed = 0;
  1881. size32_t nwritten = 0;
  1882. size32_t nleft = size;
  1883. unsigned rollover = 0;
  1884. bool prevblock = set_nonblock(true);
  1885. while ( (nwritten < size) && (elapsed <= timeoutms) )
  1886. {
  1887. size32_t amnt = write(p,nleft);
  1888. // can nonblock mode write() return -1 ?
  1889. if ( (amnt == 0) || (amnt == (size32_t)-1) )
  1890. {
  1891. if (++rollover >= 20)
  1892. {
  1893. rollover = 0;
  1894. Sleep(20);
  1895. }
  1896. }
  1897. else
  1898. {
  1899. nwritten += amnt;
  1900. nleft -= amnt;
  1901. p += amnt;
  1902. }
  1903. elapsed = msTick() - start;
  1904. }
  1905. set_nonblock(prevblock);
  1906. if (nwritten < size)
  1907. {
  1908. IERRLOG("writetms timed out; timeout: %u, nwritten: %u, size: %u", timeoutms, nwritten, size);
  1909. THROWJSOCKEXCEPTION(JSOCKERR_timeout_expired);
  1910. }
  1911. return nwritten;
  1912. }
  1913. bool CSocket::check_connection()
  1914. {
  1915. if (state != ss_open)
  1916. return false;
  1917. // This routine is for TCP stream sockets.
  1918. // It is the callers responsibility to ensure this is called
  1919. // in a thread-safe manner, while no other threads are reading.
  1920. // wait_read() returns = 0 - socket ok atm
  1921. // returns < 0 - error, assume closed
  1922. // returns > 0 - recv() to check for eof
  1923. int rc = wait_read(0);
  1924. if (rc == 0)
  1925. return true;
  1926. else if (rc < 0)
  1927. return false;
  1928. int retrycount = 100;
  1929. char buffer;
  1930. EintrRecv:
  1931. rc = recv(sock, &buffer, sizeof(buffer), MSG_PEEK);
  1932. // recv() returns = 0 - socket eof (closed)
  1933. // returns < 0 - error, assume closed
  1934. // returns > 0 - socket ok atm
  1935. if (rc == 0)
  1936. return false;
  1937. else if (rc < 0)
  1938. {
  1939. int err=ERRNO();
  1940. if ((err==JSE_INTR)&&(retrycount--!=0))
  1941. {
  1942. LOGERR2(err,7,"recv EINTR retrying");
  1943. goto EintrRecv;
  1944. }
  1945. else
  1946. return false;
  1947. }
  1948. return true;
  1949. }
  1950. size32_t CSocket::udp_write_to(const SocketEndpoint &ep, void const* buf, size32_t size)
  1951. {
  1952. if (size==0)
  1953. return 0;
  1954. unsigned startt=usTick();
  1955. if (state != ss_open) {
  1956. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  1957. }
  1958. size32_t res=0;
  1959. DEFINE_SOCKADDR(u);
  1960. for (;;) {
  1961. socklen_t ul = setSockAddr(u,ep,ep.port);
  1962. int rc = sendto(sock, (char*)buf, size, 0, &u.sa, ul);
  1963. if (rc < 0) {
  1964. int err=ERRNO();
  1965. if (((sockmode==sm_multicast)||(sockmode==sm_udp))&&(err==JSE_CONNREFUSED))
  1966. break; // ignore
  1967. if (err!=JSE_INTR) {
  1968. THROWJSOCKEXCEPTION(err);
  1969. }
  1970. }
  1971. else {
  1972. res = (size32_t)rc;
  1973. break;
  1974. }
  1975. }
  1976. STATS.writes++;
  1977. STATS.writesize += res;
  1978. STATS.writetime+=usTick()-startt;
  1979. return res;
  1980. }
  1981. size32_t CSocket::write_multiple(unsigned num,const void **buf, size32_t *size)
  1982. {
  1983. assertex(sockmode!=sm_udp_server);
  1984. assertex(!nonblocking);
  1985. if (num==1)
  1986. return write(buf[0],size[0]);
  1987. size32_t total = 0;
  1988. unsigned i;
  1989. for (i=0;i<num;i++)
  1990. total += size[i];
  1991. if (total==0)
  1992. return 0;
  1993. unsigned startt=usTick();
  1994. if (state != ss_open) {
  1995. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  1996. }
  1997. size32_t res=0;
  1998. #ifdef _WIN32
  1999. WSABUF *bufs = (WSABUF *)alloca(sizeof(WSABUF)*num);
  2000. for (i=0;i<num;i++) {
  2001. bufs[i].buf = (char *)buf[i];
  2002. bufs[i].len = size[i];
  2003. }
  2004. unsigned retrycount=100;
  2005. EintrRetry:
  2006. DWORD sent;
  2007. if (WSASendTo(sock,bufs,num,&sent,0,NULL,0,NULL,NULL)==SOCKET_ERROR) {
  2008. int err=ERRNO();
  2009. if (BADSOCKERR(err)) {
  2010. LOGERR2(err,8,"Socket closed during write");
  2011. sent = 0;
  2012. }
  2013. else if ((err==JSE_INTR)&&(retrycount--!=0)) {
  2014. LOGERR2(err,8,"EINTR retrying");
  2015. goto EintrRetry;
  2016. }
  2017. else {
  2018. LOGERR2(err,8,"write_multiple");
  2019. if ((err==JSE_CONNRESET)||(err==JSE_INTR)||(err==JSE_CONNABORTED)||(err==JSE_TIMEDOUT)) {
  2020. errclose();
  2021. err = JSOCKERR_broken_pipe;
  2022. }
  2023. THROWJSOCKEXCEPTION(err);
  2024. }
  2025. }
  2026. if (sent == 0) {
  2027. state = ss_shutdown;
  2028. THROWJSOCKEXCEPTION(JSOCKERR_graceful_close);
  2029. }
  2030. res = sent;
  2031. #else
  2032. #ifdef USE_CORK
  2033. if (total>1024) {
  2034. class Copt
  2035. {
  2036. T_SOCKET sock;
  2037. bool nagling;
  2038. public:
  2039. Copt(T_SOCKET _sock,bool _nagling)
  2040. {
  2041. nagling = _nagling;
  2042. int enabled = 1;
  2043. int disabled = 0;
  2044. if (!nagling)
  2045. setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&disabled, sizeof(disabled));
  2046. setsockopt(sock, IPPROTO_TCP, TCP_CORK, (char*)&enabled, sizeof(enabled));
  2047. }
  2048. ~Copt()
  2049. {
  2050. int enabled = 1;
  2051. int disabled = 0;
  2052. setsockopt(sock, IPPROTO_TCP, TCP_CORK, (char*)&disabled, sizeof(disabled));
  2053. if (!nagling)
  2054. setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&enabled, sizeof(enabled));
  2055. }
  2056. } copt(sock,nagling);
  2057. for (i=0;i<num;i++)
  2058. res += write(buf[i],size[i]);
  2059. }
  2060. else {
  2061. byte b[1024];
  2062. byte *p=b;
  2063. for (i=0;i<num;i++) {
  2064. memcpy(p,buf[i],size[i]);
  2065. p += size[i];
  2066. }
  2067. res = write(b,total);
  2068. }
  2069. #else
  2070. // send in equal chunks about 64K
  2071. unsigned n = (total+0xffff)/0x10000;
  2072. size32_t outbufsize = (total+n-1)/n;
  2073. MemoryAttr ma;
  2074. byte *outbuf = (byte *)ma.allocate(outbufsize);
  2075. i = 0;
  2076. size32_t os = 0;
  2077. size32_t left = total;
  2078. byte *b = NULL;
  2079. size32_t s=0;
  2080. for (;;) {
  2081. while (!s&&(i<num)) {
  2082. b = (byte *)buf[i];
  2083. s = size[i];
  2084. i++;
  2085. }
  2086. if ((os==0)&&(s==left)) {
  2087. write(b,s); // go for it
  2088. break;
  2089. }
  2090. else {
  2091. size32_t cpy = outbufsize-os;
  2092. if (cpy>s)
  2093. cpy = s;
  2094. memcpy(outbuf+os,b,cpy);
  2095. os += cpy;
  2096. left -= cpy;
  2097. s -= cpy;
  2098. b += cpy;
  2099. if (left==0) {
  2100. write(outbuf,os);
  2101. break;
  2102. }
  2103. else if (os==outbufsize) {
  2104. write(outbuf,os);
  2105. os = 0;
  2106. }
  2107. }
  2108. }
  2109. #endif
  2110. #endif
  2111. STATS.writes++;
  2112. STATS.writesize += res;
  2113. STATS.writetime+=usTick()-startt;
  2114. return res;
  2115. }
  2116. bool CSocket::send_block(const void *blk,size32_t sz)
  2117. {
  2118. unsigned startt=usTick();
  2119. #ifdef TRACE_SLOW_BLOCK_TRANSFER
  2120. unsigned startt2 = startt;
  2121. unsigned startt3 = startt;
  2122. #endif
  2123. if (blockflags&BF_SYNC_TRANSFER_PULL) {
  2124. size32_t rd;
  2125. bool eof = true;
  2126. readtms(&eof,sizeof(eof),sizeof(eof),rd,blocktimeoutms);
  2127. if (eof)
  2128. return false;
  2129. #ifdef TRACE_SLOW_BLOCK_TRANSFER
  2130. startt2=usTick();
  2131. #endif
  2132. }
  2133. if (!blk||!sz) {
  2134. sz = 0;
  2135. write(&sz,sizeof(sz));
  2136. try {
  2137. bool reply;
  2138. size32_t rd;
  2139. readtms(&reply,sizeof(reply),sizeof(reply),rd,blocktimeoutms);
  2140. }
  2141. catch (IJSOCK_Exception *e) {
  2142. if ((e->errorCode()!=JSOCKERR_broken_pipe)&&(e->errorCode()!=JSOCKERR_graceful_close))
  2143. EXCLOG(e,"CSocket::send_block");
  2144. e->Release();
  2145. }
  2146. return false;
  2147. }
  2148. size32_t rsz=sz;
  2149. _WINREV(rsz);
  2150. write(&rsz,sizeof(rsz));
  2151. if (blockflags&BF_SYNC_TRANSFER_PUSH) {
  2152. #ifdef TRACE_SLOW_BLOCK_TRANSFER
  2153. startt2=usTick();
  2154. #endif
  2155. size32_t rd;
  2156. bool eof = true;
  2157. readtms(&eof,sizeof(eof),sizeof(eof),rd,blocktimeoutms);
  2158. if (eof)
  2159. return false;
  2160. #ifdef TRACE_SLOW_BLOCK_TRANSFER
  2161. startt3=usTick();
  2162. #endif
  2163. }
  2164. write(blk,sz);
  2165. if (blockflags&BF_RELIABLE_TRANSFER) {
  2166. bool isok=false;
  2167. size32_t rd;
  2168. readtms(&isok,sizeof(isok),sizeof(isok),rd,blocktimeoutms);
  2169. if (!isok)
  2170. return false;
  2171. }
  2172. unsigned nowt = usTick();
  2173. unsigned elapsed = nowt-startt;
  2174. STATS.blocksendtime+=elapsed;
  2175. STATS.numblocksends++;
  2176. STATS.blocksendsize+=sz;
  2177. if (elapsed>STATS.longestblocksend) {
  2178. STATS.longestblocksend = elapsed;
  2179. STATS.longestblocksize = sz;
  2180. }
  2181. #ifdef TRACE_SLOW_BLOCK_TRANSFER
  2182. if (elapsed>1000000*60) // over 1min
  2183. IWARNLOG("send_block took %ds to %s (%d,%d,%d)",elapsed/1000000,tracename,startt2-startt,startt3-startt2,nowt-startt3);
  2184. #endif
  2185. return true;
  2186. }
  2187. size32_t CSocket::receive_block_size()
  2188. {
  2189. // assumed always paired with receive_block
  2190. if (nextblocksize) {
  2191. if (blockflags&BF_SYNC_TRANSFER_PULL) {
  2192. bool eof=false;
  2193. write(&eof,sizeof(eof));
  2194. }
  2195. size32_t rd;
  2196. readtms(&nextblocksize,sizeof(nextblocksize),sizeof(nextblocksize),rd,blocktimeoutms);
  2197. _WINREV(nextblocksize);
  2198. if (nextblocksize==0) { // confirm eof
  2199. try {
  2200. bool confirm=true;
  2201. write(&confirm,sizeof(confirm));
  2202. }
  2203. catch (IJSOCK_Exception *e) {
  2204. if ((e->errorCode()!=JSOCKERR_broken_pipe)&&(e->errorCode()!=JSOCKERR_graceful_close))
  2205. EXCLOG(e,"receive_block_size");
  2206. e->Release();
  2207. }
  2208. }
  2209. else if (blockflags&BF_SYNC_TRANSFER_PUSH) { // leaves receiveblocksem clear
  2210. #ifdef USERECVSEM
  2211. CSemProtect semprot; // this will catch exception in write
  2212. while (!semprot.wait(&receiveblocksem,&receiveblocksemowned,60*1000*5))
  2213. IWARNLOG("Receive block stalled");
  2214. #endif
  2215. bool eof=false;
  2216. write(&eof,sizeof(eof));
  2217. #ifdef USERECVSEM
  2218. semprot.clear();
  2219. #endif
  2220. }
  2221. }
  2222. return nextblocksize;
  2223. }
  2224. size32_t CSocket::receive_block(void *blk,size32_t maxsize)
  2225. {
  2226. #ifdef USERECVSEM
  2227. CSemProtect semprot; // this will catch exceptions
  2228. #endif
  2229. size32_t sz = nextblocksize;
  2230. if (sz) {
  2231. if (sz==UINT_MAX) { // need to get size
  2232. if (!blk||!maxsize) {
  2233. if (blockflags&BF_SYNC_TRANSFER_PUSH) { // ignore block size
  2234. size32_t rd;
  2235. readtms(&nextblocksize,sizeof(nextblocksize),sizeof(nextblocksize),rd,blocktimeoutms);
  2236. }
  2237. if (blockflags&(BF_SYNC_TRANSFER_PULL|BF_SYNC_TRANSFER_PUSH)) { // signal eof
  2238. bool eof=true;
  2239. write(&eof,sizeof(eof));
  2240. nextblocksize = 0;
  2241. return 0;
  2242. }
  2243. }
  2244. sz = receive_block_size();
  2245. if (!sz)
  2246. return 0;
  2247. }
  2248. unsigned startt=usTick(); // include sem block but not initial handshake
  2249. #ifdef USERECVSEM
  2250. if (blockflags&BF_SYNC_TRANSFER_PUSH) // read_block_size sets semaphore
  2251. semprot.set(&receiveblocksem,&receiveblocksemowned); // this will reset semaphore on exit
  2252. #endif
  2253. nextblocksize = UINT_MAX;
  2254. size32_t rd;
  2255. if (sz<=maxsize) {
  2256. readtms(blk,sz,sz,rd,blocktimeoutms);
  2257. }
  2258. else { // truncate
  2259. readtms(blk,maxsize,maxsize,rd,blocktimeoutms);
  2260. sz -= maxsize;
  2261. OwnedMalloc<void> tmp = malloc(sz);
  2262. readtms(tmp,sz,sz,rd,blocktimeoutms);
  2263. sz = maxsize;
  2264. }
  2265. if (blockflags&BF_RELIABLE_TRANSFER) {
  2266. bool isok=true;
  2267. write(&isok,sizeof(isok));
  2268. }
  2269. unsigned elapsed = usTick()-startt;
  2270. STATS.blockrecvtime+=elapsed;
  2271. STATS.numblockrecvs++;
  2272. STATS.blockrecvsize+=sz;
  2273. }
  2274. return sz;
  2275. }
  2276. void CSocket::set_block_mode(unsigned flags, size32_t recsize, unsigned _timeoutms)
  2277. {
  2278. blockflags = flags;
  2279. nextblocksize = UINT_MAX;
  2280. blocktimeoutms = _timeoutms?_timeoutms:WAIT_FOREVER;
  2281. }
  2282. void CSocket::shutdown(unsigned mode)
  2283. {
  2284. if (state == ss_open) {
  2285. state = ss_shutdown;
  2286. #ifdef SOCKTRACE
  2287. PROGLOG("SOCKTRACE: shutdown(%d) socket %x %d (%p)", mode, sock, sock, this);
  2288. #endif
  2289. int rc = ::shutdown(sock, mode);
  2290. if (rc != 0) {
  2291. int err=ERRNO();
  2292. if (err==JSE_NOTCONN) {
  2293. #ifdef _TRACELINKCLOSED
  2294. DBGLOG("CSocket::shutdown(%d) failed, socket: %d", mode, sock);
  2295. #endif
  2296. LOGERR2(err,9,"shutdown");
  2297. err = JSOCKERR_broken_pipe;
  2298. }
  2299. THROWJSOCKEXCEPTION(err);
  2300. }
  2301. }
  2302. }
  2303. void CSocket::shutdownNoThrow(unsigned mode)
  2304. {
  2305. if (state == ss_open) {
  2306. state = ss_shutdown;
  2307. #ifdef SOCKTRACE
  2308. PROGLOG("SOCKTRACE: shutdown(%d) socket %x %d (%p)", mode, sock, sock, this);
  2309. #endif
  2310. ::shutdown(sock, mode);
  2311. }
  2312. }
  2313. void CSocket::errclose()
  2314. {
  2315. #ifdef USERECVSEM
  2316. if (receiveblocksemowned) {
  2317. receiveblocksemowned = false;
  2318. receiveblocksem.signal();
  2319. }
  2320. #endif
  2321. if (state != ss_close) {
  2322. state = ss_close;
  2323. #ifdef SOCKTRACE
  2324. PROGLOG("SOCKTRACE: errclose socket %x %d (%p)", sock, sock, this);
  2325. #endif
  2326. if (mcastreq)
  2327. setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,(char*)mcastreq,sizeof(*mcastreq));
  2328. closesock();
  2329. }
  2330. }
  2331. void CSocket::close()
  2332. {
  2333. #ifdef USERECVSEM
  2334. if (receiveblocksemowned) {
  2335. receiveblocksemowned = false;
  2336. receiveblocksem.signal();
  2337. }
  2338. #endif
  2339. if (state != ss_close) {
  2340. #ifdef SOCKTRACE
  2341. PROGLOG("SOCKTRACE: close socket %x %d (%p)", sock, sock, this);
  2342. #endif
  2343. state = ss_close;
  2344. if (mcastreq)
  2345. setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,(char*)mcastreq,sizeof(*mcastreq));
  2346. if (closesock() != 0) {
  2347. THROWJSOCKEXCEPTION(ERRNO());
  2348. }
  2349. }
  2350. }
  2351. size32_t CSocket::get_max_send_size()
  2352. {
  2353. size32_t maxsend=0;
  2354. socklen_t size = sizeof(maxsend);
  2355. #if _WIN32
  2356. getsockopt(sock, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *) &maxsend, &size);
  2357. #else
  2358. getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *) &maxsend, &size); // not the same but closest I can find
  2359. #endif
  2360. return maxsend;
  2361. }
  2362. size32_t CSocket::get_send_buffer_size()
  2363. {
  2364. size32_t maxsend=0;
  2365. socklen_t size = sizeof(maxsend);
  2366. getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *) &maxsend, &size);
  2367. return maxsend;
  2368. }
  2369. void CSocket::set_send_buffer_size(size32_t maxsend)
  2370. {
  2371. if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&maxsend, sizeof(maxsend))!=0) {
  2372. LOGERR2(ERRNO(),1,"setsockopt(SO_SNDBUF)");
  2373. }
  2374. #ifdef CHECKBUFSIZE
  2375. size32_t v;
  2376. if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&v, sizeof(v))!=0) {
  2377. LOGERR2(ERRNO(),1,"getsockopt(SO_SNDBUF)");
  2378. }
  2379. if (v!=maxsend)
  2380. IWARNLOG("set_send_buffer_size requested %d, got %d",maxsend,v);
  2381. #endif
  2382. }
  2383. size32_t CSocket::get_receive_buffer_size()
  2384. {
  2385. size32_t max=0;
  2386. socklen_t size = sizeof(max);
  2387. getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *) &max, &size);
  2388. return max;
  2389. }
  2390. void CSocket::set_receive_buffer_size(size32_t max)
  2391. {
  2392. if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&max, sizeof(max))!=0) {
  2393. LOGERR2(ERRNO(),1,"setsockopt(SO_RCVBUF)");
  2394. }
  2395. #ifdef CHECKBUFSIZE
  2396. size32_t v;
  2397. if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v))!=0) {
  2398. LOGERR2(ERRNO(),1,"getsockopt(SO_RCVBUF)");
  2399. }
  2400. if (v<max)
  2401. IWARNLOG("set_receive_buffer_size requested %d, got %d",max,v);
  2402. #endif
  2403. }
  2404. bool CSocket::join_multicast_group(SocketEndpoint &ep)
  2405. {
  2406. StringBuffer s;
  2407. ep.getIpText(s); // will improve later
  2408. MCASTREQ req(s.str());
  2409. if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char*)&req, sizeof(req))!=0) {
  2410. return false;
  2411. }
  2412. return true;
  2413. }
  2414. bool CSocket::leave_multicast_group(SocketEndpoint &ep)
  2415. {
  2416. StringBuffer s;
  2417. ep.getIpText(s); // will improve later
  2418. MCASTREQ req(s.str());
  2419. if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,(char*)&req, sizeof(req))!=0) {
  2420. return false;
  2421. }
  2422. return true;
  2423. }
  2424. void CSocket::set_ttl(unsigned _ttl)
  2425. {
  2426. if (_ttl)
  2427. {
  2428. u_char ttl = _ttl;
  2429. setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
  2430. }
  2431. #ifdef SOCKTRACE
  2432. int ttl0 = 0;
  2433. socklen_t ttl1 = sizeof(ttl0);
  2434. getsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl0, &ttl1);
  2435. DBGLOG("set_ttl: socket fd: %d requested ttl: %d actual ttl: %d", sock, _ttl, ttl0);
  2436. #endif
  2437. return;
  2438. }
  2439. void CSocket::logConnectionInfo(unsigned timeoutms, unsigned conn_mstime)
  2440. {
  2441. PROGLOG("SOCKTRACE: connect(%u) - time:%u ms fd:%d l:%d r:%s:%d", timeoutms, conn_mstime, sock, localPort, (hostname?hostname:"NULL"), hostport);
  2442. // PrintStackReport();
  2443. }
  2444. bool CSocket::isSecure() const
  2445. {
  2446. return false;
  2447. }
  2448. CSocket::~CSocket()
  2449. {
  2450. if (owned)
  2451. {
  2452. try
  2453. {
  2454. close();
  2455. }
  2456. catch (IException *e)
  2457. {
  2458. EXCLOG(e,"~CSocket close()");
  2459. e->Release();
  2460. }
  2461. }
  2462. free(hostname);
  2463. hostname = NULL;
  2464. #ifdef _TRACE
  2465. free(tracename);
  2466. tracename = NULL;
  2467. #endif
  2468. delete mcastreq;
  2469. }
  2470. CSocket::CSocket(const SocketEndpoint &ep,SOCKETMODE smode,const char *name)
  2471. {
  2472. state = ss_close;
  2473. nonblocking = false;
  2474. #ifdef USERECVSEM
  2475. receiveblocksemowned = false;
  2476. #endif
  2477. nagling = true; // until turned off
  2478. hostport = ep.port;
  2479. localPort = 0;
  2480. hostname = NULL;
  2481. mcastreq = NULL;
  2482. #ifdef _TRACE
  2483. tracename = NULL;
  2484. #endif
  2485. StringBuffer tmp;
  2486. if ((smode==sm_multicast_server)&&(name&&*name)) {
  2487. mcastreq = new MCASTREQ(name);
  2488. }
  2489. else {
  2490. if (!name&&!ep.isNull())
  2491. name = ep.getIpText(tmp).str();
  2492. hostname = name?strdup(name):NULL;
  2493. }
  2494. sock = INVALID_SOCKET;
  2495. sockmode = smode;
  2496. owned = true;
  2497. nextblocksize = 0;
  2498. in_accept = false;
  2499. accept_cancel_state = accept_not_cancelled;
  2500. #ifdef _TRACE
  2501. if (name)
  2502. setTraceName("T>", name);
  2503. else
  2504. {
  2505. StringBuffer hostname;
  2506. SocketEndpoint self;
  2507. self.setLocalHost(0);
  2508. self.getUrlStr(hostname);
  2509. setTraceName("S>", hostname.str());
  2510. }
  2511. #endif
  2512. }
  2513. CSocket::CSocket(T_SOCKET new_sock,SOCKETMODE smode,bool _owned)
  2514. {
  2515. nonblocking = false;
  2516. #ifdef USERECVSEM
  2517. receiveblocksemowned = false;
  2518. #endif
  2519. nagling = true; // until turned off
  2520. sock = new_sock;
  2521. if (new_sock!=INVALID_SOCKET)
  2522. STATS.activesockets++;
  2523. mcastreq = NULL;
  2524. #ifdef _TRACE
  2525. tracename = NULL;
  2526. #endif
  2527. state = ss_open;
  2528. sockmode = smode;
  2529. owned = _owned;
  2530. nextblocksize = 0;
  2531. in_accept = false;
  2532. accept_cancel_state = accept_not_cancelled;
  2533. set_nagle(false);
  2534. //set_linger(DEFAULT_LINGER_TIME); -- experiment with removing this as closesocket should still endevour to send outstanding data
  2535. char peer[256];
  2536. hostport = peer_name(peer,sizeof(peer));
  2537. hostname = strdup(peer);
  2538. SocketEndpoint ep;
  2539. localPort = getEndpoint(ep).port;
  2540. #ifdef _TRACE
  2541. setTraceName("A!", peer);
  2542. #endif
  2543. }
  2544. ISocket* ISocket::create(unsigned short p,int listen_queue_size)
  2545. {
  2546. if (p==0)
  2547. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  2548. SocketEndpoint ep;
  2549. ep.port = p;
  2550. Owned<CSocket> sock = new CSocket(ep,sm_tcp_server,NULL);
  2551. sock->open(listen_queue_size);
  2552. return sock.getClear();
  2553. }
  2554. ISocket* ISocket::create_ip(unsigned short p,const char *host,int listen_queue_size)
  2555. {
  2556. if (p==0)
  2557. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  2558. SocketEndpoint ep(host,p);
  2559. Owned<CSocket> sock = new CSocket(ep,sm_tcp_server,host);
  2560. sock->open(listen_queue_size);
  2561. return sock.getClear();
  2562. }
  2563. ISocket* ISocket::udp_create(unsigned short p)
  2564. {
  2565. SocketEndpoint ep;
  2566. ep.port=p;
  2567. Owned<CSocket> sock = new CSocket(ep,(p==0)?sm_udp:sm_udp_server,NULL);
  2568. sock->open(0);
  2569. return sock.getClear();
  2570. }
  2571. ISocket* ISocket::multicast_create(unsigned short p, const char *mcip, unsigned _ttl)
  2572. {
  2573. if (p==0)
  2574. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  2575. SocketEndpoint ep(mcip,p);
  2576. Owned<CSocket> sock = new CSocket(ep,sm_multicast_server,mcip);
  2577. sock->open(0,true);
  2578. if (_ttl)
  2579. sock->set_ttl(_ttl);
  2580. return sock.getClear();
  2581. }
  2582. ISocket* ISocket::multicast_create(unsigned short p, const IpAddress &ip, unsigned _ttl)
  2583. {
  2584. if (p==0)
  2585. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  2586. SocketEndpoint ep(p, ip);
  2587. StringBuffer tmp;
  2588. Owned<CSocket> sock = new CSocket(ep,sm_multicast_server,ip.getIpText(tmp).str());
  2589. sock->open(0,true);
  2590. if (_ttl)
  2591. sock->set_ttl(_ttl);
  2592. return sock.getClear();
  2593. }
  2594. ISocket* ISocket::udp_connect(unsigned short p, char const* name)
  2595. {
  2596. if (!name||!*name||(p==0))
  2597. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  2598. SocketEndpoint ep(name, p);
  2599. Owned<CSocket> sock = new CSocket(ep,sm_udp,name);
  2600. sock->udpconnect();
  2601. return sock.getClear();
  2602. }
  2603. ISocket* ISocket::udp_connect(const SocketEndpoint &ep)
  2604. {
  2605. Owned<CSocket> sock = new CSocket(ep,sm_udp,NULL);
  2606. sock->udpconnect();
  2607. return sock.getClear();
  2608. }
  2609. ISocket* ISocket::multicast_connect(unsigned short p, char const* mcip, unsigned _ttl)
  2610. {
  2611. if (p==0)
  2612. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  2613. SocketEndpoint ep(mcip,p);
  2614. return multicast_connect(ep, _ttl);
  2615. }
  2616. ISocket* ISocket::multicast_connect(const SocketEndpoint &ep, unsigned _ttl)
  2617. {
  2618. Owned<CSocket> sock = new CSocket(ep,sm_multicast,NULL);
  2619. sock->udpconnect();
  2620. if (_ttl)
  2621. sock->set_ttl(_ttl);
  2622. return sock.getClear();
  2623. }
  2624. ISocket* ISocket::attach(int s, bool tcpip)
  2625. {
  2626. CSocket* sock = new CSocket((SOCKET)s, tcpip?sm_tcp:sm_udp, false);
  2627. return sock;
  2628. }
  2629. bool isInterfaceIp(const IpAddress &ip, const char *ifname)
  2630. {
  2631. #ifdef _WIN32
  2632. return false;
  2633. #else
  2634. int fd = socket(AF_INET, SOCK_DGRAM, 0); // IPV6 TBD
  2635. if (fd<0)
  2636. return false;
  2637. MemoryAttr ma;
  2638. char *buf = (char *)ma.allocate(1024);
  2639. struct ifconf ifc;
  2640. ifc.ifc_len = 1024;
  2641. ifc.ifc_buf = buf;
  2642. if(ioctl(fd, SIOCGIFCONF, &ifc) < 0) // query interfaces
  2643. {
  2644. close(fd);
  2645. return false;
  2646. }
  2647. bool match = false;
  2648. struct ifreq *ifr = ifc.ifc_req;
  2649. int len = 0;
  2650. for (int i=0; i<ifc.ifc_len;
  2651. #ifdef __APPLE__
  2652. len = _SIZEOF_ADDR_IFREQ(*ifr),
  2653. #else
  2654. len = sizeof(struct ifreq),
  2655. #endif
  2656. ifr = (struct ifreq *) ((char *) ifr + len),
  2657. i += len
  2658. )
  2659. {
  2660. struct ifreq *item = ifr;
  2661. if (ifname&&*ifname)
  2662. if (!WildMatch(item->ifr_name,ifname))
  2663. continue;
  2664. IpAddress iptest((inet_ntoa(((struct sockaddr_in *)&item->ifr_addr)->sin_addr)));
  2665. if (ip.ipequals(iptest))
  2666. {
  2667. match = true;
  2668. break;
  2669. }
  2670. }
  2671. close(fd);
  2672. return match;
  2673. #endif
  2674. }
  2675. NO_SANITIZE("alignment") bool getInterfaceIp(IpAddress &ip,const char *ifname)
  2676. {
  2677. #if defined(_WIN32)
  2678. return false;
  2679. #else
  2680. static bool recursioncheck = false;
  2681. ip.ipset(NULL);
  2682. int fd = socket(AF_INET, SOCK_DGRAM, 0); // IPV6 TBD
  2683. if (fd<0)
  2684. return false;
  2685. MemoryAttr ma;
  2686. char *buf = (char *)ma.allocate(1024);
  2687. struct ifconf ifc;
  2688. ifc.ifc_len = 1024;
  2689. ifc.ifc_buf = buf;
  2690. if(ioctl(fd, SIOCGIFCONF, &ifc) < 0) // query interfaces
  2691. {
  2692. close(fd);
  2693. return false;
  2694. }
  2695. for (int loopback = 0; loopback <= 1; loopback++)
  2696. {
  2697. struct ifreq *ifr = ifc.ifc_req;
  2698. int len = 0;
  2699. for (int i=0; i<ifc.ifc_len;
  2700. #ifdef __APPLE__
  2701. len = _SIZEOF_ADDR_IFREQ(*ifr),
  2702. #else
  2703. len = sizeof(struct ifreq),
  2704. #endif
  2705. ifr = (struct ifreq *) ((char *) ifr + len),
  2706. i += len
  2707. )
  2708. {
  2709. bool useLoopback = (loopback==1);
  2710. struct ifreq *item = ifr;
  2711. if (ifname && *ifname)
  2712. if (!WildMatch(item->ifr_name,ifname))
  2713. continue;
  2714. #ifdef __APPLE__
  2715. if (item->ifr_addr.sa_family != AF_INET) // ipv6 support TBD
  2716. continue;
  2717. char host[128];
  2718. getnameinfo(&item->ifr_addr, sizeof(item->ifr_addr), host, sizeof(host), 0, 0, NI_NUMERICHOST);
  2719. IpAddress iptest(host);
  2720. #else
  2721. IpAddress iptest((inet_ntoa(((struct sockaddr_in *)&item->ifr_addr)->sin_addr)));
  2722. #endif
  2723. struct ifreq flags;
  2724. memset(&flags, 0, sizeof(flags));
  2725. strcpy(flags.ifr_name, item->ifr_name);
  2726. if (ioctl(fd, SIOCGIFFLAGS, &flags) < 0)
  2727. {
  2728. if (!recursioncheck) {
  2729. recursioncheck = true;
  2730. IERRLOG("Error retrieving interface flags for interface %s", item->ifr_name);
  2731. recursioncheck = false;
  2732. }
  2733. continue;
  2734. }
  2735. bool isLoopback = iptest.isLoopBack() || ((flags.ifr_flags & IFF_LOOPBACK) != 0);
  2736. bool isUp = (flags.ifr_flags & IFF_UP) != 0;
  2737. if ((isLoopback==useLoopback) && isUp)
  2738. {
  2739. if (ip.isNull())
  2740. ip.ipset(iptest);
  2741. else if (!PreferredSubnet.isNull()&&!PreferredSubnet.test(ip)&&PreferredSubnet.test(iptest))
  2742. ip.ipset(iptest);
  2743. }
  2744. }
  2745. if (!ip.isNull())
  2746. break;
  2747. }
  2748. close(fd);
  2749. return !ip.isNull();
  2750. #endif
  2751. }
  2752. static StringAttr cachehostname;
  2753. static IpAddress cachehostip;
  2754. static IpAddress localhostip;
  2755. static CriticalSection hostnamesect;
  2756. const char * GetCachedHostName()
  2757. {
  2758. CriticalBlock c(hostnamesect);
  2759. if (!cachehostname.get())
  2760. {
  2761. #ifndef _WIN32
  2762. #ifdef _CONTAINERIZED
  2763. //MORE: Does this need to be implemented a different way?
  2764. #else
  2765. IpAddress ip;
  2766. const char *ifs = queryEnvironmentConf().queryProp("interface");
  2767. if (getInterfaceIp(ip, ifs))
  2768. {
  2769. StringBuffer ips;
  2770. ip.getIpText(ips);
  2771. if (ips.length())
  2772. {
  2773. cachehostname.set(ips.str());
  2774. cachehostip.ipset(ip);
  2775. return cachehostname.get();
  2776. }
  2777. }
  2778. #endif
  2779. #endif
  2780. char temp[1024];
  2781. if (gethostname(temp, sizeof(temp))==0)
  2782. cachehostname.set(temp);
  2783. else
  2784. cachehostname.set("localhost"); // assume no NIC card
  2785. }
  2786. return cachehostname.get();
  2787. }
  2788. IpAddress & queryLocalIP()
  2789. {
  2790. CriticalBlock c(hostnamesect);
  2791. if (localhostip.isNull())
  2792. {
  2793. if (IP6preferred)
  2794. localhostip.ipset("::1"); //IPv6
  2795. else
  2796. localhostip.ipset("127.0.0.1"); //IPv4
  2797. }
  2798. return localhostip;
  2799. }
  2800. IpAddress & queryHostIP()
  2801. {
  2802. CriticalBlock c(hostnamesect);
  2803. if (cachehostip.isNull()) {
  2804. if (!cachehostip.ipset(GetCachedHostName())) {
  2805. cachehostip.ipset(queryLocalIP());
  2806. // printf("hostname %s not resolved, using localhost\n",GetCachedHostName()); // don't use jlog in case recursive
  2807. }
  2808. }
  2809. return cachehostip;
  2810. }
  2811. IpAddress &GetHostIp(IpAddress &ip)
  2812. {
  2813. ip.ipset(queryHostIP());
  2814. return ip;
  2815. }
  2816. IpAddress &localHostToNIC(IpAddress &ip)
  2817. {
  2818. if (ip.isLoopBack())
  2819. GetHostIp(ip);
  2820. return ip;
  2821. }
  2822. // IpAddress
  2823. bool getInterfaceName(StringBuffer &ifname)
  2824. {
  2825. #if defined(_WIN32)
  2826. return false;
  2827. #else
  2828. IpAddress myIp;
  2829. GetHostIp(myIp);
  2830. int fd = socket(AF_INET, SOCK_DGRAM, 0); // IPV6 TBD
  2831. if (fd<0)
  2832. return false;
  2833. MemoryAttr ma;
  2834. char *buf = (char *)ma.allocate(1024);
  2835. struct ifconf ifc;
  2836. ifc.ifc_len = 1024;
  2837. ifc.ifc_buf = buf;
  2838. if(ioctl(fd, SIOCGIFCONF, &ifc) < 0) // query interfaces
  2839. {
  2840. close(fd);
  2841. return false;
  2842. }
  2843. struct ifreq *ifr = ifc.ifc_req;
  2844. int len = 0;
  2845. for (int i=0; i<ifc.ifc_len;
  2846. #ifdef __APPLE__
  2847. len = _SIZEOF_ADDR_IFREQ(*ifr),
  2848. #else
  2849. len = sizeof(struct ifreq),
  2850. #endif
  2851. ifr = (struct ifreq *) ((char *) ifr + len),
  2852. i += len
  2853. )
  2854. {
  2855. struct ifreq *item = ifr;
  2856. IpAddress iptest((inet_ntoa(((struct sockaddr_in *)&item->ifr_addr)->sin_addr)));
  2857. if (iptest.ipequals(myIp))
  2858. {
  2859. ifname.set(item->ifr_name);
  2860. close(fd);
  2861. return true;
  2862. }
  2863. }
  2864. close(fd);
  2865. return false;
  2866. #endif
  2867. }
  2868. inline bool isIp4(const unsigned *netaddr)
  2869. {
  2870. if (IP4only)
  2871. return true;
  2872. if (netaddr[2]==0xffff0000)
  2873. return (netaddr[1]==0)&&(netaddr[0]==0);
  2874. if (netaddr[2]==0)
  2875. if ((netaddr[3]==0)&&(netaddr[0]==0)&&(netaddr[1]==0))
  2876. return true; // null address
  2877. // maybe should get loopback here
  2878. return false;
  2879. }
  2880. void IpAddress::setIP4(unsigned ip)
  2881. {
  2882. netaddr[0] = 0;
  2883. netaddr[1] = 0;
  2884. if (ip)
  2885. netaddr[2] = 0xffff0000;
  2886. else
  2887. netaddr[2] = 0;
  2888. netaddr[3] = ip;
  2889. }
  2890. unsigned IpAddress::getIP4() const
  2891. {
  2892. assertex(isIp4());
  2893. return netaddr[3];
  2894. }
  2895. bool IpAddress::isIp4() const
  2896. {
  2897. return ::isIp4(netaddr);
  2898. }
  2899. bool IpAddress::isNull() const
  2900. {
  2901. return (netaddr[3]==0)&&(IP4only||((netaddr[2]==0)&&(netaddr[1]==0)&&(netaddr[0]==0)));
  2902. }
  2903. bool IpAddress::isLoopBack() const
  2904. {
  2905. if (::isIp4(netaddr)&&((netaddr[3] & 0x000000ff)==0x000007f))
  2906. return true;
  2907. return (netaddr[3]==0x1000000)&&(netaddr[2]==0)&&(netaddr[1]==0)&&(netaddr[0]==0);
  2908. }
  2909. bool IpAddress::isLocal() const
  2910. {
  2911. if (isLoopBack() || isHost())
  2912. return true;
  2913. IpAddress ip(*this);
  2914. return isInterfaceIp(ip, NULL);
  2915. }
  2916. bool IpAddress::ipequals(const IpAddress & other) const
  2917. {
  2918. // reverse compare for speed
  2919. return (other.netaddr[3]==netaddr[3])&&(IP4only||((other.netaddr[2]==netaddr[2])&&(other.netaddr[1]==netaddr[1])&&(other.netaddr[0]==netaddr[0])));
  2920. }
  2921. int IpAddress::ipcompare(const IpAddress & other) const
  2922. {
  2923. return memcmp(&netaddr, &other.netaddr, sizeof(netaddr));
  2924. }
  2925. unsigned IpAddress::iphash(unsigned prev) const
  2926. {
  2927. return hashc((const byte *)&netaddr,sizeof(netaddr),prev);
  2928. }
  2929. unsigned IpAddress::fasthash() const
  2930. {
  2931. if (IP4only || isIp4())
  2932. return netaddr[3] >> 24;
  2933. else
  2934. return iphash(0) >> 24;
  2935. }
  2936. bool IpAddress::isHost() const
  2937. {
  2938. return ipequals(queryHostIP());
  2939. }
  2940. static bool decodeNumericIP(const char *text,unsigned *netaddr)
  2941. {
  2942. if (!text)
  2943. return false;
  2944. bool isv6 = strchr(text,':')!=NULL;
  2945. StringBuffer tmp;
  2946. if ((*text=='[')&&!IP4only) {
  2947. text++;
  2948. size32_t l = strlen(text);
  2949. if ((l<=2)||(text[l-1]!=']'))
  2950. return false;
  2951. text = tmp.append(l-2,text);
  2952. }
  2953. if (!isv6&&isdigit(text[0])) {
  2954. if (_inet_pton(AF_INET, text, &netaddr[3])>0) {
  2955. netaddr[2] = netaddr[3]?0xffff0000:0; // check for NULL
  2956. netaddr[1] = 0;
  2957. netaddr[0] = 0; // special handling for loopback?
  2958. return true;
  2959. }
  2960. }
  2961. else if (isv6&&!IP4only) {
  2962. int ret = _inet_pton(AF_INET6, text, netaddr);
  2963. if (ret>=0)
  2964. return (ret>0);
  2965. int err = ERRNO();
  2966. StringBuffer tmp("_inet_pton: ");
  2967. tmp.append(text);
  2968. LOGERR(err,1,tmp.str());
  2969. }
  2970. return false;
  2971. }
  2972. static bool lookupHostAddress(const char *name,unsigned *netaddr)
  2973. {
  2974. // if IP4only or using MS V6 can only resolve IPv4 using
  2975. static bool recursioncheck = false; // needed to stop error message recursing
  2976. unsigned retry=10;
  2977. #if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo)
  2978. if (IP4only) {
  2979. #else
  2980. {
  2981. #endif
  2982. CriticalBlock c(hostnamesect);
  2983. hostent * entry = gethostbyname(name);
  2984. while (entry==NULL) {
  2985. if (retry--==0) {
  2986. if (!recursioncheck) {
  2987. recursioncheck = true;
  2988. LogErr(h_errno,1,"gethostbyname failed",__LINE__,name);
  2989. recursioncheck = false;
  2990. }
  2991. return false;
  2992. }
  2993. {
  2994. CriticalUnblock ub(hostnamesect);
  2995. Sleep((10-retry)*100);
  2996. }
  2997. entry = gethostbyname(name);
  2998. }
  2999. if (entry->h_addr_list[0]) {
  3000. unsigned ptr = 0;
  3001. if (!PreferredSubnet.isNull()) {
  3002. for (;;) {
  3003. ptr++;
  3004. if (entry->h_addr_list[ptr]==NULL) {
  3005. ptr = 0;
  3006. break;
  3007. }
  3008. IpAddress ip;
  3009. ip.setNetAddress(sizeof(unsigned),entry->h_addr_list[ptr]);
  3010. if (PreferredSubnet.test(ip))
  3011. break;
  3012. }
  3013. }
  3014. memcpy(&netaddr[3], entry->h_addr_list[ptr], sizeof(netaddr[3]));
  3015. netaddr[2] = 0xffff0000;
  3016. netaddr[1] = 0;
  3017. netaddr[0] = 0;
  3018. return true;
  3019. }
  3020. return false;
  3021. }
  3022. #if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo)
  3023. struct addrinfo hints;
  3024. memset(&hints,0,sizeof(hints));
  3025. struct addrinfo *addrInfo = NULL;
  3026. for (;;) {
  3027. memset(&hints,0,sizeof(hints));
  3028. int ret = getaddrinfo(name, NULL , &hints, &addrInfo);
  3029. if (!ret)
  3030. break;
  3031. if (retry--==0) {
  3032. if (!recursioncheck) {
  3033. recursioncheck = true;
  3034. LogErr(ret,1,"getaddrinfo failed",__LINE__,name);
  3035. #ifdef _DEBUG
  3036. PrintStackReport();
  3037. #endif
  3038. recursioncheck = false;
  3039. }
  3040. return false;
  3041. }
  3042. Sleep((10-retry)*100);
  3043. }
  3044. struct addrinfo *best = NULL;
  3045. bool snm = !PreferredSubnet.isNull();
  3046. for (;;) {
  3047. struct addrinfo *ai;
  3048. for (ai = addrInfo; ai; ai = ai->ai_next) {
  3049. // printf("flags=%d, family=%d, socktype=%d, protocol=%d, addrlen=%d, canonname=%s\n",ai->ai_flags,ai->ai_family,ai->ai_socktype,ai->ai_protocol,ai->ai_addrlen,ai->ai_canonname?ai->ai_canonname:"NULL");
  3050. switch (ai->ai_family) {
  3051. case AF_INET: {
  3052. if (snm) {
  3053. IpAddress ip;
  3054. ip.setNetAddress(sizeof(in_addr),&(((sockaddr_in *)ai->ai_addr)->sin_addr));
  3055. if (!PreferredSubnet.test(ip))
  3056. continue;
  3057. }
  3058. if ((best==NULL)||((best->ai_family==AF_INET6)&&!IP6preferred))
  3059. best = ai;
  3060. break;
  3061. }
  3062. case AF_INET6: {
  3063. if (snm) {
  3064. IpAddress ip;
  3065. ip.setNetAddress(sizeof(in_addr6),&(((sockaddr_in6 *)ai->ai_addr)->sin6_addr));
  3066. if (!PreferredSubnet.test(ip))
  3067. continue;
  3068. }
  3069. if ((best==NULL)||((best->ai_family==AF_INET)&&IP6preferred))
  3070. best = ai;
  3071. break;
  3072. }
  3073. }
  3074. }
  3075. if (best||!snm)
  3076. break;
  3077. snm = false;
  3078. }
  3079. if (best) {
  3080. if (best->ai_family==AF_INET6)
  3081. memcpy(netaddr,&(((sockaddr_in6 *)best->ai_addr)->sin6_addr),sizeof(in6_addr));
  3082. else {
  3083. memcpy(netaddr+3,&(((sockaddr_in *)best->ai_addr)->sin_addr),sizeof(in_addr));
  3084. netaddr[2] = 0xffff0000;
  3085. netaddr[1] = 0;
  3086. netaddr[0] = 0;
  3087. }
  3088. }
  3089. freeaddrinfo(addrInfo);
  3090. return best!=NULL;
  3091. #endif
  3092. return false;
  3093. }
  3094. bool IpAddress::ipset(const char *text)
  3095. {
  3096. if (text&&*text) {
  3097. if ((text[0]=='.')&&(text[1]==0)) {
  3098. ipset(queryHostIP());
  3099. return true;
  3100. }
  3101. if (decodeNumericIP(text,netaddr))
  3102. return true;
  3103. const char *s;
  3104. for (s=text;*s;s++)
  3105. if (!isdigit(*s)&&(*s!=':')&&(*s!='.'))
  3106. break;
  3107. if (!*s)
  3108. return ipset(NULL);
  3109. if (lookupHostAddress(text,netaddr))
  3110. return true;
  3111. }
  3112. memset(&netaddr,0,sizeof(netaddr));
  3113. return false;
  3114. }
  3115. inline char * addbyte(char *s,byte b)
  3116. {
  3117. if (b>=100) {
  3118. *(s++) = b/100+'0';
  3119. b %= 100;
  3120. *(s++) = b/10+'0';
  3121. b %= 10;
  3122. }
  3123. else if (b>=10) {
  3124. *(s++) = b/10+'0';
  3125. b %= 10;
  3126. }
  3127. *(s++) = b+'0';
  3128. return s;
  3129. }
  3130. StringBuffer & IpAddress::getIpText(StringBuffer & out) const
  3131. {
  3132. if (::isIp4(netaddr)) {
  3133. const byte *ip = (const byte *)&netaddr[3];
  3134. char ips[16];
  3135. char *s = ips;
  3136. for (unsigned i=0;i<4;i++) {
  3137. if (i)
  3138. *(s++) = '.';
  3139. s = addbyte(s,ip[i]);
  3140. }
  3141. return out.append(s-ips,ips);
  3142. }
  3143. char tmp[INET6_ADDRSTRLEN];
  3144. const char *res = _inet_ntop(AF_INET6, &netaddr, tmp, sizeof(tmp));
  3145. if (!res)
  3146. throw makeOsException(errno);
  3147. return out.append(res);
  3148. }
  3149. void IpAddress::ipserialize(MemoryBuffer & out) const
  3150. {
  3151. if (((netaddr[2]==0xffff0000)||(netaddr[2]==0))&&(netaddr[1]==0)&&(netaddr[0]==0)) {
  3152. if (netaddr[3]==IPV6_SERIALIZE_PREFIX)
  3153. throw MakeStringException(-1,"Invalid network address"); // hack prevention
  3154. out.append(sizeof(netaddr[3]), &netaddr[3]);
  3155. }
  3156. else {
  3157. unsigned pfx = IPV6_SERIALIZE_PREFIX;
  3158. out.append(sizeof(pfx),&pfx).append(sizeof(netaddr),&netaddr);
  3159. }
  3160. }
  3161. void IpAddress::ipdeserialize(MemoryBuffer & in)
  3162. {
  3163. unsigned pfx;
  3164. in.read(sizeof(pfx),&pfx);
  3165. if (pfx!=IPV6_SERIALIZE_PREFIX) {
  3166. netaddr[0] = 0;
  3167. netaddr[1] = 0;
  3168. netaddr[2] = (pfx == 0 || pfx == 0x1000000) ? 0 : 0xffff0000; // catch null and loopback
  3169. netaddr[3] = pfx;
  3170. }
  3171. else
  3172. in.read(sizeof(netaddr),&netaddr);
  3173. }
  3174. unsigned IpAddress::ipdistance(const IpAddress &other,unsigned offset) const
  3175. {
  3176. if (offset>3)
  3177. offset = 3;
  3178. int i1;
  3179. _cpyrev4(&i1,&netaddr[3-offset]);
  3180. int i2;
  3181. _cpyrev4(&i2,&other.netaddr[3-offset]);
  3182. i1-=i2;
  3183. if (i1>0)
  3184. return i1;
  3185. return -i1;
  3186. }
  3187. bool IpAddress::ipincrement(unsigned count,byte minoctet,byte maxoctet,unsigned short minipv6piece,unsigned maxipv6piece)
  3188. {
  3189. unsigned base;
  3190. if (::isIp4(netaddr)) {
  3191. base = maxoctet-minoctet+1;
  3192. if (!base||(base>256))
  3193. return false;
  3194. byte * ips = (byte *)&netaddr[3];
  3195. byte * ip = ips+4;
  3196. while (count) {
  3197. if (ip==ips)
  3198. return false; // overflow
  3199. ip--;
  3200. unsigned v = (count+((*ip>minoctet)?(*ip-minoctet):0));
  3201. *ip = minoctet + v%base;
  3202. count = v/base;
  3203. }
  3204. }
  3205. else {
  3206. base = maxipv6piece-minipv6piece+1;
  3207. if (!base||(base>0x10000))
  3208. return false;
  3209. unsigned short * ps = (unsigned short *)&netaddr;
  3210. unsigned short * p = ps+8;
  3211. while (count) {
  3212. if (p==ps)
  3213. return false; // overflow (actually near impossible!)
  3214. p--;
  3215. unsigned v = (count+((*p>minipv6piece)?(*p-minipv6piece):0));
  3216. *p = minipv6piece + v%base;
  3217. count = v/base;
  3218. }
  3219. }
  3220. return true;
  3221. }
  3222. unsigned IpAddress::ipsetrange( const char *text) // e.g. 10.173.72.1-65 ('-' may be omitted)
  3223. {
  3224. unsigned e=0;
  3225. unsigned f=0;
  3226. const char *r = strchr(text,'-');
  3227. bool ok;
  3228. if (r) {
  3229. e = atoi(r+1);
  3230. StringBuffer tmp(r-text,text);
  3231. ok = ipset(tmp.str());
  3232. if (!::isIp4(netaddr))
  3233. IPV6_NOT_IMPLEMENTED(); // TBD IPv6
  3234. if (ok) {
  3235. while ((r!=text)&&(*(r-1)!='.'))
  3236. r--;
  3237. f = (r!=text)?atoi(r):0;
  3238. }
  3239. }
  3240. else
  3241. ok = ipset(text);
  3242. if ((f>e)||!ok)
  3243. return 0;
  3244. return e-f+1;
  3245. }
  3246. NO_SANITIZE("alignment") size32_t IpAddress::getNetAddress(size32_t maxsz,void *dst) const
  3247. {
  3248. if (maxsz==sizeof(unsigned)) {
  3249. if (::isIp4(netaddr)) {
  3250. *(unsigned *)dst = netaddr[3];
  3251. return maxsz;
  3252. }
  3253. }
  3254. else if (!IP4only&&(maxsz==sizeof(netaddr))) {
  3255. memcpy(dst,&netaddr,maxsz);
  3256. return maxsz;
  3257. }
  3258. return 0;
  3259. }
  3260. NO_SANITIZE("alignment") void IpAddress::setNetAddress(size32_t sz,const void *src)
  3261. {
  3262. if (sz==sizeof(unsigned)) { // IPv4
  3263. netaddr[0] = 0;
  3264. netaddr[1] = 0;
  3265. netaddr[3] = *(const unsigned *)src;
  3266. netaddr[2] = netaddr[3] ? 0xffff0000 : 0; // leave as null if Ipv4 address is null
  3267. }
  3268. else if (!IP4only&&(sz==sizeof(netaddr))) { // IPv6
  3269. memcpy(&netaddr,src,sz);
  3270. if ((netaddr[2]==0)&&(netaddr[3]!=0)&&(netaddr[3]!=0x1000000)&&(netaddr[0]==0)&&(netaddr[1]==0))
  3271. netaddr[2]=0xffff0000; // use this form only
  3272. }
  3273. else
  3274. memset(&netaddr,0,sizeof(netaddr));
  3275. }
  3276. void SocketEndpoint::deserialize(MemoryBuffer & in)
  3277. {
  3278. ipdeserialize(in);
  3279. in.read(port);
  3280. }
  3281. void SocketEndpoint::serialize(MemoryBuffer & out) const
  3282. {
  3283. ipserialize(out);
  3284. out.append(port);
  3285. }
  3286. bool SocketEndpoint::set(const char *name,unsigned short _port)
  3287. {
  3288. if (name) {
  3289. if (*name=='[') {
  3290. const char *s = name+1;
  3291. const char *t = strchr(s,']');
  3292. if (t) {
  3293. StringBuffer tmp(t-s,s);
  3294. if (t[1]==':')
  3295. _port = atoi(t+2);
  3296. return set(tmp.str(),_port);
  3297. }
  3298. }
  3299. const char * colon = strchr(name, ':');
  3300. if (colon) {
  3301. if (!IP4only&&strchr(colon+1, ':'))
  3302. colon = NULL; // hello its IpV6
  3303. }
  3304. else
  3305. colon = strchr(name, '|'); // strange hole convention
  3306. char ips[260];
  3307. if (colon) {
  3308. size32_t l = colon-name;
  3309. if (l>=sizeof(ips))
  3310. l = sizeof(ips)-1;
  3311. memcpy(ips,name,l);
  3312. ips[l] = 0;
  3313. name = ips;
  3314. _port = atoi(colon+1);
  3315. }
  3316. if (ipset(name)) {
  3317. port = _port;
  3318. return true;
  3319. }
  3320. }
  3321. ipset(NULL);
  3322. port = 0;
  3323. return false;
  3324. }
  3325. void SocketEndpoint::getUrlStr(char * str, size32_t len) const
  3326. {
  3327. if (len==0)
  3328. return;
  3329. StringBuffer _str;
  3330. getUrlStr(_str);
  3331. size32_t l = _str.length()+1;
  3332. if (l>len)
  3333. {
  3334. l = len-1;
  3335. str[l] = 0;
  3336. }
  3337. memcpy(str,_str.str(),l);
  3338. }
  3339. StringBuffer &SocketEndpoint::getUrlStr(StringBuffer &str) const
  3340. {
  3341. getIpText(str);
  3342. if (port)
  3343. str.append(':').append((unsigned)port); // TBD IPv6 put [] on
  3344. return str;
  3345. }
  3346. unsigned SocketEndpoint::hash(unsigned prev) const
  3347. {
  3348. return hashc((const byte *)&port,sizeof(port),iphash(prev));
  3349. }
  3350. //---------------------------------------------------------------------------
  3351. SocketListCreator::SocketListCreator()
  3352. {
  3353. lastPort = 0;
  3354. }
  3355. void SocketListCreator::addSocket(const SocketEndpoint &ep)
  3356. {
  3357. StringBuffer ipstr;
  3358. ep.getIpText(ipstr);
  3359. addSocket(ipstr.str(), ep.port);
  3360. }
  3361. void SocketListCreator::addSocket(const char * ip, unsigned port)
  3362. {
  3363. if (fullText.length())
  3364. fullText.append("|");
  3365. const char * prev = lastIp;
  3366. const char * startCopy = ip;
  3367. if (prev)
  3368. {
  3369. if (strcmp(ip, prev) == 0)
  3370. {
  3371. fullText.append("=");
  3372. startCopy = NULL;
  3373. }
  3374. else
  3375. {
  3376. const char * cur = ip;
  3377. for (;;)
  3378. {
  3379. char n = *cur;
  3380. if (!n)
  3381. break;
  3382. if (n != *prev)
  3383. break;
  3384. cur++;
  3385. prev++;
  3386. if (n == '.')
  3387. startCopy = cur;
  3388. }
  3389. if (startCopy != ip)
  3390. fullText.append("*");
  3391. }
  3392. }
  3393. fullText.append(startCopy);
  3394. if (lastPort != port)
  3395. fullText.append(":").append(port);
  3396. lastIp.set(ip);
  3397. lastPort = port;
  3398. }
  3399. const char * SocketListCreator::getText()
  3400. {
  3401. return fullText.str();
  3402. }
  3403. void SocketListCreator::addSockets(SocketEndpointArray &array)
  3404. {
  3405. ForEachItemIn(i,array) {
  3406. const SocketEndpoint &sockep=array.item(i);
  3407. StringBuffer ipstr;
  3408. sockep.getIpText(ipstr);
  3409. addSocket(ipstr.str(),sockep.port);
  3410. }
  3411. }
  3412. //---------------------------------------------------------------------------
  3413. SocketListParser::SocketListParser(const char * text)
  3414. {
  3415. fullText.set(text);
  3416. cursor = NULL;
  3417. lastPort = 0;
  3418. }
  3419. void SocketListParser::first(unsigned port)
  3420. {
  3421. cursor = fullText;
  3422. lastIp.set(NULL);
  3423. lastPort = port;
  3424. }
  3425. bool SocketListParser::get(StringAttr & ip, unsigned & port, unsigned index, unsigned defport)
  3426. {
  3427. first(defport);
  3428. do
  3429. {
  3430. if (!next(ip, port))
  3431. return false;
  3432. } while (index--);
  3433. return true;
  3434. }
  3435. bool SocketListParser::next(StringAttr & ip, unsigned & port)
  3436. {
  3437. // IPV6TBD
  3438. StringBuffer ipText;
  3439. if (*cursor == 0)
  3440. return false;
  3441. if (*cursor == '=')
  3442. {
  3443. ipText.append(lastIp);
  3444. cursor++;
  3445. }
  3446. else if (*cursor == '*')
  3447. {
  3448. cursor++;
  3449. //count the number of dots in the tail
  3450. const char * cur = cursor;
  3451. unsigned count = 0;
  3452. for (;;)
  3453. {
  3454. char c = *cur++;
  3455. switch (c)
  3456. {
  3457. case 0:
  3458. case '|':
  3459. case ',':
  3460. case ':':
  3461. goto done;
  3462. case '.':
  3463. ++count;
  3464. break;
  3465. }
  3466. }
  3467. done:
  3468. //copy up to the appropriate dot from the previous ip.
  3469. const unsigned dotCount = 3; //more what about 6 digit ip's
  3470. cur = lastIp;
  3471. for (;;)
  3472. {
  3473. char c = *cur++;
  3474. switch (c)
  3475. {
  3476. case 0:
  3477. case '|':
  3478. case ',':
  3479. case ':':
  3480. assertex(!"Should not get here!");
  3481. goto done2;
  3482. case '.':
  3483. ipText.append(c);
  3484. if (++count == dotCount)
  3485. goto done2;
  3486. break;
  3487. default:
  3488. ipText.append(c);
  3489. break;
  3490. }
  3491. }
  3492. done2:;
  3493. }
  3494. bool inPort = false;
  3495. port = lastPort;
  3496. for (;;)
  3497. {
  3498. char c = *cursor++;
  3499. switch (c)
  3500. {
  3501. case 0:
  3502. cursor--;
  3503. goto doneCopy;
  3504. case '|':
  3505. case ',':
  3506. goto doneCopy;
  3507. case ':':
  3508. port = atoi(cursor);
  3509. inPort = true;
  3510. break;;
  3511. default:
  3512. if (!inPort)
  3513. ipText.append(c);
  3514. break;
  3515. }
  3516. }
  3517. doneCopy:
  3518. lastIp.set(ipText.str());
  3519. ip.set(lastIp);
  3520. lastPort = port;
  3521. return true;
  3522. }
  3523. unsigned SocketListParser::getSockets(SocketEndpointArray &array,unsigned defport)
  3524. {
  3525. first(defport);
  3526. StringAttr ip;
  3527. unsigned port;
  3528. while (next(ip,port)) {
  3529. SocketEndpoint ep(ip,port);
  3530. array.append(ep);
  3531. }
  3532. return array.ordinality();
  3533. }
  3534. jlib_decl JSocketStatistics *getSocketStatPtr()
  3535. {
  3536. return &STATS;
  3537. }
  3538. void getSocketStatistics(JSocketStatistics &stats)
  3539. {
  3540. // should put in simple lock
  3541. memcpy(&stats,&STATS,sizeof(stats));
  3542. }
  3543. void resetSocketStatistics()
  3544. {
  3545. unsigned activesockets=STATS.activesockets;
  3546. memset(&STATS,0,sizeof(STATS));
  3547. STATS.activesockets = activesockets;
  3548. }
  3549. static StringBuffer &appendtime(StringBuffer &s,unsigned us)
  3550. {
  3551. // attemp to get into more sensible units
  3552. if (us>10000000)
  3553. return s.append(us/1000000).append('s');
  3554. if (us>10000)
  3555. return s.append(us/1000).append("ms");
  3556. return s.append(us).append("us");
  3557. }
  3558. StringBuffer &getSocketStatisticsString(JSocketStatistics &stats,StringBuffer &str)
  3559. {
  3560. str.append("connects=").append(stats.connects).append('\n');
  3561. appendtime(str.append("connecttime="),stats.connecttime).append('\n');
  3562. str.append("failedconnects=").append(stats.failedconnects).append('\n');
  3563. appendtime(str.append("failedconnecttime="),stats.failedconnecttime).append('\n');
  3564. str.append("reads=").append(stats.reads).append('\n');
  3565. appendtime(str.append("readtime="),stats.readtime).append('\n');
  3566. str.append("readsize=").append(stats.readsize).append(" bytes\n");
  3567. str.append("writes=").append(stats.writes).append('\n');
  3568. appendtime(str.append("writetime="),stats.writetime).append('\n');
  3569. str.append("writesize=").append(stats.writesize).append(" bytes").append('\n');
  3570. str.append("activesockets=").append(stats.activesockets).append('\n');
  3571. str.append("numblockrecvs=").append(stats.numblockrecvs).append('\n');
  3572. str.append("numblocksends=").append(stats.numblocksends).append('\n');
  3573. str.append("blockrecvsize=").append(stats.blockrecvsize).append('\n');
  3574. str.append("blocksendsize=").append(stats.blocksendsize).append('\n');
  3575. str.append("blockrecvtime=").append(stats.blockrecvtime).append('\n');
  3576. str.append("blocksendtime=").append(stats.blocksendtime).append('\n');
  3577. str.append("longestblocksend=").append(stats.longestblocksend).append('\n');
  3578. str.append("longestblocksize=").append(stats.longestblocksize);
  3579. return str;
  3580. }
  3581. // ===============================================================================
  3582. // select thread for handling multiple selects
  3583. struct SelectItem
  3584. {
  3585. ISocket *sock;
  3586. T_SOCKET handle;
  3587. ISocketSelectNotify *nfy;
  3588. byte mode;
  3589. bool del; // only used in select handler method
  3590. bool operator == (const SelectItem & other) const { return sock == other.sock; }
  3591. };
  3592. class SelectItemArray : public StructArrayOf<SelectItem> { };
  3593. class SelectItemArrayP : public StructArrayOf<SelectItem*> { };
  3594. #define SELECT_TIMEOUT_SECS 1 // but it does (TBD)
  3595. #ifdef _WIN32
  3596. // fd_set utility functions
  3597. inline T_FD_SET *cpyfds(T_FD_SET &dst,const T_FD_SET &src)
  3598. {
  3599. unsigned i = src.fd_count;
  3600. dst.fd_count = i;
  3601. while (i--)
  3602. dst.fd_array[i] = src.fd_array[i]; // possibly better as memcpy
  3603. return &dst;
  3604. }
  3605. inline bool findfds(T_FD_SET &s,T_SOCKET h,bool &c)
  3606. {
  3607. unsigned n = s.fd_count;
  3608. unsigned i;
  3609. for(i=0;i<n;i++) {
  3610. if (s.fd_array[i] == h) {
  3611. if (--n)
  3612. s.fd_array[i] = s.fd_array[n]; // remove item
  3613. else
  3614. c = false;
  3615. s.fd_count = n;
  3616. return true;
  3617. }
  3618. }
  3619. return false;
  3620. }
  3621. inline T_SOCKET popfds(T_FD_SET &s)
  3622. {
  3623. unsigned n = s.fd_count;
  3624. T_SOCKET ret;
  3625. if (n) {
  3626. ret = s.fd_array[--n];
  3627. s.fd_count = n;
  3628. }
  3629. else
  3630. ret = NULL;
  3631. return ret;
  3632. }
  3633. #else
  3634. #define _USE_PIPE_FOR_SELECT_TRIGGER
  3635. // not as optimized as windows but I am expecting to convert to using poll anyway
  3636. inline T_FD_SET *cpyfds(T_FD_SET &dst,const T_FD_SET &src)
  3637. {
  3638. memcpy(&dst,&src,sizeof(T_FD_SET));
  3639. return &dst;
  3640. }
  3641. inline bool findfds(T_FD_SET &s,T_SOCKET h,bool &c)
  3642. {
  3643. if ((unsigned)h>=XFD_SETSIZE)
  3644. return false;
  3645. return FD_ISSET(h,&s); // does not remove entry or set termination flag when done
  3646. }
  3647. #endif
  3648. class CSocketBaseThread: public Thread
  3649. {
  3650. protected:
  3651. bool terminating;
  3652. CriticalSection sect;
  3653. Semaphore ticksem;
  3654. std::atomic_uint tickwait;
  3655. unsigned offset;
  3656. bool selectvarschange;
  3657. unsigned waitingchange;
  3658. Semaphore waitingchangesem;
  3659. int validateselecterror;
  3660. unsigned validateerrcount;
  3661. const char *selecttrace;
  3662. unsigned basesize;
  3663. #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  3664. T_SOCKET dummysock[2];
  3665. #else
  3666. T_SOCKET dummysock;
  3667. #endif
  3668. bool dummysockopen;
  3669. CSocketBaseThread(const char *trc) : Thread("CSocketBaseThread"), tickwait(0)
  3670. {
  3671. }
  3672. ~CSocketBaseThread()
  3673. {
  3674. }
  3675. public:
  3676. void triggerselect()
  3677. {
  3678. if (tickwait)
  3679. ticksem.signal();
  3680. #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  3681. CriticalBlock block(sect);
  3682. char c = 0;
  3683. if(write(dummysock[1], &c, 1) != 1) {
  3684. int err = ERRNO();
  3685. LOGERR(err,1,"Socket closed during trigger select");
  3686. }
  3687. #else
  3688. closedummy();
  3689. #endif
  3690. }
  3691. void resettrigger()
  3692. {
  3693. #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  3694. CriticalBlock block(sect);
  3695. char c;
  3696. while((::read(dummysock[0], &c, sizeof(c))) == sizeof(c));
  3697. #endif
  3698. }
  3699. void stop(bool wait)
  3700. {
  3701. terminating = true;
  3702. triggerselect();
  3703. if (wait)
  3704. join();
  3705. }
  3706. bool sockOk(T_SOCKET sock)
  3707. {
  3708. #ifdef _DEBUG
  3709. PROGLOG("CSocketBaseThread: sockOk testing %d",sock);
  3710. #endif
  3711. int t=0;
  3712. socklen_t tl = sizeof(t);
  3713. if (getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *)&t, &tl)!=0) {
  3714. StringBuffer sockstr;
  3715. const char *tracename = sockstr.append((unsigned)sock).str();
  3716. LOGERR2(ERRNO(),1,"CSocketBaseThread select handle");
  3717. return false;
  3718. }
  3719. #ifdef _USE_SELECT
  3720. T_FD_SET fds;
  3721. struct timeval tv;
  3722. CHECKSOCKRANGE(sock);
  3723. XFD_ZERO(&fds);
  3724. FD_SET((unsigned)sock, &fds);
  3725. //FD_SET((unsigned)sock, &except);
  3726. tv.tv_sec = 0;
  3727. tv.tv_usec = 0;
  3728. int rc = ::select( sock + 1, NULL, (fd_set *)&fds, NULL, &tv );
  3729. if (rc<0) {
  3730. StringBuffer sockstr;
  3731. const char *tracename = sockstr.append((unsigned)sock).str();
  3732. LOGERR2(ERRNO(),2,"CSocketBaseThread select handle");
  3733. return false;
  3734. }
  3735. # ifdef _DEBUG
  3736. else if (rc>0)
  3737. PROGLOG("CSocketBaseThread: select handle %d selected(2) %d",sock,rc);
  3738. # endif
  3739. XFD_ZERO(&fds);
  3740. FD_SET((unsigned)sock, &fds);
  3741. tv.tv_sec = 0;
  3742. tv.tv_usec = 0;
  3743. rc = ::select( sock + 1, (fd_set *)&fds, NULL, NULL, &tv );
  3744. if (rc<0) {
  3745. StringBuffer sockstr;
  3746. const char *tracename = sockstr.append((unsigned)sock).str();
  3747. LOGERR2(ERRNO(),3,"CSocketBaseThread select handle");
  3748. return false;
  3749. }
  3750. # ifdef _DEBUG
  3751. else if (rc>0)
  3752. PROGLOG("CSocketBaseThread: select handle %d selected(2) %d",sock,rc);
  3753. # endif
  3754. return true;
  3755. #else
  3756. struct pollfd fds[1];
  3757. fds[0].fd = sock;
  3758. fds[0].events = (POLLINX | POLLOUT);
  3759. fds[0].revents = 0;
  3760. int rc = ::poll(fds, 1, 0);
  3761. if (rc==0)
  3762. return true;
  3763. else if (rc>0)
  3764. {
  3765. if ( !(fds[0].revents & POLLNVAL) ) // MCK - skip POLLERR here
  3766. {
  3767. // PROGLOG("CSocketBaseThread: poll handle %d selected(2) %d",sock,rc);
  3768. return true;
  3769. }
  3770. }
  3771. else
  3772. {
  3773. int err = ERRNO();
  3774. if (err == JSE_INTR)
  3775. return true; // assume ok until next time called
  3776. }
  3777. StringBuffer sockstr;
  3778. const char *tracename = sockstr.append((unsigned)sock).str();
  3779. LOGERR2(ERRNO(),3,"CSocketBaseThread poll handle");
  3780. return false;
  3781. #endif
  3782. }
  3783. virtual void closedummy() = 0;
  3784. };
  3785. class CSocketSelectThread: public CSocketBaseThread
  3786. {
  3787. SelectItemArray items;
  3788. void opendummy()
  3789. {
  3790. CriticalBlock block(sect);
  3791. if (!dummysockopen) {
  3792. #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  3793. if(pipe(dummysock)) {
  3794. IWARNLOG("CSocketSelectThread: create pipe failed %d",ERRNO());
  3795. return;
  3796. }
  3797. for (unsigned i=0;i<2;i++) {
  3798. int flags = fcntl(dummysock[i], F_GETFL, 0);
  3799. if (flags!=-1) {
  3800. flags |= O_NONBLOCK;
  3801. fcntl(dummysock[i], F_SETFL, flags);
  3802. }
  3803. flags = fcntl(dummysock[i], F_GETFD, 0);
  3804. if (flags!=-1) {
  3805. flags |= FD_CLOEXEC;
  3806. fcntl(dummysock[i], F_SETFD, flags);
  3807. }
  3808. }
  3809. CHECKSOCKRANGE(dummysock[0]);
  3810. #else
  3811. if (IP6preferred)
  3812. dummysock = ::socket(AF_INET6, SOCK_STREAM, PF_INET6);
  3813. else
  3814. dummysock = ::socket(AF_INET, SOCK_STREAM, 0);
  3815. CHECKSOCKRANGE(dummysock);
  3816. #endif
  3817. dummysockopen = true;
  3818. }
  3819. }
  3820. void closedummy()
  3821. {
  3822. CriticalBlock block(sect);
  3823. if (dummysockopen) {
  3824. #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  3825. #ifdef SOCKTRACE
  3826. PROGLOG("SOCKTRACE: Closing dummy sockets %x %d %x %d (%p)", dummysock[0], dummysock[0], dummysock[1], dummysock[1], this);
  3827. #endif
  3828. ::close(dummysock[0]);
  3829. ::close(dummysock[1]);
  3830. #else
  3831. #ifdef _WIN32
  3832. ::closesocket(dummysock);
  3833. #else
  3834. ::close(dummysock);
  3835. #endif
  3836. #endif
  3837. dummysockopen = false;
  3838. }
  3839. }
  3840. #ifdef _WIN32
  3841. #define HASHTABSIZE 256
  3842. #define HASHNULL (HASHTABSIZE-1)
  3843. #define HASHTABMASK (HASHTABSIZE-1)
  3844. byte hashtab[HASHTABSIZE];
  3845. #define HASHSOCKET(s) ((((unsigned)s)>>2)&HASHTABMASK) // with some knowledge of windows handles
  3846. void inithash()
  3847. {
  3848. memset(&hashtab,HASHNULL,sizeof(hashtab));
  3849. assertex(FD_SETSIZE<255);
  3850. }
  3851. void reinithash()
  3852. { // done this way because index of items changes and hash table not that big
  3853. inithash();
  3854. assertex(items.ordinality()<HASHTABSIZE-1);
  3855. ForEachItemIn(i,items) {
  3856. unsigned h = HASHSOCKET(items.item(i).handle);
  3857. for (;;) {
  3858. if (hashtab[h]==HASHNULL) {
  3859. hashtab[h] = (byte)i;
  3860. break;
  3861. }
  3862. if (++h==HASHTABSIZE)
  3863. h = 0;
  3864. }
  3865. }
  3866. }
  3867. inline SelectItem &findhash(T_SOCKET handle)
  3868. {
  3869. unsigned h = HASHSOCKET(handle);
  3870. unsigned sh = h;
  3871. for (;;) {
  3872. SelectItem &i=items.element(hashtab[h]);
  3873. if (i.handle==handle)
  3874. return i;
  3875. if (++h==HASHTABSIZE)
  3876. h = 0;
  3877. assertex(h!=sh);
  3878. }
  3879. }
  3880. inline void processfds(T_FD_SET &s,byte mode,SelectItemArray &tonotify)
  3881. {
  3882. for (;;) {
  3883. T_SOCKET sock = popfds(s);
  3884. if (!sock)
  3885. break;
  3886. if (sock!=dummysock)
  3887. {
  3888. SelectItem &si = findhash(sock);
  3889. if (!si.del)
  3890. {
  3891. tonotify.append(si); // nb copies
  3892. SelectItem &itm = tonotify.element(tonotify.length()-1);
  3893. itm.nfy->Link();
  3894. itm.sock->Link();
  3895. itm.mode = mode;
  3896. }
  3897. }
  3898. }
  3899. }
  3900. #endif
  3901. public:
  3902. IMPLEMENT_IINTERFACE;
  3903. CSocketSelectThread(const char *trc)
  3904. : CSocketBaseThread("CSocketSelectThread")
  3905. {
  3906. dummysockopen = false;
  3907. opendummy();
  3908. terminating = false;
  3909. waitingchange = 0;
  3910. selectvarschange = false;
  3911. validateselecterror = 0;
  3912. validateerrcount = 0;
  3913. offset = 0;
  3914. selecttrace = trc;
  3915. basesize = 0;
  3916. #ifdef _WIN32
  3917. inithash();
  3918. #endif
  3919. }
  3920. ~CSocketSelectThread()
  3921. {
  3922. closedummy();
  3923. ForEachItemIn(i,items) {
  3924. // Release/dtors should not throw but leaving try/catch here until all paths checked
  3925. try {
  3926. SelectItem &si = items.element(i);
  3927. si.nfy->Release();
  3928. si.sock->Release();
  3929. }
  3930. catch (IException *e) {
  3931. EXCLOG(e,"~CSocketSelectThread");
  3932. e->Release();
  3933. }
  3934. }
  3935. }
  3936. Owned<IException> termexcept;
  3937. void updateItems()
  3938. {
  3939. // must be in CriticalBlock block(sect);
  3940. unsigned n = items.ordinality();
  3941. #ifdef _WIN32
  3942. bool hashupdateneeded = (n!=basesize); // additions all come at end
  3943. #endif
  3944. for (unsigned i=0;i<n;) {
  3945. SelectItem &si = items.element(i);
  3946. if (si.del) {
  3947. // Release/dtors should not throw but leaving try/catch here until all paths checked
  3948. try {
  3949. #ifdef SOCKTRACE
  3950. PROGLOG("CSocketSelectThread::updateItems release %d",si.handle);
  3951. #endif
  3952. si.nfy->Release();
  3953. si.sock->Release();
  3954. }
  3955. catch (IException *e) {
  3956. EXCLOG(e,"CSocketSelectThread::updateItems");
  3957. e->Release();
  3958. }
  3959. // NOTE: si is a reference, put last item into remove slot
  3960. n--;
  3961. if (i<n)
  3962. si = items.item(n);
  3963. items.remove(n);
  3964. #ifdef _WIN32
  3965. hashupdateneeded = true;
  3966. #endif
  3967. }
  3968. else
  3969. i++;
  3970. }
  3971. assertex(n<=XFD_SETSIZE-1);
  3972. #ifdef _WIN32
  3973. if (hashupdateneeded)
  3974. reinithash();
  3975. #endif
  3976. basesize = n;
  3977. }
  3978. bool checkSocks()
  3979. {
  3980. bool ret = false;
  3981. ForEachItemIn(i,items) {
  3982. SelectItem &si = items.element(i);
  3983. if (si.del)
  3984. ret = true; // maybe that bad one
  3985. else if (!sockOk(si.handle)) {
  3986. si.del = true;
  3987. ret = true;
  3988. }
  3989. }
  3990. return ret;
  3991. }
  3992. bool remove(ISocket *sock)
  3993. {
  3994. if (terminating)
  3995. return false;
  3996. CriticalBlock block(sect);
  3997. if (sock==NULL) { // wait until no changes outstanding
  3998. while (selectvarschange) {
  3999. waitingchange++;
  4000. CriticalUnblock unblock(sect);
  4001. waitingchangesem.wait();
  4002. }
  4003. return true;
  4004. }
  4005. ForEachItemIn(i,items) {
  4006. SelectItem &si = items.element(i);
  4007. if (!si.del&&(si.sock==sock)) {
  4008. si.del = true;
  4009. selectvarschange = true;
  4010. triggerselect();
  4011. return true;
  4012. }
  4013. }
  4014. return false;
  4015. }
  4016. bool add(ISocket *sock,unsigned mode,ISocketSelectNotify *nfy)
  4017. {
  4018. // maybe check once to prevent 1st delay? TBD
  4019. CriticalBlock block(sect);
  4020. unsigned n=0;
  4021. ForEachItemIn(i,items) {
  4022. SelectItem &si = items.element(i);
  4023. if (!si.del) {
  4024. if (si.sock==sock) {
  4025. si.del = true;
  4026. }
  4027. else
  4028. n++;
  4029. }
  4030. }
  4031. if (n>=XFD_SETSIZE-1) // leave 1 spare
  4032. return false;
  4033. SelectItem sn;
  4034. sn.nfy = LINK(nfy);
  4035. sn.sock = LINK(sock);
  4036. sn.mode = (byte)mode;
  4037. sn.handle = (T_SOCKET)sock->OShandle();
  4038. CHECKSOCKRANGE(sn.handle);
  4039. sn.del = false;
  4040. items.append(sn);
  4041. selectvarschange = true;
  4042. triggerselect();
  4043. return true;
  4044. }
  4045. void updateSelectVars(T_FD_SET &rdfds,T_FD_SET &wrfds,T_FD_SET &exfds,bool &isrd,bool &iswr,bool &isex,unsigned &ni,T_SOCKET &max_sockid)
  4046. {
  4047. CriticalBlock block(sect);
  4048. selectvarschange = false;
  4049. if (waitingchange) {
  4050. waitingchangesem.signal(waitingchange);
  4051. waitingchange = 0;
  4052. }
  4053. if (validateselecterror) { // something went wrong so check sockets
  4054. validateerrcount++;
  4055. if (!checkSocks()) {
  4056. // bad socket not found
  4057. PROGLOG("CSocketSelectThread::updateSelectVars cannot find socket error");
  4058. if (validateerrcount>10)
  4059. throw MakeStringException(-1,"CSocketSelectThread:Socket select error %d",validateselecterror);
  4060. }
  4061. }
  4062. else
  4063. validateerrcount = 0;
  4064. updateItems();
  4065. XFD_ZERO( &rdfds );
  4066. XFD_ZERO( &wrfds );
  4067. XFD_ZERO( &exfds );
  4068. isrd=false;
  4069. iswr=false;
  4070. isex=false;
  4071. #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  4072. max_sockid=dummysockopen?dummysock[0]:0;
  4073. #else
  4074. opendummy();
  4075. max_sockid=dummysockopen?dummysock:0;
  4076. #endif
  4077. ni = items.ordinality();
  4078. #ifdef _WIN32
  4079. if (offset>=ni)
  4080. #endif
  4081. offset = 0;
  4082. unsigned j = offset;
  4083. ForEachItemIn(i, items) {
  4084. SelectItem &si = items.element(j);
  4085. j++;
  4086. if (j==ni)
  4087. j = 0;
  4088. if (si.mode & SELECTMODE_READ) {
  4089. FD_SET( si.handle, &rdfds );
  4090. isrd = true;
  4091. }
  4092. if (si.mode & SELECTMODE_WRITE) {
  4093. FD_SET( si.handle, &wrfds );
  4094. iswr = true;
  4095. }
  4096. if (si.mode & SELECTMODE_EXCEPT) {
  4097. FD_SET( si.handle, &exfds );
  4098. isex = true;
  4099. }
  4100. max_sockid=std::max(si.handle, max_sockid);
  4101. }
  4102. if (dummysockopen) {
  4103. #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  4104. FD_SET( dummysock[0], &rdfds );
  4105. isrd = true;
  4106. #else
  4107. FD_SET( dummysock, &exfds );
  4108. isex = true;
  4109. #endif
  4110. }
  4111. validateselecterror = 0;
  4112. max_sockid++;
  4113. #ifdef SOCKTRACE
  4114. PROGLOG("SOCKTRACE: selecting on %d sockets",ni);
  4115. #endif
  4116. }
  4117. int run()
  4118. {
  4119. try
  4120. {
  4121. T_FD_SET rdfds;
  4122. T_FD_SET wrfds;
  4123. T_FD_SET exfds;
  4124. timeval selecttimeout;
  4125. bool isrd = false;
  4126. bool iswr = false;
  4127. bool isex = false;
  4128. T_SOCKET maxsockid = 0;
  4129. unsigned ni = 0;
  4130. selectvarschange = true;
  4131. unsigned numto = 0;
  4132. unsigned lastnumto = 0;
  4133. unsigned totnum = 0;
  4134. unsigned total = 0;
  4135. while (!terminating)
  4136. {
  4137. selecttimeout.tv_sec = SELECT_TIMEOUT_SECS; // linux modifies so initialize inside loop
  4138. selecttimeout.tv_usec = 0;
  4139. if (selectvarschange)
  4140. {
  4141. updateSelectVars(rdfds,wrfds,exfds,isrd,iswr,isex,ni,maxsockid);
  4142. }
  4143. if (ni==0)
  4144. {
  4145. validateerrcount = 0;
  4146. tickwait++;
  4147. if(!selectvarschange&&!terminating)
  4148. ticksem.wait(SELECT_TIMEOUT_SECS*1000);
  4149. tickwait--;
  4150. continue;
  4151. }
  4152. T_FD_SET rs;
  4153. T_FD_SET ws;
  4154. T_FD_SET es;
  4155. T_FD_SET *rsp = isrd?cpyfds(rs,rdfds):NULL;
  4156. T_FD_SET *wsp = iswr?cpyfds(ws,wrfds):NULL;
  4157. T_FD_SET *esp = isex?cpyfds(es,exfds):NULL;
  4158. int n = ::select(maxsockid,(fd_set *)rsp,(fd_set *)wsp,(fd_set *)esp,&selecttimeout); // first parameter needed for posix
  4159. if (terminating)
  4160. break;
  4161. if (n < 0)
  4162. {
  4163. CriticalBlock block(sect);
  4164. int err = ERRNO();
  4165. if (err != JSE_INTR)
  4166. {
  4167. if (dummysockopen)
  4168. {
  4169. LOGERR(err,12,"CSocketSelectThread select error"); // should cache error ?
  4170. validateselecterror = err;
  4171. #ifndef _USE_PIPE_FOR_SELECT_TRIGGER
  4172. closedummy(); // just in case was culprit
  4173. #endif
  4174. }
  4175. selectvarschange = true;
  4176. continue;
  4177. }
  4178. n = 0;
  4179. }
  4180. else if (n>0)
  4181. {
  4182. validateerrcount = 0;
  4183. numto = 0;
  4184. lastnumto = 0;
  4185. total += n;
  4186. totnum++;
  4187. SelectItemArray tonotify;
  4188. {
  4189. CriticalBlock block(sect);
  4190. #ifdef _WIN32
  4191. if (isrd)
  4192. processfds(rs,SELECTMODE_READ,tonotify);
  4193. if (iswr)
  4194. processfds(ws,SELECTMODE_WRITE,tonotify);
  4195. if (isex)
  4196. processfds(es,SELECTMODE_EXCEPT,tonotify);
  4197. #else
  4198. unsigned i;
  4199. SelectItem *si = items.getArray(offset);
  4200. SelectItem *sie = items.getArray(ni-1)+1;
  4201. bool r = isrd;
  4202. bool w = iswr;
  4203. bool e = isex;
  4204. #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  4205. if (r&&dummysockopen&&findfds(rs,dummysock[0],r))
  4206. {
  4207. resettrigger();
  4208. --n;
  4209. }
  4210. #endif
  4211. for (i=0;(n>0)&&(i<ni);i++)
  4212. {
  4213. unsigned addMode = 0;
  4214. if (r&&findfds(rs,si->handle,r))
  4215. {
  4216. if (!si->del)
  4217. addMode = SELECTMODE_READ;
  4218. --n;
  4219. }
  4220. if (w&&findfds(ws,si->handle,w))
  4221. {
  4222. if (!si->del)
  4223. addMode = SELECTMODE_WRITE;
  4224. --n;
  4225. }
  4226. if (e&&findfds(es,si->handle,e))
  4227. {
  4228. if (!si->del)
  4229. addMode = SELECTMODE_EXCEPT;
  4230. --n;
  4231. }
  4232. if (addMode)
  4233. {
  4234. tonotify.append(*si);
  4235. SelectItem &itm = tonotify.element(tonotify.length()-1);
  4236. itm.nfy->Link();
  4237. itm.sock->Link();
  4238. itm.mode = addMode;
  4239. }
  4240. si++;
  4241. if (si==sie)
  4242. si = items.getArray();
  4243. }
  4244. #endif
  4245. }
  4246. ForEachItemIn(j,tonotify)
  4247. {
  4248. const SelectItem &si = tonotify.item(j);
  4249. try
  4250. {
  4251. si.nfy->notifySelected(si.sock,si.mode); // ignore return
  4252. }
  4253. catch (IException *e)
  4254. { // should be acted upon by notifySelected
  4255. // could also not throw until after handling all events ...
  4256. EXCLOG(e,"CSocketSelectThread notifySelected");
  4257. throw ;
  4258. }
  4259. // Release/dtors should not throw but leaving try/catch here until all paths checked
  4260. try
  4261. {
  4262. si.nfy->Release();
  4263. si.sock->Release();
  4264. }
  4265. catch (IException *e)
  4266. {
  4267. EXCLOG(e,"CSocketSelectThread nfy/sock Release");
  4268. e->Release();
  4269. }
  4270. }
  4271. }
  4272. else
  4273. {
  4274. validateerrcount = 0;
  4275. if ((++numto>=lastnumto*2))
  4276. {
  4277. lastnumto = numto;
  4278. if (selecttrace&&(numto>4))
  4279. PROGLOG("%s: Select Idle(%d), %d,%d,%0.2f",selecttrace,numto,totnum,total,totnum?((double)total/(double)totnum):0.0);
  4280. }
  4281. /*
  4282. if (numto&&(numto%100))
  4283. {
  4284. CriticalBlock block(sect);
  4285. if (!selectvarschange)
  4286. selectvarschange = checkSocks();
  4287. }
  4288. */
  4289. }
  4290. if (++offset>=ni)
  4291. offset = 0;
  4292. }
  4293. }
  4294. catch (IException *e)
  4295. {
  4296. EXCLOG(e,"CSocketSelectThread");
  4297. termexcept.setown(e);
  4298. }
  4299. CriticalBlock block(sect);
  4300. try
  4301. {
  4302. updateItems();
  4303. }
  4304. catch (IException *e)
  4305. {
  4306. EXCLOG(e,"CSocketSelectThread(2)");
  4307. if (!termexcept)
  4308. termexcept.setown(e);
  4309. else
  4310. e->Release();
  4311. }
  4312. return 0;
  4313. }
  4314. };
  4315. class CSocketSelectHandler: implements ISocketSelectHandler, public CInterface
  4316. {
  4317. CIArrayOf<CSocketSelectThread> threads;
  4318. CriticalSection sect;
  4319. bool started;
  4320. std::atomic<bool> stopped;
  4321. StringAttr selecttrace;
  4322. public:
  4323. IMPLEMENT_IINTERFACE;
  4324. CSocketSelectHandler(const char *trc)
  4325. : started(false), stopped(false), selecttrace(trc)
  4326. {
  4327. }
  4328. ~CSocketSelectHandler()
  4329. {
  4330. stop(true);
  4331. threads.kill();
  4332. }
  4333. void start()
  4334. {
  4335. CriticalBlock block(sect);
  4336. if (!started) {
  4337. started = true;
  4338. ForEachItemIn(i,threads) {
  4339. threads.item(i).start();
  4340. }
  4341. }
  4342. }
  4343. void add(ISocket *sock,unsigned mode,ISocketSelectNotify *nfy)
  4344. {
  4345. CriticalBlock block(sect);
  4346. if (stopped)
  4347. return;
  4348. for (;;) {
  4349. bool added=false;
  4350. ForEachItemIn(i,threads) {
  4351. if (added)
  4352. threads.item(i).remove(sock);
  4353. else
  4354. added = threads.item(i).add(sock,mode,nfy);
  4355. }
  4356. if (added)
  4357. return;
  4358. CSocketSelectThread *thread = new CSocketSelectThread(selecttrace);
  4359. threads.append(*thread);
  4360. if (started)
  4361. thread->start();
  4362. }
  4363. }
  4364. void remove(ISocket *sock)
  4365. {
  4366. CriticalBlock block(sect);
  4367. ForEachItemIn(i,threads) {
  4368. if (threads.item(i).remove(sock)&&sock)
  4369. break;
  4370. }
  4371. }
  4372. void stop(bool wait)
  4373. {
  4374. IException *e=NULL;
  4375. CriticalBlock block(sect);
  4376. stopped = true;
  4377. unsigned i = 0;
  4378. while (i<threads.ordinality()) {
  4379. CSocketSelectThread &t=threads.item(i);
  4380. {
  4381. CriticalUnblock unblock(sect);
  4382. t.stop(wait); // not quite as quick as could be if wait true
  4383. }
  4384. if (wait && !e && t.termexcept)
  4385. e = t.termexcept.getClear();
  4386. i++;
  4387. }
  4388. #if 0 // don't throw error as too late
  4389. if (e)
  4390. throw e;
  4391. #else
  4392. ::Release(e);
  4393. #endif
  4394. }
  4395. };
  4396. #ifdef _HAS_EPOLL_SUPPORT
  4397. # define SOCK_ADDED 0x1
  4398. # define SOCK_REMOVED 0x2
  4399. class CSocketEpollThread: public CSocketBaseThread
  4400. {
  4401. int epfd;
  4402. SelectItem *sidummy;
  4403. SelectItemArrayP items;
  4404. struct epoll_event *epevents;
  4405. unsigned hdlPerThrd;
  4406. void epoll_op(int efd, int op, SelectItem *si, unsigned int event_mask)
  4407. {
  4408. int fd = si->handle;
  4409. int srtn;
  4410. struct epoll_event event;
  4411. // write all bytes to eliminate uninitialized warnings
  4412. memset(&event, 0, sizeof(event));
  4413. event.events = event_mask;
  4414. event.data.ptr = si;
  4415. # ifdef EPOLLTRACE
  4416. DBGLOG("EPOLL: op(%d) fd %d to epfd %d", op, fd, efd);
  4417. # endif
  4418. srtn = ::epoll_ctl(efd, op, fd, &event);
  4419. // if another thread closed fd before here don't fail
  4420. if ( (srtn < 0) && (op != EPOLL_CTL_DEL) ){
  4421. int err = ERRNO();
  4422. IWARNLOG("epoll_ctl failed op:%d, fd:%d, err=%d", op, fd, err);
  4423. }
  4424. }
  4425. void opendummy()
  4426. {
  4427. CriticalBlock block(sect);
  4428. if (!dummysockopen)
  4429. {
  4430. sidummy = new SelectItem;
  4431. sidummy->sock = nullptr;
  4432. sidummy->nfy = nullptr;
  4433. sidummy->del = true; // so its not added to tonotify ...
  4434. sidummy->mode = 0;
  4435. #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  4436. if(pipe(dummysock))
  4437. {
  4438. IWARNLOG("CSocketEpollThread: create pipe failed %d",ERRNO());
  4439. return;
  4440. }
  4441. for (unsigned i=0;i<2;i++)
  4442. {
  4443. int flags = fcntl(dummysock[i], F_GETFL, 0);
  4444. if (flags!=-1)
  4445. {
  4446. flags |= O_NONBLOCK;
  4447. fcntl(dummysock[i], F_SETFL, flags);
  4448. }
  4449. flags = fcntl(dummysock[i], F_GETFD, 0);
  4450. if (flags!=-1)
  4451. {
  4452. flags |= FD_CLOEXEC;
  4453. fcntl(dummysock[i], F_SETFD, flags);
  4454. }
  4455. }
  4456. sidummy->handle = dummysock[0];
  4457. epoll_op(epfd, EPOLL_CTL_ADD, sidummy, EPOLLINX);
  4458. #else
  4459. if (IP6preferred)
  4460. dummysock = ::socket(AF_INET6, SOCK_STREAM, PF_INET6);
  4461. else
  4462. dummysock = ::socket(AF_INET, SOCK_STREAM, 0);
  4463. // added EPOLLIN and EPOLLRDHUP also because cannot find anywhere MSG_OOB is sent
  4464. // added here to match existing select() code above which sets
  4465. // the except fd_set mask.
  4466. sidummy->handle = dummysock;
  4467. epoll_op(epfd, EPOLL_CTL_ADD, sidummy, (EPOLLINX | EPOLLPRI));
  4468. #endif
  4469. dummysockopen = true;
  4470. }
  4471. }
  4472. void closedummy()
  4473. {
  4474. CriticalBlock block(sect);
  4475. if (dummysockopen)
  4476. {
  4477. epoll_op(epfd, EPOLL_CTL_DEL, sidummy, 0);
  4478. #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  4479. #ifdef SOCKTRACE
  4480. PROGLOG("SOCKTRACE: Closing dummy sockets %x %d %x %d (%p)", dummysock[0], dummysock[0], dummysock[1], dummysock[1], this);
  4481. #endif
  4482. ::close(dummysock[0]);
  4483. ::close(dummysock[1]);
  4484. #else
  4485. ::close(dummysock);
  4486. #endif
  4487. delete sidummy;
  4488. dummysockopen = false;
  4489. }
  4490. }
  4491. void delSelItem(SelectItem *si)
  4492. {
  4493. epoll_op(epfd, EPOLL_CTL_DEL, si, 0);
  4494. // Release/dtors should not throw but leaving try/catch here until all paths checked
  4495. try
  4496. {
  4497. si->nfy->Release();
  4498. si->sock->Release();
  4499. delete si;
  4500. }
  4501. catch (IException *e)
  4502. {
  4503. EXCLOG(e,"CSocketEpollThread::delSelItem()");
  4504. e->Release();
  4505. }
  4506. }
  4507. void delSelItemPos(SelectItem *si, unsigned pos)
  4508. {
  4509. unsigned last = items.ordinality();
  4510. delSelItem(si);
  4511. last--;
  4512. if (pos < last)
  4513. items.swap(pos, last);
  4514. items.remove(last);
  4515. }
  4516. public:
  4517. IMPLEMENT_IINTERFACE;
  4518. CSocketEpollThread(const char *trc, unsigned _hdlPerThrd)
  4519. : CSocketBaseThread("CSocketEpollThread")
  4520. {
  4521. dummysockopen = false;
  4522. terminating = false;
  4523. waitingchange = 0;
  4524. selectvarschange = false;
  4525. validateselecterror = 0;
  4526. validateerrcount = 0;
  4527. offset = 0;
  4528. selecttrace = trc;
  4529. hdlPerThrd = _hdlPerThrd;
  4530. epfd = ::epoll_create(1); // NB: arg is not used in newer kernels
  4531. if (epfd < 0)
  4532. {
  4533. int err = ERRNO();
  4534. LOGERR(err,1,"epoll_create()");
  4535. THROWJSOCKEXCEPTION2(err);
  4536. }
  4537. # ifdef FD_CLOEXEC
  4538. int epflags = fcntl(epfd, F_GETFD, 0);
  4539. if (epflags != -1)
  4540. {
  4541. epflags |= FD_CLOEXEC;
  4542. fcntl(epfd, F_SETFD, epflags);
  4543. }
  4544. # endif
  4545. # ifdef EPOLLTRACE
  4546. DBGLOG("CSocketEpollThread: creating epoll fd %d", epfd );
  4547. # endif
  4548. try
  4549. {
  4550. epevents = new struct epoll_event[MAX_RET_EVENTS];
  4551. }
  4552. catch (const std::bad_alloc &e)
  4553. {
  4554. int err = ERRNO();
  4555. LOGERR(err,1,"epevents alloc()");
  4556. THROWJSOCKEXCEPTION2(err);
  4557. }
  4558. opendummy();
  4559. }
  4560. ~CSocketEpollThread()
  4561. {
  4562. closedummy();
  4563. ForEachItemIn(i, items)
  4564. {
  4565. SelectItem *si = items.element(i);
  4566. delSelItem(si);
  4567. }
  4568. if (epfd >= 0)
  4569. {
  4570. # ifdef EPOLLTRACE
  4571. DBGLOG("EPOLL: closing epfd %d", epfd);
  4572. # endif
  4573. ::close(epfd);
  4574. epfd = -1;
  4575. delete [] epevents;
  4576. }
  4577. }
  4578. Owned<IException> termexcept;
  4579. bool checkSocks()
  4580. {
  4581. bool ret = false;
  4582. // must be holding CriticalBlock (sect)
  4583. unsigned n = items.ordinality();
  4584. for (unsigned i=0;i<n;)
  4585. {
  4586. SelectItem *si = items.element(i);
  4587. if (!sockOk(si->handle))
  4588. {
  4589. delSelItemPos(si, i);
  4590. n--;
  4591. ret = true;
  4592. }
  4593. else
  4594. i++;
  4595. }
  4596. return ret;
  4597. }
  4598. bool removeSock(ISocket *sock)
  4599. {
  4600. // must be holding CriticalBlock (sect)
  4601. unsigned n = items.ordinality();
  4602. for (unsigned i=0;i<n;)
  4603. {
  4604. SelectItem *si = items.element(i);
  4605. if (si->sock==sock)
  4606. {
  4607. delSelItemPos(si, i);
  4608. n--;
  4609. return true;
  4610. }
  4611. else
  4612. i++;
  4613. }
  4614. return false;
  4615. }
  4616. bool remove(ISocket *sock)
  4617. {
  4618. CriticalBlock block(sect);
  4619. if (terminating)
  4620. return false;
  4621. if (sock==NULL)
  4622. { // wait until no changes outstanding
  4623. while (selectvarschange)
  4624. {
  4625. waitingchange++;
  4626. CriticalUnblock unblock(sect);
  4627. waitingchangesem.wait();
  4628. }
  4629. return true;
  4630. }
  4631. if (removeSock(sock))
  4632. {
  4633. selectvarschange = true;
  4634. // NB: could set terminating here if no more hdls on
  4635. // this thread and at least one other thread is present
  4636. triggerselect();
  4637. return true;
  4638. }
  4639. return false;
  4640. }
  4641. unsigned add(ISocket *sock,unsigned mode,ISocketSelectNotify *nfy)
  4642. {
  4643. if ( !sock || !nfy ||
  4644. !(mode & (SELECTMODE_READ|SELECTMODE_WRITE|SELECTMODE_EXCEPT)) )
  4645. {
  4646. IWARNLOG("EPOLL: adding fd but sock or nfy is NULL or mode is empty");
  4647. dbgassertex(false);
  4648. return 0;
  4649. }
  4650. CriticalBlock block(sect);
  4651. if (terminating)
  4652. return 0;
  4653. unsigned rm = 0;
  4654. if (removeSock(sock))
  4655. rm = SOCK_REMOVED;
  4656. unsigned n = items.ordinality();
  4657. // new handler thread
  4658. if (n >= hdlPerThrd)
  4659. return (0|rm);
  4660. SelectItem *sn = new SelectItem;
  4661. sn->nfy = LINK(nfy);
  4662. sn->sock = LINK(sock);
  4663. sn->mode = (byte)mode;
  4664. sn->handle = (T_SOCKET)sock->OShandle();
  4665. sn->del = false;
  4666. items.append(sn);
  4667. unsigned int ep_mode = 0;
  4668. if (mode & SELECTMODE_READ)
  4669. ep_mode |= EPOLLINX;
  4670. if (mode & SELECTMODE_WRITE)
  4671. ep_mode |= EPOLLOUT;
  4672. if (mode & SELECTMODE_EXCEPT)
  4673. ep_mode |= EPOLLPRI;
  4674. epoll_op(epfd, EPOLL_CTL_ADD, sn, ep_mode);
  4675. selectvarschange = true;
  4676. triggerselect();
  4677. return (SOCK_ADDED|rm);
  4678. }
  4679. void updateEpollVars(unsigned &ni)
  4680. {
  4681. CriticalBlock block(sect);
  4682. selectvarschange = false;
  4683. if (waitingchange)
  4684. {
  4685. waitingchangesem.signal(waitingchange);
  4686. waitingchange = 0;
  4687. }
  4688. if (validateselecterror)
  4689. { // something went wrong so check sockets
  4690. validateerrcount++;
  4691. if (!checkSocks())
  4692. {
  4693. // bad socket not found
  4694. IWARNLOG("CSocketEpollThread::updateEpollVars cannot find socket error");
  4695. if (validateerrcount>10)
  4696. throw MakeStringException(-1,"CSocketEpollThread:Socket epoll error %d",validateselecterror);
  4697. }
  4698. }
  4699. else
  4700. validateerrcount = 0;
  4701. #ifndef _USE_PIPE_FOR_SELECT_TRIGGER
  4702. opendummy();
  4703. #endif
  4704. ni = items.ordinality();
  4705. validateselecterror = 0;
  4706. }
  4707. int run()
  4708. {
  4709. try
  4710. {
  4711. unsigned ni = 0;
  4712. unsigned numto = 0;
  4713. unsigned lastnumto = 0;
  4714. unsigned totnum = 0;
  4715. unsigned total = 0;
  4716. selectvarschange = true;
  4717. while (!terminating)
  4718. {
  4719. if (selectvarschange)
  4720. updateEpollVars(ni);
  4721. if (ni==0)
  4722. {
  4723. validateerrcount = 0;
  4724. tickwait++;
  4725. if(!selectvarschange&&!terminating)
  4726. ticksem.wait(SELECT_TIMEOUT_SECS*1000);
  4727. tickwait--;
  4728. continue;
  4729. }
  4730. // poll for any events ...
  4731. int err = 0;
  4732. int n = ::epoll_wait(epfd, epevents, 1, 1000);
  4733. if (n < 0)
  4734. err = ERRNO();
  4735. # ifdef EPOLLTRACE
  4736. if(n > 0)
  4737. DBGLOG("EPOLL: after epoll_wait(), n = %d, ni = %d", n, ni);
  4738. # endif
  4739. if (terminating)
  4740. break;
  4741. if (n < 0)
  4742. {
  4743. CriticalBlock block(sect);
  4744. if (err != JSE_INTR)
  4745. {
  4746. if (dummysockopen)
  4747. {
  4748. LOGERR(err,12,"CSocketEpollThread epoll error"); // should cache error ?
  4749. validateselecterror = err;
  4750. #ifndef _USE_PIPE_FOR_SELECT_TRIGGER
  4751. closedummy(); // just in case was culprit
  4752. #endif
  4753. }
  4754. selectvarschange = true;
  4755. continue;
  4756. }
  4757. }
  4758. else if (n>0)
  4759. {
  4760. validateerrcount = 0;
  4761. numto = 0;
  4762. lastnumto = 0;
  4763. total += n;
  4764. totnum++;
  4765. SelectItemArray tonotify;
  4766. {
  4767. CriticalBlock block(sect);
  4768. // retrieve events, without waiting, while holding CS ...
  4769. int n2 = ::epoll_wait(epfd, epevents, MAX_RET_EVENTS, 0);
  4770. for (int j=0;j<n2;j++)
  4771. {
  4772. int tfd = -1;
  4773. SelectItem *epsi = (SelectItem *)epevents[j].data.ptr;
  4774. if (epsi)
  4775. tfd = epsi->handle;
  4776. # ifdef EPOLLTRACE
  4777. DBGLOG("EPOLL: j = %d, fd = %d, emask = %u", j, tfd, epevents[j].events);
  4778. # endif
  4779. if (tfd >= 0)
  4780. {
  4781. # ifdef _USE_PIPE_FOR_SELECT_TRIGGER
  4782. if ( (dummysockopen) && (tfd == dummysock[0]) )
  4783. {
  4784. resettrigger();
  4785. continue;
  4786. }
  4787. # endif
  4788. unsigned int ep_mode = 0;
  4789. if (epevents[j].events & (EPOLLINX | EPOLLHUP | EPOLLERR))
  4790. ep_mode |= SELECTMODE_READ;
  4791. if (epevents[j].events & EPOLLOUT)
  4792. ep_mode |= SELECTMODE_WRITE;
  4793. if (epevents[j].events & EPOLLPRI)
  4794. ep_mode |= SELECTMODE_EXCEPT;
  4795. if (ep_mode != 0)
  4796. {
  4797. tonotify.append(*epsi);
  4798. SelectItem &itm = tonotify.element(tonotify.length()-1);
  4799. itm.nfy->Link();
  4800. itm.sock->Link();
  4801. #ifdef _TRACELINKCLOSED
  4802. // temporary, to help diagnose spurious socket closes (hpcc-15043)
  4803. // currently no implementation of notifySelected() uses the mode
  4804. // argument so we can pass in the epoll events mask and log that
  4805. // if there is no data and the socket gets closed
  4806. itm.mode = epevents[j].events;
  4807. #else
  4808. itm.mode = ep_mode;
  4809. #endif
  4810. }
  4811. }
  4812. }
  4813. }
  4814. Owned<IException> nfyexcept;
  4815. ForEachItemIn(j,tonotify)
  4816. {
  4817. const SelectItem &si = tonotify.item(j);
  4818. try
  4819. {
  4820. si.nfy->notifySelected(si.sock,si.mode); // ignore return
  4821. }
  4822. catch (IException *e)
  4823. { // should be acted upon by notifySelected
  4824. // Don't throw until after handling all events ...
  4825. EXCLOG(e,"CSocketEpollThread notifySelected");
  4826. if (!nfyexcept)
  4827. nfyexcept.setown(e);
  4828. else
  4829. e->Release();
  4830. }
  4831. // Release/dtors should not throw but leaving try/catch here until all paths checked
  4832. try
  4833. {
  4834. si.nfy->Release();
  4835. si.sock->Release();
  4836. }
  4837. catch (IException *e)
  4838. {
  4839. EXCLOG(e,"CSocketEpollThread nfy/sock Release");
  4840. e->Release();
  4841. }
  4842. }
  4843. if (nfyexcept)
  4844. throw nfyexcept.getClear();
  4845. }
  4846. else
  4847. {
  4848. validateerrcount = 0;
  4849. if ((++numto>=lastnumto*2))
  4850. {
  4851. lastnumto = numto;
  4852. if (selecttrace&&(numto>4))
  4853. PROGLOG("%s: Epoll Idle(%d), %d,%d,%0.2f",selecttrace,numto,totnum,total,totnum?((double)total/(double)totnum):0.0);
  4854. }
  4855. /*
  4856. if (numto&&(numto%100))
  4857. {
  4858. CriticalBlock block(sect);
  4859. if (!selectvarschange)
  4860. selectvarschange = checkSocks();
  4861. }
  4862. */
  4863. }
  4864. }
  4865. }
  4866. catch (IException *e)
  4867. {
  4868. EXCLOG(e,"CSocketEpollThread");
  4869. termexcept.setown(e);
  4870. }
  4871. return 0;
  4872. }
  4873. };
  4874. class CSocketEpollHandler: implements ISocketSelectHandler, public CInterface
  4875. {
  4876. CIArrayOf<CSocketEpollThread> threads;
  4877. CriticalSection sect;
  4878. bool started;
  4879. std::atomic<bool> stopped;
  4880. StringAttr epolltrace;
  4881. unsigned hdlPerThrd;
  4882. public:
  4883. IMPLEMENT_IINTERFACE;
  4884. CSocketEpollHandler(const char *trc, unsigned _hdlPerThrd)
  4885. : started(false), stopped(false), epolltrace(trc), hdlPerThrd(_hdlPerThrd)
  4886. {
  4887. }
  4888. ~CSocketEpollHandler()
  4889. {
  4890. stop(true);
  4891. threads.kill();
  4892. }
  4893. void start()
  4894. {
  4895. CriticalBlock block(sect);
  4896. if (!started)
  4897. {
  4898. started = true;
  4899. ForEachItemIn(i,threads)
  4900. {
  4901. threads.item(i).start();
  4902. }
  4903. }
  4904. }
  4905. void add(ISocket *sock,unsigned mode,ISocketSelectNotify *nfy)
  4906. {
  4907. if ( !sock || !nfy ||
  4908. !(mode & (SELECTMODE_READ|SELECTMODE_WRITE|SELECTMODE_EXCEPT)) )
  4909. throw MakeStringException(-1,"CSocketEpollHandler::add() invalid sock or nfy or mode");
  4910. CriticalBlock block(sect);
  4911. if (stopped)
  4912. return;
  4913. // Create new handler thread if current one has hdlPerThrd fds.
  4914. // epoll() handles many fds faster than select so this would
  4915. // seem not as important, but we are still serializing on
  4916. // nfy events and spreading those over threads may help,
  4917. // especially with SSL as avail_read() could block more.
  4918. unsigned addrm = 0;
  4919. ForEachItemIn(i,threads)
  4920. {
  4921. if (!(addrm & SOCK_ADDED))
  4922. {
  4923. addrm |= threads.item(i).add(sock,mode,nfy);
  4924. if (addrm & (SOCK_ADDED | SOCK_REMOVED))
  4925. return;
  4926. }
  4927. else if (!(addrm & SOCK_REMOVED))
  4928. {
  4929. if (threads.item(i).remove(sock))
  4930. return;
  4931. }
  4932. }
  4933. if (addrm & SOCK_ADDED)
  4934. return;
  4935. CSocketEpollThread *thread = new CSocketEpollThread(epolltrace, hdlPerThrd);
  4936. threads.append(*thread);
  4937. if (started)
  4938. thread->start();
  4939. thread->add(sock,mode,nfy);
  4940. }
  4941. void remove(ISocket *sock)
  4942. {
  4943. CriticalBlock block(sect);
  4944. ForEachItemIn(i,threads)
  4945. {
  4946. if (threads.item(i).remove(sock))
  4947. break;
  4948. }
  4949. }
  4950. void stop(bool wait)
  4951. {
  4952. CriticalBlock block(sect);
  4953. stopped = true;
  4954. ForEachItemIn(i,threads)
  4955. {
  4956. CSocketEpollThread &t=threads.item(i);
  4957. {
  4958. CriticalUnblock unblock(sect);
  4959. t.stop(wait); // not quite as quick as could be if wait true
  4960. }
  4961. }
  4962. }
  4963. };
  4964. enum EpollMethod { EPOLL_INIT = 0, EPOLL_DISABLED, EPOLL_ENABLED };
  4965. static EpollMethod epoll_method = EPOLL_INIT;
  4966. static CriticalSection epollsect;
  4967. void check_epoll_cfg()
  4968. {
  4969. CriticalBlock block(epollsect);
  4970. // DBGLOG("check_epoll_cfg(): epoll_method = %d",epoll_method);
  4971. if (epoll_method == EPOLL_INIT)
  4972. {
  4973. #ifdef _CONTAINERIZED
  4974. //Does this need to be implemented a different way?
  4975. epoll_method = EPOLL_ENABLED;
  4976. epoll_hdlPerThrd = UINT_MAX;
  4977. #else
  4978. if (queryEnvironmentConf().getPropBool("use_epoll", true))
  4979. epoll_method = EPOLL_ENABLED;
  4980. else
  4981. epoll_method = EPOLL_DISABLED;
  4982. // DBGLOG("check_epoll_cfg(): after reading conf file, epoll_method = %d",epoll_method);
  4983. epoll_hdlPerThrd = (unsigned)queryEnvironmentConf().getPropInt("epoll_hdlperthrd", UINT_MAX);
  4984. if (epoll_hdlPerThrd == 0)
  4985. epoll_hdlPerThrd = UINT_MAX;
  4986. // DBGLOG("check_epoll_cfg(): after reading conf file, epoll_hdlPerThrd = %u",epoll_hdlPerThrd);
  4987. #endif
  4988. }
  4989. }
  4990. #endif // _HAS_EPOLL_SUPPORT
  4991. ISocketSelectHandler *createSocketSelectHandler(const char *trc, unsigned hdlPerThrd)
  4992. {
  4993. #ifdef _HAS_EPOLL_SUPPORT
  4994. check_epoll_cfg();
  4995. if (epoll_method == EPOLL_ENABLED)
  4996. {
  4997. if (hdlPerThrd == 0)
  4998. hdlPerThrd = epoll_hdlPerThrd;
  4999. return new CSocketEpollHandler(trc, hdlPerThrd);
  5000. }
  5001. else
  5002. return new CSocketSelectHandler(trc);
  5003. #else
  5004. return new CSocketSelectHandler(trc);
  5005. #endif
  5006. }
  5007. ISocketSelectHandler *createSocketEpollHandler(const char *trc, unsigned hdlPerThrd)
  5008. {
  5009. #ifdef _HAS_EPOLL_SUPPORT
  5010. check_epoll_cfg();
  5011. if (hdlPerThrd == 0)
  5012. hdlPerThrd = epoll_hdlPerThrd;
  5013. return new CSocketEpollHandler(trc, hdlPerThrd);
  5014. #else
  5015. return new CSocketSelectHandler(trc);
  5016. #endif
  5017. }
  5018. void readBuffer(ISocket * socket, MemoryBuffer & buffer)
  5019. {
  5020. size32_t len;
  5021. socket->read(&len, sizeof(len));
  5022. _WINREV4(len);
  5023. if (len) {
  5024. void * target = buffer.reserve(len);
  5025. socket->read(target, len);
  5026. }
  5027. }
  5028. void readBuffer(ISocket * socket, MemoryBuffer & buffer, unsigned timeoutms)
  5029. {
  5030. size32_t len;
  5031. size32_t sizeGot;
  5032. socket->readtms(&len, sizeof(len), sizeof(len), sizeGot, timeoutms);
  5033. _WINREV4(len);
  5034. if (len) {
  5035. void * target = buffer.reserve(len);
  5036. socket->readtms(target, len, len, sizeGot, timeoutms);
  5037. }
  5038. }
  5039. void writeBuffer(ISocket * socket, MemoryBuffer & buffer)
  5040. {
  5041. unsigned len = buffer.length();
  5042. _WINREV4(len);
  5043. socket->write(&len, sizeof(len));
  5044. if (len)
  5045. socket->write(buffer.toByteArray(), buffer.length());
  5046. }
  5047. bool catchReadBuffer(ISocket * socket, MemoryBuffer & buffer)
  5048. {
  5049. try
  5050. {
  5051. readBuffer(socket, buffer);
  5052. return true;
  5053. }
  5054. catch (IException * e)
  5055. {
  5056. switch (e->errorCode())
  5057. {
  5058. case JSOCKERR_graceful_close:
  5059. break;
  5060. default:
  5061. EXCLOG(e,"catchReadBuffer");
  5062. break;
  5063. }
  5064. e->Release();
  5065. }
  5066. return false;
  5067. }
  5068. bool catchReadBuffer(ISocket * socket, MemoryBuffer & buffer, unsigned timeoutms)
  5069. {
  5070. try
  5071. {
  5072. readBuffer(socket, buffer, timeoutms);
  5073. return true;
  5074. }
  5075. catch (IException * e)
  5076. {
  5077. switch (e->errorCode())
  5078. {
  5079. case JSOCKERR_graceful_close:
  5080. break;
  5081. default:
  5082. EXCLOG(e,"catchReadBuffer");
  5083. break;
  5084. }
  5085. e->Release();
  5086. }
  5087. return false;
  5088. }
  5089. bool catchWriteBuffer(ISocket * socket, MemoryBuffer & buffer)
  5090. {
  5091. try
  5092. {
  5093. writeBuffer(socket, buffer);
  5094. return true;
  5095. }
  5096. catch (IException * e)
  5097. {
  5098. EXCLOG(e,"catchWriteBuffer");
  5099. e->Release();
  5100. }
  5101. return false;
  5102. }
  5103. CSingletonSocketConnection::CSingletonSocketConnection(SocketEndpoint &_ep)
  5104. {
  5105. ep = _ep;
  5106. state = Snone;
  5107. cancelling = false;
  5108. }
  5109. CSingletonSocketConnection::~CSingletonSocketConnection()
  5110. {
  5111. shutdownAndCloseNoThrow(sock);
  5112. }
  5113. void CSingletonSocketConnection::set_keep_alive(bool keepalive)
  5114. {
  5115. if (sock)
  5116. sock->set_keep_alive(keepalive);
  5117. }
  5118. bool CSingletonSocketConnection::connect(unsigned timeoutms)
  5119. {
  5120. CriticalBlock block(crit);
  5121. if (cancelling)
  5122. state = Scancelled;
  5123. if (state==Scancelled)
  5124. return false;
  5125. assertex(!sock);
  5126. ISocket *newsock=NULL;
  5127. state = Sconnect;
  5128. unsigned start = 0;
  5129. if (timeoutms!=(unsigned)INFINITE)
  5130. start = msTick();
  5131. while (state==Sconnect) {
  5132. try {
  5133. CriticalUnblock unblock(crit);
  5134. newsock = ISocket::connect_wait(ep,1000*60*4);
  5135. break;
  5136. }
  5137. catch (IException * e) {
  5138. if ((e->errorCode()==JSOCKERR_timeout_expired)||(e->errorCode()==JSOCKERR_connection_failed)) {
  5139. e->Release();
  5140. if ((state==Sconnect)&&(timeoutms!=(unsigned)INFINITE)&&(msTick()-start>timeoutms)) {
  5141. state = Snone;
  5142. return false;
  5143. }
  5144. }
  5145. else {
  5146. state = Scancelled;
  5147. EXCLOG(e,"CSingletonSocketConnection::connect");
  5148. e->Release();
  5149. return false;
  5150. }
  5151. }
  5152. }
  5153. if (state!=Sconnect) {
  5154. ::Release(newsock);
  5155. newsock = NULL;
  5156. }
  5157. if (!newsock) {
  5158. state = Scancelled;
  5159. return false;
  5160. }
  5161. sock.setown(newsock);
  5162. return true;
  5163. }
  5164. bool CSingletonSocketConnection::send(MemoryBuffer &mb)
  5165. {
  5166. CriticalBlock block(crit);
  5167. if (cancelling)
  5168. state = Scancelled;
  5169. if (state==Scancelled)
  5170. return false;
  5171. assertex(sock);
  5172. state = Srecv;
  5173. try {
  5174. CriticalUnblock unblock(crit);
  5175. writeBuffer(sock,mb);
  5176. }
  5177. catch (IException * e) {
  5178. state = Scancelled;
  5179. EXCLOG(e,"CSingletonSocketConnection::send");
  5180. e->Release();
  5181. return false;
  5182. }
  5183. state = Snone;
  5184. return true;
  5185. }
  5186. unsigned short CSingletonSocketConnection::setRandomPort(unsigned short base, unsigned num)
  5187. {
  5188. for (;;) {
  5189. try {
  5190. ep.port = base+(unsigned short)(getRandom()%num);
  5191. listensock.setown(ISocket::create(ep.port));
  5192. return ep.port;
  5193. }
  5194. catch (IException *e) {
  5195. if (e->errorCode()!=JSOCKERR_port_in_use) {
  5196. state = Scancelled;
  5197. EXCLOG(e,"CSingletonSocketConnection::setRandomPort");
  5198. e->Release();
  5199. break;
  5200. }
  5201. e->Release();
  5202. }
  5203. }
  5204. return 0;
  5205. }
  5206. bool CSingletonSocketConnection::accept(unsigned timeoutms)
  5207. {
  5208. CriticalBlock block(crit);
  5209. if (cancelling)
  5210. state = Scancelled;
  5211. if (state==Scancelled)
  5212. return false;
  5213. if (!sock) {
  5214. ISocket *newsock=NULL;
  5215. state = Saccept;
  5216. for (;;) {
  5217. try {
  5218. {
  5219. CriticalUnblock unblock(crit);
  5220. if (!listensock)
  5221. listensock.setown(ISocket::create(ep.port));
  5222. if ((timeoutms!=(unsigned)INFINITE)&&(!listensock->wait_read(timeoutms))) {
  5223. state = Snone;
  5224. return false;
  5225. }
  5226. }
  5227. if (cancelling)
  5228. state = Scancelled;
  5229. if (state==Scancelled)
  5230. return false;
  5231. {
  5232. CriticalUnblock unblock(crit);
  5233. newsock=listensock->accept(true);
  5234. break;
  5235. }
  5236. }
  5237. catch (IException *e) {
  5238. if (e->errorCode()==JSOCKERR_graceful_close)
  5239. PROGLOG("CSingletonSocketConnection: Closed socket on accept - retrying...");
  5240. else {
  5241. state = Scancelled;
  5242. EXCLOG(e,"CSingletonSocketConnection::accept");
  5243. e->Release();
  5244. break;
  5245. }
  5246. e->Release();
  5247. }
  5248. }
  5249. if (state!=Saccept) {
  5250. ::Release(newsock);
  5251. newsock = NULL;
  5252. }
  5253. if (!newsock) {
  5254. state = Scancelled;
  5255. return false;
  5256. }
  5257. sock.setown(newsock);
  5258. }
  5259. return true;
  5260. }
  5261. bool CSingletonSocketConnection::recv(MemoryBuffer &mb, unsigned timeoutms)
  5262. {
  5263. CriticalBlock block(crit);
  5264. if (cancelling)
  5265. state = Scancelled;
  5266. if (state==Scancelled)
  5267. return false;
  5268. assertex(sock);
  5269. state = Srecv;
  5270. try {
  5271. CriticalUnblock unblock(crit);
  5272. readBuffer(sock,mb,timeoutms);
  5273. }
  5274. catch (IException *e) {
  5275. if (e->errorCode()==JSOCKERR_timeout_expired)
  5276. state = Snone;
  5277. else {
  5278. state = Scancelled;
  5279. if (e->errorCode()!=JSOCKERR_graceful_close)
  5280. EXCLOG(e,"CSingletonSocketConnection::recv");
  5281. }
  5282. e->Release();
  5283. return false;
  5284. }
  5285. state = Snone;
  5286. return true;
  5287. }
  5288. void CSingletonSocketConnection::cancel()
  5289. {
  5290. CriticalBlock block(crit);
  5291. while (state!=Scancelled) {
  5292. cancelling = true;
  5293. try {
  5294. switch (state) {
  5295. case Saccept:
  5296. {
  5297. if (listensock)
  5298. listensock->cancel_accept();
  5299. }
  5300. break;
  5301. case Sconnect:
  5302. // wait for timeout
  5303. break;
  5304. case Srecv:
  5305. {
  5306. if (sock)
  5307. sock->close();
  5308. }
  5309. break;
  5310. case Ssend:
  5311. // wait for finished
  5312. break;
  5313. default:
  5314. state = Scancelled;
  5315. break;
  5316. }
  5317. }
  5318. catch (IException *e) {
  5319. EXCLOG(e,"CSingletonSocketConnection::cancel");
  5320. e->Release();
  5321. }
  5322. {
  5323. CriticalUnblock unblock(crit);
  5324. Sleep(1000);
  5325. }
  5326. }
  5327. }
  5328. IConversation *createSingletonSocketConnection(unsigned short port,SocketEndpoint *_ep)
  5329. {
  5330. SocketEndpoint ep;
  5331. if (_ep)
  5332. ep = *_ep;
  5333. if (port)
  5334. ep.port = port;
  5335. return new CSingletonSocketConnection(ep);
  5336. }
  5337. // interface for reading from multiple sockets using the BF_SYNC_TRANSFER_PUSH protocol
  5338. class CSocketBufferReader: implements ISocketBufferReader, public CInterface
  5339. {
  5340. class SocketElem: implements ISocketSelectNotify, public CInterface
  5341. {
  5342. CSocketBufferReader *parent;
  5343. unsigned num; // top bit used for ready
  5344. MemoryAttr blk;
  5345. CriticalSection sect;
  5346. Linked<ISocket> sock;
  5347. bool active;
  5348. bool pending;
  5349. public:
  5350. IMPLEMENT_IINTERFACE;
  5351. void init(CSocketBufferReader *_parent,ISocket *_sock,unsigned _n)
  5352. {
  5353. parent = _parent;
  5354. num = _n;
  5355. sock.set(_sock);
  5356. active = true;
  5357. pending = false;
  5358. }
  5359. virtual bool notifySelected(ISocket *socket,unsigned selected)
  5360. {
  5361. assertex(sock==socket);
  5362. {
  5363. CriticalBlock block(sect);
  5364. if (pending) {
  5365. active = false;
  5366. parent->remove(sock);
  5367. return false;
  5368. }
  5369. pending = true;
  5370. unsigned t1=usTick();
  5371. size32_t sz = sock->receive_block_size();
  5372. unsigned t2=usTick();
  5373. if (sz)
  5374. sock->receive_block(blk.allocate(sz),sz);
  5375. else
  5376. parent->remove(sock);
  5377. unsigned t3=usTick();
  5378. if (t3-t1>60*1000000)
  5379. PROGLOG("CSocketBufferReader(%d): slow receive_block (%d,%d) sz=%d",num,t2-t1,t3-t2,sz);
  5380. }
  5381. parent->enqueue(this); // nb outside sect critical block
  5382. return false; // always return false
  5383. }
  5384. unsigned get(MemoryBuffer &mb)
  5385. {
  5386. CriticalBlock block(sect);
  5387. assertex(pending);
  5388. size32_t sz = (size32_t)blk.length();
  5389. if (sz)
  5390. mb.setBuffer(sz,blk.detach(),true);
  5391. pending = false;
  5392. if (!active) {
  5393. active = true;
  5394. parent->add(*this);
  5395. }
  5396. return num;
  5397. }
  5398. size32_t size()
  5399. {
  5400. return (size32_t)blk.length();
  5401. }
  5402. ISocket *getSocket() { return sock; }
  5403. } *elems;
  5404. SimpleInterThreadQueueOf<SocketElem, false> readyq;
  5405. Owned<ISocketSelectHandler> selecthandler;
  5406. size32_t buffersize;
  5407. size32_t buffermax;
  5408. unsigned bufferwaiting;
  5409. CriticalSection buffersect;
  5410. Semaphore buffersem;
  5411. bool isdone;
  5412. public:
  5413. IMPLEMENT_IINTERFACE;
  5414. CSocketBufferReader(const char *trc)
  5415. {
  5416. selecthandler.setown(createSocketSelectHandler(trc));
  5417. elems = NULL;
  5418. }
  5419. ~CSocketBufferReader()
  5420. {
  5421. delete [] elems;
  5422. }
  5423. virtual void init(unsigned num,ISocket **sockets,size32_t _buffermax)
  5424. {
  5425. elems = new SocketElem[num];
  5426. for (unsigned i=0;i<num;i++) {
  5427. ISocket *sock = sockets[i];
  5428. if (sock) { // can have gaps
  5429. elems[i].init(this,sock,i);
  5430. add(elems[i]);
  5431. }
  5432. }
  5433. buffersize = 0;
  5434. buffermax = _buffermax;
  5435. bufferwaiting = 0;
  5436. isdone = false;
  5437. selecthandler->start();
  5438. }
  5439. virtual unsigned get(MemoryBuffer &mb)
  5440. {
  5441. SocketElem &e = *readyq.dequeue();
  5442. CriticalBlock block(buffersect);
  5443. assertex(buffersize>=e.size());
  5444. buffersize-=e.size();
  5445. if (bufferwaiting) {
  5446. buffersem.signal(bufferwaiting);
  5447. bufferwaiting = 0;
  5448. }
  5449. return e.get(mb);
  5450. }
  5451. virtual void done(bool wait)
  5452. {
  5453. buffersem.signal(0x10000);
  5454. isdone = true;
  5455. selecthandler->stop(wait);
  5456. if (wait) {
  5457. delete [] elems;
  5458. elems = NULL;
  5459. }
  5460. }
  5461. void enqueue(SocketElem *elem)
  5462. {
  5463. if (elem) {
  5464. CriticalBlock block(buffersect);
  5465. size32_t sz = elem->size();
  5466. while ((buffersize>0)&&(sz>0)&&(buffersize+sz>buffermax)) {
  5467. if (isdone)
  5468. return;
  5469. bufferwaiting++;
  5470. CriticalUnblock unblock(buffersect);
  5471. buffersem.wait();
  5472. }
  5473. buffersize += sz;
  5474. }
  5475. readyq.enqueue(elem);
  5476. }
  5477. void remove(ISocket *sock)
  5478. {
  5479. selecthandler->remove(sock);
  5480. }
  5481. void add(SocketElem &elem)
  5482. {
  5483. selecthandler->add(elem.getSocket(),SELECTMODE_READ,&elem);
  5484. }
  5485. };
  5486. ISocketBufferReader *createSocketBufferReader(const char *trc)
  5487. {
  5488. return new CSocketBufferReader(trc);
  5489. }
  5490. extern jlib_decl void markNodeCentral(SocketEndpoint &ep)
  5491. {
  5492. #ifdef CENTRAL_NODE_RANDOM_DELAY
  5493. CriticalBlock block(CSocket::crit);
  5494. CentralNodeArray.append(ep);
  5495. #endif
  5496. }
  5497. static CSocket *prepareSocket(unsigned idx,const SocketEndpoint &ep, ISocketConnectNotify &inotify)
  5498. {
  5499. Owned<CSocket> sock = new CSocket(ep,sm_tcp,NULL);
  5500. int err = sock->pre_connect(false);
  5501. if ((err == JSE_INPROGRESS)||(err == JSE_WOULDBLOCK))
  5502. return sock.getClear();
  5503. if (err==0) {
  5504. int err = sock->post_connect();
  5505. if (err==0)
  5506. inotify.connected(idx,ep,sock);
  5507. else {
  5508. sock->errclose();
  5509. inotify.failed(idx,ep,err);
  5510. }
  5511. }
  5512. else
  5513. inotify.failed(idx,ep,err);
  5514. return NULL;
  5515. }
  5516. void multiConnect(const SocketEndpointArray &eps,ISocketConnectNotify &inotify,unsigned timeout)
  5517. {
  5518. class SocketElem: implements ISocketSelectNotify, public CInterface
  5519. {
  5520. CriticalSection *sect;
  5521. ISocketSelectHandler *handler;
  5522. unsigned *remaining;
  5523. Semaphore *notifysem;
  5524. ISocketConnectNotify *inotify;
  5525. public:
  5526. Owned<CSocket> sock;
  5527. SocketEndpoint ep;
  5528. unsigned idx;
  5529. IMPLEMENT_IINTERFACE;
  5530. void init(CSocket *_sock,unsigned _idx,const SocketEndpoint &_ep,CriticalSection *_sect,ISocketSelectHandler *_handler,ISocketConnectNotify *_inotify, unsigned *_remaining, Semaphore *_notifysem)
  5531. {
  5532. ep = _ep;
  5533. idx = _idx;
  5534. inotify = _inotify;
  5535. sock.setown(_sock),
  5536. sect = _sect;
  5537. handler = _handler;
  5538. remaining = _remaining;
  5539. notifysem = _notifysem;
  5540. }
  5541. virtual bool notifySelected(ISocket *socket,unsigned selected)
  5542. {
  5543. CriticalBlock block(*sect);
  5544. handler->remove(socket);
  5545. int err = sock->post_connect();
  5546. CSocket *newsock = NULL;
  5547. {
  5548. CriticalUnblock unblock(*sect); // up to caller to cope with multithread
  5549. if (err==0)
  5550. inotify->connected(idx,ep,sock);
  5551. else if ((err==JSE_TIMEDOUT)||(err==JSE_CONNREFUSED)) {
  5552. // don't give up so easily (maybe listener not yet started (i.e. racing))
  5553. newsock = prepareSocket(idx,ep,*inotify);
  5554. Sleep(100); // not very nice but without this would just loop
  5555. }
  5556. else
  5557. inotify->failed(idx,ep,err);
  5558. }
  5559. if (newsock) {
  5560. sock.setown(newsock);
  5561. handler->add(sock,SELECTMODE_WRITE|SELECTMODE_EXCEPT,this);
  5562. }
  5563. else {
  5564. sock.clear();
  5565. (*remaining)--;
  5566. notifysem->signal();
  5567. }
  5568. return false;
  5569. }
  5570. } *elems;
  5571. unsigned n = eps.ordinality();
  5572. unsigned remaining = n;
  5573. if (!n)
  5574. return;
  5575. elems = new SocketElem[n];
  5576. unsigned i;
  5577. CriticalSection sect;
  5578. Semaphore notifysem;
  5579. Owned<ISocketSelectHandler> selecthandler = createSocketSelectHandler(
  5580. #ifdef _DEBUG
  5581. "multiConnect"
  5582. #else
  5583. NULL
  5584. #endif
  5585. );
  5586. StringBuffer name;
  5587. for (i=0;i<n;i++) {
  5588. CSocket* sock = prepareSocket(i,eps.item(i),inotify);
  5589. if (sock) {
  5590. elems[i].init(sock,i,eps.item(i),&sect,selecthandler,&inotify,&remaining,&notifysem);
  5591. selecthandler->add(sock,SELECTMODE_WRITE|SELECTMODE_EXCEPT,&elems[i]);
  5592. }
  5593. else
  5594. remaining--;
  5595. }
  5596. if (remaining) {
  5597. unsigned lastremaining=remaining;
  5598. selecthandler->start();
  5599. for (;;) {
  5600. bool to=!notifysem.wait(timeout);
  5601. {
  5602. CriticalBlock block(sect);
  5603. if (remaining==0)
  5604. break;
  5605. if (to&&(remaining==lastremaining))
  5606. break; // nothing happened recently
  5607. lastremaining = remaining;
  5608. }
  5609. }
  5610. selecthandler->stop(true);
  5611. }
  5612. selecthandler.clear();
  5613. if (remaining) {
  5614. for (unsigned j=0;j<n;j++) { // mop up timeouts
  5615. SocketElem &elem = elems[j];
  5616. if (elem.sock.get()) {
  5617. elem.sock.clear();
  5618. inotify.failed(j,elem.ep,-1);
  5619. remaining--;
  5620. if (remaining==0)
  5621. break;
  5622. }
  5623. }
  5624. }
  5625. delete [] elems;
  5626. }
  5627. void multiConnect(const SocketEndpointArray &eps, IPointerArrayOf<ISocket> &retsockets,unsigned timeout)
  5628. {
  5629. unsigned n = eps.ordinality();
  5630. if (n==0)
  5631. return;
  5632. if (n==1) { // no need for multi
  5633. ISocket *sock = NULL;
  5634. try {
  5635. sock = ISocket::connect_timeout(eps.item(0),timeout);
  5636. }
  5637. catch (IException *e) { // ignore error just append NULL
  5638. sock = NULL;
  5639. e->Release();
  5640. }
  5641. retsockets.append(sock);
  5642. return;
  5643. }
  5644. while (retsockets.ordinality()<n)
  5645. retsockets.append(NULL);
  5646. CriticalSection sect;
  5647. class cNotify: implements ISocketConnectNotify
  5648. {
  5649. CriticalSection &sect;
  5650. IPointerArrayOf<ISocket> &retsockets;
  5651. public:
  5652. cNotify(IPointerArrayOf<ISocket> &_retsockets,CriticalSection &_sect)
  5653. : sect(_sect), retsockets(_retsockets)
  5654. {
  5655. }
  5656. void connected(unsigned idx,const SocketEndpoint &ep,ISocket *sock)
  5657. {
  5658. CriticalBlock block(sect);
  5659. assertex(idx<retsockets.ordinality());
  5660. sock->Link();
  5661. retsockets.replace(sock,idx);
  5662. }
  5663. void failed(unsigned idx,const SocketEndpoint &ep,int err)
  5664. {
  5665. StringBuffer s;
  5666. PROGLOG("multiConnect failed to %s with %d",ep.getUrlStr(s).str(),err);
  5667. }
  5668. } notify(retsockets,sect);
  5669. multiConnect(eps,notify,timeout);
  5670. }
  5671. inline void flushText(StringBuffer &text,unsigned short port,unsigned &rep,unsigned &range)
  5672. {
  5673. if (rep) {
  5674. text.append('*').append(rep+1);
  5675. rep = 0;
  5676. }
  5677. else if (range) {
  5678. text.append('-').append(range);
  5679. range = 0;
  5680. }
  5681. if (port)
  5682. text.append(':').append(port);
  5683. }
  5684. StringBuffer &SocketEndpointArray::getText(StringBuffer &text) const
  5685. {
  5686. unsigned count = ordinality();
  5687. if (!count)
  5688. return text;
  5689. if (count==1)
  5690. return item(0).getUrlStr(text);
  5691. byte lastip[4];
  5692. const SocketEndpoint &first = item(0);
  5693. bool lastis4 = first.getNetAddress(sizeof(lastip),&lastip)==sizeof(lastip);
  5694. unsigned short lastport = first.port;
  5695. first.getIpText(text);
  5696. unsigned rep=0;
  5697. unsigned range=0;
  5698. for (unsigned i=1;i<count;i++) {
  5699. byte ip[4];
  5700. const SocketEndpoint &ep = item(i);
  5701. bool is4 = ep.getNetAddress(sizeof(ip),&ip)==sizeof(ip);
  5702. if (!lastis4||!is4) {
  5703. flushText(text,lastport,rep,range);
  5704. text.append(',');
  5705. ep.getIpText(text);
  5706. }
  5707. else { // try and shorten
  5708. unsigned j;
  5709. for (j=0;j<4;j++)
  5710. if (ip[j]!=lastip[j])
  5711. break;
  5712. if (ep.port==lastport) {
  5713. if (j==4) {
  5714. if (range) // cant have range and rep
  5715. j--; // pretend only 3 matched
  5716. else {
  5717. rep++;
  5718. continue;
  5719. }
  5720. }
  5721. else if ((j==3)&&(lastip[3]+1==ip[3])&&(rep==0)) {
  5722. range = ip[3];
  5723. lastip[3] = (byte)range;
  5724. continue;
  5725. }
  5726. }
  5727. flushText(text,lastport,rep,range);
  5728. // output diff
  5729. text.append(',');
  5730. if (j==4)
  5731. j--;
  5732. for (unsigned k=j;k<4;k++) {
  5733. if (k>j)
  5734. text.append('.');
  5735. text.append((int)ip[k]);
  5736. }
  5737. }
  5738. memcpy(&lastip,&ip,sizeof(lastip));
  5739. lastis4 = is4;
  5740. lastport = ep.port;
  5741. }
  5742. flushText(text,lastport,rep,range);
  5743. return text;
  5744. }
  5745. inline const char *getnum(const char *s,unsigned &n)
  5746. {
  5747. n = 0;
  5748. while (isdigit(*s)) {
  5749. n = n*10+(*s-'0');
  5750. s++;
  5751. }
  5752. return s;
  5753. }
  5754. inline bool appendv4range(SocketEndpointArray *array,char *str,SocketEndpoint &ep, unsigned defport)
  5755. {
  5756. char *s = str;
  5757. unsigned dc = 0;
  5758. unsigned port = defport;
  5759. unsigned rng = 0;
  5760. unsigned rep = 1;
  5761. bool notip = false;
  5762. while (*s) {
  5763. if (*s=='.') {
  5764. dc++;
  5765. s++;
  5766. }
  5767. else if (*s==':') {
  5768. *s = 0;
  5769. s = (char *)getnum(s+1,port);
  5770. }
  5771. else if (*s=='-')
  5772. {
  5773. if (!notip)//don't assume '-' is an ip range delimiter
  5774. { //Allow '-' in any octet due to ip group support
  5775. *s = 0;
  5776. s = (char *)getnum(s+1,rng);
  5777. }
  5778. else
  5779. {
  5780. notip = true;
  5781. s++;
  5782. }
  5783. }
  5784. else if (*s=='*') {
  5785. *s = 0;
  5786. s = (char *)getnum(s+1,rep);
  5787. }
  5788. else {
  5789. if (!isdigit(*s))
  5790. notip = true;
  5791. s++;
  5792. }
  5793. }
  5794. ep.port = port;
  5795. if (*str) {
  5796. if (!notip&&((dc<3)&&((dc!=1)||(strlen(str)!=1)))) {
  5797. if (!ep.isIp4()) {
  5798. return false;
  5799. }
  5800. StringBuffer tmp;
  5801. ep.getIpText(tmp);
  5802. dc++;
  5803. for (;;) {
  5804. if (tmp.length()==0)
  5805. return false;
  5806. if (tmp.charAt(tmp.length()-1)=='.')
  5807. if (--dc==0)
  5808. break;
  5809. tmp.setLength(tmp.length()-1);
  5810. }
  5811. tmp.append(str);
  5812. if (rng) {
  5813. tmp.appendf("-%d",rng);
  5814. rep = ep.ipsetrange(tmp.str());
  5815. }
  5816. else
  5817. ep.ipset(tmp.str());
  5818. }
  5819. else if (rng) { // not nice as have to add back range (must be better way - maybe ipincrementto) TBD
  5820. StringBuffer tmp;
  5821. tmp.appendf("%s-%d",str,rng);
  5822. rep = ep.ipsetrange(tmp.str());
  5823. }
  5824. else if (*str)
  5825. ep.ipset(str);
  5826. if (ep.isNull())
  5827. ep.port = 0;
  5828. for (unsigned i=0;i<rep;i++) {
  5829. array->append(ep);
  5830. if (rng)
  5831. ep.ipincrement(1);
  5832. }
  5833. }
  5834. else {// just a port change
  5835. if (ep.isNull()) // avoid null values with ports
  5836. ep.port = 0;
  5837. array->append(ep);
  5838. }
  5839. return true;
  5840. }
  5841. bool SocketEndpointArray::fromName(const char *name, unsigned defport)
  5842. {
  5843. // Lookup a single name that may resolve to multiple IPs in a headless service scenario
  5844. StringArray portSplit;
  5845. portSplit.appendList(name, ":");
  5846. switch (portSplit.ordinality())
  5847. {
  5848. case 2:
  5849. defport = atoi(portSplit.item(1));
  5850. name = portSplit.item(0);
  5851. // fallthrough
  5852. case 1:
  5853. break;
  5854. default:
  5855. throw MakeStringException(-1, "Invalid name %s SocketEndpointArray::fromName", name);
  5856. }
  5857. #if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo)
  5858. if (IP4only)
  5859. #endif
  5860. {
  5861. CriticalBlock c(hostnamesect);
  5862. hostent * entry = gethostbyname(name);
  5863. if (entry && entry->h_addr_list[0])
  5864. {
  5865. unsigned ptr = 0;
  5866. for (;;)
  5867. {
  5868. ptr++;
  5869. if (entry->h_addr_list[ptr]==NULL)
  5870. break;
  5871. SocketEndpoint ep;
  5872. ep.setNetAddress(sizeof(unsigned),entry->h_addr_list[ptr]);
  5873. ep.port = defport;
  5874. append(ep);
  5875. }
  5876. }
  5877. return ordinality()>0;
  5878. }
  5879. #if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo)
  5880. struct addrinfo hints;
  5881. memset(&hints,0,sizeof(hints));
  5882. struct addrinfo *addrInfo = NULL;
  5883. memset(&hints,0,sizeof(hints));
  5884. int ret = getaddrinfo(name, NULL , &hints, &addrInfo);
  5885. if (ret == 0)
  5886. {
  5887. struct addrinfo *ai;
  5888. for (ai = addrInfo; ai; ai = ai->ai_next)
  5889. {
  5890. // DBGLOG("flags=%d, family=%d, socktype=%d, protocol=%d, addrlen=%d, canonname=%s",ai->ai_flags,ai->ai_family,ai->ai_socktype,ai->ai_protocol,ai->ai_addrlen,ai->ai_canonname?ai->ai_canonname:"NULL");
  5891. if (ai->ai_protocol == IPPROTO_IP)
  5892. {
  5893. switch (ai->ai_family)
  5894. {
  5895. case AF_INET:
  5896. {
  5897. SocketEndpoint ep;
  5898. ep.setNetAddress(sizeof(in_addr),&(((sockaddr_in *)ai->ai_addr)->sin_addr));
  5899. ep.port = defport;
  5900. append(ep);
  5901. // StringBuffer s;
  5902. // DBGLOG("Lookup %s found %s", name, ep.getUrlStr(s).str());
  5903. break;
  5904. }
  5905. case AF_INET6:
  5906. {
  5907. SocketEndpoint ep;
  5908. ep.setNetAddress(sizeof(in_addr6),&(((sockaddr_in6 *)ai->ai_addr)->sin6_addr));
  5909. ep.port = defport;
  5910. append(ep);
  5911. break;
  5912. }
  5913. }
  5914. }
  5915. }
  5916. }
  5917. freeaddrinfo(addrInfo);
  5918. #endif
  5919. return ordinality()>0;
  5920. }
  5921. void SocketEndpointArray::fromText(const char *text,unsigned defport)
  5922. {
  5923. // this is quite complicated with (mixed) IPv4 and IPv6
  5924. // only support 'full' IPv6 and no ranges
  5925. if (!text)
  5926. return;
  5927. char *str = strdup(text);
  5928. char *s = str;
  5929. SocketEndpoint ep;
  5930. bool eol = false;
  5931. for (;;) {
  5932. while (isspace(*s)||(*s==','))
  5933. s++;
  5934. if (!*s)
  5935. break;
  5936. char *e=s;
  5937. if (*e=='[') { // we have a IPv6
  5938. while (*e&&(*e!=']'))
  5939. e++;
  5940. while ((*e!=',')&&!isspace(*e)) {
  5941. if (!*s) {
  5942. eol = true;
  5943. break;
  5944. }
  5945. e++;
  5946. }
  5947. *e = 0;
  5948. ep.set(s,defport);
  5949. if (ep.isNull()) {
  5950. // Error TBD
  5951. }
  5952. append(ep);
  5953. }
  5954. else {
  5955. bool hascolon = false;
  5956. bool isv6 = false;
  5957. do {
  5958. if (*e==':') {
  5959. if (hascolon)
  5960. isv6 = true;
  5961. else
  5962. hascolon = true;
  5963. }
  5964. e++;
  5965. if (!*e) {
  5966. eol = true;
  5967. break;
  5968. }
  5969. } while (!isspace(*e)&&(*e!=','));
  5970. *e = 0;
  5971. if (isv6) {
  5972. ep.set(s,defport);
  5973. if (ep.isNull()) {
  5974. // Error TBD
  5975. }
  5976. append(ep);
  5977. }
  5978. else {
  5979. if (!appendv4range(this,s,ep,defport)) {
  5980. // Error TBD
  5981. }
  5982. }
  5983. }
  5984. if (eol)
  5985. break;
  5986. s = e+1;
  5987. }
  5988. free(str);
  5989. }
  5990. bool IpSubNet::set(const char *_net,const char *_mask)
  5991. {
  5992. if (!_net||!decodeNumericIP(_net,net)) { // _net NULL means match everything
  5993. memset(net,0,sizeof(net));
  5994. memset(mask,0,sizeof(mask));
  5995. return (_net==NULL);
  5996. }
  5997. if (!_mask||!decodeNumericIP(_mask,mask)) { // _mask NULL means match exact
  5998. memset(mask,0xff,sizeof(mask));
  5999. return (_mask==NULL);
  6000. }
  6001. if (isIp4(net)!=isIp4(mask))
  6002. return false;
  6003. for (unsigned j=0;j<4;j++)
  6004. if (net[j]&~mask[j])
  6005. return false;
  6006. return true;
  6007. }
  6008. bool IpSubNet::test(const IpAddress &ip) const
  6009. {
  6010. unsigned i;
  6011. if (ip.getNetAddress(sizeof(i),&i)==sizeof(i)) {
  6012. if (!isIp4(net))
  6013. return false;
  6014. return (i&mask[3])==(net[3]&mask[3]);
  6015. }
  6016. unsigned na[4];
  6017. if (ip.getNetAddress(sizeof(na),&na)==sizeof(na)) {
  6018. for (unsigned j=0;j<4;j++)
  6019. if ((na[j]&mask[j])!=(net[j]&mask[j]))
  6020. return false;
  6021. return true;
  6022. }
  6023. return false;
  6024. }
  6025. StringBuffer &IpSubNet::getNetText(StringBuffer &text) const
  6026. {
  6027. char tmp[INET6_ADDRSTRLEN];
  6028. const char *res = ::isIp4(net) ? _inet_ntop(AF_INET, &net[3], tmp, sizeof(tmp))
  6029. : _inet_ntop(AF_INET6, &net, tmp, sizeof(tmp));
  6030. return text.append(res);
  6031. }
  6032. StringBuffer &IpSubNet::getMaskText(StringBuffer &text) const
  6033. {
  6034. char tmp[INET6_ADDRSTRLEN];
  6035. // isIp4(net) is correct here
  6036. const char *res = ::isIp4(net) ? _inet_ntop(AF_INET, &mask[3], tmp, sizeof(tmp))
  6037. : _inet_ntop(AF_INET6, &mask, tmp, sizeof(tmp));
  6038. return text.append(res);
  6039. }
  6040. bool IpSubNet::isNull() const
  6041. {
  6042. for (unsigned i=0;i<4;i++)
  6043. if (net[i]||mask[i])
  6044. return false;
  6045. return true;
  6046. }
  6047. IpSubNet &queryPreferredSubnet()
  6048. {
  6049. return PreferredSubnet;
  6050. }
  6051. bool setPreferredSubnet(const char *ip,const char *mask)
  6052. {
  6053. // also resets cached host IP
  6054. if (PreferredSubnet.set(ip,mask))
  6055. {
  6056. if (!cachehostip.isNull())
  6057. {
  6058. cachehostip.ipset(NULL);
  6059. queryHostIP();
  6060. }
  6061. return true;
  6062. }
  6063. else
  6064. return false;
  6065. }
  6066. StringBuffer &lookupHostName(const IpAddress &ip,StringBuffer &ret)
  6067. {
  6068. // not a common routine (no Jlib function!) only support IPv4 initially
  6069. unsigned ipa;
  6070. if (ip.getNetAddress(sizeof(ipa),&ipa)==sizeof(ipa)) {
  6071. struct hostent *phostent = gethostbyaddr( (char *) &ipa, sizeof(ipa), PF_INET);
  6072. if (phostent)
  6073. ret.append(phostent->h_name);
  6074. else
  6075. ip.getIpText(ret);
  6076. }
  6077. else
  6078. ip.getIpText(ret);
  6079. return ret;
  6080. }
  6081. struct SocketEndpointHTElem
  6082. {
  6083. IInterface *ii;
  6084. SocketEndpoint ep;
  6085. SocketEndpointHTElem(const SocketEndpoint _ep,IInterface *_ii) { ep.set(_ep); ii = _ii; }
  6086. ~SocketEndpointHTElem() { ::Release(ii); }
  6087. };
  6088. class jlib_decl CSocketEndpointHashTable : public SuperHashTableOf<SocketEndpointHTElem, SocketEndpoint>, implements ISocketEndpointHashTable
  6089. {
  6090. virtual void onAdd(void *) {}
  6091. virtual void onRemove(void *e) { delete (SocketEndpointHTElem *)e; }
  6092. unsigned getHashFromElement(const void *e) const
  6093. {
  6094. return ((const SocketEndpointHTElem *)e)->ep.hash(0);
  6095. }
  6096. unsigned getHashFromFindParam(const void *fp) const
  6097. {
  6098. return ((const SocketEndpoint *)fp)->hash(0);
  6099. }
  6100. const void * getFindParam(const void *p) const
  6101. {
  6102. return &((const SocketEndpointHTElem *)p)->ep;
  6103. }
  6104. bool matchesFindParam(const void * et, const void *fp, unsigned) const
  6105. {
  6106. return ((const SocketEndpointHTElem *)et)->ep.equals(*(SocketEndpoint *)fp);
  6107. }
  6108. IMPLEMENT_SUPERHASHTABLEOF_REF_FIND(SocketEndpointHTElem,SocketEndpoint);
  6109. public:
  6110. IMPLEMENT_IINTERFACE;
  6111. CSocketEndpointHashTable() {}
  6112. ~CSocketEndpointHashTable() { _releaseAll(); }
  6113. void add(const SocketEndpoint &ep, IInterface *i)
  6114. {
  6115. SocketEndpointHTElem *e = SuperHashTableOf<SocketEndpointHTElem,SocketEndpoint>::find(&ep);
  6116. if (e) {
  6117. ::Release(e->ii);
  6118. e->ii = i;
  6119. }
  6120. else {
  6121. e = new SocketEndpointHTElem(ep,i);
  6122. SuperHashTableOf<SocketEndpointHTElem,SocketEndpoint>::add(*e);
  6123. }
  6124. }
  6125. void remove(const SocketEndpoint &ep)
  6126. {
  6127. SuperHashTableOf<SocketEndpointHTElem,SocketEndpoint>::remove(&ep);
  6128. }
  6129. IInterface *find(const SocketEndpoint &ep)
  6130. {
  6131. SocketEndpointHTElem *e = SuperHashTableOf<SocketEndpointHTElem,SocketEndpoint>::find(&ep);
  6132. if (e)
  6133. return e->ii;
  6134. return NULL;
  6135. }
  6136. };
  6137. ISocketEndpointHashTable *createSocketEndpointHashTable()
  6138. {
  6139. CSocketEndpointHashTable *ht = new CSocketEndpointHashTable;
  6140. return ht;
  6141. }
  6142. class CSocketConnectWait: implements ISocketConnectWait, public CInterface
  6143. {
  6144. Owned<CSocket> sock;
  6145. bool done;
  6146. CTimeMon connecttm;
  6147. unsigned startt;
  6148. bool oneshot;
  6149. bool isopen;
  6150. int initerr;
  6151. void successfulConnect()
  6152. {
  6153. STATS.connects++;
  6154. STATS.connecttime+=usTick()-startt;
  6155. #ifdef _TRACE
  6156. sock->setTraceName();
  6157. #endif
  6158. }
  6159. void failedConnect()
  6160. {
  6161. STATS.failedconnects++;
  6162. STATS.failedconnecttime+=usTick()-startt;
  6163. const char* tracename = sock->tracename;
  6164. THROWJSOCKEXCEPTION(JSOCKERR_connection_failed);
  6165. }
  6166. public:
  6167. IMPLEMENT_IINTERFACE;
  6168. CSocketConnectWait(SocketEndpoint &ep,unsigned connecttimeoutms)
  6169. : connecttm(connecttimeoutms)
  6170. {
  6171. oneshot = (connecttimeoutms==0); // i.e. as long as one connect takes
  6172. done = false;
  6173. startt = usTick();
  6174. sock.setown(new CSocket(ep,sm_tcp,NULL));
  6175. isopen = true;
  6176. initerr = sock->pre_connect(false);
  6177. }
  6178. ISocket *wait(unsigned timems)
  6179. {
  6180. // this is a bit spagetti due to dual timeouts etc
  6181. CTimeMon waittm(timems);
  6182. unsigned refuseddelay = 1;
  6183. bool waittimedout = false;
  6184. bool connectimedout = false;
  6185. do {
  6186. bool connectdone = false;
  6187. unsigned remaining;
  6188. connectimedout = connecttm.timedout(&remaining);
  6189. unsigned waitremaining;
  6190. waittimedout = waittm.timedout(&waitremaining);
  6191. if (oneshot||(waitremaining<remaining))
  6192. remaining = waitremaining;
  6193. int err = 0;
  6194. if (!isopen||initerr)
  6195. {
  6196. isopen = true;
  6197. err = initerr?initerr:sock->pre_connect(false);
  6198. initerr = 0;
  6199. if ((err == JSE_INPROGRESS)||(err == JSE_WOULDBLOCK))
  6200. err = 0; // continue
  6201. else
  6202. {
  6203. if (err==0)
  6204. connectdone = true; // done immediately
  6205. else if(!oneshot) // probably ECONNREFUSED but treat all errors same
  6206. refused_sleep((waitremaining==remaining)?waittm:connecttm,refuseddelay); // this stops becoming cpu bound
  6207. }
  6208. }
  6209. if (!connectdone&&(err==0))
  6210. {
  6211. SOCKET s = sock->sock;
  6212. #ifdef _USE_SELECT
  6213. CHECKSOCKRANGE(s);
  6214. T_FD_SET fds;
  6215. struct timeval tv;
  6216. XFD_ZERO(&fds);
  6217. FD_SET((unsigned)s, &fds);
  6218. T_FD_SET except;
  6219. XFD_ZERO(&except);
  6220. FD_SET((unsigned)s, &except);
  6221. tv.tv_sec = remaining / 1000;
  6222. tv.tv_usec = (remaining % 1000)*1000;
  6223. int rc = ::select( s + 1, NULL, (fd_set *)&fds, (fd_set *)&except, &tv );
  6224. #else
  6225. struct pollfd fds[1];
  6226. fds[0].fd = s;
  6227. fds[0].events = POLLOUT;
  6228. fds[0].revents = 0;
  6229. int rc = ::poll(fds, 1, remaining);
  6230. #endif
  6231. if (rc==0)
  6232. break; // timeout
  6233. done = true;
  6234. err = 0;
  6235. if (rc>0)
  6236. {
  6237. // select/poll succeeded - return error from socket (0 if connected)
  6238. socklen_t errlen = sizeof(err);
  6239. rc = getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); // check for error
  6240. if ((rc!=0)&&!err)
  6241. err = ERRNO(); // some implementations of getsockopt duff
  6242. if (err&&!oneshot) // probably ECONNREFUSED but treat all errors same
  6243. refused_sleep((waitremaining==remaining)?waittm:connecttm,refuseddelay); // this stops becoming cpu bound
  6244. }
  6245. else
  6246. { // select/poll failed
  6247. err = ERRNO();
  6248. if (err != JSE_INTR)
  6249. {
  6250. LOGERR(err,2,"CSocketConnectWait ::select/poll");
  6251. sock->errclose();
  6252. isopen = false;
  6253. if (!oneshot)
  6254. connectimedout = true;
  6255. break;
  6256. }
  6257. }
  6258. }
  6259. if (err==0)
  6260. {
  6261. err = sock->post_connect();
  6262. if (err==0)
  6263. {
  6264. successfulConnect();
  6265. return sock.getClear();
  6266. }
  6267. }
  6268. sock->errclose();
  6269. isopen = false;
  6270. } while (!waittimedout&&!oneshot);
  6271. if (connectimedout)
  6272. {
  6273. STATS.failedconnects++;
  6274. STATS.failedconnecttime+=usTick()-startt;
  6275. const char* tracename = sock->tracename;
  6276. THROWJSOCKEXCEPTION(JSOCKERR_connection_failed);
  6277. }
  6278. return NULL;
  6279. }
  6280. };
  6281. ISocketConnectWait *nonBlockingConnect(SocketEndpoint &ep,unsigned connecttimeoutms)
  6282. {
  6283. return new CSocketConnectWait(ep,connecttimeoutms);
  6284. }
  6285. int wait_multiple(bool isRead, //IN true if wait read, false it wait write
  6286. UnsignedArray &socks, //IN sockets to be checked for readiness
  6287. unsigned timeoutMS, //IN timeout
  6288. UnsignedArray &readySocks) //OUT sockets ready
  6289. {
  6290. aindex_t numSocks = socks.length();
  6291. if (numSocks == 0)
  6292. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  6293. #ifdef _DEBUG
  6294. StringBuffer dbgSB("wait_multiple() on sockets :");
  6295. #endif
  6296. #ifdef _USE_SELECT
  6297. SOCKET maxSocket = 0;
  6298. T_FD_SET fds;
  6299. XFD_ZERO(&fds);
  6300. //Add each SOCKET in array to T_FD_SET
  6301. for (aindex_t idx = 0; idx < numSocks; idx++)
  6302. {
  6303. #ifdef _DEBUG
  6304. dbgSB.appendf(" %d",socks.item(idx));
  6305. #endif
  6306. SOCKET s = socks.item(idx);
  6307. CHECKSOCKRANGE(s);
  6308. maxSocket = s > maxSocket ? s : maxSocket;
  6309. FD_SET((unsigned)s, &fds);
  6310. }
  6311. #else
  6312. struct pollfd *fds = nullptr;
  6313. try
  6314. {
  6315. fds = new pollfd[numSocks];
  6316. }
  6317. catch (const std::bad_alloc &e)
  6318. {
  6319. int err = ERRNO();
  6320. throw MakeStringException(-1,"wait_multiple::fds malloc failure %d", err);
  6321. }
  6322. for (aindex_t idx = 0; idx < numSocks; idx++)
  6323. {
  6324. #ifdef _DEBUG
  6325. dbgSB.appendf(" %d",socks.item(idx));
  6326. #endif
  6327. SOCKET s = socks.item(idx);
  6328. fds[idx].fd = s;
  6329. fds[idx].events = isRead ? POLLINX : POLLOUT;
  6330. fds[idx].revents = 0;
  6331. }
  6332. #endif
  6333. #ifdef _DEBUG
  6334. DBGLOG("%s",dbgSB.str());
  6335. #endif
  6336. //Check socket states
  6337. int res = 0;
  6338. #ifdef _USE_SELECT
  6339. if (timeoutMS == WAIT_FOREVER)
  6340. res = ::select( maxSocket + 1, isRead ? (fd_set *)&fds : NULL, isRead ? NULL : (fd_set *)&fds, NULL, NULL );
  6341. else
  6342. {
  6343. struct timeval tv;
  6344. tv.tv_sec = timeoutMS / 1000;
  6345. tv.tv_usec = (timeoutMS % 1000)*1000;
  6346. res = ::select( maxSocket + 1, isRead ? (fd_set *)&fds : NULL, isRead ? NULL : (fd_set *)&fds, NULL, &tv );
  6347. }
  6348. #else
  6349. res = poll(fds, numSocks, timeoutMS);
  6350. #endif
  6351. if (res > 0)
  6352. {
  6353. #ifdef _DEBUG
  6354. StringBuffer dbgSB("wait_multiple() ready socket(s) :");
  6355. #endif
  6356. //Build up list of socks which are ready for accept read/write without blocking
  6357. for (aindex_t idx = 0; idx < numSocks; idx++)
  6358. {
  6359. SOCKET s = socks.item(idx);
  6360. #ifdef _USE_SELECT
  6361. if (FD_ISSET(s, &fds))
  6362. #else
  6363. if (fds[idx].revents)
  6364. #endif
  6365. {
  6366. #ifdef _DEBUG
  6367. dbgSB.appendf(" %d",s);
  6368. #endif
  6369. readySocks.append(s);
  6370. if ((int) readySocks.length() == res)
  6371. break;
  6372. }
  6373. }
  6374. #ifdef _DEBUG
  6375. DBGLOG("%s",dbgSB.str());
  6376. #endif
  6377. res = readySocks.ordinality();
  6378. }
  6379. else if (res == SOCKET_ERROR)
  6380. {
  6381. res = 0; // dont return negative on failure
  6382. int err = ERRNO();
  6383. if (err != JSE_INTR)
  6384. {
  6385. #ifndef _USE_SELECT
  6386. delete [] fds;
  6387. #endif
  6388. throw MakeStringException(-1,"wait_multiple::select/poll error %d", err);
  6389. }
  6390. }
  6391. #ifndef _USE_SELECT
  6392. delete [] fds;
  6393. #endif
  6394. return res;
  6395. }
  6396. //Given a list of sockets, wait until any one or more are ready to be read (wont block)
  6397. //returns 0 if timeout, number of waiting sockets otherwise
  6398. int wait_read_multiple(UnsignedArray &socks, //IN sockets to be checked for readiness
  6399. unsigned timeoutMS, //IN timeout
  6400. UnsignedArray &readySocks) //OUT sockets ready to be read
  6401. {
  6402. return wait_multiple(true, socks, timeoutMS, readySocks);
  6403. }
  6404. int wait_write_multiple(UnsignedArray &socks, //IN sockets to be checked for readiness
  6405. unsigned timeoutMS, //IN timeout
  6406. UnsignedArray &readySocks) //OUT sockets ready to be written
  6407. {
  6408. return wait_multiple(false, socks, timeoutMS, readySocks);
  6409. }
  6410. inline bool isIPV4Internal(const char *ip)
  6411. {
  6412. struct sockaddr_in sa;
  6413. return 0 != inet_pton(AF_INET, ip, &sa.sin_addr);
  6414. }
  6415. inline bool isIPV6Internal(const char *ip)
  6416. {
  6417. struct sockaddr_in6 sa;
  6418. return 0 != inet_pton(AF_INET6, ip, &sa.sin6_addr);
  6419. }
  6420. bool isIPV4(const char *ip)
  6421. {
  6422. if (isEmptyString(ip))
  6423. return false;
  6424. return isIPV4Internal(ip);
  6425. }
  6426. bool isIPV6(const char *ip)
  6427. {
  6428. if (isEmptyString(ip))
  6429. return false;
  6430. return isIPV6Internal(ip);
  6431. }
  6432. bool isIPAddress(const char *ip)
  6433. {
  6434. if (isEmptyString(ip))
  6435. return false;
  6436. return isIPV4(ip) || isIPV6(ip);
  6437. }
  6438. class CAllowListHandler : public CSimpleInterfaceOf<IAllowListHandler>, implements IAllowListWriter
  6439. {
  6440. typedef CSimpleInterfaceOf<IAllowListHandler> PARENT;
  6441. struct PairHasher
  6442. {
  6443. template <class T1, class T2>
  6444. std::size_t operator () (std::pair<T1, T2> const &pair) const
  6445. {
  6446. std::size_t h1 = std::hash<T1>()(pair.first);
  6447. std::size_t h2 = std::hash<T2>()(pair.second);
  6448. return h1 ^ h2;
  6449. }
  6450. };
  6451. using AllowListHT = std::unordered_set<std::pair<std::string, unsigned __int64>, PairHasher>;
  6452. AllowListPopulateFunction populateFunc;
  6453. AllowListFormatFunction roleFormatFunc;
  6454. std::unordered_set<std::pair<std::string, unsigned __int64>, PairHasher> allowList;
  6455. std::unordered_set<std::string> IPOnlyAllowList;
  6456. bool allowAnonRoles = false;
  6457. mutable CriticalSection populatedCrit;
  6458. mutable bool populated = false;
  6459. mutable bool enabled = true;
  6460. void ensurePopulated() const
  6461. {
  6462. // should be called within CS
  6463. if (populated)
  6464. return;
  6465. // NB: want to keep this method const, as used by isXX functions that are const, but if need to refresh it's effectively mutable
  6466. enabled = populateFunc(* const_cast<IAllowListWriter *>((const IAllowListWriter *)this));
  6467. populated = true;
  6468. }
  6469. public:
  6470. IMPLEMENT_IINTERFACE_O_USING(PARENT);
  6471. CAllowListHandler(AllowListPopulateFunction _populateFunc, AllowListFormatFunction _roleFormatFunc) : populateFunc(_populateFunc), roleFormatFunc(_roleFormatFunc)
  6472. {
  6473. }
  6474. // IAllowListHandler impl.
  6475. virtual bool isAllowListed(const char *ip, unsigned __int64 role, StringBuffer *responseText) const override
  6476. {
  6477. CriticalBlock block(populatedCrit);
  6478. ensurePopulated();
  6479. if (0 == role) // unknown, can only check ip
  6480. {
  6481. if (allowAnonRoles)
  6482. {
  6483. const auto &it = IPOnlyAllowList.find(ip);
  6484. if (it != IPOnlyAllowList.end())
  6485. return true;
  6486. }
  6487. }
  6488. else
  6489. {
  6490. const auto &it = allowList.find({ip, role});
  6491. if (it != allowList.end())
  6492. return true;
  6493. }
  6494. // if !enabled and no responseText supplied, generate response and warn that disabled
  6495. StringBuffer disabledResponseText;
  6496. if (!enabled && !responseText)
  6497. responseText = &disabledResponseText;
  6498. if (responseText)
  6499. {
  6500. responseText->append("Access denied! [server ip=");
  6501. queryHostIP().getIpText(*responseText);
  6502. responseText->append(", client ip=");
  6503. responseText->append(ip);
  6504. if (role)
  6505. {
  6506. responseText->append(", role=");
  6507. if (roleFormatFunc)
  6508. roleFormatFunc(*responseText, role);
  6509. else
  6510. responseText->append(role);
  6511. }
  6512. responseText->append("] not in allowlist");
  6513. }
  6514. if (enabled)
  6515. return false;
  6516. else
  6517. {
  6518. OWARNLOG("Allowlist is disabled, ignoring: %s", responseText->str());
  6519. return true;
  6520. }
  6521. }
  6522. virtual StringBuffer &getAllowList(StringBuffer &out) const override
  6523. {
  6524. CriticalBlock block(populatedCrit);
  6525. ensurePopulated();
  6526. for (const auto &it: allowList)
  6527. {
  6528. out.append(it.first.c_str()).append(", ");
  6529. if (roleFormatFunc)
  6530. roleFormatFunc(out, it.second);
  6531. else
  6532. out.append(it.second);
  6533. out.newline();
  6534. }
  6535. out.newline().appendf("Allowlist is currently: %s", enabled ? "enabled" : "disabled").newline();
  6536. return out;
  6537. }
  6538. virtual void refresh() override
  6539. {
  6540. /* NB: clear only, so that next usage will re-populated
  6541. * Do not want to repopulate now, because refresh() is likely called within a update write transaction
  6542. */
  6543. CriticalBlock block(populatedCrit);
  6544. enabled = true;
  6545. allowList.clear();
  6546. IPOnlyAllowList.clear();
  6547. populated = false;
  6548. }
  6549. // IAllowListWriter impl.
  6550. virtual void add(const char *ip, unsigned __int64 role) override
  6551. {
  6552. // NB: called via populateFunc, which is called whilst populatedCrit is locked.
  6553. allowList.insert({ ip, role });
  6554. if (allowAnonRoles)
  6555. IPOnlyAllowList.insert(ip);
  6556. }
  6557. virtual void setAllowAnonRoles(bool tf) override
  6558. {
  6559. allowAnonRoles = tf;
  6560. refresh();
  6561. }
  6562. };
  6563. IAllowListHandler *createAllowListHandler(AllowListPopulateFunction populateFunc, AllowListFormatFunction roleFormatFunc)
  6564. {
  6565. return new CAllowListHandler(populateFunc, roleFormatFunc);
  6566. }
  6567. extern jlib_decl void shutdownAndCloseNoThrow(ISocket * optSocket)
  6568. {
  6569. if (!optSocket)
  6570. return;
  6571. optSocket->shutdownNoThrow();
  6572. try
  6573. {
  6574. optSocket->close();
  6575. }
  6576. catch (IException * e)
  6577. {
  6578. e->Release();
  6579. }
  6580. }
  6581. static_assert(sizeof(IpAddress) == 16, "check size of IpAddress");
  6582. static_assert(sizeof(SocketEndpoint) == 20, "check size of SocketEndpoint");