WebSocket disconnection callback

1,815 views
Skip to first unread message

james....@jartechnologies.com

unread,
Feb 28, 2013, 6:26:28 AM2/28/13
to mongoos...@googlegroups.com
Hi,

I'm using one of the latest mongoose source trees and have had good success with WebSockets (its much better than libwebsocket) but I need to know when a client is disconnected (i.e. the browser is closed and the TCP connection goes away)

I don't see any internal mechanism for handling this and providing a callback, I assume I can easily add one by checking the return values of send() and recv() for -1 and creating a new event if the connection is WebSocket related?

Anyone see any problems with this?

James

jmarias...@gmail.com

unread,
Feb 28, 2013, 6:57:54 AM2/28/13
to mongoos...@googlegroups.com
Hi James,
you can detect a client disconnect when, in your websocket_data_handler callback, msg_len is equal 0.
Jose

James Hunter

unread,
Feb 28, 2013, 7:00:45 AM2/28/13
to mongoos...@googlegroups.com
Hi Jose,

I'm a big fan of events, is there any problem with adding an event call back to the close connection call? This seems to work fine for me

static void close_connection(struct mg_connection *conn) {
  conn->must_close = 1;
  if (conn->client.sock != INVALID_SOCKET) {
    close_socket_gracefully(conn);
  }
#ifndef NO_SSL
  // Must be done AFTER socket is closed
  if (conn->ssl != NULL) {
    SSL_free(conn->ssl);
  }
#endif

  /* If its WebSocket, call our disconnected event */
  if (is_websocket_request( (const struct mg_connection*) conn))
  {
      if (conn->ctx->callbacks.websocket_disconnect != NULL)
          conn->ctx->callbacks.websocket_disconnect(conn) ;
  }


}


Thanks,

James
--
You received this message because you are subscribed to a topic in the Google Groups "mongoose-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mongoose-users/Rrhp7uLS7fg/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to mongoose-user...@googlegroups.com.
To post to this group, send email to mongoos...@googlegroups.com.
Visit this group at http://groups.google.com/group/mongoose-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 


--

James Hunter
JAR Technologies
Mob. +44 (0) 7738 851417

Office. +44 (0) 2890 23 33 22

www.JarTechnologies.com

JAR Technologies is a UK registered limited company, privately held.  This email is from JAR Technologies Ltd. The email and any files transmitted with it are confidential and privileged and intended solely for the use of the individual or entity to whom they are addressed. If you have received the email in error please notify general....@jartechnologies.com and delete the e-mail from your system.



jmarias...@gmail.com

unread,
Feb 28, 2013, 9:55:10 AM2/28/13
to mongoos...@googlegroups.com
Hi James,

sure, but you are dealing with the TCP closing handshake only. In the websocket protocol there is a dedicated closing handshake to, as the RFC says, "complement the TCP closing handshake (FIN/ACK), on the basis that the TCP closing handshake is not always reliable end-to-end, especially in the presence of intercepting proxies and other intermediaries". The websockets closing handshake consists in sending the client a frame with opcode 0x8 with an empty (optional) body so I think you'll need to invoke your websocket_disconnect callback in that case too.

Jose

jmarias...@gmail.com

unread,
Feb 28, 2013, 10:31:03 AM2/28/13
to mongoos...@googlegroups.com
I think the function static int websocket_data_handler(struct mg_connection *conn) in mongoose.c would be the place where to look for an opcode 0x8 to call websocket_disconnect
Jose

James Hunter

unread,
Feb 28, 2013, 12:12:14 PM2/28/13
to mongoos...@googlegroups.com
Hi Jose,

My current test is to open a websocket on a JS page, and close the pages TAB.. I see no opcode 0x8, in-fact break pointing on handling any incoming request shows nothing comes from the browser at all..

James

jmarias...@gmail.com

unread,
Mar 1, 2013, 4:36:34 AM3/1/13
to mongoos...@googlegroups.com
Hi James,

It's the browser who is on charge of sending a closing handshake frame either when, from JS, you invoke websocket.close() or when you close the current tab. I'm afraid the browser you are testing with is not sending the closing handshake frame when you close the tab. I have tested from http://www.websocket.org/echo.htm pointing to my websocket.c mongoose example and I can see a closing frame when either pushing the disconnect button or closing the tab if I test with firefox 19, but it's true, with chrome 25, it seems to work when pushing the disconnect button only. I'm break pointing on websocket_data_handler() in websocket.c.

Jose

jmarias...@gmail.com

unread,
Mar 1, 2013, 8:00:42 AM3/1/13
to mongoos...@googlegroups.com
Hi James,
I recommend to take a look https://github.com/mark-webster/mongoose
Mark improves the websockets deal and you can detect a closing disconnect with something as "if (frame->type.opcode == 0x8)" in the websocket_data_callback()
We''ll have to wait for Sergey's feedback but meanwhile it works for me.
Regards
Jose

James Hunter

unread,
Mar 2, 2013, 3:16:32 PM3/2/13
to mongoos...@googlegroups.com
Hi,

More experimenting with websockets, I'm using websockets for a long-lived connection that may be open for hours.. What I've noticed that mongoose will close the websocket connection after the "request_timeout_ms" of "30000" has passed, I assume this a bug that needs to be fixed? If I set the connection to be keep-alive the websocket will stay open but all normal HTTP requests appear to get stuck open (i.e. after 50 HTTP requests, which happens to be the default thread count) any further requests get a http 500 error..

Thanks,

James

James Hunter

unread,
Mar 2, 2013, 3:27:45 PM3/2/13
to mongoos...@googlegroups.com
Hi All,

It seems an update to the latest github source has fixed the issue.

James
--
You received this message because you are subscribed to a topic in the Google Groups "mongoose-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mongoose-users/Rrhp7uLS7fg/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to mongoose-user...@googlegroups.com.
To post to this group, send email to mongoos...@googlegroups.com.
Visit this group at http://groups.google.com/group/mongoose-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

James Hunter

unread,
Mar 10, 2013, 10:43:27 AM3/10/13
to mongoos...@googlegroups.com
Hi,

I'm using WebSocket for long lived connection between a Javascript
application and my mongoose server, its all works excellently until I
try to any real debugging on the server-side.

With the application running when I try to install or enable a
breakpoint, I see a disconnection of the WebSocket (I use my own custom
code in close_connection() to send an event to my user process.. its the
only sure fire way of knowing if the websocket has gone away - or
technically the TCP socket).

If the breakpoints are enabled before the application is launched there
is no problems, the break-point will fire correctly and I can resume
without a loss of connection.

Here's some things I notice about the problems:

1. The SIGINT signal that is called by GDB to stall all threads whilst
it inserts the break-point.
2. When the breakpoint is installed the read_websocket() will exit (or
break) and that will lead to the closure
3. If I breakpoint after the read_websocket() to detect the closure, and
"move" the PC (Program Counter) back to the read_websocket() things
continue on fine.. so the socket is not "gone", nor do I return zero
from the user data event to signal the closure.

Anyone any comments on this problems, or recommendations?

Thanks,

James

James Hunter

unread,
Mar 10, 2013, 1:33:24 PM3/10/13
to mongoos...@googlegroups.com
Hi,

I though I would provide the solution as others may run into this problem...

The SIGINT is causing the recv() ( in pull() ) to fail with a errno = 4 (interrupted system call), which obviously makes perfect sense. I personally have modified the pull() function to handle this error and to retry recv() if its detected.

James

Sergey Lyubka

unread,
Mar 10, 2013, 3:55:44 PM3/10/13
to mongoos...@googlegroups.com
On Sun, Mar 10, 2013 at 5:33 PM, James Hunter <james....@jartechnologies.com> wrote:
Hi,

I though I would provide the solution as others may run into this problem...

The SIGINT is causing the recv() ( in pull() ) to fail with a errno = 4 (interrupted system call), which obviously makes perfect sense. I personally have modified the pull() function to handle this error and to retry recv() if its detected.

Mind sending a pull request?
recv() could be interrupted by other signal IMO.

About disconnections. Are they happening after 30 seconds?
This is the default read/write timeout for the accepted sockets.
See request_timeout_ms option. Increase it if required.
 

James

Hi,

I'm using WebSocket for long lived connection between a Javascript application and my mongoose server, its all works excellently until I try to any real debugging on the server-side.

With the application running when I try to install or enable a breakpoint, I see a disconnection of the WebSocket (I use my own custom code in close_connection() to send an event to my user process.. its the only sure fire way of knowing if the websocket has gone away - or technically the TCP socket).

If the breakpoints are enabled before the application is launched there is no problems, the break-point will fire correctly and I can resume without a loss of connection.

Here's some things I notice about the problems:

1. The SIGINT signal that is called by GDB to stall all threads whilst it inserts the break-point.
2. When the breakpoint is installed the read_websocket() will exit (or break) and that will lead to the closure
3. If I breakpoint after the read_websocket() to detect the closure, and "move" the PC (Program Counter) back to the read_websocket() things continue on fine.. so the socket is not "gone", nor do I return zero from the user data event to signal the closure.

Anyone any comments on this problems, or recommendations?

Thanks,

James



--

James Hunter
JAR Technologies
Mob. +44 (0) 7738 851417

Office. +44 (0) 2890 23 33 22

www.JarTechnologies.com

JAR Technologies is a UK registered limited company, privately held.  This email is from JAR Technologies Ltd. The email and any files transmitted with it are confidential and privileged and intended solely for the use of the individual or entity to whom they are addressed. If you have received the email in error please notify general....@jartechnologies.com and delete the e-mail from your system.



--
You received this message because you are subscribed to the Google Groups "mongoose-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mongoose-user...@googlegroups.com.

James Hunter

unread,
Mar 10, 2013, 4:03:31 PM3/10/13
to mongoos...@googlegroups.com
Hi,

I'll see about a pull request tomorrow (though its the first time ive created a pull request).

Im not experiencing any other disconnection / timeout issue since getting the latest code, and my websocket traffic is almost continous (as its a game).

Thanks,
James
You received this message because you are subscribed to a topic in the Google Groups "mongoose-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mongoose-users/Rrhp7uLS7fg/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to mongoose-user...@googlegroups.com.

jmarias...@gmail.com

unread,
Mar 12, 2013, 4:54:17 AM3/12/13
to mongoos...@googlegroups.com
Hi Sergey,
the request_timeout_ms configuration option is global for all accepted sockets. I think it's fine for regular http connections but it could be a bit short time for long lived websocket connections therefore I wonder if it could be possible to override it in a socket basis in such way you can leave the 30000ms value by default (or whatever you configure in the global option) and optionally being able to set another longer value in the websocket_ready_handler() for example.
Thanks
Jose
Reply all
Reply to author
Forward
0 new messages