diff --git a/test-server/Makefile.am b/test-server/Makefile.am index 1159b378..b08460dc 100644 --- a/test-server/Makefile.am +++ b/test-server/Makefile.am @@ -109,7 +109,7 @@ libwebsockets_test_ping_CFLAGS= -Wall -Werror -std=gnu99 -pedantic -DINSTALL_DAT endif endif -EXTRA_DIST=test.html favicon.ico libwebsockets.org-logo.png +EXTRA_DIST=test.html favicon.ico libwebsockets.org-logo.png leaf.jpg # # cook a random test cert and key diff --git a/test-server/leaf.jpg b/test-server/leaf.jpg new file mode 100644 index 00000000..1a3f46b5 Binary files /dev/null and b/test-server/leaf.jpg differ diff --git a/test-server/test-server.c b/test-server/test-server.c index ecf1dd14..246c1b8d 100644 --- a/test-server/test-server.c +++ b/test-server/test-server.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #ifdef WIN32 @@ -104,6 +106,10 @@ static const struct serveable whitelist[] = { { "/test.html", "text/html" }, }; +struct per_session_data__http { + int fd; +}; + /* this protocol server (always the first one) just knows how to do HTTP */ static int callback_http(struct libwebsocket_context *context, @@ -117,6 +123,10 @@ static int callback_http(struct libwebsocket_context *context, #endif char buf[256]; int n; + unsigned char *p; + static unsigned char buffer[8192]; + struct stat stat_buf; + struct per_session_data__http *pss = (struct per_session_data__http *)user; #ifdef EXTERNAL_POLL int m; int fd = (int)(long)user; @@ -125,6 +135,55 @@ static int callback_http(struct libwebsocket_context *context, switch (reason) { case LWS_CALLBACK_HTTP: + /* check for the "send a big file by hand" example case */ + + if (!strcmp((const char *)in, "/leaf.jpg")) { + + /* well, let's demonstrate how to send the hard way */ + + p = buffer; + + pss->fd = open(LOCAL_RESOURCE_PATH"/leaf.jpg", O_RDONLY); + if (pss->fd < 0) + return -1; + + fstat(pss->fd, &stat_buf); + + /* + * we will send a big jpeg file, but it could be + * anything. Set the Content-Type: appropriately + * so the browser knows what to do with it. + */ + + p += sprintf((char *)p, + "HTTP/1.0 200 OK\x0d\x0a" + "Server: libwebsockets\x0d\x0a" + "Content-Type: image-jpeg\x0d\x0a" + "Content-Length: %u\x0d\x0a\x0d\x0a", + (unsigned int)stat_buf.st_size); + + /* + * send the http headers... + * this won't block since it's the first payload sent + * on the connection since it was established + */ + + n = libwebsocket_write(wsi, buffer, + p - buffer, LWS_WRITE_HTTP); + + if (n < 0) { + close(pss->fd); + return -1; + } + /* + * book us a LWS_CALLBACK_HTTP_WRITEABLE callback + */ + libwebsocket_callback_on_writable(context, wsi); + break; + } + + /* if not, send a file the easy way */ + for (n = 0; n < (sizeof(whitelist) / sizeof(whitelist[0]) - 1); n++) if (in && strcmp((const char *)in, whitelist[n].urlpath) == 0) break; @@ -132,7 +191,7 @@ static int callback_http(struct libwebsocket_context *context, sprintf(buf, LOCAL_RESOURCE_PATH"%s", whitelist[n].urlpath); if (libwebsockets_serve_http_file(context, wsi, buf, whitelist[n].mimetype)) - return 1; /* through completion or error, close the socket */ + return -1; /* through completion or error, close the socket */ /* * notice that the sending of the file completes asynchronously, @@ -145,7 +204,37 @@ static int callback_http(struct libwebsocket_context *context, case LWS_CALLBACK_HTTP_FILE_COMPLETION: // lwsl_info("LWS_CALLBACK_HTTP_FILE_COMPLETION seen\n"); /* kill the connection after we sent one file */ - return 1; + return -1; + + case LWS_CALLBACK_HTTP_WRITEABLE: + /* + * we can send more of whatever it is we were sending + */ + + do { + n = read(pss->fd, buffer, sizeof buffer); + /* problem reading, close conn */ + if (n < 0) + goto bail; + /* sent it all, close conn */ + if (n == 0) + goto bail; + /* + * because it's HTTP and not websocket, don't need to take + * care about pre and postamble + */ + n = libwebsocket_write(wsi, buffer, n, LWS_WRITE_HTTP); + if (n < 0) + /* write failed, close conn */ + goto bail; + + } while (!lws_send_pipe_choked(wsi)); + libwebsocket_callback_on_writable(context, wsi); + break; + +bail: + close(pss->fd); + return -1; /* * callback for confirming to continue with client IP appear in @@ -476,7 +565,7 @@ static struct libwebsocket_protocols protocols[] = { { "http-only", /* name */ callback_http, /* callback */ - 0, /* per_session_data_size */ + sizeof (struct per_session_data__http), /* per_session_data_size */ 0, /* max frame size / rx buffer */ }, { diff --git a/test-server/test.html b/test-server/test.html index 482147e0..919f46a2 100644 --- a/test-server/test.html +++ b/test-server/test.html @@ -37,8 +37,9 @@ The incrementing number is coming from the server and is individual for each connection to the server... try opening a second browser window.

-Click the button to send the server a websocket message to -reset the number. +The button zeros just this connection's number. +

+Click Here to have the test server send a big picture by http.