123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- /*
- * ws protocol handler plugin for "client_loopback_test"
- *
- * Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
- *
- * This file is made available under the Creative Commons CC0 1.0
- * Universal Public Domain Dedication.
- *
- * The person who associated a work with this deed has dedicated
- * the work to the public domain by waiving all of his or her rights
- * to the work worldwide under copyright law, including all related
- * and neighboring rights, to the extent allowed by law. You can copy,
- * modify, distribute and perform the work, even for commercial purposes,
- * all without asking permission.
- *
- * These test plugins are intended to be adapted for use in your code, which
- * may be proprietary. So unlike the library itself, they are licensed
- * Public Domain.
- */
- #define LWS_DLL
- #define LWS_INTERNAL
- #include "../lib/libwebsockets.h"
- #include <string.h>
- struct per_session_data__client_loopback_test {
- struct lws *wsi;
- };
- /*
- * This is a bit fiddly...
- *
- * 0) If you want the wss:// test to work, make sure the vhost is marked with
- * enable-client-ssl if using lwsws, or call lws_init_vhost_client_ssl() on
- * the vhost if you're doing it by hand.
- *
- * 1) enable the protocol on a vhost
- *
- * "ws-protocols": [{
- * "client-loopback-test": {
- * "status": "ok"
- * }, ...
- *
- * the vhost should listen on 80 (ws://) or 443 (wss://)
- *
- * 2) mount the http part of the test one level down on the same vhost, eg
- * {
- * "mountpoint": "/c",
- * "origin": "callback://client-loopback-test"
- * }
- *
- * 3) Use a browser to visit the mountpoint with a URI attached for looping
- * back, eg, if testing on localhost
- *
- * http://localhost/c/ws://localhost
- * https://localhost/c/wss://localhost
- *
- * 4) The HTTP part of this test protocol will try to do the requested
- * ws client connection, to the same test protocol on the same
- * server.
- */
- static int
- callback_client_loopback_test(struct lws *wsi, enum lws_callback_reasons reason,
- void *user, void *in, size_t len)
- {
- struct lws_client_connect_info i;
- struct per_session_data__client_loopback_test *pss =
- (struct per_session_data__client_loopback_test *)user;
- const char *p = (const char *)in;
- char buf[100];
- int n;
- switch (reason) {
- /* HTTP part */
- case LWS_CALLBACK_HTTP:
- if (len < 10)
- return -1;
- p++;
- while (*p && *p != '/')
- p++;
- if (!*p) {
- lws_return_http_status(wsi, 400, "Arg needs to be in format ws://xxx or wss://xxx");
- return -1;
- }
- p++;
- memset(&i, 0, sizeof(i));
- i.context = lws_get_context(wsi);
- // stacked /// get resolved to /
- if (strncmp(p, "ws:/", 4) == 0) {
- i.ssl_connection = 0;
- i.port = 80;
- p += 4;
- } else
- if (strncmp(p, "wss:/", 5) == 0) {
- i.port = 443;
- i.ssl_connection = 1;
- p += 5;
- } else {
- sprintf(buf, "Arg %s is not in format ws://xxx or wss://xxx\n", p);
- lws_return_http_status(wsi, 400, buf);
- return -1;
- }
- i.address = p;
- i.path = "";
- i.host = p;
- i.origin = p;
- i.ietf_version_or_minus_one = -1;
- i.protocol = "client-loopback-test";
- pss->wsi = lws_client_connect_via_info(&i);
- if (!pss->wsi)
- lws_return_http_status(wsi, 401, "client-loopback-test: connect failed\n");
- else {
- lwsl_notice("client connection to %s:%d with ssl: %d started\n",
- i.address, i.port, i.ssl_connection);
- lws_return_http_status(wsi, 200, "OK");
- }
- /* either way, close the triggering http link */
- return -1;
- case LWS_CALLBACK_CLOSED_HTTP:
- lwsl_notice("Http part closed\n");
- break;
- /* server part */
- case LWS_CALLBACK_ESTABLISHED:
- lwsl_notice("server part: LWS_CALLBACK_ESTABLISHED\n");
- strcpy(buf + LWS_PRE, "Made it");
- n = lws_write(wsi, (unsigned char *)buf + LWS_PRE,
- 7, LWS_WRITE_TEXT);
- if (n < 7)
- return -1;
- break;
- /* client part */
- case LWS_CALLBACK_CLIENT_ESTABLISHED:
- lwsl_notice("Client connection established\n");
- break;
- case LWS_CALLBACK_CLIENT_RECEIVE:
- strncpy(buf, in, sizeof(buf) - 1);
- lwsl_notice("Client connection received %ld from server '%s'\n", (long)len, buf);
- /* OK we are done with the client connection */
- return -1;
- default:
- break;
- }
- return 0;
- }
- static const struct lws_protocols protocols[] = {
- {
- "client-loopback-test",
- callback_client_loopback_test,
- sizeof(struct per_session_data__client_loopback_test),
- 1024, /* rx buf size must be >= permessage-deflate rx size */
- },
- };
- LWS_EXTERN LWS_VISIBLE int
- init_protocol_client_loopback_test(struct lws_context *context,
- struct lws_plugin_capability *c)
- {
- if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
- lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
- c->api_magic);
- return 1;
- }
- c->protocols = protocols;
- c->count_protocols = ARRAY_SIZE(protocols);
- c->extensions = NULL;
- c->count_extensions = 0;
- return 0;
- }
- LWS_EXTERN LWS_VISIBLE int
- destroy_protocol_client_loopback_test(struct lws_context *context)
- {
- return 0;
- }
|