Various bug fixes with the THttpClient

Summary: All kinds of buffer madness, what a pain.

Reviewed By: http


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665024 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/transport/THttpClient.cpp b/lib/cpp/src/transport/THttpClient.cpp
index 3e611ff..b389694 100644
--- a/lib/cpp/src/transport/THttpClient.cpp
+++ b/lib/cpp/src/transport/THttpClient.cpp
@@ -48,6 +48,7 @@
   if (httpBuf_ == NULL) {
     throw TTransportException("Out of memory.");
   }
+  httpBuf_[httpBufPos_] = '\0';
 }
 
 THttpClient::~THttpClient() {
@@ -79,7 +80,7 @@
     return readChunked();
   } else {
     char* read;
-    read = readContent((char*)httpBuf_, contentLength_);
+    read = readContent(httpBuf_, contentLength_);
     shift(read);
     return contentLength_;
   }
@@ -87,10 +88,9 @@
 
 uint32_t THttpClient::readChunked() {
   uint32_t length = 0;
-  char* nextLine = (char*)httpBuf_;
+  char* nextLine = httpBuf_;
   while (true) {
-    char* line = nextLine;
-    nextLine = readLine(nextLine);
+    char* line = readLine(nextLine, &nextLine);
     uint32_t chunkSize = parseChunkSize(line);
     if (chunkSize == 0) {
       break;
@@ -100,13 +100,12 @@
     length += chunkSize;
 
     // Read trailing CRLF after content
-    nextLine = readLine(nextLine);
+    readLine(nextLine, &nextLine);
   }
 
   // Read footer lines until a blank one appears
   while (true) {
-    char* line = nextLine;
-    nextLine = readLine(nextLine);
+    char* line = readLine(nextLine, &nextLine);
     if (strlen(line) == 0) {
       break;
     }
@@ -123,9 +122,8 @@
   if (semi != NULL) {
     *semi = '\0';
   }
-  int s;
-  int size;
-  s = sscanf(line, "%x", &size);
+  int size = 0;
+  sscanf(line, "%x", &size);
   return (uint32_t)size;
 }
 
@@ -135,7 +133,12 @@
   while (need > 0) {
     uint32_t avail = httpBufPos_ - (pos - httpBuf_);
     if (avail == 0) {
-      refill();
+      // We have given all the data, reset position to head of the buffer
+      pos = shift(pos);
+      pos = refill();
+      
+      // Now have available however much we read
+      avail = httpBufPos_;
     }
     uint32_t give = avail;
     if (need < give) {
@@ -147,8 +150,8 @@
   }
   return pos;
 }
-
-char* THttpClient::readLine(char* pos) {
+  
+char* THttpClient::readLine(char* pos, char** next) {
   while (true) {
     char* eol = NULL;
 
@@ -159,14 +162,14 @@
 
     // No CRLF yet?
     if (eol == NULL) {
-      // Shift whatever we have now to front
+      // Shift whatever we have now to front and refill
       pos = shift(pos);
-      // Refill the buffer
-      refill();
+      pos = refill();
     } else {
       // Return pointer to next line
       *eol = '\0';
-      return eol + CRLF_LEN;
+      *next = eol + CRLF_LEN;
+      return pos;
     }
   }
 
@@ -185,11 +188,11 @@
   return httpBuf_;
 }
 
-void THttpClient::refill() {
+char* THttpClient::refill() {
   uint32_t avail = httpBufSize_ - httpBufPos_;
   if (avail <= (httpBufSize_ / 4)) {
     httpBufSize_ *= 2;
-    httpBuf_ = (char*)realloc(httpBuf_, httpBufSize_);
+    httpBuf_ = (char*)realloc(httpBuf_, httpBufSize_+1);
     if (httpBuf_ == NULL) {
       throw TTransportException("Out of memory.");
     }
@@ -199,10 +202,12 @@
   uint32_t got = transport_->read((uint8_t*)(httpBuf_+httpBufPos_), httpBufSize_-httpBufPos_);
   httpBufPos_ += got;
   httpBuf_[httpBufPos_] = '\0';
-      
+ 
   if (got == 0) {
-    throw TTransportException("Could not finish reading HTTP headers");
+    throw TTransportException("Could not refill buffer");
   }
+
+  return httpBuf_;
 }
 
 void THttpClient::readHeaders() {
@@ -220,8 +225,7 @@
 
   // Loop until headers are finished
   while (true) {
-    char* line = nextLine;
-    nextLine = readLine(nextLine);
+    char* line = readLine(nextLine, &nextLine);
 
     if (strlen(line) == 0) {
       if (finished) {