├── Documentation.html ├── GCDAsyncSocket.h └── GCDAsyncSocket.m /Documentation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Welcome to the CocoaAsyncSocket project!

5 | 6 |

7 | A wealth of documentation can be found on the Google Code homepage:
8 | http://code.google.com/p/cocoaasyncsocket/ 9 |

10 | 11 |

12 | If you are new to networking, it is recommended you start by reading the Intro page:
13 | http://code.google.com/p/cocoaasyncsocket/wiki/Intro 14 |

15 | 16 |

17 | If you are a seasoned networking professional, with 10+ years of experience writing low-level socket code, 18 | and detailed knowledge of the underlying BSD networking stack, then you can skip the CommonPitfalls page.
19 | Otherwise, it should be considered mandatory reading:
20 | http://code.google.com/p/cocoaasyncsocket/wiki/CommonPitfalls 21 |

22 | 23 |

24 | A little bit of investment in your knowledge and understanding of networking fundamentals can go a long way.
25 | And it can save you a LOT of time and frustration in the long run. 26 |

27 | 28 |

29 | The API reference page can be found here:
30 | http://code.google.com/p/cocoaasyncsocket/wiki/Reference_GCDAsyncSocket 31 |

32 | 33 |

34 | In addition to this, the headers are generally well documented. 35 |

36 | 37 |

38 | If you have any questions you are welcome to post to the CocoaAsyncSocket mailing list:
39 | http://groups.google.com/group/cocoaasyncsocket
40 |
41 | The list is archived, and available for browsing online.
42 | You may be able to instantly find the answer you're looking for with a quick search.
43 |

44 | 45 |

We hope the CocoaAsyncSocket project can provide you with powerful and easy to use networking libraries.

46 | 47 | 48 | -------------------------------------------------------------------------------- /GCDAsyncSocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // GCDAsyncSocket.h 3 | // 4 | // This class is in the public domain. 5 | // Originally created by Robbie Hanson in Q3 2010. 6 | // Updated and maintained by Deusty LLC and the Mac development community. 7 | // 8 | // http://code.google.com/p/cocoaasyncsocket/ 9 | // 10 | 11 | #import 12 | #import 13 | #import 14 | 15 | @class GCDAsyncReadPacket; 16 | @class GCDAsyncWritePacket; 17 | 18 | extern NSString *const GCDAsyncSocketException; 19 | extern NSString *const GCDAsyncSocketErrorDomain; 20 | 21 | #if !TARGET_OS_IPHONE 22 | extern NSString *const GCDAsyncSocketSSLCipherSuites; 23 | extern NSString *const GCDAsyncSocketSSLDiffieHellmanParameters; 24 | #endif 25 | 26 | enum GCDAsyncSocketError 27 | { 28 | GCDAsyncSocketNoError = 0, // Never used 29 | GCDAsyncSocketBadConfigError, // Invalid configuration 30 | GCDAsyncSocketBadParamError, // Invalid parameter was passed 31 | GCDAsyncSocketConnectTimeoutError, // A connect operation timed out 32 | GCDAsyncSocketReadTimeoutError, // A read operation timed out 33 | GCDAsyncSocketWriteTimeoutError, // A write operation timed out 34 | GCDAsyncSocketReadMaxedOutError, // Reached set maxLength without completing 35 | GCDAsyncSocketClosedError, // The remote peer closed the connection 36 | GCDAsyncSocketOtherError, // Description provided in userInfo 37 | }; 38 | typedef enum GCDAsyncSocketError GCDAsyncSocketError; 39 | 40 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | #pragma mark - 42 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 43 | 44 | @interface GCDAsyncSocket : NSObject 45 | { 46 | uint32_t flags; 47 | uint16_t config; 48 | 49 | id delegate; 50 | dispatch_queue_t delegateQueue; 51 | 52 | int socket4FD; 53 | int socket6FD; 54 | int connectIndex; 55 | NSData * connectInterface4; 56 | NSData * connectInterface6; 57 | 58 | dispatch_queue_t socketQueue; 59 | 60 | dispatch_source_t accept4Source; 61 | dispatch_source_t accept6Source; 62 | dispatch_source_t connectTimer; 63 | dispatch_source_t readSource; 64 | dispatch_source_t writeSource; 65 | dispatch_source_t readTimer; 66 | dispatch_source_t writeTimer; 67 | 68 | NSMutableArray *readQueue; 69 | NSMutableArray *writeQueue; 70 | 71 | GCDAsyncReadPacket *currentRead; 72 | GCDAsyncWritePacket *currentWrite; 73 | 74 | unsigned long socketFDBytesAvailable; 75 | 76 | NSMutableData *partialReadBuffer; 77 | 78 | #if TARGET_OS_IPHONE 79 | CFStreamClientContext streamContext; 80 | CFReadStreamRef readStream; 81 | CFWriteStreamRef writeStream; 82 | #else 83 | SSLContextRef sslContext; 84 | NSMutableData *sslReadBuffer; 85 | size_t sslWriteCachedLength; 86 | #endif 87 | 88 | id userData; 89 | } 90 | 91 | /** 92 | * GCDAsyncSocket uses the standard delegate paradigm, 93 | * but executes all delegate callbacks on a given delegate dispatch queue. 94 | * This allows for maximum concurrency, while at the same time providing easy thread safety. 95 | * 96 | * You MUST set a delegate AND delegate dispatch queue before attempting to 97 | * use the socket, or you will get an error. 98 | * 99 | * The socket queue is optional. 100 | * If you pass NULL, GCDAsyncSocket will automatically create it's own socket queue. 101 | * If you choose to provide a socket queue, the socket queue must not be a concurrent queue. 102 | * 103 | * The delegate queue and socket queue can optionally be the same. 104 | **/ 105 | - (id)init; 106 | - (id)initWithSocketQueue:(dispatch_queue_t)sq; 107 | - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq; 108 | - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq; 109 | 110 | #pragma mark Configuration 111 | 112 | - (id)delegate; 113 | - (void)setDelegate:(id)delegate; 114 | - (void)synchronouslySetDelegate:(id)delegate; 115 | 116 | - (dispatch_queue_t)delegateQueue; 117 | - (void)setDelegateQueue:(dispatch_queue_t)delegateQueue; 118 | - (void)synchronouslySetDelegateQueue:(dispatch_queue_t)delegateQueue; 119 | 120 | - (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr; 121 | - (void)setDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue; 122 | - (void)synchronouslySetDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue; 123 | 124 | /** 125 | * Traditionally sockets are not closed until the conversation is over. 126 | * However, it is technically possible for the remote enpoint to close its write stream. 127 | * Our socket would then be notified that there is no more data to be read, 128 | * but our socket would still be writeable and the remote endpoint could continue to receive our data. 129 | * 130 | * The argument for this confusing functionality stems from the idea that a client could shut down its 131 | * write stream after sending a request to the server, thus notifying the server there are to be no further requests. 132 | * In practice, however, this technique did little to help server developers. 133 | * 134 | * To make matters worse, from a TCP perspective there is no way to tell the difference from a read stream close 135 | * and a full socket close. They both result in the TCP stack receiving a FIN packet. The only way to tell 136 | * is by continuing to write to the socket. If it was only a read stream close, then writes will continue to work. 137 | * Otherwise an error will be occur shortly (when the remote end sends us a RST packet). 138 | * 139 | * In addition to the technical challenges and confusion, many high level socket/stream API's provide 140 | * no support for dealing with the problem. If the read stream is closed, the API immediately declares the 141 | * socket to be closed, and shuts down the write stream as well. In fact, this is what Apple's CFStream API does. 142 | * It might sound like poor design at first, but in fact it simplifies development. 143 | * 144 | * The vast majority of the time if the read stream is closed it's because the remote endpoint closed its socket. 145 | * Thus it actually makes sense to close the socket at this point. 146 | * And in fact this is what most networking developers want and expect to happen. 147 | * However, if you are writing a server that interacts with a plethora of clients, 148 | * you might encounter a client that uses the discouraged technique of shutting down its write stream. 149 | * If this is the case, you can set this property to NO, 150 | * and make use of the socketDidCloseReadStream delegate method. 151 | * 152 | * The default value is YES. 153 | **/ 154 | - (BOOL)autoDisconnectOnClosedReadStream; 155 | - (void)setAutoDisconnectOnClosedReadStream:(BOOL)flag; 156 | 157 | /** 158 | * By default, both IPv4 and IPv6 are enabled. 159 | * 160 | * For accepting incoming connections, this means GCDAsyncSocket automatically supports both protocols, 161 | * and can simulataneously accept incoming connections on either protocol. 162 | * 163 | * For outgoing connections, this means GCDAsyncSocket can connect to remote hosts running either protocol. 164 | * If a DNS lookup returns only IPv4 results, GCDAsyncSocket will automatically use IPv4. 165 | * If a DNS lookup returns only IPv6 results, GCDAsyncSocket will automatically use IPv6. 166 | * If a DNS lookup returns both IPv4 and IPv6 results, the preferred protocol will be chosen. 167 | * By default, the preferred protocol is IPv4, but may be configured as desired. 168 | **/ 169 | - (BOOL)isIPv4Enabled; 170 | - (void)setIPv4Enabled:(BOOL)flag; 171 | 172 | - (BOOL)isIPv6Enabled; 173 | - (void)setIPv6Enabled:(BOOL)flag; 174 | 175 | - (BOOL)isIPv4PreferredOverIPv6; 176 | - (void)setPreferIPv4OverIPv6:(BOOL)flag; 177 | 178 | /** 179 | * User data allows you to associate arbitrary information with the socket. 180 | * This data is not used internally by socket in any way. 181 | **/ 182 | - (id)userData; 183 | - (void)setUserData:(id)arbitraryUserData; 184 | 185 | #pragma mark Accepting 186 | 187 | /** 188 | * Tells the socket to begin listening and accepting connections on the given port. 189 | * When a connection is accepted, a new instance of GCDAsyncSocket will be spawned to handle it, 190 | * and the socket:didAcceptNewSocket: delegate method will be invoked. 191 | * 192 | * The socket will listen on all available interfaces (e.g. wifi, ethernet, etc) 193 | **/ 194 | - (BOOL)acceptOnPort:(uint16_t)port error:(NSError **)errPtr; 195 | 196 | /** 197 | * This method is the same as acceptOnPort:error: with the 198 | * additional option of specifying which interface to listen on. 199 | * 200 | * For example, you could specify that the socket should only accept connections over ethernet, 201 | * and not other interfaces such as wifi. 202 | * 203 | * The interface may be specified by name (e.g. "en1" or "lo0") or by IP address (e.g. "192.168.4.34"). 204 | * You may also use the special strings "localhost" or "loopback" to specify that 205 | * the socket only accept connections from the local machine. 206 | * 207 | * You can see the list of interfaces via the command line utility "ifconfig", 208 | * or programmatically via the getifaddrs() function. 209 | * 210 | * To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method. 211 | **/ 212 | - (BOOL)acceptOnInterface:(NSString *)interface port:(uint16_t)port error:(NSError **)errPtr; 213 | 214 | #pragma mark Connecting 215 | 216 | /** 217 | * Connects to the given host and port. 218 | * 219 | * This method invokes connectToHost:onPort:viaInterface:withTimeout:error: 220 | * and uses the default interface, and no timeout. 221 | **/ 222 | - (BOOL)connectToHost:(NSString *)host onPort:(uint16_t)port error:(NSError **)errPtr; 223 | 224 | /** 225 | * Connects to the given host and port with an optional timeout. 226 | * 227 | * This method invokes connectToHost:onPort:viaInterface:withTimeout:error: and uses the default interface. 228 | **/ 229 | - (BOOL)connectToHost:(NSString *)host 230 | onPort:(uint16_t)port 231 | withTimeout:(NSTimeInterval)timeout 232 | error:(NSError **)errPtr; 233 | 234 | /** 235 | * Connects to the given host & port, via the optional interface, with an optional timeout. 236 | * 237 | * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2"). 238 | * The host may also be the special strings "localhost" or "loopback" to specify connecting 239 | * to a service on the local machine. 240 | * 241 | * The interface may be a name (e.g. "en1" or "lo0") or the corresponding IP address (e.g. "192.168.4.35"). 242 | * The interface may also be used to specify the local port (see below). 243 | * 244 | * To not time out use a negative time interval. 245 | * 246 | * This method will return NO if an error is detected, and set the error pointer (if one was given). 247 | * Possible errors would be a nil host, invalid interface, or socket is already connected. 248 | * 249 | * If no errors are detected, this method will start a background connect operation and immediately return YES. 250 | * The delegate callbacks are used to notify you when the socket connects, or if the host was unreachable. 251 | * 252 | * Since this class supports queued reads and writes, you can immediately start reading and/or writing. 253 | * All read/write operations will be queued, and upon socket connection, 254 | * the operations will be dequeued and processed in order. 255 | * 256 | * The interface may optionally contain a port number at the end of the string, separated by a colon. 257 | * This allows you to specify the local port that should be used for the outgoing connection. (read paragraph to end) 258 | * To specify both interface and local port: "en1:8082" or "192.168.4.35:2424". 259 | * To specify only local port: ":8082". 260 | * Please note this is an advanced feature, and is somewhat hidden on purpose. 261 | * You should understand that 99.999% of the time you should NOT specify the local port for an outgoing connection. 262 | * If you think you need to, there is a very good chance you have a fundamental misunderstanding somewhere. 263 | * Local ports do NOT need to match remote ports. In fact, they almost never do. 264 | * This feature is here for networking professionals using very advanced techniques. 265 | **/ 266 | - (BOOL)connectToHost:(NSString *)host 267 | onPort:(uint16_t)port 268 | viaInterface:(NSString *)interface 269 | withTimeout:(NSTimeInterval)timeout 270 | error:(NSError **)errPtr; 271 | 272 | /** 273 | * Connects to the given address, specified as a sockaddr structure wrapped in a NSData object. 274 | * For example, a NSData object returned from NSNetservice's addresses method. 275 | * 276 | * If you have an existing struct sockaddr you can convert it to a NSData object like so: 277 | * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; 278 | * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; 279 | * 280 | * This method invokes connectToAdd 281 | **/ 282 | - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; 283 | 284 | /** 285 | * This method is the same as connectToAddress:error: with an additional timeout option. 286 | * To not time out use a negative time interval, or simply use the connectToAddress:error: method. 287 | **/ 288 | - (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr; 289 | 290 | /** 291 | * Connects to the given address, using the specified interface and timeout. 292 | * 293 | * The address is specified as a sockaddr structure wrapped in a NSData object. 294 | * For example, a NSData object returned from NSNetservice's addresses method. 295 | * 296 | * If you have an existing struct sockaddr you can convert it to a NSData object like so: 297 | * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; 298 | * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; 299 | * 300 | * The interface may be a name (e.g. "en1" or "lo0") or the corresponding IP address (e.g. "192.168.4.35"). 301 | * The interface may also be used to specify the local port (see below). 302 | * 303 | * The timeout is optional. To not time out use a negative time interval. 304 | * 305 | * This method will return NO if an error is detected, and set the error pointer (if one was given). 306 | * Possible errors would be a nil host, invalid interface, or socket is already connected. 307 | * 308 | * If no errors are detected, this method will start a background connect operation and immediately return YES. 309 | * The delegate callbacks are used to notify you when the socket connects, or if the host was unreachable. 310 | * 311 | * Since this class supports queued reads and writes, you can immediately start reading and/or writing. 312 | * All read/write operations will be queued, and upon socket connection, 313 | * the operations will be dequeued and processed in order. 314 | * 315 | * The interface may optionally contain a port number at the end of the string, separated by a colon. 316 | * This allows you to specify the local port that should be used for the outgoing connection. (read paragraph to end) 317 | * To specify both interface and local port: "en1:8082" or "192.168.4.35:2424". 318 | * To specify only local port: ":8082". 319 | * Please note this is an advanced feature, and is somewhat hidden on purpose. 320 | * You should understand that 99.999% of the time you should NOT specify the local port for an outgoing connection. 321 | * If you think you need to, there is a very good chance you have a fundamental misunderstanding somewhere. 322 | * Local ports do NOT need to match remote ports. In fact, they almost never do. 323 | * This feature is here for networking professionals using very advanced techniques. 324 | **/ 325 | - (BOOL)connectToAddress:(NSData *)remoteAddr 326 | viaInterface:(NSString *)interface 327 | withTimeout:(NSTimeInterval)timeout 328 | error:(NSError **)errPtr; 329 | 330 | #pragma mark Disconnecting 331 | 332 | /** 333 | * Disconnects immediately (synchronously). Any pending reads or writes are dropped. 334 | * 335 | * If the socket is not already disconnected, an invocation to the socketDidDisconnect:withError: delegate method 336 | * will be queued onto the delegateQueue asynchronously (behind any previously queued delegate methods). 337 | * In other words, the disconnected delegate method will be invoked sometime shortly after this method returns. 338 | * 339 | * Please note the recommended way of releasing a GCDAsyncSocket instance (e.g. in a dealloc method) 340 | * [asyncSocket setDelegate:nil]; 341 | * [asyncSocket disconnect]; 342 | * [asyncSocket release]; 343 | * 344 | * If you plan on disconnecting the socket, and then immediately asking it to connect again, 345 | * you'll likely want to do so like this: 346 | * [asyncSocket setDelegate:nil]; 347 | * [asyncSocket disconnect]; 348 | * [asyncSocket setDelegate:self]; 349 | * [asyncSocket connect...]; 350 | **/ 351 | - (void)disconnect; 352 | 353 | /** 354 | * Disconnects after all pending reads have completed. 355 | * After calling this, the read and write methods will do nothing. 356 | * The socket will disconnect even if there are still pending writes. 357 | **/ 358 | - (void)disconnectAfterReading; 359 | 360 | /** 361 | * Disconnects after all pending writes have completed. 362 | * After calling this, the read and write methods will do nothing. 363 | * The socket will disconnect even if there are still pending reads. 364 | **/ 365 | - (void)disconnectAfterWriting; 366 | 367 | /** 368 | * Disconnects after all pending reads and writes have completed. 369 | * After calling this, the read and write methods will do nothing. 370 | **/ 371 | - (void)disconnectAfterReadingAndWriting; 372 | 373 | #pragma mark Diagnostics 374 | 375 | /** 376 | * Returns whether the socket is disconnected or connected. 377 | * 378 | * A disconnected socket may be recycled. 379 | * That is, it can used again for connecting or listening. 380 | * 381 | * If a socket is in the process of connecting, it may be neither disconnected nor connected. 382 | **/ 383 | - (BOOL)isDisconnected; 384 | - (BOOL)isConnected; 385 | 386 | /** 387 | * Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected. 388 | * The host will be an IP address. 389 | **/ 390 | - (NSString *)connectedHost; 391 | - (uint16_t)connectedPort; 392 | 393 | - (NSString *)localHost; 394 | - (uint16_t)localPort; 395 | 396 | /** 397 | * Returns the local or remote address to which this socket is connected, 398 | * specified as a sockaddr structure wrapped in a NSData object. 399 | * 400 | * See also the connectedHost, connectedPort, localHost and localPort methods. 401 | **/ 402 | - (NSData *)connectedAddress; 403 | - (NSData *)localAddress; 404 | 405 | /** 406 | * Returns whether the socket is IPv4 or IPv6. 407 | * An accepting socket may be both. 408 | **/ 409 | - (BOOL)isIPv4; 410 | - (BOOL)isIPv6; 411 | 412 | /** 413 | * Returns whether or not the socket has been secured via SSL/TLS. 414 | * 415 | * See also the startTLS method. 416 | **/ 417 | - (BOOL)isSecure; 418 | 419 | #pragma mark Reading 420 | 421 | // The readData and writeData methods won't block (they are asynchronous). 422 | // 423 | // When a read is complete the socket:didReadData:withTag: delegate method is dispatched on the delegateQueue. 424 | // When a write is complete the socket:didWriteDataWithTag: delegate method is dispatched on the delegateQueue. 425 | // 426 | // You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.) 427 | // If a read/write opertion times out, the corresponding "socket:shouldTimeout..." delegate method 428 | // is called to optionally allow you to extend the timeout. 429 | // Upon a timeout, the "socket:didDisconnectWithError:" method is called 430 | // 431 | // The tag is for your convenience. 432 | // You can use it as an array index, step number, state id, pointer, etc. 433 | 434 | /** 435 | * Reads the first available bytes that become available on the socket. 436 | * 437 | * If the timeout value is negative, the read operation will not use a timeout. 438 | **/ 439 | - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag; 440 | 441 | /** 442 | * Reads the first available bytes that become available on the socket. 443 | * The bytes will be appended to the given byte buffer starting at the given offset. 444 | * The given buffer will automatically be increased in size if needed. 445 | * 446 | * If the timeout value is negative, the read operation will not use a timeout. 447 | * If the buffer if nil, the socket will create a buffer for you. 448 | * 449 | * If the bufferOffset is greater than the length of the given buffer, 450 | * the method will do nothing, and the delegate will not be called. 451 | * 452 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 453 | * After completion, the data returned in socket:didReadData:withTag: will be a subset of the given buffer. 454 | * That is, it will reference the bytes that were appended to the given buffer. 455 | **/ 456 | - (void)readDataWithTimeout:(NSTimeInterval)timeout 457 | buffer:(NSMutableData *)buffer 458 | bufferOffset:(NSUInteger)offset 459 | tag:(long)tag; 460 | 461 | /** 462 | * Reads the first available bytes that become available on the socket. 463 | * The bytes will be appended to the given byte buffer starting at the given offset. 464 | * The given buffer will automatically be increased in size if needed. 465 | * A maximum of length bytes will be read. 466 | * 467 | * If the timeout value is negative, the read operation will not use a timeout. 468 | * If the buffer if nil, a buffer will automatically be created for you. 469 | * If maxLength is zero, no length restriction is enforced. 470 | * 471 | * If the bufferOffset is greater than the length of the given buffer, 472 | * the method will do nothing, and the delegate will not be called. 473 | * 474 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 475 | * After completion, the data returned in socket:didReadData:withTag: will be a subset of the given buffer. 476 | * That is, it will reference the bytes that were appended to the given buffer. 477 | **/ 478 | - (void)readDataWithTimeout:(NSTimeInterval)timeout 479 | buffer:(NSMutableData *)buffer 480 | bufferOffset:(NSUInteger)offset 481 | maxLength:(NSUInteger)length 482 | tag:(long)tag; 483 | 484 | /** 485 | * Reads the given number of bytes. 486 | * 487 | * If the timeout value is negative, the read operation will not use a timeout. 488 | * 489 | * If the length is 0, this method does nothing and the delegate is not called. 490 | **/ 491 | - (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag; 492 | 493 | /** 494 | * Reads the given number of bytes. 495 | * The bytes will be appended to the given byte buffer starting at the given offset. 496 | * The given buffer will automatically be increased in size if needed. 497 | * 498 | * If the timeout value is negative, the read operation will not use a timeout. 499 | * If the buffer if nil, a buffer will automatically be created for you. 500 | * 501 | * If the length is 0, this method does nothing and the delegate is not called. 502 | * If the bufferOffset is greater than the length of the given buffer, 503 | * the method will do nothing, and the delegate will not be called. 504 | * 505 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 506 | * After completion, the data returned in socket:didReadData:withTag: will be a subset of the given buffer. 507 | * That is, it will reference the bytes that were appended to the given buffer. 508 | **/ 509 | - (void)readDataToLength:(NSUInteger)length 510 | withTimeout:(NSTimeInterval)timeout 511 | buffer:(NSMutableData *)buffer 512 | bufferOffset:(NSUInteger)offset 513 | tag:(long)tag; 514 | 515 | /** 516 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 517 | * 518 | * If the timeout value is negative, the read operation will not use a timeout. 519 | * 520 | * If you pass nil or zero-length data as the "data" parameter, 521 | * the method will do nothing, and the delegate will not be called. 522 | * 523 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 524 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 525 | * a character, the read will prematurely end. 526 | **/ 527 | - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 528 | 529 | /** 530 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 531 | * The bytes will be appended to the given byte buffer starting at the given offset. 532 | * The given buffer will automatically be increased in size if needed. 533 | * 534 | * If the timeout value is negative, the read operation will not use a timeout. 535 | * If the buffer if nil, a buffer will automatically be created for you. 536 | * 537 | * If the bufferOffset is greater than the length of the given buffer, 538 | * the method will do nothing, and the delegate will not be called. 539 | * 540 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 541 | * After completion, the data returned in socket:didReadData:withTag: will be a subset of the given buffer. 542 | * That is, it will reference the bytes that were appended to the given buffer. 543 | * 544 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 545 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 546 | * a character, the read will prematurely end. 547 | **/ 548 | - (void)readDataToData:(NSData *)data 549 | withTimeout:(NSTimeInterval)timeout 550 | buffer:(NSMutableData *)buffer 551 | bufferOffset:(NSUInteger)offset 552 | tag:(long)tag; 553 | 554 | /** 555 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 556 | * 557 | * If the timeout value is negative, the read operation will not use a timeout. 558 | * 559 | * If maxLength is zero, no length restriction is enforced. 560 | * Otherwise if maxLength bytes are read without completing the read, 561 | * it is treated similarly to a timeout - the socket is closed with a GCDAsyncSocketReadMaxedOutError. 562 | * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. 563 | * 564 | * If you pass nil or zero-length data as the "data" parameter, 565 | * the method will do nothing, and the delegate will not be called. 566 | * If you pass a maxLength parameter that is less than the length of the data parameter, 567 | * the method will do nothing, and the delegate will not be called. 568 | * 569 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 570 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 571 | * a character, the read will prematurely end. 572 | **/ 573 | - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag; 574 | 575 | /** 576 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 577 | * The bytes will be appended to the given byte buffer starting at the given offset. 578 | * The given buffer will automatically be increased in size if needed. 579 | * 580 | * If the timeout value is negative, the read operation will not use a timeout. 581 | * If the buffer if nil, a buffer will automatically be created for you. 582 | * 583 | * If maxLength is zero, no length restriction is enforced. 584 | * Otherwise if maxLength bytes are read without completing the read, 585 | * it is treated similarly to a timeout - the socket is closed with a GCDAsyncSocketReadMaxedOutError. 586 | * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. 587 | * 588 | * If you pass a maxLength parameter that is less than the length of the data parameter, 589 | * the method will do nothing, and the delegate will not be called. 590 | * If the bufferOffset is greater than the length of the given buffer, 591 | * the method will do nothing, and the delegate will not be called. 592 | * 593 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 594 | * After completion, the data returned in socket:didReadData:withTag: will be a subset of the given buffer. 595 | * That is, it will reference the bytes that were appended to the given buffer. 596 | * 597 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 598 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 599 | * a character, the read will prematurely end. 600 | **/ 601 | - (void)readDataToData:(NSData *)data 602 | withTimeout:(NSTimeInterval)timeout 603 | buffer:(NSMutableData *)buffer 604 | bufferOffset:(NSUInteger)offset 605 | maxLength:(NSUInteger)length 606 | tag:(long)tag; 607 | 608 | #pragma mark Writing 609 | 610 | /** 611 | * Writes data to the socket, and calls the delegate when finished. 612 | * 613 | * If you pass in nil or zero-length data, this method does nothing and the delegate will not be called. 614 | * If the timeout value is negative, the write operation will not use a timeout. 615 | **/ 616 | - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 617 | 618 | #pragma mark Security 619 | 620 | /** 621 | * Secures the connection using SSL/TLS. 622 | * 623 | * This method may be called at any time, and the TLS handshake will occur after all pending reads and writes 624 | * are finished. This allows one the option of sending a protocol dependent StartTLS message, and queuing 625 | * the upgrade to TLS at the same time, without having to wait for the write to finish. 626 | * Any reads or writes scheduled after this method is called will occur over the secured connection. 627 | * 628 | * The possible keys and values for the TLS settings are well documented. 629 | * Some possible keys are: 630 | * - kCFStreamSSLLevel 631 | * - kCFStreamSSLAllowsExpiredCertificates 632 | * - kCFStreamSSLAllowsExpiredRoots 633 | * - kCFStreamSSLAllowsAnyRoot 634 | * - kCFStreamSSLValidatesCertificateChain 635 | * - kCFStreamSSLPeerName 636 | * - kCFStreamSSLCertificates 637 | * - kCFStreamSSLIsServer 638 | * 639 | * Please refer to Apple's documentation for associated values, as well as other possible keys. 640 | * 641 | * If you pass in nil or an empty dictionary, the default settings will be used. 642 | * 643 | * The default settings will check to make sure the remote party's certificate is signed by a 644 | * trusted 3rd party certificate agency (e.g. verisign) and that the certificate is not expired. 645 | * However it will not verify the name on the certificate unless you 646 | * give it a name to verify against via the kCFStreamSSLPeerName key. 647 | * The security implications of this are important to understand. 648 | * Imagine you are attempting to create a secure connection to MySecureServer.com, 649 | * but your socket gets directed to MaliciousServer.com because of a hacked DNS server. 650 | * If you simply use the default settings, and MaliciousServer.com has a valid certificate, 651 | * the default settings will not detect any problems since the certificate is valid. 652 | * To properly secure your connection in this particular scenario you 653 | * should set the kCFStreamSSLPeerName property to "MySecureServer.com". 654 | * If you do not know the peer name of the remote host in advance (for example, you're not sure 655 | * if it will be "domain.com" or "www.domain.com"), then you can use the default settings to validate the 656 | * certificate, and then use the X509Certificate class to verify the issuer after the socket has been secured. 657 | * The X509Certificate class is part of the CocoaAsyncSocket open source project. 658 | **/ 659 | - (void)startTLS:(NSDictionary *)tlsSettings; 660 | 661 | #pragma mark Advanced 662 | 663 | /** 664 | * It's not thread-safe to access certain variables from outside the socket's internal queue. 665 | * 666 | * For example, the socket file descriptor. 667 | * File descriptors are simply integers which reference an index in the per-process file table. 668 | * However, when one requests a new file descriptor (by opening a file or socket), 669 | * the file descriptor returned is guaranteed to be the lowest numbered unused descriptor. 670 | * So if we're not careful, the following could be possible: 671 | * 672 | * - Thread A invokes a method which returns the socket's file descriptor. 673 | * - The socket is closed via the socket's internal queue on thread B. 674 | * - Thread C opens a file, and subsequently receives the file descriptor that was previously the socket's FD. 675 | * - Thread A is now accessing/altering the file instead of the socket. 676 | * 677 | * In addition to this, other variables are not actually objects, 678 | * and thus cannot be retained/released or even autoreleased. 679 | * An example is the sslContext, of type SSLContextRef, which is actually a malloc'd struct. 680 | * 681 | * Although there are internal variables that make it difficult to maintain thread-safety, 682 | * it is important to provide access to these variables 683 | * to ensure this class can be used in a wide array of environments. 684 | * This method helps to accomplish this by invoking the current block on the socket's internal queue. 685 | * The methods below can be invoked from within the block to access 686 | * those generally thread-unsafe internal variables in a thread-safe manner. 687 | * The given block will be invoked synchronously on the socket's internal queue. 688 | * 689 | * If you save references to any protected variables and use them outside the block, you do so at your own peril. 690 | **/ 691 | - (void)performBlock:(dispatch_block_t)block; 692 | 693 | /** 694 | * These methods are only available from within the context of a performBlock: invocation. 695 | * See the documentation for the performBlock: method above. 696 | * 697 | * Provides access to the socket's file descriptor(s). 698 | * If the socket is a server socket (is accepting incoming connections), 699 | * it might actually have multiple internal socket file descriptors - one for IPv4 and one for IPv6. 700 | **/ 701 | - (int)socketFD; 702 | - (int)socket4FD; 703 | - (int)socket6FD; 704 | 705 | #if TARGET_OS_IPHONE 706 | 707 | /** 708 | * These methods are only available from within the context of a performBlock: invocation. 709 | * See the documentation for the performBlock: method above. 710 | * 711 | * Provides access to the socket's internal CFReadStream/CFWriteStream. 712 | * 713 | * These streams are only used as workarounds for specific iOS shortcomings: 714 | * 715 | * - Apple has decided to keep the SecureTransport framework private is iOS. 716 | * This means the only supplied way to do SSL/TLS is via CFStream or some other API layered on top of it. 717 | * Thus, in order to provide SSL/TLS support on iOS we are forced to rely on CFStream, 718 | * instead of the preferred and faster and more powerful SecureTransport. 719 | * 720 | * - If a socket doesn't have backgrounding enabled, and that socket is closed while the app is backgrounded, 721 | * Apple only bothers to notify us via the CFStream API. 722 | * The faster and more powerful GCD API isn't notified properly in this case. 723 | * 724 | * See also: (BOOL)enableBackgroundingOnSocket 725 | **/ 726 | - (CFReadStreamRef)readStream; 727 | - (CFWriteStreamRef)writeStream; 728 | 729 | /** 730 | * This method is only available from within the context of a performBlock: invocation. 731 | * See the documentation for the performBlock: method above. 732 | * 733 | * Configures the socket to allow it to operate when the iOS application has been backgrounded. 734 | * In other words, this method creates a read & write stream, and invokes: 735 | * 736 | * CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); 737 | * CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); 738 | * 739 | * Returns YES if successful, NO otherwise. 740 | * 741 | * Note: Apple does not officially support backgrounding server sockets. 742 | * That is, if your socket is accepting incoming connections, Apple does not officially support 743 | * allowing iOS applications to accept incoming connections while an app is backgrounded. 744 | * 745 | * Example usage: 746 | * 747 | * - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port 748 | * { 749 | * [asyncSocket performBlock:^{ 750 | * [asyncSocket enableBackgroundingOnSocket]; 751 | * }]; 752 | * } 753 | **/ 754 | - (BOOL)enableBackgroundingOnSocket; 755 | 756 | #else 757 | 758 | /** 759 | * This method is only available from within the context of a performBlock: invocation. 760 | * See the documentation for the performBlock: method above. 761 | * 762 | * Provides access to the socket's SSLContext, if SSL/TLS has been started on the socket. 763 | **/ 764 | - (SSLContextRef)sslContext; 765 | 766 | #endif 767 | 768 | #pragma mark Utilities 769 | 770 | /** 771 | * Extracting host and port information from raw address data. 772 | **/ 773 | + (NSString *)hostFromAddress:(NSData *)address; 774 | + (uint16_t)portFromAddress:(NSData *)address; 775 | + (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr fromAddress:(NSData *)address; 776 | 777 | /** 778 | * A few common line separators, for use with the readDataToData:... methods. 779 | **/ 780 | + (NSData *)CRLFData; // 0x0D0A 781 | + (NSData *)CRData; // 0x0D 782 | + (NSData *)LFData; // 0x0A 783 | + (NSData *)ZeroData; // 0x00 784 | 785 | @end 786 | 787 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 788 | #pragma mark - 789 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 790 | 791 | @protocol GCDAsyncSocketDelegate 792 | @optional 793 | 794 | /** 795 | * This method is called immediately prior to socket:didAcceptNewSocket:. 796 | * It optionally allows a listening socket to specify the socketQueue for a new accepted socket. 797 | * If this method is not implemented, or returns NULL, the new accepted socket will create its own default queue. 798 | * 799 | * Since you cannot autorelease a dispatch_queue, 800 | * this method uses the "new" prefix in its name to specify that the returned queue has been retained. 801 | * 802 | * Thus you could do something like this in the implementation: 803 | * return dispatch_queue_create("MyQueue", NULL); 804 | * 805 | * If you are placing multiple sockets on the same queue, 806 | * then care should be taken to increment the retain count each time this method is invoked. 807 | * 808 | * For example, your implementation might look something like this: 809 | * dispatch_retain(myExistingQueue); 810 | * return myExistingQueue; 811 | **/ 812 | - (dispatch_queue_t)newSocketQueueForConnectionFromAddress:(NSData *)address onSocket:(GCDAsyncSocket *)sock; 813 | 814 | /** 815 | * Called when a socket accepts a connection. 816 | * Another socket is automatically spawned to handle it. 817 | * 818 | * You must retain the newSocket if you wish to handle the connection. 819 | * Otherwise the newSocket instance will be released and the spawned connection will be closed. 820 | * 821 | * By default the new socket will have the same delegate and delegateQueue. 822 | * You may, of course, change this at any time. 823 | **/ 824 | - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket; 825 | 826 | /** 827 | * Called when a socket connects and is ready for reading and writing. 828 | * The host parameter will be an IP address, not a DNS name. 829 | **/ 830 | - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port; 831 | 832 | /** 833 | * Called when a socket has completed reading the requested data into memory. 834 | * Not called if there is an error. 835 | **/ 836 | - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag; 837 | 838 | /** 839 | * Called when a socket has read in data, but has not yet completed the read. 840 | * This would occur if using readToData: or readToLength: methods. 841 | * It may be used to for things such as updating progress bars. 842 | **/ 843 | - (void)socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 844 | 845 | /** 846 | * Called when a socket has completed writing the requested data. Not called if there is an error. 847 | **/ 848 | - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag; 849 | 850 | /** 851 | * Called when a socket has written some data, but has not yet completed the entire write. 852 | * It may be used to for things such as updating progress bars. 853 | **/ 854 | - (void)socket:(GCDAsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 855 | 856 | /** 857 | * Called if a read operation has reached its timeout without completing. 858 | * This method allows you to optionally extend the timeout. 859 | * If you return a positive time interval (> 0) the read's timeout will be extended by the given amount. 860 | * If you don't implement this method, or return a non-positive time interval (<= 0) the read will timeout as usual. 861 | * 862 | * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. 863 | * The length parameter is the number of bytes that have been read so far for the read operation. 864 | * 865 | * Note that this method may be called multiple times for a single read if you return positive numbers. 866 | **/ 867 | - (NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag 868 | elapsed:(NSTimeInterval)elapsed 869 | bytesDone:(NSUInteger)length; 870 | 871 | /** 872 | * Called if a write operation has reached its timeout without completing. 873 | * This method allows you to optionally extend the timeout. 874 | * If you return a positive time interval (> 0) the write's timeout will be extended by the given amount. 875 | * If you don't implement this method, or return a non-positive time interval (<= 0) the write will timeout as usual. 876 | * 877 | * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. 878 | * The length parameter is the number of bytes that have been written so far for the write operation. 879 | * 880 | * Note that this method may be called multiple times for a single write if you return positive numbers. 881 | **/ 882 | - (NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag 883 | elapsed:(NSTimeInterval)elapsed 884 | bytesDone:(NSUInteger)length; 885 | 886 | /** 887 | * Conditionally called if the read stream closes, but the write stream may still be writeable. 888 | * 889 | * This delegate method is only called if autoDisconnectOnClosedReadStream has been set to NO. 890 | * See the discussion on the autoDisconnectOnClosedReadStream method for more information. 891 | **/ 892 | - (void)socketDidCloseReadStream:(GCDAsyncSocket *)sock; 893 | 894 | /** 895 | * Called when a socket disconnects with or without error. 896 | * 897 | * If you call the disconnect method, and the socket wasn't already disconnected, 898 | * this delegate method will be called before the disconnect method returns. 899 | **/ 900 | - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err; 901 | 902 | /** 903 | * Called after the socket has successfully completed SSL/TLS negotiation. 904 | * This method is not called unless you use the provided startTLS method. 905 | * 906 | * If a SSL/TLS negotiation fails (invalid certificate, etc) then the socket will immediately close, 907 | * and the socketDidDisconnect:withError: delegate method will be called with the specific SSL error code. 908 | **/ 909 | - (void)socketDidSecure:(GCDAsyncSocket *)sock; 910 | 911 | @end 912 | --------------------------------------------------------------------------------