this->fds[this->fds_count++].events = POLLIN;
/* external POLL support via protocol 0 */
- this->protocols[0].callback(wsi,
+ this->protocols[0].callback(this, wsi,
LWS_CALLBACK_ADD_POLL_FD,
(void *)(long)wsi->sock, NULL, POLLIN);
/* call him back to inform him he is up */
- wsi->protocol->callback(wsi,
+ wsi->protocol->callback(this, wsi,
LWS_CALLBACK_CLIENT_ESTABLISHED,
wsi->user_space,
NULL, 0);
/* notify user code that we're ready to roll */
if (wsi->protocol->callback)
- wsi->protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
+ wsi->protocol->callback(wsi->protocol->owning_server,
+ wsi, LWS_CALLBACK_ESTABLISHED,
wsi->user_space, NULL, 0);
return 0;
/* notify user code that we're ready to roll */
if (wsi->protocol->callback)
- wsi->protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
+ wsi->protocol->callback(wsi->protocol->owning_server,
+ wsi, LWS_CALLBACK_ESTABLISHED,
wsi->user_space, NULL, 0);
return 0;
if (!wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len ||
!wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len) {
if (wsi->protocol->callback)
- (wsi->protocol->callback)(wsi,
+ (wsi->protocol->callback)(this, wsi,
LWS_CALLBACK_HTTP, wsi->user_space,
wsi->utf8_token[WSI_TOKEN_GET_URI].token, 0);
wsi->state = WSI_STATE_HTTP;
* have the opportunity to deny it
*/
- if ((wsi->protocol->callback)(wsi,
+ if ((wsi->protocol->callback)(wsi->protocol->owning_server, wsi,
LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
&wsi->utf8_token[0], NULL, 0)) {
fprintf(stderr, "User code denied connection\n");
struct libwebsocket *wsi)
{
int n;
+ int old_state;
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
LWS_SEND_BUFFER_POST_PADDING];
if (!wsi)
return;
- n = wsi->state;
+ old_state = wsi->state;
- if (n == WSI_STATE_DEAD_SOCKET)
+ if (old_state == WSI_STATE_DEAD_SOCKET)
return;
/* remove this fd from wsi mapping hashtable */
/* remove also from external POLL support via protocol 0 */
- this->protocols[0].callback(wsi,
+ this->protocols[0].callback(this, wsi,
LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
/*
* WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this
*/
- if (n == WSI_STATE_ESTABLISHED)
+ if (old_state == WSI_STATE_ESTABLISHED)
libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 0,
LWS_WRITE_CLOSE);
/* tell the user it's all over for this guy */
- if (wsi->protocol->callback && n == WSI_STATE_ESTABLISHED)
- wsi->protocol->callback(wsi, LWS_CALLBACK_CLOSED,
+ if (wsi->protocol->callback && old_state == WSI_STATE_ESTABLISHED)
+ wsi->protocol->callback(this, wsi, LWS_CALLBACK_CLOSED,
wsi->user_space, NULL, 0);
/* free up his allocations */
* yet so we issue this to protocols[0]
*/
- if ((this->protocols[0].callback)(wsi,
+ if ((this->protocols[0].callback)(this, wsi,
LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
(void*)(long)accept_fd, NULL, 0)) {
fprintf(stderr, "Callback denied network connection\n");
this->fds[this->fds_count++].fd = accept_fd;
/* external POLL support via protocol 0 */
- this->protocols[0].callback(new_wsi,
+ this->protocols[0].callback(this, new_wsi,
LWS_CALLBACK_ADD_POLL_FD,
(void *)(long)accept_fd, NULL, POLLIN);
this->fds[this->fds_count++].fd = accept_fd;
/* external POLL support via protocol 0 */
- this->protocols[0].callback(new_wsi,
+ this->protocols[0].callback(this, new_wsi,
LWS_CALLBACK_ADD_POLL_FD,
(void *)(long)accept_fd, NULL, POLLIN);
pollfd->events &= ~POLLOUT;
/* external POLL support via protocol 0 */
- this->protocols[0].callback(wsi,
+ this->protocols[0].callback(this, wsi,
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
(void *)(long)wsi->sock, NULL, POLLOUT);
- wsi->protocol->callback(wsi,
+ wsi->protocol->callback(this, wsi,
LWS_CALLBACK_CLIENT_WRITEABLE,
wsi->user_space,
NULL, 0);
/* broadcast it to this connection */
- new_wsi->protocol->callback(new_wsi,
+ new_wsi->protocol->callback(this, new_wsi,
LWS_CALLBACK_BROADCAST,
new_wsi->user_space,
buf + LWS_SEND_BUFFER_PRE_PADDING, len);
if (pollfd->revents & (POLLERR | POLLHUP)) {
- debug("Session Socket %p (fd=%d) dead\n",
+ fprintf(stderr, "Session Socket %p (fd=%d) dead\n",
(void *)wsi, pollfd->fd);
libwebsocket_close_and_free_session(this, wsi);
pollfd->events &= ~POLLOUT;
/* external POLL support via protocol 0 */
- this->protocols[0].callback(wsi,
+ this->protocols[0].callback(this, wsi,
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
(void *)(long)wsi->sock, NULL, POLLOUT);
- wsi->protocol->callback(wsi,
+ wsi->protocol->callback(this, wsi,
LWS_CALLBACK_CLIENT_WRITEABLE,
wsi->user_space,
NULL, 0);
if (n == 0) /* poll timeout */
return 0;
- if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) {
+ if (n < 0) {
/*
fprintf(stderr, "Listen Socket dead\n");
*/
*/
int
-libwebsocket_callback_on_writable(struct libwebsocket *wsi)
+libwebsocket_callback_on_writable(struct libwebsocket_context *this,
+ struct libwebsocket *wsi)
{
- struct libwebsocket_context *this = wsi->protocol->owning_server;
int n;
for (n = 0; n < this->fds_count; n++)
}
/* external POLL support via protocol 0 */
- this->protocols[0].callback(wsi,
+ this->protocols[0].callback(this, wsi,
LWS_CALLBACK_SET_MODE_POLL_FD,
(void *)(long)wsi->sock, NULL, POLLOUT);
wsi = this->fd_hashtable[n].wsi[m];
if (wsi->protocol == protocol)
- libwebsocket_callback_on_writable(wsi);
+ libwebsocket_callback_on_writable(this, wsi);
}
}
if (enable)
/* external POLL support via protocol 0 */
- this->protocols[0].callback(wsi,
+ this->protocols[0].callback(this, wsi,
LWS_CALLBACK_SET_MODE_POLL_FD,
(void *)(long)wsi->sock, NULL, POLLIN);
else
/* external POLL support via protocol 0 */
- this->protocols[0].callback(wsi,
+ this->protocols[0].callback(this, wsi,
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
(void *)(long)wsi->sock, NULL, POLLIN);
this->fds[this->fds_count++].events = POLLIN;
/* external POLL support via protocol 0 */
- this->protocols[0].callback(wsi,
+ this->protocols[0].callback(this, wsi,
LWS_CALLBACK_ADD_POLL_FD,
(void *)(long)sockfd, NULL, POLLIN);
this->fds_count++;
/* external POLL support via protocol 0 */
- this->protocols[0].callback(wsi,
+ this->protocols[0].callback(this, wsi,
LWS_CALLBACK_ADD_POLL_FD,
(void *)(long)fd, NULL, POLLIN);
}
if (wsi->protocol != protocol)
continue;
- wsi->protocol->callback(wsi,
+ wsi->protocol->callback(this, wsi,
LWS_CALLBACK_BROADCAST,
wsi->user_space,
buf, len);
/* document the generic callback (it's a fake prototype under this) */
/**
* callback() - User server actions
+ * @this: Websockets context
* @wsi: Opaque websocket instance pointer
* @reason: The reason for the call
* @user: Pointer to per-session user data allocated by library
* pollfd struct for this socket descriptor. If you are using the
* internal polling loop, you can just ignore it.
*/
-extern int callback(struct libwebsocket *wsi,
+extern int callback(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len);
struct libwebsocket_protocols {
const char *name;
- int (*callback)(struct libwebsocket *wsi,
+ int (*callback)(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len);
size_t per_session_data_size;
libwebsockets_get_protocol(struct libwebsocket *wsi);
extern int
-libwebsocket_callback_on_writable(struct libwebsocket *wsi);
+libwebsocket_callback_on_writable(struct libwebsocket_context *this,
+ struct libwebsocket *wsi);
extern int
libwebsocket_callback_on_writable_all_protocol(
/* no payload challenge in 01 + */
if (wsi->utf8_token[WSI_TOKEN_VERSION].token_len &&
- atoi(wsi->utf8_token[WSI_TOKEN_VERSION].token) > 0) {
- wsi->utf8_token[wsi->parser_state].token_len = 0;
- free(wsi->utf8_token[wsi->parser_state].token);
- wsi->utf8_token[wsi->parser_state].token = NULL;
+ atoi(wsi->utf8_token[WSI_TOKEN_VERSION].token) > 0) {
+ wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len = 0;
+ free(wsi->utf8_token[WSI_TOKEN_CHALLENGE].token);
+ wsi->utf8_token[WSI_TOKEN_CHALLENGE].token = NULL;
}
/* For any supported protocol we have enough payload */
break;
issue:
if (wsi->protocol->callback)
- wsi->protocol->callback(wsi, LWS_CALLBACK_RECEIVE,
+ wsi->protocol->callback(wsi->protocol->owning_server,
+ wsi, LWS_CALLBACK_RECEIVE,
wsi->user_space,
&wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
wsi->rx_user_buffer_head);
wsi->rx_user_buffer_head] = '\0';
if (wsi->protocol->callback)
- wsi->protocol->callback(wsi, LWS_CALLBACK_RECEIVE,
+ wsi->protocol->callback(wsi->protocol->owning_server,
+ wsi, LWS_CALLBACK_RECEIVE,
wsi->user_space,
&wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
wsi->rx_user_buffer_head);
break;
issue:
if (wsi->protocol->callback)
- wsi->protocol->callback(wsi,
+ wsi->protocol->callback(wsi->protocol->owning_server,
+ wsi,
LWS_CALLBACK_CLIENT_RECEIVE,
wsi->user_space,
&wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
*/
if (wsi->protocol->callback)
- wsi->protocol->callback(wsi, callback_action,
+ wsi->protocol->callback(wsi->protocol->owning_server,
+ wsi, callback_action,
wsi->user_space,
&wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
wsi->rx_user_buffer_head);
<h2>libwebsocket_callback_on_writable - Request a callback when this socket becomes able to be written to without blocking *</h2>
<i>int</i>
<b>libwebsocket_callback_on_writable</b>
-(<i>struct libwebsocket *</i> <b>wsi</b>)
+(<i>struct libwebsocket_context *</i> <b>this</b>,
+<i>struct libwebsocket *</i> <b>wsi</b>)
<h3>Arguments</h3>
<dl>
<dt><b>wsi</b>
<h2>callback - User server actions</h2>
<i>int</i>
<b>callback</b>
-(<i>struct libwebsocket *</i> <b>wsi</b>,
+(<i>struct libwebsocket_context *</i> <b>this</b>,
+<i>struct libwebsocket *</i> <b>wsi</b>,
<i>enum libwebsocket_callback_reasons</i> <b>reason</b>,
<i>void *</i> <b>user</b>,
<i>void *</i> <b>in</b>,
<i>size_t</i> <b>len</b>)
<h3>Arguments</h3>
<dl>
+<dt><b>this</b>
+<dd>Websockets context
<dt><b>wsi</b>
<dd>Opaque websocket instance pointer
<dt><b>reason</b>
<h2>struct libwebsocket_protocols - List of protocols and handlers server supports.</h2>
<b>struct libwebsocket_protocols</b> {<br>
<i>const char *</i> <b>name</b>;<br>
- <i>int (*</i><b>callback</b>) <i>(struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user,void *in, size_t len)</i>;<br>
+ <i>int (*</i><b>callback</b>) <i>(struct libwebsocket_context * this,struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user,void *in, size_t len)</i>;<br>
<i>size_t</i> <b>per_session_data_size</b>;<br>
<i>struct libwebsocket_context *</i> <b>owning_server</b>;<br>
<i>int</i> <b>broadcast_socket_port</b>;<br>
/* dumb_increment protocol */
static int
-callback_dumb_increment(struct libwebsocket *wsi,
+callback_dumb_increment(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
static int
-callback_lws_mirror(struct libwebsocket *wsi,
+callback_lws_mirror(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
* LWS_CALLBACK_CLIENT_WRITEABLE will come next service
*/
- libwebsocket_callback_on_writable(wsi);
+ libwebsocket_callback_on_writable(this, wsi);
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
/* get notified as soon as we can write again */
- libwebsocket_callback_on_writable(wsi);
+ libwebsocket_callback_on_writable(this, wsi);
/*
* without at least this delay, we choke the browser
#define MAX_PING_CLIENTS 256
#define PING_RINGBUFFER_SIZE 256
+static struct libwebsocket *ping_wsi[MAX_PING_CLIENTS];
static unsigned int interval_us = 1000000;
static unsigned int size = 64;
static int flood;
static int
-callback_lws_mirror(struct libwebsocket *wsi,
+callback_lws_mirror(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
struct per_session_data__ping *psd = user;
switch (reason) {
+ case LWS_CALLBACK_CLOSED:
+
+ fprintf(stderr, "LWS_CALLBACK_CLOSED on %p\n", (void *)wsi);
+
+ /* remove closed guy */
+
+ for (n = 0; n < clients; n++)
+ if (ping_wsi[n] == wsi) {
+ clients--;
+ while (n < clients) {
+ ping_wsi[n] = ping_wsi[n + 1];
+ n++;
+ }
+ }
+
+ break;
+
case LWS_CALLBACK_CLIENT_ESTABLISHED:
psd->rx_count = 0;
* LWS_CALLBACK_CLIENT_WRITEABLE will come next service
*/
- libwebsocket_callback_on_writable(wsi);
+ libwebsocket_callback_on_writable(this, wsi);
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
int port = 7681;
int use_ssl = 0;
struct libwebsocket_context *context;
- struct libwebsocket *wsi[MAX_PING_CLIENTS];
char protocol_name[256];
char ip[30];
struct sigaction sa;
/* create client websockets using dumb increment protocol */
for (n = 0; n < clients; n++) {
- wsi[n] = libwebsocket_client_connect(context, address, port,
- use_ssl, "/", address,
+ ping_wsi[n] = libwebsocket_client_connect(context, address,
+ port, use_ssl, "/", address,
"origin", protocols[PROTOCOL_LWS_MIRROR].name,
ietf_version);
- if (wsi[n] == NULL) {
+ if (ping_wsi[n] == NULL) {
fprintf(stderr, "client connnection %d failed to "
"connect\n", n);
return 1;
}
}
- libwebsockets_get_peer_addresses(libwebsocket_get_socket_fd(wsi[0]),
+ libwebsockets_get_peer_addresses(
+ libwebsocket_get_socket_fd(ping_wsi[0]),
peer_name, sizeof peer_name, ip, sizeof ip);
fprintf(stderr, "Websocket PING %s (%s) %d bytes of data.\n",
gettimeofday(&tv, NULL);
l = (tv.tv_sec * 1000000) + tv.tv_usec;
+ /* servers can hang up on us */
+
+ if (clients == 0) {
+ n = -1;
+ continue;
+ }
if (!interrupted_time) {
if ((l - oldus) > interval_us) {
for (n = 0; n < clients; n++)
libwebsocket_callback_on_writable(
- wsi[n]);
+ context, ping_wsi[n]);
oldus = l;
}
} else
/* this protocol server (always the first one) just knows how to do HTTP */
-static int callback_http(struct libwebsocket *wsi,
+static int callback_http(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len)
{
};
static int
-callback_dumb_increment(struct libwebsocket *wsi,
+callback_dumb_increment(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
static int
-callback_lws_mirror(struct libwebsocket *wsi,
+callback_lws_mirror(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
case LWS_CALLBACK_ESTABLISHED:
pss->ringbuffer_tail = ringbuffer_head;
pss->wsi = wsi;
- libwebsocket_callback_on_writable(wsi);
+ libwebsocket_callback_on_writable(this, wsi);
break;
case LWS_CALLBACK_CLIENT_WRITEABLE:
MAX_MESSAGE_QUEUE) < (MAX_MESSAGE_QUEUE - 15))
libwebsocket_rx_flow_control(wsi, 1);
- libwebsocket_callback_on_writable(wsi);
+ libwebsocket_callback_on_writable(this, wsi);
}
break;
/* this protocol server (always the first one) just knows how to do HTTP */
-static int callback_http(struct libwebsocket *wsi,
+static int callback_http(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len)
{
};
static int
-callback_dumb_increment(struct libwebsocket *wsi,
+callback_dumb_increment(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
static int
-callback_lws_mirror(struct libwebsocket *wsi,
+callback_lws_mirror(struct libwebsocket_context * this,
+ struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
MAX_MESSAGE_QUEUE) < (MAX_MESSAGE_QUEUE - 15))
libwebsocket_rx_flow_control(wsi, 1);
- libwebsocket_callback_on_writable(wsi);
+ libwebsocket_callback_on_writable(this, wsi);
}
break;