Changeset f42d429 in rtems


Ignore:
Timestamp:
12/15/14 02:26:31 (9 years ago)
Author:
Nick Withers <nick.withers@…>
Branches:
4.11, 5, master
Children:
b2ee119f
Parents:
3acc619
git-author:
Nick Withers <nick.withers@…> (12/15/14 02:26:31)
git-committer:
Sebastian Huber <sebastian.huber@…> (12/15/14 06:44:56)
Message:

Enable WebSocket? support in the Mongoose HTTP server

Files:
4 edited

Legend:

Unmodified
Added
Removed
  • cpukit/mghttpd/Makefile.am

    r3acc619 rf42d429  
    88libmghttpd_a_CPPFLAGS = $(AM_CPPFLAGS)
    99# libmghttpd_a_CPPFLAGS += -DHAVE_MD5
    10 libmghttpd_a_CPPFLAGS += -DNO_SSL -DNO_POPEN -DNO_CGI
     10libmghttpd_a_CPPFLAGS += -DNO_SSL -DNO_POPEN -DNO_CGI -DUSE_WEBSOCKET
    1111
    1212libmghttpd_a_SOURCES = mongoose.c mongoose.h
  • testsuites/libtests/mghttpd01/init.c

    r3acc619 rf42d429  
    2424
    2525#include <stdio.h>
     26#include <string.h>
    2627#include <mghttpd/mongoose.h>
    2728
     
    4344                        "\r\n" \
    4445                        "This is a message from the callback function.\r\n"
     46
     47#define WSTEST_REQ      "Test request"
     48#define WSTEST_RESP     "This is a message from the WebSocket callback function."
    4549
    4650#define INDEX_HTML      "HTTP/1.1 200 OK\r\n" \
     
    97101}
    98102
     103static int callback_websocket(struct mg_connection *connection,
     104                              int                  bits,
     105                              char                 *data,
     106                              size_t               data_len)
     107{
     108  if (data_len == strlen(WSTEST_REQ) && strncmp(data, WSTEST_REQ, data_len) == 0)
     109  {
     110    mg_websocket_write(connection, WEBSOCKET_OPCODE_TEXT, WSTEST_RESP, strlen(WSTEST_RESP));
     111
     112    /* Don't close the WebSocket */
     113    return 1;
     114  }
     115
     116  return 0;
     117}
     118
    99119static void test_mg_index_html(void)
    100120{
     
    165185}
    166186
     187static void test_mg_websocket(void)
     188{
     189  httpc_context httpc_ctx;
     190  char *buffer = malloc(BUFFERSIZE);
     191  bool brv = false;
     192  int rv = 0;
     193
     194  rtems_test_assert(buffer != NULL);
     195
     196  puts("=== Get a WebSocket response generated from a callback function" \
     197      " from first Mongoose instance:");
     198
     199  httpc_init_context(&httpc_ctx);
     200  brv = httpc_open_connection(&httpc_ctx, "127.0.0.1", 80);
     201  rtems_test_assert(brv);
     202  brv = httpc_ws_open_connection(&httpc_ctx);
     203  rtems_test_assert(brv);
     204  brv = httpc_ws_send_request(&httpc_ctx, WSTEST_REQ, buffer, BUFFERSIZE);
     205  rtems_test_assert(brv);
     206  brv = httpc_close_connection(&httpc_ctx);
     207  rtems_test_assert(brv);
     208  puts(buffer);
     209  rv = strcmp(buffer, WSTEST_RESP);
     210  rtems_test_assert(rv == 0);
     211
     212  puts("=== OK");
     213
     214  free(buffer);
     215}
     216
    167217static void test_mongoose(void)
    168218{
    169219  const struct mg_callbacks callbacks = {
    170     .begin_request = callback
     220    .begin_request = callback,
     221    .websocket_data = callback_websocket
    171222  };
    172223  const char *options[] = {
     
    193244  test_mg_index_html();
    194245  test_mg_callback();
     246  test_mg_websocket();
    195247
    196248  mg_stop(mg1);
  • testsuites/libtests/mghttpd01/test-http-client.c

    r3acc619 rf42d429  
    1919#include <netinet/tcp.h>
    2020#include <netdb.h>
     21#include <limits.h>
    2122#include <unistd.h>
     23#include <stdint.h>
    2224#include <string.h>
    2325
     26#include <tmacros.h>
     27
    2428#include "test-http-client.h"
     29
     30#define HTTPC_WS_CONN_REQ  "GET / HTTP/1.1\r\n" \
     31                           "Host: localhost\r\n" \
     32                           "Upgrade: websocket\r\n" \
     33                           "Connection: Upgrade\r\n" \
     34                           "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" \
     35                           "Sec-WebSocket-Version: 13\r\n" \
     36                           "\r\n"
     37#define HTTPC_WS_CONN_RESP "HTTP/1.1 101 Switching Protocols\r\n" \
     38                           "Upgrade: websocket\r\n" \
     39                           "Connection: Upgrade\r\n" \
     40                           "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" \
     41                           "\r\n"
     42
     43static ssize_t httpc_read_full(
     44  const httpc_context *ctx,
     45  void *response,
     46  size_t responsesize
     47);
    2548
    2649void httpc_init_context(
     
    3457bool httpc_open_connection(
    3558  httpc_context *ctx,
    36   char *targethost,
     59  const char *targethost,
    3760  int targetport
    3861)
     
    77100
    78101bool httpc_send_request(
    79   httpc_context *ctx,
    80   char *request,
     102  const httpc_context *ctx,
     103  const char *request,
    81104  char *response,
    82105  int responsesize
    83106)
    84107{
    85   int size = strlen(request);
    86   char lineend[] = " HTTP/1.1\r\n\r\n";
    87 
    88   write(ctx->socket, request, size);
    89   write(ctx->socket, lineend, sizeof(lineend));
    90 
    91   size = read(ctx->socket, response, responsesize-1);
    92   response[size] = '\0';
    93 
    94   return true;
    95 }
    96 
     108  rtems_test_assert(ctx != NULL);
     109  rtems_test_assert(ctx->socket >= 0);
     110  rtems_test_assert(request != NULL);
     111  rtems_test_assert(response != NULL);
     112  rtems_test_assert(responsesize > 1);
     113
     114  static const char * const lineend = " HTTP/1.1\r\n\r\n";
     115
     116  write(ctx->socket, request, strlen(request));
     117  write(ctx->socket, lineend, strlen(lineend));
     118
     119  ssize_t size;
     120  if((size = httpc_read_full(ctx, response, responsesize - 1)) == -1)
     121  {
     122    return false;
     123  }
     124  *(response + size) = '\0';
     125
     126  return true;
     127}
     128
     129bool httpc_ws_open_connection(
     130  const httpc_context *ctx
     131)
     132{
     133  rtems_test_assert(ctx != NULL);
     134  rtems_test_assert(ctx->socket >= 0);
     135
     136  write(ctx->socket, HTTPC_WS_CONN_REQ, strlen(HTTPC_WS_CONN_REQ));
     137
     138  char response[strlen(HTTPC_WS_CONN_RESP)];
     139  if(httpc_read_full(ctx, response, sizeof(response)) != sizeof(response))
     140  {
     141    return false;
     142  }
     143  if(strncmp(response, HTTPC_WS_CONN_RESP, sizeof(response)) != 0)
     144  {
     145    return false;
     146  }
     147
     148  return true;
     149}
     150
     151bool httpc_ws_send_request(
     152  const httpc_context *ctx,
     153  const char *request,
     154  char *response,
     155  int responsesize
     156)
     157{
     158  rtems_test_assert(ctx != NULL);
     159  rtems_test_assert(ctx->socket >= 0);
     160  rtems_test_assert(request != NULL);
     161  rtems_test_assert(response != NULL);
     162  rtems_test_assert(responsesize > 0);
     163
     164  static const uint16_t ws_header_fin  = 1U << 15;
     165  static const uint16_t ws_header_text = 1U << 8;
     166  static const uint16_t ws_header_size = 0x7FU;
     167
     168  /*
     169   * We don't support sending WebSocket messages which require multiple
     170   * chunks
     171   */
     172  if(strlen(request) > ws_header_size) { return false; }
     173
     174  uint16_t header = htons(ws_header_fin | ws_header_text | strlen(request));
     175
     176  write(ctx->socket, &header, sizeof(header));
     177  write(ctx->socket, request, strlen(request));
     178
     179  if (httpc_read_full(ctx, &header, sizeof(header)) != sizeof(header))
     180  {
     181    return false;
     182  }
     183  header = ntohs(header);
     184  if (!(header & ws_header_fin)) { return false; }
     185  if (!(header & ws_header_text)) { return false; }
     186  if (responsesize < (header & ws_header_size) + 1) { return false; }
     187
     188  responsesize = header & ws_header_size;
     189  if (httpc_read_full(ctx, response, responsesize) != responsesize)
     190  {
     191    return false;
     192  }
     193  *(response + responsesize) = '\0';
     194
     195  return true;
     196}
     197
     198
     199static ssize_t httpc_read_full(
     200  const httpc_context *ctx,
     201  void *response,
     202  size_t responsesize
     203)
     204{
     205  rtems_test_assert(ctx != NULL);
     206  rtems_test_assert(ctx->socket >= 0);
     207  rtems_test_assert(response != NULL);
     208  rtems_test_assert(responsesize > 0);
     209
     210  if (responsesize > SSIZE_MAX) { return -1; }
     211
     212  unsigned char *pos = response;
     213
     214  while(pos < (unsigned char *)response + responsesize)
     215  {
     216    ssize_t size =
     217      read(ctx->socket, pos, (unsigned char *)response + responsesize - pos);
     218    if (size == -1) { return -1; }
     219    if (size == 0) { break; }
     220    pos += size;
     221  }
     222
     223  return (pos - (unsigned char *)response);
     224}
  • testsuites/libtests/mghttpd01/test-http-client.h

    r3acc619 rf42d429  
    3737bool httpc_open_connection(
    3838  httpc_context *ctx,
    39   char *targethost,
     39  const char *targethost,
    4040  int targetport
    4141);
     
    4646
    4747bool httpc_send_request(
    48   httpc_context *ctx,
    49   char *request,
     48  const httpc_context *ctx,
     49  const char *request,
     50  char *response,
     51  int responsesize
     52);
     53
     54bool httpc_ws_open_connection(
     55  const httpc_context *ctx
     56);
     57
     58bool httpc_ws_send_request(
     59  const httpc_context *ctx,
     60  const char *request,
    5061  char *response,
    5162  int responsesize
Note: See TracChangeset for help on using the changeset viewer.