Shared config parsing for client utils.
This commit is contained in:
parent
e5cc63a89b
commit
94ec27911b
@ -4,11 +4,11 @@ include ../config.mk
|
||||
|
||||
all : mosquitto_pub mosquitto_sub
|
||||
|
||||
mosquitto_pub : pub_client.o ../lib/libmosquitto.so.${SOVERSION}
|
||||
${CC} $< -o $@ ${CLIENT_LDFLAGS}
|
||||
mosquitto_pub : pub_client.o client_shared.o
|
||||
${CC} $^ -o $@ ${CLIENT_LDFLAGS}
|
||||
|
||||
mosquitto_sub : sub_client.o ../lib/libmosquitto.so.${SOVERSION}
|
||||
${CC} $< -o $@ ${CLIENT_LDFLAGS}
|
||||
mosquitto_sub : sub_client.o client_shared.o
|
||||
${CC} $^ -o $@ ${CLIENT_LDFLAGS}
|
||||
|
||||
pub_client.o : pub_client.c ../lib/libmosquitto.so.${SOVERSION}
|
||||
${CC} -c $< -o $@ ${CLIENT_CFLAGS}
|
||||
@ -16,6 +16,9 @@ pub_client.o : pub_client.c ../lib/libmosquitto.so.${SOVERSION}
|
||||
sub_client.o : sub_client.c ../lib/libmosquitto.so.${SOVERSION}
|
||||
${CC} -c $< -o $@ ${CLIENT_CFLAGS}
|
||||
|
||||
client_shared.o : client_shared.c client_shared.h
|
||||
${CC} -c $< -o $@ ${CLIENT_CFLAGS}
|
||||
|
||||
../lib/libmosquitto.so.${SOVERSION} :
|
||||
$(MAKE) -C ../lib
|
||||
|
||||
|
503
client/client_shared.c
Normal file
503
client/client_shared.c
Normal file
@ -0,0 +1,503 @@
|
||||
/*
|
||||
Copyright (c) 2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <process.h>
|
||||
#include <winsock2.h>
|
||||
#define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include "client_shared.h"
|
||||
|
||||
void init_config(struct mosq_config *cfg)
|
||||
{
|
||||
memset(cfg, 0, sizeof(*cfg));
|
||||
cfg->port = 1883;
|
||||
cfg->max_inflight = 20;
|
||||
cfg->keepalive = 60;
|
||||
cfg->clean_session = true;
|
||||
cfg->eol = true;
|
||||
}
|
||||
|
||||
int client_config_load(struct mosq_config *cfg, int pub_or_sub, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
init_config(cfg);
|
||||
|
||||
for(i=1; i<argc; i++){
|
||||
if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -p argument given but no port specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->port = atoi(argv[i+1]);
|
||||
if(cfg->port<1 || cfg->port>65535){
|
||||
fprintf(stderr, "Error: Invalid port given: %d\n", cfg->port);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-A")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -A argument given but no address specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->bind_address = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--cafile")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --cafile argument given but no file specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->cafile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--capath")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --capath argument given but no directory specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->capath = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--cert")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --cert argument given but no file specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->certfile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--ciphers")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --ciphers argument given but no ciphers specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->ciphers = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")){
|
||||
cfg->debug = true;
|
||||
}else if(!strcmp(argv[i], "-f") || !strcmp(argv[i], "--file")){
|
||||
if(cfg->pub_mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
return 1;
|
||||
}else if(i==argc-1){
|
||||
fprintf(stderr, "Error: -f argument given but no file specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->pub_mode = MSGMODE_FILE;
|
||||
cfg->file_input = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--help")){
|
||||
return 1;
|
||||
}else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--host")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -h argument given but no host specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->host = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--insecure")){
|
||||
cfg->insecure = true;
|
||||
}else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--id")){
|
||||
if(cfg->id_prefix){
|
||||
fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
|
||||
return 1;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -i argument given but no id specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->id = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-I") || !strcmp(argv[i], "--id-prefix")){
|
||||
if(cfg->id){
|
||||
fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
|
||||
return 1;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -I argument given but no id prefix specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->id_prefix = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-k") || !strcmp(argv[i], "--keepalive")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -k argument given but no keepalive specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->keepalive = atoi(argv[i+1]);
|
||||
if(cfg->keepalive>65535){
|
||||
fprintf(stderr, "Error: Invalid keepalive given: %d\n", cfg->keepalive);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--key")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --key argument given but no file specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->keyfile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--stdin-line")){
|
||||
if(cfg->pub_mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->pub_mode = MSGMODE_STDIN_LINE;
|
||||
}
|
||||
}else if(!strcmp(argv[i], "-m") || !strcmp(argv[i], "--message")){
|
||||
if(cfg->pub_mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
return 1;
|
||||
}else if(i==argc-1){
|
||||
fprintf(stderr, "Error: -m argument given but no message specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->message = argv[i+1];
|
||||
cfg->msglen = strlen(cfg->message);
|
||||
cfg->pub_mode = MSGMODE_CMD;
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-M")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -M argument given but max_inflight not specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->max_inflight = atoi(argv[i+1]);
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-n") || !strcmp(argv[i], "--null-message")){
|
||||
if(cfg->pub_mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->pub_mode = MSGMODE_NULL;
|
||||
}
|
||||
}else if(!strcmp(argv[i], "--psk")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --psk argument given but no key specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->psk = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--psk-identity")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --psk-identity argument given but no identity specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->psk_identity = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-q") || !strcmp(argv[i], "--qos")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -q argument given but no QoS specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->qos = atoi(argv[i+1]);
|
||||
if(cfg->qos<0 || cfg->qos>2){
|
||||
fprintf(stderr, "Error: Invalid QoS given: %d\n", cfg->qos);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--quiet")){
|
||||
cfg->quiet = true;
|
||||
}else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--retain")){
|
||||
cfg->retain = 1;
|
||||
}else if(!strcmp(argv[i], "-s") || !strcmp(argv[i], "--stdin-file")){
|
||||
if(cfg->pub_mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->pub_mode = MSGMODE_STDIN_FILE;
|
||||
}
|
||||
}else if(!strcmp(argv[i], "-S")){
|
||||
cfg->use_srv = true;
|
||||
}else if(!strcmp(argv[i], "-t") || !strcmp(argv[i], "--topic")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -t argument given but no topic specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
if(pub_or_sub == CLIENT_PUB){
|
||||
cfg->topic = argv[i+1];
|
||||
}else{
|
||||
cfg->topic_count++;
|
||||
cfg->topics = realloc(cfg->topics, cfg->topic_count*sizeof(char *));
|
||||
cfg->topics[cfg->topic_count-1] = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}else if(!strcmp(argv[i], "-T") || !strcmp(argv[i], "--filter-out")){
|
||||
if(pub_or_sub == CLIENT_PUB){
|
||||
goto unknown_option;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -T argument given but no topic filter specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->filter_out_count++;
|
||||
cfg->filter_outs = realloc(cfg->filter_outs, cfg->filter_out_count*sizeof(char *));
|
||||
cfg->filter_outs[cfg->filter_out_count-1] = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--tls-version")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --tls-version argument given but no version specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->tls_version = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-u") || !strcmp(argv[i], "--username")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -u argument given but no username specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->username = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-P") || !strcmp(argv[i], "--pw")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -P argument given but no password specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->password = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-payload")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-payload argument given but no will payload specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->will_payload = argv[i+1];
|
||||
cfg->will_payloadlen = strlen(cfg->will_payload);
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-qos")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-qos argument given but no will QoS specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->will_qos = atoi(argv[i+1]);
|
||||
if(cfg->will_qos < 0 || cfg->will_qos > 2){
|
||||
fprintf(stderr, "Error: Invalid will QoS %d.\n\n", cfg->will_qos);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-retain")){
|
||||
cfg->will_retain = true;
|
||||
}else if(!strcmp(argv[i], "--will-topic")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-topic argument given but no will topic specified.\n\n");
|
||||
return 1;
|
||||
}else{
|
||||
cfg->will_topic = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--disable-clean-session")){
|
||||
if(pub_or_sub == CLIENT_PUB){
|
||||
goto unknown_option;
|
||||
}
|
||||
cfg->clean_session = false;
|
||||
}else if(!strcmp(argv[i], "-N")){
|
||||
if(pub_or_sub == CLIENT_PUB){
|
||||
goto unknown_option;
|
||||
}
|
||||
cfg->eol = false;
|
||||
}else if(!strcmp(argv[i], "-R")){
|
||||
if(pub_or_sub == CLIENT_PUB){
|
||||
goto unknown_option;
|
||||
}
|
||||
cfg->no_retain = true;
|
||||
}else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")){
|
||||
if(pub_or_sub == CLIENT_PUB){
|
||||
goto unknown_option;
|
||||
}
|
||||
cfg->verbose = 1;
|
||||
}else{
|
||||
goto unknown_option;
|
||||
}
|
||||
}
|
||||
|
||||
if(cfg->will_payload && !cfg->will_topic){
|
||||
fprintf(stderr, "Error: Will payload given, but no will topic given.\n");
|
||||
return 1;
|
||||
}
|
||||
if(cfg->will_retain && !cfg->will_topic){
|
||||
fprintf(stderr, "Error: Will retain given, but no will topic given.\n");
|
||||
return 1;
|
||||
}
|
||||
if(cfg->password && !cfg->username){
|
||||
if(!cfg->quiet) fprintf(stderr, "Warning: Not using password since username not set.\n");
|
||||
}
|
||||
if((cfg->certfile && !cfg->keyfile) || (cfg->keyfile && !cfg->certfile)){
|
||||
fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is.\n");
|
||||
return 1;
|
||||
}
|
||||
if((cfg->cafile || cfg->capath) && cfg->psk){
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: Only one of --psk or --cafile/--capath may be used at once.\n");
|
||||
return 1;
|
||||
}
|
||||
if(cfg->psk && !cfg->psk_identity){
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: --psk-identity required if --psk used.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(pub_or_sub == CLIENT_SUB){
|
||||
if(cfg->clean_session == false && (cfg->id_prefix || !cfg->id)){
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: You must provide a client id if you are using the -c option.\n");
|
||||
return 1;
|
||||
}
|
||||
if(cfg->topic_count == 0){
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: You must specify a topic to subscribe to.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!cfg->host){
|
||||
cfg->host = "localhost";
|
||||
}
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
|
||||
unknown_option:
|
||||
fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int client_opts_set(struct mosquitto *mosq, struct mosq_config *cfg)
|
||||
{
|
||||
if(cfg->will_topic && mosquitto_will_set(mosq, cfg->will_topic,
|
||||
cfg->will_payloadlen, cfg->will_payload, cfg->will_qos,
|
||||
cfg->will_retain)){
|
||||
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: Problem setting will.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(cfg->username && mosquitto_username_pw_set(mosq, cfg->username, cfg->password)){
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: Problem setting username and password.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if((cfg->cafile || cfg->capath)
|
||||
&& mosquitto_tls_set(mosq, cfg->cafile, cfg->capath, cfg->certfile, cfg->keyfile, NULL)){
|
||||
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(cfg->insecure && mosquitto_tls_insecure_set(mosq, true)){
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: Problem setting TLS insecure option.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(cfg->psk && mosquitto_tls_psk_set(mosq, cfg->psk, cfg->psk_identity, NULL)){
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: Problem setting TLS-PSK options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(cfg->tls_version && mosquitto_tls_opts_set(mosq, 1, cfg->tls_version, cfg->ciphers)){
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
mosquitto_max_inflight_messages_set(mosq, cfg->max_inflight);
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int client_id_generate(struct mosq_config *cfg, const char *id_base)
|
||||
{
|
||||
int len;
|
||||
char hostname[256];
|
||||
|
||||
if(cfg->id_prefix){
|
||||
cfg->id = malloc(strlen(cfg->id_prefix)+10);
|
||||
if(!cfg->id){
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
snprintf(cfg->id, strlen(cfg->id_prefix)+10, "%s%d", cfg->id_prefix, getpid());
|
||||
}else if(!cfg->id){
|
||||
hostname[0] = '\0';
|
||||
gethostname(hostname, 256);
|
||||
hostname[255] = '\0';
|
||||
len = strlen(id_base) + strlen("/-") + 6 + strlen(hostname);
|
||||
cfg->id = malloc(len);
|
||||
if(!cfg->id){
|
||||
if(!cfg->quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
snprintf(cfg->id, len, "%s/%d-%s", id_base, getpid(), hostname);
|
||||
if(strlen(cfg->id) > MOSQ_MQTT_ID_MAX_LENGTH){
|
||||
/* Enforce maximum client id length of 23 characters */
|
||||
cfg->id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0';
|
||||
}
|
||||
}
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int client_connect(struct mosquitto *mosq, struct mosq_config *cfg)
|
||||
{
|
||||
char err[1024];
|
||||
int rc;
|
||||
|
||||
if(cfg->use_srv){
|
||||
rc = mosquitto_connect_srv(mosq, cfg->host, cfg->keepalive, cfg->bind_address);
|
||||
}else{
|
||||
rc = mosquitto_connect_bind(mosq, cfg->host, cfg->port, cfg->keepalive, cfg->bind_address);
|
||||
}
|
||||
if(rc){
|
||||
if(!cfg->quiet){
|
||||
if(rc == MOSQ_ERR_ERRNO){
|
||||
#ifndef WIN32
|
||||
strerror_r(errno, err, 1024);
|
||||
#else
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errno, 0, (LPTSTR)&err, 1024, NULL);
|
||||
#endif
|
||||
fprintf(stderr, "Error: %s\n", err);
|
||||
}else{
|
||||
fprintf(stderr, "Unable to connect (%d).\n", rc);
|
||||
}
|
||||
}
|
||||
mosquitto_lib_cleanup();
|
||||
return rc;
|
||||
}
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
87
client/client_shared.h
Normal file
87
client/client_shared.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright (c) 2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef _CLIENT_CONFIG_H
|
||||
#define _CLIENT_CONFIG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* pub_client.c modes */
|
||||
#define MSGMODE_NONE 0
|
||||
#define MSGMODE_CMD 1
|
||||
#define MSGMODE_STDIN_LINE 2
|
||||
#define MSGMODE_STDIN_FILE 3
|
||||
#define MSGMODE_FILE 4
|
||||
#define MSGMODE_NULL 5
|
||||
|
||||
#define CLIENT_PUB 1
|
||||
#define CLIENT_SUB 2
|
||||
|
||||
struct mosq_config {
|
||||
char *id;
|
||||
char *id_prefix;
|
||||
int keepalive;
|
||||
char *host;
|
||||
int port;
|
||||
int qos;
|
||||
bool retain;
|
||||
int pub_mode; /* pub */
|
||||
char *file_input; /* pub */
|
||||
char *message; /* pub */
|
||||
long msglen; /* pub */
|
||||
char *topic; /* pub */
|
||||
char *bind_address;
|
||||
bool use_srv;
|
||||
bool debug;
|
||||
bool quiet;
|
||||
unsigned int max_inflight;
|
||||
char *username;
|
||||
char *password;
|
||||
char *will_topic;
|
||||
char *will_payload;
|
||||
long will_payloadlen;
|
||||
int will_qos;
|
||||
bool will_retain;
|
||||
#ifdef WITH_TLS
|
||||
char *cafile;
|
||||
char *capath;
|
||||
char *certfile;
|
||||
char *keyfile;
|
||||
char *ciphers;
|
||||
bool insecure;
|
||||
char *tls_version;
|
||||
# ifdef WITH_TLS_PSK
|
||||
char *psk;
|
||||
char *psk_identity;
|
||||
# endif
|
||||
bool clean_session; /* sub */
|
||||
char **topics; /* sub */
|
||||
int topic_count; /* sub */
|
||||
int topic_qos; /* sub */
|
||||
bool no_retain; /* sub */
|
||||
char **filter_outs; /* sub */
|
||||
int filter_out_count; /* sub */
|
||||
bool verbose; /* sub */
|
||||
bool eol; /* sub */
|
||||
#endif
|
||||
};
|
||||
|
||||
int client_config_load(struct mosq_config *config, int pub_or_sub, int argc, char *argv[]);
|
||||
int client_opts_set(struct mosquitto *mosq, struct mosq_config *cfg);
|
||||
int client_id_generate(struct mosq_config *cfg, const char *id_base);
|
||||
int client_connect(struct mosquitto *mosq, struct mosq_config *cfg);
|
||||
|
||||
#endif
|
@ -29,13 +29,7 @@ Contributors:
|
||||
#endif
|
||||
|
||||
#include <mosquitto.h>
|
||||
|
||||
#define MSGMODE_NONE 0
|
||||
#define MSGMODE_CMD 1
|
||||
#define MSGMODE_STDIN_LINE 2
|
||||
#define MSGMODE_STDIN_FILE 3
|
||||
#define MSGMODE_FILE 4
|
||||
#define MSGMODE_NULL 5
|
||||
#include "client_shared.h"
|
||||
|
||||
#define STATUS_CONNECTING 0
|
||||
#define STATUS_CONNACK_RECVD 1
|
||||
@ -273,328 +267,36 @@ void print_usage(void)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *id = NULL;
|
||||
char *id_prefix = NULL;
|
||||
int i;
|
||||
char *host = "localhost";
|
||||
int port = 1883;
|
||||
char *bind_address = NULL;
|
||||
int keepalive = 60;
|
||||
struct mosq_config cfg;
|
||||
char buf[1024];
|
||||
bool debug = false;
|
||||
struct mosquitto *mosq = NULL;
|
||||
int rc;
|
||||
int rc2;
|
||||
char hostname[256];
|
||||
char err[1024];
|
||||
int len;
|
||||
unsigned int max_inflight = 20;
|
||||
|
||||
char *will_payload = NULL;
|
||||
long will_payloadlen = 0;
|
||||
int will_qos = 0;
|
||||
bool will_retain = false;
|
||||
char *will_topic = NULL;
|
||||
if(client_config_load(&cfg, CLIENT_PUB, argc, argv)){
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool insecure = false;
|
||||
char *cafile = NULL;
|
||||
char *capath = NULL;
|
||||
char *certfile = NULL;
|
||||
char *keyfile = NULL;
|
||||
char *tls_version = NULL;
|
||||
topic = cfg.topic;
|
||||
message = cfg.message;
|
||||
msglen = cfg.msglen;
|
||||
qos = cfg.qos;
|
||||
retain = cfg.retain;
|
||||
mode = cfg.pub_mode;
|
||||
username = cfg.username;
|
||||
password = cfg.password;
|
||||
quiet = cfg.quiet;
|
||||
|
||||
char *psk = NULL;
|
||||
char *psk_identity = NULL;
|
||||
|
||||
char *ciphers = NULL;
|
||||
|
||||
bool use_srv = false;
|
||||
|
||||
for(i=1; i<argc; i++){
|
||||
if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -p argument given but no port specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
port = atoi(argv[i+1]);
|
||||
if(port<1 || port>65535){
|
||||
fprintf(stderr, "Error: Invalid port given: %d\n", port);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-A")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -A argument given but no address specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
bind_address = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--cafile")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --cafile argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
cafile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--capath")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --capath argument given but no directory specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
capath = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--cert")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --cert argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
certfile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--ciphers")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --ciphers argument given but no ciphers specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ciphers = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")){
|
||||
debug = true;
|
||||
}else if(!strcmp(argv[i], "-f") || !strcmp(argv[i], "--file")){
|
||||
if(mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else if(i==argc-1){
|
||||
fprintf(stderr, "Error: -f argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
if(load_file(argv[i+1])) return 1;
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--help")){
|
||||
print_usage();
|
||||
return 0;
|
||||
}else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--host")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -h argument given but no host specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
host = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--insecure")){
|
||||
insecure = true;
|
||||
}else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--id")){
|
||||
if(id_prefix){
|
||||
fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -i argument given but no id specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
id = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-I") || !strcmp(argv[i], "--id-prefix")){
|
||||
if(id){
|
||||
fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -I argument given but no id prefix specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
id_prefix = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--key")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --key argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
keyfile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--stdin-line")){
|
||||
if(mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
mode = MSGMODE_STDIN_LINE;
|
||||
}
|
||||
}else if(!strcmp(argv[i], "-m") || !strcmp(argv[i], "--message")){
|
||||
if(mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else if(i==argc-1){
|
||||
fprintf(stderr, "Error: -m argument given but no message specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
message = argv[i+1];
|
||||
msglen = strlen(message);
|
||||
mode = MSGMODE_CMD;
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-M")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -M argument given but max_inflight not specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
max_inflight = atoi(argv[i+1]);
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-n") || !strcmp(argv[i], "--null-message")){
|
||||
if(mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
mode = MSGMODE_NULL;
|
||||
}
|
||||
}else if(!strcmp(argv[i], "--psk")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --psk argument given but no key specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
psk = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--psk-identity")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --psk-identity argument given but no identity specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
psk_identity = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-q") || !strcmp(argv[i], "--qos")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -q argument given but no QoS specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
qos = atoi(argv[i+1]);
|
||||
if(qos<0 || qos>2){
|
||||
fprintf(stderr, "Error: Invalid QoS given: %d\n", qos);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--quiet")){
|
||||
quiet = true;
|
||||
}else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--retain")){
|
||||
retain = 1;
|
||||
}else if(!strcmp(argv[i], "-s") || !strcmp(argv[i], "--stdin-file")){
|
||||
if(mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
if(load_stdin()) return 1;
|
||||
}
|
||||
}else if(!strcmp(argv[i], "-S")){
|
||||
use_srv = true;
|
||||
}else if(!strcmp(argv[i], "-t") || !strcmp(argv[i], "--topic")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -t argument given but no topic specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
topic = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--tls-version")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --tls-version argument given but no version specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
tls_version = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-u") || !strcmp(argv[i], "--username")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -u argument given but no username specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
username = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-P") || !strcmp(argv[i], "--pw")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -P argument given but no password specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
password = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-payload")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-payload argument given but no will payload specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_payload = argv[i+1];
|
||||
will_payloadlen = strlen(will_payload);
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-qos")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-qos argument given but no will QoS specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_qos = atoi(argv[i+1]);
|
||||
if(will_qos < 0 || will_qos > 2){
|
||||
fprintf(stderr, "Error: Invalid will QoS %d.\n\n", will_qos);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-retain")){
|
||||
will_retain = true;
|
||||
}else if(!strcmp(argv[i], "--will-topic")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-topic argument given but no will topic specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_topic = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else{
|
||||
fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]);
|
||||
print_usage();
|
||||
if(cfg.pub_mode == MSGMODE_STDIN_FILE){
|
||||
if(load_stdin()){
|
||||
fprintf(stderr, "Error loading input from stdin.\n");
|
||||
return 1;
|
||||
}
|
||||
}else if(cfg.file_input){
|
||||
if(load_file(cfg.file_input)){
|
||||
fprintf(stderr, "Error loading input file \"%s\".\n", cfg.file_input);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -605,62 +307,14 @@ int main(int argc, char *argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(will_payload && !will_topic){
|
||||
fprintf(stderr, "Error: Will payload given, but no will topic given.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(will_retain && !will_topic){
|
||||
fprintf(stderr, "Error: Will retain given, but no will topic given.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(password && !username){
|
||||
if(!quiet) fprintf(stderr, "Warning: Not using password since username not set.\n");
|
||||
}
|
||||
if((certfile && !keyfile) || (keyfile && !certfile)){
|
||||
fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if((cafile || capath) && psk){
|
||||
if(!quiet) fprintf(stderr, "Error: Only one of --psk or --cafile/--capath may be used at once.\n");
|
||||
return 1;
|
||||
}
|
||||
if(psk && !psk_identity){
|
||||
if(!quiet) fprintf(stderr, "Error: --psk-identity required if --psk used.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
mosquitto_lib_init();
|
||||
|
||||
if(id_prefix){
|
||||
id = malloc(strlen(id_prefix)+10);
|
||||
if(!id){
|
||||
if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
snprintf(id, strlen(id_prefix)+10, "%s%d", id_prefix, getpid());
|
||||
}else if(!id){
|
||||
hostname[0] = '\0';
|
||||
gethostname(hostname, 256);
|
||||
hostname[255] = '\0';
|
||||
len = strlen("mosqpub/-") + 6 + strlen(hostname);
|
||||
id = malloc(len);
|
||||
if(!id){
|
||||
if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
snprintf(id, len, "mosqpub/%d-%s", getpid(), hostname);
|
||||
if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH){
|
||||
/* Enforce maximum client id length of 23 characters */
|
||||
id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0';
|
||||
}
|
||||
if(client_id_generate(&cfg, "mosqpub")){
|
||||
return 1;
|
||||
}
|
||||
|
||||
mosq = mosquitto_new(id, true, NULL);
|
||||
mosq = mosquitto_new(cfg.id, true, NULL);
|
||||
if(!mosq){
|
||||
switch(errno){
|
||||
case ENOMEM:
|
||||
@ -676,62 +330,15 @@ int main(int argc, char *argv[])
|
||||
if(debug){
|
||||
mosquitto_log_callback_set(mosq, my_log_callback);
|
||||
}
|
||||
if(will_topic && mosquitto_will_set(mosq, will_topic, will_payloadlen, will_payload, will_qos, will_retain)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting will.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(username && mosquitto_username_pw_set(mosq, username, password)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting username and password.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if((cafile || capath) && mosquitto_tls_set(mosq, cafile, capath, certfile, keyfile, NULL)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(insecure && mosquitto_tls_insecure_set(mosq, true)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting TLS insecure option.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(psk && mosquitto_tls_psk_set(mosq, psk, psk_identity, NULL)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting TLS-PSK options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(tls_version && mosquitto_tls_opts_set(mosq, 1, tls_version, ciphers)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
mosquitto_max_inflight_messages_set(mosq, max_inflight);
|
||||
mosquitto_connect_callback_set(mosq, my_connect_callback);
|
||||
mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
|
||||
mosquitto_publish_callback_set(mosq, my_publish_callback);
|
||||
|
||||
if(use_srv){
|
||||
rc = mosquitto_connect_srv(mosq, host, keepalive, bind_address);
|
||||
}else{
|
||||
rc = mosquitto_connect_bind(mosq, host, port, keepalive, bind_address);
|
||||
}
|
||||
if(rc){
|
||||
if(!quiet){
|
||||
if(rc == MOSQ_ERR_ERRNO){
|
||||
#ifndef WIN32
|
||||
strerror_r(errno, err, 1024);
|
||||
#else
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errno, 0, (LPTSTR)&err, 1024, NULL);
|
||||
#endif
|
||||
fprintf(stderr, "Error: %s\n", err);
|
||||
}else{
|
||||
fprintf(stderr, "Unable to connect (%d).\n", rc);
|
||||
}
|
||||
}
|
||||
mosquitto_lib_cleanup();
|
||||
return rc;
|
||||
if(client_opts_set(mosq, &cfg)){
|
||||
return 1;
|
||||
}
|
||||
rc = client_connect(mosq, &cfg);
|
||||
if(rc) return rc;
|
||||
|
||||
if(mode == MSGMODE_STDIN_LINE){
|
||||
mosquitto_loop_start(mosq);
|
||||
|
@ -28,50 +28,34 @@ Contributors:
|
||||
#endif
|
||||
|
||||
#include <mosquitto.h>
|
||||
|
||||
/* This struct is used to pass data to callbacks.
|
||||
* An instance "ud" is created in main() and populated, then passed to
|
||||
* mosquitto_new(). */
|
||||
struct userdata {
|
||||
char **topics;
|
||||
int topic_count;
|
||||
int topic_qos;
|
||||
char **filter_outs;
|
||||
int filter_out_count;
|
||||
char *username;
|
||||
char *password;
|
||||
int verbose;
|
||||
bool quiet;
|
||||
bool no_retain;
|
||||
bool eol;
|
||||
};
|
||||
#include "client_shared.h"
|
||||
|
||||
void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
|
||||
{
|
||||
struct userdata *ud;
|
||||
struct mosq_config *cfg;
|
||||
int i;
|
||||
bool res;
|
||||
|
||||
assert(obj);
|
||||
ud = (struct userdata *)obj;
|
||||
cfg = (struct mosq_config *)obj;
|
||||
|
||||
if(message->retain && ud->no_retain) return;
|
||||
if(ud->filter_outs){
|
||||
for(i=0; i<ud->filter_out_count; i++){
|
||||
mosquitto_topic_matches_sub(ud->filter_outs[i], message->topic, &res);
|
||||
if(message->retain && cfg->no_retain) return;
|
||||
if(cfg->filter_outs){
|
||||
for(i=0; i<cfg->filter_out_count; i++){
|
||||
mosquitto_topic_matches_sub(cfg->filter_outs[i], message->topic, &res);
|
||||
if(res) return;
|
||||
}
|
||||
}
|
||||
|
||||
if(ud->verbose){
|
||||
if(cfg->verbose){
|
||||
if(message->payloadlen){
|
||||
printf("%s ", message->topic);
|
||||
fwrite(message->payload, 1, message->payloadlen, stdout);
|
||||
if(ud->eol){
|
||||
if(cfg->eol){
|
||||
printf("\n");
|
||||
}
|
||||
}else{
|
||||
if(ud->eol){
|
||||
if(cfg->eol){
|
||||
printf("%s (null)\n", message->topic);
|
||||
}
|
||||
}
|
||||
@ -79,7 +63,7 @@ void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquit
|
||||
}else{
|
||||
if(message->payloadlen){
|
||||
fwrite(message->payload, 1, message->payloadlen, stdout);
|
||||
if(ud->eol){
|
||||
if(cfg->eol){
|
||||
printf("\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
@ -90,17 +74,17 @@ void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquit
|
||||
void my_connect_callback(struct mosquitto *mosq, void *obj, int result)
|
||||
{
|
||||
int i;
|
||||
struct userdata *ud;
|
||||
struct mosq_config *cfg;
|
||||
|
||||
assert(obj);
|
||||
ud = (struct userdata *)obj;
|
||||
cfg = (struct mosq_config *)obj;
|
||||
|
||||
if(!result){
|
||||
for(i=0; i<ud->topic_count; i++){
|
||||
mosquitto_subscribe(mosq, NULL, ud->topics[i], ud->topic_qos);
|
||||
for(i=0; i<cfg->topic_count; i++){
|
||||
mosquitto_subscribe(mosq, NULL, cfg->topics[i], cfg->topic_qos);
|
||||
}
|
||||
}else{
|
||||
if(result && !ud->quiet){
|
||||
if(result && !cfg->quiet){
|
||||
fprintf(stderr, "%s\n", mosquitto_connack_string(result));
|
||||
}
|
||||
}
|
||||
@ -109,16 +93,16 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result)
|
||||
void my_subscribe_callback(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
|
||||
{
|
||||
int i;
|
||||
struct userdata *ud;
|
||||
struct mosq_config *cfg;
|
||||
|
||||
assert(obj);
|
||||
ud = (struct userdata *)obj;
|
||||
cfg = (struct mosq_config *)obj;
|
||||
|
||||
if(!ud->quiet) printf("Subscribed (mid: %d): %d", mid, granted_qos[0]);
|
||||
if(!cfg->quiet) printf("Subscribed (mid: %d): %d", mid, granted_qos[0]);
|
||||
for(i=1; i<qos_count; i++){
|
||||
if(!ud->quiet) printf(", %d", granted_qos[i]);
|
||||
if(!cfg->quiet) printf(", %d", granted_qos[i]);
|
||||
}
|
||||
if(!ud->quiet) printf("\n");
|
||||
if(!cfg->quiet) printf("\n");
|
||||
}
|
||||
|
||||
void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str)
|
||||
@ -198,444 +182,47 @@ void print_usage(void)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *id = NULL;
|
||||
char *id_prefix = NULL;
|
||||
int i;
|
||||
char *host = "localhost";
|
||||
int port = 1883;
|
||||
char *bind_address = NULL;
|
||||
int keepalive = 60;
|
||||
bool clean_session = true;
|
||||
bool debug = false;
|
||||
struct mosq_config cfg;
|
||||
struct mosquitto *mosq = NULL;
|
||||
int rc;
|
||||
char hostname[256];
|
||||
char err[1024];
|
||||
struct userdata ud;
|
||||
int len;
|
||||
|
||||
char *will_payload = NULL;
|
||||
long will_payloadlen = 0;
|
||||
int will_qos = 0;
|
||||
bool will_retain = false;
|
||||
char *will_topic = NULL;
|
||||
|
||||
bool insecure = false;
|
||||
char *cafile = NULL;
|
||||
char *capath = NULL;
|
||||
char *certfile = NULL;
|
||||
char *keyfile = NULL;
|
||||
char *tls_version = NULL;
|
||||
|
||||
char *psk = NULL;
|
||||
char *psk_identity = NULL;
|
||||
|
||||
char *ciphers = NULL;
|
||||
|
||||
bool use_srv = false;
|
||||
|
||||
memset(&ud, 0, sizeof(struct userdata));
|
||||
ud.eol = true;
|
||||
|
||||
for(i=1; i<argc; i++){
|
||||
if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -p argument given but no port specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
port = atoi(argv[i+1]);
|
||||
if(port<1 || port>65535){
|
||||
fprintf(stderr, "Error: Invalid port given: %d\n", port);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-A")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -A argument given but no address specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
bind_address = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--disable-clean-session")){
|
||||
clean_session = false;
|
||||
}else if(!strcmp(argv[i], "--cafile")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --cafile argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
cafile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--capath")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --capath argument given but no directory specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
capath = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--cert")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --cert argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
certfile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--ciphers")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --ciphers argument given but no ciphers specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ciphers = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")){
|
||||
debug = true;
|
||||
}else if(!strcmp(argv[i], "--help")){
|
||||
print_usage();
|
||||
return 0;
|
||||
}else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--host")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -h argument given but no host specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
host = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--insecure")){
|
||||
insecure = true;
|
||||
}else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--id")){
|
||||
if(id_prefix){
|
||||
fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -i argument given but no id specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
id = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-I") || !strcmp(argv[i], "--id-prefix")){
|
||||
if(id){
|
||||
fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -I argument given but no id prefix specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
id_prefix = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-k") || !strcmp(argv[i], "--keepalive")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -k argument given but no keepalive specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
keepalive = atoi(argv[i+1]);
|
||||
if(keepalive>65535){
|
||||
fprintf(stderr, "Error: Invalid keepalive given: %d\n", keepalive);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--key")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --key argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
keyfile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-N")){
|
||||
ud.eol = false;
|
||||
}else if(!strcmp(argv[i], "--psk")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --psk argument given but no key specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
psk = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--psk-identity")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --psk-identity argument given but no identity specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
psk_identity = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-q") || !strcmp(argv[i], "--qos")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -q argument given but no QoS specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ud.topic_qos = atoi(argv[i+1]);
|
||||
if(ud.topic_qos<0 || ud.topic_qos>2){
|
||||
fprintf(stderr, "Error: Invalid QoS given: %d\n", ud.topic_qos);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--quiet")){
|
||||
ud.quiet = true;
|
||||
}else if(!strcmp(argv[i], "-R")){
|
||||
ud.no_retain = true;
|
||||
}else if(!strcmp(argv[i], "-S")){
|
||||
use_srv = true;
|
||||
}else if(!strcmp(argv[i], "-t") || !strcmp(argv[i], "--topic")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -t argument given but no topic specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ud.topic_count++;
|
||||
ud.topics = realloc(ud.topics, ud.topic_count*sizeof(char *));
|
||||
ud.topics[ud.topic_count-1] = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-T") || !strcmp(argv[i], "--filter-out")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -T argument given but no topic filter specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ud.filter_out_count++;
|
||||
ud.filter_outs = realloc(ud.filter_outs, ud.filter_out_count*sizeof(char *));
|
||||
ud.filter_outs[ud.filter_out_count-1] = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--tls-version")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --tls-version argument given but no version specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
tls_version = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-u") || !strcmp(argv[i], "--username")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -u argument given but no username specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ud.username = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")){
|
||||
ud.verbose = 1;
|
||||
}else if(!strcmp(argv[i], "-P") || !strcmp(argv[i], "--pw")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -P argument given but no password specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ud.password = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-payload")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-payload argument given but no will payload specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_payload = argv[i+1];
|
||||
will_payloadlen = strlen(will_payload);
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-qos")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-qos argument given but no will QoS specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_qos = atoi(argv[i+1]);
|
||||
if(will_qos < 0 || will_qos > 2){
|
||||
fprintf(stderr, "Error: Invalid will QoS %d.\n\n", will_qos);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-retain")){
|
||||
will_retain = true;
|
||||
}else if(!strcmp(argv[i], "--will-topic")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-topic argument given but no will topic specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_topic = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else{
|
||||
fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(clean_session == false && (id_prefix || !id)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: You must provide a client id if you are using the -c option.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(ud.topic_count == 0){
|
||||
fprintf(stderr, "Error: You must specify a topic to subscribe to.\n");
|
||||
if(client_config_load(&cfg, CLIENT_SUB, argc, argv)){
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(will_payload && !will_topic){
|
||||
fprintf(stderr, "Error: Will payload given, but no will topic given.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(will_retain && !will_topic){
|
||||
fprintf(stderr, "Error: Will retain given, but no will topic given.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(ud.password && !ud.username){
|
||||
if(!ud.quiet) fprintf(stderr, "Warning: Not using password since username not set.\n");
|
||||
}
|
||||
if((certfile && !keyfile) || (keyfile && !certfile)){
|
||||
fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if((cafile || capath) && psk){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Only one of --psk or --cafile/--capath may be used at once.\n");
|
||||
return 1;
|
||||
}
|
||||
if(psk && !psk_identity){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: --psk-identity required if --psk used.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
mosquitto_lib_init();
|
||||
|
||||
if(id_prefix){
|
||||
id = malloc(strlen(id_prefix)+10);
|
||||
if(!id){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
snprintf(id, strlen(id_prefix)+10, "%s%d", id_prefix, getpid());
|
||||
}else if(!id){
|
||||
hostname[0] = '\0';
|
||||
gethostname(hostname, 256);
|
||||
hostname[255] = '\0';
|
||||
len = strlen("mosqsub/-") + 6 + strlen(hostname);
|
||||
id = malloc(len);
|
||||
if(!id){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
snprintf(id, len, "mosqsub/%d-%s", getpid(), hostname);
|
||||
if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH){
|
||||
/* Enforce maximum client id length of 23 characters */
|
||||
id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0';
|
||||
}
|
||||
if(client_id_generate(&cfg, "mosqsub")){
|
||||
return 1;
|
||||
}
|
||||
|
||||
mosq = mosquitto_new(id, clean_session, &ud);
|
||||
mosq = mosquitto_new(cfg.id, cfg.clean_session, &cfg);
|
||||
if(!mosq){
|
||||
switch(errno){
|
||||
case ENOMEM:
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
if(!cfg.quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
break;
|
||||
case EINVAL:
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Invalid id and/or clean_session.\n");
|
||||
if(!cfg.quiet) fprintf(stderr, "Error: Invalid id and/or clean_session.\n");
|
||||
break;
|
||||
}
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(debug){
|
||||
if(client_opts_set(mosq, &cfg)){
|
||||
return 1;
|
||||
}
|
||||
if(cfg.debug){
|
||||
mosquitto_log_callback_set(mosq, my_log_callback);
|
||||
}
|
||||
if(will_topic && mosquitto_will_set(mosq, will_topic, will_payloadlen, will_payload, will_qos, will_retain)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting will.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(ud.username && mosquitto_username_pw_set(mosq, ud.username, ud.password)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting username and password.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if((cafile || capath) && mosquitto_tls_set(mosq, cafile, capath, certfile, keyfile, NULL)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(insecure && mosquitto_tls_insecure_set(mosq, true)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting TLS insecure option.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(psk && mosquitto_tls_psk_set(mosq, psk, psk_identity, NULL)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting TLS-PSK options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(tls_version && mosquitto_tls_opts_set(mosq, 1, tls_version, ciphers)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);
|
||||
}
|
||||
mosquitto_connect_callback_set(mosq, my_connect_callback);
|
||||
mosquitto_message_callback_set(mosq, my_message_callback);
|
||||
if(debug){
|
||||
mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);
|
||||
}
|
||||
|
||||
if(use_srv){
|
||||
rc = mosquitto_connect_srv(mosq, host, keepalive, bind_address);
|
||||
}else{
|
||||
rc = mosquitto_connect_bind(mosq, host, port, keepalive, bind_address);
|
||||
}
|
||||
if(rc){
|
||||
if(!ud.quiet){
|
||||
if(rc == MOSQ_ERR_ERRNO){
|
||||
#ifndef WIN32
|
||||
strerror_r(errno, err, 1024);
|
||||
#else
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errno, 0, (LPTSTR)&err, 1024, NULL);
|
||||
#endif
|
||||
fprintf(stderr, "Error: %s\n", err);
|
||||
}else{
|
||||
fprintf(stderr, "Unable to connect (%d).\n", rc);
|
||||
}
|
||||
}
|
||||
mosquitto_lib_cleanup();
|
||||
return rc;
|
||||
}
|
||||
rc = client_connect(mosq, &cfg);
|
||||
if(rc) return rc;
|
||||
|
||||
|
||||
rc = mosquitto_loop_forever(mosq, -1, 1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user