abyss_bool ConnWriteFromFile(TConn * const connectionP, TFile * const fileP, uint64_t const start, uint64_t const last, void * const buffer, uint32_t const buffersize, uint32_t const rate) { /*---------------------------------------------------------------------------- Write the contents of the file stream *fileP, from offset 'start' up through 'last', to the HTTP connection *connectionP. Meter the reading so as not to read more than 'rate' bytes per second. Use the 'bufferSize' bytes at 'buffer' as an internal buffer for this. -----------------------------------------------------------------------------*/ abyss_bool retval; uint32_t waittime; abyss_bool success; uint32_t readChunkSize; if (rate > 0) { readChunkSize = MIN(buffersize, rate); /* One second's worth */ waittime = (1000 * buffersize) / rate; } else { readChunkSize = buffersize; waittime = 0; } success = FileSeek(fileP, start, SEEK_SET); if (!success) retval = FALSE; else { uint64_t const totalBytesToRead = last - start + 1; uint64_t bytesread; bytesread = 0; /* initial value */ while (bytesread < totalBytesToRead) { uint64_t const bytesLeft = totalBytesToRead - bytesread; uint64_t const bytesToRead = MIN(readChunkSize, bytesLeft); uint64_t bytesReadThisTime; bytesReadThisTime = FileRead(fileP, buffer, bytesToRead); bytesread += bytesReadThisTime; if (bytesReadThisTime > 0) ConnWrite(connectionP, buffer, bytesReadThisTime); else break; if (waittime > 0) xmlrpc_millisecond_sleep(waittime); } retval = (bytesread >= totalBytesToRead); } return retval; }
bool ConnWriteFromFile(TConn * const connectionP, const TFile * const fileP, uint64_t const start, uint64_t const last, void * const buffer, uint32_t const buffersize, uint32_t const rate) { /*---------------------------------------------------------------------------- Write the contents of the file stream *fileP, from offset 'start' up through 'last', to the HTTP connection *connectionP. Meter the reading so as not to read more than 'rate' bytes per second. Use the 'bufferSize' bytes at 'buffer' as an internal buffer for this. -----------------------------------------------------------------------------*/ bool retval; uint32_t waittime; bool success; uint32_t readChunkSize; uint32_t ChunkSize = 4096 * 2; /* read buffer size */ if (rate > 0) { readChunkSize = MIN(buffersize, rate); /* One second's worth */ waittime = (1000 * buffersize) / rate; } else { readChunkSize = ChunkSize; waittime = 0; } success = FileSeek(fileP, start, SEEK_SET); if (!success) retval = FALSE; else { uint64_t const totalBytesToRead = last - start + 1; uint64_t bytesread = 0; int32_t bytesReadThisTime = 0; char * chunk = (char *) buffer; /* the beginning */ do { if ((bytesReadThisTime = FileRead(fileP, chunk, readChunkSize)) <= 0 ) break; bytesread += bytesReadThisTime; chunk += bytesReadThisTime; /* fix bug in ms ie as it doesn't render text/plain properly */ /* if CRLFs are split between reassembled tcp packets, */ /* ie "might" undeterministically render extra empty lines */ /* if it ends in CR or LF, read an extra chunk until the buffer is full */ /* or end of file is reached. You may still have bad luck, complaints go to MS) */ /* if (bytesReadThisTime == readChunkSize && chunk - (char *) buffer + readChunkSize < buffersize) { * char * end = chunk - 1; * if (*end == CR || *end == LF) { * continue; * } * } */ if (!bytesReadThisTime || !ConnWrite(connectionP, buffer, chunk - (char *) buffer)) { break; } chunk = (char *) buffer; /* a new beginning */ if (waittime > 0) xmlrpc_millisecond_sleep(waittime); } while (bytesReadThisTime == readChunkSize); retval = (bytesread >= totalBytesToRead); } return retval; }