5
// Created by döme on 25.10.2009.
6
// Copyright 2009 __MyCompanyName__. All rights reserved.
9
#import "TappityClient.h"
13
#include <sys/socket.h>
15
#include <netinet/in.h>
18
@implementation TappityClient
20
- (void) runThreadWithSelector: (SEL) selector
25
activeThreads = [[NSMutableDictionary alloc] init];
26
id number = [NSNumber numberWithInt: threadIds++];
28
[activeThreads setObject: [NSNumber numberWithBool: YES] forKey: number];
29
[NSThread detachNewThreadSelector: selector toTarget: self withObject: [number retain]];
34
- (void) connectToService: (NSNetService*) service
36
NSInteger port = [service port];
37
NSString* hostName = [service hostName];
39
NSLog(@"tappity attempting to connect to %@ : %d", hostName, port);
44
// _setStandardSocketOpts(socket);
46
struct addrinfo hints, *servinfo = NULL, *p = NULL;
49
memset(&hints, 0, sizeof hints);
50
hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
51
hints.ai_socktype = SOCK_STREAM;
52
//hints.ai_protocol = IPPROTO_TCP;
53
hints.ai_flags = AI_PASSIVE;
55
// NSHost* host = [NSHost hostWithName: hostName];
57
if ((rv = getaddrinfo([hostName UTF8String], [[NSString stringWithFormat: @"%d", port] UTF8String], &hints, &servinfo)) != 0)
59
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
63
// loop through all the results and connect to the first we can
64
for(p = servinfo; p != NULL; p = p->ai_next)
66
if ((sockfd = socket(p->ai_family, p->ai_socktype,
67
p->ai_protocol)) == -1) {
72
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
78
break; // if we get here, we must have connected successfully
82
// looped off the end of the list with no connection
83
fprintf(stderr, "failed to connect\n");
87
freeaddrinfo(servinfo); // all done with this structure
89
NSLog(@"tappity connected");
92
self->commsSocket = sockfd;
95
sendLock = [[NSCondition alloc] init];
97
[self runThreadWithSelector: @selector(sendingThread:)];
103
- (void) sendTapData: (NSData*) tapData
108
sendQueue = [[NSMutableArray alloc] init];
110
[sendQueue addObject: tapData];
118
- (void) recordApplicationEvent: (NSDictionary*) event
120
// NSLog(@"%@", event);
121
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: kTapRecordedEvent], TapIdKey, event, TapRecordedEventKey, nil];
123
NSData* data = [NSPropertyListSerialization dataFromPropertyList: dict format: NSPropertyListBinaryFormat_v1_0 errorDescription: nil];
125
[self sendTapData: data];
130
- (BOOL) threadActive: (id) key
132
return [[activeThreads objectForKey: key] boolValue];
136
- (void) sendingThread: (id) info
138
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
145
while ([self threadActive: info])
148
while (![sendQueue count])
151
NSLog(@"sending tap");
153
NSData* data = [[sendQueue objectAtIndex: 0] retain];
154
[sendQueue removeObjectAtIndex: 0];
156
size_t sizeToSend = 4;
158
uint32_t header = htonl([data length]);
161
while (dataSent < sizeToSend)
163
if ((err = send(commsSocket, &header + dataSent, sizeToSend - dataSent, 0)) == -1)
172
sizeToSend = [data length];
174
while (dataSent < sizeToSend)
176
if ((err = send(commsSocket, [data bytes] + dataSent, sizeToSend - dataSent, 0)) == -1)
201
static size_t _write_i8(void* buf, uint8_t val)
203
memcpy(buf, &val, 1);
207
static size_t _write_i16(void* buf, uint16_t val)
209
val = CFSwapInt16HostToBig(val);
210
memcpy(buf, &val, 2);
214
static size_t _write_i32(void* buf, uint32_t val)
216
val = CFSwapInt32HostToBig(val);
217
memcpy(buf, &val, 4);
221
static size_t _write_i64(void* buf, uint64_t val)
223
val = CFSwapInt64HostToBig(val);
224
memcpy(buf, &val, 8);
228
static size_t _write_float(void* buf, float val)
230
CFSwappedFloat32 v = CFConvertFloat32HostToSwapped(val);
235
static size_t _write_gspoint(void* buf, GSTouchPointRef p)
239
bc += _write_i32(buf+bc, p->unk0);
240
bc += _write_float(buf+bc, p->unk1);
241
bc += _write_float(buf+bc, p->touchSize);
242
bc += _write_float(buf+bc, p->x);
243
bc += _write_float(buf+bc, p->y);
244
bc += _write_i32(buf+bc, (uint32_t)p->window);
250
- (id) plistWithTouches: (NSSet*) touches
252
NSMutableArray* ary = [NSMutableArray array];
254
for (UITouch* touch in touches)
256
NSMutableData* tdata = [NSMutableData dataWithLength: sizeof(UITouch)];
258
void* buf = [tdata mutableBytes];
259
bc += _write_double(buf+bc, touch->_timestamp);
267
- (void) sendTouch: (UIEvent*) event inPhase: (int) phase
270
NSMutableDictionary* touchDict = [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: kTapTouchEvent], TapIdKey, nil];
272
// [touchDict setObject: [self touchesAsPlist: [event allTouches]] forKey: TapTouchesKey];
274
GSEvent* gse = [event _gsEvent];
276
NSMutableData* gsData = [NSMutableData dataWithLength: sizeof(GSEvent)];
278
void* buf = [gsData mutableBytes];
280
bc += _write_i32(buf + bc, gse->type0);
281
bc += _write_i32(buf + bc, gse->type1);
282
bc += _write_i32(buf + bc, gse->r3);
283
bc += _write_float(buf + bc, gse->avgX0);
284
bc += _write_float(buf + bc, gse->avgY0);
285
bc += _write_float(buf + bc, gse->avgX1);
286
bc += _write_float(buf + bc, gse->avgY1);
287
bc += _write_i32(buf + bc, gse->processId);
288
bc += _write_i64(buf + bc, gse->timestamp);
289
bc += _write_i32(buf + bc, (uint32_t)gse->window);
290
bc += _write_i32(buf + bc, gse->r11);
291
bc += _write_i32(buf + bc, gse->type12);
292
bc += _write_i32(buf + bc, gse->gesture13);
293
bc += _write_i32(buf + bc, gse->gesture14);
294
bc += _write_i16(buf + bc, gse->numInitialTouches);
295
bc += _write_i16(buf + bc, gse->numCurrentTouches);
296
bc += _write_i32(buf + bc, gse->r16);
297
bc += _write_i32(buf + bc, gse->r17);
298
bc += _write_i32(buf + bc, gse->r18);
299
bc += _write_i32(buf + bc, gse->r19);
300
bc += _write_i32(buf + bc, gse->r20);
301
bc += _write_i32(buf + bc, gse->r21);
302
bc += _write_i8(buf + bc, gse->r22_0);
303
bc += _write_i8(buf + bc, gse->numPoints);
304
bc += _write_i8(buf + bc, gse->r22_2);
305
for (size_t i = 0; i < gse->numPoints; ++i)
306
bc += _write_gspoint(buf+bc, gse->points+i);
308
[touchDict setObject: gsData forKey: TapGSEventKey];
309
[touchDict setObject: [NSNumber numberWithInt: phase] forKey: TapTouchPhaseKey];
310
//[touchDict setObject: [self plistWithTouches: [event allTouches]] forKey: TapTouchesKey];
312
NSData* data = [NSPropertyListSerialization dataFromPropertyList: touchDict format: NSPropertyListBinaryFormat_v1_0 errorDescription: nil];
314
[self sendTapData: data];
320
[currentData release];
322
[activeThreads release];