PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/iphone/Classes/AsyncUdpSocket.h

http://github.com/appcelerator/titanium_mobile
C Header | 364 lines | 86 code | 49 blank | 229 comment | 0 complexity | c74ec45d98b37c8e8eb7289b1052024e MD5 | raw file
Possible License(s): MIT, JSON, Apache-2.0, 0BSD, CC-BY-SA-3.0, BSD-2-Clause, MPL-2.0-no-copyleft-exception, BSD-3-Clause, CC-BY-3.0, Unlicense
  1. //
  2. // AsyncUdpSocket.h
  3. //
  4. // This class is in the public domain.
  5. // Originally created by Robbie Hanson on Wed Oct 01 2008.
  6. // Updated and maintained by Deusty Designs and the Mac development community.
  7. //
  8. // http://code.google.com/p/cocoaasyncsocket/
  9. //
  10. #import <Foundation/Foundation.h>
  11. @class AsyncSendPacket;
  12. @class AsyncReceivePacket;
  13. extern NSString *const AsyncUdpSocketException;
  14. extern NSString *const AsyncUdpSocketErrorDomain;
  15. enum AsyncUdpSocketError {
  16. AsyncUdpSocketCFSocketError = kCFSocketError, // From CFSocketError enum
  17. AsyncUdpSocketNoError = 0, // Never used
  18. AsyncUdpSocketBadParameter, // Used if given a bad parameter (such as an improper address)
  19. AsyncUdpSocketIPv4Unavailable, // Used if you bind/connect using IPv6 only
  20. AsyncUdpSocketIPv6Unavailable, // Used if you bind/connect using IPv4 only (or iPhone)
  21. AsyncUdpSocketSendTimeoutError,
  22. AsyncUdpSocketReceiveTimeoutError
  23. };
  24. typedef enum AsyncUdpSocketError AsyncUdpSocketError;
  25. @interface AsyncUdpSocket : NSObject {
  26. CFSocketRef theSocket4; // IPv4 socket
  27. CFSocketRef theSocket6; // IPv6 socket
  28. CFRunLoopSourceRef theSource4; // For theSocket4
  29. CFRunLoopSourceRef theSource6; // For theSocket6
  30. CFRunLoopRef theRunLoop;
  31. CFSocketContext theContext;
  32. NSArray *theRunLoopModes;
  33. NSMutableArray *theSendQueue;
  34. AsyncSendPacket *theCurrentSend;
  35. NSTimer *theSendTimer;
  36. NSMutableArray *theReceiveQueue;
  37. AsyncReceivePacket *theCurrentReceive;
  38. NSTimer *theReceiveTimer;
  39. id theDelegate;
  40. UInt16 theFlags;
  41. long theUserData;
  42. NSString *cachedLocalHost;
  43. UInt16 cachedLocalPort;
  44. NSString *cachedConnectedHost;
  45. UInt16 cachedConnectedPort;
  46. UInt32 maxReceiveBufferSize;
  47. }
  48. /**
  49. * Creates new instances of AsyncUdpSocket.
  50. **/
  51. - (id)init;
  52. - (id)initWithDelegate:(id)delegate;
  53. - (id)initWithDelegate:(id)delegate userData:(long)userData;
  54. /**
  55. * Creates new instances of AsyncUdpSocket that support only IPv4 or IPv6.
  56. * The other init methods will support both, unless specifically binded or connected to one protocol.
  57. * If you know you'll only be using one protocol, these init methods may be a bit more efficient.
  58. **/
  59. - (id)initIPv4;
  60. - (id)initIPv6;
  61. - (id)delegate;
  62. - (void)setDelegate:(id)delegate;
  63. - (long)userData;
  64. - (void)setUserData:(long)userData;
  65. /**
  66. * Returns the local address info for the socket.
  67. *
  68. * Note: Address info may not be available until after the socket has been bind'ed,
  69. * or until after data has been sent.
  70. **/
  71. - (NSString *)localHost;
  72. - (UInt16)localPort;
  73. /**
  74. * Returns the remote address info for the socket.
  75. *
  76. * Note: Since UDP is connectionless by design, connected address info
  77. * will not be available unless the socket is explicitly connected to a remote host/port
  78. **/
  79. - (NSString *)connectedHost;
  80. - (UInt16)connectedPort;
  81. /**
  82. * Returns whether or not this socket has been connected to a single host.
  83. * By design, UDP is a connectionless protocol, and connecting is not needed.
  84. * If connected, the socket will only be able to send/receive data to/from the connected host.
  85. **/
  86. - (BOOL)isConnected;
  87. /**
  88. * Returns whether or not this socket has been closed.
  89. * The only way a socket can be closed is if you explicitly call one of the close methods.
  90. **/
  91. - (BOOL)isClosed;
  92. /**
  93. * Returns whether or not this socket supports IPv4.
  94. * By default this will be true, unless the socket is specifically initialized as IPv6 only,
  95. * or is binded or connected to an IPv6 address.
  96. **/
  97. - (BOOL)isIPv4;
  98. /**
  99. * Returns whether or not this socket supports IPv6.
  100. * By default this will be true, unless the socket is specifically initialized as IPv4 only,
  101. * or is binded or connected to an IPv4 address.
  102. *
  103. * This method will also return false on platforms that do not support IPv6.
  104. * Note: The iPhone does not currently support IPv6.
  105. **/
  106. - (BOOL)isIPv6;
  107. /**
  108. * Returns the mtu of the socket.
  109. * If unknown, returns zero.
  110. *
  111. * Sending data larger than this may result in an error.
  112. * This is an advanced topic, and one should understand the wide range of mtu's on networks and the internet.
  113. * Therefore this method is only for reference and may be of little use in many situations.
  114. **/
  115. - (unsigned int)maximumTransmissionUnit;
  116. /**
  117. * Binds the UDP socket to the given port and optional address.
  118. * Binding should be done for server sockets that receive data prior to sending it.
  119. * Client sockets can skip binding,
  120. * as the OS will automatically assign the socket an available port when it starts sending data.
  121. *
  122. * You cannot bind a socket after its been connected.
  123. * You can only bind a socket once.
  124. * You can still connect a socket (if desired) after binding.
  125. *
  126. * On success, returns YES.
  127. * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr.
  128. **/
  129. - (BOOL)bindToPort:(UInt16)port error:(NSError **)errPtr;
  130. - (BOOL)bindToAddress:(NSString *)localAddr port:(UInt16)port error:(NSError **)errPtr;
  131. /**
  132. * Connects the UDP socket to the given host and port.
  133. * By design, UDP is a connectionless protocol, and connecting is not needed.
  134. *
  135. * Choosing to connect to a specific host/port has the following effect:
  136. * - You will only be able to send data to the connected host/port.
  137. * - You will only be able to receive data from the connected host/port.
  138. * - You will receive ICMP messages that come from the connected host/port, such as "connection refused".
  139. *
  140. * Connecting a UDP socket does not result in any communication on the socket.
  141. * It simply changes the internal state of the socket.
  142. *
  143. * You cannot bind a socket after its been connected.
  144. * You can only connect a socket once.
  145. *
  146. * On success, returns YES.
  147. * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr.
  148. **/
  149. - (BOOL)connectToHost:(NSString *)host onPort:(UInt16)port error:(NSError **)errPtr;
  150. - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
  151. /**
  152. * Join multicast group
  153. *
  154. * Group should be an IP address (eg @"225.228.0.1")
  155. **/
  156. - (BOOL)joinMulticastGroup:(NSString *)group error:(NSError **)errPtr;
  157. - (BOOL)joinMulticastGroup:(NSString *)group withAddress:(NSString *)interface error:(NSError **)errPtr;
  158. /**
  159. * By default, the underlying socket in the OS will not allow you to send broadcast messages.
  160. * In order to send broadcast messages, you need to enable this functionality in the socket.
  161. *
  162. * A broadcast is a UDP message to addresses like "192.168.255.255" or "255.255.255.255" that is
  163. * delivered to every host on the network.
  164. * The reason this is generally disabled by default is to prevent
  165. * accidental broadcast messages from flooding the network.
  166. **/
  167. - (BOOL)enableBroadcast:(BOOL)flag error:(NSError **)errPtr;
  168. /**
  169. * Asynchronously sends the given data, with the given timeout and tag.
  170. *
  171. * This method may only be used with a connected socket.
  172. *
  173. * If data is nil or zero-length, this method does nothing and immediately returns NO.
  174. * If the socket is not connected, this method does nothing and immediately returns NO.
  175. **/
  176. - (BOOL)sendData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  177. /**
  178. * Asynchronously sends the given data, with the given timeout and tag, to the given host and port.
  179. *
  180. * This method cannot be used with a connected socket.
  181. *
  182. * If data is nil or zero-length, this method does nothing and immediately returns NO.
  183. * If the socket is connected, this method does nothing and immediately returns NO.
  184. * If unable to resolve host to a valid IPv4 or IPv6 address, this method returns NO.
  185. **/
  186. - (BOOL)sendData:(NSData *)data toHost:(NSString *)host port:(UInt16)port withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  187. /**
  188. * Asynchronously sends the given data, with the given timeout and tag, to the given address.
  189. *
  190. * This method cannot be used with a connected socket.
  191. *
  192. * If data is nil or zero-length, this method does nothing and immediately returns NO.
  193. * If the socket is connected, this method does nothing and immediately returns NO.
  194. **/
  195. - (BOOL)sendData:(NSData *)data toAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  196. /**
  197. * Asynchronously receives a single datagram packet.
  198. *
  199. * If the receive succeeds, the onUdpSocket:didReceiveData:fromHost:port:tag delegate method will be called.
  200. * Otherwise, a timeout will occur, and the onUdpSocket:didNotReceiveDataWithTag: delegate method will be called.
  201. **/
  202. - (void)receiveWithTimeout:(NSTimeInterval)timeout tag:(long)tag;
  203. /**
  204. * Closes the socket immediately. Any pending send or receive operations are dropped.
  205. **/
  206. - (void)close;
  207. /**
  208. * Closes after all pending send operations have completed.
  209. * After calling this, the sendData: and receive: methods will do nothing.
  210. * In other words, you won't be able to add any more send or receive operations to the queue.
  211. * The socket will close even if there are still pending receive operations.
  212. **/
  213. - (void)closeAfterSending;
  214. /**
  215. * Closes after all pending receive operations have completed.
  216. * After calling this, the sendData: and receive: methods will do nothing.
  217. * In other words, you won't be able to add any more send or receive operations to the queue.
  218. * The socket will close even if there are still pending send operations.
  219. **/
  220. - (void)closeAfterReceiving;
  221. /**
  222. * Closes after all pending send and receive operations have completed.
  223. * After calling this, the sendData: and receive: methods will do nothing.
  224. * In other words, you won't be able to add any more send or receive operations to the queue.
  225. **/
  226. - (void)closeAfterSendingAndReceiving;
  227. /**
  228. * Gets/Sets the maximum size of the buffer that will be allocated for receive operations.
  229. * The default size is 9216 bytes.
  230. *
  231. * The theoretical maximum size of any IPv4 UDP packet is UINT16_MAX = 65535.
  232. * The theoretical maximum size of any IPv6 UDP packet is UINT32_MAX = 4294967295.
  233. *
  234. * In practice, however, the size of UDP packets will be much smaller.
  235. * Indeed most protocols will send and receive packets of only a few bytes,
  236. * or will set a limit on the size of packets to prevent fragmentation in the IP layer.
  237. *
  238. * If you set the buffer size too small, the sockets API in the OS will silently discard
  239. * any extra data, and you will not be notified of the error.
  240. **/
  241. - (UInt32)maxReceiveBufferSize;
  242. - (void)setMaxReceiveBufferSize:(UInt32)max;
  243. /**
  244. * When you create an AsyncUdpSocket, it is added to the runloop of the current thread.
  245. * So it is easiest to simply create the socket on the thread you intend to use it.
  246. *
  247. * If, however, you need to move the socket to a separate thread at a later time, this
  248. * method may be used to accomplish the task.
  249. *
  250. * This method must be called from the thread/runloop the socket is currently running on.
  251. *
  252. * Note: After calling this method, all further method calls to this object should be done from the given runloop.
  253. * Also, all delegate calls will be sent on the given runloop.
  254. **/
  255. - (BOOL)moveToRunLoop:(NSRunLoop *)runLoop;
  256. /**
  257. * Allows you to configure which run loop modes the socket uses.
  258. * The default set of run loop modes is NSDefaultRunLoopMode.
  259. *
  260. * If you'd like your socket to continue operation during other modes, you may want to add modes such as
  261. * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes.
  262. *
  263. * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes.
  264. **/
  265. - (BOOL)setRunLoopModes:(NSArray *)runLoopModes;
  266. /**
  267. * Returns the current run loop modes the AsyncSocket instance is operating in.
  268. * The default set of run loop modes is NSDefaultRunLoopMode.
  269. **/
  270. - (NSArray *)runLoopModes;
  271. @end
  272. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  273. #pragma mark -
  274. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  275. @protocol AsyncUdpSocketDelegate
  276. @optional
  277. /**
  278. * Called when the datagram with the given tag has been sent.
  279. **/
  280. - (void)onUdpSocket:(AsyncUdpSocket *)sock didSendDataWithTag:(long)tag;
  281. /**
  282. * Called if an error occurs while trying to send a datagram.
  283. * This could be due to a timeout, or something more serious such as the data being too large to fit in a sigle packet.
  284. **/
  285. - (void)onUdpSocket:(AsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error;
  286. /**
  287. * Called when the socket has received the requested datagram.
  288. *
  289. * Due to the nature of UDP, you may occasionally receive undesired packets.
  290. * These may be rogue UDP packets from unknown hosts,
  291. * or they may be delayed packets arriving after retransmissions have already occurred.
  292. * It's important these packets are properly ignored, while not interfering with the flow of your implementation.
  293. * As an aid, this delegate method has a boolean return value.
  294. * If you ever need to ignore a received packet, simply return NO,
  295. * and AsyncUdpSocket will continue as if the packet never arrived.
  296. * That is, the original receive request will still be queued, and will still timeout as usual if a timeout was set.
  297. * For example, say you requested to receive data, and you set a timeout of 500 milliseconds, using a tag of 15.
  298. * If rogue data arrives after 250 milliseconds, this delegate method would be invoked, and you could simply return NO.
  299. * If the expected data then arrives within the next 250 milliseconds,
  300. * this delegate method will be invoked, with a tag of 15, just as if the rogue data never appeared.
  301. *
  302. * Under normal circumstances, you simply return YES from this method.
  303. **/
  304. - (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port;
  305. /**
  306. * Called if an error occurs while trying to receive a requested datagram.
  307. * This is generally due to a timeout, but could potentially be something else if some kind of OS error occurred.
  308. **/
  309. - (void)onUdpSocket:(AsyncUdpSocket *)sock didNotReceiveDataWithTag:(long)tag dueToError:(NSError *)error;
  310. /**
  311. * Called when the socket is closed.
  312. * A socket is only closed if you explicitly call one of the close methods.
  313. **/
  314. - (void)onUdpSocketDidClose:(AsyncUdpSocket *)sock;
  315. @end