5 // Created by Chaz McGarvey on 2/1/05.
6 // Copyright 2005 Chaz McGarvey. All rights reserved.
14 // this is used to read in unclaimed data
15 #define MYSOCKET_PACKETLEN (1024)
18 kMySocketAddedToManager
= 1,
19 kMySocketConnected
= 2,
20 kMySocketIsListener
= 4
24 struct _mySocketGlobals
{
25 BOOL isManagerRunning
;
26 NSMutableArray
*sockets
;
27 NSRecursiveLock
*readLock
;
28 NSRecursiveLock
*writeLock
;
35 } _mySocketGlobals
= { NO
, nil, nil, nil, { -1, -1 }, { -1, -1 }, 0, 0 };
40 @interface _MySocketPacket
: NSObject
43 unsigned _bytesHandled
;
44 unsigned _bytesRequired
;
48 - (id)initWithData
:(NSData
*)data tag
:(int)tag
;
50 - (void *)bytes
; // pointer to the current bytes; changes are bytes are handled
51 - (unsigned)bytesRemaining
;
53 - (void)handledBytes
:(unsigned)count
;
55 - (unsigned)bytesRequired
;
66 @interface MySocket ( PrivateAPI
)
68 - (id)_initWithFileDescriptor
:(int)sockfd
;
71 - (void)_addToManager
;
72 - (void)_removeFromManager
;
74 + (void)_readWithSockFD
:(int)fd
;
75 + (void)_refreshReadThread
;
76 + (void)_writeWithSockFD
:(int)fd
;
77 + (void)_refreshWriteThread
;
83 + (void)_lockReadAndWrite
;
84 + (void)_unlockReadAndWrite
;
86 /* #### MANAGER METHODS #### */
87 + (void)_startManager
;
88 + (void)_readThread
:(id)object
;
89 + (void)_writeThread
:(id)object
;
95 - (void)_fillReadPacketsWithUnclaimedBytes
;
97 - (void)_handleReadQueue
;
98 - (void)_handleWriteQueue
;
100 - (void)_eventDidAcceptSocket
:(MySocket
*)newSocket
;
101 - (void)_eventDidDisconnect
:(id)dummy
;
102 - (void)_eventDidReadData
:(_MySocketPacket
*)packet
;
103 - (void)_eventDidWriteData
:(_MySocketPacket
*)packet
;
106 - (NSMutableData
*)_readBufferWithLength
:(unsigned *)len
;
115 @implementation MySocket
118 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
119 #pragma mark Initialization
120 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
122 - (id)initWithDelegate
:(id)delegate
124 if ( self = [super init
] ) {
125 ChazLog( @
"SOCKET CREATED" );
126 [self setDelegate
:delegate
];
133 ChazLog( @
"SOCKET DESTROYED" );
141 if ( [self retainCount
] == 1 ) {
142 [self _removeFromManager
];
149 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
150 #pragma mark Connecting/Disconnecting
151 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
153 - (BOOL)connectToHost
:(NSString
*)host port
:(int)port
155 return [self connectToAddressWithData
:[MySocket addressWithHost
:host port
:port
]];
158 - (BOOL)connectToAddress
:(const struct sockaddr
*)addr length
:(unsigned)addrLen
162 if ( [self isConnected
] ) {
166 _sockfd
= socket( addr
->sa_family
, SOCK_STREAM
, 0 );
167 if ( _sockfd
== -1 ) {
168 // can't get file descriptor
171 // make the socket NOT block
172 /*err = fcntl( _sockfd, F_SETFL, O_NONBLOCK );
178 err
= connect( _sockfd
, addr
, addrLen
);
189 - (BOOL)connectToAddressWithData
:(NSData
*)addr
191 return [self connectToAddress
:[addr bytes
] length
:[addr length
]];
194 - (BOOL)listenOnPort
:(int)port
196 struct sockaddr_in addr
;
201 if ( [self isConnected
] ) {
205 _sockfd
= socket( AF_INET
, SOCK_STREAM
, 0 );
206 if ( _sockfd
== -1 ) {
207 // can't get file descriptor
210 err
= setsockopt( _sockfd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(yes
) );
212 // can't reuse address
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 );
223 err
= bind( _sockfd
, (struct sockaddr
*)(&addr
), sizeof(addr
) );
225 // can't bind to this address
230 err
= listen( _sockfd
, 10 );
232 // can't listen on this address
237 _flags |
= kMySocketIsListener
;
245 if ( !(_flags
& kMySocketConnected
) ) {
250 [self _removeFromManager
];
255 [_readQueue release
];
257 [_writeQueue release
];
261 [_writeLock release
];
270 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
271 #pragma mark Reading/Writing
272 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
274 - (void)readDataToLength
:(unsigned)len tag
:(int)tag
276 _MySocketPacket
*packet
;
278 if ( ![self isConnected
] ||
[self isListener
] || len
== 0 ) {
279 // must be connected and have a valid length
283 // create a "read" packet
284 packet
= [[_MySocketPacket alloc
] initWithData
:[NSMutableData dataWithLength
:len
] tag
:tag
];
285 //[packet handledBytes:0];
287 // add the packet to the queue
289 [_readQueue addObject
:packet
];
293 // make sure the thread picks up the change
294 [MySocket _refreshReadThread
];
298 - (void)writeData
:(NSData
*)data tag
:(int)tag
300 _MySocketPacket
*packet
;
303 if ( ![self isConnected
] ||
[self isListener
] ) {
308 // create a "write" packet
309 packet
= [[_MySocketPacket alloc
] initWithData
:data tag
:tag
];
312 alreadyWriting
= [_writeQueue count
] > 0;
313 [_writeQueue addObject
:packet
];
317 if ( !alreadyWriting
) {
318 // make the helper aware the socket has data to write
319 [MySocket _writeWithSockFD
:_sockfd
];
323 - (void)writeBytes
:(void const *)bytes length
:(unsigned)len tag
:(int)tag
325 [self writeData
:[NSData dataWithBytes
:bytes length
:len
] tag
:tag
];
329 // AsyncSocket compatibility
330 - (void)readDataToLength
:(CFIndex
)length withTimeout
:(NSTimeInterval
)timeout tag
:(long)tag
332 [self readDataToLength
:length tag
:tag
];
335 - (void)writeData
:(NSData
*)data withTimeout
:(NSTimeInterval
)timeout tag
:(long)tag
337 [self writeData
:data tag
:tag
];
340 - (void)writeBytes
:(void *)bytes length
:(unsigned)len withTimeout
:(NSTimeInterval
)timeout tag
:(long)tag
342 [self writeBytes
:bytes length
:len tag
:tag
];
346 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
347 #pragma mark Accesors
348 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
350 - (unsigned)bytesRead
355 - (unsigned)bytesWritten
357 return _bytesWritten
;
360 - (NSTimeInterval
)timeConnected
362 return CFAbsoluteTimeGetCurrent() - _startTime
;
367 double currentTime
= CFAbsoluteTimeGetCurrent();
368 double speed
= (double)( _bytesRead
- _lastBytesRead
) / ( currentTime
- _lastBytesReadTime
);
369 _lastBytesRead
= _bytesRead
;
370 _lastBytesReadTime
= currentTime
;
376 double currentTime
= CFAbsoluteTimeGetCurrent();
377 double speed
= (double)( _bytesWritten
- _lastBytesWritten
) / ( currentTime
- _lastBytesWrittenTime
);
378 _lastBytesWritten
= _bytesWritten
;
379 _lastBytesWrittenTime
= currentTime
;
384 - (NSString
*)localHost
389 err
= gethostname( host
, sizeof(host
) );
393 return [NSString stringWithCString
:host
];
401 - (NSString
*)remoteHost
404 struct sockaddr_in addr
;
405 int len
= sizeof(addr
);
407 err
= getpeername( _sockfd
, (struct sockaddr
*)(&addr
), &len
);
411 return [NSString stringWithCString
:inet_ntoa(addr.sin_addr
)];
417 struct sockaddr_in addr
;
418 int len
= sizeof(addr
);
420 err
= getpeername( _sockfd
, (struct sockaddr
*)(&addr
), &len
);
424 return addr.sin_port
;
430 return _flags
& kMySocketConnected
;
435 return _flags
& kMySocketIsListener
;
439 + (NSData
*)addressWithHost
:(NSString
*)host port
:(int)port
442 struct sockaddr_in addr
;
445 h
= gethostbyname( [host lossyCString
] );
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 );
457 return [NSData dataWithBytes
:&addr length
:sizeof(addr
)];
466 - (void)setDelegate
:(id)delegate
468 _delegate
= delegate
;
472 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
473 #pragma mark PrivateAPI
474 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
476 - (id)_initWithFileDescriptor
:(int)sockfd
478 if ( self = [super init
] ) {
487 if ( ![self isListener
] ) {
488 _readQueue
= [[NSMutableArray alloc
] init
];
489 _writeQueue
= [[NSMutableArray alloc
] init
];
493 _readLock
= [[NSRecursiveLock alloc
] init
];
494 _writeLock
= [[NSRecursiveLock alloc
] init
];
496 _startTime
= _lastBytesReadTime
= _lastBytesWrittenTime
= CFAbsoluteTimeGetCurrent();
497 _bytesRead
= _lastBytesRead
= _bytesWritten
= _lastBytesWritten
= 0;
499 _flags |
= kMySocketConnected
;
501 [self _addToManager
];
505 - (void)_addToManager
507 if ( _flags
& kMySocketAddedToManager
) {
508 // only add this socket once
512 // start the manager if it is not already started
513 [MySocket _startManager
];
515 [MySocket _lockReadAndWrite
];
516 // add to global array of sockets
517 [_mySocketGlobals.sockets addObject
:self];
519 [MySocket _readWithSockFD
:_sockfd
];
520 [MySocket _unlockReadAndWrite
];
522 // mark as added to manager
523 _flags |
= kMySocketAddedToManager
;
526 - (void)_removeFromManager
528 if ( !(_flags
& kMySocketAddedToManager
) ) {
529 // only remove if it is added
533 [MySocket _lockReadAndWrite
];
534 // remove from global array
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
];
542 _flags ^
= kMySocketAddedToManager
;
546 + (void)_readWithSockFD
:(int)fd
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
];
556 + (void)_refreshReadThread
559 write( _mySocketGlobals.readPipe
[1], &b
, sizeof(b
) );
562 + (void)_writeWithSockFD
:(int)fd
564 [MySocket _lockWrite
];
565 FD_SET( fd
, &_mySocketGlobals.writefds
);
566 _mySocketGlobals.maxwritefd
= MAX( _mySocketGlobals.maxwritefd
, fd
);
567 [MySocket _unlockWrite
];
568 [MySocket _refreshWriteThread
];
571 + (void)_refreshWriteThread
574 write( _mySocketGlobals.writePipe
[1], &b
, sizeof(b
) );
580 [_mySocketGlobals.readLock lock
];
585 [_mySocketGlobals.readLock unlock
];
590 [_mySocketGlobals.writeLock lock
];
595 [_mySocketGlobals.writeLock unlock
];
598 + (void)_lockReadAndWrite
600 [MySocket _lockRead
];
601 [MySocket _lockWrite
];
604 + (void)_unlockReadAndWrite
606 [MySocket _unlockRead
];
607 [MySocket _unlockWrite
];
611 + (void)_startManager
615 if ( _mySocketGlobals.isManagerRunning
) {
619 ChazLog( @
"MySocketHelper STARTING" );
621 // zero the descriptor sets
622 FD_ZERO( &_mySocketGlobals.readfds
);
623 FD_ZERO( &_mySocketGlobals.writefds
);
625 // create the read pipe
626 err
= pipe( _mySocketGlobals.readPipe
);
630 FD_SET( _mySocketGlobals.readPipe
[0], &_mySocketGlobals.readfds
);
631 _mySocketGlobals.maxreadfd
= _mySocketGlobals.readPipe
[0];
632 // create the write pipe
633 err
= pipe( _mySocketGlobals.writePipe
);
635 close( _mySocketGlobals.readPipe
[0] );
636 close( _mySocketGlobals.readPipe
[1] );
639 _mySocketGlobals.maxwritefd
= _mySocketGlobals.writePipe
[0];
641 // create other global objects
642 _mySocketGlobals.sockets
= [[NSMutableArray alloc
] init
];
643 _mySocketGlobals.readLock
= [[NSRecursiveLock alloc
] init
];
644 _mySocketGlobals.writeLock
= [[NSRecursiveLock alloc
] init
];
647 [NSThread detachNewThreadSelector
:@selector(_readThread
:) toTarget
:[MySocket
class] withObject
:nil];
648 [NSThread detachNewThreadSelector
:@selector(_writeThread
:) toTarget
:[MySocket
class] withObject
:nil];
649 _mySocketGlobals.isManagerRunning
= YES
;
652 + (void)_readThread
:(id)object
661 // create the ever-so-important pool
662 NSAutoreleasePool
*pool
= [[NSAutoreleasePool alloc
] init
];
664 [MySocket _lockRead
];
665 //FD_COPY( &_mySocketGlobals.readfds, &readfds );
666 readfds
= _mySocketGlobals.readfds
;
667 [MySocket _unlockRead
];
669 // find the sockets which need processing
670 err
= select( _mySocketGlobals.maxreadfd
+1, &readfds
, NULL
, NULL
, NULL
);
672 // trouble, select() is having problems
673 ChazLog( @
"select() failed!, error: %s", strerror(errno
) );
678 if ( FD_ISSET( _mySocketGlobals.readPipe
[0], &readfds
) ) {
680 err
= read( _mySocketGlobals.readPipe
[0], &b
, sizeof(b
) );
682 // our connection to the main thread was severed...
684 ChazLog( @
"readPipe severed, exiting READ thread..." );
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
];
697 [sock _fillReadPacketsWithUnclaimedBytes
];
698 [sock _handleReadQueue
];
700 if ( FD_ISSET( sockfd
, &readfds
) ) {
701 if ( [sock isListener
] ) {
702 // socket ready for accepting
703 err
= [sock _accept
];
706 // socket ready for reading
710 // action returne error, disconnect socket
712 [sock performSelectorOnMainThread
:@selector(_eventDidDisconnect
:)
713 withObject
:nil waitUntilDone
:NO
];
718 [MySocket _unlockRead
];
723 while ( !breakLoop
);
726 + (void)_writeThread
:(id)object
730 fd_set readfds
, writefds
;
733 FD_SET( _mySocketGlobals.writePipe
[0], &pipefds
);
739 // create the ever-so-important pool
740 NSAutoreleasePool
*pool
= [[NSAutoreleasePool alloc
] init
];
743 [MySocket _lockWrite
];
744 //FD_COPY( &_mySocketGlobals.writefds, &writefds );
745 writefds
= _mySocketGlobals.writefds
;
746 [MySocket _unlockWrite
];
748 // find the sockets which need processing
749 err
= select( _mySocketGlobals.maxwritefd
+1, &readfds
, &writefds
, NULL
, NULL
);
751 // trouble, select() is having problems
752 ChazLog( @
"select() failed!, error: %s", strerror(errno
) );
757 if ( FD_ISSET( _mySocketGlobals.writePipe
[0], &readfds
) ) {
759 err
= read( _mySocketGlobals.writePipe
[0], &b
, sizeof(b
) );
761 // our connection to the main thread was severed...
763 ChazLog( @
"writePipe severed" );
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
];
776 if ( FD_ISSET( sockfd
, &writefds
) ) {
777 // socket ready for accepting
780 // action returne error, disconnect socket
782 [sock performSelectorOnMainThread
:@selector(_eventDidDisconnect
:)
783 withObject
:nil waitUntilDone
:NO
];
788 [MySocket _unlockWrite
];
793 while ( !breakLoop
);
801 struct sockaddr addr
;
802 int addrlen
= sizeof(addr
);
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
];
810 [self performSelectorOnMainThread
:@selector(_eventDidAcceptSocket
:)
811 withObject
:newSocket waitUntilDone
:NO
];
821 _MySocketPacket
*packet
= nil;
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
];
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
];
837 packet
= [_readQueue objectAtIndex
:0];
838 bytesRead
= recv( _sockfd
, [packet bytes
], [packet bytesRemaining
], 0 );
839 [packet handledBytes
:bytesRead
];
843 if ( bytesRead
> 0 ) {
844 // update total bytes read
845 _bytesRead
+= bytesRead
;
847 [self _handleReadQueue
];
850 // remove this socket
851 ChazLog( @
"MySocket disconnecting: %i", bytesRead
);
859 _MySocketPacket
*packet
= nil;
860 int bytesWritten
= 0;
863 if ( [_writeQueue count
] > 0 ) {
865 int len
= sizeof(buflen
);
867 err
= getsockopt( _sockfd
, SOL_SOCKET
, SO_SNDBUF
, &buflen
, &len
);
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
];
875 if ( bytesWritten
>= 0 ) {
876 // update total bytes read
877 _bytesWritten
+= bytesWritten
;
879 [self _handleWriteQueue
];
888 - (void)_fillReadPacketsWithUnclaimedBytes
894 total
= [_unclaimedData length
];
898 bytes
= [_unclaimedData mutableBytes
];
901 top
= [_readQueue count
];
902 for ( i
= 0; i
< top
; i
++ ) {
903 _MySocketPacket
*packet
= [_readQueue objectAtIndex
:i
];
904 int len
= MIN( total
, [packet bytesRemaining
] );
907 memcpy( [packet bytes
], bytes
, len
);
908 [packet handledBytes
:len
];
916 [_unclaimedData replaceBytesInRange
:NSMakeRange(0,[_unclaimedData length
]-total
) withBytes
:NULL length
:0];
921 - (void)_handleReadQueue
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
];
942 - (void)_handleWriteQueue
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
];
960 if ( [_writeQueue count
] == 0 ) {
961 // no more pending writes
962 FD_CLR( _sockfd
, &_mySocketGlobals.writefds
);
968 - (void)_eventDidAcceptSocket
:(MySocket
*)newSocket
970 // just report the event back to the delegate
971 if ( [_delegate respondsToSelector
:@selector(socket
:didAcceptSocket
:)] ) {
972 [_delegate socket
:self didAcceptSocket
:newSocket
];
975 // release the parameter(s)
976 // they were not released by the caller because the caller is in another thread.
980 - (void)_eventDidDisconnect
:(id)dummy
983 if ( [_delegate respondsToSelector
:@selector(socketDidDisconnect
:)] ) {
984 [_delegate socketDidDisconnect
:self];
988 - (void)_eventDidReadData
:(_MySocketPacket
*)packet
990 if ( [_delegate respondsToSelector
:@selector(socket
:didReadData
:tag
:)] ) {
991 [_delegate socket
:self didReadData
:[packet data
] tag
:[packet tag
]];
997 - (void)_eventDidWriteData
:(_MySocketPacket
*)packet
999 if ( [_delegate respondsToSelector
:@selector(socket
:didWriteDataWithTag
:)] ) {
1000 [_delegate socket
:self didWriteDataWithTag
:[packet tag
]];
1007 - (NSMutableData
*)_readBufferWithLength
:(unsigned *)len
1009 NSMutableData
*buffer
;
1010 unsigned packetLen
= *len
;
1012 if ( buffer
= _unclaimedData
) {
1014 int unclaimedLen
= [_unclaimedData length
];
1015 if ( unclaimedLen
> packetLen
) {
1017 _unclaimedData
= [[NSMutableData alloc
] initWithBytes
:[buffer bytes
]+packetLen length
:unclaimedLen
-packetLen
];
1018 //[[buffer subdataWithRange:NSMakeRange(packetLen,unclaimedLen-packetLen)] retain];
1021 *len
= unclaimedLen
;
1022 _unclaimedData
= nil;
1024 [buffer setLength
:packetLen
];
1027 buffer
= [[NSMutableData alloc
] initWithLength
:packetLen
];
1030 return [buffer autorelease
];
1043 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1044 #pragma mark _MySocketPacket
1045 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1047 @implementation _MySocketPacket
1050 - (id)initWithData
:(NSData
*)data tag
:(int)tag
1052 if ( self = [super init
] ) {
1053 _buffer
= [data retain
];
1054 _bytesRequired
= [data length
];
1069 return (void *)[_buffer bytes
] + _bytesHandled
;
1072 - (unsigned)bytesRemaining
1074 return _bytesRequired
- _bytesHandled
;
1078 - (void)handledBytes
:(unsigned)count
1080 _bytesHandled
+= count
;
1083 - (unsigned)bytesRequired
1085 return _bytesRequired
;
1101 return [self bytesRemaining
] == 0;