5
// Created by döme on 25.10.2009.
6
// Copyright 2009 __MyCompanyName__. All rights reserved.
9
#import "TappityServer.h"
13
static void _setStandardSocketOpts(int socket)
16
setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
18
setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
19
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
22
@interface UIApplication (TappityPrivate)
23
- (void)_playbackEvents:(id)arg1 atPlaybackRate:(float)arg2 messageWhenDone:(id)arg3 withSelector:(SEL)arg4;
26
@implementation TappityServer
28
- (BOOL) threadActive: (id) key
30
return [[activeThreads objectForKey: key] boolValue];
33
- (void) receivingThread: (id) info
35
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
42
while ([self threadActive: info])
57
FD_SET(commsSocket, &readfds);
58
FD_SET(commsSocket, &errorfds);
59
maxSocket = MAX(maxSocket, commsSocket);
63
//printf("No sockets, sleeping for a bit...\n");
68
if (select(maxSocket+1, &readfds, &writefds, &errorfds, &tv) < 0)
74
if (FD_ISSET(commsSocket, &readfds))
76
NSLog(@"receiving...");
77
if (!expectedMessageSize)
82
actuallyRead = recv(commsSocket, &buf, sizeof(uint32_t), MSG_PEEK);
84
if (actuallyRead == sizeof(uint32_t))
86
actuallyRead = recv(commsSocket, &buf, sizeof(uint32_t), 0);
87
expectedMessageSize = ntohl(buf);
88
currentData = [[NSMutableData alloc] initWithLength: expectedMessageSize];
90
else if (!actuallyRead)
92
// close this socket as nothing read means connection closed
94
self->commsSocket = 0;
95
printf("Connection dropped.\n");
98
if (actuallyRead == -1)
101
self->commsSocket = 0;
102
printf("Connection dropped with error.\n");
108
size_t readAmount = expectedMessageSize - currentlyRead;
109
int actuallyRead = 0;
111
actuallyRead = recv(commsSocket, [currentData mutableBytes] + currentlyRead, readAmount, 0);
112
if (actuallyRead == -1)
115
self->commsSocket = 0;
116
printf("Connection dropped with error.\n");
119
currentlyRead += actuallyRead;
121
if (currentlyRead == expectedMessageSize)
125
expectedMessageSize = 0;
127
if (!receivedPackets)
128
receivedPackets = [[NSMutableArray alloc] init];
129
[receivedPackets addObject: currentData];
130
[currentData release];
134
[self performSelectorOnMainThread: @selector(tapReceived:) withObject: currentData waitUntilDone: NO];
153
- (void) runThreadWithSelector: (SEL) selector
158
activeThreads = [[NSMutableDictionary alloc] init];
159
id number = [NSNumber numberWithInt: threadIds++];
161
[activeThreads setObject: [NSNumber numberWithBool: YES] forKey: number];
162
[NSThread detachNewThreadSelector: selector toTarget: self withObject: [number retain]];
166
- (void) acceptThread: (id) info
168
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
175
while ([self threadActive: info])
191
FD_SET(listenSocket, &readfds);
192
FD_SET(listenSocket, &errorfds);
193
maxSocket = MAX(maxSocket, listenSocket);
197
printf("No sockets, sleeping for a bit...\n");
202
//NSLog(@"listening for connection...");
204
if (select(maxSocket+1, &readfds, &writefds, &errorfds, &tv) < 0)
210
if (FD_ISSET(listenSocket, &readfds))
212
NSLog(@"Accepting connection...");
214
socklen_t sinSize = sizeof(struct sockaddr_in);
215
struct sockaddr_in peerAddress;
216
int newSocket = accept(listenSocket, (struct sockaddr *)&peerAddress, &sinSize);
218
_setStandardSocketOpts(newSocket);
223
if (errno == EWOULDBLOCK)
228
printf("Error accepting connection.\n");
236
// add socket to sockets list
237
commsSocket = newSocket;
240
[self runThreadWithSelector: @selector(receivingThread:)];
242
NSLog(@"Accepted connection.");
256
- (BOOL) enableBonjourWithDomain:(NSString*)domain applicationProtocol:(NSString*)protocol name:(NSString*)name
259
domain = @""; //Will use default Bonjour registration doamins, typically just ".local"
261
name = @""; //Will use default Bonjour name, e.g. the name assigned to the device in iTunes
263
assert([protocol length] && listenSocket);
265
NSLog(@"tappity port: %d", ntohs(myAddress.sin_port));
267
netService = [[NSNetService alloc] initWithDomain: domain type: protocol name: name port: ntohs(myAddress.sin_port)];
268
if(netService == nil)
271
[netService setDelegate:self];
272
// [netService scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
273
[netService publish];
280
NSLog(@"starting tappity server");
281
myAddress.sin_family = AF_INET; // host byte order
282
myAddress.sin_port = htons(1234); // short, network byte order, any port
283
myAddress.sin_addr.s_addr = htonl(INADDR_ANY); // auto-fill with my IP
285
listenSocket = socket(PF_INET, SOCK_STREAM, 0);
286
assert(listenSocket != -1);
288
_setStandardSocketOpts(listenSocket);
290
int err = bind(self->listenSocket, (struct sockaddr *)&myAddress, sizeof(myAddress));
293
err = listen(self->listenSocket, 1);
296
[self runThreadWithSelector: @selector(acceptThread:)];
298
if([self enableBonjourWithDomain: @"" applicationProtocol: @"_tappity._tcp" name: @"tappity"])
299
NSLog(@"tappity bounjour advertisments up and running");
303
static size_t _read_i8(const void* buf, uint8_t* p)
310
static size_t _read_i16(const void* buf, uint16_t* p)
314
*p = CFSwapInt16BigToHost(v);
317
static size_t _read_i32(const void* buf, uint32_t* p)
321
*p = CFSwapInt32BigToHost(v);
324
static size_t _read_i64(const void* buf, uint64_t* p)
328
*p = CFSwapInt64BigToHost(v);
331
static size_t _read_float(const void* buf, float* p)
335
*p = CFConvertFloat32SwappedToHost(v);
339
static size_t _read_gspoint(const void* buf, GSTouchPointRef p)
343
bc += _read_i32(buf+bc, &p->unk0);
344
bc += _read_float(buf+bc, &p->unk1);
345
bc += _read_float(buf+bc, &p->touchSize);
346
bc += _read_float(buf+bc, &p->x);
347
bc += _read_float(buf+bc, &p->y);
348
bc += _read_i32(buf+bc, (uint32_t*)&p->window);
353
- (GSEvent*) gsEventWithData: (NSData*) data
355
GSEvent* gse = [[[GSEvent alloc] init] autorelease];
358
const void* buf = [data bytes];
360
bc += _read_i32(buf+bc, &gse->type0);
361
bc += _read_i32(buf+bc, &gse->type1);
362
bc += _read_i32(buf+bc, &gse->r3);
363
bc += _read_float(buf+bc, &gse->avgX0);
364
bc += _read_float(buf+bc, &gse->avgY0);
365
bc += _read_float(buf+bc, &gse->avgX1);
366
bc += _read_float(buf+bc, &gse->avgY1);
367
bc += _read_i32(buf+bc, &gse->processId);
368
bc += _read_i64(buf+bc, &gse->timestamp);
369
bc += _read_i32(buf+bc, (uint32_t*)&gse->window);
370
bc += _read_i32(buf+bc, &gse->r11);
371
bc += _read_i32(buf+bc, &gse->type12);
372
bc += _read_i32(buf+bc, &gse->gesture13);
373
bc += _read_i32(buf+bc, &gse->gesture14);
374
bc += _read_i16(buf+bc, &gse->numInitialTouches);
375
bc += _read_i16(buf+bc, &gse->numCurrentTouches);
376
bc += _read_i32(buf+bc, &gse->r16);
377
bc += _read_i32(buf+bc, &gse->r17);
378
bc += _read_i32(buf+bc, &gse->r18);
379
bc += _read_i32(buf+bc, &gse->r19);
380
bc += _read_i32(buf+bc, &gse->r20);
381
bc += _read_i32(buf+bc, &gse->r21);
382
bc += _read_i8(buf+bc, &gse->r22_0);
383
bc += _read_i8(buf+bc, &gse->numPoints);
384
bc += _read_i16(buf+bc, &gse->r22_2);
385
for (size_t i = 0; i < gse->numPoints; ++i)
386
bc += _read_gspoint(buf+bc, gse->points + i);
391
- (void) tapReceived: (NSData*) tapData
393
assert([tapData length] > 4);
396
NSDictionary* tapDict = [NSPropertyListSerialization propertyListFromData: tapData mutabilityOption:NSPropertyListImmutable format: NULL errorDescription: NULL];
398
switch([[tapDict objectForKey: TapIdKey] intValue])
402
NSLog(@"TOUCH EVENT");
404
GSEvent* gse = [self gsEventWithData: [tapDict objectForKey: TapGSEventKey]];
405
UIWindow* window = [[UIApplication sharedApplication] keyWindow];
406
gse->window = window;
407
for (size_t i = 0; i < gse->numPoints; ++i)
408
gse->points[i].window = window;
410
int phase = [[tapDict objectForKey: TapTouchPhaseKey] intValue];
411
NSSet* touches = [UITouch _createTouchesWithGSEvent: gse phase: phase view: [[UIApplication sharedApplication] keyWindow]];
413
assert([[UIApplication sharedApplication] keyWindow]);
415
NSLog(@"%@", touches);
417
UIEvent* event = [UIEvent alloc];
419
Class touchesEventClass = objc_getClass("UITouchesEvent");
420
if (touchesEventClass && ![[event class] isEqual: touchesEventClass])
422
event = [touchesEventClass alloc];
425
[event _initWithEvent: gse touches: touches];
429
[[UIApplication sharedApplication] sendEvent: event];
434
case kTapRecordedEvent:
436
NSLog(@"RECORDED EVENT");
438
NSDictionary* eventDict = [tapDict objectForKey: TapRecordedEventKey];
440
[[UIApplication sharedApplication] _playbackEvents:[NSArray arrayWithObject: eventDict] atPlaybackRate: 1.0f messageWhenDone: nil withSelector: nil];
450
- (void)performTouches: (NSSet*) touches inView: (UIView *)view
452
UITouch *touch = [[UITouch alloc] initInView:view];
453
UIEvent *eventDown = [[UIEvent alloc] initWithTouch:touch];
455
[touch.view touchesBegan:[eventDown allTouches] withEvent:eventDown];
457
[touch setPhase:UITouchPhaseEnded];
458
UIEvent *eventUp = [[UIEvent alloc] initWithTouch:touch];
460
[touch.view touchesEnded:[eventUp allTouches] withEvent:eventUp];
472
[netService release];
474
[activeThreads release];