Ejemplo n.º 1
0
static void test_mg_download(void) {
  char *p1, *p2, ebuf[100];
  int len1, len2, port = atoi(HTTPS_PORT);
  struct mg_connection *conn;
  struct mg_context *ctx;

  ASSERT((ctx = mg_start(event_handler, NULL, OPTIONS)) != NULL);

  ASSERT(mg_download(NULL, port, 0, ebuf, sizeof(ebuf), "") == NULL);
  ASSERT(mg_download("localhost", 0, 0, ebuf, sizeof(ebuf), "") == NULL);
  ASSERT(mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "") == NULL);

  // Fetch nonexistent file, should see 404
  ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s",
                             "GET /gimbec HTTP/1.0\r\n\r\n")) != NULL);
  ASSERT(strcmp(conn->request_info.uri, "404") == 0);
  mg_close_connection(conn);

  // Fetch mongoose.c, should succeed
  ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s",
                             "GET /mongoose.c HTTP/1.0\r\n\r\n")) != NULL);
  ASSERT(!strcmp(conn->request_info.uri, "200"));
  ASSERT((p1 = read_conn(conn, &len1)) != NULL);
  ASSERT((p2 = read_file("mongoose.c", &len2)) != NULL);
  ASSERT(len1 == len2);
  ASSERT(memcmp(p1, p2, len1) == 0);
  free(p1), free(p2);
  mg_close_connection(conn);

  // Fetch in-memory file, should succeed.
  ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s",
                             "GET /blah HTTP/1.1\r\n\r\n")) != NULL);
  ASSERT((p1 = read_conn(conn, &len1)) != NULL);
  ASSERT(len1 == (int) strlen(inmemory_file_data));
  ASSERT(memcmp(p1, inmemory_file_data, len1) == 0);
  free(p1);
  mg_close_connection(conn);

  // Test SSL redirect, IP address
  ASSERT((conn = mg_download("localhost", atoi(HTTP_PORT), 0,
                             ebuf, sizeof(ebuf), "%s",
                             "GET /foo HTTP/1.1\r\n\r\n")) != NULL);
  ASSERT(strcmp(conn->request_info.uri, "302") == 0);
  ASSERT(strcmp(mg_get_header(conn, "Location"),
                "https://127.0.0.1:" HTTPS_PORT "/foo") == 0);
  mg_close_connection(conn);

  // Test SSL redirect, Host:
  ASSERT((conn = mg_download("localhost", atoi(HTTP_PORT), 0,
                             ebuf, sizeof(ebuf), "%s",
                             "GET /foo HTTP/1.1\r\nHost: a.b:77\n\n")) != NULL);
  ASSERT(strcmp(conn->request_info.uri, "302") == 0);
  ASSERT(strcmp(mg_get_header(conn, "Location"),
                "https://a.b:" HTTPS_PORT "/foo") == 0);
  mg_close_connection(conn);

  mg_stop(ctx);
}
Ejemplo n.º 2
0
int
CloseHandler(struct mg_connection *conn, void *cbdata)
{
	/* Handler may access the request info using mg_get_request_info */
	const struct mg_request_info *req_info = mg_get_request_info(conn);

	mg_printf(conn,
	          "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
	          "close\r\n\r\n");
	mg_printf(conn, "<html><body>");
	mg_printf(conn,
	          "<h2>This handler will close the connection in a second</h2>");
#ifdef _WIN32
	Sleep(1000);
#else
	sleep(1);
#endif
	mg_printf(conn, "bye");
	printf("CloseHandler: close connection\n");
	mg_close_connection(conn);
	printf("CloseHandler: wait 10 sec\n");
#ifdef _WIN32
	Sleep(10000);
#else
	sleep(10);
#endif
	printf("CloseHandler: return from function\n");
	return 1;
}
Ejemplo n.º 3
0
static void test_mg_upload(void) {
  static const char *boundary = "OOO___MY_BOUNDARY___OOO";
  struct mg_context *ctx;
  struct mg_connection *conn;
  char ebuf[100], buf[20], *file_data, *post_data = NULL;
  int file_len, post_data_len;

  ASSERT((ctx = mg_start(&CALLBACKS, NULL, OPTIONS)) != NULL);
  ASSERT((file_data = read_file("mongoose.c", &file_len)) != NULL);
  post_data_len = alloc_printf(&post_data, 0,
                                       "--%s\r\n"
                                       "Content-Disposition: form-data; "
                                       "name=\"file\"; "
                                       "filename=\"%s\"\r\n\r\n"
                                       "%.*s\r\n"
                                       "--%s\r\n",
                                       boundary, upload_filename,
                                       file_len, file_data, boundary);
  ASSERT(post_data_len > 0);
  ASSERT((conn = mg_download("localhost", atoi(HTTPS_PORT), 1,
                             ebuf, sizeof(ebuf),
                             "POST /upload HTTP/1.1\r\n"
                             "Content-Length: %d\r\n"
                             "Content-Type: multipart/form-data; "
                             "boundary=%s\r\n\r\n"
                             "%.*s", post_data_len, boundary,
                             post_data_len, post_data)) != NULL);
  free(file_data), free(post_data);
  ASSERT(mg_read(conn, buf, sizeof(buf)) == (int) strlen(upload_ok_message));
  ASSERT(memcmp(buf, upload_ok_message, strlen(upload_ok_message)) == 0);
  mg_close_connection(conn);
  mg_stop(ctx);
}
Ejemplo n.º 4
0
static void test_api_calls(void) {
  char ebuf[100];
  struct mg_connection *conn;
  struct mg_context *ctx;
  static const char *fmt = "POST %s HTTP/1.0\r\n"
    "Host:  blah.com\n"     // More spaces before
    "content-length: 3\r\n" // Lower case header name
    "\r\nb=123456";         // Content size > content-length, test for mg_read()

  ASSERT((ctx = mg_start(OPTIONS, api_cb, (void *) 123)) != NULL);
  ASSERT((conn = mg_download("localhost", atoi(HTTPS_PORT), 1,
                             ebuf, sizeof(ebuf), fmt, api_uri)) != NULL);
  mg_close_connection(conn);
  mg_stop(ctx);
}
Ejemplo n.º 5
0
static void test_api_calls(void) {
  char ebuf[100];
  struct mg_callbacks callbacks;
  struct mg_connection *conn;
  struct mg_context *ctx;
  static const char *request = "POST /?a=%20&b=&c=xx HTTP/1.0\r\n"
    "Host:  blah.com\n"     // More spaces before
    "content-length: 3\r\n" // Lower case header name
    "\r\nb=123456";         // Content size > content-length, test for mg_read()

  memset(&callbacks, 0, sizeof(callbacks));
  callbacks.begin_request = api_callback;
  ASSERT((ctx = mg_start(&callbacks, (void *) 123, OPTIONS)) != NULL);
  ASSERT((conn = mg_download("localhost", atoi(HTTPS_PORT), 1,
                             ebuf, sizeof(ebuf), "%s", request)) != NULL);
  mg_close_connection(conn);
  mg_stop(ctx);
}
Ejemplo n.º 6
0
struct mg_connection *mg_download(const char *host, int port, int use_ssl,
                                  char *ebuf, size_t ebuf_len,
                                  const char *fmt, ...) {
  struct mg_connection *conn;
  va_list ap;

  va_start(ap, fmt);
  ebuf[0] = '\0';
  if ((conn = mg_connect(host, port, use_ssl, ebuf, ebuf_len)) == NULL) {
  } else if (mg_vprintf(conn, fmt, ap) <= 0) {
    snprintf(ebuf, ebuf_len, "%s", "Error sending request");
  } else {
    getreq(conn, ebuf, ebuf_len);
  }
  if (ebuf[0] != '\0' && conn != NULL) {
    mg_close_connection(conn);
    conn = NULL;
  }

  return conn;
}
Ejemplo n.º 7
0
static void test_request_replies(void) {
  char ebuf[100];
  int i, port = atoi(HTTPS_PORT);
  struct mg_connection *conn;
  struct mg_context *ctx;
  static struct { const char *request, *reply_regex; } tests[] = {
    {
      "GET test/hello.txt HTTP/1.0\r\nRange: bytes=3-5\r\n\r\n",
      "^HTTP/1.1 206 Partial Content"
    },
    {NULL, NULL},
  };

  ASSERT((ctx = mg_start(&CALLBACKS, NULL, OPTIONS)) != NULL);
  for (i = 0; tests[i].request != NULL; i++) {
    ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s",
                               tests[i].request)) != NULL);
    mg_close_connection(conn);
  }
  mg_stop(ctx);
}
Ejemplo n.º 8
0
static void test_mg_upload(void) {
  static const char *boundary = "OOO___MY_BOUNDARY___OOO";
  struct mg_context *ctx;
  struct mg_connection *conn;
  char ebuf[100], buf[20], *file_data, *file2_data, *post_data;
  int file_len, file2_len, post_data_len;

  ASSERT((ctx = mg_start(OPTIONS, event_handler, NULL)) != NULL);

  // Upload two files
  ASSERT((file_data = read_file("lua_5.2.1.h", &file_len)) != NULL);
  ASSERT((file2_data = read_file("lsqlite3.c", &file2_len)) != NULL);
  post_data = NULL;
  post_data_len = alloc_printf(&post_data, 0,
      // First file
      "--%s\r\n" "Content-Disposition: form-data; " "name=\"file\"; "
      "filename=\"%s\"\r\n\r\n" "%.*s\r\n"
      // Second file
      "--%s\r\n" "Content-Disposition: form-data; " "name=\"file\"; "
      "filename=\"%s\"\r\n\r\n" "%.*s\r\n"
      // Final boundary
      "--%s--\r\n",
      boundary, "f1.txt", file_len, file_data, boundary, "f2.txt",
      file2_len, file2_data, boundary);
  ASSERT(post_data_len > 0);
  ASSERT((conn = mg_download("localhost", atoi(HTTPS_PORT), 1,
                             ebuf, sizeof(ebuf),
                             "POST /upload HTTP/1.1\r\n"
                             "Content-Length: %d\r\n"
                             "Content-Type: multipart/form-data; "
                             "boundary=%s\r\n\r\n"
                             "%.*s", post_data_len, boundary,
                             post_data_len, post_data)) != NULL);
  ASSERT(mg_read(conn, buf, sizeof(buf)) == (int) strlen(upload_ok_message));
  ASSERT(memcmp(buf, upload_ok_message, strlen(upload_ok_message)) == 0);
  mg_close_connection(conn);

  mg_stop(ctx);
}
Ejemplo n.º 9
0
void HttpRequest::ThreadFunction()
{
    String protocol = "http";
    String host;
    String path = "/";
    int port = 80;
    
    unsigned protocolEnd = url_.Find("://");
    if (protocolEnd != String::NPOS)
    {
        protocol = url_.Substring(0, protocolEnd);
        host = url_.Substring(protocolEnd + 3);
    }
    else
        host = url_;
    
    unsigned pathStart = host.Find('/');
    if (pathStart != String::NPOS)
    {
        path = host.Substring(pathStart);
        host = host.Substring(0, pathStart);
    }
    
    unsigned portStart = host.Find(':');
    if (portStart != String::NPOS)
    {
        port = ToInt(host.Substring(portStart + 1));
        host = host.Substring(0, portStart);
    }
    
    char errorBuffer[ERROR_BUFFER_SIZE];
    memset(errorBuffer, 0, sizeof(errorBuffer));
    
    String headersStr;
    for (unsigned i = 0; i < headers_.Size(); ++i)
    {
        // Trim and only add non-empty header strings
        String header = headers_[i].Trimmed();
        if (header.Length())
            headersStr += header + "\r\n";
    }
    
    // Initiate the connection. This may block due to DNS query
    /// \todo SSL mode will not actually work unless Civetweb's SSL mode is initialized with an external SSL DLL
    mg_connection* connection = 0;
    if (postData_.Empty())
    {
        connection = mg_download(host.CString(), port, protocol.Compare("https", false) ? 0 : 1, errorBuffer, sizeof(errorBuffer),
            "%s %s HTTP/1.0\r\n"
            "Host: %s\r\n"
            "%s"
            "\r\n", verb_.CString(), path.CString(), host.CString(), headersStr.CString());
    }
    else
    {
        connection = mg_download(host.CString(), port, protocol.Compare("https", false) ? 0 : 1, errorBuffer, sizeof(errorBuffer),
            "%s %s HTTP/1.0\r\n"
            "Host: %s\r\n"
            "%s"
            "Content-Length: %d\r\n"
            "\r\n"
            "%s", verb_.CString(), path.CString(), host.CString(), headersStr.CString(), postData_.Length(), postData_.CString());
    }
    
    {
        MutexLock lock(mutex_);
        state_ = connection ? HTTP_OPEN : HTTP_ERROR;
        
        // If no connection could be made, store the error and exit
        if (state_ == HTTP_ERROR)
        {
            error_ = String(&errorBuffer[0]);
            return;
        }
    }
    
    // Loop while should run, read data from the connection, copy to the main thread buffer if there is space
    while (shouldRun_)
    {
        // Read less than full buffer to be able to distinguish between full and empty ring buffer. Reading may block
        int bytesRead = mg_read(connection, httpReadBuffer_.Get(), READ_BUFFER_SIZE / 4);
        if (bytesRead <= 0)
            break;
        
        mutex_.Acquire();
        
        // Wait until enough space in the main thread's ring buffer
        for (;;)
        {
            unsigned spaceInBuffer = READ_BUFFER_SIZE - ((writePosition_ - readPosition_) & (READ_BUFFER_SIZE - 1));
            if ((int)spaceInBuffer > bytesRead || !shouldRun_)
                break;
            
            mutex_.Release();
            Time::Sleep(5);
            mutex_.Acquire();
        }
        
        if (!shouldRun_)
        {
            mutex_.Release();
            break;
        }
        
        if (writePosition_ + bytesRead <= READ_BUFFER_SIZE)
            memcpy(readBuffer_.Get() + writePosition_, httpReadBuffer_.Get(), bytesRead);
        else
        {
            // Handle ring buffer wrap
            unsigned part1 = READ_BUFFER_SIZE - writePosition_;
            unsigned part2 = bytesRead - part1;
            memcpy(readBuffer_.Get() + writePosition_, httpReadBuffer_.Get(), part1);
            memcpy(readBuffer_.Get(), httpReadBuffer_.Get() + part1, part2);
        }
        
        writePosition_ += bytesRead;
        writePosition_ &= READ_BUFFER_SIZE - 1;
        
        mutex_.Release();
    }
    
    // Close the connection
    mg_close_connection(connection);
    
    {
        MutexLock lock(mutex_);
        state_ = HTTP_CLOSED;
    }
}
Ejemplo n.º 10
0
END_TEST


START_TEST(test_mg_server_and_client_tls)
{
#ifndef NO_SSL

	struct mg_context *ctx;

	int ports_cnt;
	struct mg_server_ports ports[16];
	struct mg_callbacks callbacks;
	char errmsg[256];

	struct mg_connection *client_conn;
	char client_err[256];
	const struct mg_request_info *client_ri;
	int client_res;
	struct mg_client_options client_options;

	const char *OPTIONS[32]; /* initializer list here is rejected by CI test */
	int opt_idx = 0;
	char server_cert[256];
	char client_cert[256];
	const char *res_dir = locate_resources();

	ck_assert(res_dir != NULL);
	strcpy(server_cert, res_dir);
	strcpy(client_cert, res_dir);
#ifdef _WIN32
	strcat(server_cert, "cert\\server.pem");
	strcat(client_cert, "cert\\client.pem");
#else
	strcat(server_cert, "cert/server.pem");
	strcat(client_cert, "cert/client.pem");
#endif

	memset((void *)OPTIONS, 0, sizeof(OPTIONS));
#if !defined(NO_FILES)
	OPTIONS[opt_idx++] = "document_root";
	OPTIONS[opt_idx++] = ".";
#endif
	OPTIONS[opt_idx++] = "listening_ports";
	OPTIONS[opt_idx++] = "8080r,8443s";
	OPTIONS[opt_idx++] = "ssl_certificate";
	OPTIONS[opt_idx++] = server_cert;
	OPTIONS[opt_idx++] = "ssl_verify_peer";
	OPTIONS[opt_idx++] = "yes";
	OPTIONS[opt_idx++] = "ssl_ca_file";
	OPTIONS[opt_idx++] = client_cert;

	ck_assert_int_le(opt_idx, (int)(sizeof(OPTIONS) / sizeof(OPTIONS[0])));
	ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 1] == NULL);
	ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 2] == NULL);

	memset(ports, 0, sizeof(ports));
	memset(&callbacks, 0, sizeof(callbacks));
	memset(errmsg, 0, sizeof(errmsg));

	callbacks.log_message = log_msg_func;

	ctx = mg_start(&callbacks, (void *)errmsg, OPTIONS);
	mark_point();
	test_sleep(1);
	ck_assert_str_eq(errmsg, "");
	ck_assert(ctx != NULL);

	ports_cnt = mg_get_server_ports(ctx, 16, ports);
	ck_assert_int_eq(ports_cnt, 2);
	ck_assert_int_eq(ports[0].protocol, 1);
	ck_assert_int_eq(ports[0].port, 8080);
	ck_assert_int_eq(ports[0].is_ssl, 0);
	ck_assert_int_eq(ports[0].is_redirect, 1);
	ck_assert_int_eq(ports[1].protocol, 1);
	ck_assert_int_eq(ports[1].port, 8443);
	ck_assert_int_eq(ports[1].is_ssl, 1);
	ck_assert_int_eq(ports[1].is_redirect, 0);
	ck_assert_int_eq(ports[2].protocol, 0);
	ck_assert_int_eq(ports[2].port, 0);
	ck_assert_int_eq(ports[2].is_ssl, 0);
	ck_assert_int_eq(ports[2].is_redirect, 0);

	test_sleep(1);
	mark_point();

	memset(client_err, 0, sizeof(client_err));
	client_conn =
	    mg_connect_client("127.0.0.1", 8443, 1, client_err, sizeof(client_err));
	ck_assert(client_conn == NULL);
	ck_assert_str_ne(client_err, "");

	memset(client_err, 0, sizeof(client_err));
	memset(&client_options, 0, sizeof(client_options));
	client_options.host = "127.0.0.1";
	client_options.port = 8443;
	client_options.client_cert = client_cert;
	client_options.server_cert = server_cert;

	client_conn = mg_connect_client_secure(&client_options,
	                                       client_err,
	                                       sizeof(client_err));
	ck_assert(client_conn != NULL);
	ck_assert_str_eq(client_err, "");
	mg_printf(client_conn, "GET / HTTP/1.0\r\n\r\n");
	client_res =
	    mg_get_response(client_conn, client_err, sizeof(client_err), 10000);
	ck_assert_int_ge(client_res, 0);
	ck_assert_str_eq(client_err, "");
	client_ri = mg_get_request_info(client_conn);
	ck_assert(client_ri != NULL);

#if defined(NO_FILES)
	ck_assert_str_eq(client_ri->uri, "404");
#else
	ck_assert_str_eq(client_ri->uri, "200");
	/* TODO: ck_assert_str_eq(client_ri->request_method, "HTTP/1.0"); */
	client_res = (int)mg_read(client_conn, client_err, sizeof(client_err));
	ck_assert_int_gt(client_res, 0);
	ck_assert_int_le(client_res, sizeof(client_err));
#endif
	mg_close_connection(client_conn);

	/* TODO: A client API using a client certificate is missing */

	mark_point();
	test_sleep(1);
	mark_point();

	mg_stop(ctx);
#endif
}
Ejemplo n.º 11
0
END_TEST


START_TEST(test_mg_start_stop_https_server)
{
#ifndef NO_SSL

	struct mg_context *ctx;

	size_t ports_cnt;
	int ports[16];
	int ssl[16];
	struct mg_callbacks callbacks;
	char errmsg[256];

	const char *OPTIONS[8]; /* initializer list here is rejected by CI test */
	int opt_idx = 0;
	const char *ssl_cert = locate_ssl_cert();

	struct mg_connection *client_conn;
	char client_err[256];
	const struct mg_request_info *client_ri;
	int client_res;

	ck_assert(ssl_cert != NULL);

	memset((void *)OPTIONS, 0, sizeof(OPTIONS));
#if !defined(NO_FILES)
	OPTIONS[opt_idx++] = "document_root";
	OPTIONS[opt_idx++] = ".";
#endif
	OPTIONS[opt_idx++] = "listening_ports";
	OPTIONS[opt_idx++] = "8080r,8443s";
	OPTIONS[opt_idx++] = "ssl_certificate";
	OPTIONS[opt_idx++] = ssl_cert;

	ck_assert_int_le(opt_idx, (int)(sizeof(OPTIONS) / sizeof(OPTIONS[0])));
	ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 1] == NULL);
	ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 2] == NULL);

	memset(ports, 0, sizeof(ports));
	memset(ssl, 0, sizeof(ssl));
	memset(&callbacks, 0, sizeof(callbacks));
	memset(errmsg, 0, sizeof(errmsg));

	callbacks.log_message = log_msg_func;

	ctx = mg_start(&callbacks, (void *)errmsg, OPTIONS);
	mark_point();
	test_sleep(1);
	ck_assert_str_eq(errmsg, "");
	ck_assert(ctx != NULL);

	ports_cnt = mg_get_ports(ctx, 16, ports, ssl);
	ck_assert_uint_eq(ports_cnt, 2);
	ck_assert_int_eq(ports[0], 8080);
	ck_assert_int_eq(ssl[0], 0);
	ck_assert_int_eq(ports[1], 8443);
	ck_assert_int_eq(ssl[1], 1);
	ck_assert_int_eq(ports[2], 0);
	ck_assert_int_eq(ssl[2], 0);

	test_sleep(1);
	mark_point();

	memset(client_err, 0, sizeof(client_err));
	client_conn =
	    mg_connect_client("127.0.0.1", 8443, 1, client_err, sizeof(client_err));
	ck_assert(client_conn != NULL);
	ck_assert_str_eq(client_err, "");
	mg_printf(client_conn, "GET / HTTP/1.0\r\n\r\n");
	client_res =
	    mg_get_response(client_conn, client_err, sizeof(client_err), 10000);
	ck_assert_int_ge(client_res, 0);
	ck_assert_str_eq(client_err, "");
	client_ri = mg_get_request_info(client_conn);
	ck_assert(client_ri != NULL);

#if defined(NO_FILES)
	ck_assert_str_eq(client_ri->uri, "404");
#else
	ck_assert_str_eq(client_ri->uri, "200");
	/* TODO: ck_assert_str_eq(client_ri->request_method, "HTTP/1.0"); */
	client_res = (int)mg_read(client_conn, client_err, sizeof(client_err));
	ck_assert_int_gt(client_res, 0);
	ck_assert_int_le(client_res, sizeof(client_err));
#endif
	mg_close_connection(client_conn);

	mark_point();
	test_sleep(1);
	mark_point();

	mg_stop(ctx);
#endif
}
Ejemplo n.º 12
0
int main(int argc, char *argv[])
{
    struct mg_context *ctx = NULL;
    struct tclient_data client1_data = {NULL, 0, 0};
    struct tclient_data client2_data = {NULL, 0, 0};
    struct tclient_data client3_data = {NULL, 0, 0};
    struct mg_connection* newconn1 = NULL;
    struct mg_connection* newconn2 = NULL;
    struct mg_connection* newconn3 = NULL;
    char ebuf[100] = {0};

    assert(websocket_welcome_msg_len == strlen(websocket_welcome_msg));

    /* First set up a websocket server */
    ctx = start_websocket_server();
    assert(ctx != NULL);
    printf("Server init\n\n");

    /* Then connect a first client */
    newconn1 = mg_connect_websocket_client("localhost", atoi(PORT), 0, ebuf, sizeof(ebuf),
        "/websocket", NULL, websocket_client_data_handler, websocket_client_close_handler,
        &client1_data);

    if (newconn1 == NULL)
    {
        printf("Error: %s", ebuf);
        return 1;
    }

    sleep(1); /* Should get the websocket welcome message */
    assert(client1_data.closed == 0);
    assert(client2_data.closed == 0);
    assert(client2_data.data == NULL);
    assert(client2_data.len == 0);
    assert(client1_data.data != NULL);
    assert(client1_data.len == websocket_welcome_msg_len);
    assert(!memcmp(client1_data.data, websocket_welcome_msg, websocket_welcome_msg_len));
    free(client1_data.data);
    client1_data.data = NULL;
    client1_data.len = 0;

    mg_websocket_write(newconn1, WEBSOCKET_OPCODE_TEXT, "data1", 5);

    sleep(1); /* Should get the acknowledge message */
    assert(client1_data.closed == 0);
    assert(client2_data.closed == 0);
    assert(client2_data.data == NULL);
    assert(client2_data.len == 0);
    assert(client1_data.data != NULL);
    assert(client1_data.len == websocket_acknowledge_msg_len);
    assert(!memcmp(client1_data.data, websocket_acknowledge_msg, websocket_acknowledge_msg_len));
    free(client1_data.data);
    client1_data.data = NULL;
    client1_data.len = 0;

    /* Now connect a second client */
    newconn2 = mg_connect_websocket_client("localhost", atoi(PORT), 0, ebuf, sizeof(ebuf),
        "/websocket", NULL, websocket_client_data_handler, websocket_client_close_handler,
        &client2_data);

    if (newconn2 == NULL)
    {
        printf("Error: %s", ebuf);
        return 1;
    }

    sleep(1); /* Client 2 should get the websocket welcome message */
    assert(client1_data.closed == 0);
    assert(client2_data.closed == 0);
    assert(client1_data.data == NULL);
    assert(client1_data.len == 0);
    assert(client2_data.data != NULL);
    assert(client2_data.len == websocket_welcome_msg_len);
    assert(!memcmp(client2_data.data, websocket_welcome_msg, websocket_welcome_msg_len));
    free(client2_data.data);
    client2_data.data = NULL;
    client2_data.len = 0;

    mg_websocket_write(newconn1, WEBSOCKET_OPCODE_TEXT, "data2", 5);

    sleep(1); /* Should get the acknowledge message */
    assert(client1_data.closed == 0);
    assert(client2_data.closed == 0);
    assert(client2_data.data == NULL);
    assert(client2_data.len == 0);
    assert(client1_data.data != NULL);
    assert(client1_data.len == websocket_acknowledge_msg_len);
    assert(!memcmp(client1_data.data, websocket_acknowledge_msg, websocket_acknowledge_msg_len));
    free(client1_data.data);
    client1_data.data = NULL;
    client1_data.len = 0;

    mg_websocket_write(newconn1, WEBSOCKET_OPCODE_TEXT, "bye", 3);

    sleep(1); /* Should get the goodbye message */
    assert(client1_data.closed == 0);
    assert(client2_data.closed == 0);
    assert(client2_data.data == NULL);
    assert(client2_data.len == 0);
    assert(client1_data.data != NULL);
    assert(client1_data.len == websocket_goodbye_msg_len);
    assert(!memcmp(client1_data.data, websocket_goodbye_msg, websocket_goodbye_msg_len));
    free(client1_data.data);
    client1_data.data = NULL;
    client1_data.len = 0;

    mg_close_connection(newconn1);

    sleep(1); /* Won't get any message */
    assert(client1_data.closed == 1);
    assert(client2_data.closed == 0);
    assert(client1_data.data == NULL);
    assert(client1_data.len == 0);
    assert(client2_data.data == NULL);
    assert(client2_data.len == 0);

    mg_websocket_write(newconn2, WEBSOCKET_OPCODE_TEXT, "bye", 3);

    sleep(1); /* Should get the goodbye message */
    assert(client1_data.closed == 1);
    assert(client2_data.closed == 0);
    assert(client1_data.data == NULL);
    assert(client1_data.len == 0);
    assert(client2_data.data != NULL);
    assert(client2_data.len == websocket_goodbye_msg_len);
    assert(!memcmp(client2_data.data, websocket_goodbye_msg, websocket_goodbye_msg_len));
    free(client2_data.data);
    client2_data.data = NULL;
    client2_data.len = 0;

    mg_close_connection(newconn2);

    sleep(1); /* Won't get any message */
    assert(client1_data.closed == 1);
    assert(client2_data.closed == 1);
    assert(client1_data.data == NULL);
    assert(client1_data.len == 0);
    assert(client2_data.data == NULL);
    assert(client2_data.len == 0);

    /* Connect client 3 */
    newconn3 = mg_connect_websocket_client("localhost", atoi(PORT), 0, ebuf, sizeof(ebuf),
        "/websocket", NULL, websocket_client_data_handler, websocket_client_close_handler,
        &client3_data);

    sleep(1); /* Client 3 should get the websocket welcome message */
    assert(client1_data.closed == 1);
    assert(client2_data.closed == 1);
    assert(client3_data.closed == 0);
    assert(client1_data.data == NULL);
    assert(client1_data.len == 0);
    assert(client2_data.data == NULL);
    assert(client2_data.len == 0);
    assert(client3_data.data != NULL);
    assert(client3_data.len == websocket_welcome_msg_len);
    assert(!memcmp(client3_data.data, websocket_welcome_msg, websocket_welcome_msg_len));
    free(client3_data.data);
    client3_data.data = NULL;
    client3_data.len = 0;

    mg_stop(ctx);
    printf("Server shutdown\n");

    sleep(10);

    assert(client3_data.closed == 1);

    return 0;
}
Ejemplo n.º 13
0
static void test_mg_download(void) {
  char *p1, *p2, ebuf[100];
  int len1, len2, port = atoi(HTTPS_PORT);
  struct mg_connection *conn;
  struct mg_context *ctx;

  ASSERT((ctx = mg_start(OPTIONS, event_handler, NULL)) != NULL);

  ASSERT(mg_download(NULL, port, 0, ebuf, sizeof(ebuf), "%s", "") == NULL);
  ASSERT(mg_download("localhost", 0, 0, ebuf, sizeof(ebuf), "%s", "") == NULL);
  ASSERT(mg_download("localhost", port, 1, ebuf, sizeof(ebuf),
                     "%s", "") == NULL);

  // Fetch nonexistent file, should see 404
  ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s",
                             "GET /gimbec HTTP/1.0\r\n\r\n")) != NULL);
  ASSERT(strcmp(conn->request_info.uri, "404") == 0);
  mg_close_connection(conn);

  ASSERT((conn = mg_download("google.com", 443, 1, ebuf, sizeof(ebuf), "%s",
                             "GET / HTTP/1.0\r\n\r\n")) != NULL);
  mg_close_connection(conn);

  // POST with "Content-Length: 0", must not block
  ASSERT((conn = mg_download("localhost", atoi(HTTPS_PORT), 1,
                             ebuf, sizeof(ebuf), "%s",
                             "POST /zerolen HTTP/1.1\r\n"
                             "Content-Lengh: 0\r\n\r\n    ")) != NULL);
  ASSERT((p1 = read_conn(conn, &len1)) != NULL);
  ASSERT(len1 = 2);
  ASSERT(memcmp(p1, "ok", 2) == 0);
  mg_close_connection(conn);

  // Fetch main.c, should succeed
  ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s",
                             "GET /main.c HTTP/1.0\r\n\r\n")) != NULL);
  ASSERT(!strcmp(conn->request_info.uri, "200"));
  ASSERT((p1 = read_conn(conn, &len1)) != NULL);
  ASSERT((p2 = read_file("main.c", &len2)) != NULL);
  ASSERT(len1 == len2);
  ASSERT(memcmp(p1, p2, len1) == 0);
  free(p1), free(p2);
  mg_close_connection(conn);

  // Test SSL redirect, IP address
  ASSERT((conn = mg_download("localhost", atoi(HTTP_PORT), 0,
                             ebuf, sizeof(ebuf), "%s",
                             "GET /foo HTTP/1.1\r\n\r\n")) != NULL);
  ASSERT(strcmp(conn->request_info.uri, "302") == 0);
  ASSERT(strcmp(mg_get_header(conn, "Location"),
                "https://127.0.0.1:" HTTPS_PORT "/foo") == 0);
  mg_close_connection(conn);

  // Test SSL redirect, Host:
  ASSERT((conn = mg_download("localhost", atoi(HTTP_PORT), 0,
                             ebuf, sizeof(ebuf), "%s",
                             "GET /foo HTTP/1.1\r\nHost: a.b:77\n\n")) != NULL);
  ASSERT(strcmp(conn->request_info.uri, "302") == 0);
  ASSERT(strcmp(mg_get_header(conn, "Location"),
                "https://a.b:" HTTPS_PORT "/foo") == 0);
  mg_close_connection(conn);

  mg_stop(ctx);
}
Ejemplo n.º 14
0
int WebInterface_websocket_data_handler(struct mg_connection *conn)
{
	WebInterface* pThis = (WebInterface*)mg_get_user_info(conn);

	// only allow 1 connection..
	if (conn!=pThis->getConnection())
	{
		if (pThis->getConnection())
		{
			mg_close_connection(pThis->getConnection());
		}

		pThis->setConnection(conn);
	}

	// Read the message from the client
	// For now we will assume that this is a string of text
	// Read in the header and size
	unsigned char header[10];
	int totalRead = 0;
	while ( totalRead < 2 )
	{
	  int bytesRead = mg_read(conn, header+totalRead, 2-totalRead);
	  if ( bytesRead <=0 )
	    return nullptr;
	  totalRead += bytesRead;
	}
	// Check the data received
	if ( header[0] != 0x81 )
	  return nullptr;

	long long messageLength = header[1] & 127;
	int maskLength = (header[1] & 128) ? 4 : 0;
	if ( messageLength == 126 ) // Large message
	{
	  totalRead = 0;
	  while ( totalRead < 2 )
	  {
	    int bytesRead = mg_read(conn, header+totalRead, 2-totalRead);
	    if ( bytesRead <=0 )
	      return nullptr;
	    totalRead += bytesRead;
	  }
	  messageLength = (((int) header[0]) << 8) + header[1];
	}
	else if ( messageLength > 126 ) // Very large message
	{
	  totalRead = 0;
	  while ( totalRead < 8 )
	  {
	    int bytesRead = mg_read(conn, header+totalRead, 8-totalRead);
	    if ( bytesRead <=0 )
	      return nullptr;
	    totalRead += bytesRead;
	  }
	  messageLength =  (((long long) htonl(*(int*)&header[0])) << 32) | htonl(*(int*)&header[4]);
	}

	// Now read the data
	unsigned char* buf = new unsigned char[messageLength+maskLength];
	totalRead = 0;
	while ( totalRead < messageLength+maskLength )
	{
	  int bytesRead = mg_read(conn, buf+totalRead, messageLength+maskLength-totalRead);
	  if ( bytesRead <=0 )
	  {
	    delete[] buf;
	    return nullptr;
	  }
	  totalRead += bytesRead;
	}
	char* message = new char[messageLength+1];
	for ( int i=0; i<messageLength; ++i )
	{
	  int x0r = (maskLength==0 ? 0 : buf[i%4]);
	  message[i] = buf[i+maskLength] ^ x0r;
	}

	message[messageLength] = '\0';
	delete[] buf;

	printf("rec: %s\n",message);

	pThis->parseCommand(message);

	delete[] message;

	/////////////////////////////////////////
	/*printf("send ack\n");

	// acknowledge
	unsigned char outbuf[40];
	outbuf[0] = 0x81;
	outbuf[1] = snprintf((char *) outbuf + 2, sizeof(outbuf) - 2, "%s", "ACK");
	mg_write(conn, outbuf, 2 + outbuf[1]);

	printf("ack ok\n");*/

	return 1; // return 0 close websocket
}