diff --git a/lib/context.c b/lib/context.c index 1a418a622..ef0362e5a 100644 --- a/lib/context.c +++ b/lib/context.c @@ -174,6 +174,8 @@ libwebsocket_create_context(struct lws_context_creation_info *info) goto bail; } + lws_context_init_file_callbacks(info, context); + lws_context_init_extensions(info, context); context->user_space = info->user; diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index cb4a9efd6..f378f0534 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -118,7 +118,7 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context, if (wsi->u.http.fd != LWS_INVALID_FILE) { // TODO: If we're just closing with LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY this file descriptor might leak? lwsl_debug("closing http file\n"); - compatible_file_close(wsi->u.http.fd); + context->file_callbacks.pfn_close(wsi->u.http.fd); 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/libwebsockets.h b/lib/libwebsockets.h index c1285e860..961199fc3 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -1119,6 +1119,24 @@ struct libwebsocket_extension { }; #endif +/** + * struct libwebsocket_file_callbacks - File operations callbacks + * + * @pfn_open: Open file (always binary access) + * @pfn_close: Close file + * @pfn_seek_cur: Seeking function from current position + * @pfn_read: File read function + * 'amount' is a count of bytes read, + * 'len' is count of bytes to read + */ + +struct libwebsocket_file_callbacks { + void* (*pfn_open)(const char* filename, unsigned long* filelen); + void (*pfn_close)(void* handle); + unsigned long (*pfn_seek_cur)(void* handle, long offsetFromCurPos); + void (*pfn_read)(unsigned long* amount, void* handle, unsigned char* buf, unsigned long len); +}; + /** * struct lws_context_creation_info: parameters to create context with * @@ -1135,6 +1153,8 @@ struct libwebsocket_extension { * @extensions: NULL or array of libwebsocket_extension structs listing the * extensions this context supports. If you configured with * --without-extensions, you should give NULL here. + * @file_callbacks: custom file operation callbacks + to support virtual file system defined by application * @token_limits: NULL or struct lws_token_limits pointer which is initialized * with a token length limit for each possible WSI_TOKEN_*** * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want @@ -1175,6 +1195,7 @@ struct lws_context_creation_info { const char *iface; struct libwebsocket_protocols *protocols; struct libwebsocket_extension *extensions; + struct libwebsocket_file_callbacks *file_callbacks; struct lws_token_limits *token_limits; const char *ssl_private_key_password; const char *ssl_cert_filepath; diff --git a/lib/lws-plat-win.c b/lib/lws-plat-win.c index 01e8a058d..3fcfb1ebf 100644 --- a/lib/lws-plat-win.c +++ b/lib/lws-plat-win.c @@ -395,23 +395,6 @@ lws_plat_change_pollfd(struct libwebsocket_context *context, return 1; } -LWS_VISIBLE HANDLE -lws_plat_open_file(const char* filename, unsigned long* filelen) -{ - HANDLE ret; - WCHAR buffer[MAX_PATH]; - - MultiByteToWideChar(CP_UTF8, 0, filename, -1, buffer, - sizeof(buffer) / sizeof(buffer[0])); - ret = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (ret != LWS_INVALID_FILE) - *filelen = GetFileSize(ret, NULL); - - return ret; -} - LWS_VISIBLE const char * lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt) { diff --git a/lib/output.c b/lib/output.c index 6a595c9c0..9628d35d3 100644 --- a/lib/output.c +++ b/lib/output.c @@ -536,7 +536,7 @@ LWS_VISIBLE int libwebsockets_serve_http_file_fragment( if (wsi->u.http.filepos == wsi->u.http.filelen) goto all_sent; - compatible_file_read(n, wsi->u.http.fd, context->service_buffer, + context->file_callbacks.pfn_read(&n, wsi->u.http.fd, context->service_buffer, sizeof(context->service_buffer)); if (n < 0) return -1; /* caller will close */ @@ -550,7 +550,7 @@ LWS_VISIBLE int libwebsockets_serve_http_file_fragment( if (m != n) /* adjust for what was not sent */ - if (compatible_file_seek_cur(wsi->u.http.fd, m - n) < 0) + if (context->file_callbacks.pfn_seek_cur(wsi->u.http.fd, m - n) < 0) return -1; } all_sent: @@ -559,7 +559,7 @@ all_sent: wsi->state = WSI_STATE_HTTP; /* we might be in keepalive, so close it off here */ - compatible_file_close(wsi->u.http.fd); + context->file_callbacks.pfn_close(wsi->u.http.fd); wsi->u.http.fd = LWS_INVALID_FILE; if (wsi->protocol->callback) diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 5ec133d9d..0d2ca2ba8 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -59,17 +59,8 @@ #define MSG_NOSIGNAL 0 #define SHUT_RDWR SD_BOTH #define SOL_TCP IPPROTO_TCP - #define compatible_close(fd) closesocket(fd) -#define compatible_file_close(fd) CloseHandle(fd) -#define compatible_file_seek_cur(fd, offset) SetFilePointer(fd, offset, NULL, FILE_CURRENT) -#define compatible_file_read(amount, fd, buf, len) {\ - DWORD _amount; \ - if (!ReadFile(fd, buf, len, &_amount, NULL)) \ - amount = -1; \ - else \ - amount = _amount; \ - } + #define lws_set_blocking_send(wsi) wsi->sock_send_blocking = TRUE #define lws_socket_is_valid(x) (!!x) #define LWS_SOCK_INVALID 0 @@ -147,10 +138,7 @@ #define LWS_POLLIN (POLLIN) #define LWS_POLLOUT (POLLOUT) #define compatible_close(fd) close(fd) -#define compatible_file_close(fd) close(fd) -#define compatible_file_seek_cur(fd, offset) lseek(fd, offset, SEEK_CUR) -#define compatible_file_read(amount, fd, buf, len) \ - amount = read(fd, buf, len); + #define lws_set_blocking_send(wsi) #ifdef MBED_OPERATORS @@ -544,6 +532,7 @@ struct libwebsocket_context { #ifndef LWS_NO_EXTENSIONS struct libwebsocket_extension *extensions; #endif + struct libwebsocket_file_callbacks file_callbacks; struct lws_token_limits *token_limits; void *user_space; }; @@ -1031,6 +1020,10 @@ lws_ext_callback_for_each_extension_type( #define lws_context_init_extensions(_a, _b) #endif +LWS_EXTERN void +lws_context_init_file_callbacks(struct lws_context_creation_info *info, + struct libwebsocket_context *context); + LWS_EXTERN int lws_client_interpret_server_handshake(struct libwebsocket_context *context, struct libwebsocket *wsi); @@ -1149,12 +1142,6 @@ LWS_EXTERN int interface_to_sa(struct libwebsocket_context *context, #endif LWS_EXTERN void lwsl_emit_stderr(int level, const char *line); -#ifdef _WIN32 -LWS_EXTERN HANDLE lws_plat_open_file(const char* filename, unsigned long* filelen); -#else -LWS_EXTERN int lws_plat_open_file(const char* filename, unsigned long* filelen); -#endif - enum lws_ssl_capable_status { LWS_SSL_CAPABLE_ERROR = -1, LWS_SSL_CAPABLE_MORE_SERVICE = -2, diff --git a/lib/server.c b/lib/server.c index 4256d3c54..d5d23bd49 100644 --- a/lib/server.c +++ b/lib/server.c @@ -921,7 +921,7 @@ LWS_VISIBLE int libwebsockets_serve_http_file( LWS_SEND_BUFFER_PRE_PADDING; int ret = 0; - wsi->u.http.fd = lws_plat_open_file(file, &wsi->u.http.filelen); + wsi->u.http.fd = context->file_callbacks.pfn_open(file, &wsi->u.http.filelen); if (wsi->u.http.fd == LWS_INVALID_FILE) { lwsl_err("Unable to open '%s'\n", file); diff --git a/test-server/test-server.c b/test-server/test-server.c index 8949dfd25..c53037e9c 100644 --- a/test-server/test-server.c +++ b/test-server/test-server.c @@ -287,6 +287,8 @@ int main(int argc, char **argv) * which also includes libwebsocket sockets */ + pollfds->events = (0x0100 | 0x0200); + n = poll(pollfds, count_pollfds, 50); if (n < 0) continue;