Commit f6f1f763 authored by Sjoerd Crooijmans's avatar Sjoerd Crooijmans
Browse files

Merge branch 'window-support' into 'master'

Window support

See merge request clean-and-itasks/contrib/mqttclient!6
parents 767ea4c6 9f2a386c
Pipeline #46355 passed with stages
in 2 minutes and 38 seconds
# binary
MQTTClient
*.exe
# Compiler generated files
Clean System Files
......@@ -7,3 +8,7 @@ Clean System Files
*.bc
*.pbc
*.prj
*.prp
# System specific files
src/_MQTT.*
variables:
GIT_SUBMODULE_STRATEGY: recursive
stages:
- compile
- package
default:
image: "camilstaps/clean:nightly"
before_script:
- install_clean_nightly.sh bundle-complete
- apt-get update
- apt-get install -yqq build-essential autoconf libtool
- ( cd cdeps/wolfMQTT; ./autogen.sh; ./configure --enable-mqtt5 --disable-tls; make install; )
- compile
- package
compile:
stage: compile
image: "camilstaps/clean:nightly"
before_script:
- install_clean_nightly.sh bundle-complete
- apt-get update -qq
- apt-get install -yqq build-essential autoconf libtool
- ( cd cdeps/wolfMQTT; ./autogen.sh; ./configure --enable-mqtt5 --disable-tls; make; )
script:
- make
package:
only:
- master
package-linux:
stage: package
image: debian
before_script:
- apt-get update -qq
- apt-get install -yqq build-essential autoconf libtool
script:
- ( cd cdeps/wolfMQTT; ./autogen.sh; ./configure --enable-mqtt5 --disable-tls; make; )
- make buildLib
- tar czf MQTTClient-linux-x64.tar.gz src --transform s/src/MQTTClient/
artifacts:
paths:
- ./*.tar.gz
package-windows:
stage: package
image: debian
before_script:
- apt-get update -qq
- apt-get install -yqq build-essential autoconf libtool mingw-w64
script:
- cp cdeps/vs_settings.h cdeps/wolfMQTT/wolfmqtt
- ( cd cdeps/wolfMQTT; ./autogen.sh; ./configure --enable-mqtt5 --disable-tls --host=x86_64-pc-mingw32 --disable-examples --enable-static CFLAGS=-Wno-error=attributes LIBS=-lws2_32 CC=x86_64-w64-mingw32-gcc; make; )
- OS=Windows_NT CC=x86_64-w64-mingw32-gcc make buildLib
- tar czf MQTTClient-windows-x64.tar.gz src --transform s/src/MQTTClient/
artifacts:
paths:
- ./*.tar.gz
CFLAGS?=-Wall -Wextra -Wno-unused-parameter
ifeq ($(OS), Windows_NT)
SUFFIX:=obj
else
SUFFIX:=o
endif
.PHONY: clean
all: buildLib buildDemo
buildLib:
$(MAKE) -C cdeps
mkdir -p src/Clean\ System\ Files
cp cdeps/libWrapper.o src/Clean\ System\ Files/libWrapper.$(SUFFIX)
ifeq ($(OS), Windows_NT)
cp cdeps/wolfMQTT/src/libwolfmqtt_la-mqtt_client.o src/Clean\ System\ Files/libwolfmqtt_la-mqtt_client.$(SUFFIX)
cp cdeps/wolfMQTT/src/libwolfmqtt_la-mqtt_packet.o src/Clean\ System\ Files/libwolfmqtt_la-mqtt_packet.$(SUFFIX)
cp cdeps/wolfMQTT/src/libwolfmqtt_la-mqtt_socket.o src/Clean\ System\ Files/libwolfmqtt_la-mqtt_socket.$(SUFFIX)
cp cdeps/_chkstk_ms.obj src/Clean\ System\ Files/
cp src-win/* src/
else
cp cdeps/wolfMQTT/src/.libs/libwolfmqtt_la-mqtt_client.o src/Clean\ System\ Files/libwolfmqtt_la-mqtt_client.$(SUFFIX)
cp cdeps/wolfMQTT/src/.libs/libwolfmqtt_la-mqtt_packet.o src/Clean\ System\ Files/libwolfmqtt_la-mqtt_packet.$(SUFFIX)
cp cdeps/wolfMQTT/src/.libs/libwolfmqtt_la-mqtt_socket.o src/Clean\ System\ Files/libwolfmqtt_la-mqtt_socket.$(SUFFIX)
cp src-posix/* src/
endif
buildDemo: buildLib
$(MAKE) -C demo
clean:
$(RM) -r $(addsuffix /Clean\ System\ Files, src src/MQTT)
$(RM) -r $(addprefix src/_MQTT., icl dcl)
$(MAKE) -C cdeps clean
$(MAKE) -C demo clean
#define Clean(a)
typedef struct clean_string *CleanString;
/* a string in Clean is:
struct clean_string {
size_t clean_string_length;
char clean_string_characters[clean_string_length];
};
The string does not end with a '\0' !
*/
#ifndef _WIN64
/* CleanStringLength(clean_string) returns the length of the clean_string in characters */
#define CleanStringLength(clean_string) (*(unsigned long *)(clean_string))
/* CleanStringCharacters(clean_string) returns a pointer to the characters of the clean_string */
#define CleanStringCharacters(clean_string) ((char*)(1+(unsigned long *)(clean_string)))
/* CleanStringSizeInts(string_length) return size of *CleanString in integers */
#define CleanStringSizeInts(string_length) (1+(((unsigned long)(string_length)+(sizeof(unsigned long)-1))>>(1+(sizeof(unsigned long)>>2))))
/* CleanStringVariable(clean_string,string_length) defines variable clean_string with length string_length,
before using the clean_string variable, cast to CleanString, except for the macros above */
#define CleanStringVariable(clean_string,string_length) unsigned long clean_string[CleanStringSizeInts(string_length)]
/* CleanStringSizeBytes(string_length) return size of *CleanString in bytes */
#define CleanStringSizeBytes(string_length) ((sizeof(unsigned long)<<1)+(((unsigned long)(string_length)+(sizeof(unsigned long)-1)) & -(sizeof(unsigned long))))
typedef long *CleanIntArray;
/* CleanIntArraySize(clean_array) returns the size (number of elements) of the clean_int_array */
#define CleanIntArraySize(clean_int_array) (((unsigned long *)(clean_int_array))[-2])
/* CleanRealArraySize(clean_real_array) returns the size (number of elements) of the clean_real_array */
#define CleanRealArraySize(clean_real_array) (((unsigned long *)(clean_real_array))[-2])
/* CleanCharArraySize(clean_char_array) returns the size (number of elements) of the clean_char_array */
#define CleanCharArraySize(clean_char_array) (((unsigned long *)(clean_char_array))[-1])
#else
/* CleanStringLength(clean_string) returns length of the clean_string in characters */
#define CleanStringLength(clean_string) (*(unsigned __int64 *)(clean_string))
/* CleanStringCharacters(clean_string) returns a pointer to the characters of the clean_string */
#define CleanStringCharacters(clean_string) ((char*)(1+(unsigned __int64 *)(clean_string)))
/* CleanStringSizeInts(string_length) return size of *CleanString in integers */
#define CleanStringSizeInts(string_length) (1+(((unsigned __int64)(string_length)+7)>>3))
/* CleanStringVariable(clean_string,string_length) defines variable clean_string with length string_length,
before using the clean_string variable, cast to CleanString, except for the macros above */
#define CleanStringVariable(clean_string,string_length) unsigned __int64 clean_string[CleanStringSizeInts(string_length)]
/* CleanStringSizeBytes(string_length) return size of *CleanString in bytes */
#define CleanStringSizeBytes(string_length) (8+(((unsigned __int64)(string_length)+7) & -8))
typedef __int64 *CleanIntArray;
/* CleanIntArraySize(clean_array) returns the size (number of elements) of the clean_int_array */
#define CleanIntArraySize(clean_int_array) (((unsigned __int64 *)(clean_int_array))[-2])
/* CleanRealArraySize(clean_real_array) returns the size (number of elements) of the clean_real_array */
#define CleanRealArraySize(clean_real_array) (((unsigned __int64 *)(clean_real_array))[-2])
/* CleanCharArraySize(clean_char_array) returns the size (number of elements) of the clean_char_array */
#define CleanCharArraySize(clean_char_array) (((unsigned __int64 *)(clean_char_array))[-1])
#endif
typedef double *CleanRealArray;
typedef unsigned char *CleanCharArray;
CFLAGS+=-I./wolfMQTT -Wall -Wextra -Werror -Wno-unused-parameter -std=c99
all: libWrapper.o
clean:
$(RM) libWrapper.o
#include "Clean.h"
#include <stdbool.h>
#include <sys/socket.h>
#include <stdint.h>
#include <errno.h>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <sys/select.h>
#endif
#include "wolfmqtt/mqtt_client.h"
#include "Clean.h"
#define BUFFER_SIZE 2048
......@@ -20,7 +28,7 @@ typedef struct Msg {
typedef struct MqttCtx {
Msg* queue_head;
Msg* queue_tail;
u_int16_t packetId;
uint16_t packetId;
int fd;
} MqttCtx;
......@@ -117,15 +125,21 @@ static int read_cb(void *context, byte* buf, int buf_len, int timeout_ms)
return b;
}
rc = (int)recv(ctx->fd, &buf[b], buf_len - b, 0);
rc = (int)recv(ctx->fd, (char *)&buf[b], buf_len - b, 0);
#ifdef _WIN32
if (rc == SOCKET_ERROR) {
if (WSAGetLastError() == WSAEWOULDBLOCK) {
continue;
}
#else
if (rc < 0) { // Error occured
/* continue if it is non-blocking error */
if (errno == EAGAIN || errno == EWOULDBLOCK){
continue;
}
#endif
return MQTT_CODE_ERROR_NETWORK;
}
......@@ -141,7 +155,7 @@ static int write_cb(void *context, const byte* buf, int buf_len, int timeout_ms)
int totalSend = 0;
while (totalSend < buf_len) {
rc = (int)send(ctx->fd, buf, buf_len, 0);
rc = (int)send(ctx->fd, (char *)buf, buf_len, 0);
totalSend += rc;
......
/* Template build settings for Visual Studio projects */
/* This is meant to be customized */
#ifndef _WOLFMQTT_VS_SETTINGS_
#define _WOLFMQTT_VS_SETTINGS_
/* TLS Support */
#undef ENABLE_MQTT_TLS
//#define ENABLE_MQTT_TLS
/* MQTT-SN Support */
#undef WOLFMQTT_SN
//#define WOLFMQTT_SN
/* MQTT v5.0 support */
#undef WOLFMQTT_V5
#define WOLFMQTT_V5
/* Enable property callback support */
#ifdef WOLFMQTT_V5
#undef WOLFMQTT_PROPERTY_CB
#define WOLFMQTT_PROPERTY_CB
#endif
/* Non-blocking support */
#undef WOLFMQTT_NONBLOCK
//#define WOLFMQTT_NONBLOCK
/* Disable socket timeout code */
#undef WOLFMQTT_NO_TIMEOUT
//#define WOLFMQTT_NO_TIMEOUT
/* Disconnect callback support */
#undef WOLFMQTT_DISCONNECT_CB
#define WOLFMQTT_DISCONNECT_CB
/* Multi-threading */
#undef WOLFMQTT_MULTITHREAD
//#define WOLFMQTT_MULTITHREAD
/* Debugging */
#undef DEBUG_WOLFMQTT
//#define DEBUG_WOLFMQTT
#undef WOLFMQTT_DEBUG_CLIENT
//#define WOLFMQTT_DEBUG_CLIENT
#undef WOLFMQTT_DEBUG_SOCKET
//#define WOLFMQTT_DEBUG_SOCKET
#undef WOLFMQTT_DEBUG_THREAD
//#define WOLFMQTT_DEBUG_THREAD
/* Disable error strings */
#undef WOLFMQTT_NO_ERROR_STRINGS
//#define WOLFMQTT_NO_ERROR_STRINGS
#endif /* _WOLFMQTT_VS_SETTINGS_ */
......@@ -16,4 +16,4 @@ all: MQTTClient
clean:
rm -rf Clean\ System\ Files
rm -rf MQTTClient-www
rm -f MQTTClient *.bc *.pbc *.prj
\ No newline at end of file
rm -f MQTTClient *.bc *.pbc *.prj
CLEANHEADER = ${CLEAN_HOME}/lib/Directory/Clean\ System\ Files
CFLAGS?=-Wall -Wextra -Wno-unused-parameter
.PHONY: clean
all: buildLib buildDemo
buildLib:
mkdir -p src/Clean\ System\ Files
gcc -c cdeps/libWrapper.c -I $(CLEANHEADER) -o src/Clean\ System\ Files/libWrapper.o
buildDemo:
make -C demo
clean:
rm -rf $(addsuffix /Clean\ System\ Files, src src/MQTT)
make -C demo clean
definition module _MQTT
implementation module _MQTT
definition module _MQTT
implementation module _MQTT
import code from "_chkstk_ms."
implementation module MQTT.Client
import code from library "-lwolfmqtt"
import code from "libWrapper."
import code from "libwolfmqtt_la-mqtt_client."
import code from "libwolfmqtt_la-mqtt_packet."
import code from "libwolfmqtt_la-mqtt_socket."
import _MQTT
import qualified Data.Map as DM
import Data.Functor
import Data.Func
......@@ -35,29 +40,29 @@ import MQTT
import StdDebug
mqttConnect :: MQTTConnectionSettings ((SimpleSDSLens MQTTClient) -> Task a) -> Task a | iTask a
mqttConnect conSettings ftask =
mqttConnect conSettings ftask =
defaultClient >>- \client.
withShared client \sds.
(parallel
(parallel
[ (Embedded, \_. (ftask sds) @ ?Just)
, (Embedded, (\stl. (appendTask Embedded (\_. connectionTask conSettings sds @! ?None) stl) @! ?None))
, (Embedded, \_. (pingBroker sds conSettings.keepAlive) @! ?None)
, (Embedded, \_. (pingBroker sds conSettings.keepAlive) @! ?None)
, (Embedded, \stl. (onTaskCompleteHandler sds stl) @! ?None)
] [] @? \tv. case tv of
NoValue = NoValue
Value pv _ = case findTaskVal pv of
?Just (v, s) = Value v s
_ = NoValue)
where findTaskVal [(_, Value (?Just val) s):_] = ?Just (val, s)
findTaskVal [_:tv] = findTaskVal tv
findTaskVal [] = ?None
onTaskCompleteHandler :: (SimpleSDSLens MQTTClient) (SharedTaskList a) -> Task MQTTClient | iTask a
onTaskCompleteHandler sds stl
= watch (sdsFocus (Left 0) (taskListItemValue stl)) >>*
onTaskCompleteHandler sds stl
= watch (sdsFocus (Left 0) (taskListItemValue stl)) >>*
[OnValue $ ifValue isStable (\_. upd (\c. { c & disconnect=True }) sds) ]
where
where
isStable (Value _ s) = s
isStable NoValue = False
......@@ -99,7 +104,7 @@ connectionTask conSettings sds = Task evalinit
?Just (IOException e)
= (ExceptionResult (exception e),iworld)
initConnection :: !*IWorld -> (!MaybeErrorString ((!Int, !IPAddress), !*TCP_DuplexChannel), !*IWorld)
initConnection w =
initConnection w =
case resolveIP conSettings w of
(Ok ip, w) = case createTCPConnection conSettings ip w of
(Ok (ref, chl), w) = case createMQTTConnection conSettings ref w of
......@@ -127,7 +132,7 @@ connectionsHandlers =
}
onData :: !String () MQTTClient *IWorld -> *(MaybeErrorString (), ?MQTTClient, [String], Bool, *IWorld)
onData _ _ client iworld
onData _ _ client iworld
# (ret, iworld) = processCall client.context iworld
| ret == 0 = let (c,w) = receive client iworld in (Ok (), ?Just c, [], False, w)
| otherwise = (Error $ "Mqtt process failed: " +++ errorCodeToString ret, ?None, [], False, iworld)
......@@ -143,7 +148,7 @@ onShareChange _ c=:{unsubscribe=[topic:tt]} w=:{IWorld|clock}
# c = { c & unsubscribe = tt, lastMessage = timespecToStamp clock}
| ret == 0 = let (cl,iw) = receive c w in (Ok (), ?Just cl, [], False, iw)
| otherwise = (Error $ "Unsubscription failed: " +++ errorCodeToString ret, ?None, [], False, w)
onShareChange _ c=:{send=[(MQTTMsg t p opts):ss]} w=:{IWorld|clock}
onShareChange _ c=:{send=[(MQTTMsg t p opts):ss]} w=:{IWorld|clock}
# (ret, w) = (publishCall c.context (packString t) p (size p) opts.qos opts.retain w)
# c = { c & send = ss, lastMessage = timespecToStamp clock }
| ret == 0 = let (cl,iw) = receive c w in (Ok (), ?Just cl, [], False, iw)
......@@ -159,11 +164,11 @@ pingBroker sds keepalive = foreverIf ((==) (?Just 0)) $
get sds >>-
\client. timestampToLocalDateTime (nextFire client.lastMessage) >>-
\nf. waitForDateTime False nf >>-
\dt. localDateTimeToTimestamp dt >>-
\now. get sds >>-
\dt. localDateTimeToTimestamp dt >>-
\now. get sds >>-
\client. handlePing client now
where nextFire (Timestamp lm) = Timestamp (lm + (keepalive - 2))
threshold (Timestamp now) (Timestamp lm) = (lm + (keepalive - 2)) - now <= 10
threshold (Timestamp now) (Timestamp lm) = (lm + (keepalive - 2)) - now <= 10
handlePing client now | client.disconnect = return ?None
| (threshold now client.lastMessage) = sendPing client now
| otherwise = return (?Just 0)
......@@ -171,19 +176,19 @@ pingBroker sds keepalive = foreverIf ((==) (?Just 0)) $
case res of
0 = return (?Just 0)
ret = throw $ "Failed to send ping: " +++ errorCodeToString ret
// IO Task Operations that handle the low-level read, write and close operations.
ioOps :: Int -> IOTaskOperations *TCP_DuplexChannel String ()
ioOps ctx = {readData = readData, writeData = writeData, closeIO = closeIO}
where
readData i selects (chl, w)
readData i selects (chl, w)
= case getSelect i selects of
?Just SR_Available = (IODData "", chl, w) // The actual read is in the onData handler
?None = (IODNoData, chl, w)
_ = (IODClosed (), chl, w)
writeData _ (chl, w) = (chl, w)
closeIO ({rChannel, sChannel}, iworld=:{world})
closeIO ({rChannel, sChannel}, iworld=:{world})
# (ret, iworld=:{world}) = disconnectCall ctx iworld
# world = closeRChannel rChannel world
# world = closeChannel sChannel world
......@@ -220,8 +225,8 @@ createTCPConnection conSettings ip iworld
# (ref, i) = unpack_tcprchan rChannel
= (Ok (ref, {con & rChannel=pack_tcprchan (ref, i)}), {iworld & world = w})
(_, _, w) = (Error "The TCP connection could not be created.", {iworld & world = w} )
// Create the MQTT connection
createMQTTConnection :: MQTTConnectionSettings !EndpointRef !*IWorld -> (!MaybeErrorString Int, !*IWorld)
createMQTTConnection conSettings ref w
......@@ -230,7 +235,7 @@ createMQTTConnection conSettings ref w
= case ret of
0 = (Ok context, w)
ret = (Error $ "Could not connect to the MQTT broker: " +++ errorCodeToString ret , w)
where
where
clientId = conSettings.MQTTConnectionSettings.clientId
keepAlive = conSettings.MQTTConnectionSettings.keepAlive
cleanSession = conSettings.MQTTConnectionSettings.cleanSession
......@@ -283,4 +288,4 @@ processCall c w = code {
receiveCall :: !Int !*IWorld -> *(!Int, !String, !String, !Int, !Bool, !*IWorld)
receiveCall c w = code {
ccall mqtt_receive "I:VISSII:A"
}
\ No newline at end of file
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment