2014-05-07 22:27:00 +00:00
|
|
|
/*
|
2018-04-11 14:24:29 +00:00
|
|
|
Copyright (c) 2011-2018 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.
|
|
|
|
*/
|
|
|
|
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "config.h"
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
#ifndef WIN32
|
2018-08-15 16:02:56 +00:00
|
|
|
#include <time.h>
|
2014-05-07 22:27:00 +00:00
|
|
|
#endif
|
|
|
|
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "mosquitto_internal.h"
|
|
|
|
#include "net_mosq.h"
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2015-04-19 21:10:59 +00:00
|
|
|
void *mosquitto__thread_main(void *obj);
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
int mosquitto_loop_start(struct mosquitto *mosq)
|
|
|
|
{
|
|
|
|
#ifdef WITH_THREADING
|
2016-05-18 13:05:08 +00:00
|
|
|
if(!mosq || mosq->threaded != mosq_ts_none) return MOSQ_ERR_INVAL;
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2016-05-18 13:05:08 +00:00
|
|
|
mosq->threaded = mosq_ts_self;
|
2016-06-21 22:33:58 +00:00
|
|
|
if(!pthread_create(&mosq->thread_id, NULL, mosquitto__thread_main, mosq)){
|
2016-03-17 21:22:56 +00:00
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}else{
|
|
|
|
return MOSQ_ERR_ERRNO;
|
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
#else
|
|
|
|
return MOSQ_ERR_NOT_SUPPORTED;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int mosquitto_loop_stop(struct mosquitto *mosq, bool force)
|
|
|
|
{
|
|
|
|
#ifdef WITH_THREADING
|
|
|
|
# ifndef WITH_BROKER
|
|
|
|
char sockpair_data = 0;
|
|
|
|
# endif
|
|
|
|
|
2016-05-18 13:05:08 +00:00
|
|
|
if(!mosq || mosq->threaded != mosq_ts_self) return MOSQ_ERR_INVAL;
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Write a single byte to sockpairW (connected to sockpairR) to break out
|
|
|
|
* of select() if in threaded mode. */
|
|
|
|
if(mosq->sockpairW != INVALID_SOCKET){
|
|
|
|
#ifndef WIN32
|
|
|
|
if(write(mosq->sockpairW, &sockpair_data, 1)){
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
send(mosq->sockpairW, &sockpair_data, 1, 0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if(force){
|
|
|
|
pthread_cancel(mosq->thread_id);
|
|
|
|
}
|
|
|
|
pthread_join(mosq->thread_id, NULL);
|
|
|
|
mosq->thread_id = pthread_self();
|
2016-05-18 13:05:08 +00:00
|
|
|
mosq->threaded = mosq_ts_none;
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
#else
|
|
|
|
return MOSQ_ERR_NOT_SUPPORTED;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WITH_THREADING
|
2015-04-19 21:10:59 +00:00
|
|
|
void *mosquitto__thread_main(void *obj)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
|
|
|
struct mosquitto *mosq = obj;
|
2018-08-08 08:19:53 +00:00
|
|
|
int state;
|
2018-08-15 16:02:56 +00:00
|
|
|
#ifndef WIN32
|
|
|
|
struct timespec ts;
|
|
|
|
ts.tv_sec = 0;
|
|
|
|
ts.tv_nsec = 10000000;
|
|
|
|
#endif
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
if(!mosq) return NULL;
|
|
|
|
|
2018-08-08 08:19:53 +00:00
|
|
|
do{
|
|
|
|
pthread_mutex_lock(&mosq->state_mutex);
|
|
|
|
state = mosq->state;
|
2014-05-07 22:27:00 +00:00
|
|
|
pthread_mutex_unlock(&mosq->state_mutex);
|
2018-08-08 08:19:53 +00:00
|
|
|
if(state == mosq_cs_new){
|
|
|
|
#ifdef WIN32
|
|
|
|
Sleep(10);
|
|
|
|
#else
|
2018-08-15 16:02:56 +00:00
|
|
|
nanosleep(&ts, NULL);
|
2018-08-08 08:19:53 +00:00
|
|
|
#endif
|
|
|
|
}else{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}while(1);
|
|
|
|
|
|
|
|
if(state == mosq_cs_connect_async){
|
2014-05-07 22:27:00 +00:00
|
|
|
mosquitto_reconnect(mosq);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!mosq->keepalive){
|
|
|
|
/* Sleep for a day if keepalive disabled. */
|
2015-06-29 14:57:16 +00:00
|
|
|
mosquitto_loop_forever(mosq, 1000*86400, 1);
|
2014-05-07 22:27:00 +00:00
|
|
|
}else{
|
|
|
|
/* Sleep for our keepalive value. publish() etc. will wake us up. */
|
|
|
|
mosquitto_loop_forever(mosq, mosq->keepalive*1000, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-07-02 19:45:26 +00:00
|
|
|
int mosquitto_threaded_set(struct mosquitto *mosq, bool threaded)
|
|
|
|
{
|
|
|
|
if(!mosq) return MOSQ_ERR_INVAL;
|
|
|
|
|
2016-05-18 13:05:08 +00:00
|
|
|
if(threaded){
|
|
|
|
mosq->threaded = mosq_ts_external;
|
|
|
|
}else{
|
|
|
|
mosq->threaded = mosq_ts_none;
|
|
|
|
}
|
2014-07-02 19:45:26 +00:00
|
|
|
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|