RSS

(root)/iphone/tappity : 60 : common/source/SocketMessenger.m

To get this branch, use:
bzr branch /browse/iphone/tappity

« back to all changes in this revision

Viewing changes to common/source/SocketMessenger.m

Dömötör Gulyás
2010-01-18 09:01:40
Revision ID: dognotdog@gmail.com-20100118080140-g8bc7z6dp9ilr8rt
made tappity a standalone tree

Show diffs side-by-side

added added

removed removed

1
 
//
2
 
//  SocketMessenger.m
3
 
//  tappity
4
 
//
5
 
//  Created by döme on 30.10.2009.
6
 
 
7
 
//
8
 
 
9
 
/*
10
 
 * Copyright (c) 2009 Doemoetoer Gulyas.
11
 
 * All rights reserved.
12
 
 *
13
 
 * Redistribution and use in source and binary forms, with or without
14
 
 * modification, are permitted provided that the following conditions
15
 
 * are met:
16
 
 * 1. Redistributions of source code must retain the above copyright
17
 
 *    notice, this list of conditions and the following disclaimer.
18
 
 * 2. Redistributions in binary form must reproduce the above copyright
19
 
 *    notice, this list of conditions and the following disclaimer in the
20
 
 *    documentation and/or other materials provided with the distribution.
21
 
 * 3. The name of the author may not be used to endorse or promote products
22
 
 *    derived from this software without specific prior written permission.
23
 
 *
24
 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25
 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26
 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27
 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28
 
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29
 
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33
 
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
 
 */
35
 
 
36
 
#include <unistd.h>
37
 
#include <stdint.h>
38
 
#include <sys/socket.h>
39
 
#include <fcntl.h>
40
 
#include <termios.h>
41
 
#include <netinet/in.h>
42
 
#include <arpa/inet.h>
43
 
#include <sys/types.h>
44
 
#include <netdb.h>
45
 
#include <netinet/in.h>
46
 
#include <sys/time.h>
47
 
 
48
 
#import "SocketMessenger.h"
49
 
 
50
 
NSString* SocketMessageIdKey    = @"SocketMessageId";
51
 
NSString* SocketMessageDataKey  = @"SocketMessageData";
52
 
NSString* SocketMessengerKey    = @"SocketMessenger";
53
 
 
54
 
//const int kSocketMessengerTerminateMsg = -1;
55
 
 
56
 
 
57
 
@interface SocketMessenger (Private)
58
 
- (void) startCommsWorkThreads;
59
 
- (void) startWatchdogThread;
60
 
- (void) startListening;
61
 
@end
62
 
 
63
 
@implementation SocketMessenger
64
 
 
65
 
- (id) init
66
 
{
67
 
        if (!(self = [super init]))
68
 
                return nil;
69
 
                
70
 
        commsSocket = -1;
71
 
        server.listenSocket = -1;
72
 
        
73
 
        automaticallyReconnect = YES;
74
 
        
75
 
        sendLock = [[NSCondition alloc] init];
76
 
        sendQueue = [[NSMutableArray alloc] init];
77
 
                
78
 
        return self;
79
 
}
80
 
 
81
 
- (BOOL) isConnected
82
 
{
83
 
        return commsSocket != -1;
84
 
}
85
 
 
86
 
- (BOOL) threadActive: (id) key
87
 
{
88
 
        return [[activeThreads objectForKey: key] boolValue];
89
 
}
90
 
 
91
 
- (void) threadWillExit: (id) key
92
 
{
93
 
        @synchronized (self)
94
 
        {
95
 
                [activeThreads removeObjectForKey: key];
96
 
                
97
 
                if (![activeThreads count])
98
 
                {
99
 
                        close(commsSocket);
100
 
                        commsSocket = -1;
101
 
                        
102
 
                        
103
 
                }
104
 
        }
105
 
}
106
 
 
107
 
- (void) receivingThread: (id) info
108
 
{
109
 
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
110
 
 
111
 
        @synchronized(self)
112
 
        {
113
 
                [self retain];
114
 
        }
115
 
 
116
 
        while (rxThreadShouldRun)
117
 
        {
118
 
                struct timeval tv;
119
 
                fd_set readfds;
120
 
                fd_set writefds;
121
 
                fd_set errorfds;
122
 
                int socket = -1;
123
 
                int maxSocket = -1;
124
 
                
125
 
                @synchronized(self)
126
 
                {
127
 
                        socket = commsSocket;
128
 
                }
129
 
 
130
 
                tv.tv_sec = 1;
131
 
                tv.tv_usec = 0;
132
 
 
133
 
                FD_ZERO(&readfds);
134
 
                FD_ZERO(&writefds);
135
 
                FD_ZERO(&errorfds);
136
 
 
137
 
                FD_SET(socket, &readfds);
138
 
                FD_SET(socket, &errorfds);
139
 
                maxSocket = MAX(maxSocket, socket);
140
 
 
141
 
                if (select(maxSocket+1, &readfds, &writefds, &errorfds, &tv) < 0)
142
 
                {
143
 
                        perror("select");
144
 
                        goto SELECT_ERR;
145
 
                }
146
 
                
147
 
                if (FD_ISSET(socket, &errorfds))
148
 
                        goto SELECT_ERR;
149
 
 
150
 
 
151
 
                if (FD_ISSET(socket, &readfds))
152
 
                {
153
 
                        BOOL messageFinished = NO;
154
 
                        //NSLog(@"receiving...");
155
 
                        if (!expectedMessageSize)
156
 
                        {
157
 
                                uint32_t header[2] = {0,0};
158
 
                                int actuallyRead = 0;
159
 
                        
160
 
                                actuallyRead = recv(socket, header, 8, MSG_PEEK);
161
 
                                
162
 
                                if (actuallyRead == 8)
163
 
                                {
164
 
                                        actuallyRead = recv(socket, header, 8, 0);
165
 
                                        expectedMessageSize = ntohl(header[1]);
166
 
                                        currentMessageId = ntohl(header[0]);
167
 
                                        currentData = [[NSMutableData alloc] initWithLength: expectedMessageSize];
168
 
                                }
169
 
                                else if (actuallyRead == -1)
170
 
                                {
171
 
                                        if (errno != ETIMEDOUT)
172
 
                                        {
173
 
                                                printf("Connection dropped with error.\n");
174
 
                                                goto RECV_ERR;
175
 
                                        }
176
 
                                }
177
 
                                else if (actuallyRead == 0)
178
 
                                {
179
 
                                        printf("remote socket closed.\n");
180
 
                                        goto RECV_ERR;
181
 
                                }
182
 
                                
183
 
                                if (!expectedMessageSize)
184
 
                                        messageFinished = YES;
185
 
                        }
186
 
                        else
187
 
                        {
188
 
                                size_t readAmount = expectedMessageSize - currentlyRead;
189
 
                                int actuallyRead = 0;
190
 
                        
191
 
                                actuallyRead = recv(socket, [currentData mutableBytes] + currentlyRead, readAmount, 0);
192
 
                                if (actuallyRead == -1)
193
 
                                {
194
 
                                        printf("Connection dropped with error.\n");
195
 
                                        goto RECV_ERR;
196
 
                                }
197
 
                                else if (actuallyRead == 0)
198
 
                                {
199
 
                                        printf("remote socket closed.\n");
200
 
                                        goto RECV_ERR;
201
 
                                }
202
 
 
203
 
                                currentlyRead += actuallyRead;
204
 
                                
205
 
                                if (currentlyRead == expectedMessageSize)
206
 
                                        messageFinished = YES;
207
 
                        }
208
 
 
209
 
                        if (messageFinished)
210
 
                        {
211
 
                                if (currentMessageId == kSocketMessengerTerminateMsg)
212
 
                                {
213
 
                                        break;
214
 
                                }
215
 
                                @synchronized(self)
216
 
                                {
217
 
                                        expectedMessageSize = 0;
218
 
                                        /*
219
 
                                        if (!receivedPackets)
220
 
                                                receivedPackets = [[NSMutableArray alloc] init];
221
 
                                        [receivedPackets addObject: currentData];
222
 
                                        [currentData release];
223
 
                                        */
224
 
                                        
225
 
                                }
226
 
                                
227
 
                                //NSLog(@"dataReceived (%d) #%d", (int) [currentData length], currentMessageId);
228
 
 
229
 
                                if (receiveDataOnMainThread)
230
 
                                        [delegate performSelectorOnMainThread: @selector(dataReceived:) withObject: [NSDictionary dictionaryWithObjectsAndKeys: self, SocketMessengerKey, [NSNumber numberWithInt: currentMessageId], SocketMessageIdKey, currentData, SocketMessageDataKey, nil] waitUntilDone: NO];
231
 
                                else
232
 
                                        [delegate dataReceived: [NSDictionary dictionaryWithObjectsAndKeys: self, SocketMessengerKey, [NSNumber numberWithInt: currentMessageId], SocketMessageIdKey, currentData, SocketMessageDataKey, nil]];
233
 
 
234
 
                                currentData = nil;
235
 
                                currentlyRead = 0;
236
 
                        }
237
 
 
238
 
                }
239
 
 
240
 
                continue;
241
 
 
242
 
RECV_ERR:
243
 
SELECT_ERR:
244
 
                close(commsSocket);
245
 
                self->commsSocket = -1;
246
 
                break;
247
 
 
248
 
        }
249
 
        
250
 
        rxThreadActive = 0;
251
 
        
252
 
        [self threadWillExit: info];
253
 
 
254
 
        @synchronized(self)
255
 
        {
256
 
                [self release];
257
 
        }
258
 
 
259
 
        [info release];
260
 
        [pool drain];
261
 
}
262
 
 
263
 
 
264
 
- (void) runThreadWithTarget: (id) target selector: (SEL) selector
265
 
{
266
 
        @synchronized(self)
267
 
        {
268
 
                if (!activeThreads)
269
 
                        activeThreads = [[NSMutableDictionary alloc] init];
270
 
                id number = [NSNumber numberWithInt: threadIds++];
271
 
 
272
 
                [activeThreads setObject: [NSNumber numberWithBool: YES] forKey: number];
273
 
                [NSThread detachNewThreadSelector: selector toTarget: target withObject: [number retain]];
274
 
        }
275
 
}
276
 
 
277
 
- (void) sendData: (NSData*) tapData withIdentifier: (NSInteger) messageId
278
 
{               
279
 
        [sendLock lock];
280
 
 
281
 
        if (!sendQueue)
282
 
                sendQueue = [[NSMutableArray alloc] init];
283
 
 
284
 
        [sendQueue addObject: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInteger: messageId], SocketMessageIdKey, tapData, SocketMessageDataKey, nil]];
285
 
        
286
 
        [sendLock signal];
287
 
        [sendLock unlock];
288
 
                
289
 
}
290
 
 
291
 
 
292
 
- (void) sendingThread: (id) info
293
 
{
294
 
//      pthread_setname_np("sendingThread");
295
 
 
296
 
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
297
 
 
298
 
        @synchronized(self)
299
 
        {
300
 
                [self retain];
301
 
        }
302
 
 
303
 
        while (txThreadShouldRun)
304
 
        {
305
 
                [sendLock lock];
306
 
                while (![sendQueue count] && txThreadShouldRun)
307
 
                        [sendLock wait];
308
 
                                
309
 
                NSDictionary* dict = nil;
310
 
                if ([sendQueue count])
311
 
                {
312
 
                        dict = [[sendQueue objectAtIndex: 0] retain];
313
 
                        [sendQueue removeObjectAtIndex: 0];
314
 
                }
315
 
                
316
 
                [sendLock unlock];
317
 
                
318
 
                if (dict)
319
 
                {
320
 
                        NSData* data = [dict objectForKey: SocketMessageDataKey];
321
 
                        uint32_t messageId = [[dict objectForKey: SocketMessageIdKey] intValue];
322
 
 
323
 
                        size_t sizeToSend = 8;
324
 
                        size_t dataSent = 0;
325
 
                        uint32_t header[2] = {htonl(messageId), htonl([data length])};
326
 
                        int err = 0;
327
 
                        int socket = -1;
328
 
 
329
 
                        @synchronized(self)
330
 
                        {
331
 
                                socket = commsSocket;
332
 
                        }
333
 
                        
334
 
                        //printf("sending %d bytes\n", (int) sizeToSend);
335
 
 
336
 
                        while (dataSent < sizeToSend)
337
 
                        {
338
 
                                if ((err = send(socket, header + dataSent, sizeToSend - dataSent, 0)) == -1)
339
 
                                {
340
 
                                        perror("send");
341
 
                                        goto SEND_ERR;
342
 
                                }
343
 
                                else
344
 
                                        dataSent += err;
345
 
                        }
346
 
                        
347
 
                        if (err != -1)
348
 
                        {
349
 
                                sizeToSend = [data length];
350
 
                                dataSent = 0;
351
 
                                while (dataSent < sizeToSend)
352
 
                                {
353
 
                                        if ((err = send(socket, [data bytes] + dataSent, sizeToSend - dataSent, 0)) == -1)
354
 
                                        {
355
 
                                                perror("send");
356
 
                                                goto SEND_ERR;
357
 
                                        }
358
 
                                        else
359
 
                                                dataSent += err;
360
 
                                                
361
 
                                }
362
 
                        }
363
 
                        
364
 
                        if (err == -1)
365
 
                                goto SEND_ERR;
366
 
 
367
 
                        [dict release];
368
 
                }
369
 
                continue;
370
 
 
371
 
SEND_ERR:
372
 
                close(commsSocket);
373
 
                commsSocket = -1;
374
 
                [dict release];
375
 
                break;
376
 
        }
377
 
        
378
 
        txThreadActive = 0;
379
 
        
380
 
        [self threadWillExit: info];
381
 
 
382
 
        @synchronized(self)
383
 
        {
384
 
                [self release];
385
 
        }
386
 
 
387
 
        [info release];
388
 
        [pool drain];
389
 
}
390
 
 
391
 
- (void) connectToRemoteService
392
 
{
393
 
        NSInteger       port = [remoteService port];
394
 
        NSString*       hostName = [remoteService hostName];
395
 
        
396
 
        NSLog(@"SocketMessenger attempting to connect to %@ : %d", hostName, port);
397
 
 
398
 
        int sockfd = 0;
399
 
 
400
 
 
401
 
//      _setStandardSocketOpts(socket);
402
 
 
403
 
        struct addrinfo hints, *servinfo = NULL, *p = NULL;
404
 
        int rv = 0;
405
 
 
406
 
        memset(&hints, 0, sizeof hints);
407
 
        hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
408
 
        hints.ai_socktype = SOCK_STREAM;
409
 
        //hints.ai_protocol = IPPROTO_TCP;
410
 
        hints.ai_flags    = AI_PASSIVE;
411
 
        
412
 
//      NSHost* host = [NSHost hostWithName: hostName];
413
 
 
414
 
        if ((rv = getaddrinfo([hostName UTF8String], [[NSString stringWithFormat: @"%d", port] UTF8String], &hints, &servinfo)) != 0)
415
 
        {
416
 
                fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
417
 
                exit(1);
418
 
        }
419
 
 
420
 
        // loop through all the results and connect to the first we can
421
 
        for(p = servinfo; p != NULL; p = p->ai_next)
422
 
        {
423
 
                if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
424
 
                {
425
 
                        perror("socket");
426
 
                        continue;
427
 
                }
428
 
 
429
 
                if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
430
 
                {
431
 
                        close(sockfd);
432
 
                        perror("connect");
433
 
                        continue;
434
 
                }
435
 
 
436
 
                break; // if we get here, we must have connected successfully
437
 
        }
438
 
 
439
 
        if (p == NULL) {
440
 
                // looped off the end of the list with no connection
441
 
                fprintf(stderr, "failed to connect\n");
442
 
                exit(2);
443
 
        }
444
 
 
445
 
        freeaddrinfo(servinfo); // all done with this structure
446
 
        
447
 
        assert(sockfd != -1);
448
 
 
449
 
        NSLog(@"SocketMessenger connected");
450
 
 
451
 
 
452
 
        self->commsSocket = sockfd;
453
 
        
454
 
        [self startCommsWorkThreads];
455
 
        [self startWatchdogThread];
456
 
                
457
 
}
458
 
 
459
 
- (void) connectToService: (NSNetService*) service
460
 
{
461
 
        [service retain];
462
 
        [remoteService release];
463
 
        remoteService = service;
464
 
        [self connectToRemoteService];
465
 
}
466
 
 
467
 
- (void) stopCommsWorkThreads
468
 
{
469
 
        while (rxThreadActive || txThreadActive)
470
 
        {
471
 
                rxThreadShouldRun = 0;
472
 
                txThreadShouldRun = 0;
473
 
                [sendLock lock];
474
 
                [sendLock signal];
475
 
                [sendLock unlock];
476
 
                usleep(10000);
477
 
        }
478
 
}
479
 
 
480
 
- (void) stopWatchdogThread
481
 
{
482
 
        while (wdThreadActive)
483
 
        {
484
 
                wdThreadShouldRun = 0;
485
 
                usleep(10000);
486
 
        }
487
 
}
488
 
 
489
 
- (void) startWatchdogThread
490
 
{
491
 
        //[self stopWatchdogThread];
492
 
 
493
 
        if (!wdThreadActive)
494
 
        {
495
 
                wdThreadShouldRun = 1;
496
 
                @synchronized(self)
497
 
                {
498
 
                        wdThreadActive++;
499
 
                }
500
 
                [self runThreadWithTarget: self selector: @selector(watchdogThread:)];
501
 
        }
502
 
}
503
 
 
504
 
- (void) stopAcceptThread
505
 
{
506
 
        while (server.acThreadActive)
507
 
        {
508
 
                server.acThreadShouldRun = 0;
509
 
                usleep(10000);
510
 
        }
511
 
}
512
 
 
513
 
- (void) startAcceptThread
514
 
{
515
 
        [self stopAcceptThread];
516
 
 
517
 
        server.acThreadShouldRun = 1;
518
 
        server.acThreadActive = 1;
519
 
 
520
 
        [self runThreadWithTarget: self selector: @selector(acceptThread:)];
521
 
}
522
 
 
523
 
 
524
 
- (void) startCommsWorkThreads
525
 
{
526
 
        [self stopCommsWorkThreads];
527
 
        
528
 
        rxThreadShouldRun = 1;
529
 
        rxThreadActive = 1;
530
 
        txThreadShouldRun = 1;
531
 
        txThreadActive = 1;
532
 
 
533
 
        [self runThreadWithTarget: self selector: @selector(sendingThread:)];
534
 
        [self runThreadWithTarget: self selector: @selector(receivingThread:)];
535
 
        
536
 
        if ([delegate respondsToSelector: @selector(connectionWasEstablished:)])
537
 
                [delegate performSelectorOnMainThread: @selector(connectionWasEstablished:) withObject: self waitUntilDone: NO];
538
 
}
539
 
 
540
 
static void _setStandardSocketOpts(int socket)
541
 
{
542
 
    int yes = 1;
543
 
    setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
544
 
        int timeout = 2000;
545
 
        setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
546
 
        setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
547
 
}
548
 
 
549
 
 
550
 
- (void) acceptThread: (id) info
551
 
{
552
 
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
553
 
 
554
 
        @synchronized(self)
555
 
        {
556
 
                [self retain];
557
 
        }
558
 
 
559
 
        while (server.acThreadShouldRun)
560
 
        {
561
 
 
562
 
                struct timeval tv;
563
 
                fd_set readfds;
564
 
                fd_set writefds;
565
 
                fd_set errorfds;
566
 
                int maxSocket = -1;
567
 
                
568
 
                int lsock = server.listenSocket;
569
 
 
570
 
                tv.tv_sec = 1;
571
 
                tv.tv_usec = 0;
572
 
 
573
 
                FD_ZERO(&readfds);
574
 
                FD_ZERO(&writefds);
575
 
                FD_ZERO(&errorfds);
576
 
 
577
 
                FD_SET(lsock, &readfds);
578
 
                FD_SET(lsock, &errorfds);
579
 
                maxSocket = MAX(maxSocket, lsock);
580
 
                                
581
 
                //NSLog(@"listening for connection...");
582
 
 
583
 
                if (select(maxSocket+1, &readfds, NULL, &errorfds, &tv) < 0)
584
 
                {
585
 
                        perror("select");
586
 
                        goto SELECT_ERR;
587
 
                        break;
588
 
                }
589
 
 
590
 
                if (FD_ISSET(lsock, &readfds))
591
 
                {
592
 
                        NSLog(@"Accepting connection...");
593
 
                        // accept
594
 
                        socklen_t       sinSize = sizeof(struct sockaddr_in);
595
 
                        struct sockaddr_in      peerAddress;
596
 
                        int newSocket = accept(lsock, (struct sockaddr *)&peerAddress, &sinSize);
597
 
                        
598
 
                        _setStandardSocketOpts(newSocket);
599
 
 
600
 
                        
601
 
                        if (newSocket == -1)
602
 
                        {
603
 
                                if (errno == EWOULDBLOCK)
604
 
                                {
605
 
                                }
606
 
                                else
607
 
                                {
608
 
                                        printf("Error accepting connection.\n");
609
 
                                        goto ACCEPT_ERR;
610
 
                                        break;
611
 
                                }
612
 
                        }
613
 
                        
614
 
                        @synchronized(self)
615
 
                        {
616
 
                                if (commsSocket)
617
 
                                        close(commsSocket);
618
 
 
619
 
                                // add socket to sockets list
620
 
                                commsSocket = newSocket;
621
 
                        }
622
 
                        
623
 
                        [server.netService stop];
624
 
                        [server.netService release];
625
 
                        server.netService = nil;
626
 
                        
627
 
                        close(server.listenSocket);
628
 
                        server.listenSocket = -1;
629
 
                        
630
 
                        [self startCommsWorkThreads];
631
 
                        
632
 
                        NSLog(@"Accepted connection.");
633
 
                        
634
 
                        goto ACCEPT_SUCCESS;
635
 
                }
636
 
                
637
 
                continue;
638
 
 
639
 
ACCEPT_ERR:
640
 
SELECT_ERR:
641
 
                close(server.listenSocket);
642
 
                server.listenSocket = -1;
643
 
                break;
644
 
 
645
 
ACCEPT_SUCCESS:
646
 
                break;
647
 
        }
648
 
        
649
 
        server.acThreadActive = 0;
650
 
 
651
 
        @synchronized(self)
652
 
        {
653
 
                [self release];
654
 
        }
655
 
 
656
 
        [info release];
657
 
        [pool drain];
658
 
}
659
 
 
660
 
- (void) watchdogThread: (id) info
661
 
{
662
 
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
663
 
 
664
 
        @synchronized(self)
665
 
        {
666
 
                [self retain];
667
 
        }
668
 
 
669
 
        while (wdThreadShouldRun)
670
 
        {
671
 
                if (isServing)
672
 
                {
673
 
                        if ((commsSocket == -1) && (server.listenSocket == -1))
674
 
                        {
675
 
                                NSLog(@"watchdog noticed connection error");
676
 
                                if (automaticallyReconnect)
677
 
                                {
678
 
                                        NSLog(@"restarting server");
679
 
                                        [self stopCommsWorkThreads];
680
 
                                        [self startListening];
681
 
                                }
682
 
                                else 
683
 
                                {
684
 
                                        if ([delegate respondsToSelector: @selector(connectionWasTerminated:)])
685
 
                                                [delegate performSelectorOnMainThread: @selector(connectionWasTerminated:) withObject: self waitUntilDone: NO];
686
 
                                        break;
687
 
                                }
688
 
                        }
689
 
                }
690
 
                else
691
 
                {
692
 
                        if (commsSocket == -1)
693
 
                        {
694
 
                                NSLog(@"watchdog noticed connection error");
695
 
                                if (automaticallyReconnect)
696
 
                                {
697
 
                                        NSLog(@"restarting client");
698
 
                                        [self stopCommsWorkThreads];
699
 
                                        [self connectToRemoteService];
700
 
                                }
701
 
                                else 
702
 
                                {
703
 
                                        if ([delegate respondsToSelector: @selector(connectionWasTerminated:)])
704
 
                                                [delegate performSelectorOnMainThread: @selector(connectionWasTerminated:) withObject: self waitUntilDone: NO];
705
 
                                        break;
706
 
                                }
707
 
                        }
708
 
                }
709
 
                usleep(1000000);
710
 
                continue;
711
 
 
712
 
WATCH_ERR:
713
 
                assert(0);
714
 
                break;
715
 
 
716
 
        }
717
 
 
718
 
        @synchronized(self)
719
 
        {
720
 
                wdThreadActive--;
721
 
        }
722
 
        
723
 
 
724
 
        @synchronized(self)
725
 
        {
726
 
                [self release];
727
 
        }
728
 
 
729
 
        [info release];
730
 
        [pool drain];
731
 
}
732
 
 
733
 
 
734
 
- (BOOL) enableBonjourWithDomain:(NSString*)domain applicationProtocol:(NSString*)protocol name:(NSString*)name 
735
 
{
736
 
        if(![domain length])
737
 
                domain = @""; //Will use default Bonjour registration doamins, typically just ".local"
738
 
        if(![name length])
739
 
                name = @""; //Will use default Bonjour name, e.g. the name assigned to the device in iTunes
740
 
        
741
 
        assert([protocol length] && server.listenSocket);
742
 
        
743
 
        NSLog(@"tappity port: %d", server.portnum);
744
 
 
745
 
        [server.netService stop];
746
 
        [server.netService release];
747
 
 
748
 
        server.netService = [[NSNetService alloc] initWithDomain: domain type: protocol name: name port: server.portnum];
749
 
        if(server.netService == nil)
750
 
                return NO;
751
 
 
752
 
        [server.netService setDelegate: self];
753
 
//      [server.netService scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
754
 
        [server.netService publish];
755
 
        
756
 
        return YES;
757
 
}
758
 
 
759
 
 
760
 
 
761
 
- (void) startListening
762
 
{
763
 
        struct sockaddr_in myAddress;
764
 
        memset(&myAddress, 0, sizeof(myAddress));
765
 
 
766
 
        myAddress.sin_family = AF_INET;                                 // host byte order
767
 
        myAddress.sin_port = htons(server.portnum);             // short, network byte order, any port
768
 
        myAddress.sin_addr.s_addr = htonl(INADDR_ANY);  // auto-fill with my IP
769
 
 
770
 
        server.listenSocket = socket(PF_INET, SOCK_STREAM, 0);
771
 
        assert(server.listenSocket != -1);
772
 
 
773
 
        _setStandardSocketOpts(server.listenSocket);
774
 
 
775
 
        int err = bind(server.listenSocket, (struct sockaddr *)&myAddress, sizeof(myAddress));
776
 
        assert(-1 != err);
777
 
        
778
 
        err = listen(server.listenSocket, 1);
779
 
        assert(-1 != err);
780
 
 
781
 
        [self startAcceptThread];
782
 
        [self startWatchdogThread];
783
 
        
784
 
        if([self enableBonjourWithDomain: @"" applicationProtocol: server.protocolName name: server.serviceName])
785
 
                NSLog(@"tappity bounjour advertisments up and running");
786
 
 
787
 
}
788
 
 
789
 
- (void) startBonjourServerWithName: (NSString*) name protocol: (NSString*) protocol port: (int) pnum;
790
 
{
791
 
        NSLog(@"starting tappity server");
792
 
        
793
 
        [server.serviceName release];
794
 
        server.serviceName = [name retain];
795
 
        
796
 
        
797
 
        [server.protocolName release];
798
 
        server.protocolName = [protocol retain];
799
 
        
800
 
        server.portnum = pnum;
801
 
 
802
 
        isServing = YES;
803
 
        
804
 
        [self startListening];
805
 
 
806
 
}
807
 
 
808
 
- (void) terminateConnection
809
 
{
810
 
        [self stopWatchdogThread];
811
 
        [self stopAcceptThread];
812
 
        [self stopCommsWorkThreads];
813
 
}
814
 
 
815
 
- (void) dealloc
816
 
{
817
 
 
818
 
        [server.serviceName release];
819
 
 
820
 
        [server.netService stop];
821
 
        [server.netService release];
822
 
 
823
 
        [activeThreads release];
824
 
        [sendQueue release];
825
 
        [sendLock release];
826
 
 
827
 
        [remoteService release];
828
 
 
829
 
        [super dealloc];
830
 
}
831
 
 
832
 
@synthesize delegate, receiveDataOnMainThread, automaticallyReconnect;
833
 
 
834
 
@end

Loggerhead 1.17 is a web-based interface for Bazaar branches