From c9a64ad25063c52ebaa2d35ebc8be28702681788 Mon Sep 17 00:00:00 2001 From: Patrick Gansterer Date: Wed, 26 Feb 2014 18:24:24 +0100 Subject: [PATCH] Use fread() when serving http files This change allows compilation on platforms without read(). --- lib/handshake.c | 1 - lib/libwebsockets.c | 8 ++++---- lib/output.c | 17 ++++++++++------- lib/private-libwebsockets.h | 6 +++--- lib/server.c | 19 +++++++------------ 5 files changed, 24 insertions(+), 27 deletions(-) diff --git a/lib/handshake.c b/lib/handshake.c index f45ee53cb0..091f9a1dbd 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -219,7 +219,6 @@ libwebsocket_read(struct libwebsocket_context *context, memset(&wsi->u, 0, sizeof(wsi->u)); wsi->mode = LWS_CONNMODE_HTTP_SERVING_ACCEPTED; wsi->state = WSI_STATE_HTTP; - wsi->u.http.fd = -1; /* 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 5cfcfc5024..7cdb9e3032 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -257,10 +257,10 @@ 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); - close(wsi->u.http.fd); - wsi->u.http.fd = -1; + if (wsi->u.http.fp) { + lwsl_debug("closing http fp %p\n", wsi->u.http.fp); + fclose(wsi->u.http.fp); + wsi->u.http.fp = NULL; 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 173cda4990..1584fa9ed1 100644 --- a/lib/output.c +++ b/lib/output.c @@ -629,7 +629,8 @@ LWS_VISIBLE int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, LWS_VISIBLE int libwebsockets_serve_http_file_fragment( struct libwebsocket_context *context, struct libwebsocket *wsi) { - int n, m; + size_t n; + int m; while (!lws_send_pipe_choked(wsi)) { @@ -643,9 +644,13 @@ LWS_VISIBLE int libwebsockets_serve_http_file_fragment( if (wsi->u.http.filepos == wsi->u.http.filelen) goto all_sent; - n = read(wsi->u.http.fd, context->service_buffer, - sizeof(context->service_buffer)); - if (n > 0) { + n = fread(context->service_buffer, 1, + sizeof(context->service_buffer), wsi->u.http.fp); + + if (ferror(wsi->u.http.fp)) + return -1; + + if (n) { m = libwebsocket_write(wsi, context->service_buffer, n, LWS_WRITE_HTTP); if (m < 0) @@ -654,11 +659,9 @@ LWS_VISIBLE int libwebsockets_serve_http_file_fragment( wsi->u.http.filepos += m; if (m != n) /* adjust for what was not sent */ - lseek(wsi->u.http.fd, m - n, SEEK_CUR); + fseek(wsi->u.http.fp, m - n, SEEK_CUR); } - 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 87c85f4a06..6adde95677 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -344,9 +344,9 @@ struct allocated_headers { struct _lws_http_mode_related { struct allocated_headers *ah; /* mirroring _lws_header_related */ - int fd; - unsigned long filepos; - unsigned long filelen; + FILE* fp; + long filepos; + long filelen; int content_length; int content_length_seen; diff --git a/lib/server.c b/lib/server.c index d45da33390..79ff98680e 100644 --- a/lib/server.c +++ b/lib/server.c @@ -508,27 +508,23 @@ 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.fp = fopen(file, "rb"); - if (wsi->u.http.fd < 1) { + if (!wsi->u.http.fp) { 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; + fseek(wsi->u.http.fp, 0, SEEK_END); + wsi->u.http.filelen = ftell(wsi->u.http.fp); + fseek(wsi->u.http.fp, 0, SEEK_SET); + p += sprintf((char *)p, "HTTP/1.0 200 OK\x0d\x0aServer: libwebsockets\x0d\x0a""Content-Type: %s\x0d\x0a", content_type); @@ -538,8 +534,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: %ld\x0d\x0a\x0d\x0a", wsi->u.http.filelen); ret = libwebsocket_write(wsi, context->service_buffer, p - context->service_buffer, LWS_WRITE_HTTP);