瀏覽代碼

Partial fix for a bug in axtls on the implementation of SSL_read .

mingodad 12 年之前
父節點
當前提交
24a0496635
共有 2 個文件被更改,包括 80 次插入67 次删除
  1. 78 66
      SquiLu-ext/mongoose.c
  2. 2 1
      SquiLu-ext/sq_mongoose.cpp

+ 78 - 66
SquiLu-ext/mongoose.c

@@ -1667,72 +1667,84 @@ static int wait_until_socket_is_readable(struct mg_connection *conn) {
   return conn->ctx->stop_flag || result < 0 ? 0 : 1;
 }
 
-// Read from IO channel - opened file descriptor, socket, or SSL descriptor.
-// Return negative value on error, or number of bytes read on success.
-static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len) {
-  int nread;
-
-  if (fp != NULL) {
-    // Use read() instead of fread(), because if we're reading from the CGI
-    // pipe, fread() may block until IO buffer is filled up. We cannot afford
-    // to block and must pass all read bytes immediately to the client.
-    nread = read(fileno(fp), buf, (size_t) len);
-  } else if (!wait_until_socket_is_readable(conn)) {
-    nread = -1;
-  } else if (conn->ssl != NULL) {
-    nread = SSL_read(conn->ssl, buf, len);
-  } else {
-    nread = recv(conn->client.sock, buf, (size_t) len, 0);
-  }
-
-  return conn->ctx->stop_flag ? -1 : nread;
-}
-
-int mg_read(struct mg_connection *conn, void *buf, size_t len) {
-  int n, buffered_len, nread;
-
-  assert(conn->next_request != NULL &&
-         conn->body != NULL &&
-         conn->next_request >= conn->body);
-  nread = 0;
-  if (conn->consumed_content < conn->content_len) {
-    // Adjust number of bytes to read.
-    int64_t to_read = conn->content_len - conn->consumed_content;
-    if (to_read < (int64_t) len) {
-      len = (size_t) to_read;
-    }
-
-    // Return buffered data
-    buffered_len = conn->next_request - conn->body;
-    if (buffered_len > 0) {
-      if (len < (size_t) buffered_len) {
-        buffered_len = (int) len;
-      }
-      memcpy(buf, conn->body, (size_t) buffered_len);
-      len -= buffered_len;
-      conn->body += buffered_len;
-      conn->consumed_content += buffered_len;
-      nread += buffered_len;
-      buf = (char *) buf + buffered_len;
-    }
-
-    // We have returned all buffered data. Read new data from the remote socket.
-    while (len > 0) {
-      n = pull(NULL, conn, (char *) buf, (int) len);
-      if (n < 0) {
-        nread = n;  // Propagate the error
-        break;
-      } else if (n == 0) {
-        break;  // No more data to read
-      } else {
-        buf = (char *) buf + n;
-        conn->consumed_content += n;
-        nread += n;
-        len -= n;
-      }
-    }
-  }
-  return nread;
+// Read from IO channel - opened file descriptor, socket, or SSL descriptor.
+// Return negative value on error, or number of bytes read on success.
+static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len) {
+  int nread;
+
+  if (fp != NULL) {
+    // Use read() instead of fread(), because if we're reading from the CGI
+    // pipe, fread() may block until IO buffer is filled up. We cannot afford
+    // to block and must pass all read bytes immediately to the client.
+    nread = read(fileno(fp), buf, (size_t) len);
+#ifndef NO_SSL
+  } else if (conn->ssl != NULL) {
+    nread = SSL_read(conn->ssl, buf, len);
+#endif
+  } else {
+    nread = recv(conn->client.sock, buf, (size_t) len, 0);
+  }
+
+  return conn->ctx->stop_flag ? -1 : nread;
+}
+
+static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len) {
+  int n, nread = 0;
+
+  while (len > 0 && conn->ctx->stop_flag == 0) {
+    n = pull(fp, conn, buf + nread, len);
+    if (n < 0) {
+      nread = n;  // Propagate the error
+      break;
+    } else if (n == 0) {
+      break;  // No more data to read
+    } else {
+      conn->consumed_content += n;
+      nread += n;
+      len -= n;
+    }
+  }
+
+  return nread;
+}
+
+int mg_read(struct mg_connection *conn, void *buf, size_t len) {
+  int n, buffered_len, nread;
+  const char *body;
+
+  // If Content-Length is not set, read until socket is closed
+  if (conn->consumed_content == 0 && conn->content_len == 0) {
+    conn->content_len = INT64_MAX;
+    conn->must_close = 1;
+  }
+
+  nread = 0;
+  if (conn->consumed_content < conn->content_len) {
+    // Adjust number of bytes to read.
+    int64_t to_read = conn->content_len - conn->consumed_content;
+    if (to_read < (int64_t) len) {
+      len = (size_t) to_read;
+    }
+
+    // Return buffered data
+    body = conn->buf + conn->request_len + conn->consumed_content;
+    buffered_len = &conn->buf[conn->data_len] - body;
+    if (buffered_len > 0) {
+      if (len < (size_t) buffered_len) {
+        buffered_len = (int) len;
+      }
+      memcpy(buf, body, (size_t) buffered_len);
+      len -= buffered_len;
+      conn->consumed_content += buffered_len;
+      nread += buffered_len;
+      buf = (char *) buf + buffered_len;
+    }
+
+    // We have returned all buffered data. Read new data from the remote socket.
+    n = pull_all(NULL, conn, (char *) buf, (int) len);
+    nread = n >= 0 ? nread + n : n;
+  }
+  return nread;
 }
 
 int mg_write(struct mg_connection *conn, const void *buf, size_t len) {

+ 2 - 1
SquiLu-ext/sq_mongoose.cpp

@@ -156,7 +156,8 @@ sq_http_request_read(HSQUIRRELVM v)
     SQBlob blob(0, rlen);
     if (rlen > n) rlen = n;  /* cannot read more than asked */
     char *p = sq_getscratchpad(v,rlen);
-    do {
+    do {
+        //there is a bug in axtls that can return a number bigger than the actual bytes transfered
         nr = mg_read(conn, p, rlen);
         blob.Write(p, nr);
         n -= nr;  /* still have to read `n' chars */