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;
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);
}
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)) {
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) {
#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
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;
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
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);
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);