2014-05-07 22:27:00 +00:00
|
|
|
/*
|
2019-02-28 16:56:15 +00:00
|
|
|
Copyright (c) 2009-2019 Roger Light <roger@atchoo.org>
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
All rights reserved. This program and the accompanying materials
|
|
|
|
are made available under the terms of the Eclipse Public License v1.0
|
|
|
|
and Eclipse Distribution License v1.0 which accompany this distribution.
|
|
|
|
|
|
|
|
The Eclipse Public License is available at
|
|
|
|
http://www.eclipse.org/legal/epl-v10.html
|
|
|
|
and the Eclipse Distribution License is available at
|
|
|
|
http://www.eclipse.org/org/documents/edl-v10.php.
|
|
|
|
|
|
|
|
Contributors:
|
|
|
|
Roger Light - initial implementation and documentation.
|
2017-07-27 17:43:09 +00:00
|
|
|
Tatsuzo Osawa - Add epoll.
|
2014-05-07 22:27:00 +00:00
|
|
|
*/
|
|
|
|
|
2018-08-16 10:14:51 +00:00
|
|
|
#include "config.h"
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-08-30 19:44:17 +00:00
|
|
|
#ifndef WIN32
|
|
|
|
# define _GNU_SOURCE
|
|
|
|
#endif
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#ifndef WIN32
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
#include <sys/epoll.h>
|
|
|
|
#define MAX_EVENTS 1000
|
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
#include <poll.h>
|
2017-07-16 15:11:04 +00:00
|
|
|
#include <unistd.h>
|
2014-05-07 22:27:00 +00:00
|
|
|
#else
|
|
|
|
#include <process.h>
|
|
|
|
#include <winsock2.h>
|
|
|
|
#include <ws2tcpip.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2014-10-24 21:49:48 +00:00
|
|
|
#ifndef WIN32
|
|
|
|
# include <sys/socket.h>
|
|
|
|
#endif
|
2014-09-14 17:08:09 +00:00
|
|
|
#include <time.h>
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2014-05-06 09:47:00 +00:00
|
|
|
#ifdef WITH_WEBSOCKETS
|
|
|
|
# include <libwebsockets.h>
|
|
|
|
#endif
|
|
|
|
|
2016-07-08 09:10:04 +00:00
|
|
|
#include "mosquitto_broker_internal.h"
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "memory_mosq.h"
|
2015-04-29 20:23:59 +00:00
|
|
|
#include "packet_mosq.h"
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "send_mosq.h"
|
2015-05-16 11:25:35 +00:00
|
|
|
#include "sys_tree.h"
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "time_mosq.h"
|
|
|
|
#include "util_mosq.h"
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
extern bool flag_reload;
|
|
|
|
#ifdef WITH_PERSISTENCE
|
|
|
|
extern bool flag_db_backup;
|
|
|
|
#endif
|
|
|
|
extern bool flag_tree_print;
|
|
|
|
extern int run;
|
|
|
|
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
static void loop_handle_reads_writes(struct mosquitto_db *db, mosq_sock_t sock, uint32_t events);
|
|
|
|
#else
|
2014-05-07 22:27:00 +00:00
|
|
|
static void loop_handle_reads_writes(struct mosquitto_db *db, struct pollfd *pollfds);
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2015-03-27 20:50:16 +00:00
|
|
|
#ifdef WITH_WEBSOCKETS
|
|
|
|
static void temp__expire_websockets_clients(struct mosquitto_db *db)
|
|
|
|
{
|
|
|
|
struct mosquitto *context, *ctxt_tmp;
|
|
|
|
static time_t last_check = 0;
|
|
|
|
time_t now = mosquitto_time();
|
|
|
|
char *id;
|
|
|
|
|
|
|
|
if(now - last_check > 60){
|
|
|
|
HASH_ITER(hh_id, db->contexts_by_id, context, ctxt_tmp){
|
|
|
|
if(context->wsi && context->sock != INVALID_SOCKET){
|
|
|
|
if(context->keepalive && now - context->last_msg_in > (time_t)(context->keepalive)*3/2){
|
|
|
|
if(db->config->connection_messages == true){
|
|
|
|
if(context->id){
|
|
|
|
id = context->id;
|
|
|
|
}else{
|
|
|
|
id = "<unknown>";
|
|
|
|
}
|
2018-12-09 14:03:01 +00:00
|
|
|
if(db->config->connection_messages == true){
|
|
|
|
log__printf(NULL, MOSQ_LOG_NOTICE, "Client %s has exceeded timeout, disconnecting.", id);
|
|
|
|
}
|
2015-03-27 20:50:16 +00:00
|
|
|
}
|
|
|
|
/* Client has exceeded keepalive*1.5 */
|
|
|
|
do_disconnect(db, context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
last_check = mosquitto_time();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-03-13 14:11:50 +00:00
|
|
|
int mosquitto_main_loop(struct mosquitto_db *db, mosq_sock_t *listensock, int listensock_count)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
2014-09-15 21:13:13 +00:00
|
|
|
#ifdef WITH_SYS_TREE
|
2014-05-07 22:27:00 +00:00
|
|
|
time_t start_time = mosquitto_time();
|
2014-09-15 21:13:13 +00:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_PERSISTENCE
|
2014-05-07 22:27:00 +00:00
|
|
|
time_t last_backup = mosquitto_time();
|
2014-09-15 21:13:13 +00:00
|
|
|
#endif
|
2014-06-30 22:37:37 +00:00
|
|
|
time_t now = 0;
|
2014-05-07 22:27:00 +00:00
|
|
|
int time_count;
|
|
|
|
int fdcount;
|
2014-06-23 16:57:35 +00:00
|
|
|
struct mosquitto *context, *ctxt_tmp;
|
2014-05-07 22:27:00 +00:00
|
|
|
#ifndef WIN32
|
|
|
|
sigset_t sigblock, origsig;
|
|
|
|
#endif
|
|
|
|
int i;
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
int j;
|
|
|
|
struct epoll_event ev, events[MAX_EVENTS];
|
|
|
|
#else
|
2014-05-07 22:27:00 +00:00
|
|
|
struct pollfd *pollfds = NULL;
|
|
|
|
int pollfd_index;
|
2017-06-18 11:52:59 +00:00
|
|
|
int pollfd_max;
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
#ifdef WITH_BRIDGE
|
|
|
|
int rc;
|
2019-02-06 13:42:49 +00:00
|
|
|
int err;
|
|
|
|
socklen_t len;
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
2014-06-23 16:57:35 +00:00
|
|
|
time_t expiration_check_time = 0;
|
2015-01-26 21:02:53 +00:00
|
|
|
char *id;
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
sigemptyset(&sigblock);
|
|
|
|
sigaddset(&sigblock, SIGINT);
|
2017-06-27 21:32:10 +00:00
|
|
|
sigaddset(&sigblock, SIGTERM);
|
2016-07-19 14:05:53 +00:00
|
|
|
sigaddset(&sigblock, SIGUSR1);
|
|
|
|
sigaddset(&sigblock, SIGUSR2);
|
2017-06-27 21:32:10 +00:00
|
|
|
sigaddset(&sigblock, SIGHUP);
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
|
|
|
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifndef WITH_EPOLL
|
2017-06-18 11:52:59 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
pollfd_max = _getmaxstdio();
|
|
|
|
#else
|
2017-07-16 15:11:04 +00:00
|
|
|
pollfd_max = sysconf(_SC_OPEN_MAX);
|
2017-06-18 11:52:59 +00:00
|
|
|
#endif
|
|
|
|
|
2017-07-16 21:52:01 +00:00
|
|
|
pollfds = mosquitto__malloc(sizeof(struct pollfd)*pollfd_max);
|
2017-06-18 11:52:59 +00:00
|
|
|
if(!pollfds){
|
2017-07-16 21:52:01 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
2017-06-18 11:52:59 +00:00
|
|
|
return MOSQ_ERR_NOMEM;
|
|
|
|
}
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2017-06-18 11:52:59 +00:00
|
|
|
|
2014-06-23 16:57:35 +00:00
|
|
|
if(db->config->persistent_client_expiration > 0){
|
2014-08-19 00:11:22 +00:00
|
|
|
expiration_check_time = time(NULL) + 3600;
|
2014-06-23 16:57:35 +00:00
|
|
|
}
|
|
|
|
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
db->epollfd = 0;
|
|
|
|
if ((db->epollfd = epoll_create(MAX_EVENTS)) == -1) {
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error in epoll creating: %s", strerror(errno));
|
|
|
|
return MOSQ_ERR_UNKNOWN;
|
|
|
|
}
|
|
|
|
memset(&ev, 0, sizeof(struct epoll_event));
|
|
|
|
memset(&events, 0, sizeof(struct epoll_event)*MAX_EVENTS);
|
|
|
|
for(i=0; i<listensock_count; i++){
|
|
|
|
ev.data.fd = listensock[i];
|
|
|
|
ev.events = EPOLLIN;
|
|
|
|
if (epoll_ctl(db->epollfd, EPOLL_CTL_ADD, listensock[i], &ev) == -1) {
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error in epoll initial registering: %s", strerror(errno));
|
|
|
|
(void)close(db->epollfd);
|
|
|
|
db->epollfd = 0;
|
|
|
|
return MOSQ_ERR_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef WITH_BRIDGE
|
|
|
|
HASH_ITER(hh_sock, db->contexts_by_sock, context, ctxt_tmp){
|
|
|
|
if(context->bridge){
|
|
|
|
ev.data.fd = context->sock;
|
|
|
|
ev.events = EPOLLIN;
|
|
|
|
context->events = EPOLLIN;
|
|
|
|
if (epoll_ctl(db->epollfd, EPOLL_CTL_ADD, context->sock, &ev) == -1) {
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error in epoll initial registering bridge: %s", strerror(errno));
|
|
|
|
(void)close(db->epollfd);
|
|
|
|
db->epollfd = 0;
|
|
|
|
return MOSQ_ERR_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
while(run){
|
2015-05-16 14:24:24 +00:00
|
|
|
context__free_disused(db);
|
2014-05-07 22:27:00 +00:00
|
|
|
#ifdef WITH_SYS_TREE
|
|
|
|
if(db->config->sys_interval > 0){
|
2016-07-08 08:14:11 +00:00
|
|
|
sys_tree__update(db, db->config->sys_interval, start_time);
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifndef WITH_EPOLL
|
2017-06-18 11:52:59 +00:00
|
|
|
memset(pollfds, -1, sizeof(struct pollfd)*pollfd_max);
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
pollfd_index = 0;
|
|
|
|
for(i=0; i<listensock_count; i++){
|
|
|
|
pollfds[pollfd_index].fd = listensock[i];
|
|
|
|
pollfds[pollfd_index].events = POLLIN;
|
|
|
|
pollfds[pollfd_index].revents = 0;
|
|
|
|
pollfd_index++;
|
|
|
|
}
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
time_count = 0;
|
2014-06-23 16:57:35 +00:00
|
|
|
HASH_ITER(hh_sock, db->contexts_by_sock, context, ctxt_tmp){
|
|
|
|
if(time_count > 0){
|
|
|
|
time_count--;
|
|
|
|
}else{
|
|
|
|
time_count = 1000;
|
|
|
|
now = mosquitto_time();
|
|
|
|
}
|
|
|
|
context->pollfd_index = -1;
|
|
|
|
|
|
|
|
if(context->sock != INVALID_SOCKET){
|
|
|
|
#ifdef WITH_BRIDGE
|
|
|
|
if(context->bridge){
|
2015-04-19 21:10:59 +00:00
|
|
|
mosquitto__check_keepalive(db, context);
|
2014-06-23 16:57:35 +00:00
|
|
|
if(context->bridge->round_robin == false
|
|
|
|
&& context->bridge->cur_address != 0
|
2018-09-19 13:40:22 +00:00
|
|
|
&& context->bridge->primary_retry
|
2014-06-23 16:57:35 +00:00
|
|
|
&& now > context->bridge->primary_retry){
|
|
|
|
|
2018-09-19 13:40:22 +00:00
|
|
|
if(context->bridge->primary_retry_sock == INVALID_SOCKET){
|
2019-03-13 14:11:50 +00:00
|
|
|
rc = net__try_connect(context->bridge->addresses[0].address,
|
2018-09-19 13:40:22 +00:00
|
|
|
context->bridge->addresses[0].port,
|
|
|
|
&context->bridge->primary_retry_sock, NULL, false);
|
|
|
|
|
|
|
|
if(rc == 0){
|
|
|
|
COMPAT_CLOSE(context->bridge->primary_retry_sock);
|
|
|
|
context->bridge->primary_retry_sock = INVALID_SOCKET;
|
|
|
|
context->bridge->primary_retry = 0;
|
|
|
|
net__socket_close(db, context);
|
|
|
|
context->bridge->cur_address = 0;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
len = sizeof(int);
|
|
|
|
if(!getsockopt(context->bridge->primary_retry_sock, SOL_SOCKET, SO_ERROR, (char *)&err, &len)){
|
|
|
|
if(err == 0){
|
|
|
|
COMPAT_CLOSE(context->bridge->primary_retry_sock);
|
|
|
|
context->bridge->primary_retry_sock = INVALID_SOCKET;
|
|
|
|
context->bridge->primary_retry = 0;
|
|
|
|
net__socket_close(db, context);
|
|
|
|
context->bridge->cur_address = context->bridge->address_count-1;
|
|
|
|
}else{
|
|
|
|
COMPAT_CLOSE(context->bridge->primary_retry_sock);
|
|
|
|
context->bridge->primary_retry_sock = INVALID_SOCKET;
|
|
|
|
context->bridge->primary_retry = now+5;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
COMPAT_CLOSE(context->bridge->primary_retry_sock);
|
|
|
|
context->bridge->primary_retry_sock = INVALID_SOCKET;
|
|
|
|
context->bridge->primary_retry = now+5;
|
|
|
|
}
|
2014-06-23 16:57:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Local bridges never time out in this fashion. */
|
|
|
|
if(!(context->keepalive)
|
|
|
|
|| context->bridge
|
2018-08-02 12:05:36 +00:00
|
|
|
|| now - context->last_msg_in <= (time_t)(context->keepalive)*3/2){
|
2014-06-23 16:57:35 +00:00
|
|
|
|
2015-05-16 14:24:24 +00:00
|
|
|
if(db__message_write(db, context) == MOSQ_ERR_SUCCESS){
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
if(context->current_out_packet || context->state == mosq_cs_connect_pending || context->ws_want_write){
|
|
|
|
if(!(context->events & EPOLLOUT)) {
|
|
|
|
ev.data.fd = context->sock;
|
|
|
|
ev.events = EPOLLIN | EPOLLOUT;
|
|
|
|
if(epoll_ctl(db->epollfd, EPOLL_CTL_ADD, context->sock, &ev) == -1) {
|
|
|
|
if((errno != EEXIST)||(epoll_ctl(db->epollfd, EPOLL_CTL_MOD, context->sock, &ev) == -1)) {
|
|
|
|
log__printf(NULL, MOSQ_LOG_DEBUG, "Error in epoll re-registering to EPOLLOUT: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
context->events = EPOLLIN | EPOLLOUT;
|
|
|
|
}
|
|
|
|
context->ws_want_write = false;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
if(context->events & EPOLLOUT) {
|
|
|
|
ev.data.fd = context->sock;
|
|
|
|
ev.events = EPOLLIN;
|
|
|
|
if(epoll_ctl(db->epollfd, EPOLL_CTL_ADD, context->sock, &ev) == -1) {
|
|
|
|
if((errno != EEXIST)||(epoll_ctl(db->epollfd, EPOLL_CTL_MOD, context->sock, &ev) == -1)) {
|
|
|
|
log__printf(NULL, MOSQ_LOG_DEBUG, "Error in epoll re-registering to EPOLLIN: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
context->events = EPOLLIN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
2014-06-23 16:57:35 +00:00
|
|
|
pollfds[pollfd_index].fd = context->sock;
|
|
|
|
pollfds[pollfd_index].events = POLLIN;
|
|
|
|
pollfds[pollfd_index].revents = 0;
|
2017-06-18 11:52:59 +00:00
|
|
|
if(context->current_out_packet || context->state == mosq_cs_connect_pending || context->ws_want_write){
|
2014-06-23 16:57:35 +00:00
|
|
|
pollfds[pollfd_index].events |= POLLOUT;
|
2017-06-18 11:52:59 +00:00
|
|
|
context->ws_want_write = false;
|
2014-06-23 16:57:35 +00:00
|
|
|
}
|
|
|
|
context->pollfd_index = pollfd_index;
|
|
|
|
pollfd_index++;
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-06-23 16:57:35 +00:00
|
|
|
}else{
|
2014-07-08 22:07:19 +00:00
|
|
|
do_disconnect(db, context);
|
2014-06-23 16:57:35 +00:00
|
|
|
}
|
|
|
|
}else{
|
|
|
|
if(db->config->connection_messages == true){
|
2015-01-26 21:02:53 +00:00
|
|
|
if(context->id){
|
|
|
|
id = context->id;
|
|
|
|
}else{
|
|
|
|
id = "<unknown>";
|
|
|
|
}
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_NOTICE, "Client %s has exceeded timeout, disconnecting.", id);
|
2014-06-23 16:57:35 +00:00
|
|
|
}
|
|
|
|
/* Client has exceeded keepalive*1.5 */
|
2014-07-08 22:07:19 +00:00
|
|
|
do_disconnect(db, context);
|
2014-06-23 16:57:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WITH_BRIDGE
|
|
|
|
time_count = 0;
|
2014-11-18 23:34:54 +00:00
|
|
|
for(i=0; i<db->bridge_count; i++){
|
|
|
|
if(!db->bridges[i]) continue;
|
|
|
|
|
|
|
|
context = db->bridges[i];
|
|
|
|
|
2014-06-23 16:57:35 +00:00
|
|
|
if(context->sock == INVALID_SOCKET){
|
2014-05-07 22:27:00 +00:00
|
|
|
if(time_count > 0){
|
|
|
|
time_count--;
|
|
|
|
}else{
|
|
|
|
time_count = 1000;
|
|
|
|
now = mosquitto_time();
|
|
|
|
}
|
2014-06-23 16:57:35 +00:00
|
|
|
/* Want to try to restart the bridge connection */
|
|
|
|
if(!context->bridge->restart_t){
|
|
|
|
context->bridge->restart_t = now+context->bridge->restart_timeout;
|
|
|
|
context->bridge->cur_address++;
|
|
|
|
if(context->bridge->cur_address == context->bridge->address_count){
|
|
|
|
context->bridge->cur_address = 0;
|
|
|
|
}
|
|
|
|
}else{
|
2017-02-06 22:39:39 +00:00
|
|
|
if((context->bridge->start_type == bst_lazy && context->bridge->lazy_reconnect)
|
|
|
|
|| (context->bridge->start_type == bst_automatic && now > context->bridge->restart_t)){
|
2018-09-19 11:55:08 +00:00
|
|
|
|
2017-02-08 22:30:00 +00:00
|
|
|
#if defined(__GLIBC__) && defined(WITH_ADNS)
|
2017-02-06 22:39:39 +00:00
|
|
|
if(context->adns){
|
2018-09-19 11:55:08 +00:00
|
|
|
/* Connection attempted, waiting on DNS lookup */
|
2017-02-06 23:10:43 +00:00
|
|
|
rc = gai_error(context->adns);
|
|
|
|
if(rc == EAI_INPROGRESS){
|
|
|
|
/* Just keep on waiting */
|
|
|
|
}else if(rc == 0){
|
2017-03-06 21:19:53 +00:00
|
|
|
rc = bridge__connect_step2(db, context);
|
2017-02-06 23:10:43 +00:00
|
|
|
if(rc == MOSQ_ERR_SUCCESS){
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
ev.data.fd = context->sock;
|
|
|
|
ev.events = EPOLLIN;
|
|
|
|
if(context->current_out_packet){
|
|
|
|
ev.events |= EPOLLOUT;
|
|
|
|
}
|
|
|
|
if(epoll_ctl(db->epollfd, EPOLL_CTL_ADD, context->sock, &ev) == -1) {
|
|
|
|
if((errno != EEXIST)||(epoll_ctl(db->epollfd, EPOLL_CTL_MOD, context->sock, &ev) == -1)) {
|
|
|
|
log__printf(NULL, MOSQ_LOG_DEBUG, "Error in epoll re-registering bridge: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
context->events = ev.events;
|
|
|
|
}
|
|
|
|
#else
|
2017-02-06 23:10:43 +00:00
|
|
|
pollfds[pollfd_index].fd = context->sock;
|
|
|
|
pollfds[pollfd_index].events = POLLIN;
|
|
|
|
pollfds[pollfd_index].revents = 0;
|
|
|
|
if(context->current_out_packet){
|
|
|
|
pollfds[pollfd_index].events |= POLLOUT;
|
|
|
|
}
|
|
|
|
context->pollfd_index = pollfd_index;
|
|
|
|
pollfd_index++;
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2018-09-19 11:55:08 +00:00
|
|
|
}else if(rc == MOSQ_ERR_CONN_PENDING){
|
|
|
|
context->bridge->restart_t = 0;
|
2017-02-06 23:10:43 +00:00
|
|
|
}else{
|
|
|
|
context->bridge->cur_address++;
|
|
|
|
if(context->bridge->cur_address == context->bridge->address_count){
|
|
|
|
context->bridge->cur_address = 0;
|
|
|
|
}
|
2018-09-19 11:55:08 +00:00
|
|
|
context->bridge->restart_t = 0;
|
2017-02-06 22:39:39 +00:00
|
|
|
}
|
|
|
|
}else{
|
2017-02-06 23:10:43 +00:00
|
|
|
/* Need to retry */
|
|
|
|
if(context->adns->ar_result){
|
|
|
|
freeaddrinfo(context->adns->ar_result);
|
2017-02-06 22:39:39 +00:00
|
|
|
}
|
2017-07-16 21:52:01 +00:00
|
|
|
mosquitto__free(context->adns);
|
2017-02-06 23:10:43 +00:00
|
|
|
context->adns = NULL;
|
2018-09-19 11:55:08 +00:00
|
|
|
context->bridge->restart_t = 0;
|
2016-09-20 22:26:14 +00:00
|
|
|
}
|
|
|
|
}else{
|
2018-11-10 10:34:01 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
/* clean any events triggered in previous connection */
|
|
|
|
context->events = 0;
|
|
|
|
#endif
|
2017-03-06 21:19:53 +00:00
|
|
|
rc = bridge__connect_step1(db, context);
|
2017-02-06 22:39:39 +00:00
|
|
|
if(rc){
|
|
|
|
context->bridge->cur_address++;
|
|
|
|
if(context->bridge->cur_address == context->bridge->address_count){
|
|
|
|
context->bridge->cur_address = 0;
|
|
|
|
}
|
2018-09-19 11:55:08 +00:00
|
|
|
}else{
|
|
|
|
/* Short wait for ADNS lookup */
|
|
|
|
context->bridge->restart_t = 1;
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
}
|
2017-02-06 22:39:39 +00:00
|
|
|
#else
|
|
|
|
{
|
2017-03-06 21:19:53 +00:00
|
|
|
rc = bridge__connect(db, context);
|
2018-11-06 20:15:13 +00:00
|
|
|
context->bridge->restart_t = 0;
|
2017-02-06 22:39:39 +00:00
|
|
|
if(rc == MOSQ_ERR_SUCCESS){
|
2018-09-19 13:40:22 +00:00
|
|
|
if(context->bridge->round_robin == false && context->bridge->cur_address != 0){
|
|
|
|
context->bridge->primary_retry = now + 5;
|
|
|
|
}
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
ev.data.fd = context->sock;
|
|
|
|
ev.events = EPOLLIN;
|
|
|
|
if(context->current_out_packet){
|
|
|
|
ev.events |= EPOLLOUT;
|
|
|
|
}
|
|
|
|
if(epoll_ctl(db->epollfd, EPOLL_CTL_ADD, context->sock, &ev) == -1) {
|
|
|
|
if((errno != EEXIST)||(epoll_ctl(db->epollfd, EPOLL_CTL_MOD, context->sock, &ev) == -1)) {
|
|
|
|
log__printf(NULL, MOSQ_LOG_DEBUG, "Error in epoll re-registering bridge: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
context->events = ev.events;
|
|
|
|
}
|
|
|
|
#else
|
2017-02-06 22:39:39 +00:00
|
|
|
pollfds[pollfd_index].fd = context->sock;
|
|
|
|
pollfds[pollfd_index].events = POLLIN;
|
|
|
|
pollfds[pollfd_index].revents = 0;
|
|
|
|
if(context->current_out_packet){
|
|
|
|
pollfds[pollfd_index].events |= POLLOUT;
|
|
|
|
}
|
|
|
|
context->pollfd_index = pollfd_index;
|
|
|
|
pollfd_index++;
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2017-02-06 22:39:39 +00:00
|
|
|
}else{
|
|
|
|
context->bridge->cur_address++;
|
|
|
|
if(context->bridge->cur_address == context->bridge->address_count){
|
|
|
|
context->bridge->cur_address = 0;
|
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
}
|
2017-02-06 22:39:39 +00:00
|
|
|
#endif
|
2014-06-23 16:57:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
2019-03-26 14:00:42 +00:00
|
|
|
now = time(NULL);
|
|
|
|
if(db->config->persistent_client_expiration > 0 && now > expiration_check_time){
|
2014-06-23 16:57:35 +00:00
|
|
|
HASH_ITER(hh_id, db->contexts_by_id, context, ctxt_tmp){
|
2019-03-20 00:02:38 +00:00
|
|
|
if(context->sock == INVALID_SOCKET && context->session_expiry_interval > 0 && context->session_expiry_interval != UINT32_MAX){
|
2014-06-23 16:57:35 +00:00
|
|
|
/* This is a persistent client, check to see if the
|
|
|
|
* last time it connected was longer than
|
|
|
|
* persistent_client_expiration seconds ago. If so,
|
|
|
|
* expire it and clean up.
|
|
|
|
*/
|
2019-03-26 14:00:42 +00:00
|
|
|
if(now > context->session_expiry_time){
|
2015-01-26 21:02:53 +00:00
|
|
|
if(context->id){
|
|
|
|
id = context->id;
|
|
|
|
}else{
|
|
|
|
id = "<unknown>";
|
|
|
|
}
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_NOTICE, "Expiring persistent client %s due to timeout.", id);
|
2015-05-16 11:25:35 +00:00
|
|
|
G_CLIENTS_EXPIRED_INC();
|
2019-03-06 14:47:16 +00:00
|
|
|
context->session_expiry_interval = 0;
|
2019-03-15 21:31:11 +00:00
|
|
|
context__set_state(context, mosq_cs_expiring);
|
2014-08-18 23:36:09 +00:00
|
|
|
do_disconnect(db, context);
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-08-19 00:11:22 +00:00
|
|
|
expiration_check_time = time(NULL) + 3600;
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
sigprocmask(SIG_SETMASK, &sigblock, &origsig);
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
fdcount = epoll_wait(db->epollfd, events, MAX_EVENTS, 100);
|
|
|
|
#else
|
2014-05-07 22:27:00 +00:00
|
|
|
fdcount = poll(pollfds, pollfd_index, 100);
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
sigprocmask(SIG_SETMASK, &origsig, NULL);
|
|
|
|
#else
|
|
|
|
fdcount = WSAPoll(pollfds, pollfd_index, 100);
|
|
|
|
#endif
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
switch(fdcount){
|
|
|
|
case -1:
|
2018-05-02 16:33:33 +00:00
|
|
|
if(errno != EINTR){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error in epoll waiting: %s.", strerror(errno));
|
|
|
|
}
|
2017-07-27 17:43:09 +00:00
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
for(i=0; i<fdcount; i++){
|
|
|
|
for(j=0; j<listensock_count; j++){
|
|
|
|
if (events[i].data.fd == listensock[j]) {
|
|
|
|
if (events[i].events & (EPOLLIN | EPOLLPRI)){
|
|
|
|
while((ev.data.fd = net__socket_accept(db, listensock[j])) != -1){
|
|
|
|
ev.events = EPOLLIN;
|
|
|
|
if (epoll_ctl(db->epollfd, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) {
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error in epoll accepting: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
context = NULL;
|
|
|
|
HASH_FIND(hh_sock, db->contexts_by_sock, &(ev.data.fd), sizeof(mosq_sock_t), context);
|
|
|
|
if(!context) {
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error in epoll accepting: no context");
|
|
|
|
}
|
|
|
|
context->events = EPOLLIN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (j == listensock_count) {
|
|
|
|
loop_handle_reads_writes(db, events[i].data.fd, events[i].events);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
2014-05-07 22:27:00 +00:00
|
|
|
if(fdcount == -1){
|
2016-06-21 22:33:58 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Error in poll: %s.", strerror(errno));
|
2014-05-07 22:27:00 +00:00
|
|
|
}else{
|
|
|
|
loop_handle_reads_writes(db, pollfds);
|
|
|
|
|
|
|
|
for(i=0; i<listensock_count; i++){
|
|
|
|
if(pollfds[i].revents & (POLLIN | POLLPRI)){
|
2015-05-16 17:43:06 +00:00
|
|
|
while(net__socket_accept(db, listensock[i]) != -1){
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2019-03-06 14:47:16 +00:00
|
|
|
now = time(NULL);
|
|
|
|
session_expiry__check(db, now);
|
|
|
|
will_delay__check(db, now);
|
2014-05-07 22:27:00 +00:00
|
|
|
#ifdef WITH_PERSISTENCE
|
|
|
|
if(db->config->persistence && db->config->autosave_interval){
|
|
|
|
if(db->config->autosave_on_changes){
|
2015-06-29 16:11:16 +00:00
|
|
|
if(db->persistence_changes >= db->config->autosave_interval){
|
2015-05-16 14:24:24 +00:00
|
|
|
persist__backup(db, false);
|
2014-05-07 22:27:00 +00:00
|
|
|
db->persistence_changes = 0;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
if(last_backup + db->config->autosave_interval < mosquitto_time()){
|
2015-05-16 14:24:24 +00:00
|
|
|
persist__backup(db, false);
|
2014-05-07 22:27:00 +00:00
|
|
|
last_backup = mosquitto_time();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2014-11-17 23:46:02 +00:00
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
#ifdef WITH_PERSISTENCE
|
|
|
|
if(flag_db_backup){
|
2015-05-16 14:24:24 +00:00
|
|
|
persist__backup(db, false);
|
2014-05-07 22:27:00 +00:00
|
|
|
flag_db_backup = false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if(flag_reload){
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_INFO, "Reloading config.");
|
2018-05-02 22:56:11 +00:00
|
|
|
config__read(db, db->config, true);
|
2014-05-07 22:27:00 +00:00
|
|
|
mosquitto_security_cleanup(db, true);
|
|
|
|
mosquitto_security_init(db, true);
|
|
|
|
mosquitto_security_apply(db);
|
2015-05-16 14:24:24 +00:00
|
|
|
log__close(db->config);
|
|
|
|
log__init(db->config);
|
2014-05-07 22:27:00 +00:00
|
|
|
flag_reload = false;
|
|
|
|
}
|
|
|
|
if(flag_tree_print){
|
2016-07-19 14:05:53 +00:00
|
|
|
sub__tree_print(db->subs, 0);
|
2014-05-07 22:27:00 +00:00
|
|
|
flag_tree_print = false;
|
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
#ifdef WITH_WEBSOCKETS
|
2014-05-26 17:01:24 +00:00
|
|
|
for(i=0; i<db->config->listener_count; i++){
|
2014-05-26 16:09:44 +00:00
|
|
|
/* Extremely hacky, should be using the lws provided external poll
|
|
|
|
* interface, but their interface has changed recently and ours
|
|
|
|
* will soon, so for now websockets clients are second class
|
|
|
|
* citizens. */
|
|
|
|
if(db->config->listeners[i].ws_context){
|
|
|
|
libwebsocket_service(db->config->listeners[i].ws_context, 0);
|
|
|
|
}
|
|
|
|
}
|
2015-03-27 20:50:16 +00:00
|
|
|
if(db->config->have_websockets_listener){
|
|
|
|
temp__expire_websockets_clients(db);
|
|
|
|
}
|
2014-05-06 09:47:00 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
2014-05-26 16:09:44 +00:00
|
|
|
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
(void) close(db->epollfd);
|
|
|
|
db->epollfd = 0;
|
|
|
|
#else
|
2015-08-18 13:53:22 +00:00
|
|
|
mosquitto__free(pollfds);
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2014-07-03 00:00:57 +00:00
|
|
|
void do_disconnect(struct mosquitto_db *db, struct mosquitto *context)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
2015-01-26 21:02:53 +00:00
|
|
|
char *id;
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
struct epoll_event ev;
|
|
|
|
#endif
|
2015-01-26 21:02:53 +00:00
|
|
|
|
2014-07-08 22:16:34 +00:00
|
|
|
if(context->state == mosq_cs_disconnected){
|
|
|
|
return;
|
|
|
|
}
|
2014-07-03 00:00:57 +00:00
|
|
|
#ifdef WITH_WEBSOCKETS
|
|
|
|
if(context->wsi){
|
2014-06-23 16:57:35 +00:00
|
|
|
if(context->state != mosq_cs_disconnecting){
|
2019-03-15 21:31:11 +00:00
|
|
|
context__set_state(context, mosq_cs_disconnect_ws);
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
2014-07-03 00:00:57 +00:00
|
|
|
if(context->wsi){
|
|
|
|
libwebsocket_callback_on_writable(context->ws_context, context->wsi);
|
|
|
|
}
|
2017-06-18 11:52:59 +00:00
|
|
|
if(context->sock != INVALID_SOCKET){
|
|
|
|
HASH_DELETE(hh_sock, db->contexts_by_sock, context);
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
if (epoll_ctl(db->epollfd, EPOLL_CTL_DEL, context->sock, &ev) == -1) {
|
|
|
|
log__printf(NULL, MOSQ_LOG_DEBUG, "Error in epoll disconnecting websockets: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
#endif
|
2017-06-18 11:52:59 +00:00
|
|
|
context->sock = INVALID_SOCKET;
|
2017-06-19 15:14:59 +00:00
|
|
|
context->pollfd_index = -1;
|
2017-06-18 11:52:59 +00:00
|
|
|
}
|
2019-02-03 22:01:33 +00:00
|
|
|
context__remove_from_by_id(db, context);
|
2015-01-07 23:33:31 +00:00
|
|
|
}else
|
2014-07-03 00:00:57 +00:00
|
|
|
#endif
|
2015-01-07 23:33:31 +00:00
|
|
|
{
|
2014-07-03 00:00:57 +00:00
|
|
|
if(db->config->connection_messages == true){
|
2015-01-26 21:02:53 +00:00
|
|
|
if(context->id){
|
|
|
|
id = context->id;
|
|
|
|
}else{
|
|
|
|
id = "<unknown>";
|
|
|
|
}
|
2018-08-15 16:27:59 +00:00
|
|
|
if(context->state != mosq_cs_disconnecting){
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_NOTICE, "Socket error on client %s, disconnecting.", id);
|
2014-07-03 00:00:57 +00:00
|
|
|
}else{
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_NOTICE, "Client %s disconnected.", id);
|
2014-07-03 00:00:57 +00:00
|
|
|
}
|
|
|
|
}
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
2018-01-13 21:10:24 +00:00
|
|
|
if (context->sock != INVALID_SOCKET && epoll_ctl(db->epollfd, EPOLL_CTL_DEL, context->sock, &ev) == -1) {
|
2018-12-09 14:03:01 +00:00
|
|
|
if(db->config->connection_messages == true){
|
|
|
|
log__printf(NULL, MOSQ_LOG_DEBUG, "Error in epoll disconnecting: %s", strerror(errno));
|
|
|
|
}
|
2017-07-27 17:43:09 +00:00
|
|
|
}
|
|
|
|
#endif
|
2015-05-16 14:24:24 +00:00
|
|
|
context__disconnect(db, context);
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
static void loop_handle_reads_writes(struct mosquitto_db *db, mosq_sock_t sock, uint32_t events)
|
|
|
|
#else
|
2014-05-07 22:27:00 +00:00
|
|
|
static void loop_handle_reads_writes(struct mosquitto_db *db, struct pollfd *pollfds)
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
2017-07-27 17:43:09 +00:00
|
|
|
struct mosquitto *context;
|
|
|
|
#ifndef WITH_EPOLL
|
|
|
|
struct mosquitto *ctxt_tmp;
|
|
|
|
#endif
|
2014-10-24 21:39:09 +00:00
|
|
|
int err;
|
|
|
|
socklen_t len;
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
int i;
|
|
|
|
context = NULL;
|
|
|
|
HASH_FIND(hh_sock, db->contexts_by_sock, &sock, sizeof(mosq_sock_t), context);
|
|
|
|
if(!context) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (i=0;i<1;i++) {
|
|
|
|
#else
|
2014-06-23 16:57:35 +00:00
|
|
|
HASH_ITER(hh_sock, db->contexts_by_sock, context, ctxt_tmp){
|
2014-10-16 23:08:10 +00:00
|
|
|
if(context->pollfd_index < 0){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-06-23 16:57:35 +00:00
|
|
|
assert(pollfds[context->pollfd_index].fd == context->sock);
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2017-06-18 11:52:59 +00:00
|
|
|
|
|
|
|
#ifdef WITH_WEBSOCKETS
|
|
|
|
if(context->wsi){
|
|
|
|
struct lws_pollfd wspoll;
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
wspoll.fd = context->sock;
|
|
|
|
wspoll.events = context->events;
|
|
|
|
wspoll.revents = events;
|
|
|
|
#else
|
2017-06-18 11:52:59 +00:00
|
|
|
wspoll.fd = pollfds[context->pollfd_index].fd;
|
|
|
|
wspoll.events = pollfds[context->pollfd_index].events;
|
|
|
|
wspoll.revents = pollfds[context->pollfd_index].revents;
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2018-08-14 16:20:22 +00:00
|
|
|
#ifdef LWS_LIBRARY_VERSION_NUMBER
|
2017-06-18 11:52:59 +00:00
|
|
|
lws_service_fd(lws_get_context(context->wsi), &wspoll);
|
2018-08-14 16:20:22 +00:00
|
|
|
#else
|
|
|
|
lws_service_fd(context->ws_context, &wspoll);
|
|
|
|
#endif
|
2017-06-18 11:52:59 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
#ifdef WITH_TLS
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
if(events & EPOLLOUT ||
|
|
|
|
#else
|
2014-06-23 16:57:35 +00:00
|
|
|
if(pollfds[context->pollfd_index].revents & POLLOUT ||
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-06-23 16:57:35 +00:00
|
|
|
context->want_write ||
|
|
|
|
(context->ssl && context->state == mosq_cs_new)){
|
2014-05-07 22:27:00 +00:00
|
|
|
#else
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
if(events & EPOLLOUT){
|
|
|
|
#else
|
2014-06-23 16:57:35 +00:00
|
|
|
if(pollfds[context->pollfd_index].revents & POLLOUT){
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
2014-10-24 20:28:24 +00:00
|
|
|
if(context->state == mosq_cs_connect_pending){
|
|
|
|
len = sizeof(int);
|
2015-04-24 08:34:24 +00:00
|
|
|
if(!getsockopt(context->sock, SOL_SOCKET, SO_ERROR, (char *)&err, &len)){
|
2014-10-24 20:28:24 +00:00
|
|
|
if(err == 0){
|
2019-03-15 21:31:11 +00:00
|
|
|
context__set_state(context, mosq_cs_new);
|
2019-02-12 13:24:54 +00:00
|
|
|
#if defined(WITH_ADNS) && defined(WITH_BRIDGE)
|
2018-09-19 11:55:08 +00:00
|
|
|
if(context->bridge){
|
|
|
|
bridge__connect_step3(db, context);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
2014-10-24 20:28:24 +00:00
|
|
|
}
|
|
|
|
}else{
|
|
|
|
do_disconnect(db, context);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2015-05-16 13:16:40 +00:00
|
|
|
if(packet__write(context)){
|
2014-06-23 16:57:35 +00:00
|
|
|
do_disconnect(db, context);
|
|
|
|
continue;
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-23 16:57:35 +00:00
|
|
|
}
|
|
|
|
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
context = NULL;
|
|
|
|
HASH_FIND(hh_sock, db->contexts_by_sock, &sock, sizeof(mosq_sock_t), context);
|
|
|
|
if(!context) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (i=0;i<1;i++) {
|
|
|
|
#else
|
2014-06-23 16:57:35 +00:00
|
|
|
HASH_ITER(hh_sock, db->contexts_by_sock, context, ctxt_tmp){
|
2014-10-16 23:08:10 +00:00
|
|
|
if(context->pollfd_index < 0){
|
|
|
|
continue;
|
|
|
|
}
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2017-06-23 21:30:57 +00:00
|
|
|
#ifdef WITH_WEBSOCKETS
|
|
|
|
if(context->wsi){
|
|
|
|
// Websocket are already handled above
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
2014-10-16 23:08:10 +00:00
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
#ifdef WITH_TLS
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
if(events & EPOLLIN ||
|
|
|
|
#else
|
2014-06-23 16:57:35 +00:00
|
|
|
if(pollfds[context->pollfd_index].revents & POLLIN ||
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-06-23 16:57:35 +00:00
|
|
|
(context->ssl && context->state == mosq_cs_new)){
|
2017-07-27 17:43:09 +00:00
|
|
|
#else
|
|
|
|
#ifdef WITH_EPOLL
|
|
|
|
if(events & EPOLLIN){
|
2014-05-07 22:27:00 +00:00
|
|
|
#else
|
2014-06-23 16:57:35 +00:00
|
|
|
if(pollfds[context->pollfd_index].revents & POLLIN){
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
2015-06-25 09:53:24 +00:00
|
|
|
do{
|
2015-09-03 16:46:55 +00:00
|
|
|
if(packet__read(db, context)){
|
2015-06-25 09:53:24 +00:00
|
|
|
do_disconnect(db, context);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}while(SSL_DATA_PENDING(context));
|
2018-11-04 22:26:59 +00:00
|
|
|
}else{
|
2017-07-27 17:43:09 +00:00
|
|
|
#ifdef WITH_EPOLL
|
2018-11-04 22:26:59 +00:00
|
|
|
if(events & (EPOLLERR | EPOLLHUP)){
|
2017-07-27 17:43:09 +00:00
|
|
|
#else
|
2018-11-04 22:26:59 +00:00
|
|
|
if(context->pollfd_index >= 0 && pollfds[context->pollfd_index].revents & (POLLERR | POLLNVAL | POLLHUP)){
|
2017-07-27 17:43:09 +00:00
|
|
|
#endif
|
2018-11-04 22:26:59 +00:00
|
|
|
do_disconnect(db, context);
|
|
|
|
continue;
|
|
|
|
}
|
2016-06-13 16:13:44 +00:00
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-27 17:43:09 +00:00
|
|
|
|
|
|
|
|