]> Dogcows Code - chaz/thecheat/blob - MySocket.m
update contact information and project URL
[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 memset( &(addr.sin_zero), NULL, 8 );
226
227 err = bind( _sockfd, (struct sockaddr *)(&addr), sizeof(addr) );
228 if ( err == -1 ) {
229 // can't bind to this address
230 close( _sockfd );
231 return NO;
232 }
233
234 err = listen( _sockfd, 10 );
235 if ( err == -1 ) {
236 // can't listen on this address
237 close( _sockfd );
238 return NO;
239 }
240
241 _flags |= kMySocketIsListener;
242 [self _connect];
243 return YES;
244 }
245
246
247 - (void)disconnect
248 {
249 if ( !(_flags & kMySocketConnected) ) {
250 // not connected
251 return;
252 }
253
254 [self _removeFromManager];
255
256 close( _sockfd );
257 _sockfd = -1;
258
259 [_readQueue release];
260 _readQueue = nil;
261 [_writeQueue release];
262 _writeQueue = nil;
263 [_readLock release];
264 _readLock = nil;
265 [_writeLock release];
266 _writeLock = nil;
267
268 _startTime = 0.0;
269
270 _flags = 0;
271 }
272
273
274 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
275 #pragma mark Reading/Writing
276 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
277
278 - (void)readDataToLength:(unsigned)len tag:(int)tag
279 {
280 _MySocketPacket *packet;
281
282 if ( ![self isConnected] || [self isListener] || len == 0 ) {
283 // must be connected and have a valid length
284 return;
285 }
286
287 // create a "read" packet
288 packet = [[_MySocketPacket alloc] initWithData:[NSMutableData dataWithLength:len] tag:tag];
289 //[packet handledBytes:0];
290
291 // add the packet to the queue
292 [_readLock lock];
293 [_readQueue addObject:packet];
294 [packet release];
295 [_readLock unlock];
296
297 // make sure the thread picks up the change
298 [MySocket _refreshReadThread];
299 }
300
301
302 - (void)writeData:(NSData *)data tag:(int)tag
303 {
304 _MySocketPacket *packet;
305 BOOL alreadyWriting;
306
307 if ( ![self isConnected] || [self isListener] ) {
308 // must be connected
309 return;
310 }
311
312 // create a "write" packet
313 packet = [[_MySocketPacket alloc] initWithData:data tag:tag];
314
315 [_writeLock lock];
316 alreadyWriting = [_writeQueue count] > 0;
317 [_writeQueue addObject:packet];
318 [packet release];
319 [_writeLock unlock];
320
321 if ( !alreadyWriting ) {
322 // make the helper aware the socket has data to write
323 [MySocket _writeWithSockFD:_sockfd];
324 }
325 }
326
327 - (void)writeBytes:(void const *)bytes length:(unsigned)len tag:(int)tag
328 {
329 [self writeData:[NSData dataWithBytes:bytes length:len] tag:tag];
330 }
331
332
333 // AsyncSocket compatibility
334 - (void)readDataToLength:(CFIndex)length withTimeout:(NSTimeInterval)timeout tag:(long)tag
335 {
336 [self readDataToLength:length tag:tag];
337 }
338
339 - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
340 {
341 [self writeData:data tag:tag];
342 }
343
344 - (void)writeBytes:(void *)bytes length:(unsigned)len withTimeout:(NSTimeInterval)timeout tag:(long)tag
345 {
346 [self writeBytes:bytes length:len tag:tag];
347 }
348
349
350 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
351 #pragma mark Accesors
352 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
353
354 - (unsigned)bytesRead
355 {
356 return _bytesRead;
357 }
358
359 - (unsigned)bytesWritten
360 {
361 return _bytesWritten;
362 }
363
364 - (NSTimeInterval)timeConnected
365 {
366 return CFAbsoluteTimeGetCurrent() - _startTime;
367 }
368
369 - (double)readSpeed
370 {
371 double currentTime = CFAbsoluteTimeGetCurrent();
372 double speed = (double)( _bytesRead - _lastBytesRead ) / ( currentTime - _lastBytesReadTime );
373 _lastBytesRead = _bytesRead;
374 _lastBytesReadTime = currentTime;
375 return speed;
376 }
377
378 - (double)writeSpeed
379 {
380 double currentTime = CFAbsoluteTimeGetCurrent();
381 double speed = (double)( _bytesWritten - _lastBytesWritten ) / ( currentTime - _lastBytesWrittenTime );
382 _lastBytesWritten = _bytesWritten;
383 _lastBytesWrittenTime = currentTime;
384 return speed;
385 }
386
387
388 - (NSString *)localHost
389 {
390 char host[128];
391 int err;
392
393 err = gethostname( host, sizeof(host) );
394 if ( err == -1 ) {
395 return @"";
396 }
397 return [NSString stringWithCString:host];
398 }
399
400 - (int)localPort
401 {
402 return 0;
403 }
404
405 - (NSString *)remoteHost
406 {
407 int err;
408 struct sockaddr_in addr;
409 int len = sizeof(addr);
410
411 err = getpeername( _sockfd, (struct sockaddr *)(&addr), &len );
412 if ( err == -1 ) {
413 return @"Unknown";
414 }
415 return [NSString stringWithCString:inet_ntoa(addr.sin_addr)];
416 }
417
418 - (int)remotePort
419 {
420 int err;
421 struct sockaddr_in addr;
422 int len = sizeof(addr);
423
424 err = getpeername( _sockfd, (struct sockaddr *)(&addr), &len );
425 if ( err == -1 ) {
426 return -1;
427 }
428 return addr.sin_port;
429 }
430
431
432 - (BOOL)isConnected
433 {
434 return _flags & kMySocketConnected;
435 }
436
437 - (BOOL)isListener
438 {
439 return _flags & kMySocketIsListener;
440 }
441
442
443 + (NSData *)addressWithHost:(NSString *)host port:(int)port
444 {
445 struct hostent *h;
446 struct sockaddr_in addr;
447
448 // resolve the host
449 h = gethostbyname( [host lossyCString] );
450 if ( h == NULL ) {
451 // host not found
452 return nil;
453 }
454
455 // pack the socket address structure
456 addr.sin_family = AF_INET;
457 addr.sin_port = htons( (short)port );
458 memcpy( &(addr.sin_addr), h->h_addr, sizeof(struct in_addr) );
459 memset( &(addr.sin_zero), NULL, 8 );
460
461 return [NSData dataWithBytes:&addr length:sizeof(addr)];
462 }
463
464
465 - (id)delegate
466 {
467 return _delegate;
468 }
469
470 - (void)setDelegate:(id)delegate
471 {
472 _delegate = delegate;
473 }
474
475
476 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
477 #pragma mark PrivateAPI
478 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
479
480 - (id)_initWithFileDescriptor:(int)sockfd
481 {
482 if ( self = [super init] ) {
483 _sockfd = sockfd;
484 [self _connect];
485 }
486 return self;
487 }
488
489 - (void)_connect
490 {
491 if ( ![self isListener] ) {
492 _readQueue = [[NSMutableArray alloc] init];
493 _writeQueue = [[NSMutableArray alloc] init];
494 }
495
496 // create the locks
497 _readLock = [[NSRecursiveLock alloc] init];
498 _writeLock = [[NSRecursiveLock alloc] init];
499
500 _startTime = _lastBytesReadTime = _lastBytesWrittenTime = CFAbsoluteTimeGetCurrent();
501 _bytesRead = _lastBytesRead = _bytesWritten = _lastBytesWritten = 0;
502
503 _flags |= kMySocketConnected;
504
505 [self _addToManager];
506 }
507
508
509 - (void)_addToManager
510 {
511 if ( _flags & kMySocketAddedToManager ) {
512 // only add this socket once
513 return;
514 }
515
516 // start the manager if it is not already started
517 [MySocket _startManager];
518
519 [MySocket _lockReadAndWrite];
520 // add to global array of sockets
521 [_mySocketGlobals.sockets addObject:self];
522 [self release];
523 [MySocket _readWithSockFD:_sockfd];
524 [MySocket _unlockReadAndWrite];
525
526 // mark as added to manager
527 _flags |= kMySocketAddedToManager;
528 }
529
530 - (void)_removeFromManager
531 {
532 if ( !(_flags & kMySocketAddedToManager) ) {
533 // only remove if it is added
534 return;
535 }
536
537 [MySocket _lockReadAndWrite];
538 // remove from global array
539 [self retain];
540 ChazLog( @"REMOVING SOCKET AT INDEX %i", [_mySocketGlobals.sockets indexOfObject:self] );
541 [_mySocketGlobals.sockets removeObject:self];
542 FD_CLR( _sockfd, &_mySocketGlobals.readfds );
543 FD_CLR( _sockfd, &_mySocketGlobals.writefds );
544 [MySocket _unlockReadAndWrite];
545
546 _flags ^= kMySocketAddedToManager;
547 }
548
549
550 + (void)_readWithSockFD:(int)fd
551 {
552 [MySocket _lockRead];
553 FD_SET( fd, &_mySocketGlobals.readfds );
554 _mySocketGlobals.maxreadfd = MAX( _mySocketGlobals.maxreadfd, fd );
555 [MySocket _unlockRead];
556 // make sure the thread picks up the change
557 [MySocket _refreshReadThread];
558 }
559
560 + (void)_refreshReadThread
561 {
562 char b = 'R';
563 write( _mySocketGlobals.readPipe[1], &b, sizeof(b) );
564 }
565
566 + (void)_writeWithSockFD:(int)fd
567 {
568 [MySocket _lockWrite];
569 FD_SET( fd, &_mySocketGlobals.writefds );
570 _mySocketGlobals.maxwritefd = MAX( _mySocketGlobals.maxwritefd, fd );
571 [MySocket _unlockWrite];
572 [MySocket _refreshWriteThread];
573 }
574
575 + (void)_refreshWriteThread
576 {
577 char b = 'R';
578 write( _mySocketGlobals.writePipe[1], &b, sizeof(b) );
579 }
580
581
582 + (void)_lockRead
583 {
584 [_mySocketGlobals.readLock lock];
585 }
586
587 + (void)_unlockRead
588 {
589 [_mySocketGlobals.readLock unlock];
590 }
591
592 + (void)_lockWrite
593 {
594 [_mySocketGlobals.writeLock lock];
595 }
596
597 + (void)_unlockWrite
598 {
599 [_mySocketGlobals.writeLock unlock];
600 }
601
602 + (void)_lockReadAndWrite
603 {
604 [MySocket _lockRead];
605 [MySocket _lockWrite];
606 }
607
608 + (void)_unlockReadAndWrite
609 {
610 [MySocket _unlockRead];
611 [MySocket _unlockWrite];
612 }
613
614
615 + (void)_startManager
616 {
617 int err;
618
619 if ( _mySocketGlobals.isManagerRunning ) {
620 return;
621 }
622
623 ChazLog( @"MySocketHelper STARTING" );
624
625 // zero the descriptor sets
626 FD_ZERO( &_mySocketGlobals.readfds );
627 FD_ZERO( &_mySocketGlobals.writefds );
628
629 // create the read pipe
630 err = pipe( _mySocketGlobals.readPipe );
631 if ( err == -1 ) {
632 return;
633 }
634 FD_SET( _mySocketGlobals.readPipe[0], &_mySocketGlobals.readfds );
635 _mySocketGlobals.maxreadfd = _mySocketGlobals.readPipe[0];
636 // create the write pipe
637 err = pipe( _mySocketGlobals.writePipe );
638 if ( err == -1 ) {
639 close( _mySocketGlobals.readPipe[0] );
640 close( _mySocketGlobals.readPipe[1] );
641 return;
642 }
643 _mySocketGlobals.maxwritefd = _mySocketGlobals.writePipe[0];
644
645 // create other global objects
646 _mySocketGlobals.sockets = [[NSMutableArray alloc] init];
647 _mySocketGlobals.readLock = [[NSRecursiveLock alloc] init];
648 _mySocketGlobals.writeLock = [[NSRecursiveLock alloc] init];
649
650 // start the threads
651 [NSThread detachNewThreadSelector:@selector(_readThread:) toTarget:[MySocket class] withObject:nil];
652 [NSThread detachNewThreadSelector:@selector(_writeThread:) toTarget:[MySocket class] withObject:nil];
653 _mySocketGlobals.isManagerRunning = YES;
654 }
655
656 + (void)_readThread:(id)object
657 {
658 BOOL breakLoop = NO;
659 fd_set readfds;
660
661 do {
662 int err;
663 int i, top;
664
665 // create the ever-so-important pool
666 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
667
668 [MySocket _lockRead];
669 //FD_COPY( &_mySocketGlobals.readfds, &readfds );
670 readfds = _mySocketGlobals.readfds;
671 [MySocket _unlockRead];
672
673 // find the sockets which need processing
674 err = select( _mySocketGlobals.maxreadfd+1, &readfds, NULL, NULL, NULL );
675 if ( err == -1 ) {
676 // trouble, select() is having problems
677 ChazLog( @"select() failed!, error: %s", strerror(errno) );
678 goto DONE;
679 }
680
681 // check the pipe
682 if ( FD_ISSET( _mySocketGlobals.readPipe[0], &readfds ) ) {
683 char b;
684 err = read( _mySocketGlobals.readPipe[0], &b, sizeof(b) );
685 if ( err <= 0 ) {
686 // our connection to the main thread was severed...
687 // SELF DESTRUCT
688 ChazLog( @"readPipe severed, exiting READ thread..." );
689 breakLoop = YES;
690 goto DONE;
691 }
692 }
693
694 // process the sockets
695 [MySocket _lockRead];
696 top = [_mySocketGlobals.sockets count];
697 for ( i = 0; i < top; i++ ) {
698 MySocket *sock = [_mySocketGlobals.sockets objectAtIndex:i];
699 int sockfd = [sock _sockfd];
700
701 [sock _fillReadPacketsWithUnclaimedBytes];
702 [sock _handleReadQueue];
703
704 if ( FD_ISSET( sockfd, &readfds ) ) {
705 if ( [sock isListener] ) {
706 // socket ready for accepting
707 err = [sock _accept];
708 }
709 else {
710 // socket ready for reading
711 err = [sock _read];
712 }
713 if ( err == -1 ) {
714 // action returne error, disconnect socket
715 [sock disconnect];
716 [sock performSelectorOnMainThread:@selector(_eventDidDisconnect:)
717 withObject:nil waitUntilDone:NO];
718 top--;
719 }
720 }
721 }
722 [MySocket _unlockRead];
723
724 DONE:;
725 [pool release];
726 }
727 while ( !breakLoop );
728 }
729
730 + (void)_writeThread:(id)object
731 {
732 BOOL breakLoop = NO;
733 fd_set pipefds;
734 fd_set readfds, writefds;
735
736 FD_ZERO( &pipefds );
737 FD_SET( _mySocketGlobals.writePipe[0], &pipefds );
738
739 do {
740 int err;
741 int i, top;
742
743 // create the ever-so-important pool
744 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
745
746 readfds = pipefds;
747 [MySocket _lockWrite];
748 //FD_COPY( &_mySocketGlobals.writefds, &writefds );
749 writefds = _mySocketGlobals.writefds;
750 [MySocket _unlockWrite];
751
752 // find the sockets which need processing
753 err = select( _mySocketGlobals.maxwritefd+1, &readfds, &writefds, NULL, NULL );
754 if ( err == -1 ) {
755 // trouble, select() is having problems
756 ChazLog( @"select() failed!, error: %s", strerror(errno) );
757 goto DONE;
758 }
759
760 // check the pipe
761 if ( FD_ISSET( _mySocketGlobals.writePipe[0], &readfds ) ) {
762 char b;
763 err = read( _mySocketGlobals.writePipe[0], &b, sizeof(b) );
764 if ( err <= 0 ) {
765 // our connection to the main thread was severed...
766 // SELF DESTRUCT
767 ChazLog( @"writePipe severed" );
768 breakLoop = YES;
769 goto DONE;
770 }
771 }
772
773 // process the sockets
774 [MySocket _lockWrite];
775 top = [_mySocketGlobals.sockets count];
776 for ( i = 0; i < top; i++ ) {
777 MySocket *sock = [_mySocketGlobals.sockets objectAtIndex:i];
778 int sockfd = [sock _sockfd];
779
780 if ( FD_ISSET( sockfd, &writefds ) ) {
781 // socket ready for accepting
782 err = [sock _write];
783 if ( err == -1 ) {
784 // action returne error, disconnect socket
785 [sock disconnect];
786 [sock performSelectorOnMainThread:@selector(_eventDidDisconnect:)
787 withObject:nil waitUntilDone:NO];
788 top--;
789 }
790 }
791 }
792 [MySocket _unlockWrite];
793
794 DONE:;
795 [pool release];
796 }
797 while ( !breakLoop );
798 }
799
800
801 - (int)_accept
802 {
803 MySocket *newSocket;
804 int newsockfd;
805 struct sockaddr addr;
806 int addrlen = sizeof(addr);
807
808 newsockfd = accept( _sockfd, &addr, &addrlen );
809 if ( newsockfd >= 0 ) {
810 // create a new MySocket
811 newSocket = [[MySocket alloc] _initWithFileDescriptor:newsockfd];
812 [newSocket setDelegate:_delegate];
813
814 [self performSelectorOnMainThread:@selector(_eventDidAcceptSocket:)
815 withObject:newSocket waitUntilDone:NO];
816 }
817 else {
818 return -1;
819 }
820 return 0;
821 }
822
823 - (int)_read
824 {
825 _MySocketPacket *packet = nil;
826 int bytesRead;
827
828 [_readLock lock];
829 if ( [_readQueue count] == 0 ) {
830 // no packets claiming anything, so just
831 // read into the unclaimed bytes buffer.
832 if ( !_unclaimedData ) {
833 _unclaimedData = [[NSMutableData alloc] init];
834 }
835 int len = [_unclaimedData length];
836 [_unclaimedData increaseLengthBy:MYSOCKET_PACKETLEN];
837 bytesRead = recv( _sockfd, [_unclaimedData mutableBytes] + len, MYSOCKET_PACKETLEN, 0 );
838 [_unclaimedData setLength:len+bytesRead];
839 }
840 else {
841 packet = [_readQueue objectAtIndex:0];
842 bytesRead = recv( _sockfd, [packet bytes], [packet bytesRemaining], 0 );
843 [packet handledBytes:bytesRead];
844 }
845 [_readLock unlock];
846
847 if ( bytesRead > 0 ) {
848 // update total bytes read
849 _bytesRead += bytesRead;
850
851 [self _handleReadQueue];
852 }
853 else {
854 // remove this socket
855 ChazLog( @"MySocket disconnecting: %i", bytesRead );
856 return -1;
857 }
858 return 0;
859 }
860
861 - (int)_write
862 {
863 _MySocketPacket *packet = nil;
864 int bytesWritten = 0;
865
866 [_writeLock lock];
867 if ( [_writeQueue count] > 0 ) {
868 int buflen = 0;
869 int len = sizeof(buflen);
870 int err;
871 err = getsockopt( _sockfd, SOL_SOCKET, SO_SNDBUF, &buflen, &len );
872 // write data
873 packet = [_writeQueue objectAtIndex:0];
874 bytesWritten = send( _sockfd, [packet bytes], MIN([packet bytesRemaining],buflen/2), 0 ); //MIN(4096,[packet bytesRemaining]), 0 );
875 [packet handledBytes:bytesWritten];
876 }
877 [_writeLock unlock];
878
879 if ( bytesWritten >= 0 ) {
880 // update total bytes read
881 _bytesWritten += bytesWritten;
882
883 [self _handleWriteQueue];
884 }
885 else {
886 return -1;
887 }
888 return 0;
889 }
890
891
892 - (void)_fillReadPacketsWithUnclaimedBytes
893 {
894 int i, top;
895 void *bytes;
896 int total;
897
898 total = [_unclaimedData length];
899 if ( total == 0 ) {
900 return;
901 }
902 bytes = [_unclaimedData mutableBytes];
903
904 [_readLock lock];
905 top = [_readQueue count];
906 for ( i = 0; i < top; i++ ) {
907 _MySocketPacket *packet = [_readQueue objectAtIndex:i];
908 int len = MIN( total, [packet bytesRemaining] );
909
910 if ( len > 0 ) {
911 memcpy( [packet bytes], bytes, len );
912 [packet handledBytes:len];
913 bytes += len;
914 total -= len;
915 }
916 if ( total == 0 ) {
917 break;
918 }
919 }
920 [_unclaimedData replaceBytesInRange:NSMakeRange(0,[_unclaimedData length]-total) withBytes:NULL length:0];
921 [_readLock unlock];
922 }
923
924
925 - (void)_handleReadQueue
926 {
927 int i, top;
928
929 [_readLock lock];
930 top = [_readQueue count];
931 for ( i = 0; i < top; ) {
932 _MySocketPacket *packet = [_readQueue objectAtIndex:0];
933 if ( [packet isComplete] ) {
934 [self performSelectorOnMainThread:@selector(_eventDidReadData:)
935 withObject:[packet retain] waitUntilDone:NO];
936 [_readQueue removeObjectAtIndex:i];
937 top--;
938 }
939 else {
940 i++;
941 }
942 }
943 [_readLock unlock];
944 }
945
946 - (void)_handleWriteQueue
947 {
948 int i, top;
949
950 [_writeLock lock];
951 top = [_writeQueue count];
952 for ( i = 0; i < top; ) {
953 _MySocketPacket *packet = [_writeQueue objectAtIndex:0];
954 if ( [packet isComplete] ) {
955 [self performSelectorOnMainThread:@selector(_eventDidWriteData:)
956 withObject:[packet retain] waitUntilDone:NO];
957 [_writeQueue removeObjectAtIndex:i];
958 top--;
959 }
960 else {
961 i++;
962 }
963 }
964 if ( [_writeQueue count] == 0 ) {
965 // no more pending writes
966 FD_CLR( _sockfd, &_mySocketGlobals.writefds );
967 }
968 [_writeLock unlock];
969 }
970
971
972 - (void)_eventDidAcceptSocket:(MySocket *)newSocket
973 {
974 // just report the event back to the delegate
975 if ( [_delegate respondsToSelector:@selector(socket:didAcceptSocket:)] ) {
976 [_delegate socket:self didAcceptSocket:newSocket];
977 }
978
979 // release the parameter(s)
980 // they were not released by the caller because the caller is in another thread.
981 [newSocket release];
982 }
983
984 - (void)_eventDidDisconnect:(id)dummy
985 {
986 [self disconnect];
987 if ( [_delegate respondsToSelector:@selector(socketDidDisconnect:)] ) {
988 [_delegate socketDidDisconnect:self];
989 }
990 }
991
992 - (void)_eventDidReadData:(_MySocketPacket *)packet
993 {
994 if ( [_delegate respondsToSelector:@selector(socket:didReadData:tag:)] ) {
995 [_delegate socket:self didReadData:[packet data] tag:[packet tag]];
996 }
997
998 [packet release];
999 }
1000
1001 - (void)_eventDidWriteData:(_MySocketPacket *)packet
1002 {
1003 if ( [_delegate respondsToSelector:@selector(socket:didWriteDataWithTag:)] ) {
1004 [_delegate socket:self didWriteDataWithTag:[packet tag]];
1005 }
1006
1007 [packet release];
1008 }
1009
1010
1011 - (NSMutableData *)_readBufferWithLength:(unsigned *)len
1012 {
1013 NSMutableData *buffer;
1014 unsigned packetLen = *len;
1015
1016 if ( buffer = _unclaimedData ) {
1017 // claim the bytes
1018 int unclaimedLen = [_unclaimedData length];
1019 if ( unclaimedLen > packetLen ) {
1020 *len = packetLen;
1021 _unclaimedData = [[NSMutableData alloc] initWithBytes:[buffer bytes]+packetLen length:unclaimedLen-packetLen];
1022 //[[buffer subdataWithRange:NSMakeRange(packetLen,unclaimedLen-packetLen)] retain];
1023 }
1024 else {
1025 *len = unclaimedLen;
1026 _unclaimedData = nil;
1027 }
1028 [buffer setLength:packetLen];
1029 }
1030 else {
1031 buffer = [[NSMutableData alloc] initWithLength:packetLen];
1032 *len = 0;
1033 }
1034 return [buffer autorelease];
1035 }
1036
1037
1038 - (int)_sockfd
1039 {
1040 return _sockfd;
1041 }
1042
1043
1044 @end
1045
1046
1047 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1048 #pragma mark _MySocketPacket
1049 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1050
1051 @implementation _MySocketPacket
1052
1053
1054 - (id)initWithData:(NSData *)data tag:(int)tag
1055 {
1056 if ( self = [super init] ) {
1057 _buffer = [data retain];
1058 _bytesRequired = [data length];
1059 _tag = tag;
1060 }
1061 return self;
1062 }
1063
1064 - (void)dealloc
1065 {
1066 [_buffer release];
1067 [super dealloc];
1068 }
1069
1070
1071 - (void *)bytes
1072 {
1073 return (void *)[_buffer bytes] + _bytesHandled;
1074 }
1075
1076 - (unsigned)bytesRemaining
1077 {
1078 return _bytesRequired - _bytesHandled;
1079 }
1080
1081
1082 - (void)handledBytes:(unsigned)count
1083 {
1084 _bytesHandled += count;
1085 }
1086
1087 - (unsigned)bytesRequired
1088 {
1089 return _bytesRequired;
1090 }
1091
1092
1093 - (NSData *)data
1094 {
1095 return _buffer;
1096 }
1097
1098 - (int)tag
1099 {
1100 return _tag;
1101 }
1102
1103 - (BOOL)isComplete
1104 {
1105 return [self bytesRemaining] == 0;
1106 }
1107
1108
1109
1110 @end
This page took 0.073068 seconds and 4 git commands to generate.