Lookin_PTProtocol.h 4.9 KB

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