Lookin_PTProtocol.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //
  2. // A universal frame-based communication protocol which can be used to exchange
  3. // arbitrary structured data.
  4. //
  5. // In short:
  6. //
  7. // - Each transmission is comprised by one fixed-size frame.
  8. // - Each frame contains a protocol version number.
  9. // - Each frame contains an application frame type.
  10. // - Each frame can contain an identifying tag.
  11. // - Each frame can have application-specific data of up to UINT32_MAX size.
  12. // - Transactions style messaging can be modeled on top using frame tags.
  13. // - Lightweight API on top of libdispatch (aka GCD) -- close to the metal.
  14. //
  15. #include <dispatch/dispatch.h>
  16. #import <Foundation/Foundation.h>
  17. // Special frame tag that signifies "no tag". Your implementation should never
  18. // create a reply for a frame with this tag.
  19. static const uint32_t PTFrameNoTag = 0;
  20. // Special frame type that signifies that the stream has ended.
  21. static const uint32_t PTFrameTypeEndOfStream = 0;
  22. // NSError domain
  23. FOUNDATION_EXPORT NSString * const Lookin_PTProtocolErrorDomain;
  24. @interface Lookin_PTProtocol : NSObject
  25. // Queue on which to run data processing blocks.
  26. @property dispatch_queue_t queue;
  27. // Get the shared protocol object for *queue*
  28. + (Lookin_PTProtocol*)sharedProtocolForQueue:(dispatch_queue_t)queue;
  29. // Initialize a new protocol object to use a specific queue.
  30. - (id)initWithDispatchQueue:(dispatch_queue_t)queue;
  31. // Initialize a new protocol object to use the current calling queue.
  32. - (id)init;
  33. #pragma mark Sending frames
  34. // Generate a new tag that is unique within this protocol object.
  35. - (uint32_t)newTag;
  36. // Send a frame over *channel* with an optional payload and optional callback.
  37. // If *callback* is not NULL, the block is invoked when either an error occured
  38. // or when the frame (and payload, if any) has been completely sent.
  39. - (void)sendFrameOfType:(uint32_t)frameType
  40. tag:(uint32_t)tag
  41. withPayload:(dispatch_data_t)payload
  42. overChannel:(dispatch_io_t)channel
  43. callback:(void(^)(NSError *error))callback;
  44. #pragma mark Receiving frames
  45. // Read frames over *channel* as they arrive.
  46. // The onFrame handler is responsible for reading (or discarding) any payload
  47. // and call *resumeReadingFrames* afterwards to resume reading frames.
  48. // To stop reading frames, simply do not invoke *resumeReadingFrames*.
  49. // When the stream ends, a frame of type PTFrameTypeEndOfStream is received.
  50. - (void)readFramesOverChannel:(dispatch_io_t)channel
  51. onFrame:(void(^)(NSError *error,
  52. uint32_t type,
  53. uint32_t tag,
  54. uint32_t payloadSize,
  55. dispatch_block_t resumeReadingFrames))onFrame;
  56. // Read a single frame over *channel*. A frame of type PTFrameTypeEndOfStream
  57. // denotes the stream has ended.
  58. - (void)readFrameOverChannel:(dispatch_io_t)channel
  59. callback:(void(^)(NSError *error,
  60. uint32_t frameType,
  61. uint32_t frameTag,
  62. uint32_t payloadSize))callback;
  63. #pragma mark Receiving frame payloads
  64. // Read a complete payload. It's the callers responsibility to make sure
  65. // payloadSize is not too large since memory will be automatically allocated
  66. // where only payloadSize is the limit.
  67. // The returned dispatch_data_t object owns *buffer* and thus you need to call
  68. // dispatch_retain on *contiguousData* if you plan to keep *buffer* around after
  69. // returning from the callback.
  70. - (void)readPayloadOfSize:(size_t)payloadSize
  71. overChannel:(dispatch_io_t)channel
  72. callback:(void(^)(NSError *error,
  73. dispatch_data_t contiguousData,
  74. const uint8_t *buffer,
  75. size_t bufferSize))callback;
  76. // Discard data of *size* waiting on *channel*. *callback* can be NULL.
  77. - (void)readAndDiscardDataOfSize:(size_t)size
  78. overChannel:(dispatch_io_t)channel
  79. callback:(void(^)(NSError *error, BOOL endOfStream))callback;
  80. @end
  81. @interface NSData (Lookin_PTProtocol)
  82. // Creates a new dispatch_data_t object which references the receiver and uses
  83. // the receivers bytes as its backing data. The returned dispatch_data_t object
  84. // holds a reference to the recevier. It's the callers responsibility to call
  85. // dispatch_release on the returned object when done.
  86. - (dispatch_data_t)createReferencingDispatchData;
  87. + (NSData *)dataWithContentsOfDispatchData:(dispatch_data_t)data;
  88. @end
  89. @interface NSDictionary (Lookin_PTProtocol)
  90. // See description of -[NSData(Lookin_PTProtocol) createReferencingDispatchData]
  91. - (dispatch_data_t)createReferencingDispatchData;
  92. // Decode *data* as a peroperty list-encoded dictionary. Returns nil on failure.
  93. + (NSDictionary*)dictionaryWithContentsOfDispatchData:(dispatch_data_t)data;
  94. @end