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