title: Trying to upload file using CFHTTPMessage
body: <p>I am facing an issue with uploading of file using HTTP file upload. The protocol followed as per the client-server understanding is that, the http request headers for 
  upload txn should go first followed by a stream which should contain the data of the request XML followed by the data of the file buffer.</p>
  
  <p>Now, the request headers are reaching and server after reading the headers starts reading the stream. It gets the request XML from the stream as well.</p>
  
  <p>After this, server reads the file data from the stream. After the file upload shows done, I try to download the same file. In the server, I see the file is there and it shows correct size too.</p>
  
  <p>After I download the file, I find the file is cropped in the end (in case of a jpg file) or some end text is missing (in case of txt file).</p>
  
  <p>According to my project's logic, data is transferred in 8KB chunks. I have verified that the last chunk which is lesser than 8KB is the missing data causing the cropping
  of images. I have also verified that the last chunk has valid data in the buffer formed by the fileHandler API. I am sending a few code snippets which i have used for the write logic.</p>
  
  <p>Can you identify any particular reason for the last chunk not getting streamed or some junk data getting streamed in place of the last chunk?</p>
  
  <p>Code snippet for creating the writestream:</p>
  
  <pre><code>const UInt8 *uploadBuf;
  uploadBuf = (const UInt8*)malloc(totLen);
  
  CFReadStreamRef readStreamForBody = CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault, uploadBuf, (CFIndex)totLen, kCFAllocatorNull);
  CFReadStreamRef readStreamForUpload = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, messageRef, readStreamForBody);
  
  if (CFReadStreamOpen(readStreamForUpload) == TRUE)
  {   
      CFWriteStreamRef writeStream = CFWriteStreamCreateWithBuffer(kCFAllocatorDefault, (UInt8*)uploadBuf, (CFIndex)totLen);
      if (CFWriteStreamOpen(writeStream) == FALSE)
      {
          CFErrorRef streamError = CFWriteStreamCopyError(writeStream);
          CFStringRef streamErrorString = CFErrorCopyDescription(streamError);
          CFShow(streamErrorString);
          CFRelease(streamError);
          CFRelease(streamErrorString);
  
          CFWriteStreamClose(writeStream);
          CFRelease(writeStream);
          writeStream = NULL;
      }
      else 
      {
          Boolean hasBytes = FALSE;
          CFStreamStatus  streamStatus = CFWriteStreamGetStatus(writeStream);
          do
          {
              while ((hasBytes == FALSE) &amp;&amp;
                  ((streamStatus != kCFStreamStatusNotOpen) &amp;&amp;
                  (streamStatus != kCFStreamStatusAtEnd) &amp;&amp;
                  (streamStatus != kCFStreamStatusClosed) &amp;&amp;
                  (streamStatus != kCFStreamStatusError)))
              {
                  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false);
                  hasBytes = CFWriteStreamCanAcceptBytes(writeStream);
                  streamStatus = CFWriteStreamGetStatus(writeStream);
              }
          } while (hasBytes != TRUE);
  </code></pre>
  
  <p>Code snippet for saving the writestream:</p>
  
  <pre><code>[self setWriteStreamForFile:writeStream];
  [[MyHTTPLastRequestList lastRequestList] setObject:self forKey:[self sessionKey]];
  </code></pre>
  
  <p>Code snippet for writing the buffer to the writestream:</p>
  
  <pre><code>- (void) write:(const void*)fileBuffer numBytes:(NSUInteger)fileBufSize
  {
      MyThreadSafeDictionary *lastRequestList = [MyHTTPLastRequestList lastRequestList];
      NSString *sessionKey = [self sessionKey];
  
      BOOL noResponse = YES;
      while (noResponse)
          noResponse = ([lastRequestList objectForKey:sessionKey] == nil);
  
      MyHTTPMessage *httpFileUploadMsg = (MyHTTPMessage*)[lastRequestList objectForKey:sessionKey];   
      CFIndex totalLen = [httpFileUploadMsg totalLength];
      CFIndex sentLen = [httpFileUploadMsg sentLength];
  
      NSData *chunkData = [[[NSData dataWithBytes:fileBuffer length:fileBufSize] retain] autorelease];
      sentLen += (CFIndex)fileBufSize;
      CFIndex bytesRemaining = totalLen - sentLen;
      CFIndex bytesWritten = 0;
  
      CFWriteStreamRef writeStream = [httpFileUploadMsg writeStreamForFile];
      if (bytesRemaining &gt; 0)
      {
          CFWriteStreamRef writeStream = [httpFileUploadMsg writeStreamForFile];
          bytesWritten = CFWriteStreamWrite(writeStream, (const UInt8*)[chunkData bytes], (CFIndex)fileBufSize);
  
          [httpFileUploadMsg setSentLength:sentLen];
  
          NSLog(@"Bytes written to stream = %d",(NSInteger)sentLen);
          [httpFileUploadMsg setWriteStreamForFile:writeStream];
      }
      else  
      {       
          @try 
          {
              bytesWritten = CFWriteStreamWrite(writeStream, (const UInt8*)[chunkData bytes], (CFIndex)fileBufSize);
  
              if (bytesWritten == 0)
              {
                  NSLog(@"ERROR :: Stream Filled to capacity");
              }
              else if (bytesWritten &lt; 0)
              {
                  NSLog(@"ERROR :: Write failed.");
                  CFErrorRef streamError = CFWriteStreamCopyError(writeStream);
                  CFStringRef streamErrorString = CFErrorCopyDescription(streamError);
                  CFShow(streamErrorString);
                  CFRelease(streamError);
                  CFRelease(streamErrorString);
              }
              else 
              {
                  NSLog(@"Write Success");            
              }
          }
          @catch (NSException* localException) 
          {
              NSLog(@"Exception raised - %@",[localException name]);
              [localException raise];
          }
  
          NSLog(@"Sending to the server");
          CFReadStreamRef readStreamForUpload = [httpFileUploadMsg readStreamForHTTPResponse];
          CFStreamStatus  rStreamStatus = CFReadStreamGetStatus(readStreamForUpload);
          Boolean parentStreamHasBytes = FALSE;
          do
          {
              while ((parentStreamHasBytes == FALSE) &amp;&amp;
                  ((rStreamStatus != kCFStreamStatusNotOpen) &amp;&amp;
                  (rStreamStatus != kCFStreamStatusAtEnd) &amp;&amp;
                  (rStreamStatus != kCFStreamStatusClosed) &amp;&amp;
                  (rStreamStatus != kCFStreamStatusError)))
              {
                  CFRunLoopRunInMode (kCFRunLoopDefaultMode, 0, false);
                  parentStreamHasBytes = CFReadStreamHasBytesAvailable(readStreamForUpload);
                  rStreamStatus = CFReadStreamGetStatus(readStreamForUpload);
              }
          } while (parentStreamHasBytes != TRUE);
  </code></pre>