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