break-out-lib-sources.patch
Signed-off-by: Andy Green <andy@warmcat.com>
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index ac20738..6db4d07 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -19,161 +19,20 @@
* MA 02110-1301 USA
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include <poll.h>
-#include <sys/mman.h>
+#include "private-libwebsockets.h"
#ifdef LWS_OPENSSL_SUPPORT
-#include <openssl/ssl.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-
SSL_CTX *ssl_ctx;
int use_ssl;
#endif
-//#define DEBUG
-#include "libwebsockets.h"
-
-#ifdef DEBUG
-#define debug(format, args...) \
- fprintf(stderr, format , ## args)
-#else
-#define debug(format, args...)
-#endif
-
-void md5(const unsigned char *input, int ilen, unsigned char output[16]);
-static int
+extern int
libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len);
-#define MAX_CLIENTS 100
-#define LWS_MAX_HEADER_NAME_LENGTH 64
-#define LWS_MAX_HEADER_LEN 4096
-#define LWS_INITIAL_HDR_ALLOC 256
-#define LWS_ADDITIONAL_HDR_ALLOC 64
-
-enum lws_connection_states {
- WSI_STATE_HTTP,
- WSI_STATE_HTTP_HEADERS,
- WSI_STATE_DEAD_SOCKET,
- WSI_STATE_ESTABLISHED
-};
-
-enum lws_token_indexes {
- WSI_TOKEN_GET_URI,
- WSI_TOKEN_HOST,
- WSI_TOKEN_CONNECTION,
- WSI_TOKEN_KEY1,
- WSI_TOKEN_KEY2,
- WSI_TOKEN_PROTOCOL,
- WSI_TOKEN_UPGRADE,
- WSI_TOKEN_ORIGIN,
- WSI_TOKEN_CHALLENGE,
-
- /* always last real token index*/
- WSI_TOKEN_COUNT,
- /* parser state additions */
- WSI_TOKEN_NAME_PART,
- WSI_TOKEN_SKIPPING,
- WSI_TOKEN_SKIPPING_SAW_CR,
- WSI_PARSING_COMPLETE
-};
-
-enum lws_rx_parse_state {
- LWS_RXPS_NEW,
-
- LWS_RXPS_SEEN_76_FF,
- LWS_RXPS_PULLING_76_LENGTH,
-
- LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED
-};
-
-
-struct lws_tokens {
- char * token;
- int token_len;
-};
-
-
-/*
- * This is totally opaque to code using the library. It's exported as a
- * forward-reference pointer-only declaration; the user can use the pointer with
- * other APIs to get information out of it.
- */
-
-struct libwebsocket {
- int (*callback)(struct libwebsocket *,
- enum libwebsocket_callback_reasons reason, void *, void *, size_t);
-
- enum lws_connection_states state;
-
- char name_buffer[LWS_MAX_HEADER_NAME_LENGTH];
- int name_buffer_pos;
- int current_alloc_len;
- enum lws_token_indexes parser_state;
- struct lws_tokens utf8_token[WSI_TOKEN_COUNT];
- int ietf_spec_revision;
-
- int sock;
-
- enum lws_rx_parse_state lws_rx_parse_state;
- size_t rx_packet_length;
-
-#ifdef LWS_OPENSSL_SUPPORT
- char m_fOccupied;
- struct sockaddr_in m_addr;
- int m_addrlen;
-
- SSL *ssl;
-
- // these are valid if it is a POST
-
- char m_fOngoingPost;
- int m_nSessionID;
-
- time_t m_timeStarted;
- long long m_llTransferred;
- long long m_llSizeIfKnown;
-
- char m_szTitle[PATH_MAX];
- char m_szStatus[PATH_MAX];
-#endif
-
- /* last */
- char user_space[0];
-};
-
-
-const struct lws_tokens lws_tokens[WSI_TOKEN_COUNT] = {
- { "GET ", 4 },
- { "Host:", 5 },
- { "Connection:", 11 },
- { "Sec-WebSocket-Key1:", 19 },
- { "Sec-WebSocket-Key2:", 19 },
- { "Sec-WebSocket-Protocol:", 23 },
- { "Upgrade:", 8 },
- { "Origin:", 7 },
- { "\x0d\x0a", 2 },
-};
-
-static void
+void
libwebsocket_close_and_free_session(struct libwebsocket *wsi)
{
int n = wsi->state;
@@ -568,662 +427,4 @@
return 0;
}
-/**
- * libwebsocket_get_uri() - Return the URI path being requested
- * @wsi: Websocket instance
- *
- * The user code can find out the local path being opened from this
- * call, it's valid on HTTP or established websocket connections.
- * If the client opened the connection with "http://127.0.0.1/xyz/abc.d"
- * then this call will return a pointer to "/xyz/abc.d"
- */
-const char * libwebsocket_get_uri(struct libwebsocket *wsi)
-{
- if (wsi->utf8_token[WSI_TOKEN_GET_URI].token)
- return wsi->utf8_token[WSI_TOKEN_GET_URI].token;
-
- return NULL;
-}
-
-static int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
-{
- int n;
-
- switch (wsi->parser_state) {
- case WSI_TOKEN_GET_URI:
- case WSI_TOKEN_HOST:
- case WSI_TOKEN_CONNECTION:
- case WSI_TOKEN_KEY1:
- case WSI_TOKEN_KEY2:
- case WSI_TOKEN_PROTOCOL:
- case WSI_TOKEN_UPGRADE:
- case WSI_TOKEN_ORIGIN:
- case WSI_TOKEN_CHALLENGE:
-
- debug("WSI_TOKEN_(%d) '%c'\n", wsi->parser_state, c);
-
- /* collect into malloc'd buffers */
- /* optional space swallow */
- if (!wsi->utf8_token[wsi->parser_state].token_len && c == ' ')
- break;
-
- /* special case space terminator for get-uri */
- if (wsi->parser_state == WSI_TOKEN_GET_URI && c == ' ') {
- wsi->utf8_token[wsi->parser_state].token[
- wsi->utf8_token[wsi->parser_state].token_len] = '\0';
- wsi->parser_state = WSI_TOKEN_SKIPPING;
- break;
- }
-
- /* allocate appropriate memory */
- if (wsi->utf8_token[wsi->parser_state].token_len ==
- wsi->current_alloc_len - 1) {
- /* need to extend */
- wsi->current_alloc_len += LWS_ADDITIONAL_HDR_ALLOC;
- if (wsi->current_alloc_len >= LWS_MAX_HEADER_LEN) {
- /* it's waaay to much payload, fail it */
- strcpy(wsi->utf8_token[wsi->parser_state].token,
- "!!! Length exceeded maximum supported !!!");
- wsi->parser_state = WSI_TOKEN_SKIPPING;
- break;
- }
- wsi->utf8_token[wsi->parser_state].token =
- realloc(wsi->utf8_token[wsi->parser_state].token,
- wsi->current_alloc_len);
- }
-
- /* bail at EOL */
- if (wsi->parser_state != WSI_TOKEN_CHALLENGE && c == '\x0d') {
- wsi->utf8_token[wsi->parser_state].token[
- wsi->utf8_token[wsi->parser_state].token_len] = '\0';
- wsi->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
- break;
- }
-
- wsi->utf8_token[wsi->parser_state].token[
- wsi->utf8_token[wsi->parser_state].token_len++] = c;
-
- /* special payload limiting */
- if (wsi->parser_state == WSI_TOKEN_CHALLENGE &&
- wsi->utf8_token[wsi->parser_state].token_len == 8) {
- debug("Setting WSI_PARSING_COMPLETE\n");
- wsi->parser_state = WSI_PARSING_COMPLETE;
- break;
- }
-
- break;
-
- /* collecting and checking a name part */
- case WSI_TOKEN_NAME_PART:
- debug("WSI_TOKEN_NAME_PART '%c'\n", c);
-
- if (wsi->name_buffer_pos == sizeof(wsi->name_buffer) - 1) {
- /* name bigger than we can handle, skip until next */
- wsi->parser_state = WSI_TOKEN_SKIPPING;
- break;
- }
- wsi->name_buffer[wsi->name_buffer_pos++] = c;
- wsi->name_buffer[wsi->name_buffer_pos] = '\0';
-
- for (n = 0; n < WSI_TOKEN_COUNT; n++) {
- if (wsi->name_buffer_pos != lws_tokens[n].token_len)
- continue;
- if (strcmp(lws_tokens[n].token, wsi->name_buffer))
- continue;
- debug("known hdr '%s'\n", wsi->name_buffer);
- wsi->parser_state = WSI_TOKEN_GET_URI + n;
- wsi->current_alloc_len = LWS_INITIAL_HDR_ALLOC;
- wsi->utf8_token[wsi->parser_state].token =
- malloc(wsi->current_alloc_len);
- wsi->utf8_token[wsi->parser_state].token_len = 0;
- n = WSI_TOKEN_COUNT;
- }
-
- /* colon delimiter means we just don't know this name */
-
- if (wsi->parser_state == WSI_TOKEN_NAME_PART && c == ':') {
- debug("skipping unknown header '%s'\n",
- wsi->name_buffer);
- wsi->parser_state = WSI_TOKEN_SKIPPING;
- break;
- }
-
- /* don't look for payload when it can just be http headers */
-
- if (wsi->parser_state == WSI_TOKEN_CHALLENGE &&
- !wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len) {
- /* they're HTTP headers, not websocket upgrade! */
- debug("Setting WSI_PARSING_COMPLETE "
- "from http headers\n");
- wsi->parser_state = WSI_PARSING_COMPLETE;
- }
- break;
-
- /* skipping arg part of a name we didn't recognize */
- case WSI_TOKEN_SKIPPING:
- debug("WSI_TOKEN_SKIPPING '%c'\n", c);
- if (c == '\x0d')
- wsi->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
- break;
- case WSI_TOKEN_SKIPPING_SAW_CR:
- debug("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
- if (c == '\x0a')
- wsi->parser_state = WSI_TOKEN_NAME_PART;
- else
- wsi->parser_state = WSI_TOKEN_SKIPPING;
- wsi->name_buffer_pos = 0;
- break;
- /* we're done, ignore anything else */
- case WSI_PARSING_COMPLETE:
- debug("WSI_PARSING_COMPLETE '%c'\n", c);
- break;
-
- default: /* keep gcc happy */
- break;
- }
-
- return 0;
-}
-
-static int interpret_key(const char *key, unsigned int *result)
-{
- char digits[20];
- int digit_pos = 0;
- const char *p = key;
- int spaces = 0;
-
- while (*p) {
- if (isdigit(*p)) {
- if (digit_pos == sizeof(digits) - 1)
- return -1;
- digits[digit_pos++] = *p;
- }
- p++;
- }
- digits[digit_pos] = '\0';
- if (!digit_pos)
- return -2;
-
- while (*key) {
- if (*key == ' ')
- spaces++;
- key++;
- }
-
- if (!spaces)
- return -3;
-
- *result = atol(digits) / spaces;
-
- return 0;
-}
-
-static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
-{
- int n;
- unsigned char buf[2];
-
- switch (wsi->lws_rx_parse_state) {
- case LWS_RXPS_NEW:
-
- switch (wsi->ietf_spec_revision) {
- /* Firefox 4.0b6 likes this as of 30 Oct */
- case 76:
- if (c == 0xff)
- wsi->lws_rx_parse_state = LWS_RXPS_SEEN_76_FF;
- break;
- case 0:
- break;
- }
- break;
- case LWS_RXPS_SEEN_76_FF:
- if (c)
- break;
-
- debug("Seen that client is requesting "
- "a v76 close, sending ack\n");
- buf[0] = 0xff;
- buf[1] = 0;
- n = libwebsocket_write(wsi, buf, 2, LWS_WRITE_HTTP);
- if (n < 0) {
- fprintf(stderr, "ERROR writing to socket");
- return -1;
- }
- debug(" v76 close ack sent, server closing skt\n");
- /* returning < 0 will get it closed in parent */
- return -1;
-
- case LWS_RXPS_PULLING_76_LENGTH:
- break;
- case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
- break;
- }
-
- return 0;
-}
-
-static int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
- unsigned char *buf, size_t len)
-{
- int n;
-
- fprintf(stderr, "received %d byte packet\n", (int)len);
- for (n = 0; n < len; n++)
- fprintf(stderr, "%02X ", buf[n]);
- fprintf(stderr, "\n");
-
- /* let the rx protocol state machine have as much as it needs */
-
- n = 0;
- while (wsi->lws_rx_parse_state !=
- LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED && n < len)
- if (libwebsocket_rx_sm(wsi, buf[n++]) < 0)
- return -1;
-
- if (n != len && wsi->callback)
- wsi->callback(wsi, LWS_CALLBACK_RECEIVE, &wsi->user_space[0],
- &buf[n], len - n);
-
- return -0;
-}
-
-
-/*
- * We have to take care about parsing because the headers may be split
- * into multiple fragments. They may contain unknown headers with arbitrary
- * argument lengths. So, we parse using a single-character at a time state
- * machine that is completely independent of packet size.
- */
-
-static int
-libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
-{
- size_t n;
- char *p;
- unsigned int key1, key2;
- unsigned char sum[16];
- char *response;
-
- switch (wsi->state) {
- case WSI_STATE_HTTP:
- wsi->state = WSI_STATE_HTTP_HEADERS;
- wsi->parser_state = WSI_TOKEN_NAME_PART;
- /* fallthru */
- case WSI_STATE_HTTP_HEADERS:
-
- debug("issuing %d bytes to parser\n", (int)len);
-#ifdef DEBUG
- fwrite(buf, 1, len, stderr);
-#endif
- for (n = 0; n< len; n++)
- libwebsocket_parse(wsi, *buf++);
-
- if (wsi->parser_state != WSI_PARSING_COMPLETE)
- break;
-
- /* is this websocket protocol or normal http 1.0? */
-
- if (!wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
- !wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len) {
- if (wsi->callback)
- (wsi->callback)(wsi, LWS_CALLBACK_HTTP,
- &wsi->user_space[0],
- NULL, 0);
- wsi->state = WSI_STATE_HTTP;
- return 0;
- }
-
- /* Websocket - confirm we have all the necessary pieces */
-
- if (!wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len ||
- !wsi->utf8_token[WSI_TOKEN_HOST].token_len ||
- !wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len ||
- !wsi->utf8_token[WSI_TOKEN_KEY1].token_len ||
- !wsi->utf8_token[WSI_TOKEN_KEY2].token_len)
- /* completed header processing, but missing some bits */
- goto bail;
-
- /* create the response packet */
-
- /* make a buffer big enough for everything */
-
- response = malloc(256 +
- wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len +
- wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len +
- wsi->utf8_token[WSI_TOKEN_HOST].token_len +
- wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len +
- wsi->utf8_token[WSI_TOKEN_GET_URI].token_len +
- wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len);
- if (!response) {
- fprintf(stderr, "Out of memory for response buffer\n");
- goto bail;
- }
-
- p = response;
- strcpy(p, "HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"
- "Upgrade: WebSocket\x0d\x0a");
- p += strlen("HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"
- "Upgrade: WebSocket\x0d\x0a");
- strcpy(p, "Connection: Upgrade\x0d\x0a"
- "Sec-WebSocket-Origin: ");
- p += strlen("Connection: Upgrade\x0d\x0a"
- "Sec-WebSocket-Origin: ");
- strcpy(p, wsi->utf8_token[WSI_TOKEN_ORIGIN].token);
- p += wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len;
-#ifdef LWS_OPENSSL_SUPPORT
- if (use_ssl) {
- strcpy(p, "\x0d\x0aSec-WebSocket-Location: wss://");
- p += strlen("\x0d\x0aSec-WebSocket-Location: wss://");
- } else {
-#endif
- strcpy(p, "\x0d\x0aSec-WebSocket-Location: ws://");
- p += strlen("\x0d\x0aSec-WebSocket-Location: ws://");
-#ifdef LWS_OPENSSL_SUPPORT
- }
-#endif
- strcpy(p, wsi->utf8_token[WSI_TOKEN_HOST].token);
- p += wsi->utf8_token[WSI_TOKEN_HOST].token_len;
- strcpy(p, wsi->utf8_token[WSI_TOKEN_GET_URI].token);
- p += wsi->utf8_token[WSI_TOKEN_GET_URI].token_len;
-
- if (wsi->utf8_token[WSI_TOKEN_PROTOCOL].token) {
- strcpy(p, "\x0d\x0aSec-WebSocket-Protocol: ");
- p += strlen("\x0d\x0aSec-WebSocket-Protocol: ");
- strcpy(p, wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
- p += wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len;
- }
-
- strcpy(p, "\x0d\x0a\x0d\x0a");
- p += strlen("\x0d\x0a\x0d\x0a");
-
- /* convert the two keys into 32-bit integers */
-
- if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY1].token, &key1))
- goto bail;
- if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY2].token, &key2))
- goto bail;
-
- /* lay them out in network byte order (MSB first */
-
- sum[0] = key1 >> 24;
- sum[1] = key1 >> 16;
- sum[2] = key1 >> 8;
- sum[3] = key1;
- sum[4] = key2 >> 24;
- sum[5] = key2 >> 16;
- sum[6] = key2 >> 8;
- sum[7] = key2;
-
- /* follow them with the challenge token we were sent */
-
- memcpy(&sum[8], wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 8);
-
- /*
- * compute the md5sum of that 16-byte series and use as our
- * payload after our headers
- */
-
- md5(sum, 16, (unsigned char *)p);
- p += 16;
-
- /* it's complete: go ahead and send it */
-
- debug("issuing response packet %d len\n",
- (int)(p - response));
-#ifdef DEBUG
- fwrite(response, 1, p - response, stderr);
-#endif
- n = libwebsocket_write(wsi, (unsigned char *)response, p - response,
- LWS_WRITE_HTTP);
- if (n < 0) {
- fprintf(stderr, "ERROR writing to socket");
- goto bail;
- }
-
- /* alright clean up and set ourselves into established state */
-
- free(response);
- wsi->state = WSI_STATE_ESTABLISHED;
- wsi->lws_rx_parse_state = LWS_RXPS_NEW;
-
- /* notify user code that we're ready to roll */
-
- if (wsi->callback)
- wsi->callback(wsi, LWS_CALLBACK_ESTABLISHED,
- &wsi->user_space[0], NULL, 0);
- break;
-
- case WSI_STATE_ESTABLISHED:
- if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0)
- goto bail;
- break;
- default:
- break;
- }
-
- return 0;
-
-bail:
- libwebsocket_close_and_free_session(wsi);
- return -1;
-}
-
-/**
- * libwebsocket_write() - Apply protocol then write data to client
- * @wsi: Websocket instance (available from user callback)
- * @buf: The data to send. For data being sent on a websocket
- * connection (ie, not default http), this buffer MUST have
- * LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
- * and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
- * in the buffer after (buf + len). This is so the protocol
- * header and trailer data can be added in-situ.
- * @len: Count of the data bytes in the payload starting from buf
- * @protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one
- * of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
- * data on a websockets connection. Remember to allow the extra
- * bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
- * are used.
- *
- * This function provides the way to issue data back to the client
- * for both http and websocket protocols.
- *
- * In the case of sending using websocket protocol, be sure to allocate
- * valid storage before and after buf as explained above. This scheme
- * allows maximum efficiency of sending data and protocol in a single
- * packet while not burdening the user code with any protocol knowledge.
- */
-
-int libwebsocket_write(struct libwebsocket * wsi, unsigned char *buf,
- size_t len, enum libwebsocket_write_protocol protocol)
-{
- int n;
- int pre = 0;
- int post = 0;
- unsigned int shift = 7;
-
- if (protocol == LWS_WRITE_HTTP)
- goto send_raw;
-
- /* websocket protocol, either binary or text */
-
- if (wsi->state != WSI_STATE_ESTABLISHED)
- return -1;
-
- switch (wsi->ietf_spec_revision) {
- /* chrome likes this as of 30 Oct */
- /* Firefox 4.0b6 likes this as of 30 Oct */
- case 76:
- if (protocol == LWS_WRITE_BINARY) {
- /* in binary mode we send 7-bit used length blocks */
- pre = 1;
- while (len & (127 << shift)) {
- pre++;
- shift += 7;
- }
- n = 0;
- shift -= 7;
- while (shift >= 0) {
- if (shift)
- buf[0 - pre + n] =
- ((len >> shift) & 127) | 0x80;
- else
- buf[0 - pre + n] =
- ((len >> shift) & 127);
- n++;
- shift -= 7;
- }
- break;
- }
-
- /* frame type = text, length-free spam mode */
-
- buf[-1] = 0;
- buf[len] = 0xff; /* EOT marker */
- pre = 1;
- post = 1;
- break;
-
- case 0:
- buf[-9] = 0xff;
-#if defined __LP64__
- buf[-8] = len >> 56;
- buf[-7] = len >> 48;
- buf[-6] = len >> 40;
- buf[-5] = len >> 32;
-#else
- buf[-8] = 0;
- buf[-7] = 0;
- buf[-6] = 0;
- buf[-5] = 0;
-#endif
- buf[-4] = len >> 24;
- buf[-3] = len >> 16;
- buf[-2] = len >> 8;
- buf[-1] = len;
- pre = 9;
- break;
-
- /* just an unimplemented spec right now apparently */
- case 2:
- n = 4; /* text */
- if (protocol == LWS_WRITE_BINARY)
- n = 5; /* binary */
- if (len < 126) {
- buf[-2] = n;
- buf[-1] = len;
- pre = 2;
- } else {
- if (len < 65536) {
- buf[-4] = n;
- buf[-3] = 126;
- buf[-2] = len >> 8;
- buf[-1] = len;
- pre = 4;
- } else {
- buf[-10] = n;
- buf[-9] = 127;
-#if defined __LP64__
- buf[-8] = (len >> 56) & 0x7f;
- buf[-7] = len >> 48;
- buf[-6] = len >> 40;
- buf[-5] = len >> 32;
-#else
- buf[-8] = 0;
- buf[-7] = 0;
- buf[-6] = 0;
- buf[-5] = 0;
-#endif
- buf[-4] = len >> 24;
- buf[-3] = len >> 16;
- buf[-2] = len >> 8;
- buf[-1] = len;
- pre = 10;
- }
- }
- break;
- }
-
-#if 0
- for (n = 0; n < (len + pre + post); n++)
- fprintf(stderr, "%02X ", buf[n - pre]);
-
- fprintf(stderr, "\n");
-#endif
-
-send_raw:
-#ifdef LWS_OPENSSL_SUPPORT
- if (use_ssl) {
- n = SSL_write(wsi->ssl, buf - pre, len + pre + post);
- if (n < 0) {
- fprintf(stderr, "ERROR writing to socket");
- return -1;
- }
- } else {
-#endif
- n = send(wsi->sock, buf - pre, len + pre + post, 0);
- if (n < 0) {
- fprintf(stderr, "ERROR writing to socket");
- return -1;
- }
-#ifdef LWS_OPENSSL_SUPPORT
- }
-#endif
-// fprintf(stderr, "written %d bytes to client\n", (int)len);
-
- return 0;
-}
-
-
-/**
- * libwebsockets_serve_http_file() - Send a file back to the client using http
- * @wsi: Websocket instance (available from user callback)
- * @file: The file to issue over http
- * @content_type: The http content type, eg, text/html
- *
- * This function is intended to be called from the callback in response
- * to http requests from the client. It allows the callback to issue
- * local files down the http link in a single step.
- */
-
-int libwebsockets_serve_http_file(struct libwebsocket *wsi, const char * file,
- const char * content_type)
-{
- int fd;
- struct stat stat;
- char buf[512];
- char *p = buf;
- int n;
-
- fd = open(file, O_RDONLY);
- if (fd < 1) {
- p += sprintf(p, "HTTP/1.0 400 Bad\x0d\x0a"
- "Server: libwebsockets\x0d\x0a"
- "\x0d\x0a"
- );
- libwebsocket_write(wsi, (unsigned char *)buf, p - buf,
- LWS_WRITE_HTTP);
-
- return -1;
- }
-
- fstat(fd, &stat);
- p += sprintf(p, "HTTP/1.0 200 OK\x0d\x0a"
- "Server: libwebsockets\x0d\x0a"
- "Content-Type: %s\x0d\x0a"
- "Content-Length: %u\x0d\x0a"
- "\x0d\x0a", content_type, (unsigned int)stat.st_size);
-
- libwebsocket_write(wsi, (unsigned char *)buf, p - buf, LWS_WRITE_HTTP);
-
- n = 1;
- while (n > 0) {
- n = read(fd, buf, 512);
- libwebsocket_write(wsi, (unsigned char *)buf, n,
- LWS_WRITE_HTTP);
- }
-
- close(fd);
-
- return 0;
-}