From ab990e440da7b49be0f7d3b7985d3d0b0268d505 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 31 Oct 2010 12:42:52 +0000 Subject: [PATCH] add-api-documentation-comments.patch Signed-off-by: Andy Green --- libwebsockets.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++------- libwebsockets.h | 14 +++++++--- test-server.c | 84 ++++++++++++++++++++++++++++++++++----------------------- 3 files changed, 130 insertions(+), 47 deletions(-) diff --git a/libwebsockets.c b/libwebsockets.c index 7fcf4e1..05be153 100644 --- a/libwebsockets.c +++ b/libwebsockets.c @@ -95,7 +95,8 @@ struct lws_tokens { /* * This is totally opaque to code using the library. It's exported as a - * forward-reference pointer-only declaration. + * forward-reference pointer-only declaration; the user can use the pointer with + * other APIs to get information out of it. */ struct libwebsocket { @@ -130,6 +131,27 @@ const struct lws_tokens lws_tokens[WSI_TOKEN_COUNT] = { { "\x0d\x0a", 2 }, }; +/** + * libwebsocket_create_server() - Create the listening websockets server + * @port: Port to listen on + * @callback: The callback in user code to perform actual serving + * @protocol: Which version of the websockets protocol (currently 76) + * + * This function forks to create the listening socket and takes care + * of all initialization in one step. + * + * The callback function is called for a handful of events including + * http requests coming in, websocket connections becoming + * established, and data arriving; it's also called periodically to allow + * async transmission. + * + * The server created is a simple http server by default; part of the + * websocket standard is upgrading this http connection to a websocket one. + * + * This allows the same server to provide files like scripts and favicon / + * images or whatever over http and dynamic data over websockets all in + * one place; they're all handled in the user callback. + */ int libwebsocket_create_server(int port, int (*callback)(struct libwebsocket *, @@ -238,7 +260,7 @@ int libwebsocket_create_server(int port, } } -void libwebsocket_close(struct libwebsocket *wsi) +static void libwebsocket_close(struct libwebsocket *wsi) { int n; @@ -252,6 +274,16 @@ void libwebsocket_close(struct libwebsocket *wsi) free(wsi->utf8_token[n].token); } +/** + * 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) @@ -509,7 +541,8 @@ static int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi, * machine that is completely independent of packet size. */ -int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len) +static int +libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len) { size_t n; char *p; @@ -667,14 +700,29 @@ bail: return -1; } - -/* - * notice, we will use up to LWS_SEND_BUFFER_PRE_PADDING bytes BEFORE the - * buffer pointer given and LWS_SEND_BUFFER_POST_PADDING bytes AFTER - * buf + len !!! Caller must allocate and offset pointer accordingly! +/** + * 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. * - * This lets us send packets in one write() action including the protocol - * pre- and post- data without copying the payload around. + * 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, @@ -871,6 +919,17 @@ pout: } } +/** + * 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) { diff --git a/libwebsockets.h b/libwebsockets.h index 6ecccd1..ecd837f 100644 --- a/libwebsockets.h +++ b/libwebsockets.h @@ -1,3 +1,6 @@ +#ifndef __LIBWEBSOCKET_H__ +#define __LIBWEBSOCKET_H__ + enum libwebsocket_callback_reasons { LWS_CALLBACK_ESTABLISHED, @@ -33,12 +36,12 @@ extern int libwebsocket_create_server(int port, * So for example you need this kind of code to use libwebsocket_write with a * 128-byte payload * - * char buf[LWS_SEND_BUFFER_PRE_PADDING + 128 + LWS_SEND_BUFFER_POST_PADDING]; + * char buf[LWS_SEND_BUFFER_PRE_PADDING + 128 + LWS_SEND_BUFFER_POST_PADDING]; * - * // fill your part of the buffer... for example here it's all zeros - * memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, 128); + * // fill your part of the buffer... for example here it's all zeros + * memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, 128); * - * libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 128); + * libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 128); * * When sending LWS_WRITE_HTTP, there is no protocol addition and you can just * use the whole buffer without taking care of the above. @@ -52,6 +55,9 @@ libwebsocket_write(struct libwebsocket *, unsigned char *buf, size_t len, enum libwebsocket_write_protocol protocol); extern const char * libwebsocket_get_uri(struct libwebsocket *wsi); + extern int libwebsockets_serve_http_file(struct libwebsocket *wsi, const char * file, const char * content_type); + +#endif diff --git a/test-server.c b/test-server.c index 5bbda6f..4c16e2c 100644 --- a/test-server.c +++ b/test-server.c @@ -4,7 +4,6 @@ #include #include - #include "libwebsockets.h" /* @@ -13,37 +12,46 @@ * Shows how to use libwebsocket */ - static int port = 7681; static int ws_protocol = 76; +/* + * libwebsockets needs this one callback in your server application, it's + * called for a handful of different reasons during the connection lifecycle. + * + * All the serving actions occur in the callback but the websocket protocol + * stuff is already handled by the library. + */ + static int websocket_callback(struct libwebsocket * wsi, - enum libwebsocket_callback_reasons reason, void *in, size_t len) + enum libwebsocket_callback_reasons reason, void *in, size_t len) { int n; - char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 + LWS_SEND_BUFFER_POST_PADDING]; + char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 + + LWS_SEND_BUFFER_POST_PADDING]; static int bump; - static int slow; char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING]; const char *uri; switch (reason) { + /* + * Websockets session handshake completed and is established + */ case LWS_CALLBACK_ESTABLISHED: fprintf(stderr, "Websocket connection established\n"); - slow = 100; break; + /* + * Websockets session is closed + */ case LWS_CALLBACK_CLOSED: fprintf(stderr, "Websocket connection closed\n"); break; + /* + * Opportunity for us to send something on the connection + */ case LWS_CALLBACK_SEND: -// slow--; -// if (slow) { -// usleep(10000); -// break; -// } -// slow = 20; n = sprintf(p, "%d", bump++); n = libwebsocket_write(wsi, (unsigned char *)p, n, 0); if (n < 0) { @@ -51,38 +59,43 @@ static int websocket_callback(struct libwebsocket * wsi, exit(1); } break; - + /* + * Something has arrived for us on the connection, it's len bytes long + * and is available at *in + */ case LWS_CALLBACK_RECEIVE: fprintf(stderr, "Received %d bytes payload\n", (int)len); break; + + /* + * The client has asked us for something in normal HTTP mode, + * not websockets mode. Normally it means we want to send + * our script / html to the client, and when that script runs + * it will start up separate websocket connections. + * + * Interpret the URI string to figure out what is needed to send + */ + case LWS_CALLBACK_HTTP: - /* - * The client has asked us for something in normal HTTP mode, - * not websockets mode. Normally it means we want to send - * our script / html to the client, and when that script runs - * it will start up separate websocket connections. - */ + uri = libwebsocket_get_uri(wsi); - if (uri == NULL) - fprintf(stderr, "LWS_CALLBACK_HTTP NULL URI\n"); - else - fprintf(stderr, "LWS_CALLBACK_HTTP '%s'\n", uri); - if (uri && strcmp(uri, "/favicon.ico") == 0) { - if (libwebsockets_serve_http_file(wsi, "./favicon.ico", "image/x-icon")) { - fprintf(stderr, "Failed to send favicon file\n"); - } + if (libwebsockets_serve_http_file(wsi, "./favicon.ico", + "image/x-icon")) + fprintf(stderr, "Failed to send favicon\n"); break; } /* send the script... when it runs it'll start websockets */ - if (libwebsockets_serve_http_file(wsi, "./test.html", "text/html")) { + if (libwebsockets_serve_http_file(wsi, "./test.html", + "text/html")) { fprintf(stderr, "Failed to send HTTP file\n"); } break; } + return 0; } @@ -97,7 +110,9 @@ int main(int argc, char **argv) { int n = 0; - fprintf(stderr, "libwebsockets test server\nCopyright 2010 Andy Green licensed under GPL2\n"); + fprintf(stderr, "libwebsockets test server\n" + "Copyright 2010 Andy Green " + "licensed under GPL2\n"); while (n >= 0) { n = getopt_long(argc, argv, "hp:r:", options, NULL); @@ -111,19 +126,22 @@ int main(int argc, char **argv) ws_protocol = atoi(optarg); break; case 'h': - fprintf(stderr, "Usage: test-server [--port=

] [--protocol=]\n"); + fprintf(stderr, "Usage: test-server " + "[--port=

] [--protocol=]\n"); exit(1); } - } - if (libwebsocket_create_server(port, websocket_callback, ws_protocol) < 0) { + if (libwebsocket_create_server(port, websocket_callback, ws_protocol) < + 0) { fprintf(stderr, "libwebsocket init failed\n"); return -1; } + + /* just sit there until killed */ while (1) - sleep(1); + sleep(10); return 0; } -- 2.7.4