2014-05-06 09:47:00 +00:00
|
|
|
/*
|
2020-02-27 23:26:58 +00:00
|
|
|
Copyright (c) 2014-2020 Roger Light <roger@atchoo.org>
|
2014-05-06 09:47:00 +00:00
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
3. Neither the name of mosquitto nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived from
|
|
|
|
this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2014-05-26 18:16:59 +00:00
|
|
|
#ifdef WITH_WEBSOCKETS
|
|
|
|
|
2018-04-23 22:56:39 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2014-05-06 09:47:00 +00:00
|
|
|
#include <libwebsockets.h>
|
|
|
|
#include "mosquitto_internal.h"
|
2016-07-08 09:10:04 +00:00
|
|
|
#include "mosquitto_broker_internal.h"
|
2018-08-29 21:26:16 +00:00
|
|
|
#include "mqtt_protocol.h"
|
2014-05-06 09:47:00 +00:00
|
|
|
#include "memory_mosq.h"
|
2015-05-16 13:16:40 +00:00
|
|
|
#include "packet_mosq.h"
|
2015-05-16 11:25:35 +00:00
|
|
|
#include "sys_tree.h"
|
2019-09-25 11:17:17 +00:00
|
|
|
#include "util_mosq.h"
|
2014-05-06 09:47:00 +00:00
|
|
|
|
2014-09-17 22:14:22 +00:00
|
|
|
#include <stdlib.h>
|
2014-09-08 22:25:02 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
2019-03-05 14:01:29 +00:00
|
|
|
#ifndef WIN32
|
|
|
|
# include <sys/socket.h>
|
|
|
|
#endif
|
|
|
|
|
2019-08-29 12:23:26 +00:00
|
|
|
/* Be careful if changing these, if TX is not bigger than SERV then there can
|
|
|
|
* be very large write performance penalties.
|
|
|
|
*/
|
|
|
|
#define WS_SERV_BUF_SIZE 4096
|
|
|
|
#define WS_TX_BUF_SIZE (WS_SERV_BUF_SIZE*2)
|
|
|
|
|
2014-05-06 09:47:00 +00:00
|
|
|
extern struct mosquitto_db int_db;
|
|
|
|
|
2015-12-19 01:21:17 +00:00
|
|
|
#if defined(LWS_LIBRARY_VERSION_NUMBER)
|
|
|
|
static int callback_mqtt(
|
|
|
|
#else
|
2014-05-06 09:47:00 +00:00
|
|
|
static int callback_mqtt(struct libwebsocket_context *context,
|
2015-12-19 01:21:17 +00:00
|
|
|
#endif
|
2014-05-06 09:47:00 +00:00
|
|
|
struct libwebsocket *wsi,
|
|
|
|
enum libwebsocket_callback_reasons reason,
|
|
|
|
void *user,
|
|
|
|
void *in,
|
|
|
|
size_t len);
|
2015-12-19 01:21:17 +00:00
|
|
|
|
|
|
|
#if defined(LWS_LIBRARY_VERSION_NUMBER)
|
|
|
|
static int callback_http(
|
|
|
|
#else
|
2014-05-06 09:47:00 +00:00
|
|
|
static int callback_http(struct libwebsocket_context *context,
|
2015-12-19 01:21:17 +00:00
|
|
|
#endif
|
2014-05-06 09:47:00 +00:00
|
|
|
struct libwebsocket *wsi,
|
|
|
|
enum libwebsocket_callback_reasons reason,
|
|
|
|
void *user,
|
|
|
|
void *in,
|
|
|
|
size_t len);
|
|
|
|
|
|
|
|
enum mosq_ws_protocols {
|
|
|
|
PROTOCOL_HTTP = 0,
|
|
|
|
PROTOCOL_MQTT,
|
|
|
|
DEMO_PROTOCOL_COUNT
|
|
|
|
};
|
|
|
|
|
|
|
|
struct libws_http_data {
|
2014-09-08 22:25:02 +00:00
|
|
|
FILE *fptr;
|
2014-05-06 09:47:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct libwebsocket_protocols protocols[] = {
|
|
|
|
/* first protocol must always be HTTP handler */
|
|
|
|
{
|
2018-08-14 16:20:22 +00:00
|
|
|
"http-only", /* name */
|
|
|
|
callback_http, /* lws_callback_function */
|
|
|
|
sizeof (struct libws_http_data), /* per_session_data_size */
|
|
|
|
0, /* rx_buffer_size */
|
|
|
|
#ifndef LWS_LIBRARY_VERSION_NUMBER
|
|
|
|
0, /* no_buffer_all_partial_tx v1.3 only */
|
|
|
|
#endif
|
2015-02-16 22:02:34 +00:00
|
|
|
#ifdef LWS_FEATURE_PROTOCOLS_HAS_ID_FIELD
|
2018-08-14 16:20:22 +00:00
|
|
|
0, /* id */
|
2015-02-16 22:02:34 +00:00
|
|
|
#endif
|
2018-08-14 16:20:22 +00:00
|
|
|
#ifdef LWS_LIBRARY_VERSION_NUMBER
|
|
|
|
NULL, /* user v1.4 on */
|
|
|
|
# if LWS_LIBRARY_VERSION_NUMBER >= 2003000
|
2019-08-29 12:23:26 +00:00
|
|
|
WS_TX_BUF_SIZE /* tx_packet_size v2.3.0 */
|
2018-08-14 16:20:22 +00:00
|
|
|
# endif
|
2015-12-19 01:21:17 +00:00
|
|
|
#endif
|
2014-05-06 09:47:00 +00:00
|
|
|
},
|
|
|
|
{
|
2014-05-31 20:24:16 +00:00
|
|
|
"mqtt",
|
2014-05-06 09:47:00 +00:00
|
|
|
callback_mqtt,
|
|
|
|
sizeof(struct libws_mqtt_data),
|
2018-08-14 16:20:22 +00:00
|
|
|
0, /* rx_buffer_size */
|
|
|
|
#ifndef LWS_LIBRARY_VERSION_NUMBER
|
|
|
|
0, /* no_buffer_all_partial_tx v1.3 only */
|
|
|
|
#endif
|
2015-02-16 22:02:34 +00:00
|
|
|
#ifdef LWS_FEATURE_PROTOCOLS_HAS_ID_FIELD
|
2018-08-14 16:20:22 +00:00
|
|
|
1, /* id */
|
2015-02-16 22:02:34 +00:00
|
|
|
#endif
|
2018-08-14 16:20:22 +00:00
|
|
|
#ifdef LWS_LIBRARY_VERSION_NUMBER
|
|
|
|
NULL, /* user v1.4 on */
|
|
|
|
# if LWS_LIBRARY_VERSION_NUMBER >= 2003000
|
2019-08-29 12:23:26 +00:00
|
|
|
WS_TX_BUF_SIZE /* tx_packet_size v2.3.0 */
|
2018-08-14 16:20:22 +00:00
|
|
|
# endif
|
2015-12-19 01:21:17 +00:00
|
|
|
#endif
|
2014-05-06 09:47:00 +00:00
|
|
|
},
|
2014-06-20 09:52:10 +00:00
|
|
|
{
|
|
|
|
"mqttv3.1",
|
|
|
|
callback_mqtt,
|
|
|
|
sizeof(struct libws_mqtt_data),
|
2018-08-14 16:20:22 +00:00
|
|
|
0, /* rx_buffer_size */
|
|
|
|
#ifndef LWS_LIBRARY_VERSION_NUMBER
|
|
|
|
0, /* no_buffer_all_partial_tx v1.3 only */
|
|
|
|
#endif
|
2015-02-16 22:02:34 +00:00
|
|
|
#ifdef LWS_FEATURE_PROTOCOLS_HAS_ID_FIELD
|
2018-08-14 16:20:22 +00:00
|
|
|
2, /* id */
|
2015-02-16 22:02:34 +00:00
|
|
|
#endif
|
2018-08-14 16:20:22 +00:00
|
|
|
#ifdef LWS_LIBRARY_VERSION_NUMBER
|
|
|
|
NULL, /* user v1.4 on */
|
|
|
|
# if LWS_LIBRARY_VERSION_NUMBER >= 2003000
|
2019-08-29 12:23:26 +00:00
|
|
|
WS_TX_BUF_SIZE /* tx_packet_size v2.3.0 */
|
2018-08-14 16:20:22 +00:00
|
|
|
# endif
|
2015-12-19 01:21:17 +00:00
|
|
|
#endif
|
2014-06-20 09:52:10 +00:00
|
|
|
},
|
2018-08-14 16:20:22 +00:00
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
0, /* rx_buffer_size */
|
|
|
|
#ifndef LWS_LIBRARY_VERSION_NUMBER
|
|
|
|
0, /* no_buffer_all_partial_tx v1.3 only */
|
|
|
|
#endif
|
2015-02-16 22:02:34 +00:00
|
|
|
#ifdef LWS_FEATURE_PROTOCOLS_HAS_ID_FIELD
|
2018-08-14 16:20:22 +00:00
|
|
|
0, /* id */
|
|
|
|
#endif
|
|
|
|
#ifdef LWS_LIBRARY_VERSION_NUMBER
|
|
|
|
NULL, /* user v1.4 on */
|
|
|
|
# if LWS_LIBRARY_VERSION_NUMBER >= 2003000
|
|
|
|
0 /* tx_packet_size v2.3.0 */
|
2015-12-19 01:21:17 +00:00
|
|
|
# endif
|
2015-02-16 22:02:34 +00:00
|
|
|
#endif
|
2018-08-14 16:20:22 +00:00
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
};
|
|
|
|
|
2014-09-17 21:19:45 +00:00
|
|
|
static void easy_address(int sock, struct mosquitto *mosq)
|
|
|
|
{
|
|
|
|
char address[1024];
|
|
|
|
|
2015-05-16 17:43:06 +00:00
|
|
|
if(!net__socket_get_address(sock, address, 1024)){
|
2015-04-19 21:10:59 +00:00
|
|
|
mosq->address = mosquitto__strdup(address);
|
2014-09-17 21:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-19 01:21:17 +00:00
|
|
|
#if defined(LWS_LIBRARY_VERSION_NUMBER)
|
|
|
|
static int callback_mqtt(
|
|
|
|
#else
|
2014-05-06 09:47:00 +00:00
|
|
|
static int callback_mqtt(struct libwebsocket_context *context,
|
2015-12-19 01:21:17 +00:00
|
|
|
#endif
|
2014-05-06 09:47:00 +00:00
|
|
|
struct libwebsocket *wsi,
|
|
|
|
enum libwebsocket_callback_reasons reason,
|
|
|
|
void *user,
|
|
|
|
void *in,
|
|
|
|
size_t len)
|
|
|
|
{
|
|
|
|
struct mosquitto_db *db;
|
|
|
|
struct mosquitto *mosq = NULL;
|
2015-04-19 21:10:59 +00:00
|
|
|
struct mosquitto__packet *packet;
|
2019-08-29 12:23:26 +00:00
|
|
|
size_t txlen;
|
2019-08-29 11:12:05 +00:00
|
|
|
int count;
|
2016-08-16 21:10:41 +00:00
|
|
|
const struct libwebsocket_protocols *p;
|
2014-05-06 09:47:00 +00:00
|
|
|
struct libws_mqtt_data *u = (struct libws_mqtt_data *)user;
|
|
|
|
size_t pos;
|
|
|
|
uint8_t *buf;
|
|
|
|
int rc;
|
|
|
|
uint8_t byte;
|
|
|
|
|
|
|
|
db = &int_db;
|
|
|
|
|
|
|
|
switch (reason) {
|
|
|
|
case LWS_CALLBACK_ESTABLISHED:
|
2015-05-16 14:24:24 +00:00
|
|
|
mosq = context__init(db, WEBSOCKET_CLIENT);
|
2014-05-06 09:47:00 +00:00
|
|
|
if(mosq){
|
2016-09-08 11:24:29 +00:00
|
|
|
p = libwebsockets_get_protocol(wsi);
|
2019-08-29 11:12:05 +00:00
|
|
|
mosq->listener = p->user;
|
2016-09-29 17:51:31 +00:00
|
|
|
if(!mosq->listener){
|
2017-03-06 21:19:53 +00:00
|
|
|
mosquitto__free(mosq);
|
2016-09-29 17:51:31 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-12-19 01:21:17 +00:00
|
|
|
#if !defined(LWS_LIBRARY_VERSION_NUMBER)
|
2014-05-06 09:47:00 +00:00
|
|
|
mosq->ws_context = context;
|
2015-12-19 01:21:17 +00:00
|
|
|
#endif
|
2014-05-06 09:47:00 +00:00
|
|
|
mosq->wsi = wsi;
|
2018-04-06 01:04:28 +00:00
|
|
|
#ifdef WITH_TLS
|
2017-07-26 22:27:04 +00:00
|
|
|
if(in){
|
|
|
|
mosq->ssl = (SSL *)in;
|
|
|
|
if(!mosq->listener->ssl_ctx){
|
|
|
|
mosq->listener->ssl_ctx = SSL_get_SSL_CTX(mosq->ssl);
|
|
|
|
}
|
|
|
|
}
|
2018-04-06 01:04:28 +00:00
|
|
|
#endif
|
2014-05-06 09:47:00 +00:00
|
|
|
u->mosq = mosq;
|
2014-07-03 20:55:25 +00:00
|
|
|
}else{
|
|
|
|
return -1;
|
2014-05-06 09:47:00 +00:00
|
|
|
}
|
2014-09-17 21:19:45 +00:00
|
|
|
easy_address(libwebsocket_get_socket_fd(wsi), mosq);
|
|
|
|
if(!mosq->address){
|
|
|
|
/* getpeername and inet_ntop failed and not a bridge */
|
2015-04-19 21:10:59 +00:00
|
|
|
mosquitto__free(mosq);
|
2014-09-17 21:19:45 +00:00
|
|
|
u->mosq = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
2016-09-29 17:51:31 +00:00
|
|
|
if(mosq->listener->max_connections > 0 && mosq->listener->client_count > mosq->listener->max_connections){
|
2018-12-09 14:03:01 +00:00
|
|
|
if(db->config->connection_messages == true){
|
|
|
|
log__printf(NULL, MOSQ_LOG_NOTICE, "Client connection from %s denied: max_connections exceeded.", mosq->address);
|
|
|
|
}
|
2019-03-18 21:57:49 +00:00
|
|
|
mosquitto__free(mosq->address);
|
2017-03-06 21:19:53 +00:00
|
|
|
mosquitto__free(mosq);
|
2016-09-29 17:51:31 +00:00
|
|
|
u->mosq = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
2017-06-18 11:52:59 +00:00
|
|
|
mosq->sock = libwebsocket_get_socket_fd(wsi);
|
|
|
|
HASH_ADD(hh_sock, db->contexts_by_sock, sock, sizeof(mosq->sock), mosq);
|
2020-02-16 14:03:49 +00:00
|
|
|
mux__add_in(db, mosq);
|
2014-05-06 09:47:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_CLOSED:
|
2014-07-03 20:55:25 +00:00
|
|
|
if(!u){
|
|
|
|
return -1;
|
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
mosq = u->mosq;
|
2014-06-30 22:30:43 +00:00
|
|
|
if(mosq){
|
2019-02-02 22:39:47 +00:00
|
|
|
if(mosq->sock != INVALID_SOCKET){
|
2017-06-18 11:52:59 +00:00
|
|
|
HASH_DELETE(hh_sock, db->contexts_by_sock, mosq);
|
|
|
|
mosq->sock = INVALID_SOCKET;
|
2017-06-19 20:40:19 +00:00
|
|
|
mosq->pollfd_index = -1;
|
2020-02-15 14:49:53 +00:00
|
|
|
mux__delete(db, mosq);
|
2017-06-18 11:52:59 +00:00
|
|
|
}
|
2014-06-30 22:30:43 +00:00
|
|
|
mosq->wsi = NULL;
|
2018-04-06 01:04:28 +00:00
|
|
|
#ifdef WITH_TLS
|
2017-07-26 22:27:04 +00:00
|
|
|
mosq->ssl = NULL;
|
2018-04-06 01:04:28 +00:00
|
|
|
#endif
|
2019-04-17 08:43:38 +00:00
|
|
|
do_disconnect(db, mosq, MOSQ_ERR_CONN_LOST);
|
2014-06-23 17:18:29 +00:00
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_SERVER_WRITEABLE:
|
2014-07-03 20:55:25 +00:00
|
|
|
if(!u){
|
|
|
|
return -1;
|
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
mosq = u->mosq;
|
2017-12-27 18:21:32 +00:00
|
|
|
if(!mosq){
|
2014-06-26 21:13:22 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-09-02 21:24:29 +00:00
|
|
|
rc = db__message_write_inflight_out_latest(db, mosq);
|
|
|
|
if(rc) return -1;
|
|
|
|
rc = db__message_write_queued_out(db, mosq);
|
|
|
|
if(rc) return -1;
|
2016-03-05 22:31:52 +00:00
|
|
|
|
2014-05-06 09:47:00 +00:00
|
|
|
if(mosq->out_packet && !mosq->current_out_packet){
|
|
|
|
mosq->current_out_packet = mosq->out_packet;
|
|
|
|
mosq->out_packet = mosq->out_packet->next;
|
|
|
|
if(!mosq->out_packet){
|
|
|
|
mosq->out_packet_last = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-02 21:24:29 +00:00
|
|
|
while(mosq->current_out_packet && !lws_send_pipe_choked(mosq->wsi)){
|
2014-05-06 09:47:00 +00:00
|
|
|
packet = mosq->current_out_packet;
|
|
|
|
|
|
|
|
if(packet->pos == 0 && packet->to_process == packet->packet_length){
|
|
|
|
/* First time this packet has been dealt with.
|
|
|
|
* libwebsockets requires that the payload has
|
|
|
|
* LWS_SEND_BUFFER_PRE_PADDING space available before the
|
|
|
|
* actual data and LWS_SEND_BUFFER_POST_PADDING afterwards.
|
|
|
|
* We've already made the payload big enough to allow this,
|
|
|
|
* but need to move it into position here. */
|
|
|
|
memmove(&packet->payload[LWS_SEND_BUFFER_PRE_PADDING], packet->payload, packet->packet_length);
|
|
|
|
packet->pos += LWS_SEND_BUFFER_PRE_PADDING;
|
|
|
|
}
|
2019-08-29 12:23:26 +00:00
|
|
|
if(packet->to_process > WS_TX_BUF_SIZE){
|
|
|
|
txlen = WS_TX_BUF_SIZE;
|
|
|
|
}else{
|
|
|
|
txlen = packet->to_process;
|
|
|
|
}
|
|
|
|
count = libwebsocket_write(wsi, &packet->payload[packet->pos], txlen, LWS_WRITE_BINARY);
|
2014-05-18 19:54:44 +00:00
|
|
|
if(count < 0){
|
2020-07-15 21:06:29 +00:00
|
|
|
if (mosq->state == mosq_cs_disconnect_ws
|
|
|
|
|| mosq->state == mosq_cs_disconnecting
|
|
|
|
|| mosq->state == mosq_cs_disused){
|
|
|
|
|
2017-12-27 18:21:32 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2014-05-18 19:54:44 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2018-01-02 15:50:47 +00:00
|
|
|
#ifdef WITH_SYS_TREE
|
|
|
|
g_bytes_sent += count;
|
|
|
|
#endif
|
2014-05-06 09:47:00 +00:00
|
|
|
packet->to_process -= count;
|
|
|
|
packet->pos += count;
|
|
|
|
if(packet->to_process > 0){
|
2020-07-15 21:06:29 +00:00
|
|
|
if (mosq->state == mosq_cs_disconnect_ws
|
|
|
|
|| mosq->state == mosq_cs_disconnecting
|
|
|
|
|| mosq->state == mosq_cs_disused){
|
|
|
|
|
2017-12-27 18:21:32 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-01-02 15:50:47 +00:00
|
|
|
#ifdef WITH_SYS_TREE
|
|
|
|
g_msgs_sent++;
|
2018-11-27 09:58:39 +00:00
|
|
|
if(((packet->command)&0xF6) == CMD_PUBLISH){
|
2018-01-02 15:50:47 +00:00
|
|
|
g_pub_msgs_sent++;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-05-06 09:47:00 +00:00
|
|
|
/* Free data and reset values */
|
|
|
|
mosq->current_out_packet = mosq->out_packet;
|
|
|
|
if(mosq->out_packet){
|
|
|
|
mosq->out_packet = mosq->out_packet->next;
|
|
|
|
if(!mosq->out_packet){
|
|
|
|
mosq->out_packet_last = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-16 13:16:40 +00:00
|
|
|
packet__cleanup(packet);
|
2015-04-19 21:10:59 +00:00
|
|
|
mosquitto__free(packet);
|
2014-05-06 09:47:00 +00:00
|
|
|
|
2016-03-06 19:49:20 +00:00
|
|
|
mosq->next_msg_out = mosquitto_time() + mosq->keepalive;
|
2014-05-06 09:47:00 +00:00
|
|
|
}
|
2020-07-15 21:06:29 +00:00
|
|
|
if (mosq->state == mosq_cs_disconnect_ws
|
|
|
|
|| mosq->state == mosq_cs_disconnecting
|
|
|
|
|| mosq->state == mosq_cs_disused){
|
|
|
|
|
2017-12-27 18:21:32 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2014-07-03 17:48:40 +00:00
|
|
|
if(mosq->current_out_packet){
|
|
|
|
libwebsocket_callback_on_writable(mosq->ws_context, mosq->wsi);
|
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_RECEIVE:
|
2014-09-22 23:35:51 +00:00
|
|
|
if(!u || !u->mosq){
|
2014-07-03 20:55:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
mosq = u->mosq;
|
|
|
|
pos = 0;
|
|
|
|
buf = (uint8_t *)in;
|
2015-05-16 11:25:35 +00:00
|
|
|
G_BYTES_RECEIVED_INC(len);
|
2014-05-06 09:47:00 +00:00
|
|
|
while(pos < len){
|
|
|
|
if(!mosq->in_packet.command){
|
|
|
|
mosq->in_packet.command = buf[pos];
|
|
|
|
pos++;
|
|
|
|
/* Clients must send CONNECT as their first command. */
|
2018-11-27 09:58:39 +00:00
|
|
|
if(mosq->state == mosq_cs_new && (mosq->in_packet.command&0xF0) != CMD_CONNECT){
|
2014-05-06 09:47:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2015-03-27 01:07:48 +00:00
|
|
|
if(mosq->in_packet.remaining_count <= 0){
|
2014-05-06 09:47:00 +00:00
|
|
|
do{
|
|
|
|
if(pos == len){
|
2014-05-18 21:45:09 +00:00
|
|
|
return 0;
|
2014-05-06 09:47:00 +00:00
|
|
|
}
|
|
|
|
byte = buf[pos];
|
|
|
|
pos++;
|
|
|
|
|
2015-03-27 01:07:48 +00:00
|
|
|
mosq->in_packet.remaining_count--;
|
2014-05-06 09:47:00 +00:00
|
|
|
/* Max 4 bytes length for remaining length as defined by protocol.
|
|
|
|
* Anything more likely means a broken/malicious client.
|
|
|
|
*/
|
2015-03-27 01:07:48 +00:00
|
|
|
if(mosq->in_packet.remaining_count < -4){
|
2014-05-06 09:47:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
mosq->in_packet.remaining_length += (byte & 127) * mosq->in_packet.remaining_mult;
|
|
|
|
mosq->in_packet.remaining_mult *= 128;
|
|
|
|
}while((byte & 128) != 0);
|
2015-03-27 01:07:48 +00:00
|
|
|
mosq->in_packet.remaining_count *= -1;
|
2014-05-06 09:47:00 +00:00
|
|
|
|
|
|
|
if(mosq->in_packet.remaining_length > 0){
|
2015-04-19 21:10:59 +00:00
|
|
|
mosq->in_packet.payload = mosquitto__malloc(mosq->in_packet.remaining_length*sizeof(uint8_t));
|
2014-06-30 22:30:43 +00:00
|
|
|
if(!mosq->in_packet.payload){
|
|
|
|
return -1;
|
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
mosq->in_packet.to_process = mosq->in_packet.remaining_length;
|
|
|
|
}
|
|
|
|
}
|
2015-05-06 21:40:10 +00:00
|
|
|
if(mosq->in_packet.to_process>0){
|
2014-05-06 09:47:00 +00:00
|
|
|
if(len - pos >= mosq->in_packet.to_process){
|
|
|
|
memcpy(&mosq->in_packet.payload[mosq->in_packet.pos], &buf[pos], mosq->in_packet.to_process);
|
|
|
|
mosq->in_packet.pos += mosq->in_packet.to_process;
|
|
|
|
pos += mosq->in_packet.to_process;
|
|
|
|
mosq->in_packet.to_process = 0;
|
|
|
|
}else{
|
|
|
|
memcpy(&mosq->in_packet.payload[mosq->in_packet.pos], &buf[pos], len-pos);
|
|
|
|
mosq->in_packet.pos += len-pos;
|
|
|
|
mosq->in_packet.to_process -= len-pos;
|
2015-05-06 21:40:10 +00:00
|
|
|
return 0;
|
2014-05-06 09:47:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* All data for this packet is read. */
|
|
|
|
mosq->in_packet.pos = 0;
|
2015-05-16 11:25:35 +00:00
|
|
|
|
2014-05-06 09:47:00 +00:00
|
|
|
#ifdef WITH_SYS_TREE
|
2015-05-16 13:16:40 +00:00
|
|
|
G_MSGS_RECEIVED_INC(1);
|
2018-11-27 09:58:39 +00:00
|
|
|
if(((mosq->in_packet.command)&0xF5) == CMD_PUBLISH){
|
2015-05-16 13:16:40 +00:00
|
|
|
G_PUB_MSGS_RECEIVED_INC(1);
|
2014-05-06 09:47:00 +00:00
|
|
|
}
|
|
|
|
#endif
|
2015-05-18 08:29:22 +00:00
|
|
|
rc = handle__packet(db, mosq);
|
2014-05-06 09:47:00 +00:00
|
|
|
|
|
|
|
/* Free data and reset values */
|
2015-05-16 13:16:40 +00:00
|
|
|
packet__cleanup(&mosq->in_packet);
|
2014-05-06 09:47:00 +00:00
|
|
|
|
2020-09-25 08:15:22 +00:00
|
|
|
keepalive__update(mosq);
|
2014-05-06 09:47:00 +00:00
|
|
|
|
2017-12-27 18:21:32 +00:00
|
|
|
if(rc && (mosq->out_packet || mosq->current_out_packet)) {
|
|
|
|
if(mosq->state != mosq_cs_disconnecting){
|
2019-09-25 11:17:17 +00:00
|
|
|
mosquitto__set_state(mosq, mosq_cs_disconnect_ws);
|
2017-12-27 18:21:32 +00:00
|
|
|
}
|
|
|
|
libwebsocket_callback_on_writable(mosq->ws_context, mosq->wsi);
|
|
|
|
} else if (rc) {
|
2019-04-17 08:43:38 +00:00
|
|
|
do_disconnect(db, mosq, MOSQ_ERR_CONN_LOST);
|
2014-05-06 09:47:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-13 01:01:35 +00:00
|
|
|
static char *http__canonical_filename(
|
2018-08-14 16:20:22 +00:00
|
|
|
#ifndef LWS_LIBRARY_VERSION_NUMBER
|
|
|
|
struct libwebsocket_context *context,
|
|
|
|
#endif
|
2018-03-13 01:01:35 +00:00
|
|
|
struct libwebsocket *wsi,
|
|
|
|
const char *in,
|
|
|
|
const char *http_dir)
|
|
|
|
{
|
|
|
|
size_t inlen, slen;
|
|
|
|
char *filename, *filename_canonical;
|
|
|
|
|
|
|
|
inlen = strlen(in);
|
|
|
|
if(in[inlen-1] == '/'){
|
|
|
|
slen = strlen(http_dir) + inlen + strlen("/index.html") + 2;
|
|
|
|
}else{
|
|
|
|
slen = strlen(http_dir) + inlen + 2;
|
|
|
|
}
|
|
|
|
filename = mosquitto__malloc(slen);
|
|
|
|
if(!filename){
|
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if(((char *)in)[inlen-1] == '/'){
|
|
|
|
snprintf(filename, slen, "%s%sindex.html", http_dir, (char *)in);
|
|
|
|
}else{
|
|
|
|
snprintf(filename, slen, "%s%s", http_dir, (char *)in);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Get canonical path and check it is within our http_dir */
|
|
|
|
#ifdef WIN32
|
|
|
|
filename_canonical = _fullpath(NULL, filename, 0);
|
|
|
|
mosquitto__free(filename);
|
|
|
|
if(!filename_canonical){
|
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
filename_canonical = realpath(filename, NULL);
|
|
|
|
mosquitto__free(filename);
|
|
|
|
if(!filename_canonical){
|
|
|
|
if(errno == EACCES){
|
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_FORBIDDEN, NULL);
|
|
|
|
}else if(errno == EINVAL || errno == EIO || errno == ELOOP){
|
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL);
|
|
|
|
}else if(errno == ENAMETOOLONG){
|
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_REQ_URI_TOO_LONG, NULL);
|
|
|
|
}else if(errno == ENOENT || errno == ENOTDIR){
|
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_NOT_FOUND, NULL);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if(strncmp(http_dir, filename_canonical, strlen(http_dir))){
|
|
|
|
/* Requested file isn't within http_dir, deny access. */
|
|
|
|
free(filename_canonical);
|
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_FORBIDDEN, NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return filename_canonical;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-19 01:21:17 +00:00
|
|
|
#if defined(LWS_LIBRARY_VERSION_NUMBER)
|
|
|
|
static int callback_http(
|
|
|
|
#else
|
2014-05-06 09:47:00 +00:00
|
|
|
static int callback_http(struct libwebsocket_context *context,
|
2015-12-19 01:21:17 +00:00
|
|
|
#endif
|
2014-05-06 09:47:00 +00:00
|
|
|
struct libwebsocket *wsi,
|
|
|
|
enum libwebsocket_callback_reasons reason,
|
|
|
|
void *user,
|
|
|
|
void *in,
|
|
|
|
size_t len)
|
|
|
|
{
|
2014-09-08 22:25:02 +00:00
|
|
|
struct libws_http_data *u = (struct libws_http_data *)user;
|
2014-09-08 17:39:51 +00:00
|
|
|
struct libws_mqtt_hack *hack;
|
|
|
|
char *http_dir;
|
2018-03-13 01:01:35 +00:00
|
|
|
size_t buflen;
|
2015-02-16 22:02:34 +00:00
|
|
|
size_t wlen;
|
2018-03-13 01:01:35 +00:00
|
|
|
char *filename_canonical;
|
2014-09-08 22:25:02 +00:00
|
|
|
unsigned char buf[4096];
|
|
|
|
struct stat filestat;
|
2017-06-18 11:52:59 +00:00
|
|
|
struct mosquitto_db *db = &int_db;
|
|
|
|
struct mosquitto *mosq;
|
|
|
|
struct lws_pollargs *pollargs = (struct lws_pollargs *)in;
|
2014-09-08 17:39:51 +00:00
|
|
|
|
2014-06-03 01:10:55 +00:00
|
|
|
/* FIXME - ssl cert verification is done here. */
|
2014-09-08 17:39:51 +00:00
|
|
|
|
|
|
|
switch (reason) {
|
|
|
|
case LWS_CALLBACK_HTTP:
|
2015-08-18 22:33:23 +00:00
|
|
|
if(!u){
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-12-19 01:21:17 +00:00
|
|
|
#if defined(LWS_LIBRARY_VERSION_NUMBER)
|
|
|
|
hack = (struct libws_mqtt_hack *)lws_context_user(lws_get_context(wsi));
|
|
|
|
#else
|
2014-09-08 17:39:51 +00:00
|
|
|
hack = (struct libws_mqtt_hack *)libwebsocket_context_user(context);
|
2015-12-19 01:21:17 +00:00
|
|
|
#endif
|
2014-09-08 17:39:51 +00:00
|
|
|
if(!hack){
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
http_dir = hack->http_dir;
|
|
|
|
|
|
|
|
if(!http_dir){
|
|
|
|
/* http disabled */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Forbid POST */
|
|
|
|
if(lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)){
|
2014-09-08 22:25:02 +00:00
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_METHOD_NOT_ALLOWED, NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-08-14 16:20:22 +00:00
|
|
|
#if defined(LWS_LIBRARY_VERSION_NUMBER)
|
2018-03-13 01:01:35 +00:00
|
|
|
filename_canonical = http__canonical_filename(wsi, (char *)in, http_dir);
|
2018-08-14 16:20:22 +00:00
|
|
|
#else
|
|
|
|
filename_canonical = http__canonical_filename(context, wsi, (char *)in, http_dir);
|
|
|
|
#endif
|
2018-03-13 01:01:35 +00:00
|
|
|
if(!filename_canonical) return -1;
|
2014-09-08 17:39:51 +00:00
|
|
|
|
2018-03-13 01:01:35 +00:00
|
|
|
u->fptr = fopen(filename_canonical, "rb");
|
2014-09-08 22:25:02 +00:00
|
|
|
if(!u->fptr){
|
2018-03-13 01:01:35 +00:00
|
|
|
free(filename_canonical);
|
2014-09-08 22:25:02 +00:00
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_NOT_FOUND, NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if(fstat(fileno(u->fptr), &filestat) < 0){
|
2018-03-13 01:01:35 +00:00
|
|
|
free(filename_canonical);
|
2014-09-08 22:25:02 +00:00
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL);
|
|
|
|
fclose(u->fptr);
|
2017-01-21 07:50:07 +00:00
|
|
|
u->fptr = NULL;
|
2014-09-08 22:25:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2018-03-13 01:01:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
if((filestat.st_mode & S_IFDIR) == S_IFDIR){
|
|
|
|
fclose(u->fptr);
|
|
|
|
u->fptr = NULL;
|
|
|
|
free(filename_canonical);
|
|
|
|
|
|
|
|
/* FIXME - use header functions from lws 2.x */
|
|
|
|
buflen = snprintf((char *)buf, 4096, "HTTP/1.0 302 OK\r\n"
|
|
|
|
"Location: %s/\r\n\r\n",
|
|
|
|
(char *)in);
|
|
|
|
return libwebsocket_write(wsi, buf, buflen, LWS_WRITE_HTTP);
|
|
|
|
}
|
|
|
|
|
2014-09-19 09:43:14 +00:00
|
|
|
if((filestat.st_mode & S_IFREG) != S_IFREG){
|
2014-09-08 22:25:02 +00:00
|
|
|
libwebsockets_return_http_status(context, wsi, HTTP_STATUS_FORBIDDEN, NULL);
|
2017-01-21 07:50:07 +00:00
|
|
|
fclose(u->fptr);
|
|
|
|
u->fptr = NULL;
|
2018-03-13 01:01:35 +00:00
|
|
|
free(filename_canonical);
|
2014-09-08 22:25:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-03-13 01:01:35 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_DEBUG, "http serving file \"%s\".", filename_canonical);
|
|
|
|
free(filename_canonical);
|
|
|
|
/* FIXME - use header functions from lws 2.x */
|
2014-09-08 22:25:02 +00:00
|
|
|
buflen = snprintf((char *)buf, 4096, "HTTP/1.0 200 OK\r\n"
|
|
|
|
"Server: mosquitto\r\n"
|
|
|
|
"Content-Length: %u\r\n\r\n",
|
|
|
|
(unsigned int)filestat.st_size);
|
|
|
|
if(libwebsocket_write(wsi, buf, buflen, LWS_WRITE_HTTP) < 0){
|
|
|
|
fclose(u->fptr);
|
2017-01-20 18:25:04 +00:00
|
|
|
u->fptr = NULL;
|
2014-09-08 22:25:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
libwebsocket_callback_on_writable(context, wsi);
|
2014-09-08 17:39:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_HTTP_BODY:
|
|
|
|
/* For extra POST data? */
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
|
|
|
|
/* For end of extra POST data? */
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_FILTER_HTTP_CONNECTION:
|
|
|
|
/* Access control here */
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_HTTP_WRITEABLE:
|
|
|
|
/* Send our data here */
|
2015-08-18 22:33:23 +00:00
|
|
|
if(u && u->fptr){
|
2014-09-08 22:25:02 +00:00
|
|
|
do{
|
|
|
|
buflen = fread(buf, 1, sizeof(buf), u->fptr);
|
|
|
|
if(buflen < 1){
|
|
|
|
fclose(u->fptr);
|
2017-01-20 18:25:04 +00:00
|
|
|
u->fptr = NULL;
|
2014-09-08 22:25:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
wlen = libwebsocket_write(wsi, buf, buflen, LWS_WRITE_HTTP);
|
|
|
|
if(wlen < buflen){
|
2014-09-22 23:45:12 +00:00
|
|
|
if(fseek(u->fptr, buflen-wlen, SEEK_CUR) < 0){
|
|
|
|
fclose(u->fptr);
|
|
|
|
u->fptr = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
2014-09-08 22:25:02 +00:00
|
|
|
}else{
|
|
|
|
if(buflen < sizeof(buf)){
|
|
|
|
fclose(u->fptr);
|
|
|
|
u->fptr = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}while(u->fptr && !lws_send_pipe_choked(wsi));
|
|
|
|
libwebsocket_callback_on_writable(context, wsi);
|
|
|
|
}else{
|
2014-09-17 21:27:18 +00:00
|
|
|
return -1;
|
2014-09-08 22:25:02 +00:00
|
|
|
}
|
2017-01-21 07:50:07 +00:00
|
|
|
break;
|
2017-01-20 18:25:04 +00:00
|
|
|
|
|
|
|
case LWS_CALLBACK_CLOSED:
|
|
|
|
case LWS_CALLBACK_CLOSED_HTTP:
|
|
|
|
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
|
|
|
|
if(u && u->fptr){
|
|
|
|
fclose(u->fptr);
|
|
|
|
u->fptr = NULL;
|
|
|
|
}
|
|
|
|
break;
|
2014-09-08 17:39:51 +00:00
|
|
|
|
2017-06-18 11:52:59 +00:00
|
|
|
case LWS_CALLBACK_ADD_POLL_FD:
|
|
|
|
case LWS_CALLBACK_DEL_POLL_FD:
|
|
|
|
case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
|
|
|
|
HASH_FIND(hh_sock, db->contexts_by_sock, &pollargs->fd, sizeof(pollargs->fd), mosq);
|
2020-02-16 14:03:49 +00:00
|
|
|
if(mosq){
|
|
|
|
if(pollargs->events & POLLOUT){
|
|
|
|
mux__add_out(db, mosq);
|
|
|
|
mosq->ws_want_write = true;
|
|
|
|
}else{
|
|
|
|
mux__remove_out(db, mosq);
|
|
|
|
}
|
2017-06-18 11:52:59 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2018-11-08 12:10:28 +00:00
|
|
|
#ifdef WITH_TLS
|
|
|
|
case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
|
|
|
|
if(!len || (SSL_get_verify_result((SSL*)in) != X509_V_OK)){
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2014-09-08 17:39:51 +00:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-05-06 09:47:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-02-13 22:57:49 +00:00
|
|
|
static void log_wrap(int level, const char *line)
|
|
|
|
{
|
|
|
|
char *l = (char *)line;
|
2020-03-12 10:29:11 +00:00
|
|
|
l[strlen(line)-1] = '\0'; /* Remove \n */
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_WEBSOCKETS, "%s", l);
|
2015-02-13 22:57:49 +00:00
|
|
|
}
|
|
|
|
|
2017-10-03 16:25:35 +00:00
|
|
|
struct libwebsocket_context *mosq_websockets_init(struct mosquitto__listener *listener, const struct mosquitto__config *conf)
|
2014-05-06 09:47:00 +00:00
|
|
|
{
|
|
|
|
struct lws_context_creation_info info;
|
2014-07-28 13:14:36 +00:00
|
|
|
struct libwebsocket_protocols *p;
|
|
|
|
int protocol_count;
|
|
|
|
int i;
|
2014-09-08 17:21:53 +00:00
|
|
|
struct libws_mqtt_hack *user;
|
2014-07-28 13:14:36 +00:00
|
|
|
|
|
|
|
/* Count valid protocols */
|
|
|
|
for(protocol_count=0; protocols[protocol_count].name; protocol_count++);
|
|
|
|
|
2015-04-19 21:10:59 +00:00
|
|
|
p = mosquitto__calloc(protocol_count+1, sizeof(struct libwebsocket_protocols));
|
2014-07-28 13:14:36 +00:00
|
|
|
if(!p){
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Out of memory.");
|
2014-07-28 13:14:36 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
for(i=0; protocols[i].name; i++){
|
|
|
|
p[i].name = protocols[i].name;
|
|
|
|
p[i].callback = protocols[i].callback;
|
|
|
|
p[i].per_session_data_size = protocols[i].per_session_data_size;
|
|
|
|
p[i].rx_buffer_size = protocols[i].rx_buffer_size;
|
2019-08-29 11:12:05 +00:00
|
|
|
p[i].user = listener;
|
2014-07-28 13:14:36 +00:00
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
2016-05-26 08:21:15 +00:00
|
|
|
info.iface = listener->host;
|
2014-06-03 01:10:55 +00:00
|
|
|
info.port = listener->port;
|
2014-07-28 13:14:36 +00:00
|
|
|
info.protocols = p;
|
2014-05-06 09:47:00 +00:00
|
|
|
info.gid = -1;
|
|
|
|
info.uid = -1;
|
2014-06-03 01:10:55 +00:00
|
|
|
#ifdef WITH_TLS
|
|
|
|
info.ssl_ca_filepath = listener->cafile;
|
|
|
|
info.ssl_cert_filepath = listener->certfile;
|
|
|
|
info.ssl_private_key_filepath = listener->keyfile;
|
|
|
|
info.ssl_cipher_list = listener->ciphers;
|
|
|
|
if(listener->require_certificate){
|
|
|
|
info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
|
|
|
|
}
|
|
|
|
#endif
|
2017-07-18 21:12:51 +00:00
|
|
|
|
2016-06-06 14:53:05 +00:00
|
|
|
#if LWS_LIBRARY_VERSION_MAJOR>1
|
2016-06-06 15:02:55 +00:00
|
|
|
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
2016-06-06 14:53:05 +00:00
|
|
|
#endif
|
2018-11-20 12:23:27 +00:00
|
|
|
if(listener->socket_domain == AF_INET){
|
|
|
|
info.options |= LWS_SERVER_OPTION_DISABLE_IPV6;
|
|
|
|
}
|
2017-10-03 16:25:35 +00:00
|
|
|
#if defined(LWS_LIBRARY_VERSION_NUMBER) && LWS_LIBRARY_VERSION_NUMBER>=1007000
|
|
|
|
info.max_http_header_data = conf->websockets_headers_size;
|
|
|
|
#endif
|
2014-09-17 20:55:02 +00:00
|
|
|
|
2015-04-19 21:10:59 +00:00
|
|
|
user = mosquitto__calloc(1, sizeof(struct libws_mqtt_hack));
|
2014-09-08 17:21:53 +00:00
|
|
|
if(!user){
|
2015-04-19 21:10:59 +00:00
|
|
|
mosquitto__free(p);
|
2016-06-21 22:33:58 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Out of memory.");
|
2014-06-30 22:30:43 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2014-09-08 22:25:02 +00:00
|
|
|
|
2014-09-17 22:14:22 +00:00
|
|
|
if(listener->http_dir){
|
2014-09-08 22:25:02 +00:00
|
|
|
#ifdef WIN32
|
2014-09-17 22:14:22 +00:00
|
|
|
user->http_dir = _fullpath(NULL, listener->http_dir, 0);
|
2014-09-08 22:25:02 +00:00
|
|
|
#else
|
2014-09-15 20:43:44 +00:00
|
|
|
user->http_dir = realpath(listener->http_dir, NULL);
|
2014-09-17 22:14:22 +00:00
|
|
|
#endif
|
2014-09-15 20:43:44 +00:00
|
|
|
if(!user->http_dir){
|
2015-04-19 21:10:59 +00:00
|
|
|
mosquitto__free(user);
|
|
|
|
mosquitto__free(p);
|
2017-03-06 21:19:53 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open http dir \"%s\".", listener->http_dir);
|
2014-09-15 20:43:44 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2014-09-08 22:25:02 +00:00
|
|
|
}
|
2014-09-17 22:14:22 +00:00
|
|
|
|
2014-09-08 17:21:53 +00:00
|
|
|
info.user = user;
|
2019-09-12 16:15:46 +00:00
|
|
|
#if defined(LWS_LIBRARY_VERSION_NUMBER) && LWS_LIBRARY_VERSION_NUMBER>=2004000
|
2019-08-29 12:23:26 +00:00
|
|
|
info.pt_serv_buf_size = WS_SERV_BUF_SIZE;
|
2019-09-12 16:15:46 +00:00
|
|
|
#endif
|
2014-09-17 20:50:08 +00:00
|
|
|
listener->ws_protocol = p;
|
2014-05-06 09:47:00 +00:00
|
|
|
|
2017-10-03 16:25:35 +00:00
|
|
|
lws_set_log_level(conf->websockets_log_level, log_wrap);
|
2014-05-06 09:47:00 +00:00
|
|
|
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "Opening websockets listen socket on port %d.", listener->port);
|
2014-05-06 09:47:00 +00:00
|
|
|
return libwebsocket_create_context(&info);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|