jens@0: // jens@0: // TCPWriter.m jens@0: // MYNetwork jens@0: // jens@0: // Created by Jens Alfke on 5/10/08. jens@0: // Copyright 2008 Jens Alfke. All rights reserved. jens@0: // jens@0: jens@0: #import "TCPWriter.h" jens@0: #import "TCP_Internal.h" jens@0: jens@0: jens@0: @implementation TCPWriter jens@0: jens@0: jens@0: - (void) dealloc jens@0: { jens@0: [_queue release]; jens@0: [_currentData release]; jens@0: [super dealloc]; jens@0: } jens@0: jens@0: jens@0: - (TCPReader*) reader jens@0: { jens@0: return _conn.reader; jens@0: } jens@0: jens@0: jens@0: - (id) propertyForKey: (CFStringRef)cfStreamProperty jens@0: { jens@0: CFTypeRef value = CFWriteStreamCopyProperty((CFWriteStreamRef)_stream,cfStreamProperty); jens@0: return [(id)CFMakeCollectable(value) autorelease]; jens@0: } jens@0: jens@0: - (void) setProperty: (id)value forKey: (CFStringRef)cfStreamProperty jens@0: { jens@0: if( ! CFWriteStreamSetProperty((CFWriteStreamRef)_stream,cfStreamProperty,(CFTypeRef)value) ) jens@0: Warn(@"%@ didn't accept property '%@'", self,cfStreamProperty); jens@0: } jens@0: jens@0: jens@0: - (BOOL) isBusy jens@0: { jens@0: return _currentData || _queue.count > 0; jens@0: } jens@0: jens@0: jens@0: - (void) writeData: (NSData*)data jens@0: { jens@0: if( !_queue ) jens@0: _queue = [[NSMutableArray alloc] init]; jens@0: [_queue addObject: data]; jens@0: if( _queue.count==1 && ((NSOutputStream*)_stream).hasSpaceAvailable ) jens@0: [self _canWrite]; jens@0: } jens@0: jens@0: jens@0: - (void) _canWrite jens@0: { jens@0: if( ! _currentData ) { jens@0: if( _queue.count==0 ) { jens@0: [self queueIsEmpty]; // this may call -writeData, which will call _canWrite again jens@0: return; jens@0: } jens@0: _currentData = [[_queue objectAtIndex: 0] retain]; jens@0: _currentDataPos = 0; jens@0: [_queue removeObjectAtIndex: 0]; jens@0: } jens@0: jens@0: const uint8_t* src = _currentData.bytes; jens@0: src += _currentDataPos; jens@0: NSInteger len = _currentData.length - _currentDataPos; jens@0: NSInteger written = [(NSOutputStream*)_stream write: src maxLength: len]; jens@0: if( written < 0 ) jens@0: [self _gotError]; jens@0: else if( written < len ) { jens@0: LogTo(TCPVerbose,@"%@ wrote %i bytes (of %u)", self,written,len); jens@0: _currentDataPos += written; jens@0: } else { jens@0: LogTo(TCPVerbose,@"%@ wrote %i bytes", self,written); jens@0: setObj(&_currentData,nil); jens@0: } jens@0: } jens@0: jens@0: jens@0: - (void) queueIsEmpty jens@0: { jens@0: } jens@0: jens@0: jens@0: @end jens@0: jens@0: jens@0: /* jens@0: Copyright (c) 2008, Jens Alfke . All rights reserved. jens@0: jens@0: Redistribution and use in source and binary forms, with or without modification, are permitted jens@0: provided that the following conditions are met: jens@0: jens@0: * Redistributions of source code must retain the above copyright notice, this list of conditions jens@0: and the following disclaimer. jens@0: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions jens@0: and the following disclaimer in the documentation and/or other materials provided with the jens@0: distribution. jens@0: jens@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR jens@0: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND jens@0: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI- jens@0: BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES jens@0: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR jens@0: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN jens@0: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF jens@0: THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. jens@0: */