clean--fix-sigpipe.patch

Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
Andy Green 2011-01-23 16:50:33 +00:00
parent 4739e5c450
commit 6964bb5ee5
9 changed files with 255 additions and 118 deletions

View file

@ -89,13 +89,13 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
"61AC5F19-FBBA-4540-B96F-6561F1AB40A8";
char pkt[1024];
char *p = &pkt[0];
const char * pc;
const char *pc;
int len;
int okay = 0;
struct libwebsocket *wsi;
int n;
wsi = malloc(sizeof (struct libwebsocket));
wsi = malloc(sizeof(struct libwebsocket));
if (wsi == NULL)
return NULL;
@ -123,7 +123,7 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
}
wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
if (wsi->sock < 0) {
fprintf(stderr, "Unable to open socket\n");
goto bail1;
@ -139,11 +139,11 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
sizeof(struct sockaddr)) == -1) {
fprintf(stderr, "Connect failed");
goto bail1;
}
}
/*
* create the random key
*/
/*
* create the random key
*/
fd = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
if (fd < 1) {
@ -160,7 +160,7 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
}
close(fd);
lws_b64_encode_string(hash, 16, key_b64, sizeof key_b64);
lws_b64_encode_string(hash, 16, key_b64, sizeof key_b64);
/*
* 04 example client handshake
@ -283,7 +283,7 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
" Upgrade header '%s'\n",
wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
goto bail2;
}
}
strtolower(wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
if (strcmp(wsi->utf8_token[WSI_TOKEN_CONNECTION].token, "upgrade")) {

View file

@ -376,7 +376,7 @@ handshake_04(struct libwebsocket *wsi)
m += nonce_len;
strcpy(m, websocket_magic_guid_04_masking);
m += strlen(websocket_magic_guid_04_masking);
SHA1((unsigned char *)mask_summing_buf, m - mask_summing_buf,
wsi->masking_key_04);
@ -564,9 +564,9 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
return 0;
}
if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0)
goto bail;
break;
default:
break;
@ -576,5 +576,6 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
bail:
libwebsocket_close_and_free_session(wsi);
return -1;
}

View file

@ -86,7 +86,8 @@ libwebsocket_poll_connections(struct libwebsocket_context *this)
if (this->fds[client].revents & (POLLERR | POLLHUP)) {
debug("Session Socket %d %p (fd=%d) dead\n",
client, this->wsi[client], this->fds[client]);
client, (void *)this->wsi[client],
this->fds[client].fd);
libwebsocket_close_and_free_session(this->wsi[client]);
goto nuke_this;
@ -132,7 +133,7 @@ libwebsocket_poll_connections(struct libwebsocket_context *this)
continue;
/* only to clients connected to us */
if (wsi->client_mode)
continue;
@ -174,9 +175,9 @@ libwebsocket_poll_connections(struct libwebsocket_context *this)
/* service incoming data */
if (libwebsocket_read(this->wsi[client], buf, n) >= 0)
n = libwebsocket_read(this->wsi[client], buf, n);
if (n >= 0)
continue;
/*
* it closed and nuked wsi[client], so remove the
* socket handle and wsi from our service list
@ -184,19 +185,82 @@ libwebsocket_poll_connections(struct libwebsocket_context *this)
nuke_this:
debug("nuking wsi %p, fsd_count = %d\n",
this->wsi[client], this->fds_count - 1);
(void *)this->wsi[client], this->fds_count - 1);
this->fds_count--;
for (n = client; n < this->fds_count; n++) {
this->fds[n] = this->fds[n + 1];
this->wsi[n] = this->wsi[n + 1];
}
break;
return 0;
}
return 0;
}
/**
* libwebsocket_context_destroy() - Destroy the websocket context
* @this: Websocket context
*
* This function closes any active connections and then frees the
* context. After calling this, any further use of the context is
* undefined.
*/
void
libwebsocket_context_destroy(struct libwebsocket_context *this)
{
int client;
/* close listening skt and per-protocol broadcast sockets */
for (client = 0; client < this->fds_count; client++)
libwebsocket_close_and_free_session(this->wsi[client]);
#ifdef LWS_OPENSSL_SUPPORT
if (ssl_ctx)
SSL_CTX_free(ssl_ctx);
#endif
if (this)
free(this);
}
/**
* libwebsocket_service() - Service any pending websocket activity
* @this: Websocket context
* @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
* service otherwise block and service immediately, returning
* after the timeout if nothing needed service.
*
* This function deals with any pending websocket traffic, for three
* kinds of event. It handles these events on both server and client
* types of connection the same.
*
* 1) Accept new connections to our context's server
*
* 2) Perform pending broadcast writes initiated from other forked
* processes (effectively serializing asynchronous broadcasts)
*
* 3) Call the receive callback for incoming frame data received by
* server or client connections.
*
* You need to call this service function periodically to all the above
* functions to happen; if your application is single-threaded you can
* just call it in your main event loop.
*
* Alternatively you can fork a new process that asynchronously handles
* calling this service in a loop. In that case you are happy if this
* call blocks your thread until it needs to take care of something and
* would call it with a large nonzero timeout. Your loop then takes no
* CPU while there is nothing happening.
*
* If you are calling it in a single-threaded app, you don't want it to
* wait around blocking other things in your loop from happening, so you
* would call it with a timeout_ms of 0, so it returns immediately if
* nothing is pending, or as soon as it services whatever was pending.
*/
int
libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
@ -218,7 +282,7 @@ libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
n = poll(this->fds, this->fds_count, timeout_ms);
else
n = poll(&this->fds[1], this->fds_count - 1, timeout_ms);
if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) {
fprintf(stderr, "Listen Socket dead\n");
@ -369,6 +433,8 @@ fill_in_fds:
fatal:
fprintf(stderr, "service hits fatal\n");
/* close listening skt and per-protocol broadcast sockets */
for (client = 0; client < this->fds_count; client++)
close(this->fds[0].fd);
@ -376,7 +442,6 @@ fatal:
#ifdef LWS_OPENSSL_SUPPORT
SSL_CTX_free(ssl_ctx);
#endif
kill(0, SIGTERM);
if (this)
free(this);
@ -392,12 +457,12 @@ fatal:
/**
* libwebsocket_create_context() - Create the websocket handler
* @port: Port to listen on... you can use 0 to suppress listening on
* any port, that's what you want if you are not running a
* websocket server at all but just using it as a client
* any port, that's what you want if you are not running a
* websocket server at all but just using it as a client
* @protocols: Array of structures listing supported protocols and a protocol-
* specific callback for each one. The list is ended with an
* entry that has a NULL callback pointer.
* It's not const because we write the owning_server member
* It's not const because we write the owning_server member
* @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
* to listen using SSL, set to the filepath to fetch the
* server cert from, otherwise NULL for unencrypted
@ -644,10 +709,10 @@ libwebsocket_create_context(int port,
/**
* libwebsockets_fork_service_loop() - Optional helper function forks off
* a process for the websocket server loop.
* You don't have to use this but if not, you
* have to make sure you are calling
* libwebsocket_service periodically to service
* the websocket traffic
* You don't have to use this but if not, you
* have to make sure you are calling
* libwebsocket_service periodically to service
* the websocket traffic
* @this: server context returned by creation function
*/
@ -798,7 +863,7 @@ libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
* set up when the websocket server initializes
*/
n = send(protocol->broadcast_socket_user_fd, buf, len, 0);
n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
return n;
}

View file

@ -59,11 +59,11 @@ struct libwebsocket_context;
*
* This callback is the way the user controls what is served. All the
* protocol detail is hidden and handled by the library.
*
*
* For each connection / session there is user data allocated that is
* pointed to by "user". You set the size of this user data area when
* the library is initialized with libwebsocket_create_server.
*
*
* You get an opportunity to initialize user data when called back with
* LWS_CALLBACK_ESTABLISHED reason.
*
@ -77,45 +77,45 @@ struct libwebsocket_context;
* LWS_CALLBACK_RECEIVE: data has appeared for the server, it can be
* found at *in and is len bytes long
*
* LWS_CALLBACK_HTTP: an http request has come from a client that is not
* LWS_CALLBACK_HTTP: an http request has come from a client that is not
* asking to upgrade the connection to a websocket
* one. This is a chance to serve http content,
* for example, to send a script to the client
* which will then open the websockets connection.
* @in points to the URI path requested and
* @in points to the URI path requested and
* libwebsockets_serve_http_file() makes it very
* simple to send back a file to the client.
*/
extern int callback(struct libwebsocket * wsi,
enum libwebsocket_callback_reasons reason, void * user,
extern int callback(struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len);
/**
* struct libwebsocket_protocols - List of protocols and handlers server
* supports.
* struct libwebsocket_protocols - List of protocols and handlers server
* supports.
* @name: Protocol name that must match the one given in the client
* Javascript new WebSocket(url, 'protocol') name
* Javascript new WebSocket(url, 'protocol') name
* @callback: The service callback used for this protocol. It allows the
* service action for an entire protocol to be encapsulated in
* the protocol-specific callback
* service action for an entire protocol to be encapsulated in
* the protocol-specific callback
* @per_session_data_size: Each new connection using this protocol gets
* this much memory allocated on connection establishment and
* freed on connection takedown. A pointer to this per-connection
* allocation is passed into the callback in the 'user' parameter
* this much memory allocated on connection establishment and
* freed on connection takedown. A pointer to this per-connection
* allocation is passed into the callback in the 'user' parameter
* @owning_server: the server init call fills in this opaque pointer when
* registering this protocol with the server.
* registering this protocol with the server.
* @broadcast_socket_port: the server init call fills this in with the
* localhost port number used to forward broadcasts for this
* protocol
* localhost port number used to forward broadcasts for this
* protocol
* @broadcast_socket_user_fd: the server init call fills this in ... the main()
* process context can write to this socket to perform broadcasts
* (use the libwebsockets_broadcast() api to do this instead,
* it works from any process context)
* process context can write to this socket to perform broadcasts
* (use the libwebsockets_broadcast() api to do this instead,
* it works from any process context)
* @protocol_index: which protocol we are starting from zero
*
* This structure represents one protocol supported by the server. An
* array of these structures is passed to libwebsocket_create_server()
* allows as many protocols as you like to be handled by one server.
* This structure represents one protocol supported by the server. An
* array of these structures is passed to libwebsocket_create_server()
* allows as many protocols as you like to be handled by one server.
*/
struct libwebsocket_protocols {
@ -129,7 +129,7 @@ struct libwebsocket_protocols {
* below are filled in on server init and can be left uninitialized,
* no need for user to use them directly either
*/
struct libwebsocket_context *owning_server;
int broadcast_socket_port;
int broadcast_socket_user_fd;
@ -142,6 +142,9 @@ libwebsocket_create_context(int port,
const char *ssl_cert_filepath,
const char *ssl_private_key_filepath, int gid, int uid);
extern void
libwebsocket_context_destroy(struct libwebsocket_context *this);
extern int
libwebsockets_fork_service_loop(struct libwebsocket_context *this);
@ -188,7 +191,7 @@ libwebsockets_serve_http_file(struct libwebsocket *wsi, const char *file,
/* notice - you need the pre- and post- padding allocation for buf below */
extern int
libwebsockets_broadcast(const struct libwebsocket_protocols * protocol,
libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
unsigned char *buf, size_t len);
extern const struct libwebsocket_protocols *

View file

@ -149,7 +149,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
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;
@ -220,7 +220,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
return 0;
}
static unsigned char inline
static inline unsigned char
xor_mask(struct libwebsocket *wsi, unsigned char c)
{
c ^= wsi->masking_key_04[wsi->frame_mask_index++];
@ -286,7 +286,7 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
* wsi->frame_mask_04 will be our recirculating 20-byte XOR key
* for this frame
*/
SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04);
/*
@ -295,7 +295,7 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
*/
wsi->frame_mask_index = 0;
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
break;
@ -305,7 +305,7 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
*
* We ignore the possibility of extension data because we don't
* negotiate any extensions at the moment.
*
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-------+-+-------------+-------------------------------+
@ -334,23 +334,24 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
* 04 spec defines the opcode like this: (1, 2, and 3 are
* "control frame" opcodes which may not be fragmented or
* have size larger than 126)
*
* frame-opcode =
* %x0 ; continuation frame
* / %x1 ; connection close
* / %x2 ; ping
* / %x3 ; pong
* / %x4 ; text frame
* / %x5 ; binary frame
* / %x6-F ; reserved
*
* FIN (b7)
* frame-opcode =
* %x0 ; continuation frame
* / %x1 ; connection close
* / %x2 ; ping
* / %x3 ; pong
* / %x4 ; text frame
* / %x5 ; binary frame
* / %x6-F ; reserved
*
* FIN (b7)
*/
c = xor_mask(wsi, c);
if (c & 0x70) {
fprintf(stderr, "Frame has extensions set illegally 1\n");
fprintf(stderr,
"Frame has extensions set illegally 1\n");
/* kill the connection */
return -1;
}
@ -412,7 +413,6 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
break;
default:
// fprintf(stderr, "seen incoming 04 frame len %d\n", c);
wsi->rx_packet_length = c;
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
@ -605,51 +605,51 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
}
break;
case 4:
/*
* 04 logical framing from the spec (all this is masked when incoming
* and has to be unmasked)
*
* We ignore the possibility of extension data because we don't
* negotiate any extensions at the moment.
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-------+-+-------------+-------------------------------+
* |F|R|R|R| opcode|R| Payload len | Extended payload length |
* |I|S|S|S| (4) |S| (7) | (16/63) |
* |N|V|V|V| |V| | (if payload len==126/127) |
* | |1|2|3| |4| | |
* +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
* | Extended payload length continued, if payload len == 127 |
* + - - - - - - - - - - - - - - - +-------------------------------+
* | | Extension data |
* +-------------------------------+ - - - - - - - - - - - - - - - +
* : :
* +---------------------------------------------------------------+
* : Application data :
* +---------------------------------------------------------------+
*
* We pass payload through to userland as soon as we get it, ignoring
* FIN. It's up to userland to buffer it up if it wants to see a
* whole unfragmented block of the original size (which may be up to
* 2^63 long!)
*/
/*
* 04 logical framing from the spec (all this is masked when
* incoming and has to be unmasked)
*
* We ignore the possibility of extension data because we don't
* negotiate any extensions at the moment.
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-------+-+-------------+-------------------------------+
* |F|R|R|R| opcode|R| Payload len | Extended payload length |
* |I|S|S|S| (4) |S| (7) | (16/63) |
* |N|V|V|V| |V| | (if payload len==126/127) |
* | |1|2|3| |4| | |
* +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
* | Extended payload length continued, if payload len == 127 |
* + - - - - - - - - - - - - - - - +-------------------------------+
* | | Extension data |
* +-------------------------------+ - - - - - - - - - - - - - - - +
* : :
* +---------------------------------------------------------------+
* : Application data :
* +---------------------------------------------------------------+
*
* We pass payload through to userland as soon as we get it, ignoring
* FIN. It's up to userland to buffer it up if it wants to see a
* whole unfragmented block of the original size (which may be up to
* 2^63 long!)
*/
/*
* 04 spec defines the opcode like this: (1, 2, and 3 are
* "control frame" opcodes which may not be fragmented or
* have size larger than 126)
*
* frame-opcode =
* %x0 ; continuation frame
* / %x1 ; connection close
* / %x2 ; ping
* / %x3 ; pong
* / %x4 ; text frame
* / %x5 ; binary frame
* / %x6-F ; reserved
*
* FIN (b7)
* frame-opcode =
* %x0 ; continuation frame
* / %x1 ; connection close
* / %x2 ; ping
* / %x3 ; pong
* / %x4 ; text frame
* / %x5 ; binary frame
* / %x6-F ; reserved
*
* FIN (b7)
*/
if (c & 0x70) {
@ -1136,14 +1136,14 @@ send_raw:
if (use_ssl) {
n = SSL_write(wsi->ssl, buf - pre, len + pre + post);
if (n < 0) {
fprintf(stderr, "ERROR writing to socket");
fprintf(stderr, "ERROR writing to socket\n");
return -1;
}
} else {
#endif
n = send(wsi->sock, buf - pre, len + pre + post, 0);
n = send(wsi->sock, buf - pre, len + pre + post, MSG_NOSIGNAL);
if (n < 0) {
fprintf(stderr, "ERROR writing to socket");
fprintf(stderr, "ERROR writing to socket\n");
return -1;
}
#ifdef LWS_OPENSSL_SUPPORT
@ -1211,7 +1211,7 @@ int libwebsockets_serve_http_file(struct libwebsocket *wsi, const char *file,
/**
* libwebsockets_remaining_packet_payload() - Bytes to come before "overall"
* rx packet is complete
* rx packet is complete
* @wsi: Websocket instance (available from user callback)
*
* This function is intended to be called from the callback if the

View file

@ -51,16 +51,20 @@
#include <openssl/sha.h>
#include "libwebsockets.h"
//#define DEBUG
#if 0
#define DEBUG
#endif
#ifdef DEBUG
static inline void debug(const char *format, ...) {
static inline void debug(const char *format, ...)
{
va_list ap;
va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap);
}
#else
static inline void debug(const char *format, ...) { }
static inline void debug(const char *format, ...)
{
}
#endif
#ifdef LWS_OPENSSL_SUPPORT

View file

@ -1,3 +1,63 @@
<h2>libwebsocket_context_destroy - Destroy the websocket context</h2>
<i>void</i>
<b>libwebsocket_context_destroy</b>
(<i>struct libwebsocket_context *</i> <b>this</b>)
<h3>Arguments</h3>
<dl>
<dt><b>this</b>
<dd>Websocket context
</dl>
<h3>Description</h3>
<blockquote>
This function closes any active connections and then frees the
context. After calling this, any further use of the context is
undefined.
</blockquote>
<hr>
<h2>libwebsocket_service - Service any pending websocket activity</h2>
<i>int</i>
<b>libwebsocket_service</b>
(<i>struct libwebsocket_context *</i> <b>this</b>,
<i>int</i> <b>timeout_ms</b>)
<h3>Arguments</h3>
<dl>
<dt><b>this</b>
<dd>Websocket context
<dt><b>timeout_ms</b>
<dd>Timeout for poll; 0 means return immediately if nothing needed
service otherwise block and service immediately, returning
after the timeout if nothing needed service.
</dl>
<h3>Description</h3>
<blockquote>
This function deals with any pending websocket traffic, for three
kinds of event. It handles these events on both server and client
types of connection the same.
<p>
1) Accept new connections to our context's server
<p>
2) Perform pending broadcast writes initiated from other forked
processes (effectively serializing asynchronous broadcasts)
<p>
3) Call the receive callback for incoming frame data received by
server or client connections.
<p>
You need to call this service function periodically to all the above
functions to happen; if your application is single-threaded you can
just call it in your main event loop.
<p>
Alternatively you can fork a new process that asynchronously handles
calling this service in a loop. In that case you are happy if this
call blocks your thread until it needs to take care of something and
would call it with a large nonzero timeout. Your loop then takes no
CPU while there is nothing happening.
<p>
If you are calling it in a single-threaded app, you don't want it to
wait around blocking other things in your loop from happening, so you
would call it with a timeout_ms of 0, so it returns immediately if
nothing is pending, or as soon as it services whatever was pending.
</blockquote>
<hr>
<h2>libwebsocket_create_context - Create the websocket handler</h2>
<i>struct libwebsocket_context *</i>
<b>libwebsocket_create_context</b>

View file

@ -380,6 +380,8 @@ int main(int argc, char **argv)
libwebsocket_client_close(wsi_dumb);
libwebsocket_client_close(wsi_mirror);
libwebsocket_context_destroy(context);
return 0;
usage:

View file

@ -1,7 +1,7 @@
/*
* libwebsockets-test-server - libwebsockets test implementation
*
* Copyright (C) 2010 Andy Green <andy@warmcat.com>
* Copyright (C) 2010-2011 Andy Green <andy@warmcat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -233,7 +233,7 @@ int main(int argc, char **argv)
struct libwebsocket_context *context;
fprintf(stderr, "libwebsockets test server\n"
"(C) Copyright 2010 Andy Green <andy@warmcat.com> "
"(C) Copyright 2010-2011 Andy Green <andy@warmcat.com> "
"licensed under LGPL2.1\n");
while (n >= 0) {
@ -349,5 +349,7 @@ int main(int argc, char **argv)
#endif
libwebsocket_context_destroy(context);
return 0;
}