2 * libwebsockets-test-server - libwebsockets test implementation
4 * Copyright (C) 2010 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
28 #include "../lib/libwebsockets.h"
30 #define LOCAL_RESOURCE_PATH "/usr/share/libwebsockets-test-server"
31 static int port = 7681;
32 static int use_ssl = 0;
34 struct per_session_data {
39 * libwebsocket_callback() - User server actions
40 * @wsi: Opaque websocket instance pointer
41 * @reason: The reason for the call
42 * @user: Pointer to per-session user data allocated by library
43 * @in: Pointer used for some callback reasons
44 * @len: Length set for some callback reasons
46 * This callback is the way the user controls what is served. All the
47 * protocol detail is hidden and handled by the library.
49 * For each connection / session there is user data allocated that is
50 * pointed to by "user". You set the size of this user data area when
51 * the library is initialized with libwebsocket_create_server.
53 * You get an opportunity to initialize user data when called back with
54 * LWS_CALLBACK_ESTABLISHED reason.
56 * LWS_CALLBACK_ESTABLISHED: after successful websocket handshake
58 * LWS_CALLBACK_CLOSED: when the websocket session ends
60 * LWS_CALLBACK_SEND: opportunity to send to client (you would use
61 * libwebsocket_write() taking care about the
62 * special buffer requirements
63 * LWS_CALLBACK_RECEIVE: data has appeared for the server, it can be
64 * found at *in and is len bytes long
66 * LWS_CALLBACK_HTTP: an http request has come from a client that is not
67 * asking to upgrade the connection to a websocket
68 * one. This is a chance to serve http content,
69 * for example, to send a script to the client
70 * which will then open the websockets connection.
71 * @in points to the URI path requested and
72 * libwebsockets_serve_http_file() makes it very
73 * simple to send back a file to the client.
75 * LWS_CALLBACK_PROTOCOL_FILTER: before the confirmation handshake is sent
76 * the user callback is given a chance to confirm
77 * it's OK with the protocol that was requested
78 * from the client. The protocol string (which
79 * may be NULL if no protocol header was sent)
80 * can be found at parameter @in. Return 0 from
81 * the callback to allow the connection or nonzero
82 * to abort the connection.
85 static int websocket_callback(struct libwebsocket * wsi,
86 enum libwebsocket_callback_reasons reason, void * user,
90 char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 +
91 LWS_SEND_BUFFER_POST_PADDING];
92 char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
93 struct per_session_data * pss = user;
97 * Websockets session handshake completed and is established
99 case LWS_CALLBACK_ESTABLISHED:
100 fprintf(stderr, "Websocket connection established\n");
105 * Websockets session is closed
107 case LWS_CALLBACK_CLOSED:
108 fprintf(stderr, "Websocket connection closed\n");
112 * Opportunity for us to send something on the connection
114 case LWS_CALLBACK_SEND:
115 n = sprintf(p, "%d", pss->number++);
116 n = libwebsocket_write(wsi, (unsigned char *)p, n,
119 fprintf(stderr, "ERROR writing to socket");
124 * Something has arrived for us on the connection, it's len bytes long
125 * and is available at *in
127 case LWS_CALLBACK_RECEIVE:
128 fprintf(stderr, "Received %d bytes payload\n", (int)len);
132 * The client has asked us for something in normal HTTP mode,
133 * not websockets mode. Normally it means we want to send
134 * our script / html to the client, and when that script runs
135 * it will start up separate websocket connections.
137 * Interpret the URI string to figure out what is needed to send
140 case LWS_CALLBACK_HTTP:
142 fprintf(stderr, "serving HTTP URI %s\n", in);
144 if (in && strcmp(in, "/favicon.ico") == 0) {
145 if (libwebsockets_serve_http_file(wsi,
146 LOCAL_RESOURCE_PATH"/favicon.ico", "image/x-icon"))
147 fprintf(stderr, "Failed to send favicon\n");
151 /* send the script... when it runs it'll start websockets */
153 if (libwebsockets_serve_http_file(wsi,
154 LOCAL_RESOURCE_PATH"/test.html", "text/html"))
155 fprintf(stderr, "Failed to send HTTP file\n");
159 * This is our chance to choose if we support one of the requested
160 * protocols or not. in points to the protocol string. Nonzero return
161 * aborts the connection handshake
164 case LWS_CALLBACK_PROTOCOL_FILTER:
166 fprintf(stderr, "Client did not request protocol\n");
170 fprintf(stderr, "Client requested protocol '%s'\n", in);
178 static struct option options[] = {
179 { "help", no_argument, NULL, 'h' },
180 { "port", required_argument, NULL, 'p' },
181 { "protocol", required_argument, NULL, 'r' },
182 { "ssl", no_argument, NULL, 's' },
186 int main(int argc, char **argv)
189 const char * cert_path =
190 LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
191 const char * key_path =
192 LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
194 fprintf(stderr, "libwebsockets test server\n"
195 "(C) Copyright 2010 Andy Green <andy@warmcat.com> "
196 "licensed under LGPL2.1\n");
199 n = getopt_long(argc, argv, "hp:r:", options, NULL);
210 fprintf(stderr, "Usage: test-server "
211 "[--port=<p>] [--protocol=<v>]\n");
217 cert_path = key_path = NULL;
219 if (libwebsocket_create_server(port, websocket_callback,
220 sizeof(struct per_session_data),
221 cert_path, key_path, -1, -1) < 0) {
222 fprintf(stderr, "libwebsocket init failed\n");
226 /* just sit there until killed */