Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: rsms/peertalk
base: bb39e6d247
...
head fork: rsms/peertalk
compare: a454694e87
  • 5 commits
  • 6 files changed
  • 0 commit comments
  • 1 contributor
Commits on Apr 21, 2012
@rsms using a custom struct to pass the message, for illustrating the use o…
…f sending custom structured data
072016a
@rsms fixed a memory bug where, in the case of an error, PTProtocol would n…
…ot release gathered payload data, causing a memory leak
f6b352f
@rsms catching errors in PTChannel and passing them to the end delegate method fd469e8
@rsms Contribution by bwalkin: Added +NSData*[NSData dataWithContentsOfDisp…
…atchData:(dispatch_data_t)data] to easily wrap (not neccesarily copy) a dispatch_data_t object and make it sequential in an NSData object. The returned NSData object will own a reference to the dispatch_data_t object and thus can manage its lifetime
351e6c9
@rsms changed back mode from 0755 -> 0644 a454694
View
6 Peertalk Example/PTAppDelegate.m
@@ -79,7 +79,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
- (IBAction)sendMessage:(id)sender {
if (connectedChannel_) {
NSString *message = self.inputTextField.stringValue;
- dispatch_data_t payload = [[message dataUsingEncoding:NSUTF8StringEncoding] createReferencingDispatchData];
+ dispatch_data_t payload = PTExampleTextDispatchDataWithString(message);
[connectedChannel_ sendFrameOfType:PTExampleFrameTypeTextMessage tag:PTFrameNoTag withPayload:payload callback:^(NSError *error) {
if (error) {
NSLog(@"Failed to send message: %@", error);
@@ -199,7 +199,9 @@ - (void)ioFrameChannel:(PTChannel*)channel didReceiveFrameOfType:(uint32_t)type
NSDictionary *deviceInfo = [NSDictionary dictionaryWithContentsOfDispatchData:payload.dispatchData];
[self presentMessage:[NSString stringWithFormat:@"Connected to %@", deviceInfo.description] isStatus:YES];
} else if (type == PTExampleFrameTypeTextMessage) {
- NSString *message = [[NSString alloc] initWithBytes:payload.data length:payload.length encoding:NSUTF8StringEncoding];
+ PTExampleTextFrame *textFrame = (PTExampleTextFrame*)payload.data;
+ textFrame->length = ntohl(textFrame->length);
+ NSString *message = [[NSString alloc] initWithBytes:textFrame->utf8text length:textFrame->length encoding:NSUTF8StringEncoding];
[self presentMessage:[NSString stringWithFormat:@"[%@]: %@", channel.userInfo, message] isStatus:NO];
} else if (type == PTExampleFrameTypePong) {
[self pongWithTag:tag error:nil];
View
20 Peertalk Example/PTExampleProtocol.h
@@ -13,4 +13,24 @@ enum {
PTExampleFrameTypePong = 103,
};
+typedef struct _PTExampleTextFrame {
+ uint32_t length;
+ uint8_t utf8text[0];
+} PTExampleTextFrame;
+
+
+static dispatch_data_t PTExampleTextDispatchDataWithString(NSString *message) {
+ // Use a custom struct
+ const char *utf8text = [message cStringUsingEncoding:NSUTF8StringEncoding];
+ size_t length = strlen(utf8text);
+ PTExampleTextFrame *textFrame = CFAllocatorAllocate(nil, sizeof(PTExampleTextFrame) + length, 0);
+ memcpy(textFrame->utf8text, utf8text, length); // Copy bytes to utf8text array
+ textFrame->length = htonl(length); // Convert integer to network byte order
+
+ // Wrap the textFrame in a dispatch data object
+ return dispatch_data_create((const void*)textFrame, sizeof(PTExampleTextFrame)+length, nil, ^{
+ CFAllocatorDeallocate(nil, textFrame);
+ });
+}
+
#endif
View
6 Peertalk iOS Example/PTViewController.m
@@ -58,7 +58,7 @@ - (BOOL)textFieldShouldReturn:(UITextField *)textField {
- (void)sendMessage:(NSString*)message {
if (peerChannel_) {
- dispatch_data_t payload = [[message dataUsingEncoding:NSUTF8StringEncoding] createReferencingDispatchData];
+ dispatch_data_t payload = PTExampleTextDispatchDataWithString(message);
[peerChannel_ sendFrameOfType:PTExampleFrameTypeTextMessage tag:PTFrameNoTag withPayload:payload callback:^(NSError *error) {
if (error) {
NSLog(@"Failed to send message: %@", error);
@@ -135,7 +135,9 @@ - (BOOL)ioFrameChannel:(PTChannel*)channel shouldAcceptFrameOfType:(uint32_t)typ
- (void)ioFrameChannel:(PTChannel*)channel didReceiveFrameOfType:(uint32_t)type tag:(uint32_t)tag payload:(PTData*)payload {
//NSLog(@"didReceiveFrameOfType: %u, %u, %@", type, tag, payload);
if (type == PTExampleFrameTypeTextMessage) {
- NSString *message = [[NSString alloc] initWithBytes:payload.data length:payload.length encoding:NSUTF8StringEncoding];
+ PTExampleTextFrame *textFrame = (PTExampleTextFrame*)payload.data;
+ textFrame->length = ntohl(textFrame->length);
+ NSString *message = [[NSString alloc] initWithBytes:textFrame->utf8text length:textFrame->length encoding:NSUTF8StringEncoding];
[self appendOutputMessage:[NSString stringWithFormat:@"[%@]: %@", channel.userInfo, message]];
} else if (type == PTExampleFrameTypePing && peerChannel_) {
[peerChannel_ sendFrameOfType:PTExampleFrameTypePong tag:tag withPayload:nil callback:nil];
View
12 peertalk/PTChannel.m
@@ -35,6 +35,7 @@ @interface PTChannel () {
dispatch_io_t channel;
dispatch_source_t source;
} dispatchObj_; // 64 bit
+ NSError *endError_; // 64 bit
@public // here be hacks
id<PTChannelDelegate> delegate_; // 64 bit
uint8_t delegateFlags_; // 8 bit
@@ -203,6 +204,7 @@ - (void)connectToPort:(int)port overUSBHub:(PTUSBHub*)usbHub deviceID:(NSNumber*
if (delegateFlags_ & kDelegateFlagImplements_ioFrameChannel_didEndWithError) {
[delegate_ ioFrameChannel:self didEndWithError:error];
}
+ endError_ = nil;
}];
}
@@ -261,8 +263,9 @@ - (void)connectToPort:(in_port_t)port IPv4Address:(in_addr_t)ipv4Address callbac
dispatch_io_t dispatchChannel = dispatch_io_create(DISPATCH_IO_STREAM, fd, protocol_.queue, ^(int error) {
close(fd);
if (delegateFlags_ & kDelegateFlagImplements_ioFrameChannel_didEndWithError) {
- NSError *err = error == 0 ? nil : [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil];
+ NSError *err = error == 0 ? endError_ : [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil];
[delegate_ ioFrameChannel:self didEndWithError:err];
+ endError_ = nil;
}
});
@@ -348,7 +351,8 @@ - (void)listenOnPort:(in_port_t)port IPv4Address:(in_addr_t)address callback:(vo
dispatchObj_.source = nil;
close(fd);
if (delegateFlags_ & kDelegateFlagImplements_ioFrameChannel_didEndWithError) {
- [delegate_ ioFrameChannel:self didEndWithError:nil];
+ [delegate_ ioFrameChannel:self didEndWithError:endError_];
+ endError_ = nil;
}
});
@@ -388,8 +392,9 @@ - (BOOL)acceptIncomingConnection:(dispatch_fd_t)serverSocketFD {
close(clientSocketFD);
if (channel->delegateFlags_ & kDelegateFlagImplements_ioFrameChannel_didEndWithError) {
- NSError *err = error == 0 ? nil : [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil];
+ NSError *err = error == 0 ? endError_ : [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil];
[channel->delegate_ ioFrameChannel:channel didEndWithError:err];
+ endError_ = nil;
}
});
@@ -454,6 +459,7 @@ - (BOOL)startReadingFromConnectedChannel:(dispatch_io_t)channel error:(__autorel
BOOL(^handleError)(NSError*,BOOL) = ^BOOL(NSError *error, BOOL isEOS) {
if (error) {
//NSLog(@"Error while communicating: %@", error);
+ endError_ = error;
[self close];
return YES;
} else if (isEOS) {
View
1  peertalk/PTProtocol.h
@@ -103,6 +103,7 @@ NSString *PTProtocolErrorDomain;
// holds a reference to the recevier. It's the callers responsibility to call
// dispatch_release on the returned object when done.
- (dispatch_data_t)createReferencingDispatchData;
++ (NSData *)dataWithContentsOfDispatchData:(dispatch_data_t)data;
@end
@interface NSDictionary (PTProtocol)
View
40 peertalk/PTProtocol.m
@@ -1,4 +1,5 @@
#import "PTProtocol.h"
+#import <objc/runtime.h>
static const uint32_t PTProtocolVersion1 = 1;
@@ -233,11 +234,13 @@ - (void)readPayloadOfSize:(size_t)payloadSize overChannel:(dispatch_io_t)channel
if (done) {
if (error != 0) {
+ if (allData) dispatch_release(allData);
callback([[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil], NULL, NULL, 0);
return;
}
if (dataSize == 0) {
+ if (allData) dispatch_release(allData);
callback(nil, NULL, NULL, 0);
return;
}
@@ -254,6 +257,7 @@ - (void)readPayloadOfSize:(size_t)payloadSize overChannel:(dispatch_io_t)channel
return;
}
}
+
callback(nil, contiguousData, buffer, bufferSize);
if (contiguousData) dispatch_release(contiguousData);
}
@@ -285,6 +289,22 @@ - (void)readFramesOverChannel:(dispatch_io_t)channel onFrame:(void(^)(NSError*,
@end
+@interface _PTDispatchData : NSObject {
+ dispatch_data_t dispatchData_;
+}
+@end
+@implementation _PTDispatchData
+- (id)initWithDispatchData:(dispatch_data_t)dispatchData {
+ if (!(self = [super init])) return nil;
+ dispatchData_ = dispatchData;
+ dispatch_retain(dispatchData_);
+ return self;
+}
+- (void)dealloc {
+ if (dispatchData_) dispatch_release(dispatchData_);
+}
+@end
+
@implementation NSData (PTProtocol)
- (dispatch_data_t)createReferencingDispatchData {
@@ -297,6 +317,26 @@ - (dispatch_data_t)createReferencingDispatchData {
});
}
++ (NSData *)dataWithContentsOfDispatchData:(dispatch_data_t)data {
+ if (!data) {
+ return nil;
+ }
+ uint8_t *buffer = NULL;
+ size_t bufferSize = 0;
+ dispatch_data_t contiguousData = dispatch_data_create_map(data, (const void **)&buffer, &bufferSize);
+ if (!contiguousData) {
+ return nil;
+ }
+
+ _PTDispatchData *dispatchDataRef = [[_PTDispatchData alloc] initWithDispatchData:contiguousData];
+ NSData *newData = [NSData dataWithBytesNoCopy:(void*)buffer length:bufferSize freeWhenDone:NO];
+ dispatch_release(contiguousData);
+ static const bool kDispatchDataRefKey;
+ objc_setAssociatedObject(newData, (const void*)kDispatchDataRefKey, dispatchDataRef, OBJC_ASSOCIATION_RETAIN);
+
+ return newData;
+}
+
@end

No commit comments for this range

Something went wrong with that request. Please try again.