1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "server_setup.h"
25*6236dae4SAndroid Build Coastguard Worker #include <stdlib.h>
26*6236dae4SAndroid Build Coastguard Worker #include <string.h>
27*6236dae4SAndroid Build Coastguard Worker #include "util.h"
28*6236dae4SAndroid Build Coastguard Worker
29*6236dae4SAndroid Build Coastguard Worker /* Function
30*6236dae4SAndroid Build Coastguard Worker *
31*6236dae4SAndroid Build Coastguard Worker * Accepts a TCP connection on a custom port (IPv4 or IPv6). Speaks MQTT.
32*6236dae4SAndroid Build Coastguard Worker *
33*6236dae4SAndroid Build Coastguard Worker * Read commands from FILE (set with --config). The commands control how to
34*6236dae4SAndroid Build Coastguard Worker * act and is reset to defaults each client TCP connect.
35*6236dae4SAndroid Build Coastguard Worker *
36*6236dae4SAndroid Build Coastguard Worker * Config file keywords:
37*6236dae4SAndroid Build Coastguard Worker *
38*6236dae4SAndroid Build Coastguard Worker * TODO
39*6236dae4SAndroid Build Coastguard Worker */
40*6236dae4SAndroid Build Coastguard Worker
41*6236dae4SAndroid Build Coastguard Worker /* based on sockfilt.c */
42*6236dae4SAndroid Build Coastguard Worker
43*6236dae4SAndroid Build Coastguard Worker #include <signal.h>
44*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
45*6236dae4SAndroid Build Coastguard Worker #include <netinet/in.h>
46*6236dae4SAndroid Build Coastguard Worker #endif
47*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN6_H
48*6236dae4SAndroid Build Coastguard Worker #include <netinet/in6.h>
49*6236dae4SAndroid Build Coastguard Worker #endif
50*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
51*6236dae4SAndroid Build Coastguard Worker #include <arpa/inet.h>
52*6236dae4SAndroid Build Coastguard Worker #endif
53*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
54*6236dae4SAndroid Build Coastguard Worker #include <netdb.h>
55*6236dae4SAndroid Build Coastguard Worker #endif
56*6236dae4SAndroid Build Coastguard Worker
57*6236dae4SAndroid Build Coastguard Worker #include "curlx.h" /* from the private lib dir */
58*6236dae4SAndroid Build Coastguard Worker #include "getpart.h"
59*6236dae4SAndroid Build Coastguard Worker #include "inet_pton.h"
60*6236dae4SAndroid Build Coastguard Worker #include "server_sockaddr.h"
61*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
62*6236dae4SAndroid Build Coastguard Worker
63*6236dae4SAndroid Build Coastguard Worker /* include memdebug.h last */
64*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
65*6236dae4SAndroid Build Coastguard Worker
66*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
67*6236dae4SAndroid Build Coastguard Worker #undef EINTR
68*6236dae4SAndroid Build Coastguard Worker #define EINTR 4 /* errno.h value */
69*6236dae4SAndroid Build Coastguard Worker #undef EAGAIN
70*6236dae4SAndroid Build Coastguard Worker #define EAGAIN 11 /* errno.h value */
71*6236dae4SAndroid Build Coastguard Worker #undef ENOMEM
72*6236dae4SAndroid Build Coastguard Worker #define ENOMEM 12 /* errno.h value */
73*6236dae4SAndroid Build Coastguard Worker #undef EINVAL
74*6236dae4SAndroid Build Coastguard Worker #define EINVAL 22 /* errno.h value */
75*6236dae4SAndroid Build Coastguard Worker #endif
76*6236dae4SAndroid Build Coastguard Worker
77*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_PORT 1883 /* MQTT default port */
78*6236dae4SAndroid Build Coastguard Worker
79*6236dae4SAndroid Build Coastguard Worker #ifndef DEFAULT_LOGFILE
80*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_LOGFILE "log/mqttd.log"
81*6236dae4SAndroid Build Coastguard Worker #endif
82*6236dae4SAndroid Build Coastguard Worker
83*6236dae4SAndroid Build Coastguard Worker #ifndef DEFAULT_CONFIG
84*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_CONFIG "mqttd.config"
85*6236dae4SAndroid Build Coastguard Worker #endif
86*6236dae4SAndroid Build Coastguard Worker
87*6236dae4SAndroid Build Coastguard Worker #define MQTT_MSG_CONNECT 0x10
88*6236dae4SAndroid Build Coastguard Worker #define MQTT_MSG_CONNACK 0x20
89*6236dae4SAndroid Build Coastguard Worker #define MQTT_MSG_PUBLISH 0x30
90*6236dae4SAndroid Build Coastguard Worker #define MQTT_MSG_PUBACK 0x40
91*6236dae4SAndroid Build Coastguard Worker #define MQTT_MSG_SUBSCRIBE 0x82
92*6236dae4SAndroid Build Coastguard Worker #define MQTT_MSG_SUBACK 0x90
93*6236dae4SAndroid Build Coastguard Worker #define MQTT_MSG_DISCONNECT 0xe0
94*6236dae4SAndroid Build Coastguard Worker
95*6236dae4SAndroid Build Coastguard Worker #define MQTT_CONNACK_LEN 4
96*6236dae4SAndroid Build Coastguard Worker #define MQTT_SUBACK_LEN 5
97*6236dae4SAndroid Build Coastguard Worker #define MQTT_CLIENTID_LEN 12 /* "curl0123abcd" */
98*6236dae4SAndroid Build Coastguard Worker
99*6236dae4SAndroid Build Coastguard Worker struct configurable {
100*6236dae4SAndroid Build Coastguard Worker unsigned char version; /* initial version byte in the request must match
101*6236dae4SAndroid Build Coastguard Worker this */
102*6236dae4SAndroid Build Coastguard Worker bool publish_before_suback;
103*6236dae4SAndroid Build Coastguard Worker bool short_publish;
104*6236dae4SAndroid Build Coastguard Worker bool excessive_remaining;
105*6236dae4SAndroid Build Coastguard Worker unsigned char error_connack;
106*6236dae4SAndroid Build Coastguard Worker int testnum;
107*6236dae4SAndroid Build Coastguard Worker };
108*6236dae4SAndroid Build Coastguard Worker
109*6236dae4SAndroid Build Coastguard Worker #define REQUEST_DUMP "server.input"
110*6236dae4SAndroid Build Coastguard Worker #define CONFIG_VERSION 5
111*6236dae4SAndroid Build Coastguard Worker
112*6236dae4SAndroid Build Coastguard Worker static struct configurable config;
113*6236dae4SAndroid Build Coastguard Worker
114*6236dae4SAndroid Build Coastguard Worker const char *serverlogfile = DEFAULT_LOGFILE;
115*6236dae4SAndroid Build Coastguard Worker static const char *configfile = DEFAULT_CONFIG;
116*6236dae4SAndroid Build Coastguard Worker static const char *logdir = "log";
117*6236dae4SAndroid Build Coastguard Worker static char loglockfile[256];
118*6236dae4SAndroid Build Coastguard Worker
119*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
120*6236dae4SAndroid Build Coastguard Worker static bool use_ipv6 = FALSE;
121*6236dae4SAndroid Build Coastguard Worker #endif
122*6236dae4SAndroid Build Coastguard Worker static const char *ipv_inuse = "IPv4";
123*6236dae4SAndroid Build Coastguard Worker static unsigned short port = DEFAULT_PORT;
124*6236dae4SAndroid Build Coastguard Worker
resetdefaults(void)125*6236dae4SAndroid Build Coastguard Worker static void resetdefaults(void)
126*6236dae4SAndroid Build Coastguard Worker {
127*6236dae4SAndroid Build Coastguard Worker logmsg("Reset to defaults");
128*6236dae4SAndroid Build Coastguard Worker config.version = CONFIG_VERSION;
129*6236dae4SAndroid Build Coastguard Worker config.publish_before_suback = FALSE;
130*6236dae4SAndroid Build Coastguard Worker config.short_publish = FALSE;
131*6236dae4SAndroid Build Coastguard Worker config.excessive_remaining = FALSE;
132*6236dae4SAndroid Build Coastguard Worker config.error_connack = 0;
133*6236dae4SAndroid Build Coastguard Worker config.testnum = 0;
134*6236dae4SAndroid Build Coastguard Worker }
135*6236dae4SAndroid Build Coastguard Worker
byteval(char * value)136*6236dae4SAndroid Build Coastguard Worker static unsigned char byteval(char *value)
137*6236dae4SAndroid Build Coastguard Worker {
138*6236dae4SAndroid Build Coastguard Worker unsigned long num = strtoul(value, NULL, 10);
139*6236dae4SAndroid Build Coastguard Worker return num & 0xff;
140*6236dae4SAndroid Build Coastguard Worker }
141*6236dae4SAndroid Build Coastguard Worker
getconfig(void)142*6236dae4SAndroid Build Coastguard Worker static void getconfig(void)
143*6236dae4SAndroid Build Coastguard Worker {
144*6236dae4SAndroid Build Coastguard Worker FILE *fp = fopen(configfile, FOPEN_READTEXT);
145*6236dae4SAndroid Build Coastguard Worker resetdefaults();
146*6236dae4SAndroid Build Coastguard Worker if(fp) {
147*6236dae4SAndroid Build Coastguard Worker char buffer[512];
148*6236dae4SAndroid Build Coastguard Worker logmsg("parse config file");
149*6236dae4SAndroid Build Coastguard Worker while(fgets(buffer, sizeof(buffer), fp)) {
150*6236dae4SAndroid Build Coastguard Worker char key[32];
151*6236dae4SAndroid Build Coastguard Worker char value[32];
152*6236dae4SAndroid Build Coastguard Worker if(2 == sscanf(buffer, "%31s %31s", key, value)) {
153*6236dae4SAndroid Build Coastguard Worker if(!strcmp(key, "version")) {
154*6236dae4SAndroid Build Coastguard Worker config.version = byteval(value);
155*6236dae4SAndroid Build Coastguard Worker logmsg("version [%d] set", config.version);
156*6236dae4SAndroid Build Coastguard Worker }
157*6236dae4SAndroid Build Coastguard Worker else if(!strcmp(key, "PUBLISH-before-SUBACK")) {
158*6236dae4SAndroid Build Coastguard Worker logmsg("PUBLISH-before-SUBACK set");
159*6236dae4SAndroid Build Coastguard Worker config.publish_before_suback = TRUE;
160*6236dae4SAndroid Build Coastguard Worker }
161*6236dae4SAndroid Build Coastguard Worker else if(!strcmp(key, "short-PUBLISH")) {
162*6236dae4SAndroid Build Coastguard Worker logmsg("short-PUBLISH set");
163*6236dae4SAndroid Build Coastguard Worker config.short_publish = TRUE;
164*6236dae4SAndroid Build Coastguard Worker }
165*6236dae4SAndroid Build Coastguard Worker else if(!strcmp(key, "error-CONNACK")) {
166*6236dae4SAndroid Build Coastguard Worker config.error_connack = byteval(value);
167*6236dae4SAndroid Build Coastguard Worker logmsg("error-CONNACK = %d", config.error_connack);
168*6236dae4SAndroid Build Coastguard Worker }
169*6236dae4SAndroid Build Coastguard Worker else if(!strcmp(key, "Testnum")) {
170*6236dae4SAndroid Build Coastguard Worker config.testnum = atoi(value);
171*6236dae4SAndroid Build Coastguard Worker logmsg("testnum = %d", config.testnum);
172*6236dae4SAndroid Build Coastguard Worker }
173*6236dae4SAndroid Build Coastguard Worker else if(!strcmp(key, "excessive-remaining")) {
174*6236dae4SAndroid Build Coastguard Worker logmsg("excessive-remaining set");
175*6236dae4SAndroid Build Coastguard Worker config.excessive_remaining = TRUE;
176*6236dae4SAndroid Build Coastguard Worker }
177*6236dae4SAndroid Build Coastguard Worker }
178*6236dae4SAndroid Build Coastguard Worker }
179*6236dae4SAndroid Build Coastguard Worker fclose(fp);
180*6236dae4SAndroid Build Coastguard Worker }
181*6236dae4SAndroid Build Coastguard Worker else {
182*6236dae4SAndroid Build Coastguard Worker logmsg("No config file '%s' to read", configfile);
183*6236dae4SAndroid Build Coastguard Worker }
184*6236dae4SAndroid Build Coastguard Worker }
185*6236dae4SAndroid Build Coastguard Worker
loghex(unsigned char * buffer,ssize_t len)186*6236dae4SAndroid Build Coastguard Worker static void loghex(unsigned char *buffer, ssize_t len)
187*6236dae4SAndroid Build Coastguard Worker {
188*6236dae4SAndroid Build Coastguard Worker char data[12000];
189*6236dae4SAndroid Build Coastguard Worker ssize_t i;
190*6236dae4SAndroid Build Coastguard Worker unsigned char *ptr = buffer;
191*6236dae4SAndroid Build Coastguard Worker char *optr = data;
192*6236dae4SAndroid Build Coastguard Worker ssize_t width = 0;
193*6236dae4SAndroid Build Coastguard Worker int left = sizeof(data);
194*6236dae4SAndroid Build Coastguard Worker
195*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < len && (left >= 0); i++) {
196*6236dae4SAndroid Build Coastguard Worker msnprintf(optr, left, "%02x", ptr[i]);
197*6236dae4SAndroid Build Coastguard Worker width += 2;
198*6236dae4SAndroid Build Coastguard Worker optr += 2;
199*6236dae4SAndroid Build Coastguard Worker left -= 2;
200*6236dae4SAndroid Build Coastguard Worker }
201*6236dae4SAndroid Build Coastguard Worker if(width)
202*6236dae4SAndroid Build Coastguard Worker logmsg("'%s'", data);
203*6236dae4SAndroid Build Coastguard Worker }
204*6236dae4SAndroid Build Coastguard Worker
205*6236dae4SAndroid Build Coastguard Worker typedef enum {
206*6236dae4SAndroid Build Coastguard Worker FROM_CLIENT,
207*6236dae4SAndroid Build Coastguard Worker FROM_SERVER
208*6236dae4SAndroid Build Coastguard Worker } mqttdir;
209*6236dae4SAndroid Build Coastguard Worker
logprotocol(mqttdir dir,const char * prefix,size_t remlen,FILE * output,unsigned char * buffer,ssize_t len)210*6236dae4SAndroid Build Coastguard Worker static void logprotocol(mqttdir dir,
211*6236dae4SAndroid Build Coastguard Worker const char *prefix, size_t remlen,
212*6236dae4SAndroid Build Coastguard Worker FILE *output,
213*6236dae4SAndroid Build Coastguard Worker unsigned char *buffer, ssize_t len)
214*6236dae4SAndroid Build Coastguard Worker {
215*6236dae4SAndroid Build Coastguard Worker char data[12000] = "";
216*6236dae4SAndroid Build Coastguard Worker ssize_t i;
217*6236dae4SAndroid Build Coastguard Worker unsigned char *ptr = buffer;
218*6236dae4SAndroid Build Coastguard Worker char *optr = data;
219*6236dae4SAndroid Build Coastguard Worker int left = sizeof(data);
220*6236dae4SAndroid Build Coastguard Worker
221*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < len && (left >= 0); i++) {
222*6236dae4SAndroid Build Coastguard Worker msnprintf(optr, left, "%02x", ptr[i]);
223*6236dae4SAndroid Build Coastguard Worker optr += 2;
224*6236dae4SAndroid Build Coastguard Worker left -= 2;
225*6236dae4SAndroid Build Coastguard Worker }
226*6236dae4SAndroid Build Coastguard Worker fprintf(output, "%s %s %zx %s\n",
227*6236dae4SAndroid Build Coastguard Worker dir == FROM_CLIENT ? "client" : "server",
228*6236dae4SAndroid Build Coastguard Worker prefix, remlen, data);
229*6236dae4SAndroid Build Coastguard Worker }
230*6236dae4SAndroid Build Coastguard Worker
231*6236dae4SAndroid Build Coastguard Worker
232*6236dae4SAndroid Build Coastguard Worker /* return 0 on success */
connack(FILE * dump,curl_socket_t fd)233*6236dae4SAndroid Build Coastguard Worker static int connack(FILE *dump, curl_socket_t fd)
234*6236dae4SAndroid Build Coastguard Worker {
235*6236dae4SAndroid Build Coastguard Worker unsigned char packet[]={
236*6236dae4SAndroid Build Coastguard Worker MQTT_MSG_CONNACK, 0x02,
237*6236dae4SAndroid Build Coastguard Worker 0x00, 0x00
238*6236dae4SAndroid Build Coastguard Worker };
239*6236dae4SAndroid Build Coastguard Worker ssize_t rc;
240*6236dae4SAndroid Build Coastguard Worker
241*6236dae4SAndroid Build Coastguard Worker packet[3] = config.error_connack;
242*6236dae4SAndroid Build Coastguard Worker
243*6236dae4SAndroid Build Coastguard Worker rc = swrite(fd, (char *)packet, sizeof(packet));
244*6236dae4SAndroid Build Coastguard Worker if(rc > 0) {
245*6236dae4SAndroid Build Coastguard Worker logmsg("WROTE %zd bytes [CONNACK]", rc);
246*6236dae4SAndroid Build Coastguard Worker loghex(packet, rc);
247*6236dae4SAndroid Build Coastguard Worker logprotocol(FROM_SERVER, "CONNACK", 2, dump, packet, sizeof(packet));
248*6236dae4SAndroid Build Coastguard Worker }
249*6236dae4SAndroid Build Coastguard Worker if(rc == sizeof(packet)) {
250*6236dae4SAndroid Build Coastguard Worker return 0;
251*6236dae4SAndroid Build Coastguard Worker }
252*6236dae4SAndroid Build Coastguard Worker return 1;
253*6236dae4SAndroid Build Coastguard Worker }
254*6236dae4SAndroid Build Coastguard Worker
255*6236dae4SAndroid Build Coastguard Worker /* return 0 on success */
suback(FILE * dump,curl_socket_t fd,unsigned short packetid)256*6236dae4SAndroid Build Coastguard Worker static int suback(FILE *dump, curl_socket_t fd, unsigned short packetid)
257*6236dae4SAndroid Build Coastguard Worker {
258*6236dae4SAndroid Build Coastguard Worker unsigned char packet[]={
259*6236dae4SAndroid Build Coastguard Worker MQTT_MSG_SUBACK, 0x03,
260*6236dae4SAndroid Build Coastguard Worker 0, 0, /* filled in below */
261*6236dae4SAndroid Build Coastguard Worker 0x00
262*6236dae4SAndroid Build Coastguard Worker };
263*6236dae4SAndroid Build Coastguard Worker ssize_t rc;
264*6236dae4SAndroid Build Coastguard Worker packet[2] = (unsigned char)(packetid >> 8);
265*6236dae4SAndroid Build Coastguard Worker packet[3] = (unsigned char)(packetid & 0xff);
266*6236dae4SAndroid Build Coastguard Worker
267*6236dae4SAndroid Build Coastguard Worker rc = swrite(fd, (char *)packet, sizeof(packet));
268*6236dae4SAndroid Build Coastguard Worker if(rc == sizeof(packet)) {
269*6236dae4SAndroid Build Coastguard Worker logmsg("WROTE %zd bytes [SUBACK]", rc);
270*6236dae4SAndroid Build Coastguard Worker loghex(packet, rc);
271*6236dae4SAndroid Build Coastguard Worker logprotocol(FROM_SERVER, "SUBACK", 3, dump, packet, rc);
272*6236dae4SAndroid Build Coastguard Worker return 0;
273*6236dae4SAndroid Build Coastguard Worker }
274*6236dae4SAndroid Build Coastguard Worker return 1;
275*6236dae4SAndroid Build Coastguard Worker }
276*6236dae4SAndroid Build Coastguard Worker
277*6236dae4SAndroid Build Coastguard Worker #ifdef QOS
278*6236dae4SAndroid Build Coastguard Worker /* return 0 on success */
puback(FILE * dump,curl_socket_t fd,unsigned short packetid)279*6236dae4SAndroid Build Coastguard Worker static int puback(FILE *dump, curl_socket_t fd, unsigned short packetid)
280*6236dae4SAndroid Build Coastguard Worker {
281*6236dae4SAndroid Build Coastguard Worker unsigned char packet[]={
282*6236dae4SAndroid Build Coastguard Worker MQTT_MSG_PUBACK, 0x00,
283*6236dae4SAndroid Build Coastguard Worker 0, 0 /* filled in below */
284*6236dae4SAndroid Build Coastguard Worker };
285*6236dae4SAndroid Build Coastguard Worker ssize_t rc;
286*6236dae4SAndroid Build Coastguard Worker packet[2] = (unsigned char)(packetid >> 8);
287*6236dae4SAndroid Build Coastguard Worker packet[3] = (unsigned char)(packetid & 0xff);
288*6236dae4SAndroid Build Coastguard Worker
289*6236dae4SAndroid Build Coastguard Worker rc = swrite(fd, (char *)packet, sizeof(packet));
290*6236dae4SAndroid Build Coastguard Worker if(rc == sizeof(packet)) {
291*6236dae4SAndroid Build Coastguard Worker logmsg("WROTE %zd bytes [PUBACK]", rc);
292*6236dae4SAndroid Build Coastguard Worker loghex(packet, rc);
293*6236dae4SAndroid Build Coastguard Worker logprotocol(FROM_SERVER, dump, packet, rc);
294*6236dae4SAndroid Build Coastguard Worker return 0;
295*6236dae4SAndroid Build Coastguard Worker }
296*6236dae4SAndroid Build Coastguard Worker logmsg("Failed sending [PUBACK]");
297*6236dae4SAndroid Build Coastguard Worker return 1;
298*6236dae4SAndroid Build Coastguard Worker }
299*6236dae4SAndroid Build Coastguard Worker #endif
300*6236dae4SAndroid Build Coastguard Worker
301*6236dae4SAndroid Build Coastguard Worker /* return 0 on success */
disconnect(FILE * dump,curl_socket_t fd)302*6236dae4SAndroid Build Coastguard Worker static int disconnect(FILE *dump, curl_socket_t fd)
303*6236dae4SAndroid Build Coastguard Worker {
304*6236dae4SAndroid Build Coastguard Worker unsigned char packet[]={
305*6236dae4SAndroid Build Coastguard Worker MQTT_MSG_DISCONNECT, 0x00,
306*6236dae4SAndroid Build Coastguard Worker };
307*6236dae4SAndroid Build Coastguard Worker ssize_t rc = swrite(fd, (char *)packet, sizeof(packet));
308*6236dae4SAndroid Build Coastguard Worker if(rc == sizeof(packet)) {
309*6236dae4SAndroid Build Coastguard Worker logmsg("WROTE %zd bytes [DISCONNECT]", rc);
310*6236dae4SAndroid Build Coastguard Worker loghex(packet, rc);
311*6236dae4SAndroid Build Coastguard Worker logprotocol(FROM_SERVER, "DISCONNECT", 0, dump, packet, rc);
312*6236dae4SAndroid Build Coastguard Worker return 0;
313*6236dae4SAndroid Build Coastguard Worker }
314*6236dae4SAndroid Build Coastguard Worker logmsg("Failed sending [DISCONNECT]");
315*6236dae4SAndroid Build Coastguard Worker return 1;
316*6236dae4SAndroid Build Coastguard Worker }
317*6236dae4SAndroid Build Coastguard Worker
318*6236dae4SAndroid Build Coastguard Worker
319*6236dae4SAndroid Build Coastguard Worker
320*6236dae4SAndroid Build Coastguard Worker /*
321*6236dae4SAndroid Build Coastguard Worker do
322*6236dae4SAndroid Build Coastguard Worker
323*6236dae4SAndroid Build Coastguard Worker encodedByte = X MOD 128
324*6236dae4SAndroid Build Coastguard Worker
325*6236dae4SAndroid Build Coastguard Worker X = X DIV 128
326*6236dae4SAndroid Build Coastguard Worker
327*6236dae4SAndroid Build Coastguard Worker // if there are more data to encode, set the top bit of this byte
328*6236dae4SAndroid Build Coastguard Worker
329*6236dae4SAndroid Build Coastguard Worker if ( X > 0 )
330*6236dae4SAndroid Build Coastguard Worker
331*6236dae4SAndroid Build Coastguard Worker encodedByte = encodedByte OR 128
332*6236dae4SAndroid Build Coastguard Worker
333*6236dae4SAndroid Build Coastguard Worker endif
334*6236dae4SAndroid Build Coastguard Worker
335*6236dae4SAndroid Build Coastguard Worker 'output' encodedByte
336*6236dae4SAndroid Build Coastguard Worker
337*6236dae4SAndroid Build Coastguard Worker while ( X > 0 )
338*6236dae4SAndroid Build Coastguard Worker
339*6236dae4SAndroid Build Coastguard Worker */
340*6236dae4SAndroid Build Coastguard Worker
341*6236dae4SAndroid Build Coastguard Worker /* return number of bytes used */
encode_length(size_t packetlen,unsigned char * remlength)342*6236dae4SAndroid Build Coastguard Worker static size_t encode_length(size_t packetlen,
343*6236dae4SAndroid Build Coastguard Worker unsigned char *remlength) /* 4 bytes */
344*6236dae4SAndroid Build Coastguard Worker {
345*6236dae4SAndroid Build Coastguard Worker size_t bytes = 0;
346*6236dae4SAndroid Build Coastguard Worker unsigned char encode;
347*6236dae4SAndroid Build Coastguard Worker
348*6236dae4SAndroid Build Coastguard Worker do {
349*6236dae4SAndroid Build Coastguard Worker encode = packetlen % 0x80;
350*6236dae4SAndroid Build Coastguard Worker packetlen /= 0x80;
351*6236dae4SAndroid Build Coastguard Worker if(packetlen)
352*6236dae4SAndroid Build Coastguard Worker encode |= 0x80;
353*6236dae4SAndroid Build Coastguard Worker
354*6236dae4SAndroid Build Coastguard Worker remlength[bytes++] = encode;
355*6236dae4SAndroid Build Coastguard Worker
356*6236dae4SAndroid Build Coastguard Worker if(bytes > 3) {
357*6236dae4SAndroid Build Coastguard Worker logmsg("too large packet!");
358*6236dae4SAndroid Build Coastguard Worker return 0;
359*6236dae4SAndroid Build Coastguard Worker }
360*6236dae4SAndroid Build Coastguard Worker } while(packetlen);
361*6236dae4SAndroid Build Coastguard Worker
362*6236dae4SAndroid Build Coastguard Worker return bytes;
363*6236dae4SAndroid Build Coastguard Worker }
364*6236dae4SAndroid Build Coastguard Worker
365*6236dae4SAndroid Build Coastguard Worker
decode_length(unsigned char * buf,size_t buflen,size_t * lenbytes)366*6236dae4SAndroid Build Coastguard Worker static size_t decode_length(unsigned char *buf,
367*6236dae4SAndroid Build Coastguard Worker size_t buflen, size_t *lenbytes)
368*6236dae4SAndroid Build Coastguard Worker {
369*6236dae4SAndroid Build Coastguard Worker size_t len = 0;
370*6236dae4SAndroid Build Coastguard Worker size_t mult = 1;
371*6236dae4SAndroid Build Coastguard Worker size_t i;
372*6236dae4SAndroid Build Coastguard Worker unsigned char encoded = 0x80;
373*6236dae4SAndroid Build Coastguard Worker
374*6236dae4SAndroid Build Coastguard Worker for(i = 0; (i < buflen) && (encoded & 0x80); i++) {
375*6236dae4SAndroid Build Coastguard Worker encoded = buf[i];
376*6236dae4SAndroid Build Coastguard Worker len += (encoded & 0x7f) * mult;
377*6236dae4SAndroid Build Coastguard Worker mult *= 0x80;
378*6236dae4SAndroid Build Coastguard Worker }
379*6236dae4SAndroid Build Coastguard Worker
380*6236dae4SAndroid Build Coastguard Worker if(lenbytes)
381*6236dae4SAndroid Build Coastguard Worker *lenbytes = i;
382*6236dae4SAndroid Build Coastguard Worker
383*6236dae4SAndroid Build Coastguard Worker return len;
384*6236dae4SAndroid Build Coastguard Worker }
385*6236dae4SAndroid Build Coastguard Worker
386*6236dae4SAndroid Build Coastguard Worker
387*6236dae4SAndroid Build Coastguard Worker /* return 0 on success */
publish(FILE * dump,curl_socket_t fd,unsigned short packetid,char * topic,char * payload,size_t payloadlen)388*6236dae4SAndroid Build Coastguard Worker static int publish(FILE *dump,
389*6236dae4SAndroid Build Coastguard Worker curl_socket_t fd, unsigned short packetid,
390*6236dae4SAndroid Build Coastguard Worker char *topic, char *payload, size_t payloadlen)
391*6236dae4SAndroid Build Coastguard Worker {
392*6236dae4SAndroid Build Coastguard Worker size_t topiclen = strlen(topic);
393*6236dae4SAndroid Build Coastguard Worker unsigned char *packet;
394*6236dae4SAndroid Build Coastguard Worker size_t payloadindex;
395*6236dae4SAndroid Build Coastguard Worker size_t remaininglength = topiclen + 2 + payloadlen;
396*6236dae4SAndroid Build Coastguard Worker size_t packetlen;
397*6236dae4SAndroid Build Coastguard Worker size_t sendamount;
398*6236dae4SAndroid Build Coastguard Worker ssize_t rc;
399*6236dae4SAndroid Build Coastguard Worker unsigned char rembuffer[4];
400*6236dae4SAndroid Build Coastguard Worker size_t encodedlen;
401*6236dae4SAndroid Build Coastguard Worker
402*6236dae4SAndroid Build Coastguard Worker if(config.excessive_remaining) {
403*6236dae4SAndroid Build Coastguard Worker /* manually set illegal remaining length */
404*6236dae4SAndroid Build Coastguard Worker rembuffer[0] = 0xff;
405*6236dae4SAndroid Build Coastguard Worker rembuffer[1] = 0xff;
406*6236dae4SAndroid Build Coastguard Worker rembuffer[2] = 0xff;
407*6236dae4SAndroid Build Coastguard Worker rembuffer[3] = 0x80; /* maximum allowed here by spec is 0x7f */
408*6236dae4SAndroid Build Coastguard Worker encodedlen = 4;
409*6236dae4SAndroid Build Coastguard Worker }
410*6236dae4SAndroid Build Coastguard Worker else
411*6236dae4SAndroid Build Coastguard Worker encodedlen = encode_length(remaininglength, rembuffer);
412*6236dae4SAndroid Build Coastguard Worker
413*6236dae4SAndroid Build Coastguard Worker /* one packet type byte (possibly two more for packetid) */
414*6236dae4SAndroid Build Coastguard Worker packetlen = remaininglength + encodedlen + 1;
415*6236dae4SAndroid Build Coastguard Worker packet = malloc(packetlen);
416*6236dae4SAndroid Build Coastguard Worker if(!packet)
417*6236dae4SAndroid Build Coastguard Worker return 1;
418*6236dae4SAndroid Build Coastguard Worker
419*6236dae4SAndroid Build Coastguard Worker packet[0] = MQTT_MSG_PUBLISH; /* TODO: set QoS? */
420*6236dae4SAndroid Build Coastguard Worker memcpy(&packet[1], rembuffer, encodedlen);
421*6236dae4SAndroid Build Coastguard Worker
422*6236dae4SAndroid Build Coastguard Worker (void)packetid;
423*6236dae4SAndroid Build Coastguard Worker /* packet_id if QoS is set */
424*6236dae4SAndroid Build Coastguard Worker
425*6236dae4SAndroid Build Coastguard Worker packet[1 + encodedlen] = (unsigned char)(topiclen >> 8);
426*6236dae4SAndroid Build Coastguard Worker packet[2 + encodedlen] = (unsigned char)(topiclen & 0xff);
427*6236dae4SAndroid Build Coastguard Worker memcpy(&packet[3 + encodedlen], topic, topiclen);
428*6236dae4SAndroid Build Coastguard Worker
429*6236dae4SAndroid Build Coastguard Worker payloadindex = 3 + topiclen + encodedlen;
430*6236dae4SAndroid Build Coastguard Worker memcpy(&packet[payloadindex], payload, payloadlen);
431*6236dae4SAndroid Build Coastguard Worker
432*6236dae4SAndroid Build Coastguard Worker sendamount = packetlen;
433*6236dae4SAndroid Build Coastguard Worker if(config.short_publish)
434*6236dae4SAndroid Build Coastguard Worker sendamount -= 2;
435*6236dae4SAndroid Build Coastguard Worker
436*6236dae4SAndroid Build Coastguard Worker rc = swrite(fd, (char *)packet, sendamount);
437*6236dae4SAndroid Build Coastguard Worker if(rc > 0) {
438*6236dae4SAndroid Build Coastguard Worker logmsg("WROTE %zd bytes [PUBLISH]", rc);
439*6236dae4SAndroid Build Coastguard Worker loghex(packet, rc);
440*6236dae4SAndroid Build Coastguard Worker logprotocol(FROM_SERVER, "PUBLISH", remaininglength, dump, packet, rc);
441*6236dae4SAndroid Build Coastguard Worker }
442*6236dae4SAndroid Build Coastguard Worker free(packet);
443*6236dae4SAndroid Build Coastguard Worker if((size_t)rc == packetlen)
444*6236dae4SAndroid Build Coastguard Worker return 0;
445*6236dae4SAndroid Build Coastguard Worker return 1;
446*6236dae4SAndroid Build Coastguard Worker }
447*6236dae4SAndroid Build Coastguard Worker
448*6236dae4SAndroid Build Coastguard Worker #define MAX_TOPIC_LENGTH 65535
449*6236dae4SAndroid Build Coastguard Worker #define MAX_CLIENT_ID_LENGTH 32
450*6236dae4SAndroid Build Coastguard Worker
451*6236dae4SAndroid Build Coastguard Worker static char topic[MAX_TOPIC_LENGTH + 1];
452*6236dae4SAndroid Build Coastguard Worker
fixedheader(curl_socket_t fd,unsigned char * bytep,size_t * remaining_lengthp,size_t * remaining_length_bytesp)453*6236dae4SAndroid Build Coastguard Worker static int fixedheader(curl_socket_t fd,
454*6236dae4SAndroid Build Coastguard Worker unsigned char *bytep,
455*6236dae4SAndroid Build Coastguard Worker size_t *remaining_lengthp,
456*6236dae4SAndroid Build Coastguard Worker size_t *remaining_length_bytesp)
457*6236dae4SAndroid Build Coastguard Worker {
458*6236dae4SAndroid Build Coastguard Worker /* get the fixed header */
459*6236dae4SAndroid Build Coastguard Worker unsigned char buffer[10];
460*6236dae4SAndroid Build Coastguard Worker
461*6236dae4SAndroid Build Coastguard Worker /* get the first two bytes */
462*6236dae4SAndroid Build Coastguard Worker ssize_t rc = sread(fd, (char *)buffer, 2);
463*6236dae4SAndroid Build Coastguard Worker size_t i;
464*6236dae4SAndroid Build Coastguard Worker if(rc < 2) {
465*6236dae4SAndroid Build Coastguard Worker logmsg("READ %zd bytes [SHORT!]", rc);
466*6236dae4SAndroid Build Coastguard Worker return 1; /* fail */
467*6236dae4SAndroid Build Coastguard Worker }
468*6236dae4SAndroid Build Coastguard Worker logmsg("READ %zd bytes", rc);
469*6236dae4SAndroid Build Coastguard Worker loghex(buffer, rc);
470*6236dae4SAndroid Build Coastguard Worker *bytep = buffer[0];
471*6236dae4SAndroid Build Coastguard Worker
472*6236dae4SAndroid Build Coastguard Worker /* if the length byte has the top bit set, get the next one too */
473*6236dae4SAndroid Build Coastguard Worker i = 1;
474*6236dae4SAndroid Build Coastguard Worker while(buffer[i] & 0x80) {
475*6236dae4SAndroid Build Coastguard Worker i++;
476*6236dae4SAndroid Build Coastguard Worker rc = sread(fd, (char *)&buffer[i], 1);
477*6236dae4SAndroid Build Coastguard Worker if(rc != 1) {
478*6236dae4SAndroid Build Coastguard Worker logmsg("Remaining Length broken");
479*6236dae4SAndroid Build Coastguard Worker return 1;
480*6236dae4SAndroid Build Coastguard Worker }
481*6236dae4SAndroid Build Coastguard Worker }
482*6236dae4SAndroid Build Coastguard Worker *remaining_lengthp = decode_length(&buffer[1], i, remaining_length_bytesp);
483*6236dae4SAndroid Build Coastguard Worker logmsg("Remaining Length: %zu [%zu bytes]", *remaining_lengthp,
484*6236dae4SAndroid Build Coastguard Worker *remaining_length_bytesp);
485*6236dae4SAndroid Build Coastguard Worker return 0;
486*6236dae4SAndroid Build Coastguard Worker }
487*6236dae4SAndroid Build Coastguard Worker
mqttit(curl_socket_t fd)488*6236dae4SAndroid Build Coastguard Worker static curl_socket_t mqttit(curl_socket_t fd)
489*6236dae4SAndroid Build Coastguard Worker {
490*6236dae4SAndroid Build Coastguard Worker size_t buff_size = 10*1024;
491*6236dae4SAndroid Build Coastguard Worker unsigned char *buffer = NULL;
492*6236dae4SAndroid Build Coastguard Worker ssize_t rc;
493*6236dae4SAndroid Build Coastguard Worker unsigned char byte;
494*6236dae4SAndroid Build Coastguard Worker unsigned short packet_id;
495*6236dae4SAndroid Build Coastguard Worker size_t payload_len;
496*6236dae4SAndroid Build Coastguard Worker size_t client_id_length;
497*6236dae4SAndroid Build Coastguard Worker size_t topic_len;
498*6236dae4SAndroid Build Coastguard Worker size_t remaining_length = 0;
499*6236dae4SAndroid Build Coastguard Worker size_t bytes = 0; /* remaining length field size in bytes */
500*6236dae4SAndroid Build Coastguard Worker char client_id[MAX_CLIENT_ID_LENGTH];
501*6236dae4SAndroid Build Coastguard Worker long testno;
502*6236dae4SAndroid Build Coastguard Worker FILE *stream = NULL;
503*6236dae4SAndroid Build Coastguard Worker FILE *dump;
504*6236dae4SAndroid Build Coastguard Worker char dumpfile[256];
505*6236dae4SAndroid Build Coastguard Worker
506*6236dae4SAndroid Build Coastguard Worker static const char protocol[7] = {
507*6236dae4SAndroid Build Coastguard Worker 0x00, 0x04, /* protocol length */
508*6236dae4SAndroid Build Coastguard Worker 'M','Q','T','T', /* protocol name */
509*6236dae4SAndroid Build Coastguard Worker 0x04 /* protocol level */
510*6236dae4SAndroid Build Coastguard Worker };
511*6236dae4SAndroid Build Coastguard Worker msnprintf(dumpfile, sizeof(dumpfile), "%s/%s", logdir, REQUEST_DUMP);
512*6236dae4SAndroid Build Coastguard Worker dump = fopen(dumpfile, "ab");
513*6236dae4SAndroid Build Coastguard Worker if(!dump)
514*6236dae4SAndroid Build Coastguard Worker goto end;
515*6236dae4SAndroid Build Coastguard Worker
516*6236dae4SAndroid Build Coastguard Worker getconfig();
517*6236dae4SAndroid Build Coastguard Worker
518*6236dae4SAndroid Build Coastguard Worker testno = config.testnum;
519*6236dae4SAndroid Build Coastguard Worker
520*6236dae4SAndroid Build Coastguard Worker if(testno)
521*6236dae4SAndroid Build Coastguard Worker logmsg("Found test number %ld", testno);
522*6236dae4SAndroid Build Coastguard Worker
523*6236dae4SAndroid Build Coastguard Worker buffer = malloc(buff_size);
524*6236dae4SAndroid Build Coastguard Worker if(!buffer) {
525*6236dae4SAndroid Build Coastguard Worker logmsg("Out of memory, unable to allocate buffer");
526*6236dae4SAndroid Build Coastguard Worker goto end;
527*6236dae4SAndroid Build Coastguard Worker }
528*6236dae4SAndroid Build Coastguard Worker
529*6236dae4SAndroid Build Coastguard Worker do {
530*6236dae4SAndroid Build Coastguard Worker unsigned char usr_flag = 0x80;
531*6236dae4SAndroid Build Coastguard Worker unsigned char passwd_flag = 0x40;
532*6236dae4SAndroid Build Coastguard Worker unsigned char conn_flags;
533*6236dae4SAndroid Build Coastguard Worker const size_t client_id_offset = 12;
534*6236dae4SAndroid Build Coastguard Worker size_t start_usr;
535*6236dae4SAndroid Build Coastguard Worker size_t start_passwd;
536*6236dae4SAndroid Build Coastguard Worker
537*6236dae4SAndroid Build Coastguard Worker /* get the fixed header */
538*6236dae4SAndroid Build Coastguard Worker rc = fixedheader(fd, &byte, &remaining_length, &bytes);
539*6236dae4SAndroid Build Coastguard Worker if(rc)
540*6236dae4SAndroid Build Coastguard Worker break;
541*6236dae4SAndroid Build Coastguard Worker
542*6236dae4SAndroid Build Coastguard Worker if(remaining_length >= buff_size) {
543*6236dae4SAndroid Build Coastguard Worker buff_size = remaining_length;
544*6236dae4SAndroid Build Coastguard Worker buffer = realloc(buffer, buff_size);
545*6236dae4SAndroid Build Coastguard Worker if(!buffer) {
546*6236dae4SAndroid Build Coastguard Worker logmsg("Failed realloc of size %zu", buff_size);
547*6236dae4SAndroid Build Coastguard Worker goto end;
548*6236dae4SAndroid Build Coastguard Worker }
549*6236dae4SAndroid Build Coastguard Worker }
550*6236dae4SAndroid Build Coastguard Worker
551*6236dae4SAndroid Build Coastguard Worker if(remaining_length) {
552*6236dae4SAndroid Build Coastguard Worker /* reading variable header and payload into buffer */
553*6236dae4SAndroid Build Coastguard Worker rc = sread(fd, (char *)buffer, remaining_length);
554*6236dae4SAndroid Build Coastguard Worker if(rc > 0) {
555*6236dae4SAndroid Build Coastguard Worker logmsg("READ %zd bytes", rc);
556*6236dae4SAndroid Build Coastguard Worker loghex(buffer, rc);
557*6236dae4SAndroid Build Coastguard Worker }
558*6236dae4SAndroid Build Coastguard Worker }
559*6236dae4SAndroid Build Coastguard Worker
560*6236dae4SAndroid Build Coastguard Worker if(byte == MQTT_MSG_CONNECT) {
561*6236dae4SAndroid Build Coastguard Worker logprotocol(FROM_CLIENT, "CONNECT", remaining_length,
562*6236dae4SAndroid Build Coastguard Worker dump, buffer, rc);
563*6236dae4SAndroid Build Coastguard Worker
564*6236dae4SAndroid Build Coastguard Worker if(memcmp(protocol, buffer, sizeof(protocol))) {
565*6236dae4SAndroid Build Coastguard Worker logmsg("Protocol preamble mismatch");
566*6236dae4SAndroid Build Coastguard Worker goto end;
567*6236dae4SAndroid Build Coastguard Worker }
568*6236dae4SAndroid Build Coastguard Worker /* ignore the connect flag byte and two keepalive bytes */
569*6236dae4SAndroid Build Coastguard Worker payload_len = (size_t)(buffer[10] << 8) | buffer[11];
570*6236dae4SAndroid Build Coastguard Worker /* first part of the payload is the client ID */
571*6236dae4SAndroid Build Coastguard Worker client_id_length = payload_len;
572*6236dae4SAndroid Build Coastguard Worker
573*6236dae4SAndroid Build Coastguard Worker /* checking if user and password flags were set */
574*6236dae4SAndroid Build Coastguard Worker conn_flags = buffer[7];
575*6236dae4SAndroid Build Coastguard Worker
576*6236dae4SAndroid Build Coastguard Worker start_usr = client_id_offset + payload_len;
577*6236dae4SAndroid Build Coastguard Worker if(usr_flag == (unsigned char)(conn_flags & usr_flag)) {
578*6236dae4SAndroid Build Coastguard Worker logmsg("User flag is present in CONN flag");
579*6236dae4SAndroid Build Coastguard Worker payload_len += (size_t)(buffer[start_usr] << 8) |
580*6236dae4SAndroid Build Coastguard Worker buffer[start_usr + 1];
581*6236dae4SAndroid Build Coastguard Worker payload_len += 2; /* MSB and LSB for user length */
582*6236dae4SAndroid Build Coastguard Worker }
583*6236dae4SAndroid Build Coastguard Worker
584*6236dae4SAndroid Build Coastguard Worker start_passwd = client_id_offset + payload_len;
585*6236dae4SAndroid Build Coastguard Worker if(passwd_flag == (char)(conn_flags & passwd_flag)) {
586*6236dae4SAndroid Build Coastguard Worker logmsg("Password flag is present in CONN flags");
587*6236dae4SAndroid Build Coastguard Worker payload_len += (size_t)(buffer[start_passwd] << 8) |
588*6236dae4SAndroid Build Coastguard Worker buffer[start_passwd + 1];
589*6236dae4SAndroid Build Coastguard Worker payload_len += 2; /* MSB and LSB for password length */
590*6236dae4SAndroid Build Coastguard Worker }
591*6236dae4SAndroid Build Coastguard Worker
592*6236dae4SAndroid Build Coastguard Worker /* check the length of the payload */
593*6236dae4SAndroid Build Coastguard Worker if((ssize_t)payload_len != (rc - 12)) {
594*6236dae4SAndroid Build Coastguard Worker logmsg("Payload length mismatch, expected %zx got %zx",
595*6236dae4SAndroid Build Coastguard Worker rc - 12, payload_len);
596*6236dae4SAndroid Build Coastguard Worker goto end;
597*6236dae4SAndroid Build Coastguard Worker }
598*6236dae4SAndroid Build Coastguard Worker /* check the length of the client ID */
599*6236dae4SAndroid Build Coastguard Worker else if((client_id_length + 1) > MAX_CLIENT_ID_LENGTH) {
600*6236dae4SAndroid Build Coastguard Worker logmsg("Too large client id");
601*6236dae4SAndroid Build Coastguard Worker goto end;
602*6236dae4SAndroid Build Coastguard Worker }
603*6236dae4SAndroid Build Coastguard Worker memcpy(client_id, &buffer[12], client_id_length);
604*6236dae4SAndroid Build Coastguard Worker client_id[client_id_length] = 0;
605*6236dae4SAndroid Build Coastguard Worker
606*6236dae4SAndroid Build Coastguard Worker logmsg("MQTT client connect accepted: %s", client_id);
607*6236dae4SAndroid Build Coastguard Worker
608*6236dae4SAndroid Build Coastguard Worker /* The first packet sent from the Server to the Client MUST be a
609*6236dae4SAndroid Build Coastguard Worker CONNACK Packet */
610*6236dae4SAndroid Build Coastguard Worker
611*6236dae4SAndroid Build Coastguard Worker if(connack(dump, fd)) {
612*6236dae4SAndroid Build Coastguard Worker logmsg("failed sending CONNACK");
613*6236dae4SAndroid Build Coastguard Worker goto end;
614*6236dae4SAndroid Build Coastguard Worker }
615*6236dae4SAndroid Build Coastguard Worker }
616*6236dae4SAndroid Build Coastguard Worker else if(byte == MQTT_MSG_SUBSCRIBE) {
617*6236dae4SAndroid Build Coastguard Worker int error;
618*6236dae4SAndroid Build Coastguard Worker char *data;
619*6236dae4SAndroid Build Coastguard Worker size_t datalen;
620*6236dae4SAndroid Build Coastguard Worker logprotocol(FROM_CLIENT, "SUBSCRIBE", remaining_length,
621*6236dae4SAndroid Build Coastguard Worker dump, buffer, rc);
622*6236dae4SAndroid Build Coastguard Worker logmsg("Incoming SUBSCRIBE");
623*6236dae4SAndroid Build Coastguard Worker
624*6236dae4SAndroid Build Coastguard Worker if(rc < 6) {
625*6236dae4SAndroid Build Coastguard Worker logmsg("Too small SUBSCRIBE");
626*6236dae4SAndroid Build Coastguard Worker goto end;
627*6236dae4SAndroid Build Coastguard Worker }
628*6236dae4SAndroid Build Coastguard Worker
629*6236dae4SAndroid Build Coastguard Worker /* two bytes packet id */
630*6236dae4SAndroid Build Coastguard Worker packet_id = (unsigned short)((buffer[0] << 8) | buffer[1]);
631*6236dae4SAndroid Build Coastguard Worker
632*6236dae4SAndroid Build Coastguard Worker /* two bytes topic length */
633*6236dae4SAndroid Build Coastguard Worker topic_len = (size_t)(buffer[2] << 8) | buffer[3];
634*6236dae4SAndroid Build Coastguard Worker if(topic_len != (remaining_length - 5)) {
635*6236dae4SAndroid Build Coastguard Worker logmsg("Wrong topic length, got %zu expected %zu",
636*6236dae4SAndroid Build Coastguard Worker topic_len, remaining_length - 5);
637*6236dae4SAndroid Build Coastguard Worker goto end;
638*6236dae4SAndroid Build Coastguard Worker }
639*6236dae4SAndroid Build Coastguard Worker memcpy(topic, &buffer[4], topic_len);
640*6236dae4SAndroid Build Coastguard Worker topic[topic_len] = 0;
641*6236dae4SAndroid Build Coastguard Worker
642*6236dae4SAndroid Build Coastguard Worker /* there's a QoS byte (two bits) after the topic */
643*6236dae4SAndroid Build Coastguard Worker
644*6236dae4SAndroid Build Coastguard Worker logmsg("SUBSCRIBE to '%s' [%d]", topic, packet_id);
645*6236dae4SAndroid Build Coastguard Worker stream = test2fopen(testno, logdir);
646*6236dae4SAndroid Build Coastguard Worker error = getpart(&data, &datalen, "reply", "data", stream);
647*6236dae4SAndroid Build Coastguard Worker if(!error) {
648*6236dae4SAndroid Build Coastguard Worker if(!config.publish_before_suback) {
649*6236dae4SAndroid Build Coastguard Worker if(suback(dump, fd, packet_id)) {
650*6236dae4SAndroid Build Coastguard Worker logmsg("failed sending SUBACK");
651*6236dae4SAndroid Build Coastguard Worker free(data);
652*6236dae4SAndroid Build Coastguard Worker goto end;
653*6236dae4SAndroid Build Coastguard Worker }
654*6236dae4SAndroid Build Coastguard Worker }
655*6236dae4SAndroid Build Coastguard Worker if(publish(dump, fd, packet_id, topic, data, datalen)) {
656*6236dae4SAndroid Build Coastguard Worker logmsg("PUBLISH failed");
657*6236dae4SAndroid Build Coastguard Worker free(data);
658*6236dae4SAndroid Build Coastguard Worker goto end;
659*6236dae4SAndroid Build Coastguard Worker }
660*6236dae4SAndroid Build Coastguard Worker free(data);
661*6236dae4SAndroid Build Coastguard Worker if(config.publish_before_suback) {
662*6236dae4SAndroid Build Coastguard Worker if(suback(dump, fd, packet_id)) {
663*6236dae4SAndroid Build Coastguard Worker logmsg("failed sending SUBACK");
664*6236dae4SAndroid Build Coastguard Worker goto end;
665*6236dae4SAndroid Build Coastguard Worker }
666*6236dae4SAndroid Build Coastguard Worker }
667*6236dae4SAndroid Build Coastguard Worker }
668*6236dae4SAndroid Build Coastguard Worker else {
669*6236dae4SAndroid Build Coastguard Worker char *def = (char *)"this is random payload yes yes it is";
670*6236dae4SAndroid Build Coastguard Worker publish(dump, fd, packet_id, topic, def, strlen(def));
671*6236dae4SAndroid Build Coastguard Worker }
672*6236dae4SAndroid Build Coastguard Worker disconnect(dump, fd);
673*6236dae4SAndroid Build Coastguard Worker }
674*6236dae4SAndroid Build Coastguard Worker else if((byte & 0xf0) == (MQTT_MSG_PUBLISH & 0xf0)) {
675*6236dae4SAndroid Build Coastguard Worker size_t topiclen;
676*6236dae4SAndroid Build Coastguard Worker
677*6236dae4SAndroid Build Coastguard Worker logmsg("Incoming PUBLISH");
678*6236dae4SAndroid Build Coastguard Worker logprotocol(FROM_CLIENT, "PUBLISH", remaining_length,
679*6236dae4SAndroid Build Coastguard Worker dump, buffer, rc);
680*6236dae4SAndroid Build Coastguard Worker
681*6236dae4SAndroid Build Coastguard Worker topiclen = (size_t)(buffer[1 + bytes] << 8) | buffer[2 + bytes];
682*6236dae4SAndroid Build Coastguard Worker logmsg("Got %zu bytes topic", topiclen);
683*6236dae4SAndroid Build Coastguard Worker /* TODO: verify topiclen */
684*6236dae4SAndroid Build Coastguard Worker
685*6236dae4SAndroid Build Coastguard Worker #ifdef QOS
686*6236dae4SAndroid Build Coastguard Worker /* TODO: handle packetid if there is one. Send puback if QoS > 0 */
687*6236dae4SAndroid Build Coastguard Worker puback(dump, fd, 0);
688*6236dae4SAndroid Build Coastguard Worker #endif
689*6236dae4SAndroid Build Coastguard Worker /* expect a disconnect here */
690*6236dae4SAndroid Build Coastguard Worker /* get the request */
691*6236dae4SAndroid Build Coastguard Worker rc = sread(fd, (char *)&buffer[0], 2);
692*6236dae4SAndroid Build Coastguard Worker
693*6236dae4SAndroid Build Coastguard Worker logmsg("READ %zd bytes [DISCONNECT]", rc);
694*6236dae4SAndroid Build Coastguard Worker loghex(buffer, rc);
695*6236dae4SAndroid Build Coastguard Worker logprotocol(FROM_CLIENT, "DISCONNECT", 0, dump, buffer, rc);
696*6236dae4SAndroid Build Coastguard Worker goto end;
697*6236dae4SAndroid Build Coastguard Worker }
698*6236dae4SAndroid Build Coastguard Worker else {
699*6236dae4SAndroid Build Coastguard Worker /* not supported (yet) */
700*6236dae4SAndroid Build Coastguard Worker goto end;
701*6236dae4SAndroid Build Coastguard Worker }
702*6236dae4SAndroid Build Coastguard Worker } while(1);
703*6236dae4SAndroid Build Coastguard Worker
704*6236dae4SAndroid Build Coastguard Worker end:
705*6236dae4SAndroid Build Coastguard Worker if(buffer)
706*6236dae4SAndroid Build Coastguard Worker free(buffer);
707*6236dae4SAndroid Build Coastguard Worker if(dump)
708*6236dae4SAndroid Build Coastguard Worker fclose(dump);
709*6236dae4SAndroid Build Coastguard Worker if(stream)
710*6236dae4SAndroid Build Coastguard Worker fclose(stream);
711*6236dae4SAndroid Build Coastguard Worker return CURL_SOCKET_BAD;
712*6236dae4SAndroid Build Coastguard Worker }
713*6236dae4SAndroid Build Coastguard Worker
714*6236dae4SAndroid Build Coastguard Worker /*
715*6236dae4SAndroid Build Coastguard Worker sockfdp is a pointer to an established stream or CURL_SOCKET_BAD
716*6236dae4SAndroid Build Coastguard Worker
717*6236dae4SAndroid Build Coastguard Worker if sockfd is CURL_SOCKET_BAD, listendfd is a listening socket we must
718*6236dae4SAndroid Build Coastguard Worker accept()
719*6236dae4SAndroid Build Coastguard Worker */
incoming(curl_socket_t listenfd)720*6236dae4SAndroid Build Coastguard Worker static bool incoming(curl_socket_t listenfd)
721*6236dae4SAndroid Build Coastguard Worker {
722*6236dae4SAndroid Build Coastguard Worker fd_set fds_read;
723*6236dae4SAndroid Build Coastguard Worker fd_set fds_write;
724*6236dae4SAndroid Build Coastguard Worker fd_set fds_err;
725*6236dae4SAndroid Build Coastguard Worker int clients = 0; /* connected clients */
726*6236dae4SAndroid Build Coastguard Worker
727*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal) {
728*6236dae4SAndroid Build Coastguard Worker logmsg("signalled to die, exiting...");
729*6236dae4SAndroid Build Coastguard Worker return FALSE;
730*6236dae4SAndroid Build Coastguard Worker }
731*6236dae4SAndroid Build Coastguard Worker
732*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_GETPPID
733*6236dae4SAndroid Build Coastguard Worker /* As a last resort, quit if socks5 process becomes orphan. */
734*6236dae4SAndroid Build Coastguard Worker if(getppid() <= 1) {
735*6236dae4SAndroid Build Coastguard Worker logmsg("process becomes orphan, exiting");
736*6236dae4SAndroid Build Coastguard Worker return FALSE;
737*6236dae4SAndroid Build Coastguard Worker }
738*6236dae4SAndroid Build Coastguard Worker #endif
739*6236dae4SAndroid Build Coastguard Worker
740*6236dae4SAndroid Build Coastguard Worker do {
741*6236dae4SAndroid Build Coastguard Worker ssize_t rc;
742*6236dae4SAndroid Build Coastguard Worker int error = 0;
743*6236dae4SAndroid Build Coastguard Worker curl_socket_t sockfd = listenfd;
744*6236dae4SAndroid Build Coastguard Worker int maxfd = (int)sockfd;
745*6236dae4SAndroid Build Coastguard Worker
746*6236dae4SAndroid Build Coastguard Worker FD_ZERO(&fds_read);
747*6236dae4SAndroid Build Coastguard Worker FD_ZERO(&fds_write);
748*6236dae4SAndroid Build Coastguard Worker FD_ZERO(&fds_err);
749*6236dae4SAndroid Build Coastguard Worker
750*6236dae4SAndroid Build Coastguard Worker /* there's always a socket to wait for */
751*6236dae4SAndroid Build Coastguard Worker FD_SET(sockfd, &fds_read);
752*6236dae4SAndroid Build Coastguard Worker
753*6236dae4SAndroid Build Coastguard Worker do {
754*6236dae4SAndroid Build Coastguard Worker /* select() blocking behavior call on blocking descriptors please */
755*6236dae4SAndroid Build Coastguard Worker rc = select(maxfd + 1, &fds_read, &fds_write, &fds_err, NULL);
756*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal) {
757*6236dae4SAndroid Build Coastguard Worker logmsg("signalled to die, exiting...");
758*6236dae4SAndroid Build Coastguard Worker return FALSE;
759*6236dae4SAndroid Build Coastguard Worker }
760*6236dae4SAndroid Build Coastguard Worker } while((rc == -1) && ((error = SOCKERRNO) == EINTR));
761*6236dae4SAndroid Build Coastguard Worker
762*6236dae4SAndroid Build Coastguard Worker if(rc < 0) {
763*6236dae4SAndroid Build Coastguard Worker logmsg("select() failed with error: (%d) %s",
764*6236dae4SAndroid Build Coastguard Worker error, strerror(error));
765*6236dae4SAndroid Build Coastguard Worker return FALSE;
766*6236dae4SAndroid Build Coastguard Worker }
767*6236dae4SAndroid Build Coastguard Worker
768*6236dae4SAndroid Build Coastguard Worker if(FD_ISSET(sockfd, &fds_read)) {
769*6236dae4SAndroid Build Coastguard Worker curl_socket_t newfd = accept(sockfd, NULL, NULL);
770*6236dae4SAndroid Build Coastguard Worker if(CURL_SOCKET_BAD == newfd) {
771*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
772*6236dae4SAndroid Build Coastguard Worker logmsg("accept(%" FMT_SOCKET_T ", NULL, NULL) "
773*6236dae4SAndroid Build Coastguard Worker "failed with error: (%d) %s", sockfd, error, sstrerror(error));
774*6236dae4SAndroid Build Coastguard Worker }
775*6236dae4SAndroid Build Coastguard Worker else {
776*6236dae4SAndroid Build Coastguard Worker logmsg("====> Client connect, fd %" FMT_SOCKET_T ". "
777*6236dae4SAndroid Build Coastguard Worker "Read config from %s", newfd, configfile);
778*6236dae4SAndroid Build Coastguard Worker set_advisor_read_lock(loglockfile);
779*6236dae4SAndroid Build Coastguard Worker (void)mqttit(newfd); /* until done */
780*6236dae4SAndroid Build Coastguard Worker clear_advisor_read_lock(loglockfile);
781*6236dae4SAndroid Build Coastguard Worker
782*6236dae4SAndroid Build Coastguard Worker logmsg("====> Client disconnect");
783*6236dae4SAndroid Build Coastguard Worker sclose(newfd);
784*6236dae4SAndroid Build Coastguard Worker }
785*6236dae4SAndroid Build Coastguard Worker }
786*6236dae4SAndroid Build Coastguard Worker } while(clients);
787*6236dae4SAndroid Build Coastguard Worker
788*6236dae4SAndroid Build Coastguard Worker return TRUE;
789*6236dae4SAndroid Build Coastguard Worker }
790*6236dae4SAndroid Build Coastguard Worker
sockdaemon(curl_socket_t sock,unsigned short * listenport)791*6236dae4SAndroid Build Coastguard Worker static curl_socket_t sockdaemon(curl_socket_t sock,
792*6236dae4SAndroid Build Coastguard Worker unsigned short *listenport)
793*6236dae4SAndroid Build Coastguard Worker {
794*6236dae4SAndroid Build Coastguard Worker /* passive daemon style */
795*6236dae4SAndroid Build Coastguard Worker srvr_sockaddr_union_t listener;
796*6236dae4SAndroid Build Coastguard Worker int flag;
797*6236dae4SAndroid Build Coastguard Worker int rc;
798*6236dae4SAndroid Build Coastguard Worker int totdelay = 0;
799*6236dae4SAndroid Build Coastguard Worker int maxretr = 10;
800*6236dae4SAndroid Build Coastguard Worker int delay = 20;
801*6236dae4SAndroid Build Coastguard Worker int attempt = 0;
802*6236dae4SAndroid Build Coastguard Worker int error = 0;
803*6236dae4SAndroid Build Coastguard Worker
804*6236dae4SAndroid Build Coastguard Worker do {
805*6236dae4SAndroid Build Coastguard Worker attempt++;
806*6236dae4SAndroid Build Coastguard Worker flag = 1;
807*6236dae4SAndroid Build Coastguard Worker rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
808*6236dae4SAndroid Build Coastguard Worker (void *)&flag, sizeof(flag));
809*6236dae4SAndroid Build Coastguard Worker if(rc) {
810*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
811*6236dae4SAndroid Build Coastguard Worker logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
812*6236dae4SAndroid Build Coastguard Worker error, sstrerror(error));
813*6236dae4SAndroid Build Coastguard Worker if(maxretr) {
814*6236dae4SAndroid Build Coastguard Worker rc = wait_ms(delay);
815*6236dae4SAndroid Build Coastguard Worker if(rc) {
816*6236dae4SAndroid Build Coastguard Worker /* should not happen */
817*6236dae4SAndroid Build Coastguard Worker logmsg("wait_ms() failed with error: %d", rc);
818*6236dae4SAndroid Build Coastguard Worker sclose(sock);
819*6236dae4SAndroid Build Coastguard Worker return CURL_SOCKET_BAD;
820*6236dae4SAndroid Build Coastguard Worker }
821*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal) {
822*6236dae4SAndroid Build Coastguard Worker logmsg("signalled to die, exiting...");
823*6236dae4SAndroid Build Coastguard Worker sclose(sock);
824*6236dae4SAndroid Build Coastguard Worker return CURL_SOCKET_BAD;
825*6236dae4SAndroid Build Coastguard Worker }
826*6236dae4SAndroid Build Coastguard Worker totdelay += delay;
827*6236dae4SAndroid Build Coastguard Worker delay *= 2; /* double the sleep for next attempt */
828*6236dae4SAndroid Build Coastguard Worker }
829*6236dae4SAndroid Build Coastguard Worker }
830*6236dae4SAndroid Build Coastguard Worker } while(rc && maxretr--);
831*6236dae4SAndroid Build Coastguard Worker
832*6236dae4SAndroid Build Coastguard Worker if(rc) {
833*6236dae4SAndroid Build Coastguard Worker logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error: (%d) %s",
834*6236dae4SAndroid Build Coastguard Worker attempt, totdelay, error, strerror(error));
835*6236dae4SAndroid Build Coastguard Worker logmsg("Continuing anyway...");
836*6236dae4SAndroid Build Coastguard Worker }
837*6236dae4SAndroid Build Coastguard Worker
838*6236dae4SAndroid Build Coastguard Worker /* When the specified listener port is zero, it is actually a
839*6236dae4SAndroid Build Coastguard Worker request to let the system choose a non-zero available port. */
840*6236dae4SAndroid Build Coastguard Worker
841*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
842*6236dae4SAndroid Build Coastguard Worker if(!use_ipv6) {
843*6236dae4SAndroid Build Coastguard Worker #endif
844*6236dae4SAndroid Build Coastguard Worker memset(&listener.sa4, 0, sizeof(listener.sa4));
845*6236dae4SAndroid Build Coastguard Worker listener.sa4.sin_family = AF_INET;
846*6236dae4SAndroid Build Coastguard Worker listener.sa4.sin_addr.s_addr = INADDR_ANY;
847*6236dae4SAndroid Build Coastguard Worker listener.sa4.sin_port = htons(*listenport);
848*6236dae4SAndroid Build Coastguard Worker rc = bind(sock, &listener.sa, sizeof(listener.sa4));
849*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
850*6236dae4SAndroid Build Coastguard Worker }
851*6236dae4SAndroid Build Coastguard Worker else {
852*6236dae4SAndroid Build Coastguard Worker memset(&listener.sa6, 0, sizeof(listener.sa6));
853*6236dae4SAndroid Build Coastguard Worker listener.sa6.sin6_family = AF_INET6;
854*6236dae4SAndroid Build Coastguard Worker listener.sa6.sin6_addr = in6addr_any;
855*6236dae4SAndroid Build Coastguard Worker listener.sa6.sin6_port = htons(*listenport);
856*6236dae4SAndroid Build Coastguard Worker rc = bind(sock, &listener.sa, sizeof(listener.sa6));
857*6236dae4SAndroid Build Coastguard Worker }
858*6236dae4SAndroid Build Coastguard Worker #endif /* USE_IPV6 */
859*6236dae4SAndroid Build Coastguard Worker if(rc) {
860*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
861*6236dae4SAndroid Build Coastguard Worker logmsg("Error binding socket on port %hu: (%d) %s",
862*6236dae4SAndroid Build Coastguard Worker *listenport, error, sstrerror(error));
863*6236dae4SAndroid Build Coastguard Worker sclose(sock);
864*6236dae4SAndroid Build Coastguard Worker return CURL_SOCKET_BAD;
865*6236dae4SAndroid Build Coastguard Worker }
866*6236dae4SAndroid Build Coastguard Worker
867*6236dae4SAndroid Build Coastguard Worker if(!*listenport) {
868*6236dae4SAndroid Build Coastguard Worker /* The system was supposed to choose a port number, figure out which
869*6236dae4SAndroid Build Coastguard Worker port we actually got and update the listener port value with it. */
870*6236dae4SAndroid Build Coastguard Worker curl_socklen_t la_size;
871*6236dae4SAndroid Build Coastguard Worker srvr_sockaddr_union_t localaddr;
872*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
873*6236dae4SAndroid Build Coastguard Worker if(!use_ipv6)
874*6236dae4SAndroid Build Coastguard Worker #endif
875*6236dae4SAndroid Build Coastguard Worker la_size = sizeof(localaddr.sa4);
876*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
877*6236dae4SAndroid Build Coastguard Worker else
878*6236dae4SAndroid Build Coastguard Worker la_size = sizeof(localaddr.sa6);
879*6236dae4SAndroid Build Coastguard Worker #endif
880*6236dae4SAndroid Build Coastguard Worker memset(&localaddr.sa, 0, (size_t)la_size);
881*6236dae4SAndroid Build Coastguard Worker if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
882*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
883*6236dae4SAndroid Build Coastguard Worker logmsg("getsockname() failed with error: (%d) %s",
884*6236dae4SAndroid Build Coastguard Worker error, sstrerror(error));
885*6236dae4SAndroid Build Coastguard Worker sclose(sock);
886*6236dae4SAndroid Build Coastguard Worker return CURL_SOCKET_BAD;
887*6236dae4SAndroid Build Coastguard Worker }
888*6236dae4SAndroid Build Coastguard Worker switch(localaddr.sa.sa_family) {
889*6236dae4SAndroid Build Coastguard Worker case AF_INET:
890*6236dae4SAndroid Build Coastguard Worker *listenport = ntohs(localaddr.sa4.sin_port);
891*6236dae4SAndroid Build Coastguard Worker break;
892*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
893*6236dae4SAndroid Build Coastguard Worker case AF_INET6:
894*6236dae4SAndroid Build Coastguard Worker *listenport = ntohs(localaddr.sa6.sin6_port);
895*6236dae4SAndroid Build Coastguard Worker break;
896*6236dae4SAndroid Build Coastguard Worker #endif
897*6236dae4SAndroid Build Coastguard Worker default:
898*6236dae4SAndroid Build Coastguard Worker break;
899*6236dae4SAndroid Build Coastguard Worker }
900*6236dae4SAndroid Build Coastguard Worker if(!*listenport) {
901*6236dae4SAndroid Build Coastguard Worker /* Real failure, listener port shall not be zero beyond this point. */
902*6236dae4SAndroid Build Coastguard Worker logmsg("Apparently getsockname() succeeded, with listener port zero.");
903*6236dae4SAndroid Build Coastguard Worker logmsg("A valid reason for this failure is a binary built without");
904*6236dae4SAndroid Build Coastguard Worker logmsg("proper network library linkage. This might not be the only");
905*6236dae4SAndroid Build Coastguard Worker logmsg("reason, but double check it before anything else.");
906*6236dae4SAndroid Build Coastguard Worker sclose(sock);
907*6236dae4SAndroid Build Coastguard Worker return CURL_SOCKET_BAD;
908*6236dae4SAndroid Build Coastguard Worker }
909*6236dae4SAndroid Build Coastguard Worker }
910*6236dae4SAndroid Build Coastguard Worker
911*6236dae4SAndroid Build Coastguard Worker /* start accepting connections */
912*6236dae4SAndroid Build Coastguard Worker rc = listen(sock, 5);
913*6236dae4SAndroid Build Coastguard Worker if(0 != rc) {
914*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
915*6236dae4SAndroid Build Coastguard Worker logmsg("listen(%" FMT_SOCKET_T ", 5) failed with error: (%d) %s",
916*6236dae4SAndroid Build Coastguard Worker sock, error, sstrerror(error));
917*6236dae4SAndroid Build Coastguard Worker sclose(sock);
918*6236dae4SAndroid Build Coastguard Worker return CURL_SOCKET_BAD;
919*6236dae4SAndroid Build Coastguard Worker }
920*6236dae4SAndroid Build Coastguard Worker
921*6236dae4SAndroid Build Coastguard Worker return sock;
922*6236dae4SAndroid Build Coastguard Worker }
923*6236dae4SAndroid Build Coastguard Worker
924*6236dae4SAndroid Build Coastguard Worker
main(int argc,char * argv[])925*6236dae4SAndroid Build Coastguard Worker int main(int argc, char *argv[])
926*6236dae4SAndroid Build Coastguard Worker {
927*6236dae4SAndroid Build Coastguard Worker curl_socket_t sock = CURL_SOCKET_BAD;
928*6236dae4SAndroid Build Coastguard Worker curl_socket_t msgsock = CURL_SOCKET_BAD;
929*6236dae4SAndroid Build Coastguard Worker int wrotepidfile = 0;
930*6236dae4SAndroid Build Coastguard Worker int wroteportfile = 0;
931*6236dae4SAndroid Build Coastguard Worker const char *pidname = ".mqttd.pid";
932*6236dae4SAndroid Build Coastguard Worker const char *portname = ".mqttd.port";
933*6236dae4SAndroid Build Coastguard Worker bool juggle_again;
934*6236dae4SAndroid Build Coastguard Worker int error;
935*6236dae4SAndroid Build Coastguard Worker int arg = 1;
936*6236dae4SAndroid Build Coastguard Worker
937*6236dae4SAndroid Build Coastguard Worker while(argc > arg) {
938*6236dae4SAndroid Build Coastguard Worker if(!strcmp("--version", argv[arg])) {
939*6236dae4SAndroid Build Coastguard Worker printf("mqttd IPv4%s\n",
940*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
941*6236dae4SAndroid Build Coastguard Worker "/IPv6"
942*6236dae4SAndroid Build Coastguard Worker #else
943*6236dae4SAndroid Build Coastguard Worker ""
944*6236dae4SAndroid Build Coastguard Worker #endif
945*6236dae4SAndroid Build Coastguard Worker );
946*6236dae4SAndroid Build Coastguard Worker return 0;
947*6236dae4SAndroid Build Coastguard Worker }
948*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--pidfile", argv[arg])) {
949*6236dae4SAndroid Build Coastguard Worker arg++;
950*6236dae4SAndroid Build Coastguard Worker if(argc > arg)
951*6236dae4SAndroid Build Coastguard Worker pidname = argv[arg++];
952*6236dae4SAndroid Build Coastguard Worker }
953*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--portfile", argv[arg])) {
954*6236dae4SAndroid Build Coastguard Worker arg++;
955*6236dae4SAndroid Build Coastguard Worker if(argc > arg)
956*6236dae4SAndroid Build Coastguard Worker portname = argv[arg++];
957*6236dae4SAndroid Build Coastguard Worker }
958*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--config", argv[arg])) {
959*6236dae4SAndroid Build Coastguard Worker arg++;
960*6236dae4SAndroid Build Coastguard Worker if(argc > arg)
961*6236dae4SAndroid Build Coastguard Worker configfile = argv[arg++];
962*6236dae4SAndroid Build Coastguard Worker }
963*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--logfile", argv[arg])) {
964*6236dae4SAndroid Build Coastguard Worker arg++;
965*6236dae4SAndroid Build Coastguard Worker if(argc > arg)
966*6236dae4SAndroid Build Coastguard Worker serverlogfile = argv[arg++];
967*6236dae4SAndroid Build Coastguard Worker }
968*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--logdir", argv[arg])) {
969*6236dae4SAndroid Build Coastguard Worker arg++;
970*6236dae4SAndroid Build Coastguard Worker if(argc > arg)
971*6236dae4SAndroid Build Coastguard Worker logdir = argv[arg++];
972*6236dae4SAndroid Build Coastguard Worker }
973*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--ipv6", argv[arg])) {
974*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
975*6236dae4SAndroid Build Coastguard Worker ipv_inuse = "IPv6";
976*6236dae4SAndroid Build Coastguard Worker use_ipv6 = TRUE;
977*6236dae4SAndroid Build Coastguard Worker #endif
978*6236dae4SAndroid Build Coastguard Worker arg++;
979*6236dae4SAndroid Build Coastguard Worker }
980*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--ipv4", argv[arg])) {
981*6236dae4SAndroid Build Coastguard Worker /* for completeness, we support this option as well */
982*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
983*6236dae4SAndroid Build Coastguard Worker ipv_inuse = "IPv4";
984*6236dae4SAndroid Build Coastguard Worker use_ipv6 = FALSE;
985*6236dae4SAndroid Build Coastguard Worker #endif
986*6236dae4SAndroid Build Coastguard Worker arg++;
987*6236dae4SAndroid Build Coastguard Worker }
988*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--port", argv[arg])) {
989*6236dae4SAndroid Build Coastguard Worker arg++;
990*6236dae4SAndroid Build Coastguard Worker if(argc > arg) {
991*6236dae4SAndroid Build Coastguard Worker char *endptr;
992*6236dae4SAndroid Build Coastguard Worker unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
993*6236dae4SAndroid Build Coastguard Worker if((endptr != argv[arg] + strlen(argv[arg])) ||
994*6236dae4SAndroid Build Coastguard Worker ((ulnum != 0UL) && ((ulnum < 1025UL) || (ulnum > 65535UL)))) {
995*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, "mqttd: invalid --port argument (%s)\n",
996*6236dae4SAndroid Build Coastguard Worker argv[arg]);
997*6236dae4SAndroid Build Coastguard Worker return 0;
998*6236dae4SAndroid Build Coastguard Worker }
999*6236dae4SAndroid Build Coastguard Worker port = curlx_ultous(ulnum);
1000*6236dae4SAndroid Build Coastguard Worker arg++;
1001*6236dae4SAndroid Build Coastguard Worker }
1002*6236dae4SAndroid Build Coastguard Worker }
1003*6236dae4SAndroid Build Coastguard Worker else {
1004*6236dae4SAndroid Build Coastguard Worker puts("Usage: mqttd [option]\n"
1005*6236dae4SAndroid Build Coastguard Worker " --config [file]\n"
1006*6236dae4SAndroid Build Coastguard Worker " --version\n"
1007*6236dae4SAndroid Build Coastguard Worker " --logfile [file]\n"
1008*6236dae4SAndroid Build Coastguard Worker " --logdir [directory]\n"
1009*6236dae4SAndroid Build Coastguard Worker " --pidfile [file]\n"
1010*6236dae4SAndroid Build Coastguard Worker " --portfile [file]\n"
1011*6236dae4SAndroid Build Coastguard Worker " --ipv4\n"
1012*6236dae4SAndroid Build Coastguard Worker " --ipv6\n"
1013*6236dae4SAndroid Build Coastguard Worker " --port [port]\n");
1014*6236dae4SAndroid Build Coastguard Worker return 0;
1015*6236dae4SAndroid Build Coastguard Worker }
1016*6236dae4SAndroid Build Coastguard Worker }
1017*6236dae4SAndroid Build Coastguard Worker
1018*6236dae4SAndroid Build Coastguard Worker msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/mqtt-%s.lock",
1019*6236dae4SAndroid Build Coastguard Worker logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
1020*6236dae4SAndroid Build Coastguard Worker
1021*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32
1022*6236dae4SAndroid Build Coastguard Worker win32_init();
1023*6236dae4SAndroid Build Coastguard Worker atexit(win32_cleanup);
1024*6236dae4SAndroid Build Coastguard Worker
1025*6236dae4SAndroid Build Coastguard Worker setmode(fileno(stdin), O_BINARY);
1026*6236dae4SAndroid Build Coastguard Worker setmode(fileno(stdout), O_BINARY);
1027*6236dae4SAndroid Build Coastguard Worker setmode(fileno(stderr), O_BINARY);
1028*6236dae4SAndroid Build Coastguard Worker #endif
1029*6236dae4SAndroid Build Coastguard Worker
1030*6236dae4SAndroid Build Coastguard Worker install_signal_handlers(FALSE);
1031*6236dae4SAndroid Build Coastguard Worker
1032*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1033*6236dae4SAndroid Build Coastguard Worker if(!use_ipv6)
1034*6236dae4SAndroid Build Coastguard Worker #endif
1035*6236dae4SAndroid Build Coastguard Worker sock = socket(AF_INET, SOCK_STREAM, 0);
1036*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1037*6236dae4SAndroid Build Coastguard Worker else
1038*6236dae4SAndroid Build Coastguard Worker sock = socket(AF_INET6, SOCK_STREAM, 0);
1039*6236dae4SAndroid Build Coastguard Worker #endif
1040*6236dae4SAndroid Build Coastguard Worker
1041*6236dae4SAndroid Build Coastguard Worker if(CURL_SOCKET_BAD == sock) {
1042*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
1043*6236dae4SAndroid Build Coastguard Worker logmsg("Error creating socket: (%d) %s", error, sstrerror(error));
1044*6236dae4SAndroid Build Coastguard Worker goto mqttd_cleanup;
1045*6236dae4SAndroid Build Coastguard Worker }
1046*6236dae4SAndroid Build Coastguard Worker
1047*6236dae4SAndroid Build Coastguard Worker {
1048*6236dae4SAndroid Build Coastguard Worker /* passive daemon style */
1049*6236dae4SAndroid Build Coastguard Worker sock = sockdaemon(sock, &port);
1050*6236dae4SAndroid Build Coastguard Worker if(CURL_SOCKET_BAD == sock) {
1051*6236dae4SAndroid Build Coastguard Worker goto mqttd_cleanup;
1052*6236dae4SAndroid Build Coastguard Worker }
1053*6236dae4SAndroid Build Coastguard Worker msgsock = CURL_SOCKET_BAD; /* no stream socket yet */
1054*6236dae4SAndroid Build Coastguard Worker }
1055*6236dae4SAndroid Build Coastguard Worker
1056*6236dae4SAndroid Build Coastguard Worker logmsg("Running %s version", ipv_inuse);
1057*6236dae4SAndroid Build Coastguard Worker logmsg("Listening on port %hu", port);
1058*6236dae4SAndroid Build Coastguard Worker
1059*6236dae4SAndroid Build Coastguard Worker wrotepidfile = write_pidfile(pidname);
1060*6236dae4SAndroid Build Coastguard Worker if(!wrotepidfile) {
1061*6236dae4SAndroid Build Coastguard Worker goto mqttd_cleanup;
1062*6236dae4SAndroid Build Coastguard Worker }
1063*6236dae4SAndroid Build Coastguard Worker
1064*6236dae4SAndroid Build Coastguard Worker wroteportfile = write_portfile(portname, port);
1065*6236dae4SAndroid Build Coastguard Worker if(!wroteportfile) {
1066*6236dae4SAndroid Build Coastguard Worker goto mqttd_cleanup;
1067*6236dae4SAndroid Build Coastguard Worker }
1068*6236dae4SAndroid Build Coastguard Worker
1069*6236dae4SAndroid Build Coastguard Worker do {
1070*6236dae4SAndroid Build Coastguard Worker juggle_again = incoming(sock);
1071*6236dae4SAndroid Build Coastguard Worker } while(juggle_again);
1072*6236dae4SAndroid Build Coastguard Worker
1073*6236dae4SAndroid Build Coastguard Worker mqttd_cleanup:
1074*6236dae4SAndroid Build Coastguard Worker
1075*6236dae4SAndroid Build Coastguard Worker if((msgsock != sock) && (msgsock != CURL_SOCKET_BAD))
1076*6236dae4SAndroid Build Coastguard Worker sclose(msgsock);
1077*6236dae4SAndroid Build Coastguard Worker
1078*6236dae4SAndroid Build Coastguard Worker if(sock != CURL_SOCKET_BAD)
1079*6236dae4SAndroid Build Coastguard Worker sclose(sock);
1080*6236dae4SAndroid Build Coastguard Worker
1081*6236dae4SAndroid Build Coastguard Worker if(wrotepidfile)
1082*6236dae4SAndroid Build Coastguard Worker unlink(pidname);
1083*6236dae4SAndroid Build Coastguard Worker if(wroteportfile)
1084*6236dae4SAndroid Build Coastguard Worker unlink(portname);
1085*6236dae4SAndroid Build Coastguard Worker
1086*6236dae4SAndroid Build Coastguard Worker restore_signal_handlers(FALSE);
1087*6236dae4SAndroid Build Coastguard Worker
1088*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal) {
1089*6236dae4SAndroid Build Coastguard Worker logmsg("============> mqttd exits with signal (%d)", exit_signal);
1090*6236dae4SAndroid Build Coastguard Worker /*
1091*6236dae4SAndroid Build Coastguard Worker * To properly set the return status of the process we
1092*6236dae4SAndroid Build Coastguard Worker * must raise the same signal SIGINT or SIGTERM that we
1093*6236dae4SAndroid Build Coastguard Worker * caught and let the old handler take care of it.
1094*6236dae4SAndroid Build Coastguard Worker */
1095*6236dae4SAndroid Build Coastguard Worker raise(exit_signal);
1096*6236dae4SAndroid Build Coastguard Worker }
1097*6236dae4SAndroid Build Coastguard Worker
1098*6236dae4SAndroid Build Coastguard Worker logmsg("============> mqttd quits");
1099*6236dae4SAndroid Build Coastguard Worker return 0;
1100*6236dae4SAndroid Build Coastguard Worker }
1101