diff --git a/lib/handshake.c b/lib/handshake.c index 4be448ab..720ee685 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -219,7 +219,7 @@ http_postbody: memset(&wsi->u, 0, sizeof(wsi->u)); wsi->mode = LWS_CONNMODE_HTTP_SERVING_ACCEPTED; wsi->state = WSI_STATE_HTTP; - wsi->u.http.fd = -1; + wsi->u.http.fd = LWS_INVALID_FILE; /* expose it at the same offset as u.hdr */ wsi->u.http.ah = ah; diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 458a5479..7f9d20eb 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -286,10 +286,14 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context, free(wsi->u.http.post_buffer); wsi->u.http.post_buffer = NULL; } - if (wsi->u.http.fd >= 0) { - lwsl_debug("closing http fd %d\n", wsi->u.http.fd); + if (wsi->u.http.fd != LWS_INVALID_FILE) { + lwsl_debug("closing http file\n"); +#if defined(WIN32) || defined(_WIN32) + CloseHandle(wsi->u.http.fd); +#else close(wsi->u.http.fd); - wsi->u.http.fd = -1; +#endif + wsi->u.http.fd = LWS_INVALID_FILE; context->protocols[0].callback(context, wsi, LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0); } diff --git a/lib/output.c b/lib/output.c index 173cda49..8188ec25 100644 --- a/lib/output.c +++ b/lib/output.c @@ -629,7 +629,12 @@ send_raw: LWS_VISIBLE int libwebsockets_serve_http_file_fragment( struct libwebsocket_context *context, struct libwebsocket *wsi) { - int n, m; +#if defined(WIN32) || defined(_WIN32) + DWORD n; +#else + int n; +#endif + int m; while (!lws_send_pipe_choked(wsi)) { @@ -643,22 +648,33 @@ LWS_VISIBLE int libwebsockets_serve_http_file_fragment( if (wsi->u.http.filepos == wsi->u.http.filelen) goto all_sent; +#if defined(WIN32) || defined(_WIN32) + if (!ReadFile(wsi->u.http.fd, context->service_buffer, + sizeof(context->service_buffer), &n, NULL)) + return -1; /* caller will close */ +#else n = read(wsi->u.http.fd, context->service_buffer, sizeof(context->service_buffer)); - if (n > 0) { + + if (n < 0) + return -1; /* caller will close */ +#endif + if (n) { m = libwebsocket_write(wsi, context->service_buffer, n, LWS_WRITE_HTTP); if (m < 0) return -1; wsi->u.http.filepos += m; - if (m != n) + if (m != n) { /* adjust for what was not sent */ +#if defined(WIN32) || defined(_WIN32) + SetFilePointer(wsi->u.http.fd, m - n, NULL, FILE_CURRENT); +#else lseek(wsi->u.http.fd, m - n, SEEK_CUR); +#endif + } } - - if (n < 0) - return -1; /* caller will close */ all_sent: if (!wsi->truncated_send_malloc && wsi->u.http.filepos == wsi->u.http.filelen) { diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index f9df4a64..33321065 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -81,6 +81,7 @@ #include #include #include +#define LWS_INVALID_FILE INVALID_HANDLE_VALUE #else #include #include @@ -99,6 +100,7 @@ #include #include +#define LWS_INVALID_FILE -1 #define compatible_close(fd) close(fd); #endif @@ -344,7 +346,11 @@ struct allocated_headers { struct _lws_http_mode_related { struct allocated_headers *ah; /* mirroring _lws_header_related */ +#if defined(WIN32) || defined(_WIN32) + HANDLE fd; +#else int fd; +#endif unsigned long filepos; unsigned long filelen; diff --git a/lib/server.c b/lib/server.c index 4547a34e..11632c13 100644 --- a/lib/server.c +++ b/lib/server.c @@ -485,6 +485,31 @@ LWS_VISIBLE int libwebsockets_return_http_status( return m; } +#if defined(WIN32) || defined(_WIN32) +static inline HANDLE lws_open_file(const char* filename, unsigned long* filelen) +{ + HANDLE ret = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (ret != LWS_INVALID_FILE) + *filelen = GetFileSize(ret, NULL); + + return ret; +} +#else +static inline int lws_open_file(const char* filename, unsigned long* filelen) +{ + struct stat stat_buf; + int ret = open(filename, O_RDONLY); + + if (ret < 0) + return LWS_INVALID_FILE; + + fstat(ret, &stat_buf); + *filelen = stat_buf.st_size; + return ret; +} +#endif + /** * libwebsockets_serve_http_file() - Send a file back to the client using http * @context: libwebsockets context @@ -508,27 +533,19 @@ LWS_VISIBLE int libwebsockets_serve_http_file( struct libwebsocket *wsi, const char *file, const char *content_type, const char *other_headers) { - struct stat stat_buf; unsigned char *p = context->service_buffer; int ret = 0; int n; - wsi->u.http.fd = open(file, O_RDONLY -#ifdef WIN32 - | _O_BINARY -#endif - ); + wsi->u.http.fd = lws_open_file(file, &wsi->u.http.filelen); - if (wsi->u.http.fd < 1) { + if (wsi->u.http.fd == LWS_INVALID_FILE) { lwsl_err("Unable to open '%s'\n", file); libwebsockets_return_http_status(context, wsi, HTTP_STATUS_NOT_FOUND, NULL); - wsi->u.http.fd = -1; return -1; } - fstat(wsi->u.http.fd, &stat_buf); - wsi->u.http.filelen = stat_buf.st_size; p += sprintf((char *)p, "HTTP/1.0 200 OK\x0d\x0aServer: libwebsockets\x0d\x0a""Content-Type: %s\x0d\x0a", content_type); @@ -538,8 +555,7 @@ LWS_VISIBLE int libwebsockets_serve_http_file( p += n; } p += sprintf((char *)p, - "Content-Length: %u\x0d\x0a\x0d\x0a", - (unsigned int)stat_buf.st_size); + "Content-Length: %lu\x0d\x0a\x0d\x0a", wsi->u.http.filelen); ret = libwebsocket_write(wsi, context->service_buffer, p - context->service_buffer, LWS_WRITE_HTTP);