Skip to content
Snippets Groups Projects
context.c 47.7 KiB
Newer Older
/*
 * libwebsockets - small server side websockets and web server implementation
 *
 * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation:
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */

#include "private-libwebsockets.h"

#ifndef LWS_BUILD_HASH
#define LWS_BUILD_HASH "unknown-build-hash"
#endif

const struct lws_role_ops *available_roles[] = {
#if defined(LWS_ROLE_H2)
	&role_ops_h2,
#endif
#if defined(LWS_ROLE_H1)
	&role_ops_h1,
#endif
#if defined(LWS_ROLE_WS)
	&role_ops_ws,
#endif
const struct lws_event_loop_ops *available_event_libs[] = {
#if defined(LWS_WITH_POLL)
	&event_loop_ops_poll,
#endif
#if defined(LWS_WITH_LIBUV)
	&event_loop_ops_uv,
#endif
#if defined(LWS_WITH_LIBEVENT)
	&event_loop_ops_event,
#endif
#if defined(LWS_WITH_LIBEV)
	&event_loop_ops_ev,
#endif
	NULL
};

static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;

/**
 * lws_get_library_version: get version and git hash library built from
 *
 *	returns a const char * to a string like "1.1 178d78c"
 *	representing the library version followed by the git head hash it
 *	was built from
 */
LWS_VISIBLE const char *
lws_get_library_version(void)
{
	return library_version;
}

int
lws_role_call_alpn_negotiated(struct lws *wsi, const char *alpn)
{
#if defined(LWS_WITH_TLS)
	if (!alpn)
		return 0;

	lwsl_info("%s: '%s'\n", __func__, alpn);

	LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
		if (ar->alpn && !strcmp(ar->alpn, alpn) && ar->alpn_negotiated)
			return ar->alpn_negotiated(wsi, alpn);
	LWS_FOR_EVERY_AVAILABLE_ROLE_END;
Andy Green's avatar
Andy Green committed
static const char * const mount_protocols[] = {
	"http://",
	"https://",
	"file://",
	"cgi://",
	">http://",
	">https://",
	"callback://"
Andy Green's avatar
Andy Green committed
};

Andy Green's avatar
Andy Green committed
LWS_VISIBLE void *
Andy Green's avatar
Andy Green committed
lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost,
			    const struct lws_protocols *prot, int size)
Andy Green's avatar
Andy Green committed
{
	int n = 0;

	/* allocate the vh priv array only on demand */
	if (!vhost->protocol_vh_privs) {
		vhost->protocol_vh_privs = (void **)lws_zalloc(
Andy Green's avatar
Andy Green committed
				vhost->count_protocols * sizeof(void *),
				"protocol_vh_privs");
Andy Green's avatar
Andy Green committed
		if (!vhost->protocol_vh_privs)
			return NULL;
	}

	while (n < vhost->count_protocols && &vhost->protocols[n] != prot)
		n++;

Andy Green's avatar
Andy Green committed
	if (n == vhost->count_protocols) {
		n = 0;
		while (n < vhost->count_protocols &&
		       strcmp(vhost->protocols[n].name, prot->name))
			n++;

		if (n == vhost->count_protocols)
			return NULL;
	}
Andy Green's avatar
Andy Green committed

Andy Green's avatar
Andy Green committed
	vhost->protocol_vh_privs[n] = lws_zalloc(size, "vh priv");
Andy Green's avatar
Andy Green committed
	return vhost->protocol_vh_privs[n];
}

LWS_VISIBLE void *
Andy Green's avatar
Andy Green committed
lws_protocol_vh_priv_get(struct lws_vhost *vhost,
			 const struct lws_protocols *prot)
Andy Green's avatar
Andy Green committed
{
	int n = 0;

	if (!vhost || !vhost->protocol_vh_privs)
Andy Green's avatar
Andy Green committed
		return NULL;

	while (n < vhost->count_protocols && &vhost->protocols[n] != prot)
		n++;

	if (n == vhost->count_protocols) {
Andy Green's avatar
Andy Green committed
		n = 0;
		while (n < vhost->count_protocols &&
		       strcmp(vhost->protocols[n].name, prot->name))
			n++;

		if (n == vhost->count_protocols) {
			lwsl_err("%s: unknown protocol %p\n", __func__, prot);
			return NULL;
		}
Andy Green's avatar
Andy Green committed
	}

	return vhost->protocol_vh_privs[n];
}

static const struct lws_protocol_vhost_options *
lws_vhost_protocol_options(struct lws_vhost *vh, const char *name)
{
	const struct lws_protocol_vhost_options *pvo = vh->pvo;
	while (pvo) {
		if (!strcmp(pvo->name, name))
			return pvo;
		pvo = pvo->next;
	}

	return NULL;
}

/*
 * inform every vhost that hasn't already done it, that
 * his protocols are initializing
 */
Andy Green's avatar
Andy Green committed
LWS_VISIBLE int
Andy Green's avatar
Andy Green committed
lws_protocol_init(struct lws_context *context)
{
	struct lws_vhost *vh = context->vhost_list;
	const struct lws_protocol_vhost_options *pvo, *pvo1;
Andy Green's avatar
Andy Green committed
	struct lws wsi;
	int n, any = 0;
Andy Green's avatar
Andy Green committed

	if (context->doing_protocol_init)
		return 0;

	context->doing_protocol_init = 1;

Andy Green's avatar
Andy Green committed
	memset(&wsi, 0, sizeof(wsi));
	wsi.context = context;

	lwsl_info("%s\n", __func__);
Andy Green's avatar
Andy Green committed
	while (vh) {
		wsi.vhost = vh;

		/* only do the protocol init once for a given vhost */
Loading
Loading full blame...