#include <getopt.h>
#include <string.h>
#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <assert.h>
#ifdef WIN32
{ "/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,
#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;
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;
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,
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
{
"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 */
},
{