Use native file functions on Windows
authorPatrick Gansterer <paroga@paroga.com>
Thu, 27 Feb 2014 02:21:50 +0000 (03:21 +0100)
committerAndy Green <andy.green@linaro.org>
Thu, 27 Feb 2014 13:20:36 +0000 (21:20 +0800)
Add a special implementation with CreateFile(), ReadFile() and CloseFile()
for serving HTTP file request to allow compilation on all Windows platforms.

lib/handshake.c
lib/libwebsockets.c
lib/output.c
lib/private-libwebsockets.h
lib/server.c

index 4be448a..720ee68 100644 (file)
@@ -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;
index 458a547..7f9d20e 100644 (file)
@@ -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);
                }
index 173cda4..8188ec2 100644 (file)
@@ -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) {
index f9df4a6..3332106 100644 (file)
@@ -81,6 +81,7 @@
 #include <winsock2.h>
 #include <ws2ipdef.h>
 #include <windows.h>
+#define LWS_INVALID_FILE INVALID_HANDLE_VALUE
 #else
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/mman.h>
 #include <sys/time.h>
 
+#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;
 
index 4547a34..11632c1 100644 (file)
@@ -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);