AsyncSocket.m 104 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613
  1. //
  2. // AsyncSocket.m
  3. //
  4. // This class is in the public domain.
  5. // Originally created by Dustin Voss on Wed Jan 29 2003.
  6. // Updated and maintained by Deusty Designs and the Mac development community.
  7. //
  8. // http://code.google.com/p/cocoaasyncsocket/
  9. //
  10. #import "AsyncSocket.h"
  11. #import <sys/socket.h>
  12. #import <netinet/in.h>
  13. #import <arpa/inet.h>
  14. #import <netdb.h>
  15. #if TARGET_OS_IPHONE
  16. // Note: You may need to add the CFNetwork Framework to your project
  17. #import <CFNetwork/CFNetwork.h>
  18. #endif
  19. #pragma mark Declarations
  20. #define DEFAULT_PREBUFFERING YES // Whether pre-buffering is enabled by default
  21. #define READQUEUE_CAPACITY 5 // Initial capacity
  22. #define WRITEQUEUE_CAPACITY 5 // Initial capacity
  23. #define READALL_CHUNKSIZE 256 // Incremental increase in buffer size
  24. #define WRITE_CHUNKSIZE (1024 * 4) // Limit on size of each write pass
  25. NSString *const AsyncSocketException = @"AsyncSocketException";
  26. NSString *const AsyncSocketErrorDomain = @"AsyncSocketErrorDomain";
  27. #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  28. // Mutex lock used by all instances of AsyncSocket, to protect getaddrinfo.
  29. // Prior to Mac OS X 10.5 this method was not thread-safe.
  30. static NSString *getaddrinfoLock = @"lock";
  31. #endif
  32. enum AsyncSocketFlags
  33. {
  34. kEnablePreBuffering = 1 << 0, // If set, pre-buffering is enabled
  35. kDidStartDelegate = 1 << 1, // If set, disconnection results in delegate call
  36. kDidCompleteOpenForRead = 1 << 2, // If set, open callback has been called for read stream
  37. kDidCompleteOpenForWrite = 1 << 3, // If set, open callback has been called for write stream
  38. kStartingReadTLS = 1 << 4, // If set, we're waiting for TLS negotiation to complete
  39. kStartingWriteTLS = 1 << 5, // If set, we're waiting for TLS negotiation to complete
  40. kForbidReadsWrites = 1 << 6, // If set, no new reads or writes are allowed
  41. kDisconnectAfterReads = 1 << 7, // If set, disconnect after no more reads are queued
  42. kDisconnectAfterWrites = 1 << 8, // If set, disconnect after no more writes are queued
  43. kClosingWithError = 1 << 9, // If set, the socket is being closed due to an error
  44. kDequeueReadScheduled = 1 << 10, // If set, a maybeDequeueRead operation is already scheduled
  45. kDequeueWriteScheduled = 1 << 11, // If set, a maybeDequeueWrite operation is already scheduled
  46. kSocketCanAcceptBytes = 1 << 12, // If set, we know socket can accept bytes. If unset, it's unknown.
  47. kSocketHasBytesAvailable = 1 << 13, // If set, we know socket has bytes available. If unset, it's unknown.
  48. };
  49. @interface AsyncSocket (Private)
  50. // Connecting
  51. - (void)startConnectTimeout:(NSTimeInterval)timeout;
  52. - (void)endConnectTimeout;
  53. // Socket Implementation
  54. - (CFSocketRef)newAcceptSocketForAddress:(NSData *)addr error:(NSError **)errPtr;
  55. - (BOOL)createSocketForAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
  56. - (BOOL)attachSocketsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr;
  57. - (BOOL)configureSocketAndReturnError:(NSError **)errPtr;
  58. - (BOOL)connectSocketToAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
  59. - (void)doAcceptWithSocket:(CFSocketNativeHandle)newSocket;
  60. - (void)doSocketOpen:(CFSocketRef)sock withCFSocketError:(CFSocketError)err;
  61. // Stream Implementation
  62. - (BOOL)createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr;
  63. - (BOOL)createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr;
  64. - (BOOL)attachStreamsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr;
  65. - (BOOL)configureStreamsAndReturnError:(NSError **)errPtr;
  66. - (BOOL)openStreamsAndReturnError:(NSError **)errPtr;
  67. - (void)doStreamOpen;
  68. - (BOOL)setSocketFromStreamsAndReturnError:(NSError **)errPtr;
  69. // Disconnect Implementation
  70. - (void)closeWithError:(NSError *)err;
  71. - (void)recoverUnreadData;
  72. - (void)emptyQueues;
  73. - (void)close;
  74. // Errors
  75. - (NSError *)getErrnoError;
  76. - (NSError *)getAbortError;
  77. - (NSError *)getStreamError;
  78. - (NSError *)getSocketError;
  79. - (NSError *)getConnectTimeoutError;
  80. - (NSError *)getReadMaxedOutError;
  81. - (NSError *)getReadTimeoutError;
  82. - (NSError *)getWriteTimeoutError;
  83. - (NSError *)errorFromCFStreamError:(CFStreamError)err;
  84. // Diagnostics
  85. - (BOOL)isDisconnected;
  86. - (BOOL)areStreamsConnected;
  87. - (NSString *)connectedHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket;
  88. - (NSString *)connectedHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket;
  89. - (NSString *)connectedHostFromCFSocket4:(CFSocketRef)socket;
  90. - (NSString *)connectedHostFromCFSocket6:(CFSocketRef)socket;
  91. - (UInt16)connectedPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket;
  92. - (UInt16)connectedPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket;
  93. - (UInt16)connectedPortFromCFSocket4:(CFSocketRef)socket;
  94. - (UInt16)connectedPortFromCFSocket6:(CFSocketRef)socket;
  95. - (NSString *)localHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket;
  96. - (NSString *)localHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket;
  97. - (NSString *)localHostFromCFSocket4:(CFSocketRef)socket;
  98. - (NSString *)localHostFromCFSocket6:(CFSocketRef)socket;
  99. - (UInt16)localPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket;
  100. - (UInt16)localPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket;
  101. - (UInt16)localPortFromCFSocket4:(CFSocketRef)socket;
  102. - (UInt16)localPortFromCFSocket6:(CFSocketRef)socket;
  103. - (NSString *)hostFromAddress4:(struct sockaddr_in *)pSockaddr4;
  104. - (NSString *)hostFromAddress6:(struct sockaddr_in6 *)pSockaddr6;
  105. - (UInt16)portFromAddress4:(struct sockaddr_in *)pSockaddr4;
  106. - (UInt16)portFromAddress6:(struct sockaddr_in6 *)pSockaddr6;
  107. // Reading
  108. - (void)doBytesAvailable;
  109. - (void)completeCurrentRead;
  110. - (void)endCurrentRead;
  111. - (void)scheduleDequeueRead;
  112. - (void)maybeDequeueRead;
  113. - (void)doReadTimeout:(NSTimer *)timer;
  114. // Writing
  115. - (void)doSendBytes;
  116. - (void)completeCurrentWrite;
  117. - (void)endCurrentWrite;
  118. - (void)scheduleDequeueWrite;
  119. - (void)maybeDequeueWrite;
  120. - (void)maybeScheduleDisconnect;
  121. - (void)doWriteTimeout:(NSTimer *)timer;
  122. // Run Loop
  123. - (void)runLoopAddSource:(CFRunLoopSourceRef)source;
  124. - (void)runLoopRemoveSource:(CFRunLoopSourceRef)source;
  125. - (void)runLoopAddTimer:(NSTimer *)timer;
  126. - (void)runLoopRemoveTimer:(NSTimer *)timer;
  127. - (void)runLoopUnscheduleReadStream;
  128. - (void)runLoopUnscheduleWriteStream;
  129. // Security
  130. - (void)maybeStartTLS;
  131. - (void)onTLSHandshakeSuccessful;
  132. // Callbacks
  133. - (void)doCFCallback:(CFSocketCallBackType)type forSocket:(CFSocketRef)sock withAddress:(NSData *)address withData:(const void *)pData;
  134. - (void)doCFReadStreamCallback:(CFStreamEventType)type forStream:(CFReadStreamRef)stream;
  135. - (void)doCFWriteStreamCallback:(CFStreamEventType)type forStream:(CFWriteStreamRef)stream;
  136. @end
  137. static void MyCFSocketCallback(CFSocketRef, CFSocketCallBackType, CFDataRef, const void *, void *);
  138. static void MyCFReadStreamCallback(CFReadStreamRef stream, CFStreamEventType type, void *pInfo);
  139. static void MyCFWriteStreamCallback(CFWriteStreamRef stream, CFStreamEventType type, void *pInfo);
  140. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  141. #pragma mark -
  142. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  143. /**
  144. * The AsyncReadPacket encompasses the instructions for any given read.
  145. * The content of a read packet allows the code to determine if we're:
  146. * - reading to a certain length
  147. * - reading to a certain separator
  148. * - or simply reading the first chunk of available data
  149. **/
  150. @interface AsyncReadPacket : NSObject
  151. {
  152. @public
  153. NSMutableData *buffer;
  154. CFIndex bytesDone;
  155. NSTimeInterval timeout;
  156. CFIndex maxLength;
  157. long tag;
  158. NSData *term;
  159. BOOL readAllAvailableData;
  160. }
  161. - (id)initWithData:(NSMutableData *)d
  162. timeout:(NSTimeInterval)t
  163. tag:(long)i
  164. readAllAvailable:(BOOL)a
  165. terminator:(NSData *)e
  166. maxLength:(CFIndex)m;
  167. - (NSUInteger)readLengthForTerm;
  168. - (NSUInteger)prebufferReadLengthForTerm;
  169. - (CFIndex)searchForTermAfterPreBuffering:(CFIndex)numBytes;
  170. @end
  171. @implementation AsyncReadPacket
  172. - (id)initWithData:(NSMutableData *)d
  173. timeout:(NSTimeInterval)t
  174. tag:(long)i
  175. readAllAvailable:(BOOL)a
  176. terminator:(NSData *)e
  177. maxLength:(CFIndex)m
  178. {
  179. if((self = [super init]))
  180. {
  181. buffer = [d retain];
  182. timeout = t;
  183. tag = i;
  184. readAllAvailableData = a;
  185. term = [e copy];
  186. bytesDone = 0;
  187. maxLength = m;
  188. }
  189. return self;
  190. }
  191. /**
  192. * For read packets with a set terminator, returns the safe length of data that can be read
  193. * without going over a terminator, or the maxLength.
  194. *
  195. * It is assumed the terminator has not already been read.
  196. **/
  197. - (NSUInteger)readLengthForTerm
  198. {
  199. NSAssert(term != nil, @"Searching for term in data when there is no term.");
  200. // What we're going to do is look for a partial sequence of the terminator at the end of the buffer.
  201. // If a partial sequence occurs, then we must assume the next bytes to arrive will be the rest of the term,
  202. // and we can only read that amount.
  203. // Otherwise, we're safe to read the entire length of the term.
  204. NSUInteger result = [term length];
  205. // Shortcut when term is a single byte
  206. if(result == 1) return result;
  207. // i = index within buffer at which to check data
  208. // j = length of term to check against
  209. // Note: Beware of implicit casting rules
  210. // This could give you -1: MAX(0, (0 - [term length] + 1));
  211. CFIndex i = MAX(0, (CFIndex)(bytesDone - [term length] + 1));
  212. CFIndex j = MIN((CFIndex)[term length] - 1, bytesDone);
  213. while(i < bytesDone)
  214. {
  215. const void *subBuffer = [buffer bytes] + i;
  216. if(memcmp(subBuffer, [term bytes], j) == 0)
  217. {
  218. result = [term length] - j;
  219. break;
  220. }
  221. i++;
  222. j--;
  223. }
  224. if(maxLength > 0)
  225. return MIN((CFIndex)result, ((CFIndex)maxLength - bytesDone));
  226. else
  227. return result;
  228. }
  229. /**
  230. * Assuming pre-buffering is enabled, returns the amount of data that can be read
  231. * without going over the maxLength.
  232. **/
  233. - (NSUInteger)prebufferReadLengthForTerm
  234. {
  235. if(maxLength > 0)
  236. return MIN(READALL_CHUNKSIZE, (maxLength - bytesDone));
  237. else
  238. return READALL_CHUNKSIZE;
  239. }
  240. /**
  241. * For read packets with a set terminator, scans the packet buffer for the term.
  242. * It is assumed the terminator had not been fully read prior to the new bytes.
  243. *
  244. * If the term is found, the number of excess bytes after the term are returned.
  245. * If the term is not found, this method will return -1.
  246. *
  247. * Note: A return value of zero means the term was found at the very end.
  248. **/
  249. - (CFIndex)searchForTermAfterPreBuffering:(CFIndex)numBytes
  250. {
  251. NSAssert(term != nil, @"Searching for term in data when there is no term.");
  252. // We try to start the search such that the first new byte read matches up with the last byte of the term.
  253. // We continue searching forward after this until the term no longer fits into the buffer.
  254. // Note: Beware of implicit casting rules
  255. // This could give you -1: MAX(0, 1 - 1 - [term length] + 1);
  256. CFIndex i = MAX(0, (CFIndex)(bytesDone - numBytes - [term length] + 1));
  257. while(i + (CFIndex)[term length] <= bytesDone)
  258. {
  259. const void *subBuffer = [buffer bytes] + i;
  260. if(memcmp(subBuffer, [term bytes], [term length]) == 0)
  261. {
  262. return bytesDone - (i + [term length]);
  263. }
  264. i++;
  265. }
  266. return -1;
  267. }
  268. - (void)dealloc
  269. {
  270. [buffer release];
  271. [term release];
  272. [super dealloc];
  273. }
  274. @end
  275. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  276. #pragma mark -
  277. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  278. /**
  279. * The AsyncWritePacket encompasses the instructions for any given write.
  280. **/
  281. @interface AsyncWritePacket : NSObject
  282. {
  283. @public
  284. NSData *buffer;
  285. CFIndex bytesDone;
  286. long tag;
  287. NSTimeInterval timeout;
  288. }
  289. - (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i;
  290. @end
  291. @implementation AsyncWritePacket
  292. - (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i
  293. {
  294. if((self = [super init]))
  295. {
  296. buffer = [d retain];
  297. timeout = t;
  298. tag = i;
  299. bytesDone = 0;
  300. }
  301. return self;
  302. }
  303. - (void)dealloc
  304. {
  305. [buffer release];
  306. [super dealloc];
  307. }
  308. @end
  309. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  310. #pragma mark -
  311. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  312. /**
  313. * The AsyncSpecialPacket encompasses special instructions for interruptions in the read/write queues.
  314. * This class my be altered to support more than just TLS in the future.
  315. **/
  316. @interface AsyncSpecialPacket : NSObject
  317. {
  318. @public
  319. NSDictionary *tlsSettings;
  320. }
  321. - (id)initWithTLSSettings:(NSDictionary *)settings;
  322. @end
  323. @implementation AsyncSpecialPacket
  324. - (id)initWithTLSSettings:(NSDictionary *)settings
  325. {
  326. if((self = [super init]))
  327. {
  328. tlsSettings = [settings copy];
  329. }
  330. return self;
  331. }
  332. - (void)dealloc
  333. {
  334. [tlsSettings release];
  335. [super dealloc];
  336. }
  337. @end
  338. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  339. #pragma mark -
  340. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  341. @implementation AsyncSocket
  342. - (id)init
  343. {
  344. return [self initWithDelegate:nil userData:0];
  345. }
  346. - (id)initWithDelegate:(id)delegate
  347. {
  348. return [self initWithDelegate:delegate userData:0];
  349. }
  350. // Designated initializer.
  351. - (id)initWithDelegate:(id)delegate userData:(long)userData
  352. {
  353. if((self = [super init]))
  354. {
  355. theFlags = DEFAULT_PREBUFFERING ? kEnablePreBuffering : 0;
  356. theDelegate = delegate;
  357. theUserData = userData;
  358. theNativeSocket4 = 0;
  359. theNativeSocket6 = 0;
  360. theSocket4 = NULL;
  361. theSource4 = NULL;
  362. theSocket6 = NULL;
  363. theSource6 = NULL;
  364. theRunLoop = NULL;
  365. theReadStream = NULL;
  366. theWriteStream = NULL;
  367. theConnectTimer = nil;
  368. theReadQueue = [[NSMutableArray alloc] initWithCapacity:READQUEUE_CAPACITY];
  369. theCurrentRead = nil;
  370. theReadTimer = nil;
  371. partialReadBuffer = [[NSMutableData alloc] initWithCapacity:READALL_CHUNKSIZE];
  372. theWriteQueue = [[NSMutableArray alloc] initWithCapacity:WRITEQUEUE_CAPACITY];
  373. theCurrentWrite = nil;
  374. theWriteTimer = nil;
  375. // Socket context
  376. NSAssert(sizeof(CFSocketContext) == sizeof(CFStreamClientContext), @"CFSocketContext != CFStreamClientContext");
  377. theContext.version = 0;
  378. theContext.info = self;
  379. theContext.retain = nil;
  380. theContext.release = nil;
  381. theContext.copyDescription = nil;
  382. // Default run loop modes
  383. theRunLoopModes = [[NSArray arrayWithObject:NSDefaultRunLoopMode] retain];
  384. }
  385. return self;
  386. }
  387. // The socket may been initialized in a connected state and auto-released, so this should close it down cleanly.
  388. - (void)dealloc
  389. {
  390. [self close];
  391. [theReadQueue release];
  392. [theWriteQueue release];
  393. [theRunLoopModes release];
  394. [partialReadBuffer release];
  395. [NSObject cancelPreviousPerformRequestsWithTarget:self];
  396. [super dealloc];
  397. }
  398. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  399. #pragma mark Accessors
  400. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  401. - (long)userData
  402. {
  403. return theUserData;
  404. }
  405. - (void)setUserData:(long)userData
  406. {
  407. theUserData = userData;
  408. }
  409. - (id)delegate
  410. {
  411. return theDelegate;
  412. }
  413. - (void)setDelegate:(id)delegate
  414. {
  415. theDelegate = delegate;
  416. }
  417. - (BOOL)canSafelySetDelegate
  418. {
  419. return ([theReadQueue count] == 0 && [theWriteQueue count] == 0 && theCurrentRead == nil && theCurrentWrite == nil);
  420. }
  421. - (CFSocketRef)getCFSocket
  422. {
  423. if(theSocket4)
  424. return theSocket4;
  425. else
  426. return theSocket6;
  427. }
  428. - (CFReadStreamRef)getCFReadStream
  429. {
  430. return theReadStream;
  431. }
  432. - (CFWriteStreamRef)getCFWriteStream
  433. {
  434. return theWriteStream;
  435. }
  436. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  437. #pragma mark Progress
  438. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  439. - (float)progressOfReadReturningTag:(long *)tag bytesDone:(CFIndex *)done total:(CFIndex *)total
  440. {
  441. // Check to make sure we're actually reading something right now,
  442. // and that the read packet isn't an AsyncSpecialPacket (upgrade to TLS).
  443. if (!theCurrentRead || ![theCurrentRead isKindOfClass:[AsyncReadPacket class]]) return NAN;
  444. // It's only possible to know the progress of our read if we're reading to a certain length
  445. // If we're reading to data, we of course have no idea when the data will arrive
  446. // If we're reading to timeout, then we have no idea when the next chunk of data will arrive.
  447. BOOL hasTotal = (theCurrentRead->readAllAvailableData == NO && theCurrentRead->term == nil);
  448. CFIndex d = theCurrentRead->bytesDone;
  449. CFIndex t = hasTotal ? [theCurrentRead->buffer length] : 0;
  450. if (tag != NULL) *tag = theCurrentRead->tag;
  451. if (done != NULL) *done = d;
  452. if (total != NULL) *total = t;
  453. float ratio = (float)d/(float)t;
  454. return isnan(ratio) ? 1.0F : ratio; // 0 of 0 bytes is 100% done.
  455. }
  456. - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(CFIndex *)done total:(CFIndex *)total
  457. {
  458. // Check to make sure we're actually writing something right now,
  459. // and that the write packet isn't an AsyncSpecialPacket (upgrade to TLS).
  460. if (!theCurrentWrite || ![theCurrentWrite isKindOfClass:[AsyncWritePacket class]]) return NAN;
  461. CFIndex d = theCurrentWrite->bytesDone;
  462. CFIndex t = [theCurrentWrite->buffer length];
  463. if (tag != NULL) *tag = theCurrentWrite->tag;
  464. if (done != NULL) *done = d;
  465. if (total != NULL) *total = t;
  466. return (float)d/(float)t;
  467. }
  468. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  469. #pragma mark Run Loop
  470. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  471. - (void)runLoopAddSource:(CFRunLoopSourceRef)source
  472. {
  473. NSUInteger i, count = [theRunLoopModes count];
  474. for(i = 0; i < count; i++)
  475. {
  476. CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i];
  477. CFRunLoopAddSource(theRunLoop, source, runLoopMode);
  478. }
  479. }
  480. - (void)runLoopRemoveSource:(CFRunLoopSourceRef)source
  481. {
  482. NSUInteger i, count = [theRunLoopModes count];
  483. for(i = 0; i < count; i++)
  484. {
  485. CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i];
  486. CFRunLoopRemoveSource(theRunLoop, source, runLoopMode);
  487. }
  488. }
  489. - (void)runLoopAddTimer:(NSTimer *)timer
  490. {
  491. NSUInteger i, count = [theRunLoopModes count];
  492. for(i = 0; i < count; i++)
  493. {
  494. CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i];
  495. CFRunLoopAddTimer(theRunLoop, (CFRunLoopTimerRef)timer, runLoopMode);
  496. }
  497. }
  498. - (void)runLoopRemoveTimer:(NSTimer *)timer
  499. {
  500. NSUInteger i, count = [theRunLoopModes count];
  501. for(i = 0; i < count; i++)
  502. {
  503. CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i];
  504. CFRunLoopRemoveTimer(theRunLoop, (CFRunLoopTimerRef)timer, runLoopMode);
  505. }
  506. }
  507. - (void)runLoopUnscheduleReadStream
  508. {
  509. NSUInteger i, count = [theRunLoopModes count];
  510. for(i = 0; i < count; i++)
  511. {
  512. CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i];
  513. CFReadStreamUnscheduleFromRunLoop(theReadStream, theRunLoop, runLoopMode);
  514. }
  515. CFReadStreamSetClient(theReadStream, kCFStreamEventNone, NULL, NULL);
  516. }
  517. - (void)runLoopUnscheduleWriteStream
  518. {
  519. NSUInteger i, count = [theRunLoopModes count];
  520. for(i = 0; i < count; i++)
  521. {
  522. CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i];
  523. CFWriteStreamUnscheduleFromRunLoop(theWriteStream, theRunLoop, runLoopMode);
  524. }
  525. CFWriteStreamSetClient(theWriteStream, kCFStreamEventNone, NULL, NULL);
  526. }
  527. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  528. #pragma mark Configuration
  529. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  530. /**
  531. * See the header file for a full explanation of pre-buffering.
  532. **/
  533. - (void)enablePreBuffering
  534. {
  535. theFlags |= kEnablePreBuffering;
  536. }
  537. /**
  538. * See the header file for a full explanation of this method.
  539. **/
  540. - (BOOL)moveToRunLoop:(NSRunLoop *)runLoop
  541. {
  542. NSAssert((theRunLoop == NULL) || (theRunLoop == CFRunLoopGetCurrent()),
  543. @"moveToRunLoop must be called from within the current RunLoop!");
  544. if(runLoop == nil)
  545. {
  546. return NO;
  547. }
  548. if(theRunLoop == [runLoop getCFRunLoop])
  549. {
  550. return YES;
  551. }
  552. [NSObject cancelPreviousPerformRequestsWithTarget:self];
  553. theFlags &= ~kDequeueReadScheduled;
  554. theFlags &= ~kDequeueWriteScheduled;
  555. if(theReadStream && theWriteStream)
  556. {
  557. [self runLoopUnscheduleReadStream];
  558. [self runLoopUnscheduleWriteStream];
  559. }
  560. if(theSource4) [self runLoopRemoveSource:theSource4];
  561. if(theSource6) [self runLoopRemoveSource:theSource6];
  562. // We do not retain the timers - they get retained by the runloop when we add them as a source.
  563. // Since we're about to remove them as a source, we retain now, and release again below.
  564. [theReadTimer retain];
  565. [theWriteTimer retain];
  566. if(theReadTimer) [self runLoopRemoveTimer:theReadTimer];
  567. if(theWriteTimer) [self runLoopRemoveTimer:theWriteTimer];
  568. theRunLoop = [runLoop getCFRunLoop];
  569. if(theReadTimer) [self runLoopAddTimer:theReadTimer];
  570. if(theWriteTimer) [self runLoopAddTimer:theWriteTimer];
  571. // Release timers since we retained them above
  572. [theReadTimer release];
  573. [theWriteTimer release];
  574. if(theSource4) [self runLoopAddSource:theSource4];
  575. if(theSource6) [self runLoopAddSource:theSource6];
  576. if(theReadStream && theWriteStream)
  577. {
  578. if(![self attachStreamsToRunLoop:runLoop error:nil])
  579. {
  580. return NO;
  581. }
  582. }
  583. [runLoop performSelector:@selector(maybeDequeueRead) target:self argument:nil order:0 modes:theRunLoopModes];
  584. [runLoop performSelector:@selector(maybeDequeueWrite) target:self argument:nil order:0 modes:theRunLoopModes];
  585. [runLoop performSelector:@selector(maybeScheduleDisconnect) target:self argument:nil order:0 modes:theRunLoopModes];
  586. return YES;
  587. }
  588. /**
  589. * See the header file for a full explanation of this method.
  590. **/
  591. - (BOOL)setRunLoopModes:(NSArray *)runLoopModes
  592. {
  593. NSAssert((theRunLoop == NULL) || (theRunLoop == CFRunLoopGetCurrent()),
  594. @"setRunLoopModes must be called from within the current RunLoop!");
  595. if([runLoopModes count] == 0)
  596. {
  597. return NO;
  598. }
  599. if([theRunLoopModes isEqualToArray:runLoopModes])
  600. {
  601. return YES;
  602. }
  603. [NSObject cancelPreviousPerformRequestsWithTarget:self];
  604. theFlags &= ~kDequeueReadScheduled;
  605. theFlags &= ~kDequeueWriteScheduled;
  606. if(theReadStream && theWriteStream)
  607. {
  608. [self runLoopUnscheduleReadStream];
  609. [self runLoopUnscheduleWriteStream];
  610. }
  611. if(theSource4) [self runLoopRemoveSource:theSource4];
  612. if(theSource6) [self runLoopRemoveSource:theSource6];
  613. // We do not retain the timers - they get retained by the runloop when we add them as a source.
  614. // Since we're about to remove them as a source, we retain now, and release again below.
  615. [theReadTimer retain];
  616. [theWriteTimer retain];
  617. if(theReadTimer) [self runLoopRemoveTimer:theReadTimer];
  618. if(theWriteTimer) [self runLoopRemoveTimer:theWriteTimer];
  619. [theRunLoopModes release];
  620. theRunLoopModes = [runLoopModes copy];
  621. if(theReadTimer) [self runLoopAddTimer:theReadTimer];
  622. if(theWriteTimer) [self runLoopAddTimer:theWriteTimer];
  623. // Release timers since we retained them above
  624. [theReadTimer release];
  625. [theWriteTimer release];
  626. if(theSource4) [self runLoopAddSource:theSource4];
  627. if(theSource6) [self runLoopAddSource:theSource6];
  628. if(theReadStream && theWriteStream)
  629. {
  630. // Note: theRunLoop variable is a CFRunLoop, and NSRunLoop is NOT toll-free bridged with CFRunLoop.
  631. // So we cannot pass theRunLoop to the method below, which is expecting a NSRunLoop parameter.
  632. // Instead we pass nil, which will result in the method properly using the current run loop.
  633. if(![self attachStreamsToRunLoop:nil error:nil])
  634. {
  635. return NO;
  636. }
  637. }
  638. [self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0 inModes:theRunLoopModes];
  639. [self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0 inModes:theRunLoopModes];
  640. [self performSelector:@selector(maybeScheduleDisconnect) withObject:nil afterDelay:0 inModes:theRunLoopModes];
  641. return YES;
  642. }
  643. - (NSArray *)runLoopModes
  644. {
  645. return [[theRunLoopModes retain] autorelease];
  646. }
  647. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  648. #pragma mark Accepting
  649. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  650. - (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr
  651. {
  652. return [self acceptOnInterface:nil port:port error:errPtr];
  653. }
  654. /**
  655. * To accept on a certain interface, pass the address to accept on.
  656. * To accept on any interface, pass nil or an empty string.
  657. * To accept only connections from localhost pass "localhost" or "loopback".
  658. **/
  659. - (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr
  660. {
  661. if (theDelegate == NULL)
  662. {
  663. [NSException raise:AsyncSocketException
  664. format:@"Attempting to accept without a delegate. Set a delegate first."];
  665. }
  666. if (theSocket4 != NULL || theSocket6 != NULL)
  667. {
  668. [NSException raise:AsyncSocketException
  669. format:@"Attempting to accept while connected or accepting connections. Disconnect first."];
  670. }
  671. // Set up the listen sockaddr structs if needed.
  672. NSData *address4 = nil, *address6 = nil;
  673. if(interface == nil || ([interface length] == 0))
  674. {
  675. // Accept on ANY address
  676. struct sockaddr_in nativeAddr4;
  677. nativeAddr4.sin_len = sizeof(struct sockaddr_in);
  678. nativeAddr4.sin_family = AF_INET;
  679. nativeAddr4.sin_port = htons(port);
  680. nativeAddr4.sin_addr.s_addr = htonl(INADDR_ANY);
  681. memset(&(nativeAddr4.sin_zero), 0, sizeof(nativeAddr4.sin_zero));
  682. struct sockaddr_in6 nativeAddr6;
  683. nativeAddr6.sin6_len = sizeof(struct sockaddr_in6);
  684. nativeAddr6.sin6_family = AF_INET6;
  685. nativeAddr6.sin6_port = htons(port);
  686. nativeAddr6.sin6_flowinfo = 0;
  687. nativeAddr6.sin6_addr = in6addr_any;
  688. nativeAddr6.sin6_scope_id = 0;
  689. // Wrap the native address structures for CFSocketSetAddress.
  690. address4 = [NSData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)];
  691. address6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
  692. }
  693. else if([interface isEqualToString:@"localhost"] || [interface isEqualToString:@"loopback"])
  694. {
  695. // Accept only on LOOPBACK address
  696. struct sockaddr_in nativeAddr4;
  697. nativeAddr4.sin_len = sizeof(struct sockaddr_in);
  698. nativeAddr4.sin_family = AF_INET;
  699. nativeAddr4.sin_port = htons(port);
  700. nativeAddr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  701. memset(&(nativeAddr4.sin_zero), 0, sizeof(nativeAddr4.sin_zero));
  702. struct sockaddr_in6 nativeAddr6;
  703. nativeAddr6.sin6_len = sizeof(struct sockaddr_in6);
  704. nativeAddr6.sin6_family = AF_INET6;
  705. nativeAddr6.sin6_port = htons(port);
  706. nativeAddr6.sin6_flowinfo = 0;
  707. nativeAddr6.sin6_addr = in6addr_loopback;
  708. nativeAddr6.sin6_scope_id = 0;
  709. // Wrap the native address structures for CFSocketSetAddress.
  710. address4 = [NSData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)];
  711. address6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
  712. }
  713. else
  714. {
  715. NSString *portStr = [NSString stringWithFormat:@"%hu", port];
  716. #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  717. @synchronized (getaddrinfoLock)
  718. #endif
  719. {
  720. struct addrinfo hints, *res, *res0;
  721. memset(&hints, 0, sizeof(hints));
  722. hints.ai_family = PF_UNSPEC;
  723. hints.ai_socktype = SOCK_STREAM;
  724. hints.ai_protocol = IPPROTO_TCP;
  725. hints.ai_flags = AI_PASSIVE;
  726. int error = getaddrinfo([interface UTF8String], [portStr UTF8String], &hints, &res0);
  727. if(error)
  728. {
  729. if(errPtr)
  730. {
  731. NSString *errMsg = [NSString stringWithCString:gai_strerror(error) encoding:NSASCIIStringEncoding];
  732. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  733. *errPtr = [NSError errorWithDomain:@"kCFStreamErrorDomainNetDB" code:error userInfo:info];
  734. }
  735. }
  736. for(res = res0; res; res = res->ai_next)
  737. {
  738. if(!address4 && (res->ai_family == AF_INET))
  739. {
  740. // Found IPv4 address
  741. // Wrap the native address structures for CFSocketSetAddress.
  742. address4 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
  743. }
  744. else if(!address6 && (res->ai_family == AF_INET6))
  745. {
  746. // Found IPv6 address
  747. // Wrap the native address structures for CFSocketSetAddress.
  748. address6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
  749. }
  750. }
  751. freeaddrinfo(res0);
  752. }
  753. if(!address4 && !address6) return NO;
  754. }
  755. // Create the sockets.
  756. if (address4)
  757. {
  758. theSocket4 = [self newAcceptSocketForAddress:address4 error:errPtr];
  759. if (theSocket4 == NULL) goto Failed;
  760. }
  761. if (address6)
  762. {
  763. theSocket6 = [self newAcceptSocketForAddress:address6 error:errPtr];
  764. // Note: The iPhone doesn't currently support IPv6
  765. #if !TARGET_OS_IPHONE
  766. if (theSocket6 == NULL) goto Failed;
  767. #endif
  768. }
  769. // Attach the sockets to the run loop so that callback methods work
  770. [self attachSocketsToRunLoop:nil error:nil];
  771. // Set the SO_REUSEADDR flags.
  772. int reuseOn = 1;
  773. if (theSocket4) setsockopt(CFSocketGetNative(theSocket4), SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  774. if (theSocket6) setsockopt(CFSocketGetNative(theSocket6), SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  775. // Set the local bindings which causes the sockets to start listening.
  776. CFSocketError err;
  777. if (theSocket4)
  778. {
  779. err = CFSocketSetAddress(theSocket4, (CFDataRef)address4);
  780. if (err != kCFSocketSuccess) goto Failed;
  781. //NSLog(@"theSocket4: %hu", [self localPortFromCFSocket4:theSocket4]);
  782. }
  783. if(port == 0 && theSocket4 && theSocket6)
  784. {
  785. // The user has passed in port 0, which means he wants to allow the kernel to choose the port for them
  786. // However, the kernel will choose a different port for both theSocket4 and theSocket6
  787. // So we grab the port the kernel choose for theSocket4, and set it as the port for theSocket6
  788. UInt16 chosenPort = [self localPortFromCFSocket4:theSocket4];
  789. struct sockaddr_in6 *pSockAddr6 = (struct sockaddr_in6 *)[address6 bytes];
  790. pSockAddr6->sin6_port = htons(chosenPort);
  791. }
  792. if (theSocket6)
  793. {
  794. err = CFSocketSetAddress(theSocket6, (CFDataRef)address6);
  795. if (err != kCFSocketSuccess) goto Failed;
  796. //NSLog(@"theSocket6: %hu", [self localPortFromCFSocket6:theSocket6]);
  797. }
  798. theFlags |= kDidStartDelegate;
  799. return YES;
  800. Failed:
  801. if(errPtr) *errPtr = [self getSocketError];
  802. if(theSocket4 != NULL)
  803. {
  804. CFSocketInvalidate(theSocket4);
  805. CFRelease(theSocket4);
  806. theSocket4 = NULL;
  807. }
  808. if(theSocket6 != NULL)
  809. {
  810. CFSocketInvalidate(theSocket6);
  811. CFRelease(theSocket6);
  812. theSocket6 = NULL;
  813. }
  814. return NO;
  815. }
  816. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  817. #pragma mark Connecting
  818. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  819. - (BOOL)connectToHost:(NSString*)hostname onPort:(UInt16)port error:(NSError **)errPtr
  820. {
  821. return [self connectToHost:hostname onPort:port withTimeout:-1 error:errPtr];
  822. }
  823. /**
  824. * This method creates an initial CFReadStream and CFWriteStream to the given host on the given port.
  825. * The connection is then opened, and the corresponding CFSocket will be extracted after the connection succeeds.
  826. *
  827. * Thus the delegate will have access to the CFReadStream and CFWriteStream prior to connection,
  828. * specifically in the onSocketWillConnect: method.
  829. **/
  830. - (BOOL)connectToHost:(NSString *)hostname
  831. onPort:(UInt16)port
  832. withTimeout:(NSTimeInterval)timeout
  833. error:(NSError **)errPtr
  834. {
  835. if(theDelegate == NULL)
  836. {
  837. [NSException raise:AsyncSocketException
  838. format:@"Attempting to connect without a delegate. Set a delegate first."];
  839. }
  840. if(![self isDisconnected])
  841. {
  842. [NSException raise:AsyncSocketException
  843. format:@"Attempting to connect while connected or accepting connections. Disconnect first."];
  844. }
  845. if(![self createStreamsToHost:hostname onPort:port error:errPtr]) goto Failed;
  846. if(![self attachStreamsToRunLoop:nil error:errPtr]) goto Failed;
  847. if(![self configureStreamsAndReturnError:errPtr]) goto Failed;
  848. if(![self openStreamsAndReturnError:errPtr]) goto Failed;
  849. [self startConnectTimeout:timeout];
  850. theFlags |= kDidStartDelegate;
  851. return YES;
  852. Failed:
  853. [self close];
  854. return NO;
  855. }
  856. - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr
  857. {
  858. return [self connectToAddress:remoteAddr withTimeout:-1 error:errPtr];
  859. }
  860. /**
  861. * This method creates an initial CFSocket to the given address.
  862. * The connection is then opened, and the corresponding CFReadStream and CFWriteStream will be
  863. * created from the low-level sockets after the connection succeeds.
  864. *
  865. * Thus the delegate will have access to the CFSocket and CFSocketNativeHandle (BSD socket) prior to connection,
  866. * specifically in the onSocketWillConnect: method.
  867. *
  868. * Note: The NSData parameter is expected to be a sockaddr structure. For example, an NSData object returned from
  869. * NSNetservice addresses method.
  870. * If you have an existing struct sockaddr you can convert it to an NSData object like so:
  871. * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  872. * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];
  873. **/
  874. - (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr
  875. {
  876. if (theDelegate == NULL)
  877. {
  878. [NSException raise:AsyncSocketException
  879. format:@"Attempting to connect without a delegate. Set a delegate first."];
  880. }
  881. if (![self isDisconnected])
  882. {
  883. [NSException raise:AsyncSocketException
  884. format:@"Attempting to connect while connected or accepting connections. Disconnect first."];
  885. }
  886. if(![self createSocketForAddress:remoteAddr error:errPtr]) goto Failed;
  887. if(![self attachSocketsToRunLoop:nil error:errPtr]) goto Failed;
  888. if(![self configureSocketAndReturnError:errPtr]) goto Failed;
  889. if(![self connectSocketToAddress:remoteAddr error:errPtr]) goto Failed;
  890. [self startConnectTimeout:timeout];
  891. theFlags |= kDidStartDelegate;
  892. return YES;
  893. Failed:
  894. [self close];
  895. return NO;
  896. }
  897. - (void)startConnectTimeout:(NSTimeInterval)timeout
  898. {
  899. if(timeout >= 0.0)
  900. {
  901. theConnectTimer = [NSTimer timerWithTimeInterval:timeout
  902. target:self
  903. selector:@selector(doConnectTimeout:)
  904. userInfo:nil
  905. repeats:NO];
  906. [self runLoopAddTimer:theConnectTimer];
  907. }
  908. }
  909. - (void)endConnectTimeout
  910. {
  911. [theConnectTimer invalidate];
  912. theConnectTimer = nil;
  913. }
  914. - (void)doConnectTimeout:(NSTimer *)timer
  915. {
  916. [self endConnectTimeout];
  917. [self closeWithError:[self getConnectTimeoutError]];
  918. }
  919. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  920. #pragma mark Socket Implementation
  921. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  922. /**
  923. * Creates the accept sockets.
  924. * Returns true if either IPv4 or IPv6 is created.
  925. * If either is missing, an error is returned (even though the method may return true).
  926. **/
  927. - (CFSocketRef)newAcceptSocketForAddress:(NSData *)addr error:(NSError **)errPtr
  928. {
  929. struct sockaddr *pSockAddr = (struct sockaddr *)[addr bytes];
  930. int addressFamily = pSockAddr->sa_family;
  931. CFSocketRef theSocket = CFSocketCreate(kCFAllocatorDefault,
  932. addressFamily,
  933. SOCK_STREAM,
  934. 0,
  935. kCFSocketAcceptCallBack, // Callback flags
  936. (CFSocketCallBack)&MyCFSocketCallback, // Callback method
  937. &theContext);
  938. if(theSocket == NULL)
  939. {
  940. if(errPtr) *errPtr = [self getSocketError];
  941. }
  942. return theSocket;
  943. }
  944. - (BOOL)createSocketForAddress:(NSData *)remoteAddr error:(NSError **)errPtr
  945. {
  946. struct sockaddr *pSockAddr = (struct sockaddr *)[remoteAddr bytes];
  947. if(pSockAddr->sa_family == AF_INET)
  948. {
  949. theSocket4 = CFSocketCreate(NULL, // Default allocator
  950. PF_INET, // Protocol Family
  951. SOCK_STREAM, // Socket Type
  952. IPPROTO_TCP, // Protocol
  953. kCFSocketConnectCallBack, // Callback flags
  954. (CFSocketCallBack)&MyCFSocketCallback, // Callback method
  955. &theContext); // Socket Context
  956. if(theSocket4 == NULL)
  957. {
  958. if (errPtr) *errPtr = [self getSocketError];
  959. return NO;
  960. }
  961. }
  962. else if(pSockAddr->sa_family == AF_INET6)
  963. {
  964. theSocket6 = CFSocketCreate(NULL, // Default allocator
  965. PF_INET6, // Protocol Family
  966. SOCK_STREAM, // Socket Type
  967. IPPROTO_TCP, // Protocol
  968. kCFSocketConnectCallBack, // Callback flags
  969. (CFSocketCallBack)&MyCFSocketCallback, // Callback method
  970. &theContext); // Socket Context
  971. if(theSocket6 == NULL)
  972. {
  973. if (errPtr) *errPtr = [self getSocketError];
  974. return NO;
  975. }
  976. }
  977. else
  978. {
  979. if (errPtr) *errPtr = [self getSocketError];
  980. return NO;
  981. }
  982. return YES;
  983. }
  984. /**
  985. * Adds the CFSocket's to the run-loop so that callbacks will work properly.
  986. **/
  987. - (BOOL)attachSocketsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr
  988. {
  989. // Get the CFRunLoop to which the socket should be attached.
  990. theRunLoop = (runLoop == nil) ? CFRunLoopGetCurrent() : [runLoop getCFRunLoop];
  991. if(theSocket4)
  992. {
  993. theSource4 = CFSocketCreateRunLoopSource (kCFAllocatorDefault, theSocket4, 0);
  994. [self runLoopAddSource:theSource4];
  995. }
  996. if(theSocket6)
  997. {
  998. theSource6 = CFSocketCreateRunLoopSource (kCFAllocatorDefault, theSocket6, 0);
  999. [self runLoopAddSource:theSource6];
  1000. }
  1001. return YES;
  1002. }
  1003. /**
  1004. * Allows the delegate method to configure the CFSocket or CFNativeSocket as desired before we connect.
  1005. * Note that the CFReadStream and CFWriteStream will not be available until after the connection is opened.
  1006. **/
  1007. - (BOOL)configureSocketAndReturnError:(NSError **)errPtr
  1008. {
  1009. // Call the delegate method for further configuration.
  1010. if([theDelegate respondsToSelector:@selector(onSocketWillConnect:)])
  1011. {
  1012. if([theDelegate onSocketWillConnect:self] == NO)
  1013. {
  1014. if (errPtr) *errPtr = [self getAbortError];
  1015. return NO;
  1016. }
  1017. }
  1018. return YES;
  1019. }
  1020. - (BOOL)connectSocketToAddress:(NSData *)remoteAddr error:(NSError **)errPtr
  1021. {
  1022. // Start connecting to the given address in the background
  1023. // The MyCFSocketCallback method will be called when the connection succeeds or fails
  1024. if(theSocket4)
  1025. {
  1026. CFSocketError err = CFSocketConnectToAddress(theSocket4, (CFDataRef)remoteAddr, -1);
  1027. if(err != kCFSocketSuccess)
  1028. {
  1029. if (errPtr) *errPtr = [self getSocketError];
  1030. return NO;
  1031. }
  1032. }
  1033. else if(theSocket6)
  1034. {
  1035. CFSocketError err = CFSocketConnectToAddress(theSocket6, (CFDataRef)remoteAddr, -1);
  1036. if(err != kCFSocketSuccess)
  1037. {
  1038. if (errPtr) *errPtr = [self getSocketError];
  1039. return NO;
  1040. }
  1041. }
  1042. return YES;
  1043. }
  1044. /**
  1045. * Attempt to make the new socket.
  1046. * If an error occurs, ignore this event.
  1047. **/
  1048. - (void)doAcceptFromSocket:(CFSocketRef)parentSocket withNewNativeSocket:(CFSocketNativeHandle)newNativeSocket
  1049. {
  1050. if(newNativeSocket)
  1051. {
  1052. // New socket inherits same delegate and run loop modes.
  1053. // Note: We use [self class] to support subclassing AsyncSocket.
  1054. AsyncSocket *newSocket = [[[[self class] alloc] initWithDelegate:theDelegate] autorelease];
  1055. [newSocket setRunLoopModes:theRunLoopModes];
  1056. if(![newSocket createStreamsFromNative:newNativeSocket error:nil])
  1057. goto Failed;
  1058. if (parentSocket == theSocket4)
  1059. newSocket->theNativeSocket4 = newNativeSocket;
  1060. else
  1061. newSocket->theNativeSocket6 = newNativeSocket;
  1062. if ([theDelegate respondsToSelector:@selector(onSocket:didAcceptNewSocket:)])
  1063. [theDelegate onSocket:self didAcceptNewSocket:newSocket];
  1064. newSocket->theFlags |= kDidStartDelegate;
  1065. NSRunLoop *runLoop = nil;
  1066. if ([theDelegate respondsToSelector:@selector(onSocket:wantsRunLoopForNewSocket:)])
  1067. {
  1068. runLoop = [theDelegate onSocket:self wantsRunLoopForNewSocket:newSocket];
  1069. }
  1070. if(![newSocket attachStreamsToRunLoop:runLoop error:nil]) goto Failed;
  1071. if(![newSocket configureStreamsAndReturnError:nil]) goto Failed;
  1072. if(![newSocket openStreamsAndReturnError:nil]) goto Failed;
  1073. return;
  1074. Failed:
  1075. [newSocket close];
  1076. }
  1077. }
  1078. /**
  1079. * This method is called as a result of connectToAddress:withTimeout:error:.
  1080. * At this point we have an open CFSocket from which we need to create our read and write stream.
  1081. **/
  1082. - (void)doSocketOpen:(CFSocketRef)sock withCFSocketError:(CFSocketError)socketError
  1083. {
  1084. NSParameterAssert ((sock == theSocket4) || (sock == theSocket6));
  1085. if(socketError == kCFSocketTimeout || socketError == kCFSocketError)
  1086. {
  1087. [self closeWithError:[self getSocketError]];
  1088. return;
  1089. }
  1090. // Get the underlying native (BSD) socket
  1091. CFSocketNativeHandle nativeSocket = CFSocketGetNative(sock);
  1092. // Store a reference to it
  1093. if (sock == theSocket4)
  1094. theNativeSocket4 = nativeSocket;
  1095. else
  1096. theNativeSocket6 = nativeSocket;
  1097. // Setup the CFSocket so that invalidating it will not close the underlying native socket
  1098. CFSocketSetSocketFlags(sock, 0);
  1099. // Invalidate and release the CFSocket - All we need from here on out is the nativeSocket.
  1100. // Note: If we don't invalidate the CFSocket (leaving the native socket open)
  1101. // then theReadStream and theWriteStream won't function properly.
  1102. // Specifically, their callbacks won't work, with the exception of kCFStreamEventOpenCompleted.
  1103. //
  1104. // This is likely due to the mixture of the CFSocketCreateWithNative method,
  1105. // along with the CFStreamCreatePairWithSocket method.
  1106. // The documentation for CFSocketCreateWithNative states:
  1107. //
  1108. // If a CFSocket object already exists for sock,
  1109. // the function returns the pre-existing object instead of creating a new object;
  1110. // the context, callout, and callBackTypes parameters are ignored in this case.
  1111. //
  1112. // So the CFStreamCreateWithNative method invokes the CFSocketCreateWithNative method,
  1113. // thinking that is creating a new underlying CFSocket for it's own purposes.
  1114. // When it does this, it uses the context/callout/callbackTypes parameters to setup everything appropriately.
  1115. // However, if a CFSocket already exists for the native socket,
  1116. // then it is returned (as per the documentation), which in turn screws up the CFStreams.
  1117. CFSocketInvalidate(sock);
  1118. CFRelease(sock);
  1119. theSocket4 = NULL;
  1120. theSocket6 = NULL;
  1121. NSError *err;
  1122. BOOL pass = YES;
  1123. if(pass && ![self createStreamsFromNative:nativeSocket error:&err]) pass = NO;
  1124. if(pass && ![self attachStreamsToRunLoop:nil error:&err]) pass = NO;
  1125. if(pass && ![self openStreamsAndReturnError:&err]) pass = NO;
  1126. if(!pass)
  1127. {
  1128. [self closeWithError:err];
  1129. }
  1130. }
  1131. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1132. #pragma mark Stream Implementation
  1133. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1134. /**
  1135. * Creates the CFReadStream and CFWriteStream from the given native socket.
  1136. * The CFSocket may be extracted from either stream after the streams have been opened.
  1137. *
  1138. * Note: The given native socket must already be connected!
  1139. **/
  1140. - (BOOL)createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr
  1141. {
  1142. // Create the socket & streams.
  1143. CFStreamCreatePairWithSocket(kCFAllocatorDefault, native, &theReadStream, &theWriteStream);
  1144. if (theReadStream == NULL || theWriteStream == NULL)
  1145. {
  1146. NSError *err = [self getStreamError];
  1147. NSLog(@"AsyncSocket %p couldn't create streams from accepted socket: %@", self, err);
  1148. if (errPtr) *errPtr = err;
  1149. return NO;
  1150. }
  1151. // Ensure the CF & BSD socket is closed when the streams are closed.
  1152. CFReadStreamSetProperty(theReadStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
  1153. CFWriteStreamSetProperty(theWriteStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
  1154. return YES;
  1155. }
  1156. /**
  1157. * Creates the CFReadStream and CFWriteStream from the given hostname and port number.
  1158. * The CFSocket may be extracted from either stream after the streams have been opened.
  1159. **/
  1160. - (BOOL)createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr
  1161. {
  1162. // Create the socket & streams.
  1163. CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)hostname, port, &theReadStream, &theWriteStream);
  1164. if (theReadStream == NULL || theWriteStream == NULL)
  1165. {
  1166. if (errPtr) *errPtr = [self getStreamError];
  1167. return NO;
  1168. }
  1169. // Ensure the CF & BSD socket is closed when the streams are closed.
  1170. CFReadStreamSetProperty(theReadStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
  1171. CFWriteStreamSetProperty(theWriteStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
  1172. return YES;
  1173. }
  1174. - (BOOL)attachStreamsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr
  1175. {
  1176. // Get the CFRunLoop to which the socket should be attached.
  1177. theRunLoop = (runLoop == nil) ? CFRunLoopGetCurrent() : [runLoop getCFRunLoop];
  1178. // Setup read stream callbacks
  1179. CFOptionFlags readStreamEvents = kCFStreamEventHasBytesAvailable |
  1180. kCFStreamEventErrorOccurred |
  1181. kCFStreamEventEndEncountered |
  1182. kCFStreamEventOpenCompleted;
  1183. if (!CFReadStreamSetClient(theReadStream,
  1184. readStreamEvents,
  1185. (CFReadStreamClientCallBack)&MyCFReadStreamCallback,
  1186. (CFStreamClientContext *)(&theContext)))
  1187. {
  1188. NSError *err = [self getStreamError];
  1189. NSLog (@"AsyncSocket %p couldn't attach read stream to run-loop,", self);
  1190. NSLog (@"Error: %@", err);
  1191. if (errPtr) *errPtr = err;
  1192. return NO;
  1193. }
  1194. // Setup write stream callbacks
  1195. CFOptionFlags writeStreamEvents = kCFStreamEventCanAcceptBytes |
  1196. kCFStreamEventErrorOccurred |
  1197. kCFStreamEventEndEncountered |
  1198. kCFStreamEventOpenCompleted;
  1199. if (!CFWriteStreamSetClient (theWriteStream,
  1200. writeStreamEvents,
  1201. (CFWriteStreamClientCallBack)&MyCFWriteStreamCallback,
  1202. (CFStreamClientContext *)(&theContext)))
  1203. {
  1204. NSError *err = [self getStreamError];
  1205. NSLog (@"AsyncSocket %p couldn't attach write stream to run-loop,", self);
  1206. NSLog (@"Error: %@", err);
  1207. if (errPtr) *errPtr = err;
  1208. return NO;
  1209. }
  1210. // Add read and write streams to run loop
  1211. NSUInteger i, count = [theRunLoopModes count];
  1212. for(i = 0; i < count; i++)
  1213. {
  1214. CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i];
  1215. CFReadStreamScheduleWithRunLoop(theReadStream, theRunLoop, runLoopMode);
  1216. CFWriteStreamScheduleWithRunLoop(theWriteStream, theRunLoop, runLoopMode);
  1217. }
  1218. return YES;
  1219. }
  1220. /**
  1221. * Allows the delegate method to configure the CFReadStream and/or CFWriteStream as desired before we connect.
  1222. *
  1223. * If being called from a connect method,
  1224. * the CFSocket and CFNativeSocket will not be available until after the connection is opened.
  1225. **/
  1226. - (BOOL)configureStreamsAndReturnError:(NSError **)errPtr
  1227. {
  1228. // Call the delegate method for further configuration.
  1229. if([theDelegate respondsToSelector:@selector(onSocketWillConnect:)])
  1230. {
  1231. if([theDelegate onSocketWillConnect:self] == NO)
  1232. {
  1233. if (errPtr) *errPtr = [self getAbortError];
  1234. return NO;
  1235. }
  1236. }
  1237. return YES;
  1238. }
  1239. - (BOOL)openStreamsAndReturnError:(NSError **)errPtr
  1240. {
  1241. BOOL pass = YES;
  1242. if(pass && !CFReadStreamOpen(theReadStream))
  1243. {
  1244. NSLog (@"AsyncSocket %p couldn't open read stream,", self);
  1245. pass = NO;
  1246. }
  1247. if(pass && !CFWriteStreamOpen(theWriteStream))
  1248. {
  1249. NSLog (@"AsyncSocket %p couldn't open write stream,", self);
  1250. pass = NO;
  1251. }
  1252. if(!pass)
  1253. {
  1254. if (errPtr) *errPtr = [self getStreamError];
  1255. }
  1256. return pass;
  1257. }
  1258. /**
  1259. * Called when read or write streams open.
  1260. * When the socket is connected and both streams are open, consider the AsyncSocket instance to be ready.
  1261. **/
  1262. - (void)doStreamOpen
  1263. {
  1264. if ((theFlags & kDidCompleteOpenForRead) && (theFlags & kDidCompleteOpenForWrite))
  1265. {
  1266. NSError *err = nil;
  1267. // Get the socket
  1268. if (![self setSocketFromStreamsAndReturnError: &err])
  1269. {
  1270. NSLog (@"AsyncSocket %p couldn't get socket from streams, %@. Disconnecting.", self, err);
  1271. [self closeWithError:err];
  1272. return;
  1273. }
  1274. // Stop the connection attempt timeout timer
  1275. [self endConnectTimeout];
  1276. if ([theDelegate respondsToSelector:@selector(onSocket:didConnectToHost:port:)])
  1277. {
  1278. [theDelegate onSocket:self didConnectToHost:[self connectedHost] port:[self connectedPort]];
  1279. }
  1280. // Immediately deal with any already-queued requests.
  1281. [self maybeDequeueRead];
  1282. [self maybeDequeueWrite];
  1283. }
  1284. }
  1285. - (BOOL)setSocketFromStreamsAndReturnError:(NSError **)errPtr
  1286. {
  1287. // Get the CFSocketNativeHandle from theReadStream
  1288. CFSocketNativeHandle native;
  1289. CFDataRef nativeProp = CFReadStreamCopyProperty(theReadStream, kCFStreamPropertySocketNativeHandle);
  1290. if(nativeProp == NULL)
  1291. {
  1292. if (errPtr) *errPtr = [self getStreamError];
  1293. return NO;
  1294. }
  1295. CFIndex len = MIN(CFDataGetLength(nativeProp), sizeof(native));
  1296. CFDataGetBytes(nativeProp, CFRangeMake(0, len), (UInt8 *)&native);
  1297. CFRelease(nativeProp);
  1298. CFSocketRef theSocket = CFSocketCreateWithNative(kCFAllocatorDefault, native, 0, NULL, NULL);
  1299. if(theSocket == NULL)
  1300. {
  1301. if (errPtr) *errPtr = [self getSocketError];
  1302. return NO;
  1303. }
  1304. // Determine whether the connection was IPv4 or IPv6.
  1305. // We may already know if this was an accepted socket,
  1306. // or if the connectToAddress method was used.
  1307. // In either of the above two cases, the native socket variable would already be set.
  1308. if (theNativeSocket4 > 0)
  1309. {
  1310. theSocket4 = theSocket;
  1311. return YES;
  1312. }
  1313. if (theNativeSocket6 > 0)
  1314. {
  1315. theSocket6 = theSocket;
  1316. return YES;
  1317. }
  1318. CFDataRef peeraddr = CFSocketCopyPeerAddress(theSocket);
  1319. if(peeraddr == NULL)
  1320. {
  1321. NSLog(@"AsyncSocket couldn't determine IP version of socket");
  1322. CFRelease(theSocket);
  1323. if (errPtr) *errPtr = [self getSocketError];
  1324. return NO;
  1325. }
  1326. struct sockaddr *sa = (struct sockaddr *)CFDataGetBytePtr(peeraddr);
  1327. if(sa->sa_family == AF_INET)
  1328. {
  1329. theSocket4 = theSocket;
  1330. theNativeSocket4 = native;
  1331. }
  1332. else
  1333. {
  1334. theSocket6 = theSocket;
  1335. theNativeSocket6 = native;
  1336. }
  1337. CFRelease(peeraddr);
  1338. return YES;
  1339. }
  1340. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1341. #pragma mark Disconnect Implementation
  1342. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1343. // Sends error message and disconnects
  1344. - (void)closeWithError:(NSError *)err
  1345. {
  1346. theFlags |= kClosingWithError;
  1347. if (theFlags & kDidStartDelegate)
  1348. {
  1349. // Try to salvage what data we can.
  1350. [self recoverUnreadData];
  1351. // Let the delegate know, so it can try to recover if it likes.
  1352. if ([theDelegate respondsToSelector:@selector(onSocket:willDisconnectWithError:)])
  1353. {
  1354. [theDelegate onSocket:self willDisconnectWithError:err];
  1355. }
  1356. }
  1357. [self close];
  1358. }
  1359. // Prepare partially read data for recovery.
  1360. - (void)recoverUnreadData
  1361. {
  1362. if(theCurrentRead != nil)
  1363. {
  1364. // We never finished the current read.
  1365. // Check to see if it's a normal read packet (not AsyncSpecialPacket) and if it had read anything yet.
  1366. if(([theCurrentRead isKindOfClass:[AsyncReadPacket class]]) && (theCurrentRead->bytesDone > 0))
  1367. {
  1368. // We need to move its data into the front of the partial read buffer.
  1369. [partialReadBuffer replaceBytesInRange:NSMakeRange(0, 0)
  1370. withBytes:[theCurrentRead->buffer bytes]
  1371. length:theCurrentRead->bytesDone];
  1372. }
  1373. }
  1374. [self emptyQueues];
  1375. }
  1376. - (void)emptyQueues
  1377. {
  1378. if (theCurrentRead != nil) [self endCurrentRead];
  1379. if (theCurrentWrite != nil) [self endCurrentWrite];
  1380. [theReadQueue removeAllObjects];
  1381. [theWriteQueue removeAllObjects];
  1382. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(maybeDequeueRead) object:nil];
  1383. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(maybeDequeueWrite) object:nil];
  1384. theFlags &= ~kDequeueReadScheduled;
  1385. theFlags &= ~kDequeueWriteScheduled;
  1386. }
  1387. /**
  1388. * Disconnects. This is called for both error and clean disconnections.
  1389. **/
  1390. - (void)close
  1391. {
  1392. // Empty queues
  1393. [self emptyQueues];
  1394. // Clear partialReadBuffer (pre-buffer and also unreadData buffer in case of error)
  1395. [partialReadBuffer replaceBytesInRange:NSMakeRange(0, [partialReadBuffer length]) withBytes:NULL length:0];
  1396. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(disconnect) object:nil];
  1397. // Stop the connection attempt timeout timer
  1398. if (theConnectTimer != nil)
  1399. {
  1400. [self endConnectTimeout];
  1401. }
  1402. // Close streams.
  1403. if (theReadStream != NULL)
  1404. {
  1405. [self runLoopUnscheduleReadStream];
  1406. CFReadStreamClose(theReadStream);
  1407. CFRelease(theReadStream);
  1408. theReadStream = NULL;
  1409. }
  1410. if (theWriteStream != NULL)
  1411. {
  1412. [self runLoopUnscheduleWriteStream];
  1413. CFWriteStreamClose(theWriteStream);
  1414. CFRelease(theWriteStream);
  1415. theWriteStream = NULL;
  1416. }
  1417. // Close sockets.
  1418. if (theSocket4 != NULL)
  1419. {
  1420. CFSocketInvalidate (theSocket4);
  1421. CFRelease (theSocket4);
  1422. theSocket4 = NULL;
  1423. }
  1424. if (theSocket6 != NULL)
  1425. {
  1426. CFSocketInvalidate (theSocket6);
  1427. CFRelease (theSocket6);
  1428. theSocket6 = NULL;
  1429. }
  1430. // Closing the streams or sockets resulted in closing the underlying native socket
  1431. theNativeSocket4 = 0;
  1432. theNativeSocket6 = 0;
  1433. // Remove run loop sources
  1434. if (theSource4 != NULL)
  1435. {
  1436. [self runLoopRemoveSource:theSource4];
  1437. CFRelease (theSource4);
  1438. theSource4 = NULL;
  1439. }
  1440. if (theSource6 != NULL)
  1441. {
  1442. [self runLoopRemoveSource:theSource6];
  1443. CFRelease (theSource6);
  1444. theSource6 = NULL;
  1445. }
  1446. theRunLoop = NULL;
  1447. // If the client has passed the connect/accept method, then the connection has at least begun.
  1448. // Notify delegate that it is now ending.
  1449. BOOL shouldCallDelegate = (theFlags & kDidStartDelegate);
  1450. // Clear all flags (except the pre-buffering flag, which should remain as is)
  1451. theFlags &= kEnablePreBuffering;
  1452. if (shouldCallDelegate)
  1453. {
  1454. if ([theDelegate respondsToSelector: @selector(onSocketDidDisconnect:)])
  1455. {
  1456. [theDelegate onSocketDidDisconnect:self];
  1457. }
  1458. }
  1459. // Do not access any instance variables after calling onSocketDidDisconnect.
  1460. // This gives the delegate freedom to release us without returning here and crashing.
  1461. }
  1462. /**
  1463. * Disconnects immediately. Any pending reads or writes are dropped.
  1464. **/
  1465. - (void)disconnect
  1466. {
  1467. [self close];
  1468. }
  1469. /**
  1470. * Diconnects after all pending reads have completed.
  1471. **/
  1472. - (void)disconnectAfterReading
  1473. {
  1474. theFlags |= (kForbidReadsWrites | kDisconnectAfterReads);
  1475. [self maybeScheduleDisconnect];
  1476. }
  1477. /**
  1478. * Disconnects after all pending writes have completed.
  1479. **/
  1480. - (void)disconnectAfterWriting
  1481. {
  1482. theFlags |= (kForbidReadsWrites | kDisconnectAfterWrites);
  1483. [self maybeScheduleDisconnect];
  1484. }
  1485. /**
  1486. * Disconnects after all pending reads and writes have completed.
  1487. **/
  1488. - (void)disconnectAfterReadingAndWriting
  1489. {
  1490. theFlags |= (kForbidReadsWrites | kDisconnectAfterReads | kDisconnectAfterWrites);
  1491. [self maybeScheduleDisconnect];
  1492. }
  1493. /**
  1494. * Schedules a call to disconnect if possible.
  1495. * That is, if all writes have completed, and we're set to disconnect after writing,
  1496. * or if all reads have completed, and we're set to disconnect after reading.
  1497. **/
  1498. - (void)maybeScheduleDisconnect
  1499. {
  1500. BOOL shouldDisconnect = NO;
  1501. if(theFlags & kDisconnectAfterReads)
  1502. {
  1503. if(([theReadQueue count] == 0) && (theCurrentRead == nil))
  1504. {
  1505. if(theFlags & kDisconnectAfterWrites)
  1506. {
  1507. if(([theWriteQueue count] == 0) && (theCurrentWrite == nil))
  1508. {
  1509. shouldDisconnect = YES;
  1510. }
  1511. }
  1512. else
  1513. {
  1514. shouldDisconnect = YES;
  1515. }
  1516. }
  1517. }
  1518. else if(theFlags & kDisconnectAfterWrites)
  1519. {
  1520. if(([theWriteQueue count] == 0) && (theCurrentWrite == nil))
  1521. {
  1522. shouldDisconnect = YES;
  1523. }
  1524. }
  1525. if(shouldDisconnect)
  1526. {
  1527. [self performSelector:@selector(disconnect) withObject:nil afterDelay:0 inModes:theRunLoopModes];
  1528. }
  1529. }
  1530. /**
  1531. * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read
  1532. * any data that's left on the socket.
  1533. **/
  1534. - (NSData *)unreadData
  1535. {
  1536. // Ensure this method will only return data in the event of an error
  1537. if(!(theFlags & kClosingWithError)) return nil;
  1538. if(theReadStream == NULL) return nil;
  1539. CFIndex totalBytesRead = [partialReadBuffer length];
  1540. BOOL error = NO;
  1541. while(!error && CFReadStreamHasBytesAvailable(theReadStream))
  1542. {
  1543. [partialReadBuffer increaseLengthBy:READALL_CHUNKSIZE];
  1544. // Number of bytes to read is space left in packet buffer.
  1545. CFIndex bytesToRead = [partialReadBuffer length] - totalBytesRead;
  1546. // Read data into packet buffer
  1547. UInt8 *packetbuf = (UInt8 *)( [partialReadBuffer mutableBytes] + totalBytesRead );
  1548. CFIndex bytesRead = CFReadStreamRead(theReadStream, packetbuf, bytesToRead);
  1549. // Check results
  1550. if(bytesRead < 0)
  1551. {
  1552. error = YES;
  1553. }
  1554. else
  1555. {
  1556. totalBytesRead += bytesRead;
  1557. }
  1558. }
  1559. [partialReadBuffer setLength:totalBytesRead];
  1560. return partialReadBuffer;
  1561. }
  1562. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1563. #pragma mark Errors
  1564. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1565. /**
  1566. * Returns a standard error object for the current errno value.
  1567. * Errno is used for low-level BSD socket errors.
  1568. **/
  1569. - (NSError *)getErrnoError
  1570. {
  1571. NSString *errorMsg = [NSString stringWithUTF8String:strerror(errno)];
  1572. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errorMsg forKey:NSLocalizedDescriptionKey];
  1573. return [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:userInfo];
  1574. }
  1575. /**
  1576. * Returns a standard error message for a CFSocket error.
  1577. * Unfortunately, CFSocket offers no feedback on its errors.
  1578. **/
  1579. - (NSError *)getSocketError
  1580. {
  1581. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketCFSocketError",
  1582. @"AsyncSocket", [NSBundle mainBundle],
  1583. @"General CFSocket error", nil);
  1584. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1585. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCFSocketError userInfo:info];
  1586. }
  1587. - (NSError *)getStreamError
  1588. {
  1589. CFStreamError err;
  1590. if (theReadStream != NULL)
  1591. {
  1592. err = CFReadStreamGetError (theReadStream);
  1593. if (err.error != 0) return [self errorFromCFStreamError: err];
  1594. }
  1595. if (theWriteStream != NULL)
  1596. {
  1597. err = CFWriteStreamGetError (theWriteStream);
  1598. if (err.error != 0) return [self errorFromCFStreamError: err];
  1599. }
  1600. return nil;
  1601. }
  1602. /**
  1603. * Returns a standard AsyncSocket abort error.
  1604. **/
  1605. - (NSError *)getAbortError
  1606. {
  1607. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketCanceledError",
  1608. @"AsyncSocket", [NSBundle mainBundle],
  1609. @"Connection canceled", nil);
  1610. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1611. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCanceledError userInfo:info];
  1612. }
  1613. /**
  1614. * Returns a standard AsyncSocket connect timeout error.
  1615. **/
  1616. - (NSError *)getConnectTimeoutError
  1617. {
  1618. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketConnectTimeoutError",
  1619. @"AsyncSocket", [NSBundle mainBundle],
  1620. @"Attempt to connect to host timed out", nil);
  1621. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1622. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketConnectTimeoutError userInfo:info];
  1623. }
  1624. /**
  1625. * Returns a standard AsyncSocket maxed out error.
  1626. **/
  1627. - (NSError *)getReadMaxedOutError
  1628. {
  1629. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketReadMaxedOutError",
  1630. @"AsyncSocket", [NSBundle mainBundle],
  1631. @"Read operation reached set maximum length", nil);
  1632. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1633. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketReadMaxedOutError userInfo:info];
  1634. }
  1635. /**
  1636. * Returns a standard AsyncSocket read timeout error.
  1637. **/
  1638. - (NSError *)getReadTimeoutError
  1639. {
  1640. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketReadTimeoutError",
  1641. @"AsyncSocket", [NSBundle mainBundle],
  1642. @"Read operation timed out", nil);
  1643. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1644. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketReadTimeoutError userInfo:info];
  1645. }
  1646. /**
  1647. * Returns a standard AsyncSocket write timeout error.
  1648. **/
  1649. - (NSError *)getWriteTimeoutError
  1650. {
  1651. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketWriteTimeoutError",
  1652. @"AsyncSocket", [NSBundle mainBundle],
  1653. @"Write operation timed out", nil);
  1654. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1655. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketWriteTimeoutError userInfo:info];
  1656. }
  1657. - (NSError *)errorFromCFStreamError:(CFStreamError)err
  1658. {
  1659. if (err.domain == 0 && err.error == 0) return nil;
  1660. // Can't use switch; these constants aren't int literals.
  1661. NSString *domain = @"CFStreamError (unlisted domain)";
  1662. NSString *message = nil;
  1663. if(err.domain == kCFStreamErrorDomainPOSIX) {
  1664. domain = NSPOSIXErrorDomain;
  1665. }
  1666. else if(err.domain == kCFStreamErrorDomainMacOSStatus) {
  1667. domain = NSOSStatusErrorDomain;
  1668. }
  1669. else if(err.domain == kCFStreamErrorDomainMach) {
  1670. domain = NSMachErrorDomain;
  1671. }
  1672. else if(err.domain == kCFStreamErrorDomainNetDB)
  1673. {
  1674. domain = @"kCFStreamErrorDomainNetDB";
  1675. message = [NSString stringWithCString:gai_strerror(err.error) encoding:NSASCIIStringEncoding];
  1676. }
  1677. else if(err.domain == kCFStreamErrorDomainNetServices) {
  1678. domain = @"kCFStreamErrorDomainNetServices";
  1679. }
  1680. else if(err.domain == kCFStreamErrorDomainSOCKS) {
  1681. domain = @"kCFStreamErrorDomainSOCKS";
  1682. }
  1683. else if(err.domain == kCFStreamErrorDomainSystemConfiguration) {
  1684. domain = @"kCFStreamErrorDomainSystemConfiguration";
  1685. }
  1686. else if(err.domain == kCFStreamErrorDomainSSL) {
  1687. domain = @"kCFStreamErrorDomainSSL";
  1688. }
  1689. NSDictionary *info = nil;
  1690. if(message != nil)
  1691. {
  1692. info = [NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey];
  1693. }
  1694. return [NSError errorWithDomain:domain code:err.error userInfo:info];
  1695. }
  1696. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1697. #pragma mark Diagnostics
  1698. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1699. - (BOOL)isDisconnected
  1700. {
  1701. if (theNativeSocket4 > 0) return NO;
  1702. if (theNativeSocket6 > 0) return NO;
  1703. if (theSocket4) return NO;
  1704. if (theSocket6) return NO;
  1705. if (theReadStream) return NO;
  1706. if (theWriteStream) return NO;
  1707. return YES;
  1708. }
  1709. - (BOOL)isConnected
  1710. {
  1711. return [self areStreamsConnected];
  1712. }
  1713. - (NSString *)connectedHost
  1714. {
  1715. if(theSocket4)
  1716. return [self connectedHostFromCFSocket4:theSocket4];
  1717. if(theSocket6)
  1718. return [self connectedHostFromCFSocket6:theSocket6];
  1719. if(theNativeSocket4 > 0)
  1720. return [self connectedHostFromNativeSocket4:theNativeSocket4];
  1721. if(theNativeSocket6 > 0)
  1722. return [self connectedHostFromNativeSocket6:theNativeSocket6];
  1723. return nil;
  1724. }
  1725. - (UInt16)connectedPort
  1726. {
  1727. if(theSocket4)
  1728. return [self connectedPortFromCFSocket4:theSocket4];
  1729. if(theSocket6)
  1730. return [self connectedPortFromCFSocket6:theSocket6];
  1731. if(theNativeSocket4 > 0)
  1732. return [self connectedPortFromNativeSocket4:theNativeSocket4];
  1733. if(theNativeSocket6 > 0)
  1734. return [self connectedPortFromNativeSocket6:theNativeSocket6];
  1735. return 0;
  1736. }
  1737. - (NSString *)localHost
  1738. {
  1739. if(theSocket4)
  1740. return [self localHostFromCFSocket4:theSocket4];
  1741. if(theSocket6)
  1742. return [self localHostFromCFSocket6:theSocket6];
  1743. if(theNativeSocket4 > 0)
  1744. return [self localHostFromNativeSocket4:theNativeSocket4];
  1745. if(theNativeSocket6 > 0)
  1746. return [self localHostFromNativeSocket6:theNativeSocket6];
  1747. return nil;
  1748. }
  1749. - (UInt16)localPort
  1750. {
  1751. if(theSocket4)
  1752. return [self localPortFromCFSocket4:theSocket4];
  1753. if(theSocket6)
  1754. return [self localPortFromCFSocket6:theSocket6];
  1755. if(theNativeSocket4 > 0)
  1756. return [self localPortFromNativeSocket4:theNativeSocket4];
  1757. if(theNativeSocket6 > 0)
  1758. return [self localPortFromNativeSocket6:theNativeSocket6];
  1759. return 0;
  1760. }
  1761. - (NSString *)connectedHost4
  1762. {
  1763. if(theSocket4)
  1764. return [self connectedHostFromCFSocket4:theSocket4];
  1765. if(theNativeSocket4 > 0)
  1766. return [self connectedHostFromNativeSocket4:theNativeSocket4];
  1767. return nil;
  1768. }
  1769. - (NSString *)connectedHost6
  1770. {
  1771. if(theSocket6)
  1772. return [self connectedHostFromCFSocket6:theSocket6];
  1773. if(theNativeSocket6 > 0)
  1774. return [self connectedHostFromNativeSocket6:theNativeSocket6];
  1775. return nil;
  1776. }
  1777. - (UInt16)connectedPort4
  1778. {
  1779. if(theSocket4)
  1780. return [self connectedPortFromCFSocket4:theSocket4];
  1781. if(theNativeSocket4 > 0)
  1782. return [self connectedPortFromNativeSocket4:theNativeSocket4];
  1783. return 0;
  1784. }
  1785. - (UInt16)connectedPort6
  1786. {
  1787. if(theSocket6)
  1788. return [self connectedPortFromCFSocket6:theSocket6];
  1789. if(theNativeSocket6 > 0)
  1790. return [self connectedPortFromNativeSocket6:theNativeSocket6];
  1791. return 0;
  1792. }
  1793. - (NSString *)localHost4
  1794. {
  1795. if(theSocket4)
  1796. return [self localHostFromCFSocket4:theSocket4];
  1797. if(theNativeSocket4 > 0)
  1798. return [self localHostFromNativeSocket4:theNativeSocket4];
  1799. return nil;
  1800. }
  1801. - (NSString *)localHost6
  1802. {
  1803. if(theSocket6)
  1804. return [self localHostFromCFSocket6:theSocket6];
  1805. if(theNativeSocket6 > 0)
  1806. return [self localHostFromNativeSocket6:theNativeSocket6];
  1807. return nil;
  1808. }
  1809. - (UInt16)localPort4
  1810. {
  1811. if(theSocket4)
  1812. return [self localPortFromCFSocket4:theSocket4];
  1813. if(theNativeSocket4 > 0)
  1814. return [self localPortFromNativeSocket4:theNativeSocket4];
  1815. return 0;
  1816. }
  1817. - (UInt16)localPort6
  1818. {
  1819. if(theSocket6)
  1820. return [self localPortFromCFSocket6:theSocket6];
  1821. if(theNativeSocket6 > 0)
  1822. return [self localPortFromNativeSocket6:theNativeSocket6];
  1823. return 0;
  1824. }
  1825. - (NSString *)connectedHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket
  1826. {
  1827. struct sockaddr_in sockaddr4;
  1828. socklen_t sockaddr4len = sizeof(sockaddr4);
  1829. if(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  1830. {
  1831. return nil;
  1832. }
  1833. return [self hostFromAddress4:&sockaddr4];
  1834. }
  1835. - (NSString *)connectedHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket
  1836. {
  1837. struct sockaddr_in6 sockaddr6;
  1838. socklen_t sockaddr6len = sizeof(sockaddr6);
  1839. if(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  1840. {
  1841. return nil;
  1842. }
  1843. return [self hostFromAddress6:&sockaddr6];
  1844. }
  1845. - (NSString *)connectedHostFromCFSocket4:(CFSocketRef)theSocket
  1846. {
  1847. CFDataRef peeraddr;
  1848. NSString *peerstr = nil;
  1849. if((peeraddr = CFSocketCopyPeerAddress(theSocket)))
  1850. {
  1851. struct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(peeraddr);
  1852. peerstr = [self hostFromAddress4:pSockAddr];
  1853. CFRelease (peeraddr);
  1854. }
  1855. return peerstr;
  1856. }
  1857. - (NSString *)connectedHostFromCFSocket6:(CFSocketRef)theSocket
  1858. {
  1859. CFDataRef peeraddr;
  1860. NSString *peerstr = nil;
  1861. if((peeraddr = CFSocketCopyPeerAddress(theSocket)))
  1862. {
  1863. struct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(peeraddr);
  1864. peerstr = [self hostFromAddress6:pSockAddr];
  1865. CFRelease (peeraddr);
  1866. }
  1867. return peerstr;
  1868. }
  1869. - (UInt16)connectedPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket
  1870. {
  1871. struct sockaddr_in sockaddr4;
  1872. socklen_t sockaddr4len = sizeof(sockaddr4);
  1873. if(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  1874. {
  1875. return 0;
  1876. }
  1877. return [self portFromAddress4:&sockaddr4];
  1878. }
  1879. - (UInt16)connectedPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket
  1880. {
  1881. struct sockaddr_in6 sockaddr6;
  1882. socklen_t sockaddr6len = sizeof(sockaddr6);
  1883. if(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  1884. {
  1885. return 0;
  1886. }
  1887. return [self portFromAddress6:&sockaddr6];
  1888. }
  1889. - (UInt16)connectedPortFromCFSocket4:(CFSocketRef)theSocket
  1890. {
  1891. CFDataRef peeraddr;
  1892. UInt16 peerport = 0;
  1893. if((peeraddr = CFSocketCopyPeerAddress(theSocket)))
  1894. {
  1895. struct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(peeraddr);
  1896. peerport = [self portFromAddress4:pSockAddr];
  1897. CFRelease (peeraddr);
  1898. }
  1899. return peerport;
  1900. }
  1901. - (UInt16)connectedPortFromCFSocket6:(CFSocketRef)theSocket
  1902. {
  1903. CFDataRef peeraddr;
  1904. UInt16 peerport = 0;
  1905. if((peeraddr = CFSocketCopyPeerAddress(theSocket)))
  1906. {
  1907. struct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(peeraddr);
  1908. peerport = [self portFromAddress6:pSockAddr];
  1909. CFRelease (peeraddr);
  1910. }
  1911. return peerport;
  1912. }
  1913. - (NSString *)localHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket
  1914. {
  1915. struct sockaddr_in sockaddr4;
  1916. socklen_t sockaddr4len = sizeof(sockaddr4);
  1917. if(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  1918. {
  1919. return nil;
  1920. }
  1921. return [self hostFromAddress4:&sockaddr4];
  1922. }
  1923. - (NSString *)localHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket
  1924. {
  1925. struct sockaddr_in6 sockaddr6;
  1926. socklen_t sockaddr6len = sizeof(sockaddr6);
  1927. if(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  1928. {
  1929. return nil;
  1930. }
  1931. return [self hostFromAddress6:&sockaddr6];
  1932. }
  1933. - (NSString *)localHostFromCFSocket4:(CFSocketRef)theSocket
  1934. {
  1935. CFDataRef selfaddr;
  1936. NSString *selfstr = nil;
  1937. if((selfaddr = CFSocketCopyAddress(theSocket)))
  1938. {
  1939. struct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(selfaddr);
  1940. selfstr = [self hostFromAddress4:pSockAddr];
  1941. CFRelease (selfaddr);
  1942. }
  1943. return selfstr;
  1944. }
  1945. - (NSString *)localHostFromCFSocket6:(CFSocketRef)theSocket
  1946. {
  1947. CFDataRef selfaddr;
  1948. NSString *selfstr = nil;
  1949. if((selfaddr = CFSocketCopyAddress(theSocket)))
  1950. {
  1951. struct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(selfaddr);
  1952. selfstr = [self hostFromAddress6:pSockAddr];
  1953. CFRelease (selfaddr);
  1954. }
  1955. return selfstr;
  1956. }
  1957. - (UInt16)localPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket
  1958. {
  1959. struct sockaddr_in sockaddr4;
  1960. socklen_t sockaddr4len = sizeof(sockaddr4);
  1961. if(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  1962. {
  1963. return 0;
  1964. }
  1965. return [self portFromAddress4:&sockaddr4];
  1966. }
  1967. - (UInt16)localPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket
  1968. {
  1969. struct sockaddr_in6 sockaddr6;
  1970. socklen_t sockaddr6len = sizeof(sockaddr6);
  1971. if(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  1972. {
  1973. return 0;
  1974. }
  1975. return [self portFromAddress6:&sockaddr6];
  1976. }
  1977. - (UInt16)localPortFromCFSocket4:(CFSocketRef)theSocket
  1978. {
  1979. CFDataRef selfaddr;
  1980. UInt16 selfport = 0;
  1981. if ((selfaddr = CFSocketCopyAddress(theSocket)))
  1982. {
  1983. struct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(selfaddr);
  1984. selfport = [self portFromAddress4:pSockAddr];
  1985. CFRelease (selfaddr);
  1986. }
  1987. return selfport;
  1988. }
  1989. - (UInt16)localPortFromCFSocket6:(CFSocketRef)theSocket
  1990. {
  1991. CFDataRef selfaddr;
  1992. UInt16 selfport = 0;
  1993. if ((selfaddr = CFSocketCopyAddress(theSocket)))
  1994. {
  1995. struct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(selfaddr);
  1996. selfport = [self portFromAddress6:pSockAddr];
  1997. CFRelease (selfaddr);
  1998. }
  1999. return selfport;
  2000. }
  2001. - (NSString *)hostFromAddress4:(struct sockaddr_in *)pSockaddr4
  2002. {
  2003. char addrBuf[INET_ADDRSTRLEN];
  2004. if(inet_ntop(AF_INET, &pSockaddr4->sin_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL)
  2005. {
  2006. [NSException raise:NSInternalInconsistencyException format:@"Cannot convert IPv4 address to string."];
  2007. }
  2008. return [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding];
  2009. }
  2010. - (NSString *)hostFromAddress6:(struct sockaddr_in6 *)pSockaddr6
  2011. {
  2012. char addrBuf[INET6_ADDRSTRLEN];
  2013. if(inet_ntop(AF_INET6, &pSockaddr6->sin6_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL)
  2014. {
  2015. [NSException raise:NSInternalInconsistencyException format:@"Cannot convert IPv6 address to string."];
  2016. }
  2017. return [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding];
  2018. }
  2019. - (UInt16)portFromAddress4:(struct sockaddr_in *)pSockaddr4
  2020. {
  2021. return ntohs(pSockaddr4->sin_port);
  2022. }
  2023. - (UInt16)portFromAddress6:(struct sockaddr_in6 *)pSockaddr6
  2024. {
  2025. return ntohs(pSockaddr6->sin6_port);
  2026. }
  2027. - (NSData *)connectedAddress
  2028. {
  2029. // Extract address from CFSocket
  2030. CFSocketRef theSocket;
  2031. if (theSocket4)
  2032. theSocket = theSocket4;
  2033. else
  2034. theSocket = theSocket6;
  2035. if (theSocket)
  2036. {
  2037. CFDataRef peeraddr = CFSocketCopyPeerAddress(theSocket);
  2038. if (peeraddr == NULL) return nil;
  2039. #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  2040. NSData *result = [NSData dataWithBytes:CFDataGetBytePtr(peeraddr) length:CFDataGetLength(peeraddr)];
  2041. CFRelease(peeraddr);
  2042. return result;
  2043. #else
  2044. return [(NSData *)NSMakeCollectable(peeraddr) autorelease];
  2045. #endif
  2046. }
  2047. // Extract address from CFSocketNativeHandle
  2048. socklen_t sockaddrlen;
  2049. CFSocketNativeHandle theNativeSocket = 0;
  2050. if (theNativeSocket4 > 0)
  2051. {
  2052. theNativeSocket = theNativeSocket4;
  2053. sockaddrlen = sizeof(struct sockaddr_in);
  2054. }
  2055. else
  2056. {
  2057. theNativeSocket = theNativeSocket6;
  2058. sockaddrlen = sizeof(struct sockaddr_in6);
  2059. }
  2060. NSData *result = nil;
  2061. void *sockaddr = malloc(sockaddrlen);
  2062. if(getpeername(theNativeSocket, (struct sockaddr *)sockaddr, &sockaddrlen) >= 0)
  2063. {
  2064. result = [NSData dataWithBytesNoCopy:sockaddr length:sockaddrlen freeWhenDone:YES];
  2065. }
  2066. else
  2067. {
  2068. free(sockaddr);
  2069. }
  2070. return result;
  2071. }
  2072. - (NSData *)localAddress
  2073. {
  2074. // Extract address from CFSocket
  2075. CFSocketRef theSocket;
  2076. if (theSocket4)
  2077. theSocket = theSocket4;
  2078. else
  2079. theSocket = theSocket6;
  2080. if (theSocket)
  2081. {
  2082. CFDataRef selfaddr = CFSocketCopyAddress(theSocket);
  2083. if (selfaddr == NULL) return nil;
  2084. #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  2085. NSData *result = [NSData dataWithBytes:CFDataGetBytePtr(selfaddr) length:CFDataGetLength(selfaddr)];
  2086. CFRelease(selfaddr);
  2087. return result;
  2088. #else
  2089. return [(NSData *)NSMakeCollectable(selfaddr) autorelease];
  2090. #endif
  2091. }
  2092. // Extract address from CFSocketNativeHandle
  2093. socklen_t sockaddrlen;
  2094. CFSocketNativeHandle theNativeSocket = 0;
  2095. if (theNativeSocket4 > 0)
  2096. {
  2097. theNativeSocket = theNativeSocket4;
  2098. sockaddrlen = sizeof(struct sockaddr_in);
  2099. }
  2100. else
  2101. {
  2102. theNativeSocket = theNativeSocket6;
  2103. sockaddrlen = sizeof(struct sockaddr_in6);
  2104. }
  2105. NSData *result = nil;
  2106. void *sockaddr = malloc(sockaddrlen);
  2107. if(getsockname(theNativeSocket, (struct sockaddr *)sockaddr, &sockaddrlen) >= 0)
  2108. {
  2109. result = [NSData dataWithBytesNoCopy:sockaddr length:sockaddrlen freeWhenDone:YES];
  2110. }
  2111. else
  2112. {
  2113. free(sockaddr);
  2114. }
  2115. return result;
  2116. }
  2117. - (BOOL)isIPv4
  2118. {
  2119. return (theNativeSocket4 > 0 || theSocket4 != NULL);
  2120. }
  2121. - (BOOL)isIPv6
  2122. {
  2123. return (theNativeSocket6 > 0 || theSocket6 != NULL);
  2124. }
  2125. - (BOOL)areStreamsConnected
  2126. {
  2127. CFStreamStatus s;
  2128. if (theReadStream != NULL)
  2129. {
  2130. s = CFReadStreamGetStatus(theReadStream);
  2131. if ( !(s == kCFStreamStatusOpen || s == kCFStreamStatusReading || s == kCFStreamStatusError) )
  2132. return NO;
  2133. }
  2134. else return NO;
  2135. if (theWriteStream != NULL)
  2136. {
  2137. s = CFWriteStreamGetStatus(theWriteStream);
  2138. if ( !(s == kCFStreamStatusOpen || s == kCFStreamStatusWriting || s == kCFStreamStatusError) )
  2139. return NO;
  2140. }
  2141. else return NO;
  2142. return YES;
  2143. }
  2144. - (NSString *)description
  2145. {
  2146. static const char *statstr[] = {"not open","opening","open","reading","writing","at end","closed","has error"};
  2147. CFStreamStatus rs = (theReadStream != NULL) ? CFReadStreamGetStatus(theReadStream) : 0;
  2148. CFStreamStatus ws = (theWriteStream != NULL) ? CFWriteStreamGetStatus(theWriteStream) : 0;
  2149. NSString *peerstr, *selfstr;
  2150. BOOL is4 = [self isIPv4];
  2151. BOOL is6 = [self isIPv6];
  2152. if (is4 || is6)
  2153. {
  2154. if (is4 && is6)
  2155. {
  2156. peerstr = [NSString stringWithFormat: @"%@/%@ %u",
  2157. [self connectedHost4],
  2158. [self connectedHost6],
  2159. [self connectedPort]];
  2160. }
  2161. else if (is4)
  2162. {
  2163. peerstr = [NSString stringWithFormat: @"%@ %u",
  2164. [self connectedHost4],
  2165. [self connectedPort4]];
  2166. }
  2167. else
  2168. {
  2169. peerstr = [NSString stringWithFormat: @"%@ %u",
  2170. [self connectedHost6],
  2171. [self connectedPort6]];
  2172. }
  2173. }
  2174. else peerstr = @"nowhere";
  2175. if (is4 || is6)
  2176. {
  2177. if (is4 && is6)
  2178. {
  2179. selfstr = [NSString stringWithFormat: @"%@/%@ %u",
  2180. [self localHost4],
  2181. [self localHost6],
  2182. [self localPort]];
  2183. }
  2184. else if (is4)
  2185. {
  2186. selfstr = [NSString stringWithFormat: @"%@ %u",
  2187. [self localHost4],
  2188. [self localPort4]];
  2189. }
  2190. else
  2191. {
  2192. selfstr = [NSString stringWithFormat: @"%@ %u",
  2193. [self localHost6],
  2194. [self localPort6]];
  2195. }
  2196. }
  2197. else selfstr = @"nowhere";
  2198. NSMutableString *ms = [[NSMutableString alloc] initWithCapacity:150];
  2199. [ms appendString:[NSString stringWithFormat:@"<AsyncSocket %p", self]];
  2200. [ms appendString:[NSString stringWithFormat:@" local %@ remote %@ ", selfstr, peerstr]];
  2201. unsigned readQueueCount = (unsigned)[theReadQueue count];
  2202. unsigned writeQueueCount = (unsigned)[theWriteQueue count];
  2203. [ms appendString:[NSString stringWithFormat:@"has queued %u reads %u writes, ", readQueueCount, writeQueueCount]];
  2204. if (theCurrentRead == nil)
  2205. [ms appendString: @"no current read, "];
  2206. else
  2207. {
  2208. int percentDone;
  2209. if ([theCurrentRead->buffer length] != 0)
  2210. percentDone = (float)theCurrentRead->bytesDone /
  2211. (float)[theCurrentRead->buffer length] * 100.0F;
  2212. else
  2213. percentDone = 100.0F;
  2214. [ms appendString: [NSString stringWithFormat:@"currently read %u bytes (%d%% done), ",
  2215. (unsigned int)[theCurrentRead->buffer length],
  2216. theCurrentRead->bytesDone ? percentDone : 0]];
  2217. }
  2218. if (theCurrentWrite == nil)
  2219. [ms appendString: @"no current write, "];
  2220. else
  2221. {
  2222. int percentDone;
  2223. if ([theCurrentWrite->buffer length] != 0)
  2224. percentDone = (float)theCurrentWrite->bytesDone /
  2225. (float)[theCurrentWrite->buffer length] * 100.0F;
  2226. else
  2227. percentDone = 100.0F;
  2228. [ms appendString: [NSString stringWithFormat:@"currently written %u (%d%%), ",
  2229. (unsigned int)[theCurrentWrite->buffer length],
  2230. theCurrentWrite->bytesDone ? percentDone : 0]];
  2231. }
  2232. [ms appendString:[NSString stringWithFormat:@"read stream %p %s, ", theReadStream, statstr[rs]]];
  2233. [ms appendString:[NSString stringWithFormat:@"write stream %p %s", theWriteStream, statstr[ws]]];
  2234. if(theFlags & kDisconnectAfterReads)
  2235. {
  2236. if(theFlags & kDisconnectAfterWrites)
  2237. [ms appendString: @", will disconnect after reads & writes"];
  2238. else
  2239. [ms appendString: @", will disconnect after reads"];
  2240. }
  2241. else if(theFlags & kDisconnectAfterWrites)
  2242. {
  2243. [ms appendString: @", will disconnect after writes"];
  2244. }
  2245. if (![self isConnected]) [ms appendString: @", not connected"];
  2246. [ms appendString:@">"];
  2247. return [ms autorelease];
  2248. }
  2249. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2250. #pragma mark Reading
  2251. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2252. - (void)readDataToLength:(CFIndex)length withTimeout:(NSTimeInterval)timeout tag:(long)tag
  2253. {
  2254. if(length == 0) return;
  2255. if(theFlags & kForbidReadsWrites) return;
  2256. NSMutableData *buffer = [[NSMutableData alloc] initWithLength:length];
  2257. AsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer
  2258. timeout:timeout
  2259. tag:tag
  2260. readAllAvailable:NO
  2261. terminator:nil
  2262. maxLength:length];
  2263. [theReadQueue addObject:packet];
  2264. [self scheduleDequeueRead];
  2265. [packet release];
  2266. [buffer release];
  2267. }
  2268. - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
  2269. {
  2270. [self readDataToData:data withTimeout:timeout maxLength:-1 tag:tag];
  2271. }
  2272. - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(CFIndex)length tag:(long)tag
  2273. {
  2274. if(data == nil || [data length] == 0) return;
  2275. if(length >= 0 && length < (CFIndex)[data length]) return;
  2276. if(theFlags & kForbidReadsWrites) return;
  2277. NSMutableData *buffer = [[NSMutableData alloc] initWithLength:0];
  2278. AsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer
  2279. timeout:timeout
  2280. tag:tag
  2281. readAllAvailable:NO
  2282. terminator:data
  2283. maxLength:length];
  2284. [theReadQueue addObject:packet];
  2285. [self scheduleDequeueRead];
  2286. [packet release];
  2287. [buffer release];
  2288. }
  2289. - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag
  2290. {
  2291. if (theFlags & kForbidReadsWrites) return;
  2292. NSMutableData *buffer = [[NSMutableData alloc] initWithLength:0];
  2293. AsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer
  2294. timeout:timeout
  2295. tag:tag
  2296. readAllAvailable:YES
  2297. terminator:nil
  2298. maxLength:-1];
  2299. [theReadQueue addObject:packet];
  2300. [self scheduleDequeueRead];
  2301. [packet release];
  2302. [buffer release];
  2303. }
  2304. /**
  2305. * Puts a maybeDequeueRead on the run loop.
  2306. * An assumption here is that selectors will be performed consecutively within their priority.
  2307. **/
  2308. - (void)scheduleDequeueRead
  2309. {
  2310. if((theFlags & kDequeueReadScheduled) == 0)
  2311. {
  2312. theFlags |= kDequeueReadScheduled;
  2313. [self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0 inModes:theRunLoopModes];
  2314. }
  2315. }
  2316. /**
  2317. * This method starts a new read, if needed.
  2318. * It is called when a user requests a read,
  2319. * or when a stream opens that may have requested reads sitting in the queue, etc.
  2320. **/
  2321. - (void)maybeDequeueRead
  2322. {
  2323. // Unset the flag indicating a call to this method is scheduled
  2324. theFlags &= ~kDequeueReadScheduled;
  2325. // If we're not currently processing a read AND we have an available read stream
  2326. if((theCurrentRead == nil) && (theReadStream != NULL))
  2327. {
  2328. if([theReadQueue count] > 0)
  2329. {
  2330. // Dequeue the next object in the write queue
  2331. theCurrentRead = [[theReadQueue objectAtIndex:0] retain];
  2332. [theReadQueue removeObjectAtIndex:0];
  2333. if([theCurrentRead isKindOfClass:[AsyncSpecialPacket class]])
  2334. {
  2335. // Attempt to start TLS
  2336. theFlags |= kStartingReadTLS;
  2337. // This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set
  2338. [self maybeStartTLS];
  2339. }
  2340. else
  2341. {
  2342. // Start time-out timer
  2343. if(theCurrentRead->timeout >= 0.0)
  2344. {
  2345. theReadTimer = [NSTimer timerWithTimeInterval:theCurrentRead->timeout
  2346. target:self
  2347. selector:@selector(doReadTimeout:)
  2348. userInfo:nil
  2349. repeats:NO];
  2350. [self runLoopAddTimer:theReadTimer];
  2351. }
  2352. // Immediately read, if possible
  2353. [self doBytesAvailable];
  2354. }
  2355. }
  2356. else if(theFlags & kDisconnectAfterReads)
  2357. {
  2358. if(theFlags & kDisconnectAfterWrites)
  2359. {
  2360. if(([theWriteQueue count] == 0) && (theCurrentWrite == nil))
  2361. {
  2362. [self disconnect];
  2363. }
  2364. }
  2365. else
  2366. {
  2367. [self disconnect];
  2368. }
  2369. }
  2370. }
  2371. }
  2372. /**
  2373. * Call this method in doBytesAvailable instead of CFReadStreamHasBytesAvailable().
  2374. * This method supports pre-buffering properly as well as the kSocketHasBytesAvailable flag.
  2375. **/
  2376. - (BOOL)hasBytesAvailable
  2377. {
  2378. if ((theFlags & kSocketHasBytesAvailable) || ([partialReadBuffer length] > 0))
  2379. {
  2380. return YES;
  2381. }
  2382. else
  2383. {
  2384. return CFReadStreamHasBytesAvailable(theReadStream);
  2385. }
  2386. }
  2387. /**
  2388. * Call this method in doBytesAvailable instead of CFReadStreamRead().
  2389. * This method support pre-buffering properly.
  2390. **/
  2391. - (CFIndex)readIntoBuffer:(UInt8 *)buffer maxLength:(CFIndex)length
  2392. {
  2393. if([partialReadBuffer length] > 0)
  2394. {
  2395. // Determine the maximum amount of data to read
  2396. CFIndex bytesToRead = MIN(length, (CFIndex)[partialReadBuffer length]);
  2397. // Copy the bytes from the partial read buffer
  2398. memcpy(buffer, [partialReadBuffer bytes], bytesToRead);
  2399. // Remove the copied bytes from the partial read buffer
  2400. [partialReadBuffer replaceBytesInRange:NSMakeRange(0, bytesToRead) withBytes:NULL length:0];
  2401. return bytesToRead;
  2402. }
  2403. else
  2404. {
  2405. // Unset the "has-bytes-available" flag
  2406. theFlags &= ~kSocketHasBytesAvailable;
  2407. return CFReadStreamRead(theReadStream, buffer, length);
  2408. }
  2409. }
  2410. /**
  2411. * This method is called when a new read is taken from the read queue or when new data becomes available on the stream.
  2412. **/
  2413. - (void)doBytesAvailable
  2414. {
  2415. // If data is available on the stream, but there is no read request, then we don't need to process the data yet.
  2416. // Also, if there is a read request, but no read stream setup yet, we can't process any data yet.
  2417. if((theCurrentRead != nil) && (theReadStream != NULL))
  2418. {
  2419. // Note: This method is not called if theCurrentRead is an AsyncSpecialPacket (startTLS packet)
  2420. CFIndex totalBytesRead = 0;
  2421. BOOL done = NO;
  2422. BOOL socketError = NO;
  2423. BOOL maxoutError = NO;
  2424. while(!done && !socketError && !maxoutError && [self hasBytesAvailable])
  2425. {
  2426. BOOL didPreBuffer = NO;
  2427. // There are 3 types of read packets:
  2428. //
  2429. // 1) Read a specific length of data.
  2430. // 2) Read all available data.
  2431. // 3) Read up to a particular terminator.
  2432. if(theCurrentRead->readAllAvailableData == YES)
  2433. {
  2434. // We're reading all available data.
  2435. //
  2436. // Make sure there is at least READALL_CHUNKSIZE bytes available.
  2437. // We don't want to increase the buffer any more than this or we'll waste space.
  2438. // With prebuffering it's possible to read in a small chunk on the first read.
  2439. NSUInteger buffInc = READALL_CHUNKSIZE - ([theCurrentRead->buffer length] - theCurrentRead->bytesDone);
  2440. [theCurrentRead->buffer increaseLengthBy:buffInc];
  2441. }
  2442. else if(theCurrentRead->term != nil)
  2443. {
  2444. // We're reading up to a terminator.
  2445. //
  2446. // We may only want to read a few bytes.
  2447. // Just enough to ensure we don't go past our term or over our max limit.
  2448. // Unless pre-buffering is enabled, in which case we may want to read in a larger chunk.
  2449. // If we already have data pre-buffered, we obviously don't want to pre-buffer it again.
  2450. // So in this case we'll just read as usual.
  2451. if(([partialReadBuffer length] > 0) || !(theFlags & kEnablePreBuffering))
  2452. {
  2453. NSUInteger maxToRead = [theCurrentRead readLengthForTerm];
  2454. NSUInteger bufInc = maxToRead - ([theCurrentRead->buffer length] - theCurrentRead->bytesDone);
  2455. [theCurrentRead->buffer increaseLengthBy:bufInc];
  2456. }
  2457. else
  2458. {
  2459. didPreBuffer = YES;
  2460. NSUInteger maxToRead = [theCurrentRead prebufferReadLengthForTerm];
  2461. NSUInteger buffInc = maxToRead - ([theCurrentRead->buffer length] - theCurrentRead->bytesDone);
  2462. [theCurrentRead->buffer increaseLengthBy:buffInc];
  2463. }
  2464. }
  2465. // Number of bytes to read is space left in packet buffer.
  2466. CFIndex bytesToRead = [theCurrentRead->buffer length] - theCurrentRead->bytesDone;
  2467. // Read data into packet buffer
  2468. UInt8 *subBuffer = (UInt8 *)([theCurrentRead->buffer mutableBytes] + theCurrentRead->bytesDone);
  2469. CFIndex bytesRead = [self readIntoBuffer:subBuffer maxLength:bytesToRead];
  2470. // Check results
  2471. if(bytesRead < 0)
  2472. {
  2473. socketError = YES;
  2474. }
  2475. else
  2476. {
  2477. // Update total amount read for the current read
  2478. theCurrentRead->bytesDone += bytesRead;
  2479. // Update total amount read in this method invocation
  2480. totalBytesRead += bytesRead;
  2481. }
  2482. // Is packet done?
  2483. if(theCurrentRead->readAllAvailableData != YES)
  2484. {
  2485. if(theCurrentRead->term != nil)
  2486. {
  2487. if(didPreBuffer)
  2488. {
  2489. // Search for the terminating sequence within the big chunk we just read.
  2490. CFIndex overflow = [theCurrentRead searchForTermAfterPreBuffering:bytesRead];
  2491. if(overflow > 0)
  2492. {
  2493. // Copy excess data into partialReadBuffer
  2494. NSMutableData *buffer = theCurrentRead->buffer;
  2495. const void *overflowBuffer = [buffer bytes] + theCurrentRead->bytesDone - overflow;
  2496. [partialReadBuffer appendBytes:overflowBuffer length:overflow];
  2497. // Update the bytesDone variable.
  2498. // Note: The completeCurrentRead method will trim the buffer for us.
  2499. theCurrentRead->bytesDone -= overflow;
  2500. }
  2501. done = (overflow >= 0);
  2502. }
  2503. else
  2504. {
  2505. // Search for the terminating sequence at the end of the buffer
  2506. NSUInteger termlen = [theCurrentRead->term length];
  2507. if(theCurrentRead->bytesDone >= termlen)
  2508. {
  2509. const void *buf = [theCurrentRead->buffer bytes] + (theCurrentRead->bytesDone - termlen);
  2510. const void *seq = [theCurrentRead->term bytes];
  2511. done = (memcmp (buf, seq, termlen) == 0);
  2512. }
  2513. }
  2514. if(!done && theCurrentRead->maxLength >= 0 && theCurrentRead->bytesDone >= theCurrentRead->maxLength)
  2515. {
  2516. // There's a set maxLength, and we've reached that maxLength without completing the read
  2517. maxoutError = YES;
  2518. }
  2519. }
  2520. else
  2521. {
  2522. // Done when (sized) buffer is full.
  2523. done = ((CFIndex)[theCurrentRead->buffer length] == theCurrentRead->bytesDone);
  2524. }
  2525. }
  2526. // else readAllAvailable doesn't end until all readable is read.
  2527. }
  2528. if(theCurrentRead->readAllAvailableData && theCurrentRead->bytesDone > 0)
  2529. {
  2530. // Ran out of bytes, so the "read-all-available-data" type packet is done
  2531. done = YES;
  2532. }
  2533. if(done)
  2534. {
  2535. [self completeCurrentRead];
  2536. if (!socketError) [self scheduleDequeueRead];
  2537. }
  2538. else if(totalBytesRead > 0)
  2539. {
  2540. // We're not done with the readToLength or readToData yet, but we have read in some bytes
  2541. if ([theDelegate respondsToSelector:@selector(onSocket:didReadPartialDataOfLength:tag:)])
  2542. {
  2543. [theDelegate onSocket:self didReadPartialDataOfLength:totalBytesRead tag:theCurrentRead->tag];
  2544. }
  2545. }
  2546. if(socketError)
  2547. {
  2548. CFStreamError err = CFReadStreamGetError(theReadStream);
  2549. [self closeWithError:[self errorFromCFStreamError:err]];
  2550. return;
  2551. }
  2552. if(maxoutError)
  2553. {
  2554. [self closeWithError:[self getReadMaxedOutError]];
  2555. return;
  2556. }
  2557. }
  2558. }
  2559. // Ends current read and calls delegate.
  2560. - (void)completeCurrentRead
  2561. {
  2562. NSAssert(theCurrentRead, @"Trying to complete current read when there is no current read.");
  2563. [theCurrentRead->buffer setLength:theCurrentRead->bytesDone];
  2564. if([theDelegate respondsToSelector:@selector(onSocket:didReadData:withTag:)])
  2565. {
  2566. [theDelegate onSocket:self didReadData:theCurrentRead->buffer withTag:theCurrentRead->tag];
  2567. }
  2568. if (theCurrentRead != nil) [self endCurrentRead]; // Caller may have disconnected.
  2569. }
  2570. // Ends current read.
  2571. - (void)endCurrentRead
  2572. {
  2573. NSAssert(theCurrentRead, @"Trying to end current read when there is no current read.");
  2574. [theReadTimer invalidate];
  2575. theReadTimer = nil;
  2576. [theCurrentRead release];
  2577. theCurrentRead = nil;
  2578. }
  2579. - (void)doReadTimeout:(NSTimer *)timer
  2580. {
  2581. NSTimeInterval timeoutExtension = 0.0;
  2582. if([theDelegate respondsToSelector:@selector(onSocket:shouldTimeoutReadWithTag:elapsed:bytesDone:)])
  2583. {
  2584. timeoutExtension = [theDelegate onSocket:self shouldTimeoutReadWithTag:theCurrentRead->tag
  2585. elapsed:theCurrentRead->timeout
  2586. bytesDone:theCurrentRead->bytesDone];
  2587. }
  2588. if(timeoutExtension > 0.0)
  2589. {
  2590. theCurrentRead->timeout += timeoutExtension;
  2591. theReadTimer = [NSTimer timerWithTimeInterval:timeoutExtension
  2592. target:self
  2593. selector:@selector(doReadTimeout:)
  2594. userInfo:nil
  2595. repeats:NO];
  2596. [self runLoopAddTimer:theReadTimer];
  2597. }
  2598. else
  2599. {
  2600. // Do not call endCurrentRead here.
  2601. // We must allow the delegate access to any partial read in the unreadData method.
  2602. [self closeWithError:[self getReadTimeoutError]];
  2603. }
  2604. }
  2605. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2606. #pragma mark Writing
  2607. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2608. - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
  2609. {
  2610. if (data == nil || [data length] == 0) return;
  2611. if (theFlags & kForbidReadsWrites) return;
  2612. AsyncWritePacket *packet = [[AsyncWritePacket alloc] initWithData:data timeout:timeout tag:tag];
  2613. [theWriteQueue addObject:packet];
  2614. [self scheduleDequeueWrite];
  2615. [packet release];
  2616. }
  2617. - (void)scheduleDequeueWrite
  2618. {
  2619. if((theFlags & kDequeueWriteScheduled) == 0)
  2620. {
  2621. theFlags |= kDequeueWriteScheduled;
  2622. [self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0 inModes:theRunLoopModes];
  2623. }
  2624. }
  2625. /**
  2626. * Conditionally starts a new write.
  2627. *
  2628. * IF there is not another write in process
  2629. * AND there is a write queued
  2630. * AND we have a write stream available
  2631. *
  2632. * This method also handles auto-disconnect post read/write completion.
  2633. **/
  2634. - (void)maybeDequeueWrite
  2635. {
  2636. // Unset the flag indicating a call to this method is scheduled
  2637. theFlags &= ~kDequeueWriteScheduled;
  2638. // If we're not currently processing a write AND we have an available write stream
  2639. if((theCurrentWrite == nil) && (theWriteStream != NULL))
  2640. {
  2641. if([theWriteQueue count] > 0)
  2642. {
  2643. // Dequeue the next object in the write queue
  2644. theCurrentWrite = [[theWriteQueue objectAtIndex:0] retain];
  2645. [theWriteQueue removeObjectAtIndex:0];
  2646. if([theCurrentWrite isKindOfClass:[AsyncSpecialPacket class]])
  2647. {
  2648. // Attempt to start TLS
  2649. theFlags |= kStartingWriteTLS;
  2650. // This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set
  2651. [self maybeStartTLS];
  2652. }
  2653. else
  2654. {
  2655. // Start time-out timer
  2656. if(theCurrentWrite->timeout >= 0.0)
  2657. {
  2658. theWriteTimer = [NSTimer timerWithTimeInterval:theCurrentWrite->timeout
  2659. target:self
  2660. selector:@selector(doWriteTimeout:)
  2661. userInfo:nil
  2662. repeats:NO];
  2663. [self runLoopAddTimer:theWriteTimer];
  2664. }
  2665. // Immediately write, if possible
  2666. [self doSendBytes];
  2667. }
  2668. }
  2669. else if(theFlags & kDisconnectAfterWrites)
  2670. {
  2671. if(theFlags & kDisconnectAfterReads)
  2672. {
  2673. if(([theReadQueue count] == 0) && (theCurrentRead == nil))
  2674. {
  2675. [self disconnect];
  2676. }
  2677. }
  2678. else
  2679. {
  2680. [self disconnect];
  2681. }
  2682. }
  2683. }
  2684. }
  2685. /**
  2686. * Call this method in doSendBytes instead of CFWriteStreamCanAcceptBytes().
  2687. * This method supports the kSocketCanAcceptBytes flag.
  2688. **/
  2689. - (BOOL)canAcceptBytes
  2690. {
  2691. if (theFlags & kSocketCanAcceptBytes)
  2692. {
  2693. return YES;
  2694. }
  2695. else
  2696. {
  2697. return CFWriteStreamCanAcceptBytes(theWriteStream);
  2698. }
  2699. }
  2700. /**
  2701. * Returns the maximum bytes to write.
  2702. * This value is dependent on the size of theCurrentWrite as well as the WRITE_CHUNKSIZE.
  2703. **/
  2704. - (CFIndex)maxBytesToWrite
  2705. {
  2706. CFIndex bytesRemaining = [theCurrentWrite->buffer length] - theCurrentWrite->bytesDone;
  2707. return (bytesRemaining < WRITE_CHUNKSIZE) ? bytesRemaining : WRITE_CHUNKSIZE;
  2708. }
  2709. - (void)doSendBytes
  2710. {
  2711. if((theCurrentWrite != nil) && (theWriteStream != NULL))
  2712. {
  2713. // Note: This method is not called if theCurrentWrite is an AsyncSpecialPacket (startTLS packet)
  2714. CFIndex totalBytesWritten = 0;
  2715. BOOL done = NO;
  2716. BOOL error = NO;
  2717. while (!done && !error && [self canAcceptBytes])
  2718. {
  2719. // Figure out what to write.
  2720. CFIndex bytesRemaining = [theCurrentWrite->buffer length] - theCurrentWrite->bytesDone;
  2721. CFIndex bytesToWrite = (bytesRemaining < WRITE_CHUNKSIZE) ? bytesRemaining : WRITE_CHUNKSIZE;
  2722. UInt8 *writestart = (UInt8 *)([theCurrentWrite->buffer bytes] + theCurrentWrite->bytesDone);
  2723. // Write.
  2724. CFIndex bytesWritten = CFWriteStreamWrite(theWriteStream, writestart, bytesToWrite);
  2725. // Unset the "can accept bytes" flag
  2726. theFlags &= ~kSocketCanAcceptBytes;
  2727. // Check results
  2728. if (bytesWritten < 0)
  2729. {
  2730. error = YES;
  2731. }
  2732. else
  2733. {
  2734. // Update total amount read for the current write
  2735. theCurrentWrite->bytesDone += bytesWritten;
  2736. // Update total amount written in this method invocation
  2737. totalBytesWritten += bytesWritten;
  2738. // Is packet done?
  2739. done = ((CFIndex)[theCurrentWrite->buffer length] == theCurrentWrite->bytesDone);
  2740. }
  2741. }
  2742. if(done)
  2743. {
  2744. [self completeCurrentWrite];
  2745. [self scheduleDequeueWrite];
  2746. }
  2747. else if(error)
  2748. {
  2749. CFStreamError err = CFWriteStreamGetError(theWriteStream);
  2750. [self closeWithError:[self errorFromCFStreamError:err]];
  2751. return;
  2752. }
  2753. else
  2754. {
  2755. // We're not done with the entire write, but we have written some bytes
  2756. if ([theDelegate respondsToSelector:@selector(onSocket:didWritePartialDataOfLength:tag:)])
  2757. {
  2758. [theDelegate onSocket:self didWritePartialDataOfLength:totalBytesWritten tag:theCurrentWrite->tag];
  2759. }
  2760. }
  2761. }
  2762. }
  2763. // Ends current write and calls delegate.
  2764. - (void)completeCurrentWrite
  2765. {
  2766. NSAssert(theCurrentWrite, @"Trying to complete current write when there is no current write.");
  2767. if ([theDelegate respondsToSelector:@selector(onSocket:didWriteDataWithTag:)])
  2768. {
  2769. [theDelegate onSocket:self didWriteDataWithTag:theCurrentWrite->tag];
  2770. }
  2771. if (theCurrentWrite != nil) [self endCurrentWrite]; // Caller may have disconnected.
  2772. }
  2773. // Ends current write.
  2774. - (void)endCurrentWrite
  2775. {
  2776. NSAssert(theCurrentWrite, @"Trying to complete current write when there is no current write.");
  2777. [theWriteTimer invalidate];
  2778. theWriteTimer = nil;
  2779. [theCurrentWrite release];
  2780. theCurrentWrite = nil;
  2781. }
  2782. - (void)doWriteTimeout:(NSTimer *)timer
  2783. {
  2784. NSTimeInterval timeoutExtension = 0.0;
  2785. if([theDelegate respondsToSelector:@selector(onSocket:shouldTimeoutWriteWithTag:elapsed:bytesDone:)])
  2786. {
  2787. timeoutExtension = [theDelegate onSocket:self shouldTimeoutWriteWithTag:theCurrentWrite->tag
  2788. elapsed:theCurrentWrite->timeout
  2789. bytesDone:theCurrentWrite->bytesDone];
  2790. }
  2791. if(timeoutExtension > 0.0)
  2792. {
  2793. theCurrentWrite->timeout += timeoutExtension;
  2794. theWriteTimer = [NSTimer timerWithTimeInterval:timeoutExtension
  2795. target:self
  2796. selector:@selector(doWriteTimeout:)
  2797. userInfo:nil
  2798. repeats:NO];
  2799. [self runLoopAddTimer:theWriteTimer];
  2800. }
  2801. else
  2802. {
  2803. [self closeWithError:[self getWriteTimeoutError]];
  2804. }
  2805. }
  2806. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2807. #pragma mark Security
  2808. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2809. - (void)startTLS:(NSDictionary *)tlsSettings
  2810. {
  2811. if(tlsSettings == nil)
  2812. {
  2813. // Passing nil/NULL to CFReadStreamSetProperty will appear to work the same as passing an empty dictionary,
  2814. // but causes problems if we later try to fetch the remote host's certificate.
  2815. //
  2816. // To be exact, it causes the following to return NULL instead of the normal result:
  2817. // CFReadStreamCopyProperty(readStream, kCFStreamPropertySSLPeerCertificates)
  2818. //
  2819. // So we use an empty dictionary instead, which works perfectly.
  2820. tlsSettings = [NSDictionary dictionary];
  2821. }
  2822. AsyncSpecialPacket *packet = [[AsyncSpecialPacket alloc] initWithTLSSettings:tlsSettings];
  2823. [theReadQueue addObject:packet];
  2824. [self scheduleDequeueRead];
  2825. [theWriteQueue addObject:packet];
  2826. [self scheduleDequeueWrite];
  2827. [packet release];
  2828. }
  2829. - (void)maybeStartTLS
  2830. {
  2831. // We can't start TLS until:
  2832. // - All queued reads prior to the user calling StartTLS are complete
  2833. // - All queued writes prior to the user calling StartTLS are complete
  2834. //
  2835. // We'll know these conditions are met when both kStartingReadTLS and kStartingWriteTLS are set
  2836. if((theFlags & kStartingReadTLS) && (theFlags & kStartingWriteTLS))
  2837. {
  2838. AsyncSpecialPacket *tlsPacket = (AsyncSpecialPacket *)theCurrentRead;
  2839. BOOL didStartOnReadStream = CFReadStreamSetProperty(theReadStream, kCFStreamPropertySSLSettings,
  2840. (CFDictionaryRef)tlsPacket->tlsSettings);
  2841. BOOL didStartOnWriteStream = CFWriteStreamSetProperty(theWriteStream, kCFStreamPropertySSLSettings,
  2842. (CFDictionaryRef)tlsPacket->tlsSettings);
  2843. if(!didStartOnReadStream || !didStartOnWriteStream)
  2844. {
  2845. [self closeWithError:[self getSocketError]];
  2846. }
  2847. }
  2848. }
  2849. - (void)onTLSHandshakeSuccessful
  2850. {
  2851. if((theFlags & kStartingReadTLS) && (theFlags & kStartingWriteTLS))
  2852. {
  2853. theFlags &= ~kStartingReadTLS;
  2854. theFlags &= ~kStartingWriteTLS;
  2855. if([theDelegate respondsToSelector:@selector(onSocketDidSecure:)])
  2856. {
  2857. [theDelegate onSocketDidSecure:self];
  2858. }
  2859. [self endCurrentRead];
  2860. [self endCurrentWrite];
  2861. [self scheduleDequeueRead];
  2862. [self scheduleDequeueWrite];
  2863. }
  2864. }
  2865. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2866. #pragma mark CF Callbacks
  2867. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2868. - (void)doCFSocketCallback:(CFSocketCallBackType)type
  2869. forSocket:(CFSocketRef)sock
  2870. withAddress:(NSData *)address
  2871. withData:(const void *)pData
  2872. {
  2873. NSParameterAssert ((sock == theSocket4) || (sock == theSocket6));
  2874. switch (type)
  2875. {
  2876. case kCFSocketConnectCallBack:
  2877. // The data argument is either NULL or a pointer to an SInt32 error code, if the connect failed.
  2878. if(pData)
  2879. [self doSocketOpen:sock withCFSocketError:kCFSocketError];
  2880. else
  2881. [self doSocketOpen:sock withCFSocketError:kCFSocketSuccess];
  2882. break;
  2883. case kCFSocketAcceptCallBack:
  2884. [self doAcceptFromSocket:sock withNewNativeSocket:*((CFSocketNativeHandle *)pData)];
  2885. break;
  2886. default:
  2887. NSLog (@"AsyncSocket %p received unexpected CFSocketCallBackType %d.", self, type);
  2888. break;
  2889. }
  2890. }
  2891. - (void)doCFReadStreamCallback:(CFStreamEventType)type forStream:(CFReadStreamRef)stream
  2892. {
  2893. NSParameterAssert(theReadStream != NULL);
  2894. CFStreamError err;
  2895. switch (type)
  2896. {
  2897. case kCFStreamEventOpenCompleted:
  2898. theFlags |= kDidCompleteOpenForRead;
  2899. [self doStreamOpen];
  2900. break;
  2901. case kCFStreamEventHasBytesAvailable:
  2902. if(theFlags & kStartingReadTLS) {
  2903. [self onTLSHandshakeSuccessful];
  2904. }
  2905. else {
  2906. theFlags |= kSocketHasBytesAvailable;
  2907. [self doBytesAvailable];
  2908. }
  2909. break;
  2910. case kCFStreamEventErrorOccurred:
  2911. case kCFStreamEventEndEncountered:
  2912. err = CFReadStreamGetError (theReadStream);
  2913. [self closeWithError: [self errorFromCFStreamError:err]];
  2914. break;
  2915. default:
  2916. NSLog (@"AsyncSocket %p received unexpected CFReadStream callback, CFStreamEventType %d.", self, type);
  2917. }
  2918. }
  2919. - (void)doCFWriteStreamCallback:(CFStreamEventType)type forStream:(CFWriteStreamRef)stream
  2920. {
  2921. NSParameterAssert(theWriteStream != NULL);
  2922. CFStreamError err;
  2923. switch (type)
  2924. {
  2925. case kCFStreamEventOpenCompleted:
  2926. theFlags |= kDidCompleteOpenForWrite;
  2927. [self doStreamOpen];
  2928. break;
  2929. case kCFStreamEventCanAcceptBytes:
  2930. if(theFlags & kStartingWriteTLS) {
  2931. [self onTLSHandshakeSuccessful];
  2932. }
  2933. else {
  2934. theFlags |= kSocketCanAcceptBytes;
  2935. [self doSendBytes];
  2936. }
  2937. break;
  2938. case kCFStreamEventErrorOccurred:
  2939. case kCFStreamEventEndEncountered:
  2940. err = CFWriteStreamGetError (theWriteStream);
  2941. [self closeWithError: [self errorFromCFStreamError:err]];
  2942. break;
  2943. default:
  2944. NSLog (@"AsyncSocket %p received unexpected CFWriteStream callback, CFStreamEventType %d.", self, type);
  2945. }
  2946. }
  2947. /**
  2948. * This is the callback we setup for CFSocket.
  2949. * This method does nothing but forward the call to it's Objective-C counterpart
  2950. **/
  2951. static void MyCFSocketCallback (CFSocketRef sref, CFSocketCallBackType type, CFDataRef address, const void *pData, void *pInfo)
  2952. {
  2953. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  2954. AsyncSocket *theSocket = [[(AsyncSocket *)pInfo retain] autorelease];
  2955. [theSocket doCFSocketCallback:type forSocket:sref withAddress:(NSData *)address withData:pData];
  2956. [pool release];
  2957. }
  2958. /**
  2959. * This is the callback we setup for CFReadStream.
  2960. * This method does nothing but forward the call to it's Objective-C counterpart
  2961. **/
  2962. static void MyCFReadStreamCallback (CFReadStreamRef stream, CFStreamEventType type, void *pInfo)
  2963. {
  2964. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  2965. AsyncSocket *theSocket = [[(AsyncSocket *)pInfo retain] autorelease];
  2966. [theSocket doCFReadStreamCallback:type forStream:stream];
  2967. [pool release];
  2968. }
  2969. /**
  2970. * This is the callback we setup for CFWriteStream.
  2971. * This method does nothing but forward the call to it's Objective-C counterpart
  2972. **/
  2973. static void MyCFWriteStreamCallback (CFWriteStreamRef stream, CFStreamEventType type, void *pInfo)
  2974. {
  2975. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  2976. AsyncSocket *theSocket = [[(AsyncSocket *)pInfo retain] autorelease];
  2977. [theSocket doCFWriteStreamCallback:type forStream:stream];
  2978. [pool release];
  2979. }
  2980. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2981. #pragma mark Class Methods
  2982. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2983. // Return line separators.
  2984. + (NSData *)CRLFData
  2985. {
  2986. return [NSData dataWithBytes:"\x0D\x0A" length:2];
  2987. }
  2988. + (NSData *)CRData
  2989. {
  2990. return [NSData dataWithBytes:"\x0D" length:1];
  2991. }
  2992. + (NSData *)LFData
  2993. {
  2994. return [NSData dataWithBytes:"\x0A" length:1];
  2995. }
  2996. + (NSData *)ZeroData
  2997. {
  2998. return [NSData dataWithBytes:"" length:1];
  2999. }
  3000. + (NSData *)JsonData
  3001. {
  3002. return [NSData dataWithBytes:"}" length:1];
  3003. }
  3004. @end