1

I had installed Apache-WebSocket into my Wamp Apache with great difficulty. That problem is not solved yet, as the build still has errors, but since it generated an .so file, I included that into modules and included that into Apache. The problem is that since I have never worked with WebSockets under Apache, I do not know how to start to work with it. I see that it is possible with C, but I would prefer to write PHP. Is that possible?

P.S.

Example Page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    <title>WebSocket Dumb Increment</title>
    <script type="text/javascript">
    <!--
      var ws;

      if ((typeof(WebSocket) == 'undefined') &&
          (typeof(MozWebSocket) != 'undefined')) {
        WebSocket = MozWebSocket;
      }

      function init() {
        ws = new WebSocket(((window.location.protocol == "https:") ? "wss:" : "ws:") + "//" + window.location.host + "/dumb-increment", "dumb-increment-protocol");
        ws.onopen = function(event) {
          document.getElementById("main").style.visibility = "visible";
          document.getElementById("connected").innerHTML = "Connected to WebSocket server";
        };
        ws.onmessage = function(event) {
          document.getElementById("output").innerHTML = event.data;
        };
        ws.onerror = function(event) { alert("Received error"); };
        ws.onclose = function(event) {
          ws = null;
          document.getElementById("main").style.visibility = "hidden";
          document.getElementById("connected").innerHTML = "Connection Closed";
        }
      }

      function send(message) {
        if (ws) {
          ws.send(message);
        }
      }
    // -->
    </script>
  </head>
  <body onload="init();">
    <h1>WebSocket Dumb Increment</h1>
    <div id="connected">Not Connected</div>
    <div id="main" style="visibility:hidden">
    <button type="button" onclick="send('reset\n')">Reset</button><br/>
    Count:<div id="output"></div>
    </div>
  </body>
</html>

Example Module in C:

/*
 * Copyright 2011 self.disconnect
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include "httpd.h"
#include "apr_thread_proc.h"

#include "websocket_plugin.h"

typedef struct _DumbIncrementData {
  const WebSocketServer *server;
  apr_pool_t *pool;
  apr_thread_t *thread;
  int counter;
  int active;
} DumbIncrementData;

void* APR_THREAD_FUNC dumb_increment_run(apr_thread_t *thread, void *data)
{
  char buffer[64];
  DumbIncrementData *dib = (DumbIncrementData *) data;

  if (dib != NULL) {
    /* Keep sending messages as long as the connection is active */
    while (dib->active) {
      apr_sleep(50000); /* 50ms */
      sprintf(buffer,"%d", dib->counter++);
      dib->server->send(dib->server, MESSAGE_TYPE_TEXT, (unsigned char *)buffer, strlen(buffer));
    }
  }
  return NULL;
}

void * CALLBACK dumb_increment_on_connect(const WebSocketServer *server)
{
  DumbIncrementData *dib = NULL;

  if ((server != NULL) && (server->version == WEBSOCKET_SERVER_VERSION_1)) {
    /* Get access to the request_rec strucure for this connection */
    request_rec *r = server->request(server);

    if (r != NULL) {
      apr_pool_t *pool = NULL;
      size_t i, count = server->protocol_count(server);

      /* Only support "dumb-increment-protocol" */
      for (i = 0; i < count; i++) {
        const char *protocol = server->protocol_index(server, i);

        if ((protocol != NULL) &&
            (strcmp(protocol, "dumb-increment-protocol") == 0)) {
          /* If the client can speak the protocol, set it in the response */
          server->protocol_set(server, protocol);
          break;
        }
      }
      /* If the protocol negotiation worked, create a new memory pool */
      if ((i < count) &&
          (apr_pool_create(&pool, r->pool) == APR_SUCCESS)) {
        /* Allocate memory to hold the dumb increment state */
        if ((dib = (DumbIncrementData *) apr_palloc(pool, sizeof(DumbIncrementData))) != NULL) {
          apr_thread_t *thread = NULL;
          apr_threadattr_t *thread_attr = NULL;

          dib->server = server;
          dib->pool = pool;
          dib->thread = NULL;
          dib->counter = 0;
          dib->active = 1;

          /* Create a non-detached thread that will perform the work */
          if ((apr_threadattr_create(&thread_attr, pool) == APR_SUCCESS) &&
              (apr_threadattr_detach_set(thread_attr, 0) == APR_SUCCESS) &&
              (apr_thread_create(&thread, thread_attr, dumb_increment_run, dib, pool) == APR_SUCCESS)) {
            dib->thread = thread;
            /* Success */
            pool = NULL;
          } else {
            dib = NULL;
          }
        }
        if (pool != NULL) {
          apr_pool_destroy(pool);
        }
      }
    }
  }
  return dib;
}

static size_t CALLBACK dumb_increment_on_message(void *plugin_private, const WebSocketServer *server,
    const int type, unsigned char *buffer, const size_t buffer_size)
{
  DumbIncrementData *dib = (DumbIncrementData *) plugin_private;

  if ((dib != 0) &&
      (buffer != 0) && (buffer_size == 6) &&
      (buffer[0] == 'r') &&
      (buffer[1] == 'e') &&
      (buffer[2] == 's') &&
      (buffer[3] == 'e') &&
      (buffer[4] == 't') &&
      (buffer[5] == '\n')) {
    /* If a message containing "reset\n" is received, reset the counter */
    dib->counter = 0;
  }
  return 0;
}

void CALLBACK dumb_increment_on_disconnect(void *plugin_private, const WebSocketServer *server)
{
  DumbIncrementData *dib = (DumbIncrementData *) plugin_private;

  if (dib != 0) {
    /* When disconnecting, inform the thread that it is time to stop */
    dib->active = 0;
    if (dib->thread) {
      apr_status_t status;

      /* Wait for the thread to finish */
      status = apr_thread_join(&status, dib->thread);
    }
    apr_pool_destroy(dib->pool);
  }
}

/*
 * Since we are returning a pointer to static memory, there is no need for a
 * "destroy" function.
 */

static WebSocketPlugin s_plugin = {
  sizeof(WebSocketPlugin),
  WEBSOCKET_PLUGIN_VERSION_0,
  NULL, /* destroy */
  dumb_increment_on_connect,
  dumb_increment_on_message,
  dumb_increment_on_disconnect
};

extern EXPORT WebSocketPlugin * CALLBACK dumb_increment_init()
{
  return &s_plugin;
}
Community
  • 1
  • 1
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175

0 Answers0