|
@@ -897,7 +897,7 @@ struct mg_connection {
|
|
|
int64_t num_bytes_sent; /* Total bytes sent to client */
|
|
|
int64_t content_len; /* Content-Length header value */
|
|
|
int64_t consumed_content; /* How many bytes of content have been read */
|
|
|
- int is_chunked; /* Transfer-encoding is chunked */
|
|
|
+ int is_chunked; /* Transfer-encoding is chunked: 0=no, 1=yes: data available, 2: all data read */
|
|
|
size_t chunk_remainder; /* Unread data from the last chunk */
|
|
|
char *buf; /* Buffer for received data */
|
|
|
char *path_info; /* PATH_INFO part of the URL */
|
|
@@ -2587,24 +2587,42 @@ static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
|
|
|
return nread;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
static void discard_unread_request_data(struct mg_connection *conn)
|
|
|
{
|
|
|
char buf[MG_BUF_LEN];
|
|
|
int to_read, nread;
|
|
|
|
|
|
- while (conn->consumed_content < conn->content_len) {
|
|
|
- to_read = sizeof(buf);
|
|
|
- if ((int64_t) to_read > conn->content_len - conn->consumed_content) {
|
|
|
- to_read = (int) (conn->content_len - conn->consumed_content);
|
|
|
+ to_read = sizeof(buf);
|
|
|
+
|
|
|
+ if (conn->is_chunked) {
|
|
|
+
|
|
|
+ /* Chunked encoding: 1=chunk not read completely, 2=chunk read completely */
|
|
|
+ while (conn->is_chunked == 1) {
|
|
|
+ nread = mg_read(conn, buf, to_read);
|
|
|
+ if (nread <= 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- nread = mg_read(conn, buf, to_read);
|
|
|
- if (nread <= 0) {
|
|
|
- break;
|
|
|
+ } else {
|
|
|
+
|
|
|
+ /* Not chunked: content length is known */
|
|
|
+ while (conn->consumed_content < conn->content_len) {
|
|
|
+
|
|
|
+ if ((int64_t) to_read > (conn->content_len - conn->consumed_content)) {
|
|
|
+ to_read = (int) (conn->content_len - conn->consumed_content);
|
|
|
+ }
|
|
|
+
|
|
|
+ nread = mg_read(conn, buf, to_read);
|
|
|
+ if (nread <= 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
int mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
|
|
|
{
|
|
|
int64_t n, buffered_len, nread;
|
|
@@ -2650,6 +2668,7 @@ int mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
|
|
|
return (int)nread;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
static char mg_getc(struct mg_connection *conn)
|
|
|
{
|
|
|
char c;
|
|
@@ -2661,8 +2680,11 @@ static char mg_getc(struct mg_connection *conn)
|
|
|
return c;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
int mg_read(struct mg_connection *conn, void *buf, size_t len)
|
|
|
{
|
|
|
+ if (len>INT_MAX) len=INT_MAX;
|
|
|
+
|
|
|
if (conn->is_chunked)
|
|
|
{
|
|
|
size_t all_read = 0;
|
|
@@ -2670,8 +2692,8 @@ int mg_read(struct mg_connection *conn, void *buf, size_t len)
|
|
|
|
|
|
if (conn->chunk_remainder) {
|
|
|
/* copy from the remainder of the last received chunk */
|
|
|
- int read_ret;
|
|
|
- int read_now = ((conn->chunk_remainder>len) ? (len) : (conn->chunk_remainder));
|
|
|
+ long read_ret;
|
|
|
+ int read_now = (int)((conn->chunk_remainder>len) ? (len) : (conn->chunk_remainder));
|
|
|
|
|
|
conn->content_len += read_now;
|
|
|
read_ret = mg_read_inner(conn, (char*)buf+all_read, read_now);
|
|
@@ -2716,57 +2738,13 @@ int mg_read(struct mg_connection *conn, void *buf, size_t len)
|
|
|
conn->chunk_remainder = chunkSize;
|
|
|
if (chunkSize == 0) {
|
|
|
/* regular end of content */
|
|
|
+ conn->is_chunked = 2;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return all_read;
|
|
|
-
|
|
|
- /* TODO: chunked transfer encoding (#95) is currently not working. See #98. */
|
|
|
- /*
|
|
|
- if (conn->content_len <= 0)
|
|
|
- {
|
|
|
- conn->content_len = 0;
|
|
|
- }
|
|
|
- if (conn->consumed_content < conn->content_len)
|
|
|
- {
|
|
|
- return mg_read_inner(conn, buf,len);
|
|
|
- }
|
|
|
-
|
|
|
- while (1)
|
|
|
- {
|
|
|
- int c = mg_getc(conn);
|
|
|
- if (!(c == '\n' || c == '\r'))
|
|
|
- {
|
|
|
- buf[i++] = c;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- for (; i < (int)sizeof(buf); i++)
|
|
|
- {
|
|
|
- int c = mg_getc(conn);
|
|
|
- if ( c == EOF )
|
|
|
- {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- buf[i] = (char) c;
|
|
|
- if (buf[i] == '\n' && buf[i-1] == '\r')
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (end != buf+(i-1))
|
|
|
- {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if (chunkSize == 0)
|
|
|
- {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- conn->content_len += chunkSize;
|
|
|
- */
|
|
|
+ return (int)all_read;
|
|
|
}
|
|
|
return mg_read_inner(conn,buf,len);
|
|
|
}
|
|
@@ -6560,7 +6538,7 @@ static int get_request_handler(struct mg_connection *conn,
|
|
|
return 0; /* none found */
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+#if defined(USE_WEBSOCKET)
|
|
|
static int deprecated_websocket_connect_wrapper(const struct mg_connection * conn, void *cbdata)
|
|
|
{
|
|
|
struct mg_callbacks *pcallbacks = (struct mg_callbacks*)cbdata;
|
|
@@ -6588,6 +6566,7 @@ static int deprecated_websocket_data_wrapper(const struct mg_connection * conn,
|
|
|
/* No handler set - assume "OK" */
|
|
|
return 1;
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
/* This is the heart of the Civetweb's logic.
|
|
|
This function is called when the request is read, parsed and validated,
|
|
@@ -8338,6 +8317,7 @@ static void get_system_name(char **sysName)
|
|
|
dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
|
|
|
dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
|
|
|
dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0);
|
|
|
+ (void)dwBuild;
|
|
|
|
|
|
sprintf(name, "Windows %u.%u", (unsigned)dwMajorVersion, (unsigned)dwMinorVersion);
|
|
|
*sysName = mg_strdup(name);
|
|
@@ -8365,7 +8345,9 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
|
|
|
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
|
|
WSADATA data;
|
|
|
WSAStartup(MAKEWORD(2,2), &data);
|
|
|
+#ifdef _MSC_VER
|
|
|
#pragma warning(suppress: 28125)
|
|
|
+#endif
|
|
|
if (!sTlsInit) InitializeCriticalSection(&global_log_file_lock);
|
|
|
#endif /* _WIN32 && !__SYMBIAN32__ */
|
|
|
|