Question

Solved

My solution for the read problem was to move the code to a handler, and there using HDL_AFTER_READ state to handle the websocket connection. After putting handshake to reply buffer, return 2 to send it. Additionally you might want to change KALIVE_TMO, as that dictates after how much time the connection is closed if there is no traffic. I've still not gotten the whole websocket thing finished, as I can't seem to identify the connection afterwards (US_REQUEST_DATA doesn't work here), but that's a different topic and I only mention it here so people know why I'm not (yet) updating my code.

-- Original question:

I'm currently in the process of trying to get websockets to work with GWAN (http://gwan.com/) 4.3.14. So far I've gotten past the connection handshake with firefox/chrome, but afterwards the connection closes after a few seconds.

I already have a guess why this is happening, which is probably the missing PONG from the server, but my problem now is, I can't figure out how to read more data from the client from a servlet. I've found that it seems to be possible to do that from a handler (at least according to the manual, which I've found to be wrong/outdated a couple of times), but there also seem to be a couple of possibilities using servlets which I'd prefer.

So far I've tried: - wake_up with WK_FD on file_fd of get_env(argv, HTTP_HEADERS) ; wake_up doesn't seem to work no matter what I do (tried using WK_MS with values between 1000 and 100000 with no difference - servlet was called again instantly after returning RC_NOHEADERS + RC_STREAMING) - recv on get_env(argv, CLIENT_SOCKET) ; here recv tells me that whatever I'm operating on (int with value 0) is not a socket (never got CLIENT_SOCKET to work in the past either, I must be doing something wrong there?) - simple sleep(1) (up to 20) calls - READ_XBUF does not have new data afterwards, even if wireshark on the client + tcpdump on the server tells me that there is data going from client to server

I've also tried using different handler states returning 1 for "read more data from client" in the past (some versions ago, so maybe this is already fixed - but as said, I'd prefer a solution with servlets). This didn't even work with a simple ajax post request (most browsers send post data in a second tcp packet when using post, so you don't initially get the payload with gwan), so no luck there either.

P.S: On a sidenote (as I know Gil is answering most if not all gwan related questions here), I've wanted to sign up for a hobbyist support contract on GWAN website a few times already, but I've not found out how to get past the initial price list (which isn't available in euro as of the time of writing this).

I'll gladly provide any kind of code which could help solving this,

Thank you very much for your time.

Edit: Code of main function (I know that the termination code is wrong, so please ignore it for now, as that is also not the reason for my question here)

printf("\n---------- RUN ---------\n");


xbuf_t *reply = get_reply(argv);


xbuf_t *request = (xbuf_t *)get_env(argv, READ_XBUF);


   void **pdata = (void**)get_env(argv, US_REQUEST_DATA);


   if (!pdata[0]) { // no request data yet, send upgrade to websocket

  char *upgrade = xbuf_findstr(request, "\r\nUpgrade: websocket\r\n"); // FF only sends this ; chrome also sends "Connection: Upgrade\r\n" afterwards



  if (upgrade != NULL) { // correct upgrade header found?
     const char keyHeader[] ="\r\nSec-WebSocket-Key: ";

     char *key = xbuf_findstr(request, (char *)keyHeader);

     if (key != NULL && (key += sizeof(keyHeader) - 1) != NULL && (request->len - (u32)(key - request->ptr)) >= (u32)23) { // correct key header found? + sanity check
        char websocketGUID[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // 8 + 4 + 4 + 4 + 12 = 32 + 4 bytes for '-' = 36

        const char data[] = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %20B\r\n\r\n";

        // 36 + 24
        char keyCompose[60];
        strncpy(keyCompose, key, 24);
        strncpy(keyCompose + 24, websocketGUID, 36);

        u8 sha[20];
        sha1_t ctx;
        sha1_init(&ctx);
        sha1_add(&ctx, (u8 *)keyCompose, 60);

        sha1_end(&ctx, sha);


        xbuf_xcat(reply, (char *)data, sha);

        pdata[0] = (void*)1;

        printf("Init.");

        return RC_NOHEADERS + RC_STREAMING; // don't build headers automatically
     }
  }


   } else { // websocket connection here


 const unsigned char websocketTerm[2] = { 0x00, 0xFF }; // websocket close = opcode 0x8
  printf("Streaming!\n"); // TODO: next find way to get next user input (best would be to only wake up on user input or if we have something to send?)

  char *buf = alloca(2);
  buf[0] = 0; buf[1] = 0;

  pdata[0]++;

  if ((int)(pdata[0]) >= 20) {
  xbuf_ncat(reply, (char *)websocketTerm, 2);

  printf("Fin.\n");

  pdata[0] = 0; // cleanup

  return RC_NOHEADERS;
  }

  return RC_NOHEADERS + RC_STREAMING;
   }

   xbuf_cat(reply, "test");

   return 403;
Was it helpful?

Solution

G-WAN Servlets are clearly not the most efficient way to implement a network protocol.

Since websockets are breaking the HTTP protocol, you should rater use a G-WAN Handler.

And G-WAN Protocol Handlers are dedicated to this task. Documentation and examples are lacking in this area because we have had to focus on G-WAN-based applications recently.

OTHER TIPS

Without any code you're using it's practically impossible to debug where you might be going wrong.

Also, I've wondered about the payment method as well and I'm sure he will be using PayPal or some other payment gateway where payments would be automatically converted from your own currency to the CHF. If it's straight credit card merchant authorizing, there may incur an exchange fee from your credit card company, usually 3%.

What about using this library ? https://github.com/payden/libwebsock instead of trying to re-write the full websocket implementation ?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top