GCDAsyncSocket.m 232 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421
  1. //
  2. // GCDAsyncSocket.m
  3. //
  4. // This class is in the public domain.
  5. // Originally created by Robbie Hanson in Q4 2010.
  6. // Updated and maintained by Deusty LLC and the Apple development community.
  7. //
  8. // https://github.com/robbiehanson/CocoaAsyncSocket
  9. //
  10. #import "GCDAsyncSocket.h"
  11. #if TARGET_OS_IPHONE
  12. #import <CFNetwork/CFNetwork.h>
  13. #endif
  14. #import <arpa/inet.h>
  15. #import <fcntl.h>
  16. #import <ifaddrs.h>
  17. #import <netdb.h>
  18. #import <netinet/in.h>
  19. #import <net/if.h>
  20. #import <sys/socket.h>
  21. #import <sys/types.h>
  22. #import <sys/ioctl.h>
  23. #import <sys/poll.h>
  24. #import <sys/uio.h>
  25. #import <unistd.h>
  26. #if ! __has_feature(objc_arc)
  27. #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
  28. // For more information see: https://github.com/robbiehanson/CocoaAsyncSocket/wiki/ARC
  29. #endif
  30. /**
  31. * Does ARC support support GCD objects?
  32. * It does if the minimum deployment target is iOS 6+ or Mac OS X 10.8+
  33. **/
  34. #if TARGET_OS_IPHONE
  35. // Compiling for iOS
  36. #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 // iOS 6.0 or later
  37. #define NEEDS_DISPATCH_RETAIN_RELEASE 0
  38. #else // iOS 5.X or earlier
  39. #define NEEDS_DISPATCH_RETAIN_RELEASE 1
  40. #endif
  41. #else
  42. // Compiling for Mac OS X
  43. #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 // Mac OS X 10.8 or later
  44. #define NEEDS_DISPATCH_RETAIN_RELEASE 0
  45. #else
  46. #define NEEDS_DISPATCH_RETAIN_RELEASE 1 // Mac OS X 10.7 or earlier
  47. #endif
  48. #endif
  49. #if 0
  50. // Logging Enabled - See log level below
  51. // Logging uses the CocoaLumberjack framework (which is also GCD based).
  52. // https://github.com/CocoaLumberjack/CocoaLumberjack
  53. //
  54. // It allows us to do a lot of logging without significantly slowing down the code.
  55. #import <CocoaLumberjack/CocoaLumberjack.h>
  56. #define LogAsync YES
  57. #define LogContext 65535
  58. #define LogObjc(flg, frmt, ...) LOG_MAYBE(LogAsync, logLevel, flg, LogContext, frmt, ##__VA_ARGS__)
  59. #define LogError(frmt, ...) LogObjc(DDLogFlagError, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  60. #define LogWarn(frmt, ...) LogObjc(DDLogFlagWarning, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  61. #define LogInfo(frmt, ...) LogObjc(DDLogFlagInfo, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  62. #define LogVerbose(frmt, ...) LogObjc(DDLogFlagVerbose, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  63. #define LogTrace() LogObjc(DDLogFlagVerbose, @"%@: %@", THIS_FILE, THIS_METHOD)
  64. // Log levels : off, error, warn, info, verbose
  65. static const int logLevel = DDLogLevelVerbose;
  66. #else
  67. // Logging Disabled
  68. #define LogError(frmt, ...) {}
  69. #define LogWarn(frmt, ...) {}
  70. #define LogInfo(frmt, ...) {}
  71. #define LogVerbose(frmt, ...) {}
  72. #define LogTrace() {}
  73. #endif
  74. /**
  75. * Seeing a return statements within an inner block
  76. * can sometimes be mistaken for a return point of the enclosing method.
  77. * This makes inline blocks a bit easier to read.
  78. **/
  79. #define return_from_block return
  80. /**
  81. * A socket file descriptor is really just an integer.
  82. * It represents the index of the socket within the kernel.
  83. * This makes invalid file descriptor comparisons easier to read.
  84. **/
  85. #define SOCKET_NULL -1
  86. NSString *const GCDAsyncSocketException = @"GCDAsyncSocketException";
  87. NSString *const GCDAsyncSocketErrorDomain = @"GCDAsyncSocketErrorDomain";
  88. NSString *const GCDAsyncSocketQueueName = @"GCDAsyncSocket";
  89. NSString *const GCDAsyncSocketThreadName = @"GCDAsyncSocket-CFStream";
  90. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  91. NSString *const GCDAsyncSocketSSLCipherSuites = @"GCDAsyncSocketSSLCipherSuites";
  92. #if TARGET_OS_IPHONE
  93. NSString *const GCDAsyncSocketSSLProtocolVersionMin = @"GCDAsyncSocketSSLProtocolVersionMin";
  94. NSString *const GCDAsyncSocketSSLProtocolVersionMax = @"GCDAsyncSocketSSLProtocolVersionMax";
  95. #else
  96. NSString *const GCDAsyncSocketSSLDiffieHellmanParameters = @"GCDAsyncSocketSSLDiffieHellmanParameters";
  97. #endif
  98. #endif
  99. enum GCDAsyncSocketFlags
  100. {
  101. kSocketStarted = 1 << 0, // If set, socket has been started (accepting/connecting)
  102. kConnected = 1 << 1, // If set, the socket is connected
  103. kForbidReadsWrites = 1 << 2, // If set, no new reads or writes are allowed
  104. kReadsPaused = 1 << 3, // If set, reads are paused due to possible timeout
  105. kWritesPaused = 1 << 4, // If set, writes are paused due to possible timeout
  106. kDisconnectAfterReads = 1 << 5, // If set, disconnect after no more reads are queued
  107. kDisconnectAfterWrites = 1 << 6, // If set, disconnect after no more writes are queued
  108. kSocketCanAcceptBytes = 1 << 7, // If set, we know socket can accept bytes. If unset, it's unknown.
  109. kReadSourceSuspended = 1 << 8, // If set, the read source is suspended
  110. kWriteSourceSuspended = 1 << 9, // If set, the write source is suspended
  111. kQueuedTLS = 1 << 10, // If set, we've queued an upgrade to TLS
  112. kStartingReadTLS = 1 << 11, // If set, we're waiting for TLS negotiation to complete
  113. kStartingWriteTLS = 1 << 12, // If set, we're waiting for TLS negotiation to complete
  114. kSocketSecure = 1 << 13, // If set, socket is using secure communication via SSL/TLS
  115. kSocketHasReadEOF = 1 << 14, // If set, we have read EOF from socket
  116. kReadStreamClosed = 1 << 15, // If set, we've read EOF plus prebuffer has been drained
  117. #if TARGET_OS_IPHONE
  118. kAddedStreamsToRunLoop = 1 << 16, // If set, CFStreams have been added to listener thread
  119. kUsingCFStreamForTLS = 1 << 17, // If set, we're forced to use CFStream instead of SecureTransport
  120. kSecureSocketHasBytesAvailable = 1 << 18, // If set, CFReadStream has notified us of bytes available
  121. #endif
  122. };
  123. enum GCDAsyncSocketConfig
  124. {
  125. kIPv4Disabled = 1 << 0, // If set, IPv4 is disabled
  126. kIPv6Disabled = 1 << 1, // If set, IPv6 is disabled
  127. kPreferIPv6 = 1 << 2, // If set, IPv6 is preferred over IPv4
  128. kAllowHalfDuplexConnection = 1 << 3, // If set, the socket will stay open even if the read stream closes
  129. };
  130. #if TARGET_OS_IPHONE
  131. static NSThread *cfstreamThread; // Used for CFStreams
  132. #endif
  133. @interface GCDAsyncSocket ()
  134. {
  135. uint32_t flags;
  136. uint16_t config;
  137. #if __has_feature(objc_arc_weak)
  138. __weak id delegate;
  139. #else
  140. __unsafe_unretained id delegate;
  141. #endif
  142. dispatch_queue_t delegateQueue;
  143. int socket4FD;
  144. int socket6FD;
  145. int connectIndex;
  146. NSData * connectInterface4;
  147. NSData * connectInterface6;
  148. dispatch_queue_t socketQueue;
  149. dispatch_source_t accept4Source;
  150. dispatch_source_t accept6Source;
  151. dispatch_source_t connectTimer;
  152. dispatch_source_t readSource;
  153. dispatch_source_t writeSource;
  154. dispatch_source_t readTimer;
  155. dispatch_source_t writeTimer;
  156. NSMutableArray *readQueue;
  157. NSMutableArray *writeQueue;
  158. GCDAsyncReadPacket *currentRead;
  159. GCDAsyncWritePacket *currentWrite;
  160. unsigned long socketFDBytesAvailable;
  161. GCDAsyncSocketPreBuffer *preBuffer;
  162. #if TARGET_OS_IPHONE
  163. CFStreamClientContext streamContext;
  164. CFReadStreamRef readStream;
  165. CFWriteStreamRef writeStream;
  166. #endif
  167. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  168. SSLContextRef sslContext;
  169. GCDAsyncSocketPreBuffer *sslPreBuffer;
  170. size_t sslWriteCachedLength;
  171. OSStatus sslErrCode;
  172. #endif
  173. void *IsOnSocketQueueOrTargetQueueKey;
  174. id userData;
  175. }
  176. // Accepting
  177. - (BOOL)doAccept:(int)socketFD;
  178. // Connecting
  179. - (void)startConnectTimeout:(NSTimeInterval)timeout;
  180. - (void)endConnectTimeout;
  181. - (void)doConnectTimeout;
  182. - (void)lookup:(int)aConnectIndex host:(NSString *)host port:(uint16_t)port;
  183. - (void)lookup:(int)aConnectIndex didSucceedWithAddress4:(NSData *)address4 address6:(NSData *)address6;
  184. - (void)lookup:(int)aConnectIndex didFail:(NSError *)error;
  185. - (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr;
  186. - (void)didConnect:(int)aConnectIndex;
  187. - (void)didNotConnect:(int)aConnectIndex error:(NSError *)error;
  188. // Disconnect
  189. - (void)closeWithError:(NSError *)error;
  190. - (void)maybeClose;
  191. // Errors
  192. - (NSError *)badConfigError:(NSString *)msg;
  193. - (NSError *)badParamError:(NSString *)msg;
  194. - (NSError *)gaiError:(int)gai_error;
  195. - (NSError *)errnoError;
  196. - (NSError *)errnoErrorWithReason:(NSString *)reason;
  197. - (NSError *)connectTimeoutError;
  198. - (NSError *)otherError:(NSString *)msg;
  199. // Diagnostics
  200. - (NSString *)connectedHost4;
  201. - (NSString *)connectedHost6;
  202. - (uint16_t)connectedPort4;
  203. - (uint16_t)connectedPort6;
  204. - (NSString *)localHost4;
  205. - (NSString *)localHost6;
  206. - (uint16_t)localPort4;
  207. - (uint16_t)localPort6;
  208. - (NSString *)connectedHostFromSocket4:(int)socketFD;
  209. - (NSString *)connectedHostFromSocket6:(int)socketFD;
  210. - (uint16_t)connectedPortFromSocket4:(int)socketFD;
  211. - (uint16_t)connectedPortFromSocket6:(int)socketFD;
  212. - (NSString *)localHostFromSocket4:(int)socketFD;
  213. - (NSString *)localHostFromSocket6:(int)socketFD;
  214. - (uint16_t)localPortFromSocket4:(int)socketFD;
  215. - (uint16_t)localPortFromSocket6:(int)socketFD;
  216. // Utilities
  217. - (void)getInterfaceAddress4:(NSMutableData **)addr4Ptr
  218. address6:(NSMutableData **)addr6Ptr
  219. fromDescription:(NSString *)interfaceDescription
  220. port:(uint16_t)port;
  221. - (void)setupReadAndWriteSourcesForNewlyConnectedSocket:(int)socketFD;
  222. - (void)suspendReadSource;
  223. - (void)resumeReadSource;
  224. - (void)suspendWriteSource;
  225. - (void)resumeWriteSource;
  226. // Reading
  227. - (void)maybeDequeueRead;
  228. - (void)flushSSLBuffers;
  229. - (void)doReadData;
  230. - (void)doReadEOF;
  231. - (void)completeCurrentRead;
  232. - (void)endCurrentRead;
  233. - (void)setupReadTimerWithTimeout:(NSTimeInterval)timeout;
  234. - (void)doReadTimeout;
  235. - (void)doReadTimeoutWithExtension:(NSTimeInterval)timeoutExtension;
  236. // Writing
  237. - (void)maybeDequeueWrite;
  238. - (void)doWriteData;
  239. - (void)completeCurrentWrite;
  240. - (void)endCurrentWrite;
  241. - (void)setupWriteTimerWithTimeout:(NSTimeInterval)timeout;
  242. - (void)doWriteTimeout;
  243. - (void)doWriteTimeoutWithExtension:(NSTimeInterval)timeoutExtension;
  244. // Security
  245. - (void)maybeStartTLS;
  246. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  247. - (void)ssl_startTLS;
  248. - (void)ssl_continueSSLHandshake;
  249. #endif
  250. #if TARGET_OS_IPHONE
  251. - (void)cf_startTLS;
  252. #endif
  253. // CFStream
  254. #if TARGET_OS_IPHONE
  255. + (void)startCFStreamThreadIfNeeded;
  256. - (BOOL)createReadAndWriteStream;
  257. - (BOOL)registerForStreamCallbacksIncludingReadWrite:(BOOL)includeReadWrite;
  258. - (BOOL)addStreamsToRunLoop;
  259. - (BOOL)openStreams;
  260. - (void)removeStreamsFromRunLoop;
  261. #endif
  262. // Class Methods
  263. + (NSString *)hostFromSockaddr4:(const struct sockaddr_in *)pSockaddr4;
  264. + (NSString *)hostFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6;
  265. + (uint16_t)portFromSockaddr4:(const struct sockaddr_in *)pSockaddr4;
  266. + (uint16_t)portFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6;
  267. @end
  268. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  269. #pragma mark -
  270. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  271. /**
  272. * A PreBuffer is used when there is more data available on the socket
  273. * than is being requested by current read request.
  274. * In this case we slurp up all data from the socket (to minimize sys calls),
  275. * and store additional yet unread data in a "prebuffer".
  276. *
  277. * The prebuffer is entirely drained before we read from the socket again.
  278. * In other words, a large chunk of data is written is written to the prebuffer.
  279. * The prebuffer is then drained via a series of one or more reads (for subsequent read request(s)).
  280. *
  281. * A ring buffer was once used for this purpose.
  282. * But a ring buffer takes up twice as much memory as needed (double the size for mirroring).
  283. * In fact, it generally takes up more than twice the needed size as everything has to be rounded up to vm_page_size.
  284. * And since the prebuffer is always completely drained after being written to, a full ring buffer isn't needed.
  285. *
  286. * The current design is very simple and straight-forward, while also keeping memory requirements lower.
  287. **/
  288. @interface GCDAsyncSocketPreBuffer : NSObject
  289. {
  290. uint8_t *preBuffer;
  291. size_t preBufferSize;
  292. uint8_t *readPointer;
  293. uint8_t *writePointer;
  294. }
  295. - (id)initWithCapacity:(size_t)numBytes;
  296. - (void)ensureCapacityForWrite:(size_t)numBytes;
  297. - (size_t)availableBytes;
  298. - (uint8_t *)readBuffer;
  299. - (void)getReadBuffer:(uint8_t **)bufferPtr availableBytes:(size_t *)availableBytesPtr;
  300. - (size_t)availableSpace;
  301. - (uint8_t *)writeBuffer;
  302. - (void)getWriteBuffer:(uint8_t **)bufferPtr availableSpace:(size_t *)availableSpacePtr;
  303. - (void)didRead:(size_t)bytesRead;
  304. - (void)didWrite:(size_t)bytesWritten;
  305. - (void)reset;
  306. @end
  307. @implementation GCDAsyncSocketPreBuffer
  308. - (id)initWithCapacity:(size_t)numBytes
  309. {
  310. if ((self = [super init]))
  311. {
  312. preBufferSize = numBytes;
  313. preBuffer = malloc(preBufferSize);
  314. readPointer = preBuffer;
  315. writePointer = preBuffer;
  316. }
  317. return self;
  318. }
  319. - (void)dealloc
  320. {
  321. if (preBuffer)
  322. free(preBuffer);
  323. }
  324. - (void)ensureCapacityForWrite:(size_t)numBytes
  325. {
  326. size_t availableSpace = preBufferSize - (writePointer - readPointer);
  327. if (numBytes > availableSpace)
  328. {
  329. size_t additionalBytes = numBytes - availableSpace;
  330. size_t newPreBufferSize = preBufferSize + additionalBytes;
  331. uint8_t *newPreBuffer = realloc(preBuffer, newPreBufferSize);
  332. size_t readPointerOffset = readPointer - preBuffer;
  333. size_t writePointerOffset = writePointer - preBuffer;
  334. preBuffer = newPreBuffer;
  335. preBufferSize = newPreBufferSize;
  336. readPointer = preBuffer + readPointerOffset;
  337. writePointer = preBuffer + writePointerOffset;
  338. }
  339. }
  340. - (size_t)availableBytes
  341. {
  342. return writePointer - readPointer;
  343. }
  344. - (uint8_t *)readBuffer
  345. {
  346. return readPointer;
  347. }
  348. - (void)getReadBuffer:(uint8_t **)bufferPtr availableBytes:(size_t *)availableBytesPtr
  349. {
  350. if (bufferPtr) *bufferPtr = readPointer;
  351. if (availableBytesPtr) *availableBytesPtr = writePointer - readPointer;
  352. }
  353. - (void)didRead:(size_t)bytesRead
  354. {
  355. readPointer += bytesRead;
  356. if (readPointer == writePointer)
  357. {
  358. // The prebuffer has been drained. Reset pointers.
  359. readPointer = preBuffer;
  360. writePointer = preBuffer;
  361. }
  362. }
  363. - (size_t)availableSpace
  364. {
  365. return preBufferSize - (writePointer - readPointer);
  366. }
  367. - (uint8_t *)writeBuffer
  368. {
  369. return writePointer;
  370. }
  371. - (void)getWriteBuffer:(uint8_t **)bufferPtr availableSpace:(size_t *)availableSpacePtr
  372. {
  373. if (bufferPtr) *bufferPtr = writePointer;
  374. if (availableSpacePtr) *availableSpacePtr = preBufferSize - (writePointer - readPointer);
  375. }
  376. - (void)didWrite:(size_t)bytesWritten
  377. {
  378. writePointer += bytesWritten;
  379. }
  380. - (void)reset
  381. {
  382. readPointer = preBuffer;
  383. writePointer = preBuffer;
  384. }
  385. @end
  386. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  387. #pragma mark -
  388. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  389. /**
  390. * The GCDAsyncReadPacket encompasses the instructions for any given read.
  391. * The content of a read packet allows the code to determine if we're:
  392. * - reading to a certain length
  393. * - reading to a certain separator
  394. * - or simply reading the first chunk of available data
  395. **/
  396. @interface GCDAsyncReadPacket : NSObject
  397. {
  398. @public
  399. NSMutableData *buffer;
  400. NSUInteger startOffset;
  401. NSUInteger bytesDone;
  402. NSUInteger maxLength;
  403. NSTimeInterval timeout;
  404. NSUInteger readLength;
  405. NSData *term;
  406. BOOL bufferOwner;
  407. NSUInteger originalBufferLength;
  408. long tag;
  409. }
  410. - (id)initWithData:(NSMutableData *)d
  411. startOffset:(NSUInteger)s
  412. maxLength:(NSUInteger)m
  413. timeout:(NSTimeInterval)t
  414. readLength:(NSUInteger)l
  415. terminator:(NSData *)e
  416. tag:(long)i;
  417. - (void)ensureCapacityForAdditionalDataOfLength:(NSUInteger)bytesToRead;
  418. - (NSUInteger)optimalReadLengthWithDefault:(NSUInteger)defaultValue shouldPreBuffer:(BOOL *)shouldPreBufferPtr;
  419. - (NSUInteger)readLengthForNonTermWithHint:(NSUInteger)bytesAvailable;
  420. - (NSUInteger)readLengthForTermWithHint:(NSUInteger)bytesAvailable shouldPreBuffer:(BOOL *)shouldPreBufferPtr;
  421. - (NSUInteger)readLengthForTermWithPreBuffer:(GCDAsyncSocketPreBuffer *)preBuffer found:(BOOL *)foundPtr;
  422. - (NSInteger)searchForTermAfterPreBuffering:(ssize_t)numBytes;
  423. @end
  424. @implementation GCDAsyncReadPacket
  425. - (id)initWithData:(NSMutableData *)d
  426. startOffset:(NSUInteger)s
  427. maxLength:(NSUInteger)m
  428. timeout:(NSTimeInterval)t
  429. readLength:(NSUInteger)l
  430. terminator:(NSData *)e
  431. tag:(long)i
  432. {
  433. if((self = [super init]))
  434. {
  435. bytesDone = 0;
  436. maxLength = m;
  437. timeout = t;
  438. readLength = l;
  439. term = [e copy];
  440. tag = i;
  441. if (d)
  442. {
  443. buffer = d;
  444. startOffset = s;
  445. bufferOwner = NO;
  446. originalBufferLength = [d length];
  447. }
  448. else
  449. {
  450. if (readLength > 0)
  451. buffer = [[NSMutableData alloc] initWithLength:readLength];
  452. else
  453. buffer = [[NSMutableData alloc] initWithLength:0];
  454. startOffset = 0;
  455. bufferOwner = YES;
  456. originalBufferLength = 0;
  457. }
  458. }
  459. return self;
  460. }
  461. /**
  462. * Increases the length of the buffer (if needed) to ensure a read of the given size will fit.
  463. **/
  464. - (void)ensureCapacityForAdditionalDataOfLength:(NSUInteger)bytesToRead
  465. {
  466. NSUInteger buffSize = [buffer length];
  467. NSUInteger buffUsed = startOffset + bytesDone;
  468. NSUInteger buffSpace = buffSize - buffUsed;
  469. if (bytesToRead > buffSpace)
  470. {
  471. NSUInteger buffInc = bytesToRead - buffSpace;
  472. [buffer increaseLengthBy:buffInc];
  473. }
  474. }
  475. /**
  476. * This method is used when we do NOT know how much data is available to be read from the socket.
  477. * This method returns the default value unless it exceeds the specified readLength or maxLength.
  478. *
  479. * Furthermore, the shouldPreBuffer decision is based upon the packet type,
  480. * and whether the returned value would fit in the current buffer without requiring a resize of the buffer.
  481. **/
  482. - (NSUInteger)optimalReadLengthWithDefault:(NSUInteger)defaultValue shouldPreBuffer:(BOOL *)shouldPreBufferPtr
  483. {
  484. NSUInteger result;
  485. if (readLength > 0)
  486. {
  487. // Read a specific length of data
  488. result = MIN(defaultValue, (readLength - bytesDone));
  489. // There is no need to prebuffer since we know exactly how much data we need to read.
  490. // Even if the buffer isn't currently big enough to fit this amount of data,
  491. // it would have to be resized eventually anyway.
  492. if (shouldPreBufferPtr)
  493. *shouldPreBufferPtr = NO;
  494. }
  495. else
  496. {
  497. // Either reading until we find a specified terminator,
  498. // or we're simply reading all available data.
  499. //
  500. // In other words, one of:
  501. //
  502. // - readDataToData packet
  503. // - readDataWithTimeout packet
  504. if (maxLength > 0)
  505. result = MIN(defaultValue, (maxLength - bytesDone));
  506. else
  507. result = defaultValue;
  508. // Since we don't know the size of the read in advance,
  509. // the shouldPreBuffer decision is based upon whether the returned value would fit
  510. // in the current buffer without requiring a resize of the buffer.
  511. //
  512. // This is because, in all likelyhood, the amount read from the socket will be less than the default value.
  513. // Thus we should avoid over-allocating the read buffer when we can simply use the pre-buffer instead.
  514. if (shouldPreBufferPtr)
  515. {
  516. NSUInteger buffSize = [buffer length];
  517. NSUInteger buffUsed = startOffset + bytesDone;
  518. NSUInteger buffSpace = buffSize - buffUsed;
  519. if (buffSpace >= result)
  520. *shouldPreBufferPtr = NO;
  521. else
  522. *shouldPreBufferPtr = YES;
  523. }
  524. }
  525. return result;
  526. }
  527. /**
  528. * For read packets without a set terminator, returns the amount of data
  529. * that can be read without exceeding the readLength or maxLength.
  530. *
  531. * The given parameter indicates the number of bytes estimated to be available on the socket,
  532. * which is taken into consideration during the calculation.
  533. *
  534. * The given hint MUST be greater than zero.
  535. **/
  536. - (NSUInteger)readLengthForNonTermWithHint:(NSUInteger)bytesAvailable
  537. {
  538. NSAssert(term == nil, @"This method does not apply to term reads");
  539. NSAssert(bytesAvailable > 0, @"Invalid parameter: bytesAvailable");
  540. if (readLength > 0)
  541. {
  542. // Read a specific length of data
  543. return MIN(bytesAvailable, (readLength - bytesDone));
  544. // No need to avoid resizing the buffer.
  545. // If the user provided their own buffer,
  546. // and told us to read a certain length of data that exceeds the size of the buffer,
  547. // then it is clear that our code will resize the buffer during the read operation.
  548. //
  549. // This method does not actually do any resizing.
  550. // The resizing will happen elsewhere if needed.
  551. }
  552. else
  553. {
  554. // Read all available data
  555. NSUInteger result = bytesAvailable;
  556. if (maxLength > 0)
  557. {
  558. result = MIN(result, (maxLength - bytesDone));
  559. }
  560. // No need to avoid resizing the buffer.
  561. // If the user provided their own buffer,
  562. // and told us to read all available data without giving us a maxLength,
  563. // then it is clear that our code might resize the buffer during the read operation.
  564. //
  565. // This method does not actually do any resizing.
  566. // The resizing will happen elsewhere if needed.
  567. return result;
  568. }
  569. }
  570. /**
  571. * For read packets with a set terminator, returns the amount of data
  572. * that can be read without exceeding the maxLength.
  573. *
  574. * The given parameter indicates the number of bytes estimated to be available on the socket,
  575. * which is taken into consideration during the calculation.
  576. *
  577. * To optimize memory allocations, mem copies, and mem moves
  578. * the shouldPreBuffer boolean value will indicate if the data should be read into a prebuffer first,
  579. * or if the data can be read directly into the read packet's buffer.
  580. **/
  581. - (NSUInteger)readLengthForTermWithHint:(NSUInteger)bytesAvailable shouldPreBuffer:(BOOL *)shouldPreBufferPtr
  582. {
  583. NSAssert(term != nil, @"This method does not apply to non-term reads");
  584. NSAssert(bytesAvailable > 0, @"Invalid parameter: bytesAvailable");
  585. NSUInteger result = bytesAvailable;
  586. if (maxLength > 0)
  587. {
  588. result = MIN(result, (maxLength - bytesDone));
  589. }
  590. // Should the data be read into the read packet's buffer, or into a pre-buffer first?
  591. //
  592. // One would imagine the preferred option is the faster one.
  593. // So which one is faster?
  594. //
  595. // Reading directly into the packet's buffer requires:
  596. // 1. Possibly resizing packet buffer (malloc/realloc)
  597. // 2. Filling buffer (read)
  598. // 3. Searching for term (memcmp)
  599. // 4. Possibly copying overflow into prebuffer (malloc/realloc, memcpy)
  600. //
  601. // Reading into prebuffer first:
  602. // 1. Possibly resizing prebuffer (malloc/realloc)
  603. // 2. Filling buffer (read)
  604. // 3. Searching for term (memcmp)
  605. // 4. Copying underflow into packet buffer (malloc/realloc, memcpy)
  606. // 5. Removing underflow from prebuffer (memmove)
  607. //
  608. // Comparing the performance of the two we can see that reading
  609. // data into the prebuffer first is slower due to the extra memove.
  610. //
  611. // However:
  612. // The implementation of NSMutableData is open source via core foundation's CFMutableData.
  613. // Decreasing the length of a mutable data object doesn't cause a realloc.
  614. // In other words, the capacity of a mutable data object can grow, but doesn't shrink.
  615. //
  616. // This means the prebuffer will rarely need a realloc.
  617. // The packet buffer, on the other hand, may often need a realloc.
  618. // This is especially true if we are the buffer owner.
  619. // Furthermore, if we are constantly realloc'ing the packet buffer,
  620. // and then moving the overflow into the prebuffer,
  621. // then we're consistently over-allocating memory for each term read.
  622. // And now we get into a bit of a tradeoff between speed and memory utilization.
  623. //
  624. // The end result is that the two perform very similarly.
  625. // And we can answer the original question very simply by another means.
  626. //
  627. // If we can read all the data directly into the packet's buffer without resizing it first,
  628. // then we do so. Otherwise we use the prebuffer.
  629. if (shouldPreBufferPtr)
  630. {
  631. NSUInteger buffSize = [buffer length];
  632. NSUInteger buffUsed = startOffset + bytesDone;
  633. if ((buffSize - buffUsed) >= result)
  634. *shouldPreBufferPtr = NO;
  635. else
  636. *shouldPreBufferPtr = YES;
  637. }
  638. return result;
  639. }
  640. /**
  641. * For read packets with a set terminator,
  642. * returns the amount of data that can be read from the given preBuffer,
  643. * without going over a terminator or the maxLength.
  644. *
  645. * It is assumed the terminator has not already been read.
  646. **/
  647. - (NSUInteger)readLengthForTermWithPreBuffer:(GCDAsyncSocketPreBuffer *)preBuffer found:(BOOL *)foundPtr
  648. {
  649. NSAssert(term != nil, @"This method does not apply to non-term reads");
  650. NSAssert([preBuffer availableBytes] > 0, @"Invoked with empty pre buffer!");
  651. // We know that the terminator, as a whole, doesn't exist in our own buffer.
  652. // But it is possible that a _portion_ of it exists in our buffer.
  653. // So we're going to look for the terminator starting with a portion of our own buffer.
  654. //
  655. // Example:
  656. //
  657. // term length = 3 bytes
  658. // bytesDone = 5 bytes
  659. // preBuffer length = 5 bytes
  660. //
  661. // If we append the preBuffer to our buffer,
  662. // it would look like this:
  663. //
  664. // ---------------------
  665. // |B|B|B|B|B|P|P|P|P|P|
  666. // ---------------------
  667. //
  668. // So we start our search here:
  669. //
  670. // ---------------------
  671. // |B|B|B|B|B|P|P|P|P|P|
  672. // -------^-^-^---------
  673. //
  674. // And move forwards...
  675. //
  676. // ---------------------
  677. // |B|B|B|B|B|P|P|P|P|P|
  678. // ---------^-^-^-------
  679. //
  680. // Until we find the terminator or reach the end.
  681. //
  682. // ---------------------
  683. // |B|B|B|B|B|P|P|P|P|P|
  684. // ---------------^-^-^-
  685. BOOL found = NO;
  686. NSUInteger termLength = [term length];
  687. NSUInteger preBufferLength = [preBuffer availableBytes];
  688. if ((bytesDone + preBufferLength) < termLength)
  689. {
  690. // Not enough data for a full term sequence yet
  691. return preBufferLength;
  692. }
  693. NSUInteger maxPreBufferLength;
  694. if (maxLength > 0) {
  695. maxPreBufferLength = MIN(preBufferLength, (maxLength - bytesDone));
  696. // Note: maxLength >= termLength
  697. }
  698. else {
  699. maxPreBufferLength = preBufferLength;
  700. }
  701. uint8_t seq[termLength];
  702. const void *termBuf = [term bytes];
  703. NSUInteger bufLen = MIN(bytesDone, (termLength - 1));
  704. uint8_t *buf = (uint8_t *)[buffer mutableBytes] + startOffset + bytesDone - bufLen;
  705. NSUInteger preLen = termLength - bufLen;
  706. const uint8_t *pre = [preBuffer readBuffer];
  707. NSUInteger loopCount = bufLen + maxPreBufferLength - termLength + 1; // Plus one. See example above.
  708. NSUInteger result = maxPreBufferLength;
  709. NSUInteger i;
  710. for (i = 0; i < loopCount; i++)
  711. {
  712. if (bufLen > 0)
  713. {
  714. // Combining bytes from buffer and preBuffer
  715. memcpy(seq, buf, bufLen);
  716. memcpy(seq + bufLen, pre, preLen);
  717. if (memcmp(seq, termBuf, termLength) == 0)
  718. {
  719. result = preLen;
  720. found = YES;
  721. break;
  722. }
  723. buf++;
  724. bufLen--;
  725. preLen++;
  726. }
  727. else
  728. {
  729. // Comparing directly from preBuffer
  730. if (memcmp(pre, termBuf, termLength) == 0)
  731. {
  732. NSUInteger preOffset = pre - [preBuffer readBuffer]; // pointer arithmetic
  733. result = preOffset + termLength;
  734. found = YES;
  735. break;
  736. }
  737. pre++;
  738. }
  739. }
  740. // There is no need to avoid resizing the buffer in this particular situation.
  741. if (foundPtr) *foundPtr = found;
  742. return result;
  743. }
  744. /**
  745. * For read packets with a set terminator, scans the packet buffer for the term.
  746. * It is assumed the terminator had not been fully read prior to the new bytes.
  747. *
  748. * If the term is found, the number of excess bytes after the term are returned.
  749. * If the term is not found, this method will return -1.
  750. *
  751. * Note: A return value of zero means the term was found at the very end.
  752. *
  753. * Prerequisites:
  754. * The given number of bytes have been added to the end of our buffer.
  755. * Our bytesDone variable has NOT been changed due to the prebuffered bytes.
  756. **/
  757. - (NSInteger)searchForTermAfterPreBuffering:(ssize_t)numBytes
  758. {
  759. NSAssert(term != nil, @"This method does not apply to non-term reads");
  760. // The implementation of this method is very similar to the above method.
  761. // See the above method for a discussion of the algorithm used here.
  762. uint8_t *buff = [buffer mutableBytes];
  763. NSUInteger buffLength = bytesDone + numBytes;
  764. const void *termBuff = [term bytes];
  765. NSUInteger termLength = [term length];
  766. // Note: We are dealing with unsigned integers,
  767. // so make sure the math doesn't go below zero.
  768. NSUInteger i = ((buffLength - numBytes) >= termLength) ? (buffLength - numBytes - termLength + 1) : 0;
  769. while (i + termLength <= buffLength)
  770. {
  771. uint8_t *subBuffer = buff + startOffset + i;
  772. if (memcmp(subBuffer, termBuff, termLength) == 0)
  773. {
  774. return buffLength - (i + termLength);
  775. }
  776. i++;
  777. }
  778. return -1;
  779. }
  780. @end
  781. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  782. #pragma mark -
  783. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  784. /**
  785. * The GCDAsyncWritePacket encompasses the instructions for any given write.
  786. **/
  787. @interface GCDAsyncWritePacket : NSObject
  788. {
  789. @public
  790. NSData *buffer;
  791. NSUInteger bytesDone;
  792. long tag;
  793. NSTimeInterval timeout;
  794. }
  795. - (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i;
  796. @end
  797. @implementation GCDAsyncWritePacket
  798. - (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i
  799. {
  800. if((self = [super init]))
  801. {
  802. buffer = d; // Retain not copy. For performance as documented in header file.
  803. bytesDone = 0;
  804. timeout = t;
  805. tag = i;
  806. }
  807. return self;
  808. }
  809. @end
  810. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  811. #pragma mark -
  812. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  813. /**
  814. * The GCDAsyncSpecialPacket encompasses special instructions for interruptions in the read/write queues.
  815. * This class my be altered to support more than just TLS in the future.
  816. **/
  817. @interface GCDAsyncSpecialPacket : NSObject
  818. {
  819. @public
  820. NSDictionary *tlsSettings;
  821. }
  822. - (id)initWithTLSSettings:(NSDictionary *)settings;
  823. @end
  824. @implementation GCDAsyncSpecialPacket
  825. - (id)initWithTLSSettings:(NSDictionary *)settings
  826. {
  827. if((self = [super init]))
  828. {
  829. tlsSettings = [settings copy];
  830. }
  831. return self;
  832. }
  833. @end
  834. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  835. #pragma mark -
  836. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  837. @implementation GCDAsyncSocket
  838. - (id)init
  839. {
  840. return [self initWithDelegate:nil delegateQueue:NULL socketQueue:NULL];
  841. }
  842. - (id)initWithSocketQueue:(dispatch_queue_t)sq
  843. {
  844. return [self initWithDelegate:nil delegateQueue:NULL socketQueue:sq];
  845. }
  846. - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq
  847. {
  848. return [self initWithDelegate:aDelegate delegateQueue:dq socketQueue:NULL];
  849. }
  850. - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq
  851. {
  852. if((self = [super init]))
  853. {
  854. delegate = aDelegate;
  855. delegateQueue = dq;
  856. #if NEEDS_DISPATCH_RETAIN_RELEASE
  857. if (dq) dispatch_retain(dq);
  858. #endif
  859. socket4FD = SOCKET_NULL;
  860. socket6FD = SOCKET_NULL;
  861. connectIndex = 0;
  862. if (sq)
  863. {
  864. NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
  865. @"The given socketQueue parameter must not be a concurrent queue.");
  866. NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
  867. @"The given socketQueue parameter must not be a concurrent queue.");
  868. NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
  869. @"The given socketQueue parameter must not be a concurrent queue.");
  870. socketQueue = sq;
  871. #if NEEDS_DISPATCH_RETAIN_RELEASE
  872. dispatch_retain(sq);
  873. #endif
  874. }
  875. else
  876. {
  877. socketQueue = dispatch_queue_create([GCDAsyncSocketQueueName UTF8String], NULL);
  878. }
  879. // The dispatch_queue_set_specific() and dispatch_get_specific() functions take a "void *key" parameter.
  880. // From the documentation:
  881. //
  882. // > Keys are only compared as pointers and are never dereferenced.
  883. // > Thus, you can use a pointer to a static variable for a specific subsystem or
  884. // > any other value that allows you to identify the value uniquely.
  885. //
  886. // We're just going to use the memory address of an ivar.
  887. // Specifically an ivar that is explicitly named for our purpose to make the code more readable.
  888. //
  889. // However, it feels tedious (and less readable) to include the "&" all the time:
  890. // dispatch_get_specific(&IsOnSocketQueueOrTargetQueueKey)
  891. //
  892. // So we're going to make it so it doesn't matter if we use the '&' or not,
  893. // by assigning the value of the ivar to the address of the ivar.
  894. // Thus: IsOnSocketQueueOrTargetQueueKey == &IsOnSocketQueueOrTargetQueueKey;
  895. IsOnSocketQueueOrTargetQueueKey = &IsOnSocketQueueOrTargetQueueKey;
  896. void *nonNullUnusedPointer = (__bridge void *)self;
  897. dispatch_queue_set_specific(socketQueue, IsOnSocketQueueOrTargetQueueKey, nonNullUnusedPointer, NULL);
  898. readQueue = [[NSMutableArray alloc] initWithCapacity:5];
  899. currentRead = nil;
  900. writeQueue = [[NSMutableArray alloc] initWithCapacity:5];
  901. currentWrite = nil;
  902. preBuffer = [[GCDAsyncSocketPreBuffer alloc] initWithCapacity:(1024 * 4)];
  903. }
  904. return self;
  905. }
  906. - (void)dealloc
  907. {
  908. LogInfo(@"%@ - %@ (start)", THIS_METHOD, self);
  909. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  910. {
  911. [self closeWithError:nil];
  912. }
  913. else
  914. {
  915. dispatch_sync(socketQueue, ^{
  916. [self closeWithError:nil];
  917. });
  918. }
  919. delegate = nil;
  920. #if NEEDS_DISPATCH_RETAIN_RELEASE
  921. if (delegateQueue) dispatch_release(delegateQueue);
  922. #endif
  923. delegateQueue = NULL;
  924. #if NEEDS_DISPATCH_RETAIN_RELEASE
  925. if (socketQueue) dispatch_release(socketQueue);
  926. #endif
  927. socketQueue = NULL;
  928. LogInfo(@"%@ - %@ (finish)", THIS_METHOD, self);
  929. }
  930. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  931. #pragma mark Configuration
  932. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  933. - (id)delegate
  934. {
  935. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  936. {
  937. return delegate;
  938. }
  939. else
  940. {
  941. __block id result;
  942. dispatch_sync(socketQueue, ^{
  943. result = delegate;
  944. });
  945. return result;
  946. }
  947. }
  948. - (void)setDelegate:(id)newDelegate synchronously:(BOOL)synchronously
  949. {
  950. dispatch_block_t block = ^{
  951. delegate = newDelegate;
  952. };
  953. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) {
  954. block();
  955. }
  956. else {
  957. if (synchronously)
  958. dispatch_sync(socketQueue, block);
  959. else
  960. dispatch_async(socketQueue, block);
  961. }
  962. }
  963. - (void)setDelegate:(id)newDelegate
  964. {
  965. [self setDelegate:newDelegate synchronously:NO];
  966. }
  967. - (void)synchronouslySetDelegate:(id)newDelegate
  968. {
  969. [self setDelegate:newDelegate synchronously:YES];
  970. }
  971. - (dispatch_queue_t)delegateQueue
  972. {
  973. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  974. {
  975. return delegateQueue;
  976. }
  977. else
  978. {
  979. __block dispatch_queue_t result;
  980. dispatch_sync(socketQueue, ^{
  981. result = delegateQueue;
  982. });
  983. return result;
  984. }
  985. }
  986. - (void)setDelegateQueue:(dispatch_queue_t)newDelegateQueue synchronously:(BOOL)synchronously
  987. {
  988. dispatch_block_t block = ^{
  989. #if NEEDS_DISPATCH_RETAIN_RELEASE
  990. if (delegateQueue) dispatch_release(delegateQueue);
  991. if (newDelegateQueue) dispatch_retain(newDelegateQueue);
  992. #endif
  993. delegateQueue = newDelegateQueue;
  994. };
  995. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) {
  996. block();
  997. }
  998. else {
  999. if (synchronously)
  1000. dispatch_sync(socketQueue, block);
  1001. else
  1002. dispatch_async(socketQueue, block);
  1003. }
  1004. }
  1005. - (void)setDelegateQueue:(dispatch_queue_t)newDelegateQueue
  1006. {
  1007. [self setDelegateQueue:newDelegateQueue synchronously:NO];
  1008. }
  1009. - (void)synchronouslySetDelegateQueue:(dispatch_queue_t)newDelegateQueue
  1010. {
  1011. [self setDelegateQueue:newDelegateQueue synchronously:YES];
  1012. }
  1013. - (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr
  1014. {
  1015. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1016. {
  1017. if (delegatePtr) *delegatePtr = delegate;
  1018. if (delegateQueuePtr) *delegateQueuePtr = delegateQueue;
  1019. }
  1020. else
  1021. {
  1022. __block id dPtr = NULL;
  1023. __block dispatch_queue_t dqPtr = NULL;
  1024. dispatch_sync(socketQueue, ^{
  1025. dPtr = delegate;
  1026. dqPtr = delegateQueue;
  1027. });
  1028. if (delegatePtr) *delegatePtr = dPtr;
  1029. if (delegateQueuePtr) *delegateQueuePtr = dqPtr;
  1030. }
  1031. }
  1032. - (void)setDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue synchronously:(BOOL)synchronously
  1033. {
  1034. dispatch_block_t block = ^{
  1035. delegate = newDelegate;
  1036. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1037. if (delegateQueue) dispatch_release(delegateQueue);
  1038. if (newDelegateQueue) dispatch_retain(newDelegateQueue);
  1039. #endif
  1040. delegateQueue = newDelegateQueue;
  1041. };
  1042. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) {
  1043. block();
  1044. }
  1045. else {
  1046. if (synchronously)
  1047. dispatch_sync(socketQueue, block);
  1048. else
  1049. dispatch_async(socketQueue, block);
  1050. }
  1051. }
  1052. - (void)setDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue
  1053. {
  1054. [self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:NO];
  1055. }
  1056. - (void)synchronouslySetDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue
  1057. {
  1058. [self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:YES];
  1059. }
  1060. - (BOOL)isIPv4Enabled
  1061. {
  1062. // Note: YES means kIPv4Disabled is OFF
  1063. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1064. {
  1065. return ((config & kIPv4Disabled) == 0);
  1066. }
  1067. else
  1068. {
  1069. __block BOOL result;
  1070. dispatch_sync(socketQueue, ^{
  1071. result = ((config & kIPv4Disabled) == 0);
  1072. });
  1073. return result;
  1074. }
  1075. }
  1076. - (void)setIPv4Enabled:(BOOL)flag
  1077. {
  1078. // Note: YES means kIPv4Disabled is OFF
  1079. dispatch_block_t block = ^{
  1080. if (flag)
  1081. config &= ~kIPv4Disabled;
  1082. else
  1083. config |= kIPv4Disabled;
  1084. };
  1085. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1086. block();
  1087. else
  1088. dispatch_async(socketQueue, block);
  1089. }
  1090. - (BOOL)isIPv6Enabled
  1091. {
  1092. // Note: YES means kIPv6Disabled is OFF
  1093. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1094. {
  1095. return ((config & kIPv6Disabled) == 0);
  1096. }
  1097. else
  1098. {
  1099. __block BOOL result;
  1100. dispatch_sync(socketQueue, ^{
  1101. result = ((config & kIPv6Disabled) == 0);
  1102. });
  1103. return result;
  1104. }
  1105. }
  1106. - (void)setIPv6Enabled:(BOOL)flag
  1107. {
  1108. // Note: YES means kIPv6Disabled is OFF
  1109. dispatch_block_t block = ^{
  1110. if (flag)
  1111. config &= ~kIPv6Disabled;
  1112. else
  1113. config |= kIPv6Disabled;
  1114. };
  1115. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1116. block();
  1117. else
  1118. dispatch_async(socketQueue, block);
  1119. }
  1120. - (BOOL)isIPv4PreferredOverIPv6
  1121. {
  1122. // Note: YES means kPreferIPv6 is OFF
  1123. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1124. {
  1125. return ((config & kPreferIPv6) == 0);
  1126. }
  1127. else
  1128. {
  1129. __block BOOL result;
  1130. dispatch_sync(socketQueue, ^{
  1131. result = ((config & kPreferIPv6) == 0);
  1132. });
  1133. return result;
  1134. }
  1135. }
  1136. - (void)setPreferIPv4OverIPv6:(BOOL)flag
  1137. {
  1138. // Note: YES means kPreferIPv6 is OFF
  1139. dispatch_block_t block = ^{
  1140. if (flag)
  1141. config &= ~kPreferIPv6;
  1142. else
  1143. config |= kPreferIPv6;
  1144. };
  1145. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1146. block();
  1147. else
  1148. dispatch_async(socketQueue, block);
  1149. }
  1150. - (id)userData
  1151. {
  1152. __block id result = nil;
  1153. dispatch_block_t block = ^{
  1154. result = userData;
  1155. };
  1156. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1157. block();
  1158. else
  1159. dispatch_sync(socketQueue, block);
  1160. return result;
  1161. }
  1162. - (void)setUserData:(id)arbitraryUserData
  1163. {
  1164. dispatch_block_t block = ^{
  1165. if (userData != arbitraryUserData)
  1166. {
  1167. userData = arbitraryUserData;
  1168. }
  1169. };
  1170. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1171. block();
  1172. else
  1173. dispatch_async(socketQueue, block);
  1174. }
  1175. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1176. #pragma mark Accepting
  1177. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1178. - (BOOL)acceptOnPort:(uint16_t)port error:(NSError **)errPtr
  1179. {
  1180. return [self acceptOnInterface:nil port:port error:errPtr];
  1181. }
  1182. - (BOOL)acceptOnInterface:(NSString *)inInterface port:(uint16_t)port error:(NSError **)errPtr
  1183. {
  1184. LogTrace();
  1185. // Just in-case interface parameter is immutable.
  1186. NSString *interface = [inInterface copy];
  1187. __block BOOL result = NO;
  1188. __block NSError *err = nil;
  1189. // CreateSocket Block
  1190. // This block will be invoked within the dispatch block below.
  1191. int(^createSocket)(int, NSData*) = ^int (int domain, NSData *interfaceAddr) {
  1192. int socketFD = socket(domain, SOCK_STREAM, 0);
  1193. if (socketFD == SOCKET_NULL)
  1194. {
  1195. NSString *reason = @"Error in socket() function";
  1196. err = [self errnoErrorWithReason:reason];
  1197. return SOCKET_NULL;
  1198. }
  1199. int status;
  1200. // Set socket options
  1201. status = fcntl(socketFD, F_SETFL, O_NONBLOCK);
  1202. if (status == -1)
  1203. {
  1204. NSString *reason = @"Error enabling non-blocking IO on socket (fcntl)";
  1205. err = [self errnoErrorWithReason:reason];
  1206. LogVerbose(@"close(socketFD)");
  1207. close(socketFD);
  1208. return SOCKET_NULL;
  1209. }
  1210. int reuseOn = 1;
  1211. status = setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  1212. if (status == -1)
  1213. {
  1214. NSString *reason = @"Error enabling address reuse (setsockopt)";
  1215. err = [self errnoErrorWithReason:reason];
  1216. LogVerbose(@"close(socketFD)");
  1217. close(socketFD);
  1218. return SOCKET_NULL;
  1219. }
  1220. // Bind socket
  1221. status = bind(socketFD, (const struct sockaddr *)[interfaceAddr bytes], (socklen_t)[interfaceAddr length]);
  1222. if (status == -1)
  1223. {
  1224. NSString *reason = @"Error in bind() function";
  1225. err = [self errnoErrorWithReason:reason];
  1226. LogVerbose(@"close(socketFD)");
  1227. close(socketFD);
  1228. return SOCKET_NULL;
  1229. }
  1230. // Listen
  1231. status = listen(socketFD, 1024);
  1232. if (status == -1)
  1233. {
  1234. NSString *reason = @"Error in listen() function";
  1235. err = [self errnoErrorWithReason:reason];
  1236. LogVerbose(@"close(socketFD)");
  1237. close(socketFD);
  1238. return SOCKET_NULL;
  1239. }
  1240. return socketFD;
  1241. };
  1242. // Create dispatch block and run on socketQueue
  1243. dispatch_block_t block = ^{ @autoreleasepool {
  1244. if (delegate == nil) // Must have delegate set
  1245. {
  1246. NSString *msg = @"Attempting to accept without a delegate. Set a delegate first.";
  1247. err = [self badConfigError:msg];
  1248. return_from_block;
  1249. }
  1250. if (delegateQueue == NULL) // Must have delegate queue set
  1251. {
  1252. NSString *msg = @"Attempting to accept without a delegate queue. Set a delegate queue first.";
  1253. err = [self badConfigError:msg];
  1254. return_from_block;
  1255. }
  1256. BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO;
  1257. BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO;
  1258. if (isIPv4Disabled && isIPv6Disabled) // Must have IPv4 or IPv6 enabled
  1259. {
  1260. NSString *msg = @"Both IPv4 and IPv6 have been disabled. Must enable at least one protocol first.";
  1261. err = [self badConfigError:msg];
  1262. return_from_block;
  1263. }
  1264. if (![self isDisconnected]) // Must be disconnected
  1265. {
  1266. NSString *msg = @"Attempting to accept while connected or accepting connections. Disconnect first.";
  1267. err = [self badConfigError:msg];
  1268. return_from_block;
  1269. }
  1270. // Clear queues (spurious read/write requests post disconnect)
  1271. [readQueue removeAllObjects];
  1272. [writeQueue removeAllObjects];
  1273. // Resolve interface from description
  1274. NSMutableData *interface4 = nil;
  1275. NSMutableData *interface6 = nil;
  1276. [self getInterfaceAddress4:&interface4 address6:&interface6 fromDescription:interface port:port];
  1277. if ((interface4 == nil) && (interface6 == nil))
  1278. {
  1279. NSString *msg = @"Unknown interface. Specify valid interface by name (e.g. \"en1\") or IP address.";
  1280. err = [self badParamError:msg];
  1281. return_from_block;
  1282. }
  1283. if (isIPv4Disabled && (interface6 == nil))
  1284. {
  1285. NSString *msg = @"IPv4 has been disabled and specified interface doesn't support IPv6.";
  1286. err = [self badParamError:msg];
  1287. return_from_block;
  1288. }
  1289. if (isIPv6Disabled && (interface4 == nil))
  1290. {
  1291. NSString *msg = @"IPv6 has been disabled and specified interface doesn't support IPv4.";
  1292. err = [self badParamError:msg];
  1293. return_from_block;
  1294. }
  1295. BOOL enableIPv4 = !isIPv4Disabled && (interface4 != nil);
  1296. BOOL enableIPv6 = !isIPv6Disabled && (interface6 != nil);
  1297. // Create sockets, configure, bind, and listen
  1298. if (enableIPv4)
  1299. {
  1300. LogVerbose(@"Creating IPv4 socket");
  1301. socket4FD = createSocket(AF_INET, interface4);
  1302. if (socket4FD == SOCKET_NULL)
  1303. {
  1304. return_from_block;
  1305. }
  1306. }
  1307. if (enableIPv6)
  1308. {
  1309. LogVerbose(@"Creating IPv6 socket");
  1310. if (enableIPv4 && (port == 0))
  1311. {
  1312. // No specific port was specified, so we allowed the OS to pick an available port for us.
  1313. // Now we need to make sure the IPv6 socket listens on the same port as the IPv4 socket.
  1314. struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)[interface6 mutableBytes];
  1315. addr6->sin6_port = htons([self localPort4]);
  1316. }
  1317. socket6FD = createSocket(AF_INET6, interface6);
  1318. if (socket6FD == SOCKET_NULL)
  1319. {
  1320. if (socket4FD != SOCKET_NULL)
  1321. {
  1322. LogVerbose(@"close(socket4FD)");
  1323. close(socket4FD);
  1324. }
  1325. return_from_block;
  1326. }
  1327. }
  1328. // Create accept sources
  1329. if (enableIPv4)
  1330. {
  1331. accept4Source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socket4FD, 0, socketQueue);
  1332. int socketFD = socket4FD;
  1333. dispatch_source_t acceptSource = accept4Source;
  1334. dispatch_source_set_event_handler(accept4Source, ^{ @autoreleasepool {
  1335. LogVerbose(@"event4Block");
  1336. unsigned long i = 0;
  1337. unsigned long numPendingConnections = dispatch_source_get_data(acceptSource);
  1338. LogVerbose(@"numPendingConnections: %lu", numPendingConnections);
  1339. while ([self doAccept:socketFD] && (++i < numPendingConnections));
  1340. }});
  1341. dispatch_source_set_cancel_handler(accept4Source, ^{
  1342. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1343. LogVerbose(@"dispatch_release(accept4Source)");
  1344. dispatch_release(acceptSource);
  1345. #endif
  1346. LogVerbose(@"close(socket4FD)");
  1347. close(socketFD);
  1348. });
  1349. LogVerbose(@"dispatch_resume(accept4Source)");
  1350. dispatch_resume(accept4Source);
  1351. }
  1352. if (enableIPv6)
  1353. {
  1354. accept6Source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socket6FD, 0, socketQueue);
  1355. int socketFD = socket6FD;
  1356. dispatch_source_t acceptSource = accept6Source;
  1357. dispatch_source_set_event_handler(accept6Source, ^{ @autoreleasepool {
  1358. LogVerbose(@"event6Block");
  1359. unsigned long i = 0;
  1360. unsigned long numPendingConnections = dispatch_source_get_data(acceptSource);
  1361. LogVerbose(@"numPendingConnections: %lu", numPendingConnections);
  1362. while ([self doAccept:socketFD] && (++i < numPendingConnections));
  1363. }});
  1364. dispatch_source_set_cancel_handler(accept6Source, ^{
  1365. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1366. LogVerbose(@"dispatch_release(accept6Source)");
  1367. dispatch_release(acceptSource);
  1368. #endif
  1369. LogVerbose(@"close(socket6FD)");
  1370. close(socketFD);
  1371. });
  1372. LogVerbose(@"dispatch_resume(accept6Source)");
  1373. dispatch_resume(accept6Source);
  1374. }
  1375. flags |= kSocketStarted;
  1376. result = YES;
  1377. }};
  1378. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1379. block();
  1380. else
  1381. dispatch_sync(socketQueue, block);
  1382. if (result == NO)
  1383. {
  1384. LogInfo(@"Error in accept: %@", err);
  1385. if (errPtr)
  1386. *errPtr = err;
  1387. }
  1388. return result;
  1389. }
  1390. - (BOOL)doAccept:(int)parentSocketFD
  1391. {
  1392. LogTrace();
  1393. BOOL isIPv4;
  1394. int childSocketFD;
  1395. NSData *childSocketAddress;
  1396. if (parentSocketFD == socket4FD)
  1397. {
  1398. isIPv4 = YES;
  1399. struct sockaddr_in addr;
  1400. socklen_t addrLen = sizeof(addr);
  1401. childSocketFD = accept(parentSocketFD, (struct sockaddr *)&addr, &addrLen);
  1402. if (childSocketFD == -1)
  1403. {
  1404. LogWarn(@"Accept failed with error: %@", [self errnoError]);
  1405. return NO;
  1406. }
  1407. childSocketAddress = [NSData dataWithBytes:&addr length:addrLen];
  1408. }
  1409. else // if (parentSocketFD == socket6FD)
  1410. {
  1411. isIPv4 = NO;
  1412. struct sockaddr_in6 addr;
  1413. socklen_t addrLen = sizeof(addr);
  1414. childSocketFD = accept(parentSocketFD, (struct sockaddr *)&addr, &addrLen);
  1415. if (childSocketFD == -1)
  1416. {
  1417. LogWarn(@"Accept failed with error: %@", [self errnoError]);
  1418. return NO;
  1419. }
  1420. childSocketAddress = [NSData dataWithBytes:&addr length:addrLen];
  1421. }
  1422. // Enable non-blocking IO on the socket
  1423. int result = fcntl(childSocketFD, F_SETFL, O_NONBLOCK);
  1424. if (result == -1)
  1425. {
  1426. LogWarn(@"Error enabling non-blocking IO on accepted socket (fcntl)");
  1427. return NO;
  1428. }
  1429. // Prevent SIGPIPE signals
  1430. int nosigpipe = 1;
  1431. setsockopt(childSocketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
  1432. // Notify delegate
  1433. if (delegateQueue)
  1434. {
  1435. __strong id theDelegate = delegate;
  1436. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  1437. // Query delegate for custom socket queue
  1438. dispatch_queue_t childSocketQueue = NULL;
  1439. if ([theDelegate respondsToSelector:@selector(newSocketQueueForConnectionFromAddress:onSocket:)])
  1440. {
  1441. childSocketQueue = [theDelegate newSocketQueueForConnectionFromAddress:childSocketAddress
  1442. onSocket:self];
  1443. }
  1444. // Create GCDAsyncSocket instance for accepted socket
  1445. GCDAsyncSocket *acceptedSocket = [[GCDAsyncSocket alloc] initWithDelegate:theDelegate
  1446. delegateQueue:delegateQueue
  1447. socketQueue:childSocketQueue];
  1448. if (isIPv4)
  1449. acceptedSocket->socket4FD = childSocketFD;
  1450. else
  1451. acceptedSocket->socket6FD = childSocketFD;
  1452. acceptedSocket->flags = (kSocketStarted | kConnected);
  1453. // Setup read and write sources for accepted socket
  1454. dispatch_async(acceptedSocket->socketQueue, ^{ @autoreleasepool {
  1455. [acceptedSocket setupReadAndWriteSourcesForNewlyConnectedSocket:childSocketFD];
  1456. }});
  1457. // Notify delegate
  1458. if ([theDelegate respondsToSelector:@selector(socket:didAcceptNewSocket:)])
  1459. {
  1460. [theDelegate socket:self didAcceptNewSocket:acceptedSocket];
  1461. }
  1462. // Release the socket queue returned from the delegate (it was retained by acceptedSocket)
  1463. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1464. if (childSocketQueue) dispatch_release(childSocketQueue);
  1465. #endif
  1466. // The accepted socket should have been retained by the delegate.
  1467. // Otherwise it gets properly released when exiting the block.
  1468. }});
  1469. }
  1470. return YES;
  1471. }
  1472. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1473. #pragma mark Connecting
  1474. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1475. /**
  1476. * This method runs through the various checks required prior to a connection attempt.
  1477. * It is shared between the connectToHost and connectToAddress methods.
  1478. *
  1479. **/
  1480. - (BOOL)preConnectWithInterface:(NSString *)interface error:(NSError **)errPtr
  1481. {
  1482. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  1483. if (delegate == nil) // Must have delegate set
  1484. {
  1485. if (errPtr)
  1486. {
  1487. NSString *msg = @"Attempting to connect without a delegate. Set a delegate first.";
  1488. *errPtr = [self badConfigError:msg];
  1489. }
  1490. return NO;
  1491. }
  1492. if (delegateQueue == NULL) // Must have delegate queue set
  1493. {
  1494. if (errPtr)
  1495. {
  1496. NSString *msg = @"Attempting to connect without a delegate queue. Set a delegate queue first.";
  1497. *errPtr = [self badConfigError:msg];
  1498. }
  1499. return NO;
  1500. }
  1501. if (![self isDisconnected]) // Must be disconnected
  1502. {
  1503. if (errPtr)
  1504. {
  1505. NSString *msg = @"Attempting to connect while connected or accepting connections. Disconnect first.";
  1506. *errPtr = [self badConfigError:msg];
  1507. }
  1508. return NO;
  1509. }
  1510. BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO;
  1511. BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO;
  1512. if (isIPv4Disabled && isIPv6Disabled) // Must have IPv4 or IPv6 enabled
  1513. {
  1514. if (errPtr)
  1515. {
  1516. NSString *msg = @"Both IPv4 and IPv6 have been disabled. Must enable at least one protocol first.";
  1517. *errPtr = [self badConfigError:msg];
  1518. }
  1519. return NO;
  1520. }
  1521. if (interface)
  1522. {
  1523. NSMutableData *interface4 = nil;
  1524. NSMutableData *interface6 = nil;
  1525. [self getInterfaceAddress4:&interface4 address6:&interface6 fromDescription:interface port:0];
  1526. if ((interface4 == nil) && (interface6 == nil))
  1527. {
  1528. if (errPtr)
  1529. {
  1530. NSString *msg = @"Unknown interface. Specify valid interface by name (e.g. \"en1\") or IP address.";
  1531. *errPtr = [self badParamError:msg];
  1532. }
  1533. return NO;
  1534. }
  1535. if (isIPv4Disabled && (interface6 == nil))
  1536. {
  1537. if (errPtr)
  1538. {
  1539. NSString *msg = @"IPv4 has been disabled and specified interface doesn't support IPv6.";
  1540. *errPtr = [self badParamError:msg];
  1541. }
  1542. return NO;
  1543. }
  1544. if (isIPv6Disabled && (interface4 == nil))
  1545. {
  1546. if (errPtr)
  1547. {
  1548. NSString *msg = @"IPv6 has been disabled and specified interface doesn't support IPv4.";
  1549. *errPtr = [self badParamError:msg];
  1550. }
  1551. return NO;
  1552. }
  1553. connectInterface4 = interface4;
  1554. connectInterface6 = interface6;
  1555. }
  1556. // Clear queues (spurious read/write requests post disconnect)
  1557. [readQueue removeAllObjects];
  1558. [writeQueue removeAllObjects];
  1559. return YES;
  1560. }
  1561. - (BOOL)connectToHost:(NSString*)host onPort:(uint16_t)port error:(NSError **)errPtr
  1562. {
  1563. return [self connectToHost:host onPort:port withTimeout:-1 error:errPtr];
  1564. }
  1565. - (BOOL)connectToHost:(NSString *)host
  1566. onPort:(uint16_t)port
  1567. withTimeout:(NSTimeInterval)timeout
  1568. error:(NSError **)errPtr
  1569. {
  1570. return [self connectToHost:host onPort:port viaInterface:nil withTimeout:timeout error:errPtr];
  1571. }
  1572. - (BOOL)connectToHost:(NSString *)inHost
  1573. onPort:(uint16_t)port
  1574. viaInterface:(NSString *)inInterface
  1575. withTimeout:(NSTimeInterval)timeout
  1576. error:(NSError **)errPtr
  1577. {
  1578. LogTrace();
  1579. // Just in case immutable objects were passed
  1580. NSString *host = [inHost copy];
  1581. NSString *interface = [inInterface copy];
  1582. __block BOOL result = NO;
  1583. __block NSError *err = nil;
  1584. dispatch_block_t block = ^{ @autoreleasepool {
  1585. // Check for problems with host parameter
  1586. if ([host length] == 0)
  1587. {
  1588. NSString *msg = @"Invalid host parameter (nil or \"\"). Should be a domain name or IP address string.";
  1589. err = [self badParamError:msg];
  1590. return_from_block;
  1591. }
  1592. // Run through standard pre-connect checks
  1593. if (![self preConnectWithInterface:interface error:&err])
  1594. {
  1595. return_from_block;
  1596. }
  1597. // We've made it past all the checks.
  1598. // It's time to start the connection process.
  1599. flags |= kSocketStarted;
  1600. LogVerbose(@"Dispatching DNS lookup...");
  1601. // It's possible that the given host parameter is actually a NSMutableString.
  1602. // So we want to copy it now, within this block that will be executed synchronously.
  1603. // This way the asynchronous lookup block below doesn't have to worry about it changing.
  1604. int aConnectIndex = connectIndex;
  1605. NSString *hostCpy = [host copy];
  1606. dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  1607. dispatch_async(globalConcurrentQueue, ^{ @autoreleasepool {
  1608. [self lookup:aConnectIndex host:hostCpy port:port];
  1609. }});
  1610. [self startConnectTimeout:timeout];
  1611. result = YES;
  1612. }};
  1613. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1614. block();
  1615. else
  1616. dispatch_sync(socketQueue, block);
  1617. if (result == NO)
  1618. {
  1619. if (errPtr)
  1620. *errPtr = err;
  1621. }
  1622. return result;
  1623. }
  1624. - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr
  1625. {
  1626. return [self connectToAddress:remoteAddr viaInterface:nil withTimeout:-1 error:errPtr];
  1627. }
  1628. - (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr
  1629. {
  1630. return [self connectToAddress:remoteAddr viaInterface:nil withTimeout:timeout error:errPtr];
  1631. }
  1632. - (BOOL)connectToAddress:(NSData *)inRemoteAddr
  1633. viaInterface:(NSString *)inInterface
  1634. withTimeout:(NSTimeInterval)timeout
  1635. error:(NSError **)errPtr
  1636. {
  1637. LogTrace();
  1638. // Just in case immutable objects were passed
  1639. NSData *remoteAddr = [inRemoteAddr copy];
  1640. NSString *interface = [inInterface copy];
  1641. __block BOOL result = NO;
  1642. __block NSError *err = nil;
  1643. dispatch_block_t block = ^{ @autoreleasepool {
  1644. // Check for problems with remoteAddr parameter
  1645. NSData *address4 = nil;
  1646. NSData *address6 = nil;
  1647. if ([remoteAddr length] >= sizeof(struct sockaddr))
  1648. {
  1649. const struct sockaddr *sockaddr = (const struct sockaddr *)[remoteAddr bytes];
  1650. if (sockaddr->sa_family == AF_INET)
  1651. {
  1652. if ([remoteAddr length] == sizeof(struct sockaddr_in))
  1653. {
  1654. address4 = remoteAddr;
  1655. }
  1656. }
  1657. else if (sockaddr->sa_family == AF_INET6)
  1658. {
  1659. if ([remoteAddr length] == sizeof(struct sockaddr_in6))
  1660. {
  1661. address6 = remoteAddr;
  1662. }
  1663. }
  1664. }
  1665. if ((address4 == nil) && (address6 == nil))
  1666. {
  1667. NSString *msg = @"A valid IPv4 or IPv6 address was not given";
  1668. err = [self badParamError:msg];
  1669. return_from_block;
  1670. }
  1671. BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO;
  1672. BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO;
  1673. if (isIPv4Disabled && (address4 != nil))
  1674. {
  1675. NSString *msg = @"IPv4 has been disabled and an IPv4 address was passed.";
  1676. err = [self badParamError:msg];
  1677. return_from_block;
  1678. }
  1679. if (isIPv6Disabled && (address6 != nil))
  1680. {
  1681. NSString *msg = @"IPv6 has been disabled and an IPv6 address was passed.";
  1682. err = [self badParamError:msg];
  1683. return_from_block;
  1684. }
  1685. // Run through standard pre-connect checks
  1686. if (![self preConnectWithInterface:interface error:&err])
  1687. {
  1688. return_from_block;
  1689. }
  1690. // We've made it past all the checks.
  1691. // It's time to start the connection process.
  1692. if (![self connectWithAddress4:address4 address6:address6 error:&err])
  1693. {
  1694. return_from_block;
  1695. }
  1696. flags |= kSocketStarted;
  1697. [self startConnectTimeout:timeout];
  1698. result = YES;
  1699. }};
  1700. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  1701. block();
  1702. else
  1703. dispatch_sync(socketQueue, block);
  1704. if (result == NO)
  1705. {
  1706. if (errPtr)
  1707. *errPtr = err;
  1708. }
  1709. return result;
  1710. }
  1711. - (void)lookup:(int)aConnectIndex host:(NSString *)host port:(uint16_t)port
  1712. {
  1713. LogTrace();
  1714. // This method is executed on a global concurrent queue.
  1715. // It posts the results back to the socket queue.
  1716. // The lookupIndex is used to ignore the results if the connect operation was cancelled or timed out.
  1717. NSError *error = nil;
  1718. NSData *address4 = nil;
  1719. NSData *address6 = nil;
  1720. if ([host isEqualToString:@"localhost"] || [host isEqualToString:@"loopback"])
  1721. {
  1722. // Use LOOPBACK address
  1723. struct sockaddr_in nativeAddr;
  1724. nativeAddr.sin_len = sizeof(struct sockaddr_in);
  1725. nativeAddr.sin_family = AF_INET;
  1726. nativeAddr.sin_port = htons(port);
  1727. nativeAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  1728. memset(&(nativeAddr.sin_zero), 0, sizeof(nativeAddr.sin_zero));
  1729. struct sockaddr_in6 nativeAddr6;
  1730. nativeAddr6.sin6_len = sizeof(struct sockaddr_in6);
  1731. nativeAddr6.sin6_family = AF_INET6;
  1732. nativeAddr6.sin6_port = htons(port);
  1733. nativeAddr6.sin6_flowinfo = 0;
  1734. nativeAddr6.sin6_addr = in6addr_loopback;
  1735. nativeAddr6.sin6_scope_id = 0;
  1736. // Wrap the native address structures
  1737. address4 = [NSData dataWithBytes:&nativeAddr length:sizeof(nativeAddr)];
  1738. address6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
  1739. }
  1740. else
  1741. {
  1742. NSString *portStr = [NSString stringWithFormat:@"%hu", port];
  1743. struct addrinfo hints, *res, *res0;
  1744. memset(&hints, 0, sizeof(hints));
  1745. hints.ai_family = PF_UNSPEC;
  1746. hints.ai_socktype = SOCK_STREAM;
  1747. hints.ai_protocol = IPPROTO_TCP;
  1748. int gai_error = getaddrinfo([host UTF8String], [portStr UTF8String], &hints, &res0);
  1749. if (gai_error)
  1750. {
  1751. error = [self gaiError:gai_error];
  1752. }
  1753. else
  1754. {
  1755. for(res = res0; res; res = res->ai_next)
  1756. {
  1757. if ((address4 == nil) && (res->ai_family == AF_INET))
  1758. {
  1759. // Found IPv4 address
  1760. // Wrap the native address structure
  1761. address4 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
  1762. }
  1763. else if ((address6 == nil) && (res->ai_family == AF_INET6))
  1764. {
  1765. // Found IPv6 address
  1766. // Wrap the native address structure
  1767. address6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
  1768. }
  1769. }
  1770. freeaddrinfo(res0);
  1771. if ((address4 == nil) && (address6 == nil))
  1772. {
  1773. error = [self gaiError:EAI_FAIL];
  1774. }
  1775. }
  1776. }
  1777. if (error)
  1778. {
  1779. dispatch_async(socketQueue, ^{ @autoreleasepool {
  1780. [self lookup:aConnectIndex didFail:error];
  1781. }});
  1782. }
  1783. else
  1784. {
  1785. dispatch_async(socketQueue, ^{ @autoreleasepool {
  1786. [self lookup:aConnectIndex didSucceedWithAddress4:address4 address6:address6];
  1787. }});
  1788. }
  1789. }
  1790. - (void)lookup:(int)aConnectIndex didSucceedWithAddress4:(NSData *)address4 address6:(NSData *)address6
  1791. {
  1792. LogTrace();
  1793. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  1794. NSAssert(address4 || address6, @"Expected at least one valid address");
  1795. if (aConnectIndex != connectIndex)
  1796. {
  1797. LogInfo(@"Ignoring lookupDidSucceed, already disconnected");
  1798. // The connect operation has been cancelled.
  1799. // That is, socket was disconnected, or connection has already timed out.
  1800. return;
  1801. }
  1802. // Check for problems
  1803. BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO;
  1804. BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO;
  1805. if (isIPv4Disabled && (address6 == nil))
  1806. {
  1807. NSString *msg = @"IPv4 has been disabled and DNS lookup found no IPv6 address.";
  1808. [self closeWithError:[self otherError:msg]];
  1809. return;
  1810. }
  1811. if (isIPv6Disabled && (address4 == nil))
  1812. {
  1813. NSString *msg = @"IPv6 has been disabled and DNS lookup found no IPv4 address.";
  1814. [self closeWithError:[self otherError:msg]];
  1815. return;
  1816. }
  1817. // Start the normal connection process
  1818. NSError *err = nil;
  1819. if (![self connectWithAddress4:address4 address6:address6 error:&err])
  1820. {
  1821. [self closeWithError:err];
  1822. }
  1823. }
  1824. /**
  1825. * This method is called if the DNS lookup fails.
  1826. * This method is executed on the socketQueue.
  1827. *
  1828. * Since the DNS lookup executed synchronously on a global concurrent queue,
  1829. * the original connection request may have already been cancelled or timed-out by the time this method is invoked.
  1830. * The lookupIndex tells us whether the lookup is still valid or not.
  1831. **/
  1832. - (void)lookup:(int)aConnectIndex didFail:(NSError *)error
  1833. {
  1834. LogTrace();
  1835. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  1836. if (aConnectIndex != connectIndex)
  1837. {
  1838. LogInfo(@"Ignoring lookup:didFail: - already disconnected");
  1839. // The connect operation has been cancelled.
  1840. // That is, socket was disconnected, or connection has already timed out.
  1841. return;
  1842. }
  1843. [self endConnectTimeout];
  1844. [self closeWithError:error];
  1845. }
  1846. - (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr
  1847. {
  1848. LogTrace();
  1849. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  1850. LogVerbose(@"IPv4: %@:%hu", [[self class] hostFromAddress:address4], [[self class] portFromAddress:address4]);
  1851. LogVerbose(@"IPv6: %@:%hu", [[self class] hostFromAddress:address6], [[self class] portFromAddress:address6]);
  1852. // Determine socket type
  1853. BOOL preferIPv6 = (config & kPreferIPv6) ? YES : NO;
  1854. BOOL useIPv6 = ((preferIPv6 && address6) || (address4 == nil));
  1855. // Create the socket
  1856. int socketFD;
  1857. NSData *address;
  1858. NSData *connectInterface;
  1859. if (useIPv6)
  1860. {
  1861. LogVerbose(@"Creating IPv6 socket");
  1862. socket6FD = socket(AF_INET6, SOCK_STREAM, 0);
  1863. socketFD = socket6FD;
  1864. address = address6;
  1865. connectInterface = connectInterface6;
  1866. }
  1867. else
  1868. {
  1869. LogVerbose(@"Creating IPv4 socket");
  1870. socket4FD = socket(AF_INET, SOCK_STREAM, 0);
  1871. socketFD = socket4FD;
  1872. address = address4;
  1873. connectInterface = connectInterface4;
  1874. }
  1875. if (socketFD == SOCKET_NULL)
  1876. {
  1877. if (errPtr)
  1878. *errPtr = [self errnoErrorWithReason:@"Error in socket() function"];
  1879. return NO;
  1880. }
  1881. // Bind the socket to the desired interface (if needed)
  1882. if (connectInterface)
  1883. {
  1884. LogVerbose(@"Binding socket...");
  1885. if ([[self class] portFromAddress:connectInterface] > 0)
  1886. {
  1887. // Since we're going to be binding to a specific port,
  1888. // we should turn on reuseaddr to allow us to override sockets in time_wait.
  1889. int reuseOn = 1;
  1890. setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  1891. }
  1892. const struct sockaddr *interfaceAddr = (const struct sockaddr *)[connectInterface bytes];
  1893. int result = bind(socketFD, interfaceAddr, (socklen_t)[connectInterface length]);
  1894. if (result != 0)
  1895. {
  1896. if (errPtr)
  1897. *errPtr = [self errnoErrorWithReason:@"Error in bind() function"];
  1898. return NO;
  1899. }
  1900. }
  1901. // Prevent SIGPIPE signals
  1902. int nosigpipe = 1;
  1903. setsockopt(socketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
  1904. // Start the connection process in a background queue
  1905. int aConnectIndex = connectIndex;
  1906. dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  1907. dispatch_async(globalConcurrentQueue, ^{
  1908. int result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]);
  1909. if (result == 0)
  1910. {
  1911. dispatch_async(socketQueue, ^{ @autoreleasepool {
  1912. [self didConnect:aConnectIndex];
  1913. }});
  1914. }
  1915. else
  1916. {
  1917. NSError *error = [self errnoErrorWithReason:@"Error in connect() function"];
  1918. dispatch_async(socketQueue, ^{ @autoreleasepool {
  1919. [self didNotConnect:aConnectIndex error:error];
  1920. }});
  1921. }
  1922. });
  1923. LogVerbose(@"Connecting...");
  1924. return YES;
  1925. }
  1926. - (void)didConnect:(int)aConnectIndex
  1927. {
  1928. LogTrace();
  1929. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  1930. if (aConnectIndex != connectIndex)
  1931. {
  1932. LogInfo(@"Ignoring didConnect, already disconnected");
  1933. // The connect operation has been cancelled.
  1934. // That is, socket was disconnected, or connection has already timed out.
  1935. return;
  1936. }
  1937. flags |= kConnected;
  1938. [self endConnectTimeout];
  1939. #if TARGET_OS_IPHONE
  1940. // The endConnectTimeout method executed above incremented the connectIndex.
  1941. aConnectIndex = connectIndex;
  1942. #endif
  1943. // Setup read/write streams (as workaround for specific shortcomings in the iOS platform)
  1944. //
  1945. // Note:
  1946. // There may be configuration options that must be set by the delegate before opening the streams.
  1947. // The primary example is the kCFStreamNetworkServiceTypeVoIP flag, which only works on an unopened stream.
  1948. //
  1949. // Thus we wait until after the socket:didConnectToHost:port: delegate method has completed.
  1950. // This gives the delegate time to properly configure the streams if needed.
  1951. dispatch_block_t SetupStreamsPart1 = ^{
  1952. #if TARGET_OS_IPHONE
  1953. if (![self createReadAndWriteStream])
  1954. {
  1955. [self closeWithError:[self otherError:@"Error creating CFStreams"]];
  1956. return;
  1957. }
  1958. if (![self registerForStreamCallbacksIncludingReadWrite:NO])
  1959. {
  1960. [self closeWithError:[self otherError:@"Error in CFStreamSetClient"]];
  1961. return;
  1962. }
  1963. #endif
  1964. };
  1965. dispatch_block_t SetupStreamsPart2 = ^{
  1966. #if TARGET_OS_IPHONE
  1967. if (aConnectIndex != connectIndex)
  1968. {
  1969. // The socket has been disconnected.
  1970. return;
  1971. }
  1972. if (![self addStreamsToRunLoop])
  1973. {
  1974. [self closeWithError:[self otherError:@"Error in CFStreamScheduleWithRunLoop"]];
  1975. return;
  1976. }
  1977. if (![self openStreams])
  1978. {
  1979. [self closeWithError:[self otherError:@"Error creating CFStreams"]];
  1980. return;
  1981. }
  1982. #endif
  1983. };
  1984. // Notify delegate
  1985. NSString *host = [self connectedHost];
  1986. uint16_t port = [self connectedPort];
  1987. if (delegateQueue && [delegate respondsToSelector:@selector(socket:didConnectToHost:port:)])
  1988. {
  1989. SetupStreamsPart1();
  1990. __strong id theDelegate = delegate;
  1991. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  1992. [theDelegate socket:self didConnectToHost:host port:port];
  1993. dispatch_async(socketQueue, ^{ @autoreleasepool {
  1994. SetupStreamsPart2();
  1995. }});
  1996. }});
  1997. }
  1998. else
  1999. {
  2000. SetupStreamsPart1();
  2001. SetupStreamsPart2();
  2002. }
  2003. // Get the connected socket
  2004. int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : socket6FD;
  2005. // Enable non-blocking IO on the socket
  2006. int result = fcntl(socketFD, F_SETFL, O_NONBLOCK);
  2007. if (result == -1)
  2008. {
  2009. NSString *errMsg = @"Error enabling non-blocking IO on socket (fcntl)";
  2010. [self closeWithError:[self otherError:errMsg]];
  2011. return;
  2012. }
  2013. // Setup our read/write sources
  2014. [self setupReadAndWriteSourcesForNewlyConnectedSocket:socketFD];
  2015. // Dequeue any pending read/write requests
  2016. [self maybeDequeueRead];
  2017. [self maybeDequeueWrite];
  2018. }
  2019. - (void)didNotConnect:(int)aConnectIndex error:(NSError *)error
  2020. {
  2021. LogTrace();
  2022. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  2023. if (aConnectIndex != connectIndex)
  2024. {
  2025. LogInfo(@"Ignoring didNotConnect, already disconnected");
  2026. // The connect operation has been cancelled.
  2027. // That is, socket was disconnected, or connection has already timed out.
  2028. return;
  2029. }
  2030. [self closeWithError:error];
  2031. }
  2032. - (void)startConnectTimeout:(NSTimeInterval)timeout
  2033. {
  2034. if (timeout >= 0.0)
  2035. {
  2036. connectTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, socketQueue);
  2037. dispatch_source_set_event_handler(connectTimer, ^{ @autoreleasepool {
  2038. [self doConnectTimeout];
  2039. }});
  2040. #if NEEDS_DISPATCH_RETAIN_RELEASE
  2041. dispatch_source_t theConnectTimer = connectTimer;
  2042. dispatch_source_set_cancel_handler(connectTimer, ^{
  2043. LogVerbose(@"dispatch_release(connectTimer)");
  2044. dispatch_release(theConnectTimer);
  2045. });
  2046. #endif
  2047. dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeout * NSEC_PER_SEC));
  2048. dispatch_source_set_timer(connectTimer, tt, DISPATCH_TIME_FOREVER, 0);
  2049. dispatch_resume(connectTimer);
  2050. }
  2051. }
  2052. - (void)endConnectTimeout
  2053. {
  2054. LogTrace();
  2055. if (connectTimer)
  2056. {
  2057. dispatch_source_cancel(connectTimer);
  2058. connectTimer = NULL;
  2059. }
  2060. // Increment connectIndex.
  2061. // This will prevent us from processing results from any related background asynchronous operations.
  2062. //
  2063. // Note: This should be called from close method even if connectTimer is NULL.
  2064. // This is because one might disconnect a socket prior to a successful connection which had no timeout.
  2065. connectIndex++;
  2066. if (connectInterface4)
  2067. {
  2068. connectInterface4 = nil;
  2069. }
  2070. if (connectInterface6)
  2071. {
  2072. connectInterface6 = nil;
  2073. }
  2074. }
  2075. - (void)doConnectTimeout
  2076. {
  2077. LogTrace();
  2078. [self endConnectTimeout];
  2079. [self closeWithError:[self connectTimeoutError]];
  2080. }
  2081. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2082. #pragma mark Disconnecting
  2083. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2084. - (void)closeWithError:(NSError *)error
  2085. {
  2086. LogTrace();
  2087. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  2088. [self endConnectTimeout];
  2089. if (currentRead != nil) [self endCurrentRead];
  2090. if (currentWrite != nil) [self endCurrentWrite];
  2091. [readQueue removeAllObjects];
  2092. [writeQueue removeAllObjects];
  2093. [preBuffer reset];
  2094. #if TARGET_OS_IPHONE
  2095. {
  2096. if (readStream || writeStream)
  2097. {
  2098. [self removeStreamsFromRunLoop];
  2099. if (readStream)
  2100. {
  2101. CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL);
  2102. CFReadStreamClose(readStream);
  2103. CFRelease(readStream);
  2104. readStream = NULL;
  2105. }
  2106. if (writeStream)
  2107. {
  2108. CFWriteStreamSetClient(writeStream, kCFStreamEventNone, NULL, NULL);
  2109. CFWriteStreamClose(writeStream);
  2110. CFRelease(writeStream);
  2111. writeStream = NULL;
  2112. }
  2113. }
  2114. }
  2115. #endif
  2116. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  2117. {
  2118. [sslPreBuffer reset];
  2119. sslErrCode = noErr;
  2120. if (sslContext)
  2121. {
  2122. // Getting a linker error here about the SSLx() functions?
  2123. // You need to add the Security Framework to your application.
  2124. SSLClose(sslContext);
  2125. #if TARGET_OS_IPHONE
  2126. CFRelease(sslContext);
  2127. #else
  2128. SSLDisposeContext(sslContext);
  2129. #endif
  2130. sslContext = NULL;
  2131. }
  2132. }
  2133. #endif
  2134. // For some crazy reason (in my opinion), cancelling a dispatch source doesn't
  2135. // invoke the cancel handler if the dispatch source is paused.
  2136. // So we have to unpause the source if needed.
  2137. // This allows the cancel handler to be run, which in turn releases the source and closes the socket.
  2138. if (!accept4Source && !accept6Source && !readSource && !writeSource)
  2139. {
  2140. LogVerbose(@"manually closing close");
  2141. if (socket4FD != SOCKET_NULL)
  2142. {
  2143. LogVerbose(@"close(socket4FD)");
  2144. close(socket4FD);
  2145. socket4FD = SOCKET_NULL;
  2146. }
  2147. if (socket6FD != SOCKET_NULL)
  2148. {
  2149. LogVerbose(@"close(socket6FD)");
  2150. close(socket6FD);
  2151. socket6FD = SOCKET_NULL;
  2152. }
  2153. }
  2154. else
  2155. {
  2156. if (accept4Source)
  2157. {
  2158. LogVerbose(@"dispatch_source_cancel(accept4Source)");
  2159. dispatch_source_cancel(accept4Source);
  2160. // We never suspend accept4Source
  2161. accept4Source = NULL;
  2162. }
  2163. if (accept6Source)
  2164. {
  2165. LogVerbose(@"dispatch_source_cancel(accept6Source)");
  2166. dispatch_source_cancel(accept6Source);
  2167. // We never suspend accept6Source
  2168. accept6Source = NULL;
  2169. }
  2170. if (readSource)
  2171. {
  2172. LogVerbose(@"dispatch_source_cancel(readSource)");
  2173. dispatch_source_cancel(readSource);
  2174. [self resumeReadSource];
  2175. readSource = NULL;
  2176. }
  2177. if (writeSource)
  2178. {
  2179. LogVerbose(@"dispatch_source_cancel(writeSource)");
  2180. dispatch_source_cancel(writeSource);
  2181. [self resumeWriteSource];
  2182. writeSource = NULL;
  2183. }
  2184. // The sockets will be closed by the cancel handlers of the corresponding source
  2185. socket4FD = SOCKET_NULL;
  2186. socket6FD = SOCKET_NULL;
  2187. }
  2188. // If the client has passed the connect/accept method, then the connection has at least begun.
  2189. // Notify delegate that it is now ending.
  2190. BOOL shouldCallDelegate = (flags & kSocketStarted);
  2191. // Clear stored socket info and all flags (config remains as is)
  2192. socketFDBytesAvailable = 0;
  2193. flags = 0;
  2194. if (shouldCallDelegate)
  2195. {
  2196. if (delegateQueue && [delegate respondsToSelector: @selector(socketDidDisconnect:withError:)])
  2197. {
  2198. __strong id theDelegate = delegate;
  2199. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  2200. [theDelegate socketDidDisconnect:self withError:error];
  2201. }});
  2202. }
  2203. }
  2204. }
  2205. - (void)disconnect
  2206. {
  2207. dispatch_block_t block = ^{ @autoreleasepool {
  2208. if (flags & kSocketStarted)
  2209. {
  2210. [self closeWithError:nil];
  2211. }
  2212. }};
  2213. // Synchronous disconnection, as documented in the header file
  2214. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2215. block();
  2216. else
  2217. dispatch_sync(socketQueue, block);
  2218. }
  2219. - (void)disconnectAfterReading
  2220. {
  2221. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2222. if (flags & kSocketStarted)
  2223. {
  2224. flags |= (kForbidReadsWrites | kDisconnectAfterReads);
  2225. [self maybeClose];
  2226. }
  2227. }});
  2228. }
  2229. - (void)disconnectAfterWriting
  2230. {
  2231. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2232. if (flags & kSocketStarted)
  2233. {
  2234. flags |= (kForbidReadsWrites | kDisconnectAfterWrites);
  2235. [self maybeClose];
  2236. }
  2237. }});
  2238. }
  2239. - (void)disconnectAfterReadingAndWriting
  2240. {
  2241. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2242. if (flags & kSocketStarted)
  2243. {
  2244. flags |= (kForbidReadsWrites | kDisconnectAfterReads | kDisconnectAfterWrites);
  2245. [self maybeClose];
  2246. }
  2247. }});
  2248. }
  2249. /**
  2250. * Closes the socket if possible.
  2251. * That is, if all writes have completed, and we're set to disconnect after writing,
  2252. * or if all reads have completed, and we're set to disconnect after reading.
  2253. **/
  2254. - (void)maybeClose
  2255. {
  2256. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  2257. BOOL shouldClose = NO;
  2258. if (flags & kDisconnectAfterReads)
  2259. {
  2260. if (([readQueue count] == 0) && (currentRead == nil))
  2261. {
  2262. if (flags & kDisconnectAfterWrites)
  2263. {
  2264. if (([writeQueue count] == 0) && (currentWrite == nil))
  2265. {
  2266. shouldClose = YES;
  2267. }
  2268. }
  2269. else
  2270. {
  2271. shouldClose = YES;
  2272. }
  2273. }
  2274. }
  2275. else if (flags & kDisconnectAfterWrites)
  2276. {
  2277. if (([writeQueue count] == 0) && (currentWrite == nil))
  2278. {
  2279. shouldClose = YES;
  2280. }
  2281. }
  2282. if (shouldClose)
  2283. {
  2284. [self closeWithError:nil];
  2285. }
  2286. }
  2287. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2288. #pragma mark Errors
  2289. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2290. - (NSError *)badConfigError:(NSString *)errMsg
  2291. {
  2292. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2293. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketBadConfigError userInfo:userInfo];
  2294. }
  2295. - (NSError *)badParamError:(NSString *)errMsg
  2296. {
  2297. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2298. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketBadParamError userInfo:userInfo];
  2299. }
  2300. - (NSError *)gaiError:(int)gai_error
  2301. {
  2302. NSString *errMsg = [NSString stringWithCString:gai_strerror(gai_error) encoding:NSASCIIStringEncoding];
  2303. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2304. return [NSError errorWithDomain:@"kCFStreamErrorDomainNetDB" code:gai_error userInfo:userInfo];
  2305. }
  2306. - (NSError *)errnoErrorWithReason:(NSString *)reason
  2307. {
  2308. NSString *errMsg = [NSString stringWithUTF8String:strerror(errno)];
  2309. NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:errMsg, NSLocalizedDescriptionKey,
  2310. reason, NSLocalizedFailureReasonErrorKey, nil];
  2311. return [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:userInfo];
  2312. }
  2313. - (NSError *)errnoError
  2314. {
  2315. NSString *errMsg = [NSString stringWithUTF8String:strerror(errno)];
  2316. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2317. return [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:userInfo];
  2318. }
  2319. - (NSError *)sslError:(OSStatus)ssl_error
  2320. {
  2321. NSString *msg = @"Error code definition can be found in Apple's SecureTransport.h";
  2322. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:msg forKey:NSLocalizedRecoverySuggestionErrorKey];
  2323. return [NSError errorWithDomain:@"kCFStreamErrorDomainSSL" code:ssl_error userInfo:userInfo];
  2324. }
  2325. - (NSError *)connectTimeoutError
  2326. {
  2327. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketConnectTimeoutError",
  2328. @"GCDAsyncSocket", [NSBundle mainBundle],
  2329. @"Attempt to connect to host timed out", nil);
  2330. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2331. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketConnectTimeoutError userInfo:userInfo];
  2332. }
  2333. /**
  2334. * Returns a standard AsyncSocket maxed out error.
  2335. **/
  2336. - (NSError *)readMaxedOutError
  2337. {
  2338. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketReadMaxedOutError",
  2339. @"GCDAsyncSocket", [NSBundle mainBundle],
  2340. @"Read operation reached set maximum length", nil);
  2341. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2342. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketReadMaxedOutError userInfo:info];
  2343. }
  2344. /**
  2345. * Returns a standard AsyncSocket write timeout error.
  2346. **/
  2347. - (NSError *)readTimeoutError
  2348. {
  2349. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketReadTimeoutError",
  2350. @"GCDAsyncSocket", [NSBundle mainBundle],
  2351. @"Read operation timed out", nil);
  2352. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2353. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketReadTimeoutError userInfo:userInfo];
  2354. }
  2355. /**
  2356. * Returns a standard AsyncSocket write timeout error.
  2357. **/
  2358. - (NSError *)writeTimeoutError
  2359. {
  2360. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketWriteTimeoutError",
  2361. @"GCDAsyncSocket", [NSBundle mainBundle],
  2362. @"Write operation timed out", nil);
  2363. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2364. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketWriteTimeoutError userInfo:userInfo];
  2365. }
  2366. - (NSError *)connectionClosedError
  2367. {
  2368. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketClosedError",
  2369. @"GCDAsyncSocket", [NSBundle mainBundle],
  2370. @"Socket closed by remote peer", nil);
  2371. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2372. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketClosedError userInfo:userInfo];
  2373. }
  2374. - (NSError *)otherError:(NSString *)errMsg
  2375. {
  2376. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2377. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketOtherError userInfo:userInfo];
  2378. }
  2379. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2380. #pragma mark Diagnostics
  2381. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2382. - (BOOL)isDisconnected
  2383. {
  2384. __block BOOL result = NO;
  2385. dispatch_block_t block = ^{
  2386. result = (flags & kSocketStarted) ? NO : YES;
  2387. };
  2388. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2389. block();
  2390. else
  2391. dispatch_sync(socketQueue, block);
  2392. return result;
  2393. }
  2394. - (BOOL)isConnected
  2395. {
  2396. __block BOOL result = NO;
  2397. dispatch_block_t block = ^{
  2398. result = (flags & kConnected) ? YES : NO;
  2399. };
  2400. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2401. block();
  2402. else
  2403. dispatch_sync(socketQueue, block);
  2404. return result;
  2405. }
  2406. - (NSString *)connectedHost
  2407. {
  2408. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2409. {
  2410. if (socket4FD != SOCKET_NULL)
  2411. return [self connectedHostFromSocket4:socket4FD];
  2412. if (socket6FD != SOCKET_NULL)
  2413. return [self connectedHostFromSocket6:socket6FD];
  2414. return nil;
  2415. }
  2416. else
  2417. {
  2418. __block NSString *result = nil;
  2419. dispatch_sync(socketQueue, ^{ @autoreleasepool {
  2420. if (socket4FD != SOCKET_NULL)
  2421. result = [self connectedHostFromSocket4:socket4FD];
  2422. else if (socket6FD != SOCKET_NULL)
  2423. result = [self connectedHostFromSocket6:socket6FD];
  2424. }});
  2425. return result;
  2426. }
  2427. }
  2428. - (uint16_t)connectedPort
  2429. {
  2430. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2431. {
  2432. if (socket4FD != SOCKET_NULL)
  2433. return [self connectedPortFromSocket4:socket4FD];
  2434. if (socket6FD != SOCKET_NULL)
  2435. return [self connectedPortFromSocket6:socket6FD];
  2436. return 0;
  2437. }
  2438. else
  2439. {
  2440. __block uint16_t result = 0;
  2441. dispatch_sync(socketQueue, ^{
  2442. // No need for autorelease pool
  2443. if (socket4FD != SOCKET_NULL)
  2444. result = [self connectedPortFromSocket4:socket4FD];
  2445. else if (socket6FD != SOCKET_NULL)
  2446. result = [self connectedPortFromSocket6:socket6FD];
  2447. });
  2448. return result;
  2449. }
  2450. }
  2451. - (NSString *)localHost
  2452. {
  2453. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2454. {
  2455. if (socket4FD != SOCKET_NULL)
  2456. return [self localHostFromSocket4:socket4FD];
  2457. if (socket6FD != SOCKET_NULL)
  2458. return [self localHostFromSocket6:socket6FD];
  2459. return nil;
  2460. }
  2461. else
  2462. {
  2463. __block NSString *result = nil;
  2464. dispatch_sync(socketQueue, ^{ @autoreleasepool {
  2465. if (socket4FD != SOCKET_NULL)
  2466. result = [self localHostFromSocket4:socket4FD];
  2467. else if (socket6FD != SOCKET_NULL)
  2468. result = [self localHostFromSocket6:socket6FD];
  2469. }});
  2470. return result;
  2471. }
  2472. }
  2473. - (uint16_t)localPort
  2474. {
  2475. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2476. {
  2477. if (socket4FD != SOCKET_NULL)
  2478. return [self localPortFromSocket4:socket4FD];
  2479. if (socket6FD != SOCKET_NULL)
  2480. return [self localPortFromSocket6:socket6FD];
  2481. return 0;
  2482. }
  2483. else
  2484. {
  2485. __block uint16_t result = 0;
  2486. dispatch_sync(socketQueue, ^{
  2487. // No need for autorelease pool
  2488. if (socket4FD != SOCKET_NULL)
  2489. result = [self localPortFromSocket4:socket4FD];
  2490. else if (socket6FD != SOCKET_NULL)
  2491. result = [self localPortFromSocket6:socket6FD];
  2492. });
  2493. return result;
  2494. }
  2495. }
  2496. - (NSString *)connectedHost4
  2497. {
  2498. if (socket4FD != SOCKET_NULL)
  2499. return [self connectedHostFromSocket4:socket4FD];
  2500. return nil;
  2501. }
  2502. - (NSString *)connectedHost6
  2503. {
  2504. if (socket6FD != SOCKET_NULL)
  2505. return [self connectedHostFromSocket6:socket6FD];
  2506. return nil;
  2507. }
  2508. - (uint16_t)connectedPort4
  2509. {
  2510. if (socket4FD != SOCKET_NULL)
  2511. return [self connectedPortFromSocket4:socket4FD];
  2512. return 0;
  2513. }
  2514. - (uint16_t)connectedPort6
  2515. {
  2516. if (socket6FD != SOCKET_NULL)
  2517. return [self connectedPortFromSocket6:socket6FD];
  2518. return 0;
  2519. }
  2520. - (NSString *)localHost4
  2521. {
  2522. if (socket4FD != SOCKET_NULL)
  2523. return [self localHostFromSocket4:socket4FD];
  2524. return nil;
  2525. }
  2526. - (NSString *)localHost6
  2527. {
  2528. if (socket6FD != SOCKET_NULL)
  2529. return [self localHostFromSocket6:socket6FD];
  2530. return nil;
  2531. }
  2532. - (uint16_t)localPort4
  2533. {
  2534. if (socket4FD != SOCKET_NULL)
  2535. return [self localPortFromSocket4:socket4FD];
  2536. return 0;
  2537. }
  2538. - (uint16_t)localPort6
  2539. {
  2540. if (socket6FD != SOCKET_NULL)
  2541. return [self localPortFromSocket6:socket6FD];
  2542. return 0;
  2543. }
  2544. - (NSString *)connectedHostFromSocket4:(int)socketFD
  2545. {
  2546. struct sockaddr_in sockaddr4;
  2547. socklen_t sockaddr4len = sizeof(sockaddr4);
  2548. if (getpeername(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  2549. {
  2550. return nil;
  2551. }
  2552. return [[self class] hostFromSockaddr4:&sockaddr4];
  2553. }
  2554. - (NSString *)connectedHostFromSocket6:(int)socketFD
  2555. {
  2556. struct sockaddr_in6 sockaddr6;
  2557. socklen_t sockaddr6len = sizeof(sockaddr6);
  2558. if (getpeername(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  2559. {
  2560. return nil;
  2561. }
  2562. return [[self class] hostFromSockaddr6:&sockaddr6];
  2563. }
  2564. - (uint16_t)connectedPortFromSocket4:(int)socketFD
  2565. {
  2566. struct sockaddr_in sockaddr4;
  2567. socklen_t sockaddr4len = sizeof(sockaddr4);
  2568. if (getpeername(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  2569. {
  2570. return 0;
  2571. }
  2572. return [[self class] portFromSockaddr4:&sockaddr4];
  2573. }
  2574. - (uint16_t)connectedPortFromSocket6:(int)socketFD
  2575. {
  2576. struct sockaddr_in6 sockaddr6;
  2577. socklen_t sockaddr6len = sizeof(sockaddr6);
  2578. if (getpeername(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  2579. {
  2580. return 0;
  2581. }
  2582. return [[self class] portFromSockaddr6:&sockaddr6];
  2583. }
  2584. - (NSString *)localHostFromSocket4:(int)socketFD
  2585. {
  2586. struct sockaddr_in sockaddr4;
  2587. socklen_t sockaddr4len = sizeof(sockaddr4);
  2588. if (getsockname(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  2589. {
  2590. return nil;
  2591. }
  2592. return [[self class] hostFromSockaddr4:&sockaddr4];
  2593. }
  2594. - (NSString *)localHostFromSocket6:(int)socketFD
  2595. {
  2596. struct sockaddr_in6 sockaddr6;
  2597. socklen_t sockaddr6len = sizeof(sockaddr6);
  2598. if (getsockname(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  2599. {
  2600. return nil;
  2601. }
  2602. return [[self class] hostFromSockaddr6:&sockaddr6];
  2603. }
  2604. - (uint16_t)localPortFromSocket4:(int)socketFD
  2605. {
  2606. struct sockaddr_in sockaddr4;
  2607. socklen_t sockaddr4len = sizeof(sockaddr4);
  2608. if (getsockname(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  2609. {
  2610. return 0;
  2611. }
  2612. return [[self class] portFromSockaddr4:&sockaddr4];
  2613. }
  2614. - (uint16_t)localPortFromSocket6:(int)socketFD
  2615. {
  2616. struct sockaddr_in6 sockaddr6;
  2617. socklen_t sockaddr6len = sizeof(sockaddr6);
  2618. if (getsockname(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  2619. {
  2620. return 0;
  2621. }
  2622. return [[self class] portFromSockaddr6:&sockaddr6];
  2623. }
  2624. - (NSData *)connectedAddress
  2625. {
  2626. __block NSData *result = nil;
  2627. dispatch_block_t block = ^{
  2628. if (socket4FD != SOCKET_NULL)
  2629. {
  2630. struct sockaddr_in sockaddr4;
  2631. socklen_t sockaddr4len = sizeof(sockaddr4);
  2632. if (getpeername(socket4FD, (struct sockaddr *)&sockaddr4, &sockaddr4len) == 0)
  2633. {
  2634. result = [[NSData alloc] initWithBytes:&sockaddr4 length:sockaddr4len];
  2635. }
  2636. }
  2637. if (socket6FD != SOCKET_NULL)
  2638. {
  2639. struct sockaddr_in6 sockaddr6;
  2640. socklen_t sockaddr6len = sizeof(sockaddr6);
  2641. if (getpeername(socket6FD, (struct sockaddr *)&sockaddr6, &sockaddr6len) == 0)
  2642. {
  2643. result = [[NSData alloc] initWithBytes:&sockaddr6 length:sockaddr6len];
  2644. }
  2645. }
  2646. };
  2647. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2648. block();
  2649. else
  2650. dispatch_sync(socketQueue, block);
  2651. return result;
  2652. }
  2653. - (NSData *)localAddress
  2654. {
  2655. __block NSData *result = nil;
  2656. dispatch_block_t block = ^{
  2657. if (socket4FD != SOCKET_NULL)
  2658. {
  2659. struct sockaddr_in sockaddr4;
  2660. socklen_t sockaddr4len = sizeof(sockaddr4);
  2661. if (getsockname(socket4FD, (struct sockaddr *)&sockaddr4, &sockaddr4len) == 0)
  2662. {
  2663. result = [[NSData alloc] initWithBytes:&sockaddr4 length:sockaddr4len];
  2664. }
  2665. }
  2666. if (socket6FD != SOCKET_NULL)
  2667. {
  2668. struct sockaddr_in6 sockaddr6;
  2669. socklen_t sockaddr6len = sizeof(sockaddr6);
  2670. if (getsockname(socket6FD, (struct sockaddr *)&sockaddr6, &sockaddr6len) == 0)
  2671. {
  2672. result = [[NSData alloc] initWithBytes:&sockaddr6 length:sockaddr6len];
  2673. }
  2674. }
  2675. };
  2676. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2677. block();
  2678. else
  2679. dispatch_sync(socketQueue, block);
  2680. return result;
  2681. }
  2682. - (BOOL)isIPv4
  2683. {
  2684. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2685. {
  2686. return (socket4FD != SOCKET_NULL);
  2687. }
  2688. else
  2689. {
  2690. __block BOOL result = NO;
  2691. dispatch_sync(socketQueue, ^{
  2692. result = (socket4FD != SOCKET_NULL);
  2693. });
  2694. return result;
  2695. }
  2696. }
  2697. - (BOOL)isIPv6
  2698. {
  2699. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2700. {
  2701. return (socket6FD != SOCKET_NULL);
  2702. }
  2703. else
  2704. {
  2705. __block BOOL result = NO;
  2706. dispatch_sync(socketQueue, ^{
  2707. result = (socket6FD != SOCKET_NULL);
  2708. });
  2709. return result;
  2710. }
  2711. }
  2712. - (BOOL)isSecure
  2713. {
  2714. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  2715. {
  2716. return (flags & kSocketSecure) ? YES : NO;
  2717. }
  2718. else
  2719. {
  2720. __block BOOL result;
  2721. dispatch_sync(socketQueue, ^{
  2722. result = (flags & kSocketSecure) ? YES : NO;
  2723. });
  2724. return result;
  2725. }
  2726. }
  2727. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2728. #pragma mark Utilities
  2729. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2730. /**
  2731. * Finds the address of an interface description.
  2732. * An inteface description may be an interface name (en0, en1, lo0) or corresponding IP (192.168.4.34).
  2733. *
  2734. * The interface description may optionally contain a port number at the end, separated by a colon.
  2735. * If a non-zero port parameter is provided, any port number in the interface description is ignored.
  2736. *
  2737. * The returned value is a 'struct sockaddr' wrapped in an NSMutableData object.
  2738. **/
  2739. - (void)getInterfaceAddress4:(NSMutableData **)interfaceAddr4Ptr
  2740. address6:(NSMutableData **)interfaceAddr6Ptr
  2741. fromDescription:(NSString *)interfaceDescription
  2742. port:(uint16_t)port
  2743. {
  2744. NSMutableData *addr4 = nil;
  2745. NSMutableData *addr6 = nil;
  2746. NSString *interface = nil;
  2747. NSArray *components = [interfaceDescription componentsSeparatedByString:@":"];
  2748. if ([components count] > 0)
  2749. {
  2750. NSString *temp = [components objectAtIndex:0];
  2751. if ([temp length] > 0)
  2752. {
  2753. interface = temp;
  2754. }
  2755. }
  2756. if ([components count] > 1 && port == 0)
  2757. {
  2758. long portL = strtol([[components objectAtIndex:1] UTF8String], NULL, 10);
  2759. if (portL > 0 && portL <= UINT16_MAX)
  2760. {
  2761. port = (uint16_t)portL;
  2762. }
  2763. }
  2764. if (interface == nil)
  2765. {
  2766. // ANY address
  2767. struct sockaddr_in sockaddr4;
  2768. memset(&sockaddr4, 0, sizeof(sockaddr4));
  2769. sockaddr4.sin_len = sizeof(sockaddr4);
  2770. sockaddr4.sin_family = AF_INET;
  2771. sockaddr4.sin_port = htons(port);
  2772. sockaddr4.sin_addr.s_addr = htonl(INADDR_ANY);
  2773. struct sockaddr_in6 sockaddr6;
  2774. memset(&sockaddr6, 0, sizeof(sockaddr6));
  2775. sockaddr6.sin6_len = sizeof(sockaddr6);
  2776. sockaddr6.sin6_family = AF_INET6;
  2777. sockaddr6.sin6_port = htons(port);
  2778. sockaddr6.sin6_addr = in6addr_any;
  2779. addr4 = [NSMutableData dataWithBytes:&sockaddr4 length:sizeof(sockaddr4)];
  2780. addr6 = [NSMutableData dataWithBytes:&sockaddr6 length:sizeof(sockaddr6)];
  2781. }
  2782. else if ([interface isEqualToString:@"localhost"] || [interface isEqualToString:@"loopback"])
  2783. {
  2784. // LOOPBACK address
  2785. struct sockaddr_in sockaddr4;
  2786. memset(&sockaddr4, 0, sizeof(sockaddr4));
  2787. sockaddr4.sin_len = sizeof(sockaddr4);
  2788. sockaddr4.sin_family = AF_INET;
  2789. sockaddr4.sin_port = htons(port);
  2790. sockaddr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  2791. struct sockaddr_in6 sockaddr6;
  2792. memset(&sockaddr6, 0, sizeof(sockaddr6));
  2793. sockaddr6.sin6_len = sizeof(sockaddr6);
  2794. sockaddr6.sin6_family = AF_INET6;
  2795. sockaddr6.sin6_port = htons(port);
  2796. sockaddr6.sin6_addr = in6addr_loopback;
  2797. addr4 = [NSMutableData dataWithBytes:&sockaddr4 length:sizeof(sockaddr4)];
  2798. addr6 = [NSMutableData dataWithBytes:&sockaddr6 length:sizeof(sockaddr6)];
  2799. }
  2800. else
  2801. {
  2802. const char *iface = [interface UTF8String];
  2803. struct ifaddrs *addrs;
  2804. const struct ifaddrs *cursor;
  2805. if ((getifaddrs(&addrs) == 0))
  2806. {
  2807. cursor = addrs;
  2808. while (cursor != NULL)
  2809. {
  2810. if ((addr4 == nil) && (cursor->ifa_addr->sa_family == AF_INET))
  2811. {
  2812. // IPv4
  2813. struct sockaddr_in nativeAddr4;
  2814. memcpy(&nativeAddr4, cursor->ifa_addr, sizeof(nativeAddr4));
  2815. if (strcmp(cursor->ifa_name, iface) == 0)
  2816. {
  2817. // Name match
  2818. nativeAddr4.sin_port = htons(port);
  2819. addr4 = [NSMutableData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)];
  2820. }
  2821. else
  2822. {
  2823. char ip[INET_ADDRSTRLEN];
  2824. const char *conversion = inet_ntop(AF_INET, &nativeAddr4.sin_addr, ip, sizeof(ip));
  2825. if ((conversion != NULL) && (strcmp(ip, iface) == 0))
  2826. {
  2827. // IP match
  2828. nativeAddr4.sin_port = htons(port);
  2829. addr4 = [NSMutableData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)];
  2830. }
  2831. }
  2832. }
  2833. else if ((addr6 == nil) && (cursor->ifa_addr->sa_family == AF_INET6))
  2834. {
  2835. // IPv6
  2836. struct sockaddr_in6 nativeAddr6;
  2837. memcpy(&nativeAddr6, cursor->ifa_addr, sizeof(nativeAddr6));
  2838. if (strcmp(cursor->ifa_name, iface) == 0)
  2839. {
  2840. // Name match
  2841. nativeAddr6.sin6_port = htons(port);
  2842. addr6 = [NSMutableData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
  2843. }
  2844. else
  2845. {
  2846. char ip[INET6_ADDRSTRLEN];
  2847. const char *conversion = inet_ntop(AF_INET6, &nativeAddr6.sin6_addr, ip, sizeof(ip));
  2848. if ((conversion != NULL) && (strcmp(ip, iface) == 0))
  2849. {
  2850. // IP match
  2851. nativeAddr6.sin6_port = htons(port);
  2852. addr6 = [NSMutableData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
  2853. }
  2854. }
  2855. }
  2856. cursor = cursor->ifa_next;
  2857. }
  2858. freeifaddrs(addrs);
  2859. }
  2860. }
  2861. if (interfaceAddr4Ptr) *interfaceAddr4Ptr = addr4;
  2862. if (interfaceAddr6Ptr) *interfaceAddr6Ptr = addr6;
  2863. }
  2864. - (void)setupReadAndWriteSourcesForNewlyConnectedSocket:(int)socketFD
  2865. {
  2866. readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socketFD, 0, socketQueue);
  2867. writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, socketFD, 0, socketQueue);
  2868. // Setup event handlers
  2869. dispatch_source_set_event_handler(readSource, ^{ @autoreleasepool {
  2870. LogVerbose(@"readEventBlock");
  2871. socketFDBytesAvailable = dispatch_source_get_data(readSource);
  2872. LogVerbose(@"socketFDBytesAvailable: %lu", socketFDBytesAvailable);
  2873. if (socketFDBytesAvailable > 0)
  2874. [self doReadData];
  2875. else
  2876. [self doReadEOF];
  2877. }});
  2878. dispatch_source_set_event_handler(writeSource, ^{ @autoreleasepool {
  2879. LogVerbose(@"writeEventBlock");
  2880. flags |= kSocketCanAcceptBytes;
  2881. [self doWriteData];
  2882. }});
  2883. // Setup cancel handlers
  2884. __block int socketFDRefCount = 2;
  2885. #if NEEDS_DISPATCH_RETAIN_RELEASE
  2886. dispatch_source_t theReadSource = readSource;
  2887. dispatch_source_t theWriteSource = writeSource;
  2888. #endif
  2889. dispatch_source_set_cancel_handler(readSource, ^{
  2890. LogVerbose(@"readCancelBlock");
  2891. #if NEEDS_DISPATCH_RETAIN_RELEASE
  2892. LogVerbose(@"dispatch_release(readSource)");
  2893. dispatch_release(theReadSource);
  2894. #endif
  2895. if (--socketFDRefCount == 0)
  2896. {
  2897. LogVerbose(@"close(socketFD)");
  2898. close(socketFD);
  2899. }
  2900. });
  2901. dispatch_source_set_cancel_handler(writeSource, ^{
  2902. LogVerbose(@"writeCancelBlock");
  2903. #if NEEDS_DISPATCH_RETAIN_RELEASE
  2904. LogVerbose(@"dispatch_release(writeSource)");
  2905. dispatch_release(theWriteSource);
  2906. #endif
  2907. if (--socketFDRefCount == 0)
  2908. {
  2909. LogVerbose(@"close(socketFD)");
  2910. close(socketFD);
  2911. }
  2912. });
  2913. // We will not be able to read until data arrives.
  2914. // But we should be able to write immediately.
  2915. socketFDBytesAvailable = 0;
  2916. flags &= ~kReadSourceSuspended;
  2917. LogVerbose(@"dispatch_resume(readSource)");
  2918. dispatch_resume(readSource);
  2919. flags |= kSocketCanAcceptBytes;
  2920. flags |= kWriteSourceSuspended;
  2921. }
  2922. - (BOOL)usingCFStreamForTLS
  2923. {
  2924. #if TARGET_OS_IPHONE
  2925. {
  2926. if ((flags & kSocketSecure) && (flags & kUsingCFStreamForTLS))
  2927. {
  2928. // Due to the fact that Apple doesn't give us the full power of SecureTransport on iOS,
  2929. // we are relegated to using the slower, less powerful, and RunLoop based CFStream API. :( Boo!
  2930. //
  2931. // Thus we're not able to use the GCD read/write sources in this particular scenario.
  2932. return YES;
  2933. }
  2934. }
  2935. #endif
  2936. return NO;
  2937. }
  2938. - (BOOL)usingSecureTransportForTLS
  2939. {
  2940. #if TARGET_OS_IPHONE
  2941. {
  2942. return ![self usingCFStreamForTLS];
  2943. }
  2944. #endif
  2945. return YES;
  2946. }
  2947. - (void)suspendReadSource
  2948. {
  2949. if (!(flags & kReadSourceSuspended))
  2950. {
  2951. LogVerbose(@"dispatch_suspend(readSource)");
  2952. dispatch_suspend(readSource);
  2953. flags |= kReadSourceSuspended;
  2954. }
  2955. }
  2956. - (void)resumeReadSource
  2957. {
  2958. if (flags & kReadSourceSuspended)
  2959. {
  2960. LogVerbose(@"dispatch_resume(readSource)");
  2961. dispatch_resume(readSource);
  2962. flags &= ~kReadSourceSuspended;
  2963. }
  2964. }
  2965. - (void)suspendWriteSource
  2966. {
  2967. if (!(flags & kWriteSourceSuspended))
  2968. {
  2969. LogVerbose(@"dispatch_suspend(writeSource)");
  2970. dispatch_suspend(writeSource);
  2971. flags |= kWriteSourceSuspended;
  2972. }
  2973. }
  2974. - (void)resumeWriteSource
  2975. {
  2976. if (flags & kWriteSourceSuspended)
  2977. {
  2978. LogVerbose(@"dispatch_resume(writeSource)");
  2979. dispatch_resume(writeSource);
  2980. flags &= ~kWriteSourceSuspended;
  2981. }
  2982. }
  2983. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2984. #pragma mark Reading
  2985. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2986. - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag
  2987. {
  2988. [self readDataWithTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag];
  2989. }
  2990. - (void)readDataWithTimeout:(NSTimeInterval)timeout
  2991. buffer:(NSMutableData *)buffer
  2992. bufferOffset:(NSUInteger)offset
  2993. tag:(long)tag
  2994. {
  2995. [self readDataWithTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag];
  2996. }
  2997. - (void)readDataWithTimeout:(NSTimeInterval)timeout
  2998. buffer:(NSMutableData *)buffer
  2999. bufferOffset:(NSUInteger)offset
  3000. maxLength:(NSUInteger)length
  3001. tag:(long)tag
  3002. {
  3003. if (offset > [buffer length]) {
  3004. LogWarn(@"Cannot read: offset > [buffer length]");
  3005. return;
  3006. }
  3007. GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer
  3008. startOffset:offset
  3009. maxLength:length
  3010. timeout:timeout
  3011. readLength:0
  3012. terminator:nil
  3013. tag:tag];
  3014. dispatch_async(socketQueue, ^{ @autoreleasepool {
  3015. LogTrace();
  3016. if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
  3017. {
  3018. [readQueue addObject:packet];
  3019. [self maybeDequeueRead];
  3020. }
  3021. }});
  3022. // Do not rely on the block being run in order to release the packet,
  3023. // as the queue might get released without the block completing.
  3024. }
  3025. - (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag
  3026. {
  3027. [self readDataToLength:length withTimeout:timeout buffer:nil bufferOffset:0 tag:tag];
  3028. }
  3029. - (void)readDataToLength:(NSUInteger)length
  3030. withTimeout:(NSTimeInterval)timeout
  3031. buffer:(NSMutableData *)buffer
  3032. bufferOffset:(NSUInteger)offset
  3033. tag:(long)tag
  3034. {
  3035. if (length == 0) {
  3036. LogWarn(@"Cannot read: length == 0");
  3037. return;
  3038. }
  3039. if (offset > [buffer length]) {
  3040. LogWarn(@"Cannot read: offset > [buffer length]");
  3041. return;
  3042. }
  3043. GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer
  3044. startOffset:offset
  3045. maxLength:0
  3046. timeout:timeout
  3047. readLength:length
  3048. terminator:nil
  3049. tag:tag];
  3050. dispatch_async(socketQueue, ^{ @autoreleasepool {
  3051. LogTrace();
  3052. if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
  3053. {
  3054. [readQueue addObject:packet];
  3055. [self maybeDequeueRead];
  3056. }
  3057. }});
  3058. // Do not rely on the block being run in order to release the packet,
  3059. // as the queue might get released without the block completing.
  3060. }
  3061. - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
  3062. {
  3063. [self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag];
  3064. }
  3065. - (void)readDataToData:(NSData *)data
  3066. withTimeout:(NSTimeInterval)timeout
  3067. buffer:(NSMutableData *)buffer
  3068. bufferOffset:(NSUInteger)offset
  3069. tag:(long)tag
  3070. {
  3071. [self readDataToData:data withTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag];
  3072. }
  3073. - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag
  3074. {
  3075. [self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:length tag:tag];
  3076. }
  3077. - (void)readDataToData:(NSData *)data
  3078. withTimeout:(NSTimeInterval)timeout
  3079. buffer:(NSMutableData *)buffer
  3080. bufferOffset:(NSUInteger)offset
  3081. maxLength:(NSUInteger)maxLength
  3082. tag:(long)tag
  3083. {
  3084. if ([data length] == 0) {
  3085. LogWarn(@"Cannot read: [data length] == 0");
  3086. return;
  3087. }
  3088. if (offset > [buffer length]) {
  3089. LogWarn(@"Cannot read: offset > [buffer length]");
  3090. return;
  3091. }
  3092. if (maxLength > 0 && maxLength < [data length]) {
  3093. LogWarn(@"Cannot read: maxLength > 0 && maxLength < [data length]");
  3094. return;
  3095. }
  3096. GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer
  3097. startOffset:offset
  3098. maxLength:maxLength
  3099. timeout:timeout
  3100. readLength:0
  3101. terminator:data
  3102. tag:tag];
  3103. dispatch_async(socketQueue, ^{ @autoreleasepool {
  3104. LogTrace();
  3105. if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
  3106. {
  3107. [readQueue addObject:packet];
  3108. [self maybeDequeueRead];
  3109. }
  3110. }});
  3111. // Do not rely on the block being run in order to release the packet,
  3112. // as the queue might get released without the block completing.
  3113. }
  3114. - (float)progressOfReadReturningTag:(long *)tagPtr bytesDone:(NSUInteger *)donePtr total:(NSUInteger *)totalPtr
  3115. {
  3116. __block float result = 0.0F;
  3117. dispatch_block_t block = ^{
  3118. if (!currentRead || ![currentRead isKindOfClass:[GCDAsyncReadPacket class]])
  3119. {
  3120. // We're not reading anything right now.
  3121. if (tagPtr != NULL) *tagPtr = 0;
  3122. if (donePtr != NULL) *donePtr = 0;
  3123. if (totalPtr != NULL) *totalPtr = 0;
  3124. result = NAN;
  3125. }
  3126. else
  3127. {
  3128. // It's only possible to know the progress of our read if we're reading to a certain length.
  3129. // If we're reading to data, we of course have no idea when the data will arrive.
  3130. // If we're reading to timeout, then we have no idea when the next chunk of data will arrive.
  3131. NSUInteger done = currentRead->bytesDone;
  3132. NSUInteger total = currentRead->readLength;
  3133. if (tagPtr != NULL) *tagPtr = currentRead->tag;
  3134. if (donePtr != NULL) *donePtr = done;
  3135. if (totalPtr != NULL) *totalPtr = total;
  3136. if (total > 0)
  3137. result = (float)done / (float)total;
  3138. else
  3139. result = 1.0F;
  3140. }
  3141. };
  3142. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  3143. block();
  3144. else
  3145. dispatch_sync(socketQueue, block);
  3146. return result;
  3147. }
  3148. /**
  3149. * This method starts a new read, if needed.
  3150. *
  3151. * It is called when:
  3152. * - a user requests a read
  3153. * - after a read request has finished (to handle the next request)
  3154. * - immediately after the socket opens to handle any pending requests
  3155. *
  3156. * This method also handles auto-disconnect post read/write completion.
  3157. **/
  3158. - (void)maybeDequeueRead
  3159. {
  3160. LogTrace();
  3161. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  3162. // If we're not currently processing a read AND we have an available read stream
  3163. if ((currentRead == nil) && (flags & kConnected))
  3164. {
  3165. if ([readQueue count] > 0)
  3166. {
  3167. // Dequeue the next object in the write queue
  3168. currentRead = [readQueue objectAtIndex:0];
  3169. [readQueue removeObjectAtIndex:0];
  3170. if ([currentRead isKindOfClass:[GCDAsyncSpecialPacket class]])
  3171. {
  3172. LogVerbose(@"Dequeued GCDAsyncSpecialPacket");
  3173. // Attempt to start TLS
  3174. flags |= kStartingReadTLS;
  3175. // This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set
  3176. [self maybeStartTLS];
  3177. }
  3178. else
  3179. {
  3180. LogVerbose(@"Dequeued GCDAsyncReadPacket");
  3181. // Setup read timer (if needed)
  3182. [self setupReadTimerWithTimeout:currentRead->timeout];
  3183. // Immediately read, if possible
  3184. [self doReadData];
  3185. }
  3186. }
  3187. else if (flags & kDisconnectAfterReads)
  3188. {
  3189. if (flags & kDisconnectAfterWrites)
  3190. {
  3191. if (([writeQueue count] == 0) && (currentWrite == nil))
  3192. {
  3193. [self closeWithError:nil];
  3194. }
  3195. }
  3196. else
  3197. {
  3198. [self closeWithError:nil];
  3199. }
  3200. }
  3201. else if (flags & kSocketSecure)
  3202. {
  3203. [self flushSSLBuffers];
  3204. // Edge case:
  3205. //
  3206. // We just drained all data from the ssl buffers,
  3207. // and all known data from the socket (socketFDBytesAvailable).
  3208. //
  3209. // If we didn't get any data from this process,
  3210. // then we may have reached the end of the TCP stream.
  3211. //
  3212. // Be sure callbacks are enabled so we're notified about a disconnection.
  3213. if ([preBuffer availableBytes] == 0)
  3214. {
  3215. if ([self usingCFStreamForTLS]) {
  3216. // Callbacks never disabled
  3217. }
  3218. else {
  3219. [self resumeReadSource];
  3220. }
  3221. }
  3222. }
  3223. }
  3224. }
  3225. - (void)flushSSLBuffers
  3226. {
  3227. LogTrace();
  3228. NSAssert((flags & kSocketSecure), @"Cannot flush ssl buffers on non-secure socket");
  3229. if ([preBuffer availableBytes] > 0)
  3230. {
  3231. // Only flush the ssl buffers if the prebuffer is empty.
  3232. // This is to avoid growing the prebuffer inifinitely large.
  3233. return;
  3234. }
  3235. #if TARGET_OS_IPHONE
  3236. if ([self usingCFStreamForTLS])
  3237. {
  3238. if ((flags & kSecureSocketHasBytesAvailable) && CFReadStreamHasBytesAvailable(readStream))
  3239. {
  3240. LogVerbose(@"%@ - Flushing ssl buffers into prebuffer...", THIS_METHOD);
  3241. CFIndex defaultBytesToRead = (1024 * 4);
  3242. [preBuffer ensureCapacityForWrite:defaultBytesToRead];
  3243. uint8_t *buffer = [preBuffer writeBuffer];
  3244. CFIndex result = CFReadStreamRead(readStream, buffer, defaultBytesToRead);
  3245. LogVerbose(@"%@ - CFReadStreamRead(): result = %i", THIS_METHOD, (int)result);
  3246. if (result > 0)
  3247. {
  3248. [preBuffer didWrite:result];
  3249. }
  3250. flags &= ~kSecureSocketHasBytesAvailable;
  3251. }
  3252. return;
  3253. }
  3254. #endif
  3255. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  3256. __block NSUInteger estimatedBytesAvailable = 0;
  3257. dispatch_block_t updateEstimatedBytesAvailable = ^{
  3258. // Figure out if there is any data available to be read
  3259. //
  3260. // socketFDBytesAvailable <- Number of encrypted bytes we haven't read from the bsd socket
  3261. // [sslPreBuffer availableBytes] <- Number of encrypted bytes we've buffered from bsd socket
  3262. // sslInternalBufSize <- Number of decrypted bytes SecureTransport has buffered
  3263. //
  3264. // We call the variable "estimated" because we don't know how many decrypted bytes we'll get
  3265. // from the encrypted bytes in the sslPreBuffer.
  3266. // However, we do know this is an upper bound on the estimation.
  3267. estimatedBytesAvailable = socketFDBytesAvailable + [sslPreBuffer availableBytes];
  3268. size_t sslInternalBufSize = 0;
  3269. SSLGetBufferedReadSize(sslContext, &sslInternalBufSize);
  3270. estimatedBytesAvailable += sslInternalBufSize;
  3271. };
  3272. updateEstimatedBytesAvailable();
  3273. if (estimatedBytesAvailable > 0)
  3274. {
  3275. LogVerbose(@"%@ - Flushing ssl buffers into prebuffer...", THIS_METHOD);
  3276. BOOL done = NO;
  3277. do
  3278. {
  3279. LogVerbose(@"%@ - estimatedBytesAvailable = %lu", THIS_METHOD, (unsigned long)estimatedBytesAvailable);
  3280. // Make sure there's enough room in the prebuffer
  3281. [preBuffer ensureCapacityForWrite:estimatedBytesAvailable];
  3282. // Read data into prebuffer
  3283. uint8_t *buffer = [preBuffer writeBuffer];
  3284. size_t bytesRead = 0;
  3285. OSStatus result = SSLRead(sslContext, buffer, (size_t)estimatedBytesAvailable, &bytesRead);
  3286. LogVerbose(@"%@ - read from secure socket = %u", THIS_METHOD, (unsigned)bytesRead);
  3287. if (bytesRead > 0)
  3288. {
  3289. [preBuffer didWrite:bytesRead];
  3290. }
  3291. LogVerbose(@"%@ - prebuffer.length = %zu", THIS_METHOD, [preBuffer availableBytes]);
  3292. if (result != noErr)
  3293. {
  3294. done = YES;
  3295. }
  3296. else
  3297. {
  3298. updateEstimatedBytesAvailable();
  3299. }
  3300. } while (!done && estimatedBytesAvailable > 0);
  3301. }
  3302. #endif
  3303. }
  3304. - (void)doReadData
  3305. {
  3306. LogTrace();
  3307. // This method is called on the socketQueue.
  3308. // It might be called directly, or via the readSource when data is available to be read.
  3309. if ((currentRead == nil) || (flags & kReadsPaused))
  3310. {
  3311. LogVerbose(@"No currentRead or kReadsPaused");
  3312. // Unable to read at this time
  3313. if (flags & kSocketSecure)
  3314. {
  3315. // Here's the situation:
  3316. //
  3317. // We have an established secure connection.
  3318. // There may not be a currentRead, but there might be encrypted data sitting around for us.
  3319. // When the user does get around to issuing a read, that encrypted data will need to be decrypted.
  3320. //
  3321. // So why make the user wait?
  3322. // We might as well get a head start on decrypting some data now.
  3323. //
  3324. // The other reason we do this has to do with detecting a socket disconnection.
  3325. // The SSL/TLS protocol has it's own disconnection handshake.
  3326. // So when a secure socket is closed, a "goodbye" packet comes across the wire.
  3327. // We want to make sure we read the "goodbye" packet so we can properly detect the TCP disconnection.
  3328. [self flushSSLBuffers];
  3329. }
  3330. if ([self usingCFStreamForTLS])
  3331. {
  3332. // CFReadStream only fires once when there is available data.
  3333. // It won't fire again until we've invoked CFReadStreamRead.
  3334. }
  3335. else
  3336. {
  3337. // If the readSource is firing, we need to pause it
  3338. // or else it will continue to fire over and over again.
  3339. //
  3340. // If the readSource is not firing,
  3341. // we want it to continue monitoring the socket.
  3342. if (socketFDBytesAvailable > 0)
  3343. {
  3344. [self suspendReadSource];
  3345. }
  3346. }
  3347. return;
  3348. }
  3349. BOOL hasBytesAvailable = NO;
  3350. unsigned long estimatedBytesAvailable = 0;
  3351. if ([self usingCFStreamForTLS])
  3352. {
  3353. #if TARGET_OS_IPHONE
  3354. // Relegated to using CFStream... :( Boo! Give us a full SecureTransport stack Apple!
  3355. estimatedBytesAvailable = 0;
  3356. if ((flags & kSecureSocketHasBytesAvailable) && CFReadStreamHasBytesAvailable(readStream))
  3357. hasBytesAvailable = YES;
  3358. else
  3359. hasBytesAvailable = NO;
  3360. #endif
  3361. }
  3362. else
  3363. {
  3364. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  3365. estimatedBytesAvailable = socketFDBytesAvailable;
  3366. if (flags & kSocketSecure)
  3367. {
  3368. // There are 2 buffers to be aware of here.
  3369. //
  3370. // We are using SecureTransport, a TLS/SSL security layer which sits atop TCP.
  3371. // We issue a read to the SecureTranport API, which in turn issues a read to our SSLReadFunction.
  3372. // Our SSLReadFunction then reads from the BSD socket and returns the encrypted data to SecureTransport.
  3373. // SecureTransport then decrypts the data, and finally returns the decrypted data back to us.
  3374. //
  3375. // The first buffer is one we create.
  3376. // SecureTransport often requests small amounts of data.
  3377. // This has to do with the encypted packets that are coming across the TCP stream.
  3378. // But it's non-optimal to do a bunch of small reads from the BSD socket.
  3379. // So our SSLReadFunction reads all available data from the socket (optimizing the sys call)
  3380. // and may store excess in the sslPreBuffer.
  3381. estimatedBytesAvailable += [sslPreBuffer availableBytes];
  3382. // The second buffer is within SecureTransport.
  3383. // As mentioned earlier, there are encrypted packets coming across the TCP stream.
  3384. // SecureTransport needs the entire packet to decrypt it.
  3385. // But if the entire packet produces X bytes of decrypted data,
  3386. // and we only asked SecureTransport for X/2 bytes of data,
  3387. // it must store the extra X/2 bytes of decrypted data for the next read.
  3388. //
  3389. // The SSLGetBufferedReadSize function will tell us the size of this internal buffer.
  3390. // From the documentation:
  3391. //
  3392. // "This function does not block or cause any low-level read operations to occur."
  3393. size_t sslInternalBufSize = 0;
  3394. SSLGetBufferedReadSize(sslContext, &sslInternalBufSize);
  3395. estimatedBytesAvailable += sslInternalBufSize;
  3396. }
  3397. hasBytesAvailable = (estimatedBytesAvailable > 0);
  3398. #endif
  3399. }
  3400. if ((hasBytesAvailable == NO) && ([preBuffer availableBytes] == 0))
  3401. {
  3402. LogVerbose(@"No data available to read...");
  3403. // No data available to read.
  3404. if (![self usingCFStreamForTLS])
  3405. {
  3406. // Need to wait for readSource to fire and notify us of
  3407. // available data in the socket's internal read buffer.
  3408. [self resumeReadSource];
  3409. }
  3410. return;
  3411. }
  3412. if (flags & kStartingReadTLS)
  3413. {
  3414. LogVerbose(@"Waiting for SSL/TLS handshake to complete");
  3415. // The readQueue is waiting for SSL/TLS handshake to complete.
  3416. if (flags & kStartingWriteTLS)
  3417. {
  3418. if ([self usingSecureTransportForTLS])
  3419. {
  3420. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  3421. // We are in the process of a SSL Handshake.
  3422. // We were waiting for incoming data which has just arrived.
  3423. [self ssl_continueSSLHandshake];
  3424. #endif
  3425. }
  3426. }
  3427. else
  3428. {
  3429. // We are still waiting for the writeQueue to drain and start the SSL/TLS process.
  3430. // We now know data is available to read.
  3431. if (![self usingCFStreamForTLS])
  3432. {
  3433. // Suspend the read source or else it will continue to fire nonstop.
  3434. [self suspendReadSource];
  3435. }
  3436. }
  3437. return;
  3438. }
  3439. BOOL done = NO; // Completed read operation
  3440. NSError *error = nil; // Error occured
  3441. NSUInteger totalBytesReadForCurrentRead = 0;
  3442. //
  3443. // STEP 1 - READ FROM PREBUFFER
  3444. //
  3445. if ([preBuffer availableBytes] > 0)
  3446. {
  3447. // There are 3 types of read packets:
  3448. //
  3449. // 1) Read all available data.
  3450. // 2) Read a specific length of data.
  3451. // 3) Read up to a particular terminator.
  3452. NSUInteger bytesToCopy;
  3453. if (currentRead->term != nil)
  3454. {
  3455. // Read type #3 - read up to a terminator
  3456. bytesToCopy = [currentRead readLengthForTermWithPreBuffer:preBuffer found:&done];
  3457. }
  3458. else
  3459. {
  3460. // Read type #1 or #2
  3461. bytesToCopy = [currentRead readLengthForNonTermWithHint:[preBuffer availableBytes]];
  3462. }
  3463. // Make sure we have enough room in the buffer for our read.
  3464. [currentRead ensureCapacityForAdditionalDataOfLength:bytesToCopy];
  3465. // Copy bytes from prebuffer into packet buffer
  3466. uint8_t *buffer = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset +
  3467. currentRead->bytesDone;
  3468. memcpy(buffer, [preBuffer readBuffer], bytesToCopy);
  3469. // Remove the copied bytes from the preBuffer
  3470. [preBuffer didRead:bytesToCopy];
  3471. LogVerbose(@"copied(%lu) preBufferLength(%zu)", (unsigned long)bytesToCopy, [preBuffer availableBytes]);
  3472. // Update totals
  3473. currentRead->bytesDone += bytesToCopy;
  3474. totalBytesReadForCurrentRead += bytesToCopy;
  3475. // Check to see if the read operation is done
  3476. if (currentRead->readLength > 0)
  3477. {
  3478. // Read type #2 - read a specific length of data
  3479. done = (currentRead->bytesDone == currentRead->readLength);
  3480. }
  3481. else if (currentRead->term != nil)
  3482. {
  3483. // Read type #3 - read up to a terminator
  3484. // Our 'done' variable was updated via the readLengthForTermWithPreBuffer:found: method
  3485. if (!done && currentRead->maxLength > 0)
  3486. {
  3487. // We're not done and there's a set maxLength.
  3488. // Have we reached that maxLength yet?
  3489. if (currentRead->bytesDone >= currentRead->maxLength)
  3490. {
  3491. error = [self readMaxedOutError];
  3492. }
  3493. }
  3494. }
  3495. else
  3496. {
  3497. // Read type #1 - read all available data
  3498. //
  3499. // We're done as soon as
  3500. // - we've read all available data (in prebuffer and socket)
  3501. // - we've read the maxLength of read packet.
  3502. done = ((currentRead->maxLength > 0) && (currentRead->bytesDone == currentRead->maxLength));
  3503. }
  3504. }
  3505. //
  3506. // STEP 2 - READ FROM SOCKET
  3507. //
  3508. BOOL socketEOF = (flags & kSocketHasReadEOF) ? YES : NO; // Nothing more to via socket (end of file)
  3509. BOOL waiting = !done && !error && !socketEOF && !hasBytesAvailable; // Ran out of data, waiting for more
  3510. if (!done && !error && !socketEOF && !waiting && hasBytesAvailable)
  3511. {
  3512. NSAssert(([preBuffer availableBytes] == 0), @"Invalid logic");
  3513. // There are 3 types of read packets:
  3514. //
  3515. // 1) Read all available data.
  3516. // 2) Read a specific length of data.
  3517. // 3) Read up to a particular terminator.
  3518. BOOL readIntoPreBuffer = NO;
  3519. NSUInteger bytesToRead;
  3520. if ([self usingCFStreamForTLS])
  3521. {
  3522. // Since Apple hasn't made the full power of SecureTransport available on iOS,
  3523. // we are relegated to using the slower, less powerful, RunLoop based CFStream API.
  3524. //
  3525. // This API doesn't tell us how much data is available on the socket to be read.
  3526. // If we had that information we could optimize our memory allocations, and sys calls.
  3527. //
  3528. // But alas...
  3529. // So we do it old school, and just read as much data from the socket as we can.
  3530. NSUInteger defaultReadLength = (1024 * 32);
  3531. bytesToRead = [currentRead optimalReadLengthWithDefault:defaultReadLength
  3532. shouldPreBuffer:&readIntoPreBuffer];
  3533. }
  3534. else
  3535. {
  3536. if (currentRead->term != nil)
  3537. {
  3538. // Read type #3 - read up to a terminator
  3539. bytesToRead = [currentRead readLengthForTermWithHint:estimatedBytesAvailable
  3540. shouldPreBuffer:&readIntoPreBuffer];
  3541. }
  3542. else
  3543. {
  3544. // Read type #1 or #2
  3545. bytesToRead = [currentRead readLengthForNonTermWithHint:estimatedBytesAvailable];
  3546. }
  3547. }
  3548. if (bytesToRead > SIZE_MAX) // NSUInteger may be bigger than size_t (read param 3)
  3549. {
  3550. bytesToRead = SIZE_MAX;
  3551. }
  3552. // Make sure we have enough room in the buffer for our read.
  3553. //
  3554. // We are either reading directly into the currentRead->buffer,
  3555. // or we're reading into the temporary preBuffer.
  3556. uint8_t *buffer;
  3557. if (readIntoPreBuffer)
  3558. {
  3559. [preBuffer ensureCapacityForWrite:bytesToRead];
  3560. buffer = [preBuffer writeBuffer];
  3561. }
  3562. else
  3563. {
  3564. [currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead];
  3565. buffer = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset + currentRead->bytesDone;
  3566. }
  3567. // Read data into buffer
  3568. size_t bytesRead = 0;
  3569. if (flags & kSocketSecure)
  3570. {
  3571. if ([self usingCFStreamForTLS])
  3572. {
  3573. #if TARGET_OS_IPHONE
  3574. CFIndex result = CFReadStreamRead(readStream, buffer, (CFIndex)bytesToRead);
  3575. LogVerbose(@"CFReadStreamRead(): result = %i", (int)result);
  3576. if (result < 0)
  3577. {
  3578. error = (__bridge_transfer NSError *)CFReadStreamCopyError(readStream);
  3579. }
  3580. else if (result == 0)
  3581. {
  3582. socketEOF = YES;
  3583. }
  3584. else
  3585. {
  3586. waiting = YES;
  3587. bytesRead = (size_t)result;
  3588. }
  3589. // We only know how many decrypted bytes were read.
  3590. // The actual number of bytes read was likely more due to the overhead of the encryption.
  3591. // So we reset our flag, and rely on the next callback to alert us of more data.
  3592. flags &= ~kSecureSocketHasBytesAvailable;
  3593. #endif
  3594. }
  3595. else
  3596. {
  3597. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  3598. // The documentation from Apple states:
  3599. //
  3600. // "a read operation might return errSSLWouldBlock,
  3601. // indicating that less data than requested was actually transferred"
  3602. //
  3603. // However, starting around 10.7, the function will sometimes return noErr,
  3604. // even if it didn't read as much data as requested. So we need to watch out for that.
  3605. OSStatus result;
  3606. do
  3607. {
  3608. void *loop_buffer = buffer + bytesRead;
  3609. size_t loop_bytesToRead = (size_t)bytesToRead - bytesRead;
  3610. size_t loop_bytesRead = 0;
  3611. result = SSLRead(sslContext, loop_buffer, loop_bytesToRead, &loop_bytesRead);
  3612. LogVerbose(@"read from secure socket = %u", (unsigned)bytesRead);
  3613. bytesRead += loop_bytesRead;
  3614. } while ((result == noErr) && (bytesRead < bytesToRead));
  3615. if (result != noErr)
  3616. {
  3617. if (result == errSSLWouldBlock)
  3618. waiting = YES;
  3619. else
  3620. {
  3621. if (result == errSSLClosedGraceful || result == errSSLClosedAbort)
  3622. {
  3623. // We've reached the end of the stream.
  3624. // Handle this the same way we would an EOF from the socket.
  3625. socketEOF = YES;
  3626. sslErrCode = result;
  3627. }
  3628. else
  3629. {
  3630. error = [self sslError:result];
  3631. }
  3632. }
  3633. // It's possible that bytesRead > 0, even if the result was errSSLWouldBlock.
  3634. // This happens when the SSLRead function is able to read some data,
  3635. // but not the entire amount we requested.
  3636. if (bytesRead <= 0)
  3637. {
  3638. bytesRead = 0;
  3639. }
  3640. }
  3641. // Do not modify socketFDBytesAvailable.
  3642. // It will be updated via the SSLReadFunction().
  3643. #endif
  3644. }
  3645. }
  3646. else
  3647. {
  3648. int socketFD = (socket4FD == SOCKET_NULL) ? socket6FD : socket4FD;
  3649. ssize_t result = read(socketFD, buffer, (size_t)bytesToRead);
  3650. LogVerbose(@"read from socket = %i", (int)result);
  3651. if (result < 0)
  3652. {
  3653. if (errno == EWOULDBLOCK)
  3654. waiting = YES;
  3655. else
  3656. error = [self errnoErrorWithReason:@"Error in read() function"];
  3657. socketFDBytesAvailable = 0;
  3658. }
  3659. else if (result == 0)
  3660. {
  3661. socketEOF = YES;
  3662. socketFDBytesAvailable = 0;
  3663. }
  3664. else
  3665. {
  3666. bytesRead = result;
  3667. if (bytesRead < bytesToRead)
  3668. {
  3669. // The read returned less data than requested.
  3670. // This means socketFDBytesAvailable was a bit off due to timing,
  3671. // because we read from the socket right when the readSource event was firing.
  3672. socketFDBytesAvailable = 0;
  3673. }
  3674. else
  3675. {
  3676. if (socketFDBytesAvailable <= bytesRead)
  3677. socketFDBytesAvailable = 0;
  3678. else
  3679. socketFDBytesAvailable -= bytesRead;
  3680. }
  3681. if (socketFDBytesAvailable == 0)
  3682. {
  3683. waiting = YES;
  3684. }
  3685. }
  3686. }
  3687. if (bytesRead > 0)
  3688. {
  3689. // Check to see if the read operation is done
  3690. if (currentRead->readLength > 0)
  3691. {
  3692. // Read type #2 - read a specific length of data
  3693. //
  3694. // Note: We should never be using a prebuffer when we're reading a specific length of data.
  3695. NSAssert(readIntoPreBuffer == NO, @"Invalid logic");
  3696. currentRead->bytesDone += bytesRead;
  3697. totalBytesReadForCurrentRead += bytesRead;
  3698. done = (currentRead->bytesDone == currentRead->readLength);
  3699. }
  3700. else if (currentRead->term != nil)
  3701. {
  3702. // Read type #3 - read up to a terminator
  3703. if (readIntoPreBuffer)
  3704. {
  3705. // We just read a big chunk of data into the preBuffer
  3706. [preBuffer didWrite:bytesRead];
  3707. LogVerbose(@"read data into preBuffer - preBuffer.length = %zu", [preBuffer availableBytes]);
  3708. // Search for the terminating sequence
  3709. bytesToRead = [currentRead readLengthForTermWithPreBuffer:preBuffer found:&done];
  3710. LogVerbose(@"copying %lu bytes from preBuffer", (unsigned long)bytesToRead);
  3711. // Ensure there's room on the read packet's buffer
  3712. [currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead];
  3713. // Copy bytes from prebuffer into read buffer
  3714. uint8_t *readBuf = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset
  3715. + currentRead->bytesDone;
  3716. memcpy(readBuf, [preBuffer readBuffer], bytesToRead);
  3717. // Remove the copied bytes from the prebuffer
  3718. [preBuffer didRead:bytesToRead];
  3719. LogVerbose(@"preBuffer.length = %zu", [preBuffer availableBytes]);
  3720. // Update totals
  3721. currentRead->bytesDone += bytesToRead;
  3722. totalBytesReadForCurrentRead += bytesToRead;
  3723. // Our 'done' variable was updated via the readLengthForTermWithPreBuffer:found: method above
  3724. }
  3725. else
  3726. {
  3727. // We just read a big chunk of data directly into the packet's buffer.
  3728. // We need to move any overflow into the prebuffer.
  3729. NSInteger overflow = [currentRead searchForTermAfterPreBuffering:bytesRead];
  3730. if (overflow == 0)
  3731. {
  3732. // Perfect match!
  3733. // Every byte we read stays in the read buffer,
  3734. // and the last byte we read was the last byte of the term.
  3735. currentRead->bytesDone += bytesRead;
  3736. totalBytesReadForCurrentRead += bytesRead;
  3737. done = YES;
  3738. }
  3739. else if (overflow > 0)
  3740. {
  3741. // The term was found within the data that we read,
  3742. // and there are extra bytes that extend past the end of the term.
  3743. // We need to move these excess bytes out of the read packet and into the prebuffer.
  3744. NSInteger underflow = bytesRead - overflow;
  3745. // Copy excess data into preBuffer
  3746. LogVerbose(@"copying %ld overflow bytes into preBuffer", (long)overflow);
  3747. [preBuffer ensureCapacityForWrite:overflow];
  3748. uint8_t *overflowBuffer = buffer + underflow;
  3749. memcpy([preBuffer writeBuffer], overflowBuffer, overflow);
  3750. [preBuffer didWrite:overflow];
  3751. LogVerbose(@"preBuffer.length = %zu", [preBuffer availableBytes]);
  3752. // Note: The completeCurrentRead method will trim the buffer for us.
  3753. currentRead->bytesDone += underflow;
  3754. totalBytesReadForCurrentRead += underflow;
  3755. done = YES;
  3756. }
  3757. else
  3758. {
  3759. // The term was not found within the data that we read.
  3760. currentRead->bytesDone += bytesRead;
  3761. totalBytesReadForCurrentRead += bytesRead;
  3762. done = NO;
  3763. }
  3764. }
  3765. if (!done && currentRead->maxLength > 0)
  3766. {
  3767. // We're not done and there's a set maxLength.
  3768. // Have we reached that maxLength yet?
  3769. if (currentRead->bytesDone >= currentRead->maxLength)
  3770. {
  3771. error = [self readMaxedOutError];
  3772. }
  3773. }
  3774. }
  3775. else
  3776. {
  3777. // Read type #1 - read all available data
  3778. if (readIntoPreBuffer)
  3779. {
  3780. // We just read a chunk of data into the preBuffer
  3781. [preBuffer didWrite:bytesRead];
  3782. // Now copy the data into the read packet.
  3783. //
  3784. // Recall that we didn't read directly into the packet's buffer to avoid
  3785. // over-allocating memory since we had no clue how much data was available to be read.
  3786. //
  3787. // Ensure there's room on the read packet's buffer
  3788. [currentRead ensureCapacityForAdditionalDataOfLength:bytesRead];
  3789. // Copy bytes from prebuffer into read buffer
  3790. uint8_t *readBuf = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset
  3791. + currentRead->bytesDone;
  3792. memcpy(readBuf, [preBuffer readBuffer], bytesRead);
  3793. // Remove the copied bytes from the prebuffer
  3794. [preBuffer didRead:bytesRead];
  3795. // Update totals
  3796. currentRead->bytesDone += bytesRead;
  3797. totalBytesReadForCurrentRead += bytesRead;
  3798. }
  3799. else
  3800. {
  3801. currentRead->bytesDone += bytesRead;
  3802. totalBytesReadForCurrentRead += bytesRead;
  3803. }
  3804. done = YES;
  3805. }
  3806. } // if (bytesRead > 0)
  3807. } // if (!done && !error && !socketEOF && !waiting && hasBytesAvailable)
  3808. if (!done && currentRead->readLength == 0 && currentRead->term == nil)
  3809. {
  3810. // Read type #1 - read all available data
  3811. //
  3812. // We might arrive here if we read data from the prebuffer but not from the socket.
  3813. done = (totalBytesReadForCurrentRead > 0);
  3814. }
  3815. // Check to see if we're done, or if we've made progress
  3816. if (done)
  3817. {
  3818. [self completeCurrentRead];
  3819. if (!error && (!socketEOF || [preBuffer availableBytes] > 0))
  3820. {
  3821. [self maybeDequeueRead];
  3822. }
  3823. }
  3824. else if (totalBytesReadForCurrentRead > 0)
  3825. {
  3826. // We're not done read type #2 or #3 yet, but we have read in some bytes
  3827. if (delegateQueue && [delegate respondsToSelector:@selector(socket:didReadPartialDataOfLength:tag:)])
  3828. {
  3829. __strong id theDelegate = delegate;
  3830. long theReadTag = currentRead->tag;
  3831. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  3832. [theDelegate socket:self didReadPartialDataOfLength:totalBytesReadForCurrentRead tag:theReadTag];
  3833. }});
  3834. }
  3835. }
  3836. // Check for errors
  3837. if (error)
  3838. {
  3839. [self closeWithError:error];
  3840. }
  3841. else if (socketEOF)
  3842. {
  3843. [self doReadEOF];
  3844. }
  3845. else if (waiting)
  3846. {
  3847. if (![self usingCFStreamForTLS])
  3848. {
  3849. // Monitor the socket for readability (if we're not already doing so)
  3850. [self resumeReadSource];
  3851. }
  3852. }
  3853. // Do not add any code here without first adding return statements in the error cases above.
  3854. }
  3855. - (void)doReadEOF
  3856. {
  3857. LogTrace();
  3858. // This method may be called more than once.
  3859. // If the EOF is read while there is still data in the preBuffer,
  3860. // then this method may be called continually after invocations of doReadData to see if it's time to disconnect.
  3861. flags |= kSocketHasReadEOF;
  3862. if (flags & kSocketSecure)
  3863. {
  3864. // If the SSL layer has any buffered data, flush it into the preBuffer now.
  3865. [self flushSSLBuffers];
  3866. }
  3867. BOOL shouldDisconnect;
  3868. NSError *error = nil;
  3869. if ((flags & kStartingReadTLS) || (flags & kStartingWriteTLS))
  3870. {
  3871. // We received an EOF during or prior to startTLS.
  3872. // The SSL/TLS handshake is now impossible, so this is an unrecoverable situation.
  3873. shouldDisconnect = YES;
  3874. if ([self usingSecureTransportForTLS])
  3875. {
  3876. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  3877. error = [self sslError:errSSLClosedAbort];
  3878. #endif
  3879. }
  3880. }
  3881. else if (flags & kReadStreamClosed)
  3882. {
  3883. // The preBuffer has already been drained.
  3884. // The config allows half-duplex connections.
  3885. // We've previously checked the socket, and it appeared writeable.
  3886. // So we marked the read stream as closed and notified the delegate.
  3887. //
  3888. // As per the half-duplex contract, the socket will be closed when a write fails,
  3889. // or when the socket is manually closed.
  3890. shouldDisconnect = NO;
  3891. }
  3892. else if ([preBuffer availableBytes] > 0)
  3893. {
  3894. LogVerbose(@"Socket reached EOF, but there is still data available in prebuffer");
  3895. // Although we won't be able to read any more data from the socket,
  3896. // there is existing data that has been prebuffered that we can read.
  3897. shouldDisconnect = NO;
  3898. }
  3899. else if (config & kAllowHalfDuplexConnection)
  3900. {
  3901. // We just received an EOF (end of file) from the socket's read stream.
  3902. // This means the remote end of the socket (the peer we're connected to)
  3903. // has explicitly stated that it will not be sending us any more data.
  3904. //
  3905. // Query the socket to see if it is still writeable. (Perhaps the peer will continue reading data from us)
  3906. int socketFD = (socket4FD == SOCKET_NULL) ? socket6FD : socket4FD;
  3907. struct pollfd pfd[1];
  3908. pfd[0].fd = socketFD;
  3909. pfd[0].events = POLLOUT;
  3910. pfd[0].revents = 0;
  3911. poll(pfd, 1, 0);
  3912. if (pfd[0].revents & POLLOUT)
  3913. {
  3914. // Socket appears to still be writeable
  3915. shouldDisconnect = NO;
  3916. flags |= kReadStreamClosed;
  3917. // Notify the delegate that we're going half-duplex
  3918. if (delegateQueue && [delegate respondsToSelector:@selector(socketDidCloseReadStream:)])
  3919. {
  3920. __strong id theDelegate = delegate;
  3921. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  3922. [theDelegate socketDidCloseReadStream:self];
  3923. }});
  3924. }
  3925. }
  3926. else
  3927. {
  3928. shouldDisconnect = YES;
  3929. }
  3930. }
  3931. else
  3932. {
  3933. shouldDisconnect = YES;
  3934. }
  3935. if (shouldDisconnect)
  3936. {
  3937. if (error == nil)
  3938. {
  3939. if ([self usingSecureTransportForTLS])
  3940. {
  3941. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  3942. if (sslErrCode != noErr && sslErrCode != errSSLClosedGraceful)
  3943. {
  3944. error = [self sslError:sslErrCode];
  3945. }
  3946. else
  3947. {
  3948. error = [self connectionClosedError];
  3949. }
  3950. #endif
  3951. }
  3952. else
  3953. {
  3954. error = [self connectionClosedError];
  3955. }
  3956. }
  3957. [self closeWithError:error];
  3958. }
  3959. else
  3960. {
  3961. if (![self usingCFStreamForTLS])
  3962. {
  3963. // Suspend the read source (if needed)
  3964. [self suspendReadSource];
  3965. }
  3966. }
  3967. }
  3968. - (void)completeCurrentRead
  3969. {
  3970. LogTrace();
  3971. NSAssert(currentRead, @"Trying to complete current read when there is no current read.");
  3972. NSData *result;
  3973. if (currentRead->bufferOwner)
  3974. {
  3975. // We created the buffer on behalf of the user.
  3976. // Trim our buffer to be the proper size.
  3977. [currentRead->buffer setLength:currentRead->bytesDone];
  3978. result = currentRead->buffer;
  3979. }
  3980. else
  3981. {
  3982. // We did NOT create the buffer.
  3983. // The buffer is owned by the caller.
  3984. // Only trim the buffer if we had to increase its size.
  3985. if ([currentRead->buffer length] > currentRead->originalBufferLength)
  3986. {
  3987. NSUInteger readSize = currentRead->startOffset + currentRead->bytesDone;
  3988. NSUInteger origSize = currentRead->originalBufferLength;
  3989. NSUInteger buffSize = MAX(readSize, origSize);
  3990. [currentRead->buffer setLength:buffSize];
  3991. }
  3992. uint8_t *buffer = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset;
  3993. result = [NSData dataWithBytesNoCopy:buffer length:currentRead->bytesDone freeWhenDone:NO];
  3994. }
  3995. if (delegateQueue && [delegate respondsToSelector:@selector(socket:didReadData:withTag:)])
  3996. {
  3997. __strong id theDelegate = delegate;
  3998. GCDAsyncReadPacket *theRead = currentRead; // Ensure currentRead retained since result may not own buffer
  3999. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4000. [theDelegate socket:self didReadData:result withTag:theRead->tag];
  4001. }});
  4002. }
  4003. [self endCurrentRead];
  4004. }
  4005. - (void)endCurrentRead
  4006. {
  4007. if (readTimer)
  4008. {
  4009. dispatch_source_cancel(readTimer);
  4010. readTimer = NULL;
  4011. }
  4012. currentRead = nil;
  4013. }
  4014. - (void)setupReadTimerWithTimeout:(NSTimeInterval)timeout
  4015. {
  4016. if (timeout >= 0.0)
  4017. {
  4018. readTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, socketQueue);
  4019. dispatch_source_set_event_handler(readTimer, ^{ @autoreleasepool {
  4020. [self doReadTimeout];
  4021. }});
  4022. #if NEEDS_DISPATCH_RETAIN_RELEASE
  4023. dispatch_source_t theReadTimer = readTimer;
  4024. dispatch_source_set_cancel_handler(readTimer, ^{
  4025. LogVerbose(@"dispatch_release(readTimer)");
  4026. dispatch_release(theReadTimer);
  4027. });
  4028. #endif
  4029. dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeout * NSEC_PER_SEC));
  4030. dispatch_source_set_timer(readTimer, tt, DISPATCH_TIME_FOREVER, 0);
  4031. dispatch_resume(readTimer);
  4032. }
  4033. }
  4034. - (void)doReadTimeout
  4035. {
  4036. // This is a little bit tricky.
  4037. // Ideally we'd like to synchronously query the delegate about a timeout extension.
  4038. // But if we do so synchronously we risk a possible deadlock.
  4039. // So instead we have to do so asynchronously, and callback to ourselves from within the delegate block.
  4040. flags |= kReadsPaused;
  4041. if (delegateQueue && [delegate respondsToSelector:@selector(socket:shouldTimeoutReadWithTag:elapsed:bytesDone:)])
  4042. {
  4043. __strong id theDelegate = delegate;
  4044. GCDAsyncReadPacket *theRead = currentRead;
  4045. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4046. NSTimeInterval timeoutExtension = 0.0;
  4047. timeoutExtension = [theDelegate socket:self shouldTimeoutReadWithTag:theRead->tag
  4048. elapsed:theRead->timeout
  4049. bytesDone:theRead->bytesDone];
  4050. dispatch_async(socketQueue, ^{ @autoreleasepool {
  4051. [self doReadTimeoutWithExtension:timeoutExtension];
  4052. }});
  4053. }});
  4054. }
  4055. else
  4056. {
  4057. [self doReadTimeoutWithExtension:0.0];
  4058. }
  4059. }
  4060. - (void)doReadTimeoutWithExtension:(NSTimeInterval)timeoutExtension
  4061. {
  4062. if (currentRead)
  4063. {
  4064. if (timeoutExtension > 0.0)
  4065. {
  4066. currentRead->timeout += timeoutExtension;
  4067. // Reschedule the timer
  4068. dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeoutExtension * NSEC_PER_SEC));
  4069. dispatch_source_set_timer(readTimer, tt, DISPATCH_TIME_FOREVER, 0);
  4070. // Unpause reads, and continue
  4071. flags &= ~kReadsPaused;
  4072. [self doReadData];
  4073. }
  4074. else
  4075. {
  4076. LogVerbose(@"ReadTimeout");
  4077. [self closeWithError:[self readTimeoutError]];
  4078. }
  4079. }
  4080. }
  4081. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4082. #pragma mark Writing
  4083. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4084. - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
  4085. {
  4086. if ([data length] == 0) return;
  4087. GCDAsyncWritePacket *packet = [[GCDAsyncWritePacket alloc] initWithData:data timeout:timeout tag:tag];
  4088. dispatch_async(socketQueue, ^{ @autoreleasepool {
  4089. LogTrace();
  4090. if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
  4091. {
  4092. [writeQueue addObject:packet];
  4093. [self maybeDequeueWrite];
  4094. }
  4095. }});
  4096. // Do not rely on the block being run in order to release the packet,
  4097. // as the queue might get released without the block completing.
  4098. }
  4099. - (float)progressOfWriteReturningTag:(long *)tagPtr bytesDone:(NSUInteger *)donePtr total:(NSUInteger *)totalPtr
  4100. {
  4101. __block float result = 0.0F;
  4102. dispatch_block_t block = ^{
  4103. if (!currentWrite || ![currentWrite isKindOfClass:[GCDAsyncWritePacket class]])
  4104. {
  4105. // We're not writing anything right now.
  4106. if (tagPtr != NULL) *tagPtr = 0;
  4107. if (donePtr != NULL) *donePtr = 0;
  4108. if (totalPtr != NULL) *totalPtr = 0;
  4109. result = NAN;
  4110. }
  4111. else
  4112. {
  4113. NSUInteger done = currentWrite->bytesDone;
  4114. NSUInteger total = [currentWrite->buffer length];
  4115. if (tagPtr != NULL) *tagPtr = currentWrite->tag;
  4116. if (donePtr != NULL) *donePtr = done;
  4117. if (totalPtr != NULL) *totalPtr = total;
  4118. result = (float)done / (float)total;
  4119. }
  4120. };
  4121. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  4122. block();
  4123. else
  4124. dispatch_sync(socketQueue, block);
  4125. return result;
  4126. }
  4127. /**
  4128. * Conditionally starts a new write.
  4129. *
  4130. * It is called when:
  4131. * - a user requests a write
  4132. * - after a write request has finished (to handle the next request)
  4133. * - immediately after the socket opens to handle any pending requests
  4134. *
  4135. * This method also handles auto-disconnect post read/write completion.
  4136. **/
  4137. - (void)maybeDequeueWrite
  4138. {
  4139. LogTrace();
  4140. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  4141. // If we're not currently processing a write AND we have an available write stream
  4142. if ((currentWrite == nil) && (flags & kConnected))
  4143. {
  4144. if ([writeQueue count] > 0)
  4145. {
  4146. // Dequeue the next object in the write queue
  4147. currentWrite = [writeQueue objectAtIndex:0];
  4148. [writeQueue removeObjectAtIndex:0];
  4149. if ([currentWrite isKindOfClass:[GCDAsyncSpecialPacket class]])
  4150. {
  4151. LogVerbose(@"Dequeued GCDAsyncSpecialPacket");
  4152. // Attempt to start TLS
  4153. flags |= kStartingWriteTLS;
  4154. // This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set
  4155. [self maybeStartTLS];
  4156. }
  4157. else
  4158. {
  4159. LogVerbose(@"Dequeued GCDAsyncWritePacket");
  4160. // Setup write timer (if needed)
  4161. [self setupWriteTimerWithTimeout:currentWrite->timeout];
  4162. // Immediately write, if possible
  4163. [self doWriteData];
  4164. }
  4165. }
  4166. else if (flags & kDisconnectAfterWrites)
  4167. {
  4168. if (flags & kDisconnectAfterReads)
  4169. {
  4170. if (([readQueue count] == 0) && (currentRead == nil))
  4171. {
  4172. [self closeWithError:nil];
  4173. }
  4174. }
  4175. else
  4176. {
  4177. [self closeWithError:nil];
  4178. }
  4179. }
  4180. }
  4181. }
  4182. - (void)doWriteData
  4183. {
  4184. LogTrace();
  4185. // This method is called by the writeSource via the socketQueue
  4186. if ((currentWrite == nil) || (flags & kWritesPaused))
  4187. {
  4188. LogVerbose(@"No currentWrite or kWritesPaused");
  4189. // Unable to write at this time
  4190. if ([self usingCFStreamForTLS])
  4191. {
  4192. // CFWriteStream only fires once when there is available data.
  4193. // It won't fire again until we've invoked CFWriteStreamWrite.
  4194. }
  4195. else
  4196. {
  4197. // If the writeSource is firing, we need to pause it
  4198. // or else it will continue to fire over and over again.
  4199. if (flags & kSocketCanAcceptBytes)
  4200. {
  4201. [self suspendWriteSource];
  4202. }
  4203. }
  4204. return;
  4205. }
  4206. if (!(flags & kSocketCanAcceptBytes))
  4207. {
  4208. LogVerbose(@"No space available to write...");
  4209. // No space available to write.
  4210. if (![self usingCFStreamForTLS])
  4211. {
  4212. // Need to wait for writeSource to fire and notify us of
  4213. // available space in the socket's internal write buffer.
  4214. [self resumeWriteSource];
  4215. }
  4216. return;
  4217. }
  4218. if (flags & kStartingWriteTLS)
  4219. {
  4220. LogVerbose(@"Waiting for SSL/TLS handshake to complete");
  4221. // The writeQueue is waiting for SSL/TLS handshake to complete.
  4222. if (flags & kStartingReadTLS)
  4223. {
  4224. if ([self usingSecureTransportForTLS])
  4225. {
  4226. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  4227. // We are in the process of a SSL Handshake.
  4228. // We were waiting for available space in the socket's internal OS buffer to continue writing.
  4229. [self ssl_continueSSLHandshake];
  4230. #endif
  4231. }
  4232. }
  4233. else
  4234. {
  4235. // We are still waiting for the readQueue to drain and start the SSL/TLS process.
  4236. // We now know we can write to the socket.
  4237. if (![self usingCFStreamForTLS])
  4238. {
  4239. // Suspend the write source or else it will continue to fire nonstop.
  4240. [self suspendWriteSource];
  4241. }
  4242. }
  4243. return;
  4244. }
  4245. // Note: This method is not called if currentWrite is a GCDAsyncSpecialPacket (startTLS packet)
  4246. BOOL waiting = NO;
  4247. NSError *error = nil;
  4248. size_t bytesWritten = 0;
  4249. if (flags & kSocketSecure)
  4250. {
  4251. if ([self usingCFStreamForTLS])
  4252. {
  4253. #if TARGET_OS_IPHONE
  4254. //
  4255. // Writing data using CFStream (over internal TLS)
  4256. //
  4257. const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes] + currentWrite->bytesDone;
  4258. NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone;
  4259. if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3)
  4260. {
  4261. bytesToWrite = SIZE_MAX;
  4262. }
  4263. CFIndex result = CFWriteStreamWrite(writeStream, buffer, (CFIndex)bytesToWrite);
  4264. LogVerbose(@"CFWriteStreamWrite(%lu) = %li", (unsigned long)bytesToWrite, result);
  4265. if (result < 0)
  4266. {
  4267. error = (__bridge_transfer NSError *)CFWriteStreamCopyError(writeStream);
  4268. }
  4269. else
  4270. {
  4271. bytesWritten = (size_t)result;
  4272. // We always set waiting to true in this scenario.
  4273. // CFStream may have altered our underlying socket to non-blocking.
  4274. // Thus if we attempt to write without a callback, we may end up blocking our queue.
  4275. waiting = YES;
  4276. }
  4277. #endif
  4278. }
  4279. else
  4280. {
  4281. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  4282. // We're going to use the SSLWrite function.
  4283. //
  4284. // OSStatus SSLWrite(SSLContextRef context, const void *data, size_t dataLength, size_t *processed)
  4285. //
  4286. // Parameters:
  4287. // context - An SSL session context reference.
  4288. // data - A pointer to the buffer of data to write.
  4289. // dataLength - The amount, in bytes, of data to write.
  4290. // processed - On return, the length, in bytes, of the data actually written.
  4291. //
  4292. // It sounds pretty straight-forward,
  4293. // but there are a few caveats you should be aware of.
  4294. //
  4295. // The SSLWrite method operates in a non-obvious (and rather annoying) manner.
  4296. // According to the documentation:
  4297. //
  4298. // Because you may configure the underlying connection to operate in a non-blocking manner,
  4299. // a write operation might return errSSLWouldBlock, indicating that less data than requested
  4300. // was actually transferred. In this case, you should repeat the call to SSLWrite until some
  4301. // other result is returned.
  4302. //
  4303. // This sounds perfect, but when our SSLWriteFunction returns errSSLWouldBlock,
  4304. // then the SSLWrite method returns (with the proper errSSLWouldBlock return value),
  4305. // but it sets processed to dataLength !!
  4306. //
  4307. // In other words, if the SSLWrite function doesn't completely write all the data we tell it to,
  4308. // then it doesn't tell us how many bytes were actually written. So, for example, if we tell it to
  4309. // write 256 bytes then it might actually write 128 bytes, but then report 0 bytes written.
  4310. //
  4311. // You might be wondering:
  4312. // If the SSLWrite function doesn't tell us how many bytes were written,
  4313. // then how in the world are we supposed to update our parameters (buffer & bytesToWrite)
  4314. // for the next time we invoke SSLWrite?
  4315. //
  4316. // The answer is that SSLWrite cached all the data we told it to write,
  4317. // and it will push out that data next time we call SSLWrite.
  4318. // If we call SSLWrite with new data, it will push out the cached data first, and then the new data.
  4319. // If we call SSLWrite with empty data, then it will simply push out the cached data.
  4320. //
  4321. // For this purpose we're going to break large writes into a series of smaller writes.
  4322. // This allows us to report progress back to the delegate.
  4323. OSStatus result;
  4324. BOOL hasCachedDataToWrite = (sslWriteCachedLength > 0);
  4325. BOOL hasNewDataToWrite = YES;
  4326. if (hasCachedDataToWrite)
  4327. {
  4328. size_t processed = 0;
  4329. result = SSLWrite(sslContext, NULL, 0, &processed);
  4330. if (result == noErr)
  4331. {
  4332. bytesWritten = sslWriteCachedLength;
  4333. sslWriteCachedLength = 0;
  4334. if ([currentWrite->buffer length] == (currentWrite->bytesDone + bytesWritten))
  4335. {
  4336. // We've written all data for the current write.
  4337. hasNewDataToWrite = NO;
  4338. }
  4339. }
  4340. else
  4341. {
  4342. if (result == errSSLWouldBlock)
  4343. {
  4344. waiting = YES;
  4345. }
  4346. else
  4347. {
  4348. error = [self sslError:result];
  4349. }
  4350. // Can't write any new data since we were unable to write the cached data.
  4351. hasNewDataToWrite = NO;
  4352. }
  4353. }
  4354. if (hasNewDataToWrite)
  4355. {
  4356. const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes]
  4357. + currentWrite->bytesDone
  4358. + bytesWritten;
  4359. NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone - bytesWritten;
  4360. if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3)
  4361. {
  4362. bytesToWrite = SIZE_MAX;
  4363. }
  4364. size_t bytesRemaining = bytesToWrite;
  4365. BOOL keepLooping = YES;
  4366. while (keepLooping)
  4367. {
  4368. size_t sslBytesToWrite = MIN(bytesRemaining, 32768);
  4369. size_t sslBytesWritten = 0;
  4370. result = SSLWrite(sslContext, buffer, sslBytesToWrite, &sslBytesWritten);
  4371. if (result == noErr)
  4372. {
  4373. buffer += sslBytesWritten;
  4374. bytesWritten += sslBytesWritten;
  4375. bytesRemaining -= sslBytesWritten;
  4376. keepLooping = (bytesRemaining > 0);
  4377. }
  4378. else
  4379. {
  4380. if (result == errSSLWouldBlock)
  4381. {
  4382. waiting = YES;
  4383. sslWriteCachedLength = sslBytesToWrite;
  4384. }
  4385. else
  4386. {
  4387. error = [self sslError:result];
  4388. }
  4389. keepLooping = NO;
  4390. }
  4391. } // while (keepLooping)
  4392. } // if (hasNewDataToWrite)
  4393. #endif
  4394. }
  4395. }
  4396. else
  4397. {
  4398. //
  4399. // Writing data directly over raw socket
  4400. //
  4401. int socketFD = (socket4FD == SOCKET_NULL) ? socket6FD : socket4FD;
  4402. const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes] + currentWrite->bytesDone;
  4403. NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone;
  4404. if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3)
  4405. {
  4406. bytesToWrite = SIZE_MAX;
  4407. }
  4408. ssize_t result = write(socketFD, buffer, (size_t)bytesToWrite);
  4409. LogVerbose(@"wrote to socket = %zd", result);
  4410. // Check results
  4411. if (result < 0)
  4412. {
  4413. if (errno == EWOULDBLOCK)
  4414. {
  4415. waiting = YES;
  4416. }
  4417. else
  4418. {
  4419. error = [self errnoErrorWithReason:@"Error in write() function"];
  4420. }
  4421. }
  4422. else
  4423. {
  4424. bytesWritten = result;
  4425. }
  4426. }
  4427. // We're done with our writing.
  4428. // If we explictly ran into a situation where the socket told us there was no room in the buffer,
  4429. // then we immediately resume listening for notifications.
  4430. //
  4431. // We must do this before we dequeue another write,
  4432. // as that may in turn invoke this method again.
  4433. //
  4434. // Note that if CFStream is involved, it may have maliciously put our socket in blocking mode.
  4435. if (waiting)
  4436. {
  4437. flags &= ~kSocketCanAcceptBytes;
  4438. if (![self usingCFStreamForTLS])
  4439. {
  4440. [self resumeWriteSource];
  4441. }
  4442. }
  4443. // Check our results
  4444. BOOL done = NO;
  4445. if (bytesWritten > 0)
  4446. {
  4447. // Update total amount read for the current write
  4448. currentWrite->bytesDone += bytesWritten;
  4449. LogVerbose(@"currentWrite->bytesDone = %lu", (unsigned long)currentWrite->bytesDone);
  4450. // Is packet done?
  4451. done = (currentWrite->bytesDone == [currentWrite->buffer length]);
  4452. }
  4453. if (done)
  4454. {
  4455. [self completeCurrentWrite];
  4456. if (!error)
  4457. {
  4458. [self maybeDequeueWrite];
  4459. }
  4460. }
  4461. else
  4462. {
  4463. // We were unable to finish writing the data,
  4464. // so we're waiting for another callback to notify us of available space in the lower-level output buffer.
  4465. if (!waiting & !error)
  4466. {
  4467. // This would be the case if our write was able to accept some data, but not all of it.
  4468. flags &= ~kSocketCanAcceptBytes;
  4469. if (![self usingCFStreamForTLS])
  4470. {
  4471. [self resumeWriteSource];
  4472. }
  4473. }
  4474. if (bytesWritten > 0)
  4475. {
  4476. // We're not done with the entire write, but we have written some bytes
  4477. if (delegateQueue && [delegate respondsToSelector:@selector(socket:didWritePartialDataOfLength:tag:)])
  4478. {
  4479. __strong id theDelegate = delegate;
  4480. long theWriteTag = currentWrite->tag;
  4481. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4482. [theDelegate socket:self didWritePartialDataOfLength:bytesWritten tag:theWriteTag];
  4483. }});
  4484. }
  4485. }
  4486. }
  4487. // Check for errors
  4488. if (error)
  4489. {
  4490. [self closeWithError:[self errnoErrorWithReason:@"Error in write() function"]];
  4491. }
  4492. // Do not add any code here without first adding a return statement in the error case above.
  4493. }
  4494. - (void)completeCurrentWrite
  4495. {
  4496. LogTrace();
  4497. NSAssert(currentWrite, @"Trying to complete current write when there is no current write.");
  4498. if (delegateQueue && [delegate respondsToSelector:@selector(socket:didWriteDataWithTag:)])
  4499. {
  4500. __strong id theDelegate = delegate;
  4501. long theWriteTag = currentWrite->tag;
  4502. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4503. [theDelegate socket:self didWriteDataWithTag:theWriteTag];
  4504. }});
  4505. }
  4506. [self endCurrentWrite];
  4507. }
  4508. - (void)endCurrentWrite
  4509. {
  4510. if (writeTimer)
  4511. {
  4512. dispatch_source_cancel(writeTimer);
  4513. writeTimer = NULL;
  4514. }
  4515. currentWrite = nil;
  4516. }
  4517. - (void)setupWriteTimerWithTimeout:(NSTimeInterval)timeout
  4518. {
  4519. if (timeout >= 0.0)
  4520. {
  4521. writeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, socketQueue);
  4522. dispatch_source_set_event_handler(writeTimer, ^{ @autoreleasepool {
  4523. [self doWriteTimeout];
  4524. }});
  4525. #if NEEDS_DISPATCH_RETAIN_RELEASE
  4526. dispatch_source_t theWriteTimer = writeTimer;
  4527. dispatch_source_set_cancel_handler(writeTimer, ^{
  4528. LogVerbose(@"dispatch_release(writeTimer)");
  4529. dispatch_release(theWriteTimer);
  4530. });
  4531. #endif
  4532. dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeout * NSEC_PER_SEC));
  4533. dispatch_source_set_timer(writeTimer, tt, DISPATCH_TIME_FOREVER, 0);
  4534. dispatch_resume(writeTimer);
  4535. }
  4536. }
  4537. - (void)doWriteTimeout
  4538. {
  4539. // This is a little bit tricky.
  4540. // Ideally we'd like to synchronously query the delegate about a timeout extension.
  4541. // But if we do so synchronously we risk a possible deadlock.
  4542. // So instead we have to do so asynchronously, and callback to ourselves from within the delegate block.
  4543. flags |= kWritesPaused;
  4544. if (delegateQueue && [delegate respondsToSelector:@selector(socket:shouldTimeoutWriteWithTag:elapsed:bytesDone:)])
  4545. {
  4546. __strong id theDelegate = delegate;
  4547. GCDAsyncWritePacket *theWrite = currentWrite;
  4548. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4549. NSTimeInterval timeoutExtension = 0.0;
  4550. timeoutExtension = [theDelegate socket:self shouldTimeoutWriteWithTag:theWrite->tag
  4551. elapsed:theWrite->timeout
  4552. bytesDone:theWrite->bytesDone];
  4553. dispatch_async(socketQueue, ^{ @autoreleasepool {
  4554. [self doWriteTimeoutWithExtension:timeoutExtension];
  4555. }});
  4556. }});
  4557. }
  4558. else
  4559. {
  4560. [self doWriteTimeoutWithExtension:0.0];
  4561. }
  4562. }
  4563. - (void)doWriteTimeoutWithExtension:(NSTimeInterval)timeoutExtension
  4564. {
  4565. if (currentWrite)
  4566. {
  4567. if (timeoutExtension > 0.0)
  4568. {
  4569. currentWrite->timeout += timeoutExtension;
  4570. // Reschedule the timer
  4571. dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeoutExtension * NSEC_PER_SEC));
  4572. dispatch_source_set_timer(writeTimer, tt, DISPATCH_TIME_FOREVER, 0);
  4573. // Unpause writes, and continue
  4574. flags &= ~kWritesPaused;
  4575. [self doWriteData];
  4576. }
  4577. else
  4578. {
  4579. LogVerbose(@"WriteTimeout");
  4580. [self closeWithError:[self writeTimeoutError]];
  4581. }
  4582. }
  4583. }
  4584. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4585. #pragma mark Security
  4586. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4587. - (void)startTLS:(NSDictionary *)tlsSettings
  4588. {
  4589. LogTrace();
  4590. if (tlsSettings == nil)
  4591. {
  4592. // Passing nil/NULL to CFReadStreamSetProperty will appear to work the same as passing an empty dictionary,
  4593. // but causes problems if we later try to fetch the remote host's certificate.
  4594. //
  4595. // To be exact, it causes the following to return NULL instead of the normal result:
  4596. // CFReadStreamCopyProperty(readStream, kCFStreamPropertySSLPeerCertificates)
  4597. //
  4598. // So we use an empty dictionary instead, which works perfectly.
  4599. tlsSettings = [NSDictionary dictionary];
  4600. }
  4601. GCDAsyncSpecialPacket *packet = [[GCDAsyncSpecialPacket alloc] initWithTLSSettings:tlsSettings];
  4602. dispatch_async(socketQueue, ^{ @autoreleasepool {
  4603. if ((flags & kSocketStarted) && !(flags & kQueuedTLS) && !(flags & kForbidReadsWrites))
  4604. {
  4605. [readQueue addObject:packet];
  4606. [writeQueue addObject:packet];
  4607. flags |= kQueuedTLS;
  4608. [self maybeDequeueRead];
  4609. [self maybeDequeueWrite];
  4610. }
  4611. }});
  4612. }
  4613. - (void)maybeStartTLS
  4614. {
  4615. // We can't start TLS until:
  4616. // - All queued reads prior to the user calling startTLS are complete
  4617. // - All queued writes prior to the user calling startTLS are complete
  4618. //
  4619. // We'll know these conditions are met when both kStartingReadTLS and kStartingWriteTLS are set
  4620. if ((flags & kStartingReadTLS) && (flags & kStartingWriteTLS))
  4621. {
  4622. BOOL canUseSecureTransport = YES;
  4623. #if TARGET_OS_IPHONE
  4624. {
  4625. GCDAsyncSpecialPacket *tlsPacket = (GCDAsyncSpecialPacket *)currentRead;
  4626. NSDictionary *tlsSettings = tlsPacket->tlsSettings;
  4627. NSNumber *value;
  4628. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
  4629. if (value && [value boolValue] == YES)
  4630. canUseSecureTransport = NO;
  4631. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsExpiredRoots];
  4632. if (value && [value boolValue] == YES)
  4633. canUseSecureTransport = NO;
  4634. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLValidatesCertificateChain];
  4635. if (value && [value boolValue] == NO)
  4636. canUseSecureTransport = NO;
  4637. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates];
  4638. if (value && [value boolValue] == YES)
  4639. canUseSecureTransport = NO;
  4640. }
  4641. #endif
  4642. if (IS_SECURE_TRANSPORT_AVAILABLE && canUseSecureTransport)
  4643. {
  4644. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  4645. [self ssl_startTLS];
  4646. #endif
  4647. }
  4648. else
  4649. {
  4650. #if TARGET_OS_IPHONE
  4651. [self cf_startTLS];
  4652. #endif
  4653. }
  4654. }
  4655. }
  4656. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4657. #pragma mark Security via SecureTransport
  4658. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4659. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  4660. - (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength
  4661. {
  4662. LogVerbose(@"sslReadWithBuffer:%p length:%lu", buffer, (unsigned long)*bufferLength);
  4663. if ((socketFDBytesAvailable == 0) && ([sslPreBuffer availableBytes] == 0))
  4664. {
  4665. LogVerbose(@"%@ - No data available to read...", THIS_METHOD);
  4666. // No data available to read.
  4667. //
  4668. // Need to wait for readSource to fire and notify us of
  4669. // available data in the socket's internal read buffer.
  4670. [self resumeReadSource];
  4671. *bufferLength = 0;
  4672. return errSSLWouldBlock;
  4673. }
  4674. size_t totalBytesRead = 0;
  4675. size_t totalBytesLeftToBeRead = *bufferLength;
  4676. BOOL done = NO;
  4677. BOOL socketError = NO;
  4678. //
  4679. // STEP 1 : READ FROM SSL PRE BUFFER
  4680. //
  4681. size_t sslPreBufferLength = [sslPreBuffer availableBytes];
  4682. if (sslPreBufferLength > 0)
  4683. {
  4684. LogVerbose(@"%@: Reading from SSL pre buffer...", THIS_METHOD);
  4685. size_t bytesToCopy;
  4686. if (sslPreBufferLength > totalBytesLeftToBeRead)
  4687. bytesToCopy = totalBytesLeftToBeRead;
  4688. else
  4689. bytesToCopy = sslPreBufferLength;
  4690. LogVerbose(@"%@: Copying %zu bytes from sslPreBuffer", THIS_METHOD, bytesToCopy);
  4691. memcpy(buffer, [sslPreBuffer readBuffer], bytesToCopy);
  4692. [sslPreBuffer didRead:bytesToCopy];
  4693. LogVerbose(@"%@: sslPreBuffer.length = %zu", THIS_METHOD, [sslPreBuffer availableBytes]);
  4694. totalBytesRead += bytesToCopy;
  4695. totalBytesLeftToBeRead -= bytesToCopy;
  4696. done = (totalBytesLeftToBeRead == 0);
  4697. if (done) LogVerbose(@"%@: Complete", THIS_METHOD);
  4698. }
  4699. //
  4700. // STEP 2 : READ FROM SOCKET
  4701. //
  4702. if (!done && (socketFDBytesAvailable > 0))
  4703. {
  4704. LogVerbose(@"%@: Reading from socket...", THIS_METHOD);
  4705. int socketFD = (socket6FD == SOCKET_NULL) ? socket4FD : socket6FD;
  4706. BOOL readIntoPreBuffer;
  4707. size_t bytesToRead;
  4708. uint8_t *buf;
  4709. if (socketFDBytesAvailable > totalBytesLeftToBeRead)
  4710. {
  4711. // Read all available data from socket into sslPreBuffer.
  4712. // Then copy requested amount into dataBuffer.
  4713. LogVerbose(@"%@: Reading into sslPreBuffer...", THIS_METHOD);
  4714. [sslPreBuffer ensureCapacityForWrite:socketFDBytesAvailable];
  4715. readIntoPreBuffer = YES;
  4716. bytesToRead = (size_t)socketFDBytesAvailable;
  4717. buf = [sslPreBuffer writeBuffer];
  4718. }
  4719. else
  4720. {
  4721. // Read available data from socket directly into dataBuffer.
  4722. LogVerbose(@"%@: Reading directly into dataBuffer...", THIS_METHOD);
  4723. readIntoPreBuffer = NO;
  4724. bytesToRead = totalBytesLeftToBeRead;
  4725. buf = (uint8_t *)buffer + totalBytesRead;
  4726. }
  4727. ssize_t result = read(socketFD, buf, bytesToRead);
  4728. LogVerbose(@"%@: read from socket = %zd", THIS_METHOD, result);
  4729. if (result < 0)
  4730. {
  4731. LogVerbose(@"%@: read errno = %i", THIS_METHOD, errno);
  4732. if (errno != EWOULDBLOCK)
  4733. {
  4734. socketError = YES;
  4735. }
  4736. socketFDBytesAvailable = 0;
  4737. }
  4738. else if (result == 0)
  4739. {
  4740. LogVerbose(@"%@: read EOF", THIS_METHOD);
  4741. socketError = YES;
  4742. socketFDBytesAvailable = 0;
  4743. }
  4744. else
  4745. {
  4746. size_t bytesReadFromSocket = result;
  4747. if (socketFDBytesAvailable > bytesReadFromSocket)
  4748. socketFDBytesAvailable -= bytesReadFromSocket;
  4749. else
  4750. socketFDBytesAvailable = 0;
  4751. if (readIntoPreBuffer)
  4752. {
  4753. [sslPreBuffer didWrite:bytesReadFromSocket];
  4754. size_t bytesToCopy = MIN(totalBytesLeftToBeRead, bytesReadFromSocket);
  4755. LogVerbose(@"%@: Copying %zu bytes out of sslPreBuffer", THIS_METHOD, bytesToCopy);
  4756. memcpy((uint8_t *)buffer + totalBytesRead, [sslPreBuffer readBuffer], bytesToCopy);
  4757. [sslPreBuffer didRead:bytesToCopy];
  4758. totalBytesRead += bytesToCopy;
  4759. totalBytesLeftToBeRead -= bytesToCopy;
  4760. LogVerbose(@"%@: sslPreBuffer.length = %zu", THIS_METHOD, [sslPreBuffer availableBytes]);
  4761. }
  4762. else
  4763. {
  4764. totalBytesRead += bytesReadFromSocket;
  4765. totalBytesLeftToBeRead -= bytesReadFromSocket;
  4766. }
  4767. done = (totalBytesLeftToBeRead == 0);
  4768. if (done) LogVerbose(@"%@: Complete", THIS_METHOD);
  4769. }
  4770. }
  4771. *bufferLength = totalBytesRead;
  4772. if (done)
  4773. return noErr;
  4774. if (socketError)
  4775. return errSSLClosedAbort;
  4776. return errSSLWouldBlock;
  4777. }
  4778. - (OSStatus)sslWriteWithBuffer:(const void *)buffer length:(size_t *)bufferLength
  4779. {
  4780. if (!(flags & kSocketCanAcceptBytes))
  4781. {
  4782. // Unable to write.
  4783. //
  4784. // Need to wait for writeSource to fire and notify us of
  4785. // available space in the socket's internal write buffer.
  4786. [self resumeWriteSource];
  4787. *bufferLength = 0;
  4788. return errSSLWouldBlock;
  4789. }
  4790. size_t bytesToWrite = *bufferLength;
  4791. size_t bytesWritten = 0;
  4792. BOOL done = NO;
  4793. BOOL socketError = NO;
  4794. int socketFD = (socket4FD == SOCKET_NULL) ? socket6FD : socket4FD;
  4795. ssize_t result = write(socketFD, buffer, bytesToWrite);
  4796. if (result < 0)
  4797. {
  4798. if (errno != EWOULDBLOCK)
  4799. {
  4800. socketError = YES;
  4801. }
  4802. flags &= ~kSocketCanAcceptBytes;
  4803. }
  4804. else if (result == 0)
  4805. {
  4806. flags &= ~kSocketCanAcceptBytes;
  4807. }
  4808. else
  4809. {
  4810. bytesWritten = result;
  4811. done = (bytesWritten == bytesToWrite);
  4812. }
  4813. *bufferLength = bytesWritten;
  4814. if (done)
  4815. return noErr;
  4816. if (socketError)
  4817. return errSSLClosedAbort;
  4818. return errSSLWouldBlock;
  4819. }
  4820. static OSStatus SSLReadFunction(SSLConnectionRef connection, void *data, size_t *dataLength)
  4821. {
  4822. GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)connection;
  4823. NSCAssert(dispatch_get_specific(asyncSocket->IsOnSocketQueueOrTargetQueueKey), @"What the deuce?");
  4824. return [asyncSocket sslReadWithBuffer:data length:dataLength];
  4825. }
  4826. static OSStatus SSLWriteFunction(SSLConnectionRef connection, const void *data, size_t *dataLength)
  4827. {
  4828. GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)connection;
  4829. NSCAssert(dispatch_get_specific(asyncSocket->IsOnSocketQueueOrTargetQueueKey), @"What the deuce?");
  4830. return [asyncSocket sslWriteWithBuffer:data length:dataLength];
  4831. }
  4832. - (void)ssl_startTLS
  4833. {
  4834. LogTrace();
  4835. LogVerbose(@"Starting TLS (via SecureTransport)...");
  4836. OSStatus status;
  4837. GCDAsyncSpecialPacket *tlsPacket = (GCDAsyncSpecialPacket *)currentRead;
  4838. NSDictionary *tlsSettings = tlsPacket->tlsSettings;
  4839. // Create SSLContext, and setup IO callbacks and connection ref
  4840. BOOL isServer = [[tlsSettings objectForKey:(NSString *)kCFStreamSSLIsServer] boolValue];
  4841. #if TARGET_OS_IPHONE
  4842. {
  4843. if (isServer)
  4844. sslContext = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
  4845. else
  4846. sslContext = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
  4847. if (sslContext == NULL)
  4848. {
  4849. [self closeWithError:[self otherError:@"Error in SSLCreateContext"]];
  4850. return;
  4851. }
  4852. }
  4853. #else
  4854. {
  4855. status = SSLNewContext(isServer, &sslContext);
  4856. if (status != noErr)
  4857. {
  4858. [self closeWithError:[self otherError:@"Error in SSLNewContext"]];
  4859. return;
  4860. }
  4861. }
  4862. #endif
  4863. status = SSLSetIOFuncs(sslContext, &SSLReadFunction, &SSLWriteFunction);
  4864. if (status != noErr)
  4865. {
  4866. [self closeWithError:[self otherError:@"Error in SSLSetIOFuncs"]];
  4867. return;
  4868. }
  4869. status = SSLSetConnection(sslContext, (__bridge SSLConnectionRef)self);
  4870. if (status != noErr)
  4871. {
  4872. [self closeWithError:[self otherError:@"Error in SSLSetConnection"]];
  4873. return;
  4874. }
  4875. // Configure SSLContext from given settings
  4876. //
  4877. // Checklist:
  4878. // 1. kCFStreamSSLPeerName
  4879. // 2. kCFStreamSSLAllowsAnyRoot
  4880. // 3. kCFStreamSSLAllowsExpiredRoots
  4881. // 4. kCFStreamSSLValidatesCertificateChain
  4882. // 5. kCFStreamSSLAllowsExpiredCertificates
  4883. // 6. kCFStreamSSLCertificates
  4884. // 7. kCFStreamSSLLevel (GCDAsyncSocketSSLProtocolVersionMin / GCDAsyncSocketSSLProtocolVersionMax)
  4885. // 8. GCDAsyncSocketSSLCipherSuites
  4886. // 9. GCDAsyncSocketSSLDiffieHellmanParameters (Mac)
  4887. id value;
  4888. // 1. kCFStreamSSLPeerName
  4889. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLPeerName];
  4890. if ([value isKindOfClass:[NSString class]])
  4891. {
  4892. NSString *peerName = (NSString *)value;
  4893. const char *peer = [peerName UTF8String];
  4894. size_t peerLen = strlen(peer);
  4895. status = SSLSetPeerDomainName(sslContext, peer, peerLen);
  4896. if (status != noErr)
  4897. {
  4898. [self closeWithError:[self otherError:@"Error in SSLSetPeerDomainName"]];
  4899. return;
  4900. }
  4901. }
  4902. // 2. kCFStreamSSLAllowsAnyRoot
  4903. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
  4904. if (value)
  4905. {
  4906. #if TARGET_OS_IPHONE
  4907. NSAssert(NO, @"Security option unavailable via SecureTransport in iOS - kCFStreamSSLAllowsAnyRoot");
  4908. #else
  4909. BOOL allowsAnyRoot = [value boolValue];
  4910. status = SSLSetAllowsAnyRoot(sslContext, allowsAnyRoot);
  4911. if (status != noErr)
  4912. {
  4913. [self closeWithError:[self otherError:@"Error in SSLSetAllowsAnyRoot"]];
  4914. return;
  4915. }
  4916. #endif
  4917. }
  4918. // 3. kCFStreamSSLAllowsExpiredRoots
  4919. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsExpiredRoots];
  4920. if (value)
  4921. {
  4922. #if TARGET_OS_IPHONE
  4923. NSAssert(NO, @"Security option unavailable via SecureTransport in iOS - kCFStreamSSLAllowsExpiredRoots");
  4924. #else
  4925. BOOL allowsExpiredRoots = [value boolValue];
  4926. status = SSLSetAllowsExpiredRoots(sslContext, allowsExpiredRoots);
  4927. if (status != noErr)
  4928. {
  4929. [self closeWithError:[self otherError:@"Error in SSLSetAllowsExpiredRoots"]];
  4930. return;
  4931. }
  4932. #endif
  4933. }
  4934. // 4. kCFStreamSSLValidatesCertificateChain
  4935. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLValidatesCertificateChain];
  4936. if (value)
  4937. {
  4938. #if TARGET_OS_IPHONE
  4939. NSAssert(NO, @"Security option unavailable via SecureTransport in iOS - kCFStreamSSLValidatesCertificateChain");
  4940. #else
  4941. BOOL validatesCertChain = [value boolValue];
  4942. status = SSLSetEnableCertVerify(sslContext, validatesCertChain);
  4943. if (status != noErr)
  4944. {
  4945. [self closeWithError:[self otherError:@"Error in SSLSetEnableCertVerify"]];
  4946. return;
  4947. }
  4948. #endif
  4949. }
  4950. // 5. kCFStreamSSLAllowsExpiredCertificates
  4951. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates];
  4952. if (value)
  4953. {
  4954. #if TARGET_OS_IPHONE
  4955. NSAssert(NO, @"Security option unavailable via SecureTransport in iOS - kCFStreamSSLAllowsExpiredCertificates");
  4956. #else
  4957. BOOL allowsExpiredCerts = [value boolValue];
  4958. status = SSLSetAllowsExpiredCerts(sslContext, allowsExpiredCerts);
  4959. if (status != noErr)
  4960. {
  4961. [self closeWithError:[self otherError:@"Error in SSLSetAllowsExpiredCerts"]];
  4962. return;
  4963. }
  4964. #endif
  4965. }
  4966. // 6. kCFStreamSSLCertificates
  4967. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLCertificates];
  4968. if (value)
  4969. {
  4970. CFArrayRef certs = (__bridge CFArrayRef)value;
  4971. status = SSLSetCertificate(sslContext, certs);
  4972. if (status != noErr)
  4973. {
  4974. [self closeWithError:[self otherError:@"Error in SSLSetCertificate"]];
  4975. return;
  4976. }
  4977. }
  4978. // 7. kCFStreamSSLLevel
  4979. #if TARGET_OS_IPHONE
  4980. {
  4981. NSString *sslLevel = [tlsSettings objectForKey:(NSString *)kCFStreamSSLLevel];
  4982. NSString *sslMinLevel = [tlsSettings objectForKey:GCDAsyncSocketSSLProtocolVersionMin];
  4983. NSString *sslMaxLevel = [tlsSettings objectForKey:GCDAsyncSocketSSLProtocolVersionMax];
  4984. if (sslLevel)
  4985. {
  4986. if (sslMinLevel || sslMaxLevel)
  4987. {
  4988. LogWarn(@"kCFStreamSSLLevel security option ignored. Overriden by "
  4989. @"GCDAsyncSocketSSLProtocolVersionMin and/or GCDAsyncSocketSSLProtocolVersionMax");
  4990. }
  4991. else
  4992. {
  4993. if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelSSLv3])
  4994. {
  4995. sslMinLevel = sslMaxLevel = @"kSSLProtocol3";
  4996. }
  4997. else if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelTLSv1])
  4998. {
  4999. sslMinLevel = sslMaxLevel = @"kTLSProtocol1";
  5000. }
  5001. else
  5002. {
  5003. LogWarn(@"Unable to match kCFStreamSSLLevel security option to valid SSL protocol min/max");
  5004. }
  5005. }
  5006. }
  5007. if (sslMinLevel || sslMaxLevel)
  5008. {
  5009. OSStatus status1 = noErr;
  5010. OSStatus status2 = noErr;
  5011. SSLProtocol (^sslProtocolForString)(NSString*) = ^SSLProtocol (NSString *protocolStr) {
  5012. if ([protocolStr isEqualToString:@"kSSLProtocol3"]) return kSSLProtocol3;
  5013. if ([protocolStr isEqualToString:@"kTLSProtocol1"]) return kTLSProtocol1;
  5014. if ([protocolStr isEqualToString:@"kTLSProtocol11"]) return kTLSProtocol11;
  5015. if ([protocolStr isEqualToString:@"kTLSProtocol12"]) return kTLSProtocol12;
  5016. return kSSLProtocolUnknown;
  5017. };
  5018. SSLProtocol minProtocol = sslProtocolForString(sslMinLevel);
  5019. SSLProtocol maxProtocol = sslProtocolForString(sslMaxLevel);
  5020. if (minProtocol != kSSLProtocolUnknown)
  5021. {
  5022. status1 = SSLSetProtocolVersionMin(sslContext, minProtocol);
  5023. }
  5024. if (maxProtocol != kSSLProtocolUnknown)
  5025. {
  5026. status2 = SSLSetProtocolVersionMax(sslContext, maxProtocol);
  5027. }
  5028. if (status1 != noErr || status2 != noErr)
  5029. {
  5030. [self closeWithError:[self otherError:@"Error in SSLSetProtocolVersionMinMax"]];
  5031. return;
  5032. }
  5033. }
  5034. }
  5035. #else
  5036. {
  5037. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLLevel];
  5038. if (value)
  5039. {
  5040. NSString *sslLevel = (NSString *)value;
  5041. OSStatus status1 = noErr;
  5042. OSStatus status2 = noErr;
  5043. OSStatus status3 = noErr;
  5044. if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelSSLv2])
  5045. {
  5046. // kCFStreamSocketSecurityLevelSSLv2:
  5047. //
  5048. // Specifies that SSL version 2 be set as the security protocol.
  5049. status1 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocolAll, NO);
  5050. status2 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocol2, YES);
  5051. }
  5052. else if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelSSLv3])
  5053. {
  5054. // kCFStreamSocketSecurityLevelSSLv3:
  5055. //
  5056. // Specifies that SSL version 3 be set as the security protocol.
  5057. // If SSL version 3 is not available, specifies that SSL version 2 be set as the security protocol.
  5058. status1 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocolAll, NO);
  5059. status2 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocol2, YES);
  5060. status3 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocol3, YES);
  5061. }
  5062. else if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelTLSv1])
  5063. {
  5064. // kCFStreamSocketSecurityLevelTLSv1:
  5065. //
  5066. // Specifies that TLS version 1 be set as the security protocol.
  5067. status1 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocolAll, NO);
  5068. status2 = SSLSetProtocolVersionEnabled(sslContext, kTLSProtocol1, YES);
  5069. }
  5070. else if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL])
  5071. {
  5072. // kCFStreamSocketSecurityLevelNegotiatedSSL:
  5073. //
  5074. // Specifies that the highest level security protocol that can be negotiated be used.
  5075. status1 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocolAll, YES);
  5076. }
  5077. if (status1 != noErr || status2 != noErr || status3 != noErr)
  5078. {
  5079. [self closeWithError:[self otherError:@"Error in SSLSetProtocolVersionEnabled"]];
  5080. return;
  5081. }
  5082. }
  5083. }
  5084. #endif
  5085. // 8. GCDAsyncSocketSSLCipherSuites
  5086. value = [tlsSettings objectForKey:GCDAsyncSocketSSLCipherSuites];
  5087. if (value)
  5088. {
  5089. NSArray *cipherSuites = (NSArray *)value;
  5090. NSUInteger numberCiphers = [cipherSuites count];
  5091. SSLCipherSuite ciphers[numberCiphers];
  5092. NSUInteger cipherIndex;
  5093. for (cipherIndex = 0; cipherIndex < numberCiphers; cipherIndex++)
  5094. {
  5095. NSNumber *cipherObject = [cipherSuites objectAtIndex:cipherIndex];
  5096. ciphers[cipherIndex] = [cipherObject shortValue];
  5097. }
  5098. status = SSLSetEnabledCiphers(sslContext, ciphers, numberCiphers);
  5099. if (status != noErr)
  5100. {
  5101. [self closeWithError:[self otherError:@"Error in SSLSetEnabledCiphers"]];
  5102. return;
  5103. }
  5104. }
  5105. // 9. GCDAsyncSocketSSLDiffieHellmanParameters
  5106. #if !TARGET_OS_IPHONE
  5107. value = [tlsSettings objectForKey:GCDAsyncSocketSSLDiffieHellmanParameters];
  5108. if (value)
  5109. {
  5110. NSData *diffieHellmanData = (NSData *)value;
  5111. status = SSLSetDiffieHellmanParams(sslContext, [diffieHellmanData bytes], [diffieHellmanData length]);
  5112. if (status != noErr)
  5113. {
  5114. [self closeWithError:[self otherError:@"Error in SSLSetDiffieHellmanParams"]];
  5115. return;
  5116. }
  5117. }
  5118. #endif
  5119. // Setup the sslPreBuffer
  5120. //
  5121. // Any data in the preBuffer needs to be moved into the sslPreBuffer,
  5122. // as this data is now part of the secure read stream.
  5123. sslPreBuffer = [[GCDAsyncSocketPreBuffer alloc] initWithCapacity:(1024 * 4)];
  5124. size_t preBufferLength = [preBuffer availableBytes];
  5125. if (preBufferLength > 0)
  5126. {
  5127. [sslPreBuffer ensureCapacityForWrite:preBufferLength];
  5128. memcpy([sslPreBuffer writeBuffer], [preBuffer readBuffer], preBufferLength);
  5129. [preBuffer didRead:preBufferLength];
  5130. [sslPreBuffer didWrite:preBufferLength];
  5131. }
  5132. sslErrCode = noErr;
  5133. // Start the SSL Handshake process
  5134. [self ssl_continueSSLHandshake];
  5135. }
  5136. - (void)ssl_continueSSLHandshake
  5137. {
  5138. LogTrace();
  5139. // If the return value is noErr, the session is ready for normal secure communication.
  5140. // If the return value is errSSLWouldBlock, the SSLHandshake function must be called again.
  5141. // Otherwise, the return value indicates an error code.
  5142. OSStatus status = SSLHandshake(sslContext);
  5143. if (status == noErr)
  5144. {
  5145. LogVerbose(@"SSLHandshake complete");
  5146. flags &= ~kStartingReadTLS;
  5147. flags &= ~kStartingWriteTLS;
  5148. flags |= kSocketSecure;
  5149. if (delegateQueue && [delegate respondsToSelector:@selector(socketDidSecure:)])
  5150. {
  5151. __strong id theDelegate = delegate;
  5152. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  5153. [theDelegate socketDidSecure:self];
  5154. }});
  5155. }
  5156. [self endCurrentRead];
  5157. [self endCurrentWrite];
  5158. [self maybeDequeueRead];
  5159. [self maybeDequeueWrite];
  5160. }
  5161. else if (status == errSSLWouldBlock)
  5162. {
  5163. LogVerbose(@"SSLHandshake continues...");
  5164. // Handshake continues...
  5165. //
  5166. // This method will be called again from doReadData or doWriteData.
  5167. }
  5168. else
  5169. {
  5170. [self closeWithError:[self sslError:status]];
  5171. }
  5172. }
  5173. #endif
  5174. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5175. #pragma mark Security via CFStream
  5176. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5177. #if TARGET_OS_IPHONE
  5178. - (void)cf_finishSSLHandshake
  5179. {
  5180. LogTrace();
  5181. if ((flags & kStartingReadTLS) && (flags & kStartingWriteTLS))
  5182. {
  5183. flags &= ~kStartingReadTLS;
  5184. flags &= ~kStartingWriteTLS;
  5185. flags |= kSocketSecure;
  5186. if (delegateQueue && [delegate respondsToSelector:@selector(socketDidSecure:)])
  5187. {
  5188. __strong id theDelegate = delegate;
  5189. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  5190. [theDelegate socketDidSecure:self];
  5191. }});
  5192. }
  5193. [self endCurrentRead];
  5194. [self endCurrentWrite];
  5195. [self maybeDequeueRead];
  5196. [self maybeDequeueWrite];
  5197. }
  5198. }
  5199. - (void)cf_abortSSLHandshake:(NSError *)error
  5200. {
  5201. LogTrace();
  5202. if ((flags & kStartingReadTLS) && (flags & kStartingWriteTLS))
  5203. {
  5204. flags &= ~kStartingReadTLS;
  5205. flags &= ~kStartingWriteTLS;
  5206. [self closeWithError:error];
  5207. }
  5208. }
  5209. - (void)cf_startTLS
  5210. {
  5211. LogTrace();
  5212. LogVerbose(@"Starting TLS (via CFStream)...");
  5213. if ([preBuffer availableBytes] > 0)
  5214. {
  5215. NSString *msg = @"Invalid TLS transition. Handshake has already been read from socket.";
  5216. [self closeWithError:[self otherError:msg]];
  5217. return;
  5218. }
  5219. [self suspendReadSource];
  5220. [self suspendWriteSource];
  5221. socketFDBytesAvailable = 0;
  5222. flags &= ~kSocketCanAcceptBytes;
  5223. flags &= ~kSecureSocketHasBytesAvailable;
  5224. flags |= kUsingCFStreamForTLS;
  5225. if (![self createReadAndWriteStream])
  5226. {
  5227. [self closeWithError:[self otherError:@"Error in CFStreamCreatePairWithSocket"]];
  5228. return;
  5229. }
  5230. if (![self registerForStreamCallbacksIncludingReadWrite:YES])
  5231. {
  5232. [self closeWithError:[self otherError:@"Error in CFStreamSetClient"]];
  5233. return;
  5234. }
  5235. if (![self addStreamsToRunLoop])
  5236. {
  5237. [self closeWithError:[self otherError:@"Error in CFStreamScheduleWithRunLoop"]];
  5238. return;
  5239. }
  5240. NSAssert([currentRead isKindOfClass:[GCDAsyncSpecialPacket class]], @"Invalid read packet for startTLS");
  5241. NSAssert([currentWrite isKindOfClass:[GCDAsyncSpecialPacket class]], @"Invalid write packet for startTLS");
  5242. GCDAsyncSpecialPacket *tlsPacket = (GCDAsyncSpecialPacket *)currentRead;
  5243. CFDictionaryRef tlsSettings = (__bridge CFDictionaryRef)tlsPacket->tlsSettings;
  5244. // Getting an error concerning kCFStreamPropertySSLSettings ?
  5245. // You need to add the CFNetwork framework to your iOS application.
  5246. BOOL r1 = CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, tlsSettings);
  5247. BOOL r2 = CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, tlsSettings);
  5248. // For some reason, starting around the time of iOS 4.3,
  5249. // the first call to set the kCFStreamPropertySSLSettings will return true,
  5250. // but the second will return false.
  5251. //
  5252. // Order doesn't seem to matter.
  5253. // So you could call CFReadStreamSetProperty and then CFWriteStreamSetProperty, or you could reverse the order.
  5254. // Either way, the first call will return true, and the second returns false.
  5255. //
  5256. // Interestingly, this doesn't seem to affect anything.
  5257. // Which is not altogether unusual, as the documentation seems to suggest that (for many settings)
  5258. // setting it on one side of the stream automatically sets it for the other side of the stream.
  5259. //
  5260. // Although there isn't anything in the documentation to suggest that the second attempt would fail.
  5261. //
  5262. // Furthermore, this only seems to affect streams that are negotiating a security upgrade.
  5263. // In other words, the socket gets connected, there is some back-and-forth communication over the unsecure
  5264. // connection, and then a startTLS is issued.
  5265. // So this mostly affects newer protocols (XMPP, IMAP) as opposed to older protocols (HTTPS).
  5266. if (!r1 && !r2) // Yes, the && is correct - workaround for apple bug.
  5267. {
  5268. [self closeWithError:[self otherError:@"Error in CFStreamSetProperty"]];
  5269. return;
  5270. }
  5271. if (![self openStreams])
  5272. {
  5273. [self closeWithError:[self otherError:@"Error in CFStreamOpen"]];
  5274. return;
  5275. }
  5276. LogVerbose(@"Waiting for SSL Handshake to complete...");
  5277. }
  5278. #endif
  5279. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5280. #pragma mark CFStream
  5281. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5282. #if TARGET_OS_IPHONE
  5283. + (void)startCFStreamThreadIfNeeded
  5284. {
  5285. static dispatch_once_t predicate;
  5286. dispatch_once(&predicate, ^{
  5287. cfstreamThread = [[NSThread alloc] initWithTarget:self
  5288. selector:@selector(cfstreamThread)
  5289. object:nil];
  5290. [cfstreamThread start];
  5291. });
  5292. }
  5293. + (void)cfstreamThread { @autoreleasepool
  5294. {
  5295. [[NSThread currentThread] setName:GCDAsyncSocketThreadName];
  5296. LogInfo(@"CFStreamThread: Started");
  5297. // We can't run the run loop unless it has an associated input source or a timer.
  5298. // So we'll just create a timer that will never fire - unless the server runs for decades.
  5299. [NSTimer scheduledTimerWithTimeInterval:[[NSDate distantFuture] timeIntervalSinceNow]
  5300. target:self
  5301. selector:@selector(doNothingAtAll:)
  5302. userInfo:nil
  5303. repeats:YES];
  5304. [[NSRunLoop currentRunLoop] run];
  5305. LogInfo(@"CFStreamThread: Stopped");
  5306. }}
  5307. - (void)doNothingAtAll:(NSTimer *)timer
  5308. {
  5309. }
  5310. + (void)scheduleCFStreams:(GCDAsyncSocket *)asyncSocket
  5311. {
  5312. LogTrace();
  5313. NSAssert([NSThread currentThread] == cfstreamThread, @"Invoked on wrong thread");
  5314. CFRunLoopRef runLoop = CFRunLoopGetCurrent();
  5315. if (asyncSocket->readStream)
  5316. CFReadStreamScheduleWithRunLoop(asyncSocket->readStream, runLoop, kCFRunLoopDefaultMode);
  5317. if (asyncSocket->writeStream)
  5318. CFWriteStreamScheduleWithRunLoop(asyncSocket->writeStream, runLoop, kCFRunLoopDefaultMode);
  5319. }
  5320. + (void)unscheduleCFStreams:(GCDAsyncSocket *)asyncSocket
  5321. {
  5322. LogTrace();
  5323. NSAssert([NSThread currentThread] == cfstreamThread, @"Invoked on wrong thread");
  5324. CFRunLoopRef runLoop = CFRunLoopGetCurrent();
  5325. if (asyncSocket->readStream)
  5326. CFReadStreamUnscheduleFromRunLoop(asyncSocket->readStream, runLoop, kCFRunLoopDefaultMode);
  5327. if (asyncSocket->writeStream)
  5328. CFWriteStreamUnscheduleFromRunLoop(asyncSocket->writeStream, runLoop, kCFRunLoopDefaultMode);
  5329. }
  5330. static void CFReadStreamCallback (CFReadStreamRef stream, CFStreamEventType type, void *pInfo)
  5331. {
  5332. GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)pInfo;
  5333. switch(type)
  5334. {
  5335. case kCFStreamEventHasBytesAvailable:
  5336. {
  5337. dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool {
  5338. LogVerbose(@"CFReadStreamCallback - HasBytesAvailable");
  5339. if (asyncSocket->readStream != stream)
  5340. return_from_block;
  5341. if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS))
  5342. {
  5343. // If we set kCFStreamPropertySSLSettings before we opened the streams, this might be a lie.
  5344. // (A callback related to the tcp stream, but not to the SSL layer).
  5345. if (CFReadStreamHasBytesAvailable(asyncSocket->readStream))
  5346. {
  5347. asyncSocket->flags |= kSecureSocketHasBytesAvailable;
  5348. [asyncSocket cf_finishSSLHandshake];
  5349. }
  5350. }
  5351. else
  5352. {
  5353. asyncSocket->flags |= kSecureSocketHasBytesAvailable;
  5354. [asyncSocket doReadData];
  5355. }
  5356. }});
  5357. break;
  5358. }
  5359. default:
  5360. {
  5361. NSError *error = (__bridge_transfer NSError *)CFReadStreamCopyError(stream);
  5362. if (error == nil && type == kCFStreamEventEndEncountered)
  5363. {
  5364. error = [asyncSocket connectionClosedError];
  5365. }
  5366. dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool {
  5367. LogVerbose(@"CFReadStreamCallback - Other");
  5368. if (asyncSocket->readStream != stream)
  5369. return_from_block;
  5370. if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS))
  5371. {
  5372. [asyncSocket cf_abortSSLHandshake:error];
  5373. }
  5374. else
  5375. {
  5376. [asyncSocket closeWithError:error];
  5377. }
  5378. }});
  5379. break;
  5380. }
  5381. }
  5382. }
  5383. static void CFWriteStreamCallback (CFWriteStreamRef stream, CFStreamEventType type, void *pInfo)
  5384. {
  5385. GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)pInfo;
  5386. switch(type)
  5387. {
  5388. case kCFStreamEventCanAcceptBytes:
  5389. {
  5390. dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool {
  5391. LogVerbose(@"CFWriteStreamCallback - CanAcceptBytes");
  5392. if (asyncSocket->writeStream != stream)
  5393. return_from_block;
  5394. if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS))
  5395. {
  5396. // If we set kCFStreamPropertySSLSettings before we opened the streams, this might be a lie.
  5397. // (A callback related to the tcp stream, but not to the SSL layer).
  5398. if (CFWriteStreamCanAcceptBytes(asyncSocket->writeStream))
  5399. {
  5400. asyncSocket->flags |= kSocketCanAcceptBytes;
  5401. [asyncSocket cf_finishSSLHandshake];
  5402. }
  5403. }
  5404. else
  5405. {
  5406. asyncSocket->flags |= kSocketCanAcceptBytes;
  5407. [asyncSocket doWriteData];
  5408. }
  5409. }});
  5410. break;
  5411. }
  5412. default:
  5413. {
  5414. NSError *error = (__bridge_transfer NSError *)CFWriteStreamCopyError(stream);
  5415. if (error == nil && type == kCFStreamEventEndEncountered)
  5416. {
  5417. error = [asyncSocket connectionClosedError];
  5418. }
  5419. dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool {
  5420. LogVerbose(@"CFWriteStreamCallback - Other");
  5421. if (asyncSocket->writeStream != stream)
  5422. return_from_block;
  5423. if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS))
  5424. {
  5425. [asyncSocket cf_abortSSLHandshake:error];
  5426. }
  5427. else
  5428. {
  5429. [asyncSocket closeWithError:error];
  5430. }
  5431. }});
  5432. break;
  5433. }
  5434. }
  5435. }
  5436. - (BOOL)createReadAndWriteStream
  5437. {
  5438. LogTrace();
  5439. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  5440. if (readStream || writeStream)
  5441. {
  5442. // Streams already created
  5443. return YES;
  5444. }
  5445. int socketFD = (socket6FD == SOCKET_NULL) ? socket4FD : socket6FD;
  5446. if (socketFD == SOCKET_NULL)
  5447. {
  5448. // Cannot create streams without a file descriptor
  5449. return NO;
  5450. }
  5451. if (![self isConnected])
  5452. {
  5453. // Cannot create streams until file descriptor is connected
  5454. return NO;
  5455. }
  5456. LogVerbose(@"Creating read and write stream...");
  5457. CFStreamCreatePairWithSocket(NULL, (CFSocketNativeHandle)socketFD, &readStream, &writeStream);
  5458. // The kCFStreamPropertyShouldCloseNativeSocket property should be false by default (for our case).
  5459. // But let's not take any chances.
  5460. if (readStream)
  5461. CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse);
  5462. if (writeStream)
  5463. CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse);
  5464. if ((readStream == NULL) || (writeStream == NULL))
  5465. {
  5466. LogWarn(@"Unable to create read and write stream...");
  5467. if (readStream)
  5468. {
  5469. CFReadStreamClose(readStream);
  5470. CFRelease(readStream);
  5471. readStream = NULL;
  5472. }
  5473. if (writeStream)
  5474. {
  5475. CFWriteStreamClose(writeStream);
  5476. CFRelease(writeStream);
  5477. writeStream = NULL;
  5478. }
  5479. return NO;
  5480. }
  5481. return YES;
  5482. }
  5483. - (BOOL)registerForStreamCallbacksIncludingReadWrite:(BOOL)includeReadWrite
  5484. {
  5485. LogVerbose(@"%@ %@", THIS_METHOD, (includeReadWrite ? @"YES" : @"NO"));
  5486. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  5487. NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null");
  5488. streamContext.version = 0;
  5489. streamContext.info = (__bridge void *)(self);
  5490. streamContext.retain = nil;
  5491. streamContext.release = nil;
  5492. streamContext.copyDescription = nil;
  5493. CFOptionFlags readStreamEvents = kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
  5494. if (includeReadWrite)
  5495. readStreamEvents |= kCFStreamEventHasBytesAvailable;
  5496. if (!CFReadStreamSetClient(readStream, readStreamEvents, &CFReadStreamCallback, &streamContext))
  5497. {
  5498. return NO;
  5499. }
  5500. CFOptionFlags writeStreamEvents = kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
  5501. if (includeReadWrite)
  5502. writeStreamEvents |= kCFStreamEventCanAcceptBytes;
  5503. if (!CFWriteStreamSetClient(writeStream, writeStreamEvents, &CFWriteStreamCallback, &streamContext))
  5504. {
  5505. return NO;
  5506. }
  5507. return YES;
  5508. }
  5509. - (BOOL)addStreamsToRunLoop
  5510. {
  5511. LogTrace();
  5512. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  5513. NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null");
  5514. if (!(flags & kAddedStreamsToRunLoop))
  5515. {
  5516. LogVerbose(@"Adding streams to runloop...");
  5517. [[self class] startCFStreamThreadIfNeeded];
  5518. [[self class] performSelector:@selector(scheduleCFStreams:)
  5519. onThread:cfstreamThread
  5520. withObject:self
  5521. waitUntilDone:YES];
  5522. flags |= kAddedStreamsToRunLoop;
  5523. }
  5524. return YES;
  5525. }
  5526. - (void)removeStreamsFromRunLoop
  5527. {
  5528. LogTrace();
  5529. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  5530. NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null");
  5531. if (flags & kAddedStreamsToRunLoop)
  5532. {
  5533. LogVerbose(@"Removing streams from runloop...");
  5534. [[self class] performSelector:@selector(unscheduleCFStreams:)
  5535. onThread:cfstreamThread
  5536. withObject:self
  5537. waitUntilDone:YES];
  5538. flags &= ~kAddedStreamsToRunLoop;
  5539. }
  5540. }
  5541. - (BOOL)openStreams
  5542. {
  5543. LogTrace();
  5544. NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
  5545. NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null");
  5546. CFStreamStatus readStatus = CFReadStreamGetStatus(readStream);
  5547. CFStreamStatus writeStatus = CFWriteStreamGetStatus(writeStream);
  5548. if ((readStatus == kCFStreamStatusNotOpen) || (writeStatus == kCFStreamStatusNotOpen))
  5549. {
  5550. LogVerbose(@"Opening read and write stream...");
  5551. BOOL r1 = CFReadStreamOpen(readStream);
  5552. BOOL r2 = CFWriteStreamOpen(writeStream);
  5553. if (!r1 || !r2)
  5554. {
  5555. LogError(@"Error in CFStreamOpen");
  5556. return NO;
  5557. }
  5558. }
  5559. return YES;
  5560. }
  5561. #endif
  5562. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5563. #pragma mark Advanced
  5564. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5565. /**
  5566. * See header file for big discussion of this method.
  5567. **/
  5568. - (BOOL)autoDisconnectOnClosedReadStream
  5569. {
  5570. // Note: YES means kAllowHalfDuplexConnection is OFF
  5571. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5572. {
  5573. return ((config & kAllowHalfDuplexConnection) == 0);
  5574. }
  5575. else
  5576. {
  5577. __block BOOL result;
  5578. dispatch_sync(socketQueue, ^{
  5579. result = ((config & kAllowHalfDuplexConnection) == 0);
  5580. });
  5581. return result;
  5582. }
  5583. }
  5584. /**
  5585. * See header file for big discussion of this method.
  5586. **/
  5587. - (void)setAutoDisconnectOnClosedReadStream:(BOOL)flag
  5588. {
  5589. // Note: YES means kAllowHalfDuplexConnection is OFF
  5590. dispatch_block_t block = ^{
  5591. if (flag)
  5592. config &= ~kAllowHalfDuplexConnection;
  5593. else
  5594. config |= kAllowHalfDuplexConnection;
  5595. };
  5596. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5597. block();
  5598. else
  5599. dispatch_async(socketQueue, block);
  5600. }
  5601. /**
  5602. * See header file for big discussion of this method.
  5603. **/
  5604. - (void)markSocketQueueTargetQueue:(dispatch_queue_t)socketNewTargetQueue
  5605. {
  5606. void *nonNullUnusedPointer = (__bridge void *)self;
  5607. dispatch_queue_set_specific(socketNewTargetQueue, IsOnSocketQueueOrTargetQueueKey, nonNullUnusedPointer, NULL);
  5608. }
  5609. /**
  5610. * See header file for big discussion of this method.
  5611. **/
  5612. - (void)unmarkSocketQueueTargetQueue:(dispatch_queue_t)socketOldTargetQueue
  5613. {
  5614. dispatch_queue_set_specific(socketOldTargetQueue, IsOnSocketQueueOrTargetQueueKey, NULL, NULL);
  5615. }
  5616. /**
  5617. * See header file for big discussion of this method.
  5618. **/
  5619. - (void)performBlock:(dispatch_block_t)block
  5620. {
  5621. if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5622. block();
  5623. else
  5624. dispatch_sync(socketQueue, block);
  5625. }
  5626. /**
  5627. * Questions? Have you read the header file?
  5628. **/
  5629. - (int)socketFD
  5630. {
  5631. if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5632. {
  5633. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5634. return SOCKET_NULL;
  5635. }
  5636. if (socket4FD != SOCKET_NULL)
  5637. return socket4FD;
  5638. else
  5639. return socket6FD;
  5640. }
  5641. /**
  5642. * Questions? Have you read the header file?
  5643. **/
  5644. - (int)socket4FD
  5645. {
  5646. if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5647. {
  5648. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5649. return SOCKET_NULL;
  5650. }
  5651. return socket4FD;
  5652. }
  5653. /**
  5654. * Questions? Have you read the header file?
  5655. **/
  5656. - (int)socket6FD
  5657. {
  5658. if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5659. {
  5660. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5661. return SOCKET_NULL;
  5662. }
  5663. return socket6FD;
  5664. }
  5665. #if TARGET_OS_IPHONE
  5666. /**
  5667. * Questions? Have you read the header file?
  5668. **/
  5669. - (CFReadStreamRef)readStream
  5670. {
  5671. if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5672. {
  5673. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5674. return NULL;
  5675. }
  5676. if (readStream == NULL)
  5677. [self createReadAndWriteStream];
  5678. return readStream;
  5679. }
  5680. /**
  5681. * Questions? Have you read the header file?
  5682. **/
  5683. - (CFWriteStreamRef)writeStream
  5684. {
  5685. if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5686. {
  5687. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5688. return NULL;
  5689. }
  5690. if (writeStream == NULL)
  5691. [self createReadAndWriteStream];
  5692. return writeStream;
  5693. }
  5694. - (BOOL)enableBackgroundingOnSocketWithCaveat:(BOOL)caveat
  5695. {
  5696. if (![self createReadAndWriteStream])
  5697. {
  5698. // Error occured creating streams (perhaps socket isn't open)
  5699. return NO;
  5700. }
  5701. BOOL r1, r2;
  5702. LogVerbose(@"Enabling backgrouding on socket");
  5703. r1 = CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  5704. r2 = CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  5705. if (!r1 || !r2)
  5706. {
  5707. return NO;
  5708. }
  5709. if (!caveat)
  5710. {
  5711. if (![self openStreams])
  5712. {
  5713. return NO;
  5714. }
  5715. }
  5716. return YES;
  5717. }
  5718. /**
  5719. * Questions? Have you read the header file?
  5720. **/
  5721. - (BOOL)enableBackgroundingOnSocket
  5722. {
  5723. LogTrace();
  5724. if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5725. {
  5726. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5727. return NO;
  5728. }
  5729. return [self enableBackgroundingOnSocketWithCaveat:NO];
  5730. }
  5731. - (BOOL)enableBackgroundingOnSocketWithCaveat // Deprecated in iOS 4.???
  5732. {
  5733. // This method was created as a workaround for a bug in iOS.
  5734. // Apple has since fixed this bug.
  5735. // I'm not entirely sure which version of iOS they fixed it in...
  5736. LogTrace();
  5737. if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5738. {
  5739. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5740. return NO;
  5741. }
  5742. return [self enableBackgroundingOnSocketWithCaveat:YES];
  5743. }
  5744. #endif
  5745. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  5746. - (SSLContextRef)sslContext
  5747. {
  5748. if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
  5749. {
  5750. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5751. return NULL;
  5752. }
  5753. return sslContext;
  5754. }
  5755. #endif
  5756. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5757. #pragma mark Class Methods
  5758. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5759. + (NSString *)hostFromSockaddr4:(const struct sockaddr_in *)pSockaddr4
  5760. {
  5761. char addrBuf[INET_ADDRSTRLEN];
  5762. if (inet_ntop(AF_INET, &pSockaddr4->sin_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL)
  5763. {
  5764. addrBuf[0] = '\0';
  5765. }
  5766. return [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding];
  5767. }
  5768. + (NSString *)hostFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6
  5769. {
  5770. char addrBuf[INET6_ADDRSTRLEN];
  5771. if (inet_ntop(AF_INET6, &pSockaddr6->sin6_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL)
  5772. {
  5773. addrBuf[0] = '\0';
  5774. }
  5775. return [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding];
  5776. }
  5777. + (uint16_t)portFromSockaddr4:(const struct sockaddr_in *)pSockaddr4
  5778. {
  5779. return ntohs(pSockaddr4->sin_port);
  5780. }
  5781. + (uint16_t)portFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6
  5782. {
  5783. return ntohs(pSockaddr6->sin6_port);
  5784. }
  5785. + (NSString *)hostFromAddress:(NSData *)address
  5786. {
  5787. NSString *host;
  5788. if ([self getHost:&host port:NULL fromAddress:address])
  5789. return host;
  5790. else
  5791. return nil;
  5792. }
  5793. + (uint16_t)portFromAddress:(NSData *)address
  5794. {
  5795. uint16_t port;
  5796. if ([self getHost:NULL port:&port fromAddress:address])
  5797. return port;
  5798. else
  5799. return 0;
  5800. }
  5801. + (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr fromAddress:(NSData *)address
  5802. {
  5803. if ([address length] >= sizeof(struct sockaddr))
  5804. {
  5805. const struct sockaddr *sockaddrX = [address bytes];
  5806. if (sockaddrX->sa_family == AF_INET)
  5807. {
  5808. if ([address length] >= sizeof(struct sockaddr_in))
  5809. {
  5810. struct sockaddr_in sockaddr4;
  5811. memcpy(&sockaddr4, sockaddrX, sizeof(sockaddr4));
  5812. if (hostPtr) *hostPtr = [self hostFromSockaddr4:&sockaddr4];
  5813. if (portPtr) *portPtr = [self portFromSockaddr4:&sockaddr4];
  5814. return YES;
  5815. }
  5816. }
  5817. else if (sockaddrX->sa_family == AF_INET6)
  5818. {
  5819. if ([address length] >= sizeof(struct sockaddr_in6))
  5820. {
  5821. struct sockaddr_in6 sockaddr6;
  5822. memcpy(&sockaddr6, sockaddrX, sizeof(sockaddr6));
  5823. if (hostPtr) *hostPtr = [self hostFromSockaddr6:&sockaddr6];
  5824. if (portPtr) *portPtr = [self portFromSockaddr6:&sockaddr6];
  5825. return YES;
  5826. }
  5827. }
  5828. }
  5829. return NO;
  5830. }
  5831. + (NSData *)CRLFData
  5832. {
  5833. return [NSData dataWithBytes:"\x0D\x0A" length:2];
  5834. }
  5835. + (NSData *)CRData
  5836. {
  5837. return [NSData dataWithBytes:"\x0D" length:1];
  5838. }
  5839. + (NSData *)LFData
  5840. {
  5841. return [NSData dataWithBytes:"\x0A" length:1];
  5842. }
  5843. + (NSData *)ZeroData
  5844. {
  5845. return [NSData dataWithBytes:"" length:1];
  5846. }
  5847. @end