]> Dogcows Code - chaz/thecheat/blob - MySocket.m
Remove support of Mac OS X 10.3 and earlier system, change codes for Mac OS X 10.7.
[chaz/thecheat] / MySocket.m
1
2 /*
3 * The Cheat - The legendary universal game trainer for Mac OS X.
4 * http://www.brokenzipper.com/trac/wiki/TheCheat
5 *
6 * Copyright (c) 2003-2011, Charles McGarvey et al.
7 *
8 * Distributable under the terms and conditions of the 2-clause BSD
9 * license; see the file COPYING for the legal text of the license.
10 */
11
12
13 #import "MySocket.h"
14
15
16 // CONSTANTS
17
18 // this is used to read in unclaimed data
19 #define MYSOCKET_PACKETLEN (1024)
20
21 enum {
22 kMySocketAddedToManager = 1,
23 kMySocketConnected = 2,
24 kMySocketIsListener = 4
25 };
26
27
28 struct _mySocketGlobals {
29 BOOL isManagerRunning;
30 NSMutableArray *sockets;
31 NSRecursiveLock *readLock;
32 NSRecursiveLock *writeLock;
33 int readPipe[2];
34 int writePipe[2];
35 int maxreadfd;
36 int maxwritefd;
37 fd_set readfds;
38 fd_set writefds;
39 } _mySocketGlobals = { NO, nil, nil, nil, { -1, -1 }, { -1, -1 }, 0, 0 };
40
41
42 // HELPER CLASSES
43
44 @interface _MySocketPacket : NSObject
45 {
46 NSData *_buffer;
47 unsigned _bytesHandled;
48 unsigned _bytesRequired;
49 int _tag;
50 }
51
52 - (id)initWithData:(NSData *)data tag:(int)tag;
53
54 - (void *)bytes; // pointer to the current bytes; changes are bytes are handled
55 - (unsigned)bytesRemaining;
56
57 - (void)handledBytes:(unsigned)count;
58
59 - (unsigned)bytesRequired;
60
61 - (NSData *)data;
62 - (int)tag;
63 - (BOOL)isComplete;
64
65 @end
66
67
68 // PRIVATE STUFF
69
70 @interface MySocket ( PrivateAPI )
71
72 - (id)_initWithFileDescriptor:(int)sockfd;
73 - (void)_connect;
74
75 - (void)_addToManager;
76 - (void)_removeFromManager;
77
78 + (void)_readWithSockFD:(int)fd;
79 + (void)_refreshReadThread;
80 + (void)_writeWithSockFD:(int)fd;
81 + (void)_refreshWriteThread;
82
83 + (void)_lockRead;
84 + (void)_unlockRead;
85 + (void)_lockWrite;
86 + (void)_unlockWrite;
87 + (void)_lockReadAndWrite;
88 + (void)_unlockReadAndWrite;
89
90 /* #### MANAGER METHODS #### */
91 + (void)_startManager;
92 + (void)_readThread:(id)object;
93 + (void)_writeThread:(id)object;
94
95 - (int)_accept;
96 - (int)_read;
97 - (int)_write;
98
99 - (void)_fillReadPacketsWithUnclaimedBytes;
100
101 - (void)_handleReadQueue;
102 - (void)_handleWriteQueue;
103
104 - (void)_eventDidAcceptSocket:(MySocket *)newSocket;
105 - (void)_eventDidDisconnect:(id)dummy;
106 - (void)_eventDidReadData:(_MySocketPacket *)packet;
107 - (void)_eventDidWriteData:(_MySocketPacket *)packet;
108
109 // utility
110 - (NSMutableData *)_readBufferWithLength:(unsigned *)len;
111
112 // accessors
113 - (int)_sockfd;
114
115 @end
116
117
118
119 @implementation MySocket
120
121
122 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
123 #pragma mark Initialization
124 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
125
126 - (id)initWithDelegate:(id)delegate
127 {
128 if ( self = [super init] ) {
129 ChazLog( @"SOCKET CREATED" );
130 [self setDelegate:delegate];
131 }
132 return self;
133 }
134
135 - (void)dealloc
136 {
137 ChazLog( @"SOCKET DESTROYED" );
138 [self disconnect];
139 [super dealloc];
140 }
141
142
143 - (void)release
144 {
145 if ( [self retainCount] == 1 ) {
146 [self _removeFromManager];
147 }
148
149 [super release];
150 }
151
152
153 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
154 #pragma mark Connecting/Disconnecting
155 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
156
157 - (BOOL)connectToHost:(NSString *)host port:(int)port
158 {
159 return [self connectToAddressWithData:[MySocket addressWithHost:host port:port]];
160 }
161
162 - (BOOL)connectToAddress:(const struct sockaddr *)addr length:(unsigned)addrLen
163 {
164 int err = 0;
165
166 if ( [self isConnected] ) {
167 return NO;
168 }
169
170 _sockfd = socket( addr->sa_family, SOCK_STREAM, 0 );
171 if ( _sockfd == -1 ) {
172 // can't get file descriptor
173 return NO;
174 }
175 // make the socket NOT block
176 /*err = fcntl( _sockfd, F_SETFL, O_NONBLOCK );
177 if ( err == -1 ) {
178 // can't not block
179 close( _sockfd );
180 return NO;
181 }*/
182 err = connect( _sockfd, addr, addrLen );
183 if ( err == -1 ) {
184 // can't connect
185 close( _sockfd );
186 return NO;
187 }
188
189 [self _connect];
190 return YES;
191 }
192
193 - (BOOL)connectToAddressWithData:(NSData *)addr
194 {
195 return [self connectToAddress:[addr bytes] length:[addr length]];
196 }
197
198 - (BOOL)listenOnPort:(int)port
199 {
200 struct sockaddr_in addr;
201
202 int err = 0;
203 int yes = 1;
204
205 if ( [self isConnected] ) {
206 return NO;
207 }
208
209 _sockfd = socket( AF_INET, SOCK_STREAM, 0 );
210 if ( _sockfd == -1 ) {
211 // can't get file descriptor
212 return NO;
213 }
214 err = setsockopt( _sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes) );
215 if ( err == -1 ) {
216 // can't reuse address
217 close( _sockfd );
218 return NO;
219 }
220
221 // pack the socket address structure
222 addr.sin_family = AF_INET;
223 addr.sin_port = htons( (short)port );
224 addr.sin_addr.s_addr = INADDR_ANY;
225 // Use 0 replace NULL
226 memset( &(addr.sin_zero), 0, 8 );
227
228 err = bind( _sockfd, (struct sockaddr *)(&addr), sizeof(addr) );
229 if ( err == -1 ) {
230 // can't bind to this address
231 close( _sockfd );
232 return NO;
233 }
234
235 err = listen( _sockfd, 10 );
236 if ( err == -1 ) {
237 // can't listen on this address
238 close( _sockfd );
239 return NO;
240 }
241
242 _flags |= kMySocketIsListener;
243 [self _connect];
244 return YES;
245 }
246
247
248 - (void)disconnect
249 {
250 if ( !(_flags & kMySocketConnected) ) {
251 // not connected
252 return;
253 }
254
255 [self _removeFromManager];
256
257 close( _sockfd );
258 _sockfd = -1;
259
260 [_readQueue release];
261 _readQueue = nil;
262 [_writeQueue release];
263 _writeQueue = nil;
264 [_readLock release];
265 _readLock = nil;
266 [_writeLock release];
267 _writeLock = nil;
268
269 _startTime = 0.0;
270
271 _flags = 0;
272 }
273
274
275 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
276 #pragma mark Reading/Writing
277 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
278
279 - (void)readDataToLength:(unsigned)len tag:(int)tag
280 {
281 _MySocketPacket *packet;
282
283 if ( ![self isConnected] || [self isListener] || len == 0 ) {
284 // must be connected and have a valid length
285 return;
286 }
287
288 // create a "read" packet
289 packet = [[_MySocketPacket alloc] initWithData:[NSMutableData dataWithLength:len] tag:tag];
290 //[packet handledBytes:0];
291
292 // add the packet to the queue
293 [_readLock lock];
294 [_readQueue addObject:packet];
295 [packet release];
296 [_readLock unlock];
297
298 // make sure the thread picks up the change
299 [MySocket _refreshReadThread];
300 }
301
302
303 - (void)writeData:(NSData *)data tag:(int)tag
304 {
305 _MySocketPacket *packet;
306 BOOL alreadyWriting;
307
308 if ( ![self isConnected] || [self isListener] ) {
309 // must be connected
310 return;
311 }
312
313 // create a "write" packet
314 packet = [[_MySocketPacket alloc] initWithData:data tag:tag];
315
316 [_writeLock lock];
317 alreadyWriting = [_writeQueue count] > 0;
318 [_writeQueue addObject:packet];
319 [packet release];
320 [_writeLock unlock];
321
322 if ( !alreadyWriting ) {
323 // make the helper aware the socket has data to write
324 [MySocket _writeWithSockFD:_sockfd];
325 }
326 }
327
328 - (void)writeBytes:(void const *)bytes length:(unsigned)len tag:(int)tag
329 {
330 [self writeData:[NSData dataWithBytes:bytes length:len] tag:tag];
331 }
332
333
334 // AsyncSocket compatibility
335 - (void)readDataToLength:(CFIndex)length withTimeout:(NSTimeInterval)timeout tag:(long)tag
336 {
337 [self readDataToLength:length tag:tag];
338 }
339
340 - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
341 {
342 [self writeData:data tag:tag];
343 }
344
345 - (void)writeBytes:(void *)bytes length:(unsigned)len withTimeout:(NSTimeInterval)timeout tag:(long)tag
346 {
347 [self writeBytes:bytes length:len tag:tag];
348 }
349
350
351 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
352 #pragma mark Accesors
353 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
354
355 - (unsigned)bytesRead
356 {
357 return _bytesRead;
358 }
359
360 - (unsigned)bytesWritten
361 {
362 return _bytesWritten;
363 }
364
365 - (NSTimeInterval)timeConnected
366 {
367 return CFAbsoluteTimeGetCurrent() - _startTime;
368 }
369
370 - (double)readSpeed
371 {
372 double currentTime = CFAbsoluteTimeGetCurrent();
373 double speed = (double)( _bytesRead - _lastBytesRead ) / ( currentTime - _lastBytesReadTime );
374 _lastBytesRead = _bytesRead;
375 _lastBytesReadTime = currentTime;
376 return speed;
377 }
378
379 - (double)writeSpeed
380 {
381 double currentTime = CFAbsoluteTimeGetCurrent();
382 double speed = (double)( _bytesWritten - _lastBytesWritten ) / ( currentTime - _lastBytesWrittenTime );
383 _lastBytesWritten = _bytesWritten;
384 _lastBytesWrittenTime = currentTime;
385 return speed;
386 }
387
388
389 - (NSString *)localHost
390 {
391 char host[128];
392 int err;
393
394 err = gethostname( host, sizeof(host) );
395 if ( err == -1 ) {
396 return @"";
397 }
398 return [NSString stringWithCString:host encoding:NSUTF8StringEncoding];
399 }
400
401 - (int)localPort
402 {
403 return 0;
404 }
405
406 - (NSString *)remoteHost
407 {
408 int err;
409 struct sockaddr_in addr;
410 unsigned int len = sizeof(addr);
411
412 err = getpeername( _sockfd, (struct sockaddr *)(&addr), &len );
413 if ( err == -1 ) {
414 return @"Unknown";
415 }
416 return [NSString stringWithCString:inet_ntoa(addr.sin_addr) encoding:NSUTF8StringEncoding];
417 }
418
419 - (int)remotePort
420 {
421 int err;
422 struct sockaddr_in addr;
423 unsigned int len = sizeof(addr);
424
425 err = getpeername( _sockfd, (struct sockaddr *)(&addr), &len );
426 if ( err == -1 ) {
427 return -1;
428 }
429 return addr.sin_port;
430 }
431
432
433 - (BOOL)isConnected
434 {
435 return _flags & kMySocketConnected;
436 }
437
438 - (BOOL)isListener
439 {
440 return _flags & kMySocketIsListener;
441 }
442
443
444 + (NSData *)addressWithHost:(NSString *)host port:(int)port
445 {
446 struct hostent *h;
447 struct sockaddr_in addr;
448
449 // resolve the host
450 h = gethostbyname( [host cStringUsingEncoding:NSUTF8StringEncoding] );
451 if ( h == NULL ) {
452 // host not found
453 return nil;
454 }
455
456 // pack the socket address structure
457 addr.sin_family = AF_INET;
458 addr.sin_port = htons( (short)port );
459 memcpy( &(addr.sin_addr), h->h_addr, sizeof(struct in_addr) );
460 // Use 0 replace NULL
461 memset( &(addr.sin_zero), 0, 8 );
462
463 return [NSData dataWithBytes:&addr length:sizeof(addr)];
464 }
465
466
467 - (id)delegate
468 {
469 return _delegate;
470 }
471
472 - (void)setDelegate:(id)delegate
473 {
474 _delegate = delegate;
475 }
476
477
478 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
479 #pragma mark PrivateAPI
480 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
481
482 - (id)_initWithFileDescriptor:(int)sockfd
483 {
484 if ( self = [super init] ) {
485 _sockfd = sockfd;
486 [self _connect];
487 }
488 return self;
489 }
490
491 - (void)_connect
492 {
493 if ( ![self isListener] ) {
494 _readQueue = [[NSMutableArray alloc] init];
495 _writeQueue = [[NSMutableArray alloc] init];
496 }
497
498 // create the locks
499 _readLock = [[NSRecursiveLock alloc] init];
500 _writeLock = [[NSRecursiveLock alloc] init];
501
502 _startTime = _lastBytesReadTime = _lastBytesWrittenTime = CFAbsoluteTimeGetCurrent();
503 _bytesRead = _lastBytesRead = _bytesWritten = _lastBytesWritten = 0;
504
505 _flags |= kMySocketConnected;
506
507 [self _addToManager];
508 }
509
510
511 - (void)_addToManager
512 {
513 if ( _flags & kMySocketAddedToManager ) {
514 // only add this socket once
515 return;
516 }
517
518 // start the manager if it is not already started
519 [MySocket _startManager];
520
521 [MySocket _lockReadAndWrite];
522 // add to global array of sockets
523 [_mySocketGlobals.sockets addObject:self];
524 [self release];
525 [MySocket _readWithSockFD:_sockfd];
526 [MySocket _unlockReadAndWrite];
527
528 // mark as added to manager
529 _flags |= kMySocketAddedToManager;
530 }
531
532 - (void)_removeFromManager
533 {
534 if ( !(_flags & kMySocketAddedToManager) ) {
535 // only remove if it is added
536 return;
537 }
538
539 [MySocket _lockReadAndWrite];
540 // remove from global array
541 [self retain];
542 ChazLog( @"REMOVING SOCKET AT INDEX %i", [_mySocketGlobals.sockets indexOfObject:self] );
543 [_mySocketGlobals.sockets removeObject:self];
544 FD_CLR( _sockfd, &_mySocketGlobals.readfds );
545 FD_CLR( _sockfd, &_mySocketGlobals.writefds );
546 [MySocket _unlockReadAndWrite];
547
548 _flags ^= kMySocketAddedToManager;
549 }
550
551
552 + (void)_readWithSockFD:(int)fd
553 {
554 [MySocket _lockRead];
555 FD_SET( fd, &_mySocketGlobals.readfds );
556 _mySocketGlobals.maxreadfd = MAX( _mySocketGlobals.maxreadfd, fd );
557 [MySocket _unlockRead];
558 // make sure the thread picks up the change
559 [MySocket _refreshReadThread];
560 }
561
562 + (void)_refreshReadThread
563 {
564 char b = 'R';
565 write( _mySocketGlobals.readPipe[1], &b, sizeof(b) );
566 }
567
568 + (void)_writeWithSockFD:(int)fd
569 {
570 [MySocket _lockWrite];
571 FD_SET( fd, &_mySocketGlobals.writefds );
572 _mySocketGlobals.maxwritefd = MAX( _mySocketGlobals.maxwritefd, fd );
573 [MySocket _unlockWrite];
574 [MySocket _refreshWriteThread];
575 }
576
577 + (void)_refreshWriteThread
578 {
579 char b = 'R';
580 write( _mySocketGlobals.writePipe[1], &b, sizeof(b) );
581 }
582
583
584 + (void)_lockRead
585 {
586 [_mySocketGlobals.readLock lock];
587 }
588
589 + (void)_unlockRead
590 {
591 [_mySocketGlobals.readLock unlock];
592 }
593
594 + (void)_lockWrite
595 {
596 [_mySocketGlobals.writeLock lock];
597 }
598
599 + (void)_unlockWrite
600 {
601 [_mySocketGlobals.writeLock unlock];
602 }
603
604 + (void)_lockReadAndWrite
605 {
606 [MySocket _lockRead];
607 [MySocket _lockWrite];
608 }
609
610 + (void)_unlockReadAndWrite
611 {
612 [MySocket _unlockRead];
613 [MySocket _unlockWrite];
614 }
615
616
617 + (void)_startManager
618 {
619 int err;
620
621 if ( _mySocketGlobals.isManagerRunning ) {
622 return;
623 }
624
625 ChazLog( @"MySocketHelper STARTING" );
626
627 // zero the descriptor sets
628 FD_ZERO( &_mySocketGlobals.readfds );
629 FD_ZERO( &_mySocketGlobals.writefds );
630
631 // create the read pipe
632 err = pipe( _mySocketGlobals.readPipe );
633 if ( err == -1 ) {
634 return;
635 }
636 FD_SET( _mySocketGlobals.readPipe[0], &_mySocketGlobals.readfds );
637 _mySocketGlobals.maxreadfd = _mySocketGlobals.readPipe[0];
638 // create the write pipe
639 err = pipe( _mySocketGlobals.writePipe );
640 if ( err == -1 ) {
641 close( _mySocketGlobals.readPipe[0] );
642 close( _mySocketGlobals.readPipe[1] );
643 return;
644 }
645 _mySocketGlobals.maxwritefd = _mySocketGlobals.writePipe[0];
646
647 // create other global objects
648 _mySocketGlobals.sockets = [[NSMutableArray alloc] init];
649 _mySocketGlobals.readLock = [[NSRecursiveLock alloc] init];
650 _mySocketGlobals.writeLock = [[NSRecursiveLock alloc] init];
651
652 // start the threads
653 [NSThread detachNewThreadSelector:@selector(_readThread:) toTarget:[MySocket class] withObject:nil];
654 [NSThread detachNewThreadSelector:@selector(_writeThread:) toTarget:[MySocket class] withObject:nil];
655 _mySocketGlobals.isManagerRunning = YES;
656 }
657
658 + (void)_readThread:(id)object
659 {
660 BOOL breakLoop = NO;
661 fd_set readfds;
662
663 do {
664 int err;
665 int i, top;
666
667 // create the ever-so-important pool
668 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
669
670 [MySocket _lockRead];
671 //FD_COPY( &_mySocketGlobals.readfds, &readfds );
672 readfds = _mySocketGlobals.readfds;
673 [MySocket _unlockRead];
674
675 // find the sockets which need processing
676 err = select( _mySocketGlobals.maxreadfd+1, &readfds, NULL, NULL, NULL );
677 if ( err == -1 ) {
678 // trouble, select() is having problems
679 ChazLog( @"select() failed!, error: %s", strerror(errno) );
680 goto DONE;
681 }
682
683 // check the pipe
684 if ( FD_ISSET( _mySocketGlobals.readPipe[0], &readfds ) ) {
685 char b;
686 err = read( _mySocketGlobals.readPipe[0], &b, sizeof(b) );
687 if ( err <= 0 ) {
688 // our connection to the main thread was severed...
689 // SELF DESTRUCT
690 ChazLog( @"readPipe severed, exiting READ thread..." );
691 breakLoop = YES;
692 goto DONE;
693 }
694 }
695
696 // process the sockets
697 [MySocket _lockRead];
698 top = [_mySocketGlobals.sockets count];
699 for ( i = 0; i < top; i++ ) {
700 MySocket *sock = [_mySocketGlobals.sockets objectAtIndex:i];
701 int sockfd = [sock _sockfd];
702
703 [sock _fillReadPacketsWithUnclaimedBytes];
704 [sock _handleReadQueue];
705
706 if ( FD_ISSET( sockfd, &readfds ) ) {
707 if ( [sock isListener] ) {
708 // socket ready for accepting
709 err = [sock _accept];
710 }
711 else {
712 // socket ready for reading
713 err = [sock _read];
714 }
715 if ( err == -1 ) {
716 // action returne error, disconnect socket
717 [sock disconnect];
718 [sock performSelectorOnMainThread:@selector(_eventDidDisconnect:)
719 withObject:nil waitUntilDone:NO];
720 top--;
721 }
722 }
723 }
724 [MySocket _unlockRead];
725
726 DONE:;
727 [pool release];
728 }
729 while ( !breakLoop );
730 }
731
732 + (void)_writeThread:(id)object
733 {
734 BOOL breakLoop = NO;
735 fd_set pipefds;
736 fd_set readfds, writefds;
737
738 FD_ZERO( &pipefds );
739 FD_SET( _mySocketGlobals.writePipe[0], &pipefds );
740
741 do {
742 int err;
743 int i, top;
744
745 // create the ever-so-important pool
746 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
747
748 readfds = pipefds;
749 [MySocket _lockWrite];
750 //FD_COPY( &_mySocketGlobals.writefds, &writefds );
751 writefds = _mySocketGlobals.writefds;
752 [MySocket _unlockWrite];
753
754 // find the sockets which need processing
755 err = select( _mySocketGlobals.maxwritefd+1, &readfds, &writefds, NULL, NULL );
756 if ( err == -1 ) {
757 // trouble, select() is having problems
758 ChazLog( @"select() failed!, error: %s", strerror(errno) );
759 goto DONE;
760 }
761
762 // check the pipe
763 if ( FD_ISSET( _mySocketGlobals.writePipe[0], &readfds ) ) {
764 char b;
765 err = read( _mySocketGlobals.writePipe[0], &b, sizeof(b) );
766 if ( err <= 0 ) {
767 // our connection to the main thread was severed...
768 // SELF DESTRUCT
769 ChazLog( @"writePipe severed" );
770 breakLoop = YES;
771 goto DONE;
772 }
773 }
774
775 // process the sockets
776 [MySocket _lockWrite];
777 top = [_mySocketGlobals.sockets count];
778 for ( i = 0; i < top; i++ ) {
779 MySocket *sock = [_mySocketGlobals.sockets objectAtIndex:i];
780 int sockfd = [sock _sockfd];
781
782 if ( FD_ISSET( sockfd, &writefds ) ) {
783 // socket ready for accepting
784 err = [sock _write];
785 if ( err == -1 ) {
786 // action returne error, disconnect socket
787 [sock disconnect];
788 [sock performSelectorOnMainThread:@selector(_eventDidDisconnect:)
789 withObject:nil waitUntilDone:NO];
790 top--;
791 }
792 }
793 }
794 [MySocket _unlockWrite];
795
796 DONE:;
797 [pool release];
798 }
799 while ( !breakLoop );
800 }
801
802
803 - (int)_accept
804 {
805 MySocket *newSocket;
806 int newsockfd;
807 struct sockaddr addr;
808 unsigned int addrlen = sizeof(addr);
809
810 newsockfd = accept( _sockfd, &addr, &addrlen );
811 if ( newsockfd >= 0 ) {
812 // create a new MySocket
813 newSocket = [[MySocket alloc] _initWithFileDescriptor:newsockfd];
814 [newSocket setDelegate:_delegate];
815
816 [self performSelectorOnMainThread:@selector(_eventDidAcceptSocket:)
817 withObject:newSocket waitUntilDone:NO];
818 }
819 else {
820 return -1;
821 }
822 return 0;
823 }
824
825 - (int)_read
826 {
827 _MySocketPacket *packet = nil;
828 int bytesRead;
829
830 [_readLock lock];
831 if ( [_readQueue count] == 0 ) {
832 // no packets claiming anything, so just
833 // read into the unclaimed bytes buffer.
834 if ( !_unclaimedData ) {
835 _unclaimedData = [[NSMutableData alloc] init];
836 }
837 int len = [_unclaimedData length];
838 [_unclaimedData increaseLengthBy:MYSOCKET_PACKETLEN];
839 bytesRead = recv( _sockfd, [_unclaimedData mutableBytes] + len, MYSOCKET_PACKETLEN, 0 );
840 [_unclaimedData setLength:len+bytesRead];
841 }
842 else {
843 packet = [_readQueue objectAtIndex:0];
844 bytesRead = recv( _sockfd, [packet bytes], [packet bytesRemaining], 0 );
845 [packet handledBytes:bytesRead];
846 }
847 [_readLock unlock];
848
849 if ( bytesRead > 0 ) {
850 // update total bytes read
851 _bytesRead += bytesRead;
852
853 [self _handleReadQueue];
854 }
855 else {
856 // remove this socket
857 ChazLog( @"MySocket disconnecting: %i", bytesRead );
858 return -1;
859 }
860 return 0;
861 }
862
863 - (int)_write
864 {
865 _MySocketPacket *packet = nil;
866 int bytesWritten = 0;
867
868 [_writeLock lock];
869 if ( [_writeQueue count] > 0 ) {
870 int buflen = 0;
871 unsigned int len = sizeof(buflen);
872 int err;
873 err = getsockopt( _sockfd, SOL_SOCKET, SO_SNDBUF, &buflen, &len );
874 // write data
875 packet = [_writeQueue objectAtIndex:0];
876 bytesWritten = send( _sockfd, [packet bytes], MIN([packet bytesRemaining],buflen/2), 0 ); //MIN(4096,[packet bytesRemaining]), 0 );
877 [packet handledBytes:bytesWritten];
878 }
879 [_writeLock unlock];
880
881 if ( bytesWritten >= 0 ) {
882 // update total bytes read
883 _bytesWritten += bytesWritten;
884
885 [self _handleWriteQueue];
886 }
887 else {
888 return -1;
889 }
890 return 0;
891 }
892
893
894 - (void)_fillReadPacketsWithUnclaimedBytes
895 {
896 int i, top;
897 void *bytes;
898 int total;
899
900 total = [_unclaimedData length];
901 if ( total == 0 ) {
902 return;
903 }
904 bytes = [_unclaimedData mutableBytes];
905
906 [_readLock lock];
907 top = [_readQueue count];
908 for ( i = 0; i < top; i++ ) {
909 _MySocketPacket *packet = [_readQueue objectAtIndex:i];
910 int len = MIN( total, [packet bytesRemaining] );
911
912 if ( len > 0 ) {
913 memcpy( [packet bytes], bytes, len );
914 [packet handledBytes:len];
915 bytes += len;
916 total -= len;
917 }
918 if ( total == 0 ) {
919 break;
920 }
921 }
922 [_unclaimedData replaceBytesInRange:NSMakeRange(0,[_unclaimedData length]-total) withBytes:NULL length:0];
923 [_readLock unlock];
924 }
925
926
927 - (void)_handleReadQueue
928 {
929 int i, top;
930
931 [_readLock lock];
932 top = [_readQueue count];
933 for ( i = 0; i < top; ) {
934 _MySocketPacket *packet = [_readQueue objectAtIndex:0];
935 if ( [packet isComplete] ) {
936 [self performSelectorOnMainThread:@selector(_eventDidReadData:)
937 withObject:[packet retain] waitUntilDone:NO];
938 [_readQueue removeObjectAtIndex:i];
939 top--;
940 }
941 else {
942 i++;
943 }
944 }
945 [_readLock unlock];
946 }
947
948 - (void)_handleWriteQueue
949 {
950 int i, top;
951
952 [_writeLock lock];
953 top = [_writeQueue count];
954 for ( i = 0; i < top; ) {
955 _MySocketPacket *packet = [_writeQueue objectAtIndex:0];
956 if ( [packet isComplete] ) {
957 [self performSelectorOnMainThread:@selector(_eventDidWriteData:)
958 withObject:[packet retain] waitUntilDone:NO];
959 [_writeQueue removeObjectAtIndex:i];
960 top--;
961 }
962 else {
963 i++;
964 }
965 }
966 if ( [_writeQueue count] == 0 ) {
967 // no more pending writes
968 FD_CLR( _sockfd, &_mySocketGlobals.writefds );
969 }
970 [_writeLock unlock];
971 }
972
973
974 - (void)_eventDidAcceptSocket:(MySocket *)newSocket
975 {
976 // just report the event back to the delegate
977 if ( [_delegate respondsToSelector:@selector(socket:didAcceptSocket:)] ) {
978 [_delegate socket:self didAcceptSocket:newSocket];
979 }
980
981 // release the parameter(s)
982 // they were not released by the caller because the caller is in another thread.
983 [newSocket release];
984 }
985
986 - (void)_eventDidDisconnect:(id)dummy
987 {
988 [self disconnect];
989 if ( [_delegate respondsToSelector:@selector(socketDidDisconnect:)] ) {
990 [_delegate socketDidDisconnect:self];
991 }
992 }
993
994 - (void)_eventDidReadData:(_MySocketPacket *)packet
995 {
996 if ( [_delegate respondsToSelector:@selector(socket:didReadData:tag:)] ) {
997 [_delegate socket:self didReadData:[packet data] tag:[packet tag]];
998 }
999
1000 [packet release];
1001 }
1002
1003 - (void)_eventDidWriteData:(_MySocketPacket *)packet
1004 {
1005 if ( [_delegate respondsToSelector:@selector(socket:didWriteDataWithTag:)] ) {
1006 [_delegate socket:self didWriteDataWithTag:[packet tag]];
1007 }
1008
1009 [packet release];
1010 }
1011
1012
1013 - (NSMutableData *)_readBufferWithLength:(unsigned *)len
1014 {
1015 NSMutableData *buffer;
1016 unsigned packetLen = *len;
1017
1018 if ( (buffer = _unclaimedData) ) {
1019 // claim the bytes
1020 int unclaimedLen = [_unclaimedData length];
1021 if ( unclaimedLen > packetLen ) {
1022 *len = packetLen;
1023 _unclaimedData = [[NSMutableData alloc] initWithBytes:[buffer bytes]+packetLen length:unclaimedLen-packetLen];
1024 //[[buffer subdataWithRange:NSMakeRange(packetLen,unclaimedLen-packetLen)] retain];
1025 }
1026 else {
1027 *len = unclaimedLen;
1028 _unclaimedData = nil;
1029 }
1030 [buffer setLength:packetLen];
1031 }
1032 else {
1033 buffer = [[NSMutableData alloc] initWithLength:packetLen];
1034 *len = 0;
1035 }
1036 return [buffer autorelease];
1037 }
1038
1039
1040 - (int)_sockfd
1041 {
1042 return _sockfd;
1043 }
1044
1045
1046 @end
1047
1048
1049 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1050 #pragma mark _MySocketPacket
1051 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1052
1053 @implementation _MySocketPacket
1054
1055
1056 - (id)initWithData:(NSData *)data tag:(int)tag
1057 {
1058 if ( self = [super init] ) {
1059 _buffer = [data retain];
1060 _bytesRequired = [data length];
1061 _tag = tag;
1062 }
1063 return self;
1064 }
1065
1066 - (void)dealloc
1067 {
1068 [_buffer release];
1069 [super dealloc];
1070 }
1071
1072
1073 - (void *)bytes
1074 {
1075 return (void *)[_buffer bytes] + _bytesHandled;
1076 }
1077
1078 - (unsigned)bytesRemaining
1079 {
1080 return _bytesRequired - _bytesHandled;
1081 }
1082
1083
1084 - (void)handledBytes:(unsigned)count
1085 {
1086 _bytesHandled += count;
1087 }
1088
1089 - (unsigned)bytesRequired
1090 {
1091 return _bytesRequired;
1092 }
1093
1094
1095 - (NSData *)data
1096 {
1097 return _buffer;
1098 }
1099
1100 - (int)tag
1101 {
1102 return _tag;
1103 }
1104
1105 - (BOOL)isComplete
1106 {
1107 return [self bytesRemaining] == 0;
1108 }
1109
1110
1111
1112 @end
This page took 0.083018 seconds and 4 git commands to generate.