├── .swift-version
├── .gitattributes
├── .gitmodules
├── Moscapsule.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcshareddata
│ └── xcschemes
│ │ └── Moscapsule.xcscheme
└── project.pbxproj
├── mosquitto
└── lib
│ ├── dummypthread.h
│ ├── time_mosq.h
│ ├── socks_mosq.h
│ ├── logging_mosq.h
│ ├── will_mosq.h
│ ├── tls_mosq.h
│ ├── memory_mosq.h
│ ├── util_mosq.h
│ ├── messages_mosq.h
│ ├── read_handle.h
│ ├── logging_mosq.c
│ ├── mqtt3_protocol.h
│ ├── read_handle_client.c
│ ├── send_mosq.h
│ ├── time_mosq.c
│ ├── memory_mosq.c
│ ├── thread_mosq.c
│ ├── will_mosq.c
│ ├── srv_mosq.c
│ ├── net_mosq.h
│ ├── tls_mosq.c
│ ├── read_handle.c
│ ├── read_handle_shared.c
│ ├── mosquitto_internal.h
│ ├── send_client_mosq.c
│ ├── util_mosq.c
│ ├── send_mosq.c
│ ├── messages_mosq.c
│ └── socks_mosq.c
├── download_mosquitto.sh
├── Moscapsule
├── Moscapsule.h
├── MosquittoCallbackBridge.h
├── Info.plist
├── config.h
├── MosquittoCallbackBridge.m
└── Moscapsule.swift
├── MoscapsuleTests
├── Info.plist
├── cert.bundle
│ └── mosquitto.org.crt
└── MoscapsuleTests.swift
├── LICENSE
├── Moscapsule.podspec
├── .gitignore
└── README.md
/.swift-version:
--------------------------------------------------------------------------------
1 | 5.0
2 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj binary merge=union
2 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "submodules/OpenSSL"]
2 | path = submodules/OpenSSL
3 | url = git@github.com:krzyzanowskim/OpenSSL.git
4 |
--------------------------------------------------------------------------------
/Moscapsule.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/mosquitto/lib/dummypthread.h:
--------------------------------------------------------------------------------
1 | #ifndef _DUMMYPTHREAD_H_
2 | #define _DUMMYPTHREAD_H_
3 |
4 | #define pthread_create(A, B, C, D)
5 | #define pthread_join(A, B)
6 | #define pthread_cancel(A)
7 |
8 | #define pthread_mutex_init(A, B)
9 | #define pthread_mutex_destroy(A)
10 | #define pthread_mutex_lock(A)
11 | #define pthread_mutex_unlock(A)
12 |
13 | #endif
14 |
--------------------------------------------------------------------------------
/download_mosquitto.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | MOSQ_VERSION="1.4.8"
4 | MOSQ_URL="http://mosquitto.org/files/source/mosquitto-${MOSQ_VERSION}.tar.gz"
5 |
6 | TMP_FILE="/tmp/mosquitto-${MOSQ_VERSION}.tar.gz"
7 |
8 | # download & copy
9 | curl -o $TMP_FILE $MOSQ_URL
10 | tar zxf $TMP_FILE -C ${TMP_FILE%/*}
11 | rsync -av --delete ${TMP_FILE%.tar.gz}/ ./mosquitto
12 |
13 | # clean up
14 | rm -rf ${TMP_FILE%-*}*
15 |
--------------------------------------------------------------------------------
/Moscapsule/Moscapsule.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | //! Project version number for Moscapsule.
4 | FOUNDATION_EXPORT double MoscapsuleVersionNumber;
5 |
6 | //! Project version string for Moscapsule.
7 | FOUNDATION_EXPORT const unsigned char MoscapsuleVersionString[];
8 |
9 | // In this header, you should import all the public headers of your framework using statements like #import
10 | #import "mosquitto.h"
11 | #import "MosquittoCallbackBridge.h"
12 |
--------------------------------------------------------------------------------
/mosquitto/lib/time_mosq.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013,2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #ifndef _TIME_MOSQ_H_
18 | #define _TIME_MOSQ_H_
19 |
20 | time_t mosquitto_time(void);
21 |
22 | #endif
23 |
--------------------------------------------------------------------------------
/mosquitto/lib/socks_mosq.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #ifndef SOCKS_MOSQ_H
18 | #define SOCKS_MOSQ_H
19 |
20 | int mosquitto__socks5_send(struct mosquitto *mosq);
21 | int mosquitto__socks5_read(struct mosquitto *mosq);
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/mosquitto/lib/logging_mosq.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 | #ifndef _LOGGING_MOSQ_H_
17 | #define _LOGGING_MOSQ_H_
18 |
19 | #include
20 |
21 | int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...);
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/MoscapsuleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Moscapsule/MosquittoCallbackBridge.h:
--------------------------------------------------------------------------------
1 | #ifndef Moscapsule_MosquittoCallbackBridge_h
2 | #define Moscapsule_MosquittoCallbackBridge_h
3 |
4 | struct mosquitto;
5 | struct mosquitto_message;
6 |
7 | @class __MosquittoContext;
8 |
9 | void mosquitto_context_setup(const char *client_id, bool clean_session, __MosquittoContext *mosquittoContext, int protocolVersion);
10 | void mosquitto_context_cleanup(__MosquittoContext *mosquitto_context);
11 |
12 | void mosquitto_tls_set_bridge(NSString *cafile, NSString *capath, NSString *certfile, NSString *keyfile, __MosquittoContext *mosquitto_context);
13 | void mosquitto_tls_opts_set_bridge(int cert_reqs, NSString *tls_version, NSString *ciphers, __MosquittoContext *mosquitto_context);
14 | void mosquitto_tls_psk_set_bridge(NSString *psk, NSString *identity, NSString *ciphers, __MosquittoContext *mosquitto_context);
15 | #endif
16 |
--------------------------------------------------------------------------------
/Moscapsule/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/mosquitto/lib/will_mosq.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2010-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #ifndef _WILL_MOSQ_H_
18 | #define _WILL_MOSQ_H_
19 |
20 | #include
21 | #include
22 |
23 | int _mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain);
24 | int _mosquitto_will_clear(struct mosquitto *mosq);
25 |
26 | #endif
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Tonary
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MoscapsuleTests/cert.bundle/mosquitto.org.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIC8DCCAlmgAwIBAgIJAOD63PlXjJi8MA0GCSqGSIb3DQEBBQUAMIGQMQswCQYD
3 | VQQGEwJHQjEXMBUGA1UECAwOVW5pdGVkIEtpbmdkb20xDjAMBgNVBAcMBURlcmJ5
4 | MRIwEAYDVQQKDAlNb3NxdWl0dG8xCzAJBgNVBAsMAkNBMRYwFAYDVQQDDA1tb3Nx
5 | dWl0dG8ub3JnMR8wHQYJKoZIhvcNAQkBFhByb2dlckBhdGNob28ub3JnMB4XDTEy
6 | MDYyOTIyMTE1OVoXDTIyMDYyNzIyMTE1OVowgZAxCzAJBgNVBAYTAkdCMRcwFQYD
7 | VQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwGA1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1v
8 | c3F1aXR0bzELMAkGA1UECwwCQ0ExFjAUBgNVBAMMDW1vc3F1aXR0by5vcmcxHzAd
9 | BgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hvby5vcmcwgZ8wDQYJKoZIhvcNAQEBBQAD
10 | gY0AMIGJAoGBAMYkLmX7SqOT/jJCZoQ1NWdCrr/pq47m3xxyXcI+FLEmwbE3R9vM
11 | rE6sRbP2S89pfrCt7iuITXPKycpUcIU0mtcT1OqxGBV2lb6RaOT2gC5pxyGaFJ+h
12 | A+GIbdYKO3JprPxSBoRponZJvDGEZuM3N7p3S/lRoi7G5wG5mvUmaE5RAgMBAAGj
13 | UDBOMB0GA1UdDgQWBBTad2QneVztIPQzRRGj6ZHKqJTv5jAfBgNVHSMEGDAWgBTa
14 | d2QneVztIPQzRRGj6ZHKqJTv5jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUA
15 | A4GBAAqw1rK4NlRUCUBLhEFUQasjP7xfFqlVbE2cRy0Rs4o3KS0JwzQVBwG85xge
16 | REyPOFdGdhBY2P1FNRy0MDr6xr+D2ZOwxs63dG1nnAnWZg7qwoLgpZ4fESPD3PkA
17 | 1ZgKJc2zbSQ9fCPxt2W3mdVav66c6fsb7els2W2Iz7gERJSX
18 | -----END CERTIFICATE-----
19 |
--------------------------------------------------------------------------------
/mosquitto/lib/tls_mosq.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013,2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #ifndef _TLS_MOSQ_H_
18 | #define _TLS_MOSQ_H_
19 |
20 | #ifdef WITH_TLS
21 | # define SSL_DATA_PENDING(A) ((A)->ssl && SSL_pending((A)->ssl))
22 | #else
23 | # define SSL_DATA_PENDING(A) 0
24 | #endif
25 |
26 | #ifdef WITH_TLS
27 |
28 | #include
29 | #ifdef WITH_TLS_PSK
30 | # if OPENSSL_VERSION_NUMBER >= 0x10000000
31 | # define REAL_WITH_TLS_PSK
32 | # else
33 | # warning "TLS-PSK not supported, openssl too old."
34 | # endif
35 | #endif
36 |
37 | int _mosquitto_server_certificate_verify(int preverify_ok, X509_STORE_CTX *ctx);
38 | int _mosquitto_verify_certificate_hostname(X509 *cert, const char *hostname);
39 |
40 | #endif /* WITH_TLS */
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/mosquitto/lib/memory_mosq.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2010-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #ifndef _MEMORY_MOSQ_H_
18 | #define _MEMORY_MOSQ_H_
19 |
20 | #include
21 | #include
22 |
23 | #if defined(WITH_MEMORY_TRACKING) && defined(WITH_BROKER) && !defined(WIN32) && !defined(__SYMBIAN32__) && !defined(__ANDROID__) && !defined(__UCLIBC__) && !defined(__OpenBSD__)
24 | #define REAL_WITH_MEMORY_TRACKING
25 | #endif
26 |
27 | void *_mosquitto_calloc(size_t nmemb, size_t size);
28 | void _mosquitto_free(void *mem);
29 | void *_mosquitto_malloc(size_t size);
30 | #ifdef REAL_WITH_MEMORY_TRACKING
31 | unsigned long _mosquitto_memory_used(void);
32 | unsigned long _mosquitto_max_memory_used(void);
33 | #endif
34 | void *_mosquitto_realloc(void *ptr, size_t size);
35 | char *_mosquitto_strdup(const char *s);
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/mosquitto/lib/util_mosq.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 | #ifndef _UTIL_MOSQ_H_
17 | #define _UTIL_MOSQ_H_
18 |
19 | #include
20 |
21 | #include "tls_mosq.h"
22 | #include "mosquitto.h"
23 | #include "mosquitto_internal.h"
24 | #ifdef WITH_BROKER
25 | # include "mosquitto_broker.h"
26 | #endif
27 |
28 | int _mosquitto_packet_alloc(struct _mosquitto_packet *packet);
29 | #ifdef WITH_BROKER
30 | void _mosquitto_check_keepalive(struct mosquitto_db *db, struct mosquitto *mosq);
31 | #else
32 | void _mosquitto_check_keepalive(struct mosquitto *mosq);
33 | #endif
34 | uint16_t _mosquitto_mid_generate(struct mosquitto *mosq);
35 | FILE *_mosquitto_fopen(const char *path, const char *mode);
36 |
37 | #ifdef REAL_WITH_TLS_PSK
38 | int _mosquitto_hex2bin(const char *hex, unsigned char *bin, int bin_max_len);
39 | #endif
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/Moscapsule/config.h:
--------------------------------------------------------------------------------
1 | //
2 | // config.h
3 | // MosquittoSwiftWrapper
4 | //
5 | // Created by flightonary on 2014/11/23.
6 | //
7 | // The MIT License (MIT)
8 | //
9 | // Copyright (c) 2014 tonary . All rights reserved.
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
12 | // this software and associated documentation files (the "Software"), to deal in
13 | // the Software without restriction, including without limitation the rights to
14 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
15 | // the Software, and to permit persons to whom the Software is furnished to do so,
16 | // subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
23 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
24 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 | // this is dummy header
30 |
--------------------------------------------------------------------------------
/Moscapsule.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "Moscapsule"
4 | s.version = "0.6.4"
5 | s.summary = "MQTT Client for iOS written in Swift"
6 | s.description = <<-DESC
7 | MQTT Client for iOS written in Swift.
8 | This framework is implemented as a wrapper of Mosquitto library
9 | and covers almost all mosquitto features.
10 | DESC
11 | s.homepage = "https://github.com/flightonary/Moscapsule"
12 |
13 | s.license = "MIT"
14 | s.author = { "tonary" => "nekomelife@gmail.com" }
15 |
16 | s.platform = :ios
17 | s.ios.deployment_target = '8.0'
18 |
19 | s.source = { :git => "https://github.com/flightonary/Moscapsule.git", :tag => s.version }
20 |
21 | s.source_files = "Moscapsule/*.{h,m,swift}", "mosquitto/lib/*.{h,c}"
22 | s.public_header_files = "Moscapsule/Moscapsule.h", "Moscapsule/MosquittoCallbackBridge.h", "mosquitto/lib/mosquitto.h"
23 |
24 | s.libraries = "ssl", "crypto"
25 | s.requires_arc = true
26 | s.xcconfig = {
27 | 'SWIFT_VERSION' => '4.0',
28 | 'OTHER_CFLAGS' => '-DWITH_THREADING -DWITH_TLS -DWITH_TLS_PSK',
29 | 'HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/Headers/Public/OpenSSL-Universal"',
30 | 'LIBRARY_SEARCH_PATHS' => [
31 | '"$(PODS_ROOT)/OpenSSL-Universal/lib-ios"',
32 | '"$(PODS_ROOT)/OpenSSL-Universal/ios/lib"'
33 | ]
34 | }
35 |
36 | #s.dependency "OpenSSL-Universal", "~> 1.0.1.20" # not working well
37 |
38 | end
39 |
--------------------------------------------------------------------------------
/mosquitto/lib/messages_mosq.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2010-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 | #ifndef _MESSAGES_MOSQ_H_
17 | #define _MESSAGES_MOSQ_H_
18 |
19 | #include
20 | #include
21 |
22 | void _mosquitto_message_cleanup_all(struct mosquitto *mosq);
23 | void _mosquitto_message_cleanup(struct mosquitto_message_all **message);
24 | int _mosquitto_message_delete(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir);
25 | int _mosquitto_message_queue(struct mosquitto *mosq, struct mosquitto_message_all *message, enum mosquitto_msg_direction dir);
26 | void _mosquitto_messages_reconnect_reset(struct mosquitto *mosq);
27 | int _mosquitto_message_remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, struct mosquitto_message_all **message);
28 | void _mosquitto_message_retry_check(struct mosquitto *mosq);
29 | int _mosquitto_message_out_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_state state);
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/mosquitto/lib/read_handle.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2010-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 | #ifndef _READ_HANDLE_H_
17 | #define _READ_HANDLE_H_
18 |
19 | #include
20 | struct mosquitto_db;
21 |
22 | int _mosquitto_packet_handle(struct mosquitto *mosq);
23 | int _mosquitto_handle_connack(struct mosquitto *mosq);
24 | int _mosquitto_handle_pingreq(struct mosquitto *mosq);
25 | int _mosquitto_handle_pingresp(struct mosquitto *mosq);
26 | #ifdef WITH_BROKER
27 | int _mosquitto_handle_pubackcomp(struct mosquitto_db *db, struct mosquitto *mosq, const char *type);
28 | #else
29 | int _mosquitto_handle_pubackcomp(struct mosquitto *mosq, const char *type);
30 | #endif
31 | int _mosquitto_handle_publish(struct mosquitto *mosq);
32 | int _mosquitto_handle_pubrec(struct mosquitto *mosq);
33 | int _mosquitto_handle_pubrel(struct mosquitto_db *db, struct mosquitto *mosq);
34 | int _mosquitto_handle_suback(struct mosquitto *mosq);
35 | int _mosquitto_handle_unsuback(struct mosquitto *mosq);
36 |
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/mosquitto/lib/logging_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #include
22 | #include
23 | #include
24 |
25 | int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...)
26 | {
27 | va_list va;
28 | char *s;
29 | int len;
30 |
31 | assert(mosq);
32 | assert(fmt);
33 |
34 | pthread_mutex_lock(&mosq->log_callback_mutex);
35 | if(mosq->on_log){
36 | len = (int)(strlen(fmt) + 500);
37 | s = _mosquitto_malloc(len*sizeof(char));
38 | if(!s){
39 | pthread_mutex_unlock(&mosq->log_callback_mutex);
40 | return MOSQ_ERR_NOMEM;
41 | }
42 |
43 | va_start(va, fmt);
44 | vsnprintf(s, len, fmt, va);
45 | va_end(va);
46 | s[len-1] = '\0'; /* Ensure string is null terminated. */
47 |
48 | mosq->on_log(mosq, mosq->userdata, priority, s);
49 |
50 | _mosquitto_free(s);
51 | }
52 | pthread_mutex_unlock(&mosq->log_callback_mutex);
53 |
54 | return MOSQ_ERR_SUCCESS;
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/mosquitto/lib/mqtt3_protocol.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #ifndef _MQTT3_PROTOCOL_H_
18 | #define _MQTT3_PROTOCOL_H_
19 |
20 | /* For version 3 of the MQTT protocol */
21 |
22 | #define PROTOCOL_NAME_v31 "MQIsdp"
23 | #define PROTOCOL_VERSION_v31 3
24 |
25 | #define PROTOCOL_NAME_v311 "MQTT"
26 | #define PROTOCOL_VERSION_v311 4
27 |
28 | /* Message types */
29 | #define CONNECT 0x10
30 | #define CONNACK 0x20
31 | #define PUBLISH 0x30
32 | #define PUBACK 0x40
33 | #define PUBREC 0x50
34 | #define PUBREL 0x60
35 | #define PUBCOMP 0x70
36 | #define SUBSCRIBE 0x80
37 | #define SUBACK 0x90
38 | #define UNSUBSCRIBE 0xA0
39 | #define UNSUBACK 0xB0
40 | #define PINGREQ 0xC0
41 | #define PINGRESP 0xD0
42 | #define DISCONNECT 0xE0
43 |
44 | #define CONNACK_ACCEPTED 0
45 | #define CONNACK_REFUSED_PROTOCOL_VERSION 1
46 | #define CONNACK_REFUSED_IDENTIFIER_REJECTED 2
47 | #define CONNACK_REFUSED_SERVER_UNAVAILABLE 3
48 | #define CONNACK_REFUSED_BAD_USERNAME_PASSWORD 4
49 | #define CONNACK_REFUSED_NOT_AUTHORIZED 5
50 |
51 | #define MQTT_MAX_PAYLOAD 268435455
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/mosquitto/lib/read_handle_client.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | int _mosquitto_handle_connack(struct mosquitto *mosq)
26 | {
27 | uint8_t byte;
28 | uint8_t result;
29 | int rc;
30 |
31 | assert(mosq);
32 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK", mosq->id);
33 | rc = _mosquitto_read_byte(&mosq->in_packet, &byte); // Reserved byte, not used
34 | if(rc) return rc;
35 | rc = _mosquitto_read_byte(&mosq->in_packet, &result);
36 | if(rc) return rc;
37 | pthread_mutex_lock(&mosq->callback_mutex);
38 | if(mosq->on_connect){
39 | mosq->in_callback = true;
40 | mosq->on_connect(mosq, mosq->userdata, result);
41 | mosq->in_callback = false;
42 | }
43 | pthread_mutex_unlock(&mosq->callback_mutex);
44 | switch(result){
45 | case 0:
46 | if(mosq->state != mosq_cs_disconnecting){
47 | mosq->state = mosq_cs_connected;
48 | }
49 | return MOSQ_ERR_SUCCESS;
50 | case 1:
51 | case 2:
52 | case 3:
53 | case 4:
54 | case 5:
55 | return MOSQ_ERR_CONN_REFUSED;
56 | default:
57 | return MOSQ_ERR_PROTOCOL;
58 | }
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/mosquitto/lib/send_mosq.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2010-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 | #ifndef _SEND_MOSQ_H_
17 | #define _SEND_MOSQ_H_
18 |
19 | #include
20 |
21 | int _mosquitto_send_simple_command(struct mosquitto *mosq, uint8_t command);
22 | int _mosquitto_send_command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup);
23 | int _mosquitto_send_real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup);
24 |
25 | int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session);
26 | int _mosquitto_send_disconnect(struct mosquitto *mosq);
27 | int _mosquitto_send_pingreq(struct mosquitto *mosq);
28 | int _mosquitto_send_pingresp(struct mosquitto *mosq);
29 | int _mosquitto_send_puback(struct mosquitto *mosq, uint16_t mid);
30 | int _mosquitto_send_pubcomp(struct mosquitto *mosq, uint16_t mid);
31 | int _mosquitto_send_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup);
32 | int _mosquitto_send_pubrec(struct mosquitto *mosq, uint16_t mid);
33 | int _mosquitto_send_pubrel(struct mosquitto *mosq, uint16_t mid);
34 | int _mosquitto_send_subscribe(struct mosquitto *mosq, int *mid, const char *topic, uint8_t topic_qos);
35 | int _mosquitto_send_unsubscribe(struct mosquitto *mosq, int *mid, const char *topic);
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # CocoaPods
2 | #
3 | # We recommend against adding the Pods directory to your .gitignore. However
4 | # you should judge for yourself, the pros and cons are mentioned at:
5 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
6 | #
7 | Pods/
8 |
9 | # Mosquitto
10 | mosquitto/*
11 | !mosquitto/lib/
12 | mosquitto/lib/*/
13 | mosquitto/lib/CMakeLists.txt
14 | mosquitto/lib/Makefile
15 | mosquitto/lib/linker.version
16 | ### https://raw.github.com/github/gitignore/50e42aa1064d004a5c99eaa72a2d8054a0d8de55/Global/Xcode.gitignore
17 |
18 | # Xcode
19 | #
20 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
21 |
22 | ## User settings
23 | xcuserdata/
24 |
25 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
26 | *.xcscmblueprint
27 | *.xccheckout
28 |
29 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
30 | build/
31 | DerivedData/
32 | *.moved-aside
33 | *.pbxuser
34 | !default.pbxuser
35 | *.mode1v3
36 | !default.mode1v3
37 | *.mode2v3
38 | !default.mode2v3
39 | *.perspectivev3
40 | !default.perspectivev3
41 |
42 | ## Xcode Patch
43 | *.xcodeproj/*
44 | !*.xcodeproj/project.pbxproj
45 | !*.xcodeproj/xcshareddata/
46 | !*.xcworkspace/contents.xcworkspacedata
47 | /*.gcno
48 |
49 |
50 | ### https://raw.github.com/github/gitignore/50e42aa1064d004a5c99eaa72a2d8054a0d8de55/Global/macOS.gitignore
51 |
52 | # General
53 | .DS_Store
54 | .AppleDouble
55 | .LSOverride
56 |
57 | # Icon must end with two \r
58 | Icon
59 |
60 | # Thumbnails
61 | ._*
62 |
63 | # Files that might appear in the root of a volume
64 | .DocumentRevisions-V100
65 | .fseventsd
66 | .Spotlight-V100
67 | .TemporaryItems
68 | .Trashes
69 | .VolumeIcon.icns
70 | .com.apple.timemachine.donotpresent
71 |
72 | # Directories potentially created on remote AFP share
73 | .AppleDB
74 | .AppleDesktop
75 | Network Trash Folder
76 | Temporary Items
77 | .apdisk
78 |
--------------------------------------------------------------------------------
/mosquitto/lib/time_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013,2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #ifdef __APPLE__
18 | #include
19 | #include
20 | #endif
21 |
22 | #ifdef WIN32
23 | # define _WIN32_WINNT _WIN32_WINNT_VISTA
24 | # include
25 | #else
26 | # include
27 | #endif
28 | #include
29 |
30 | #include "mosquitto.h"
31 | #include "time_mosq.h"
32 |
33 | #ifdef WIN32
34 | static bool tick64 = false;
35 |
36 | void _windows_time_version_check(void)
37 | {
38 | OSVERSIONINFO vi;
39 |
40 | tick64 = false;
41 |
42 | memset(&vi, 0, sizeof(OSVERSIONINFO));
43 | vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
44 | if(GetVersionEx(&vi)){
45 | if(vi.dwMajorVersion > 5){
46 | tick64 = true;
47 | }
48 | }
49 | }
50 | #endif
51 |
52 | time_t mosquitto_time(void)
53 | {
54 | #ifdef WIN32
55 | if(tick64){
56 | return GetTickCount64()/1000;
57 | }else{
58 | return GetTickCount()/1000; /* FIXME - need to deal with overflow. */
59 | }
60 | #elif _POSIX_TIMERS>0 && defined(_POSIX_MONOTONIC_CLOCK)
61 | struct timespec tp;
62 |
63 | clock_gettime(CLOCK_MONOTONIC, &tp);
64 | return tp.tv_sec;
65 | #elif defined(__APPLE__)
66 | static mach_timebase_info_data_t tb;
67 | uint64_t ticks;
68 | uint64_t sec;
69 |
70 | ticks = mach_absolute_time();
71 |
72 | if(tb.denom == 0){
73 | mach_timebase_info(&tb);
74 | }
75 | sec = ticks*tb.numer/tb.denom/1000000000;
76 |
77 | return (time_t)sec;
78 | #else
79 | return time(NULL);
80 | #endif
81 | }
82 |
83 |
--------------------------------------------------------------------------------
/mosquitto/lib/memory_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 |
19 | #include
20 | #include
21 |
22 | #include
23 |
24 | #ifdef REAL_WITH_MEMORY_TRACKING
25 | # if defined(__APPLE__)
26 | # include
27 | # define malloc_usable_size malloc_size
28 | # elif defined(__FreeBSD__)
29 | # include
30 | # else
31 | # include
32 | # endif
33 | #endif
34 |
35 | #ifdef REAL_WITH_MEMORY_TRACKING
36 | static unsigned long memcount = 0;
37 | static unsigned long max_memcount = 0;
38 | #endif
39 |
40 | void *_mosquitto_calloc(size_t nmemb, size_t size)
41 | {
42 | void *mem = calloc(nmemb, size);
43 |
44 | #ifdef REAL_WITH_MEMORY_TRACKING
45 | memcount += malloc_usable_size(mem);
46 | if(memcount > max_memcount){
47 | max_memcount = memcount;
48 | }
49 | #endif
50 |
51 | return mem;
52 | }
53 |
54 | void _mosquitto_free(void *mem)
55 | {
56 | #ifdef REAL_WITH_MEMORY_TRACKING
57 | if(!mem){
58 | return;
59 | }
60 | memcount -= malloc_usable_size(mem);
61 | #endif
62 | free(mem);
63 | }
64 |
65 | void *_mosquitto_malloc(size_t size)
66 | {
67 | void *mem = malloc(size);
68 |
69 | #ifdef REAL_WITH_MEMORY_TRACKING
70 | memcount += malloc_usable_size(mem);
71 | if(memcount > max_memcount){
72 | max_memcount = memcount;
73 | }
74 | #endif
75 |
76 | return mem;
77 | }
78 |
79 | #ifdef REAL_WITH_MEMORY_TRACKING
80 | unsigned long _mosquitto_memory_used(void)
81 | {
82 | return memcount;
83 | }
84 |
85 | unsigned long _mosquitto_max_memory_used(void)
86 | {
87 | return max_memcount;
88 | }
89 | #endif
90 |
91 | void *_mosquitto_realloc(void *ptr, size_t size)
92 | {
93 | void *mem;
94 | #ifdef REAL_WITH_MEMORY_TRACKING
95 | if(ptr){
96 | memcount -= malloc_usable_size(ptr);
97 | }
98 | #endif
99 | mem = realloc(ptr, size);
100 |
101 | #ifdef REAL_WITH_MEMORY_TRACKING
102 | memcount += malloc_usable_size(mem);
103 | if(memcount > max_memcount){
104 | max_memcount = memcount;
105 | }
106 | #endif
107 |
108 | return mem;
109 | }
110 |
111 | char *_mosquitto_strdup(const char *s)
112 | {
113 | char *str = strdup(s);
114 |
115 | #ifdef REAL_WITH_MEMORY_TRACKING
116 | memcount += malloc_usable_size(str);
117 | if(memcount > max_memcount){
118 | max_memcount = memcount;
119 | }
120 | #endif
121 |
122 | return str;
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/mosquitto/lib/thread_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2011-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 |
19 | #ifndef WIN32
20 | #include
21 | #endif
22 |
23 | #include
24 | #include
25 |
26 | void *_mosquitto_thread_main(void *obj);
27 |
28 | int mosquitto_loop_start(struct mosquitto *mosq)
29 | {
30 | #ifdef WITH_THREADING
31 | if(!mosq || mosq->threaded) return MOSQ_ERR_INVAL;
32 |
33 | mosq->threaded = true;
34 | pthread_create(&mosq->thread_id, NULL, _mosquitto_thread_main, mosq);
35 | return MOSQ_ERR_SUCCESS;
36 | #else
37 | return MOSQ_ERR_NOT_SUPPORTED;
38 | #endif
39 | }
40 |
41 | int mosquitto_loop_stop(struct mosquitto *mosq, bool force)
42 | {
43 | #ifdef WITH_THREADING
44 | # ifndef WITH_BROKER
45 | char sockpair_data = 0;
46 | # endif
47 |
48 | if(!mosq || !mosq->threaded) return MOSQ_ERR_INVAL;
49 |
50 |
51 | /* Write a single byte to sockpairW (connected to sockpairR) to break out
52 | * of select() if in threaded mode. */
53 | if(mosq->sockpairW != INVALID_SOCKET){
54 | #ifndef WIN32
55 | if(write(mosq->sockpairW, &sockpair_data, 1)){
56 | }
57 | #else
58 | send(mosq->sockpairW, &sockpair_data, 1, 0);
59 | #endif
60 | }
61 |
62 | if(force){
63 | pthread_cancel(mosq->thread_id);
64 | }
65 | pthread_join(mosq->thread_id, NULL);
66 | mosq->thread_id = pthread_self();
67 | mosq->threaded = false;
68 |
69 | return MOSQ_ERR_SUCCESS;
70 | #else
71 | return MOSQ_ERR_NOT_SUPPORTED;
72 | #endif
73 | }
74 |
75 | #ifdef WITH_THREADING
76 | void *_mosquitto_thread_main(void *obj)
77 | {
78 | struct mosquitto *mosq = obj;
79 |
80 | if(!mosq) return NULL;
81 |
82 | pthread_mutex_lock(&mosq->state_mutex);
83 | if(mosq->state == mosq_cs_connect_async){
84 | pthread_mutex_unlock(&mosq->state_mutex);
85 | mosquitto_reconnect(mosq);
86 | }else{
87 | pthread_mutex_unlock(&mosq->state_mutex);
88 | }
89 |
90 | if(!mosq->keepalive){
91 | /* Sleep for a day if keepalive disabled. */
92 | mosquitto_loop_forever(mosq, 1000*86400, 1);
93 | }else{
94 | /* Sleep for our keepalive value. publish() etc. will wake us up. */
95 | mosquitto_loop_forever(mosq, mosq->keepalive*1000, 1);
96 | }
97 |
98 | return obj;
99 | }
100 | #endif
101 |
102 | int mosquitto_threaded_set(struct mosquitto *mosq, bool threaded)
103 | {
104 | if(!mosq) return MOSQ_ERR_INVAL;
105 |
106 | mosq->threaded = threaded;
107 |
108 | return MOSQ_ERR_SUCCESS;
109 | }
110 |
--------------------------------------------------------------------------------
/mosquitto/lib/will_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2010-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | int _mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain)
25 | {
26 | int rc = MOSQ_ERR_SUCCESS;
27 |
28 | if(!mosq || !topic) return MOSQ_ERR_INVAL;
29 | if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE;
30 | if(payloadlen > 0 && !payload) return MOSQ_ERR_INVAL;
31 |
32 | if(mosquitto_pub_topic_check(topic)) return MOSQ_ERR_INVAL;
33 |
34 | if(mosq->will){
35 | if(mosq->will->topic){
36 | _mosquitto_free(mosq->will->topic);
37 | mosq->will->topic = NULL;
38 | }
39 | if(mosq->will->payload){
40 | _mosquitto_free(mosq->will->payload);
41 | mosq->will->payload = NULL;
42 | }
43 | _mosquitto_free(mosq->will);
44 | mosq->will = NULL;
45 | }
46 |
47 | mosq->will = _mosquitto_calloc(1, sizeof(struct mosquitto_message));
48 | if(!mosq->will) return MOSQ_ERR_NOMEM;
49 | mosq->will->topic = _mosquitto_strdup(topic);
50 | if(!mosq->will->topic){
51 | rc = MOSQ_ERR_NOMEM;
52 | goto cleanup;
53 | }
54 | mosq->will->payloadlen = payloadlen;
55 | if(mosq->will->payloadlen > 0){
56 | if(!payload){
57 | rc = MOSQ_ERR_INVAL;
58 | goto cleanup;
59 | }
60 | mosq->will->payload = _mosquitto_malloc(sizeof(char)*mosq->will->payloadlen);
61 | if(!mosq->will->payload){
62 | rc = MOSQ_ERR_NOMEM;
63 | goto cleanup;
64 | }
65 |
66 | memcpy(mosq->will->payload, payload, payloadlen);
67 | }
68 | mosq->will->qos = qos;
69 | mosq->will->retain = retain;
70 |
71 | return MOSQ_ERR_SUCCESS;
72 |
73 | cleanup:
74 | if(mosq->will){
75 | if(mosq->will->topic) _mosquitto_free(mosq->will->topic);
76 | if(mosq->will->payload) _mosquitto_free(mosq->will->payload);
77 | }
78 | _mosquitto_free(mosq->will);
79 | mosq->will = NULL;
80 |
81 | return rc;
82 | }
83 |
84 | int _mosquitto_will_clear(struct mosquitto *mosq)
85 | {
86 | if(!mosq->will) return MOSQ_ERR_SUCCESS;
87 |
88 | if(mosq->will->topic){
89 | _mosquitto_free(mosq->will->topic);
90 | mosq->will->topic = NULL;
91 | }
92 | if(mosq->will->payload){
93 | _mosquitto_free(mosq->will->payload);
94 | mosq->will->payload = NULL;
95 | }
96 | _mosquitto_free(mosq->will);
97 | mosq->will = NULL;
98 |
99 | return MOSQ_ERR_SUCCESS;
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/mosquitto/lib/srv_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013,2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #ifdef WITH_SRV
18 | # include
19 |
20 | # include
21 | # include
22 | # include
23 | #endif
24 |
25 | #include "logging_mosq.h"
26 | #include "memory_mosq.h"
27 | #include "mosquitto_internal.h"
28 | #include "mosquitto.h"
29 |
30 | #ifdef WITH_SRV
31 | static void srv_callback(void *arg, int status, int timeouts, unsigned char *abuf, int alen)
32 | {
33 | struct mosquitto *mosq = arg;
34 | struct ares_srv_reply *reply = NULL;
35 | if(status == ARES_SUCCESS){
36 | status = ares_parse_srv_reply(abuf, alen, &reply);
37 | if(status == ARES_SUCCESS){
38 | // FIXME - choose which answer to use based on rfc2782 page 3. */
39 | mosquitto_connect(mosq, reply->host, reply->port, mosq->keepalive);
40 | }
41 | }else{
42 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: SRV lookup failed (%d).", status);
43 | /* FIXME - calling on_disconnect here isn't correct. */
44 | pthread_mutex_lock(&mosq->callback_mutex);
45 | if(mosq->on_disconnect){
46 | mosq->in_callback = true;
47 | mosq->on_disconnect(mosq, mosq->userdata, 2);
48 | mosq->in_callback = false;
49 | }
50 | pthread_mutex_unlock(&mosq->callback_mutex);
51 | }
52 | }
53 | #endif
54 |
55 | int mosquitto_connect_srv(struct mosquitto *mosq, const char *host, int keepalive, const char *bind_address)
56 | {
57 | #ifdef WITH_SRV
58 | char *h;
59 | int rc;
60 | if(!mosq) return MOSQ_ERR_INVAL;
61 |
62 | rc = ares_init(&mosq->achan);
63 | if(rc != ARES_SUCCESS){
64 | return MOSQ_ERR_UNKNOWN;
65 | }
66 |
67 | if(!host){
68 | // get local domain
69 | }else{
70 | #ifdef WITH_TLS
71 | if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
72 | h = _mosquitto_malloc(strlen(host) + strlen("_secure-mqtt._tcp.") + 1);
73 | if(!h) return MOSQ_ERR_NOMEM;
74 | sprintf(h, "_secure-mqtt._tcp.%s", host);
75 | }else{
76 | #endif
77 | h = _mosquitto_malloc(strlen(host) + strlen("_mqtt._tcp.") + 1);
78 | if(!h) return MOSQ_ERR_NOMEM;
79 | sprintf(h, "_mqtt._tcp.%s", host);
80 | #ifdef WITH_TLS
81 | }
82 | #endif
83 | ares_search(mosq->achan, h, ns_c_in, ns_t_srv, srv_callback, mosq);
84 | _mosquitto_free(h);
85 | }
86 |
87 | pthread_mutex_lock(&mosq->state_mutex);
88 | mosq->state = mosq_cs_connect_srv;
89 | pthread_mutex_unlock(&mosq->state_mutex);
90 |
91 | mosq->keepalive = keepalive;
92 |
93 | return MOSQ_ERR_SUCCESS;
94 |
95 | #else
96 | return MOSQ_ERR_NOT_SUPPORTED;
97 | #endif
98 | }
99 |
100 |
101 |
--------------------------------------------------------------------------------
/mosquitto/lib/net_mosq.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2010-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 | #ifndef _NET_MOSQ_H_
17 | #define _NET_MOSQ_H_
18 |
19 | #ifndef WIN32
20 | #include
21 | #else
22 | #include
23 | typedef int ssize_t;
24 | #endif
25 |
26 | #include
27 | #include
28 |
29 | #ifdef WITH_BROKER
30 | struct mosquitto_db;
31 | #endif
32 |
33 | #ifdef WIN32
34 | # define COMPAT_CLOSE(a) closesocket(a)
35 | # define COMPAT_ECONNRESET WSAECONNRESET
36 | # define COMPAT_EWOULDBLOCK WSAEWOULDBLOCK
37 | #else
38 | # define COMPAT_CLOSE(a) close(a)
39 | # define COMPAT_ECONNRESET ECONNRESET
40 | # define COMPAT_EWOULDBLOCK EWOULDBLOCK
41 | #endif
42 |
43 | /* For when not using winsock libraries. */
44 | #ifndef INVALID_SOCKET
45 | #define INVALID_SOCKET -1
46 | #endif
47 |
48 | /* Macros for accessing the MSB and LSB of a uint16_t */
49 | #define MOSQ_MSB(A) (uint8_t)((A & 0xFF00) >> 8)
50 | #define MOSQ_LSB(A) (uint8_t)(A & 0x00FF)
51 |
52 | void _mosquitto_net_init(void);
53 | void _mosquitto_net_cleanup(void);
54 |
55 | void _mosquitto_packet_cleanup(struct _mosquitto_packet *packet);
56 | int _mosquitto_packet_queue(struct mosquitto *mosq, struct _mosquitto_packet *packet);
57 | int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking);
58 | #ifdef WITH_BROKER
59 | int _mosquitto_socket_close(struct mosquitto_db *db, struct mosquitto *mosq);
60 | #else
61 | int _mosquitto_socket_close(struct mosquitto *mosq);
62 | #endif
63 | int _mosquitto_try_connect(struct mosquitto *mosq, const char *host, uint16_t port, mosq_sock_t *sock, const char *bind_address, bool blocking);
64 | int _mosquitto_socket_nonblock(mosq_sock_t sock);
65 | int _mosquitto_socketpair(mosq_sock_t *sp1, mosq_sock_t *sp2);
66 |
67 | int _mosquitto_read_byte(struct _mosquitto_packet *packet, uint8_t *byte);
68 | int _mosquitto_read_bytes(struct _mosquitto_packet *packet, void *bytes, uint32_t count);
69 | int _mosquitto_read_string(struct _mosquitto_packet *packet, char **str);
70 | int _mosquitto_read_uint16(struct _mosquitto_packet *packet, uint16_t *word);
71 |
72 | void _mosquitto_write_byte(struct _mosquitto_packet *packet, uint8_t byte);
73 | void _mosquitto_write_bytes(struct _mosquitto_packet *packet, const void *bytes, uint32_t count);
74 | void _mosquitto_write_string(struct _mosquitto_packet *packet, const char *str, uint16_t length);
75 | void _mosquitto_write_uint16(struct _mosquitto_packet *packet, uint16_t word);
76 |
77 | ssize_t _mosquitto_net_read(struct mosquitto *mosq, void *buf, size_t count);
78 | ssize_t _mosquitto_net_write(struct mosquitto *mosq, void *buf, size_t count);
79 |
80 | int _mosquitto_packet_write(struct mosquitto *mosq);
81 | #ifdef WITH_BROKER
82 | int _mosquitto_packet_read(struct mosquitto_db *db, struct mosquitto *mosq);
83 | #else
84 | int _mosquitto_packet_read(struct mosquitto *mosq);
85 | #endif
86 |
87 | #ifdef WITH_TLS
88 | int _mosquitto_socket_apply_tls(struct mosquitto *mosq);
89 | int mosquitto__socket_connect_tls(struct mosquitto *mosq);
90 | #endif
91 |
92 | #endif
93 |
--------------------------------------------------------------------------------
/Moscapsule.xcodeproj/xcshareddata/xcschemes/Moscapsule.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
65 |
71 |
72 |
73 |
74 |
75 |
76 |
82 |
83 |
89 |
90 |
91 |
92 |
94 |
95 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/mosquitto/lib/tls_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013,2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #ifdef WITH_TLS
18 |
19 | #ifdef WIN32
20 | # include
21 | # include
22 | #else
23 | # include
24 | # include
25 | #endif
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #ifdef WITH_BROKER
33 | # include "mosquitto_broker.h"
34 | #endif
35 | #include "mosquitto_internal.h"
36 | #include "tls_mosq.h"
37 |
38 | extern int tls_ex_index_mosq;
39 |
40 | int _mosquitto_server_certificate_verify(int preverify_ok, X509_STORE_CTX *ctx)
41 | {
42 | /* Preverify should have already checked expiry, revocation.
43 | * We need to verify the hostname. */
44 | struct mosquitto *mosq;
45 | SSL *ssl;
46 | X509 *cert;
47 |
48 | /* Always reject if preverify_ok has failed. */
49 | if(!preverify_ok) return 0;
50 |
51 | ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
52 | mosq = SSL_get_ex_data(ssl, tls_ex_index_mosq);
53 | if(!mosq) return 0;
54 |
55 | if(mosq->tls_insecure == false){
56 | if(X509_STORE_CTX_get_error_depth(ctx) == 0){
57 | /* FIXME - use X509_check_host() etc. for sufficiently new openssl (>=1.1.x) */
58 | cert = X509_STORE_CTX_get_current_cert(ctx);
59 | /* This is the peer certificate, all others are upwards in the chain. */
60 | #if defined(WITH_BROKER)
61 | return _mosquitto_verify_certificate_hostname(cert, mosq->bridge->addresses[mosq->bridge->cur_address].address);
62 | #else
63 | return _mosquitto_verify_certificate_hostname(cert, mosq->host);
64 | #endif
65 | }else{
66 | return preverify_ok;
67 | }
68 | }else{
69 | return preverify_ok;
70 | }
71 | }
72 |
73 | int mosquitto__cmp_hostname_wildcard(char *certname, const char *hostname)
74 | {
75 | int i;
76 | unsigned long len;
77 |
78 | if(!certname || !hostname){
79 | return 1;
80 | }
81 |
82 | if(certname[0] == '*'){
83 | if(certname[1] != '.'){
84 | return 1;
85 | }
86 | certname += 2;
87 | len = strlen(hostname);
88 | for(i=0; itype == GEN_DNS){
130 | data = ASN1_STRING_data(nval->d.dNSName);
131 | if(data && !mosquitto__cmp_hostname_wildcard((char *)data, hostname)){
132 | return 1;
133 | }
134 | have_san_dns = true;
135 | }else if(nval->type == GEN_IPADD){
136 | data = ASN1_STRING_data(nval->d.iPAddress);
137 | if(nval->d.iPAddress->length == 4 && ipv4_ok){
138 | if(!memcmp(ipv4_addr, data, 4)){
139 | return 1;
140 | }
141 | }else if(nval->d.iPAddress->length == 16 && ipv6_ok){
142 | if(!memcmp(ipv6_addr, data, 16)){
143 | return 1;
144 | }
145 | }
146 | }
147 | }
148 | if(have_san_dns){
149 | /* Only check CN if subjectAltName DNS entry does not exist. */
150 | return 0;
151 | }
152 | }
153 | subj = X509_get_subject_name(cert);
154 | if(X509_NAME_get_text_by_NID(subj, NID_commonName, name, sizeof(name)) > 0){
155 | name[sizeof(name) - 1] = '\0';
156 | if (!mosquitto__cmp_hostname_wildcard(name, hostname)) return 1;
157 | }
158 | return 0;
159 | }
160 |
161 | #endif
162 |
163 |
--------------------------------------------------------------------------------
/mosquitto/lib/read_handle.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | int _mosquitto_packet_handle(struct mosquitto *mosq)
33 | {
34 | assert(mosq);
35 |
36 | switch((mosq->in_packet.command)&0xF0){
37 | case PINGREQ:
38 | return _mosquitto_handle_pingreq(mosq);
39 | case PINGRESP:
40 | return _mosquitto_handle_pingresp(mosq);
41 | case PUBACK:
42 | return _mosquitto_handle_pubackcomp(mosq, "PUBACK");
43 | case PUBCOMP:
44 | return _mosquitto_handle_pubackcomp(mosq, "PUBCOMP");
45 | case PUBLISH:
46 | return _mosquitto_handle_publish(mosq);
47 | case PUBREC:
48 | return _mosquitto_handle_pubrec(mosq);
49 | case PUBREL:
50 | return _mosquitto_handle_pubrel(NULL, mosq);
51 | case CONNACK:
52 | return _mosquitto_handle_connack(mosq);
53 | case SUBACK:
54 | return _mosquitto_handle_suback(mosq);
55 | case UNSUBACK:
56 | return _mosquitto_handle_unsuback(mosq);
57 | default:
58 | /* If we don't recognise the command, return an error straight away. */
59 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unrecognised command %d\n", (mosq->in_packet.command)&0xF0);
60 | return MOSQ_ERR_PROTOCOL;
61 | }
62 | }
63 |
64 | int _mosquitto_handle_publish(struct mosquitto *mosq)
65 | {
66 | uint8_t header;
67 | struct mosquitto_message_all *message;
68 | int rc = 0;
69 | uint16_t mid;
70 |
71 | assert(mosq);
72 |
73 | message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all));
74 | if(!message) return MOSQ_ERR_NOMEM;
75 |
76 | header = mosq->in_packet.command;
77 |
78 | message->dup = (header & 0x08)>>3;
79 | message->msg.qos = (header & 0x06)>>1;
80 | message->msg.retain = (header & 0x01);
81 |
82 | rc = _mosquitto_read_string(&mosq->in_packet, &message->msg.topic);
83 | if(rc){
84 | _mosquitto_message_cleanup(&message);
85 | return rc;
86 | }
87 | if(!strlen(message->msg.topic)){
88 | _mosquitto_message_cleanup(&message);
89 | return MOSQ_ERR_PROTOCOL;
90 | }
91 |
92 | if(message->msg.qos > 0){
93 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
94 | if(rc){
95 | _mosquitto_message_cleanup(&message);
96 | return rc;
97 | }
98 | message->msg.mid = (int)mid;
99 | }
100 |
101 | message->msg.payloadlen = mosq->in_packet.remaining_length - mosq->in_packet.pos;
102 | if(message->msg.payloadlen){
103 | message->msg.payload = _mosquitto_calloc(message->msg.payloadlen+1, sizeof(uint8_t));
104 | if(!message->msg.payload){
105 | _mosquitto_message_cleanup(&message);
106 | return MOSQ_ERR_NOMEM;
107 | }
108 | rc = _mosquitto_read_bytes(&mosq->in_packet, message->msg.payload, message->msg.payloadlen);
109 | if(rc){
110 | _mosquitto_message_cleanup(&message);
111 | return rc;
112 | }
113 | }
114 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG,
115 | "Client %s received PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))",
116 | mosq->id, message->dup, message->msg.qos, message->msg.retain,
117 | message->msg.mid, message->msg.topic,
118 | (long)message->msg.payloadlen);
119 |
120 | message->timestamp = mosquitto_time();
121 | switch(message->msg.qos){
122 | case 0:
123 | pthread_mutex_lock(&mosq->callback_mutex);
124 | if(mosq->on_message){
125 | mosq->in_callback = true;
126 | mosq->on_message(mosq, mosq->userdata, &message->msg);
127 | mosq->in_callback = false;
128 | }
129 | pthread_mutex_unlock(&mosq->callback_mutex);
130 | _mosquitto_message_cleanup(&message);
131 | return MOSQ_ERR_SUCCESS;
132 | case 1:
133 | rc = _mosquitto_send_puback(mosq, message->msg.mid);
134 | pthread_mutex_lock(&mosq->callback_mutex);
135 | if(mosq->on_message){
136 | mosq->in_callback = true;
137 | mosq->on_message(mosq, mosq->userdata, &message->msg);
138 | mosq->in_callback = false;
139 | }
140 | pthread_mutex_unlock(&mosq->callback_mutex);
141 | _mosquitto_message_cleanup(&message);
142 | return rc;
143 | case 2:
144 | rc = _mosquitto_send_pubrec(mosq, message->msg.mid);
145 | pthread_mutex_lock(&mosq->in_message_mutex);
146 | message->state = mosq_ms_wait_for_pubrel;
147 | _mosquitto_message_queue(mosq, message, mosq_md_in);
148 | pthread_mutex_unlock(&mosq->in_message_mutex);
149 | return rc;
150 | default:
151 | _mosquitto_message_cleanup(&message);
152 | return MOSQ_ERR_PROTOCOL;
153 | }
154 | }
155 |
156 |
--------------------------------------------------------------------------------
/Moscapsule/MosquittoCallbackBridge.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import "MosquittoCallbackBridge.h"
3 | #import "mosquitto.h"
4 | #import "Moscapsule/Moscapsule-Swift.h"
5 |
6 | // Local Functions
7 | static int pw_callback(char *, int, int, void *);
8 | static void setMosquittoCallbackBridge(struct mosquitto *);
9 | static void on_connect(struct mosquitto *, void *, int);
10 | static void on_disconnect(struct mosquitto *, void *, int);
11 | static void on_publish(struct mosquitto *, void *, int);
12 | static void on_message(struct mosquitto *, void *, const struct mosquitto_message *);
13 | static void on_subscribe(struct mosquitto *, void *, int, int, const int *);
14 | static void on_unsubscribe(struct mosquitto *, void *, int);
15 | static void on_log(struct mosquitto *, void *, int, const char *);
16 | static const char *LogLevelString(int);
17 | static void log_d(__MosquittoContext *, enum mosq_err_t, NSString *);
18 |
19 | void mosquitto_context_setup(const char *clientId, bool cleanSession, __MosquittoContext *mosquittoContext, int protocolVersion)
20 | {
21 | mosquittoContext.mosquittoHandler = mosquitto_new(clientId, cleanSession, (__bridge void*)mosquittoContext);
22 | mosquitto_opts_set(mosquittoContext.mosquittoHandler, MOSQ_OPT_PROTOCOL_VERSION, &protocolVersion);
23 | mosquittoContext.isConnected = false;
24 | setMosquittoCallbackBridge(mosquittoContext.mosquittoHandler);
25 | }
26 |
27 | void mosquitto_context_cleanup(__MosquittoContext *mosquittoContext)
28 | {
29 | mosquitto_destroy(mosquittoContext.mosquittoHandler);
30 | }
31 |
32 | void mosquitto_tls_set_bridge(NSString *cafile, NSString *capath, NSString *certfile, NSString *keyfile, __MosquittoContext *mosquitto_context)
33 | {
34 | int ret = mosquitto_tls_set(mosquitto_context.mosquittoHandler,
35 | cafile != nil ? cafile.UTF8String : nil,
36 | capath != nil ? capath.UTF8String : nil,
37 | certfile != nil ? certfile.UTF8String : nil,
38 | keyfile != nil ? keyfile.UTF8String : nil,
39 | pw_callback);
40 |
41 | log_d(mosquitto_context, ret, [NSString stringWithFormat:@"mosquitto_tls_set error (code: %d)", ret]);
42 | }
43 |
44 | void mosquitto_tls_opts_set_bridge(int cert_reqs, NSString *tls_version, NSString *ciphers, __MosquittoContext *mosquitto_context)
45 | {
46 | int ret = mosquitto_tls_opts_set(mosquitto_context.mosquittoHandler, cert_reqs,
47 | tls_version != nil ? tls_version.UTF8String : nil,
48 | ciphers != nil ? ciphers.UTF8String : nil);
49 |
50 | log_d(mosquitto_context, ret, [NSString stringWithFormat:@"mosquitto_tls_opts_set error (code: %d)", ret]);
51 | }
52 |
53 | void mosquitto_tls_psk_set_bridge(NSString *psk, NSString *identity, NSString *ciphers, __MosquittoContext *mosquitto_context)
54 | {
55 | int ret = mosquitto_tls_psk_set(mosquitto_context.mosquittoHandler, psk.UTF8String, identity.UTF8String,
56 | ciphers != nil ? ciphers.UTF8String : nil);
57 |
58 | log_d(mosquitto_context, ret, [NSString stringWithFormat:@"mosquitto_tls_psk_set error (code: %d)", ret]);
59 | }
60 |
61 | static int pw_callback(char *buf, int size, int rwflag, void *obj)
62 | {
63 | __MosquittoContext *mosquittoContext = (__bridge __MosquittoContext*)obj;
64 | strncpy(buf, mosquittoContext.keyfile_passwd.UTF8String, size);
65 | buf[size - 1] = '\0';
66 | return (int)strlen(buf);
67 | }
68 |
69 | static void setMosquittoCallbackBridge(struct mosquitto *mosquittoHandler)
70 | {
71 | mosquitto_connect_callback_set(mosquittoHandler, on_connect);
72 | mosquitto_disconnect_callback_set(mosquittoHandler, on_disconnect);
73 | mosquitto_publish_callback_set(mosquittoHandler, on_publish);
74 | mosquitto_message_callback_set(mosquittoHandler, on_message);
75 | mosquitto_subscribe_callback_set(mosquittoHandler, on_subscribe);
76 | mosquitto_unsubscribe_callback_set(mosquittoHandler, on_unsubscribe);
77 | mosquitto_log_callback_set(mosquittoHandler, on_log);
78 | }
79 |
80 | static void on_connect(struct mosquitto *mosquittoHandler, void *obj, int returnCode)
81 | {
82 | __MosquittoContext *mosquittoContext = (__bridge __MosquittoContext*)obj;
83 | mosquittoContext.isConnected = returnCode == 0 ? true : false;
84 | if (mosquittoContext.onConnectCallback) {
85 | mosquittoContext.onConnectCallback(returnCode);
86 | }
87 | }
88 |
89 | static void on_disconnect(struct mosquitto *mosquittoHandler, void *obj, int reasonCode)
90 | {
91 | __MosquittoContext* mosquittoContext = (__bridge __MosquittoContext*)obj;
92 | mosquittoContext.isConnected = false;
93 | if (mosquittoContext.onDisconnectCallback) {
94 | mosquittoContext.onDisconnectCallback(reasonCode);
95 | }
96 | }
97 |
98 | static void on_publish(struct mosquitto *mosquittoHandler, void *obj, int messageId)
99 | {
100 | __MosquittoContext* mosquittoContext = (__bridge __MosquittoContext*)obj;
101 | if (mosquittoContext.onPublishCallback) {
102 | mosquittoContext.onPublishCallback(messageId);
103 | }
104 | }
105 |
106 | static void on_message(struct mosquitto *mosquittoHandler, void *obj, const struct mosquitto_message *message)
107 | {
108 | __MosquittoContext* mosquittoContext = (__bridge __MosquittoContext*)obj;
109 | if (mosquittoContext.onMessageCallback) {
110 | mosquittoContext.onMessageCallback(message);
111 | }
112 | }
113 |
114 | static void on_subscribe(struct mosquitto *mosquittoHandler, void *obj, int messageId, int qos_count, const int *granted_qos)
115 | {
116 | __MosquittoContext* mosquittoContext = (__bridge __MosquittoContext*)obj;
117 | if (mosquittoContext.onSubscribeCallback) {
118 | mosquittoContext.onSubscribeCallback(messageId, qos_count, granted_qos);
119 | }
120 | }
121 |
122 | static void on_unsubscribe(struct mosquitto *mosquittoHandler, void *obj, int messageId)
123 | {
124 | __MosquittoContext* mosquittoContext = (__bridge __MosquittoContext*)obj;
125 | if (mosquittoContext.onUnsubscribeCallback) {
126 | mosquittoContext.onUnsubscribeCallback(messageId);
127 | }
128 | }
129 |
130 | static void on_log(struct mosquitto *mosquittoHandler, void *obj, int logLevel, const char *logMessage)
131 | {
132 | #ifdef DEBUG
133 | NSLog(@"[MOSQUITTO] %s %s", LogLevelString(logLevel), logMessage);
134 | #endif
135 | }
136 |
137 | static const char *LogLevelString(int logLevel)
138 | {
139 | switch (logLevel) {
140 | case MOSQ_LOG_INFO:
141 | return "INFO ";
142 | case MOSQ_LOG_NOTICE:
143 | return "NOTICE ";
144 | case MOSQ_LOG_WARNING:
145 | return "WARNING";
146 | case MOSQ_LOG_ERR:
147 | return "ERROR ";
148 | case MOSQ_LOG_DEBUG:
149 | return "DEBUG ";
150 | default:
151 | break;
152 | }
153 | return " ";
154 | }
155 |
156 | static void log_d(__MosquittoContext *mosquitto_context, enum mosq_err_t mosq_ret, NSString *log)
157 | {
158 | if(mosq_ret != MOSQ_ERR_SUCCESS) {
159 | on_log(mosquitto_context.mosquittoHandler, (__bridge void *)(mosquitto_context), MOSQ_LOG_DEBUG, [log UTF8String]);
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/mosquitto/lib/read_handle_shared.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #ifdef WITH_BROKER
31 | #include
32 | #endif
33 |
34 | int _mosquitto_handle_pingreq(struct mosquitto *mosq)
35 | {
36 | assert(mosq);
37 | #ifdef WITH_BROKER
38 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PINGREQ from %s", mosq->id);
39 | #else
40 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PINGREQ", mosq->id);
41 | #endif
42 | return _mosquitto_send_pingresp(mosq);
43 | }
44 |
45 | int _mosquitto_handle_pingresp(struct mosquitto *mosq)
46 | {
47 | assert(mosq);
48 | mosq->ping_t = 0; /* No longer waiting for a PINGRESP. */
49 | #ifdef WITH_BROKER
50 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PINGRESP from %s", mosq->id);
51 | #else
52 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PINGRESP", mosq->id);
53 | #endif
54 | return MOSQ_ERR_SUCCESS;
55 | }
56 |
57 | #ifdef WITH_BROKER
58 | int _mosquitto_handle_pubackcomp(struct mosquitto_db *db, struct mosquitto *mosq, const char *type)
59 | #else
60 | int _mosquitto_handle_pubackcomp(struct mosquitto *mosq, const char *type)
61 | #endif
62 | {
63 | uint16_t mid;
64 | int rc;
65 |
66 | assert(mosq);
67 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
68 | if(rc) return rc;
69 | #ifdef WITH_BROKER
70 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received %s from %s (Mid: %d)", type, mosq->id, mid);
71 |
72 | if(mid){
73 | rc = mqtt3_db_message_delete(db, mosq, mid, mosq_md_out);
74 | if(rc) return rc;
75 | }
76 | #else
77 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received %s (Mid: %d)", mosq->id, type, mid);
78 |
79 | if(!_mosquitto_message_delete(mosq, mid, mosq_md_out)){
80 | /* Only inform the client the message has been sent once. */
81 | pthread_mutex_lock(&mosq->callback_mutex);
82 | if(mosq->on_publish){
83 | mosq->in_callback = true;
84 | mosq->on_publish(mosq, mosq->userdata, mid);
85 | mosq->in_callback = false;
86 | }
87 | pthread_mutex_unlock(&mosq->callback_mutex);
88 | }
89 | #endif
90 |
91 | return MOSQ_ERR_SUCCESS;
92 | }
93 |
94 | int _mosquitto_handle_pubrec(struct mosquitto *mosq)
95 | {
96 | uint16_t mid;
97 | int rc;
98 |
99 | assert(mosq);
100 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
101 | if(rc) return rc;
102 | #ifdef WITH_BROKER
103 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREC from %s (Mid: %d)", mosq->id, mid);
104 |
105 | rc = mqtt3_db_message_update(mosq, mid, mosq_md_out, mosq_ms_wait_for_pubcomp);
106 | #else
107 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREC (Mid: %d)", mosq->id, mid);
108 |
109 | rc = _mosquitto_message_out_update(mosq, mid, mosq_ms_wait_for_pubcomp);
110 | #endif
111 | if(rc) return rc;
112 | rc = _mosquitto_send_pubrel(mosq, mid);
113 | if(rc) return rc;
114 |
115 | return MOSQ_ERR_SUCCESS;
116 | }
117 |
118 | int _mosquitto_handle_pubrel(struct mosquitto_db *db, struct mosquitto *mosq)
119 | {
120 | uint16_t mid;
121 | #ifndef WITH_BROKER
122 | struct mosquitto_message_all *message = NULL;
123 | #endif
124 | int rc;
125 |
126 | assert(mosq);
127 | if(mosq->protocol == mosq_p_mqtt311){
128 | if((mosq->in_packet.command&0x0F) != 0x02){
129 | return MOSQ_ERR_PROTOCOL;
130 | }
131 | }
132 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
133 | if(rc) return rc;
134 | #ifdef WITH_BROKER
135 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREL from %s (Mid: %d)", mosq->id, mid);
136 |
137 | if(mqtt3_db_message_release(db, mosq, mid, mosq_md_in)){
138 | /* Message not found. Still send a PUBCOMP anyway because this could be
139 | * due to a repeated PUBREL after a client has reconnected. */
140 | }
141 | #else
142 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREL (Mid: %d)", mosq->id, mid);
143 |
144 | if(!_mosquitto_message_remove(mosq, mid, mosq_md_in, &message)){
145 | /* Only pass the message on if we have removed it from the queue - this
146 | * prevents multiple callbacks for the same message. */
147 | pthread_mutex_lock(&mosq->callback_mutex);
148 | if(mosq->on_message){
149 | mosq->in_callback = true;
150 | mosq->on_message(mosq, mosq->userdata, &message->msg);
151 | mosq->in_callback = false;
152 | }
153 | pthread_mutex_unlock(&mosq->callback_mutex);
154 | _mosquitto_message_cleanup(&message);
155 | }
156 | #endif
157 | rc = _mosquitto_send_pubcomp(mosq, mid);
158 | if(rc) return rc;
159 |
160 | return MOSQ_ERR_SUCCESS;
161 | }
162 |
163 | int _mosquitto_handle_suback(struct mosquitto *mosq)
164 | {
165 | uint16_t mid;
166 | uint8_t qos;
167 | int *granted_qos;
168 | int qos_count;
169 | int i = 0;
170 | int rc;
171 |
172 | assert(mosq);
173 | #ifdef WITH_BROKER
174 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received SUBACK from %s", mosq->id);
175 | #else
176 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received SUBACK", mosq->id);
177 | #endif
178 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
179 | if(rc) return rc;
180 |
181 | qos_count = mosq->in_packet.remaining_length - mosq->in_packet.pos;
182 | granted_qos = _mosquitto_malloc(qos_count*sizeof(int));
183 | if(!granted_qos) return MOSQ_ERR_NOMEM;
184 | while(mosq->in_packet.pos < mosq->in_packet.remaining_length){
185 | rc = _mosquitto_read_byte(&mosq->in_packet, &qos);
186 | if(rc){
187 | _mosquitto_free(granted_qos);
188 | return rc;
189 | }
190 | granted_qos[i] = (int)qos;
191 | i++;
192 | }
193 | #ifndef WITH_BROKER
194 | pthread_mutex_lock(&mosq->callback_mutex);
195 | if(mosq->on_subscribe){
196 | mosq->in_callback = true;
197 | mosq->on_subscribe(mosq, mosq->userdata, mid, qos_count, granted_qos);
198 | mosq->in_callback = false;
199 | }
200 | pthread_mutex_unlock(&mosq->callback_mutex);
201 | #endif
202 | _mosquitto_free(granted_qos);
203 |
204 | return MOSQ_ERR_SUCCESS;
205 | }
206 |
207 | int _mosquitto_handle_unsuback(struct mosquitto *mosq)
208 | {
209 | uint16_t mid;
210 | int rc;
211 |
212 | assert(mosq);
213 | #ifdef WITH_BROKER
214 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received UNSUBACK from %s", mosq->id);
215 | #else
216 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received UNSUBACK", mosq->id);
217 | #endif
218 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
219 | if(rc) return rc;
220 | #ifndef WITH_BROKER
221 | pthread_mutex_lock(&mosq->callback_mutex);
222 | if(mosq->on_unsubscribe){
223 | mosq->in_callback = true;
224 | mosq->on_unsubscribe(mosq, mosq->userdata, mid);
225 | mosq->in_callback = false;
226 | }
227 | pthread_mutex_unlock(&mosq->callback_mutex);
228 | #endif
229 |
230 | return MOSQ_ERR_SUCCESS;
231 | }
232 |
233 |
--------------------------------------------------------------------------------
/mosquitto/lib/mosquitto_internal.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2010-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #ifndef _MOSQUITTO_INTERNAL_H_
18 | #define _MOSQUITTO_INTERNAL_H_
19 |
20 | #include
21 |
22 | #ifdef WIN32
23 | # include
24 | #endif
25 |
26 | #ifdef WITH_TLS
27 | # include
28 | #else
29 | # include
30 | #endif
31 | #include
32 |
33 | #if defined(WITH_THREADING) && !defined(WITH_BROKER)
34 | # include
35 | #else
36 | # include
37 | #endif
38 |
39 | #ifdef WITH_SRV
40 | # include
41 | #endif
42 |
43 | #ifdef WIN32
44 | # if _MSC_VER < 1600
45 | typedef unsigned char uint8_t;
46 | typedef unsigned short uint16_t;
47 | typedef unsigned int uint32_t;
48 | typedef unsigned long long uint64_t;
49 | # else
50 | # include
51 | # endif
52 | #else
53 | # include
54 | #endif
55 |
56 | #include "mosquitto.h"
57 | #include "time_mosq.h"
58 | #ifdef WITH_BROKER
59 | # include "uthash.h"
60 | struct mosquitto_client_msg;
61 | #endif
62 |
63 | #ifdef WIN32
64 | typedef SOCKET mosq_sock_t;
65 | #else
66 | typedef int mosq_sock_t;
67 | #endif
68 |
69 | enum mosquitto_msg_direction {
70 | mosq_md_in = 0,
71 | mosq_md_out = 1
72 | };
73 |
74 | enum mosquitto_msg_state {
75 | mosq_ms_invalid = 0,
76 | mosq_ms_publish_qos0 = 1,
77 | mosq_ms_publish_qos1 = 2,
78 | mosq_ms_wait_for_puback = 3,
79 | mosq_ms_publish_qos2 = 4,
80 | mosq_ms_wait_for_pubrec = 5,
81 | mosq_ms_resend_pubrel = 6,
82 | mosq_ms_wait_for_pubrel = 7,
83 | mosq_ms_resend_pubcomp = 8,
84 | mosq_ms_wait_for_pubcomp = 9,
85 | mosq_ms_send_pubrec = 10,
86 | mosq_ms_queued = 11
87 | };
88 |
89 | enum mosquitto_client_state {
90 | mosq_cs_new = 0,
91 | mosq_cs_connected = 1,
92 | mosq_cs_disconnecting = 2,
93 | mosq_cs_connect_async = 3,
94 | mosq_cs_connect_pending = 4,
95 | mosq_cs_connect_srv = 5,
96 | mosq_cs_disconnect_ws = 6,
97 | mosq_cs_disconnected = 7,
98 | mosq_cs_socks5_new = 8,
99 | mosq_cs_socks5_start = 9,
100 | mosq_cs_socks5_request = 10,
101 | mosq_cs_socks5_reply = 11,
102 | mosq_cs_socks5_auth_ok = 12,
103 | mosq_cs_socks5_userpass_reply = 13,
104 | mosq_cs_socks5_send_userpass = 14,
105 | mosq_cs_expiring = 15,
106 | };
107 |
108 | enum _mosquitto_protocol {
109 | mosq_p_invalid = 0,
110 | mosq_p_mqtt31 = 1,
111 | mosq_p_mqtt311 = 2,
112 | mosq_p_mqtts = 3
113 | };
114 |
115 | enum _mosquitto_transport {
116 | mosq_t_invalid = 0,
117 | mosq_t_tcp = 1,
118 | mosq_t_ws = 2,
119 | mosq_t_sctp = 3
120 | };
121 |
122 | struct _mosquitto_packet{
123 | uint8_t *payload;
124 | struct _mosquitto_packet *next;
125 | uint32_t remaining_mult;
126 | uint32_t remaining_length;
127 | uint32_t packet_length;
128 | uint32_t to_process;
129 | uint32_t pos;
130 | uint16_t mid;
131 | uint8_t command;
132 | int8_t remaining_count;
133 | };
134 |
135 | struct mosquitto_message_all{
136 | struct mosquitto_message_all *next;
137 | time_t timestamp;
138 | //enum mosquitto_msg_direction direction;
139 | enum mosquitto_msg_state state;
140 | bool dup;
141 | struct mosquitto_message msg;
142 | };
143 |
144 | struct mosquitto {
145 | mosq_sock_t sock;
146 | #ifndef WITH_BROKER
147 | mosq_sock_t sockpairR, sockpairW;
148 | #endif
149 | enum _mosquitto_protocol protocol;
150 | char *address;
151 | char *id;
152 | char *username;
153 | char *password;
154 | uint16_t keepalive;
155 | uint16_t last_mid;
156 | enum mosquitto_client_state state;
157 | time_t last_msg_in;
158 | time_t last_msg_out;
159 | time_t ping_t;
160 | struct _mosquitto_packet in_packet;
161 | struct _mosquitto_packet *current_out_packet;
162 | struct _mosquitto_packet *out_packet;
163 | struct mosquitto_message *will;
164 | #ifdef WITH_TLS
165 | SSL *ssl;
166 | SSL_CTX *ssl_ctx;
167 | char *tls_cafile;
168 | char *tls_capath;
169 | char *tls_certfile;
170 | char *tls_keyfile;
171 | int (*tls_pw_callback)(char *buf, int size, int rwflag, void *userdata);
172 | char *tls_version;
173 | char *tls_ciphers;
174 | char *tls_psk;
175 | char *tls_psk_identity;
176 | int tls_cert_reqs;
177 | bool tls_insecure;
178 | #endif
179 | bool want_write;
180 | bool want_connect;
181 | #if defined(WITH_THREADING) && !defined(WITH_BROKER)
182 | pthread_mutex_t callback_mutex;
183 | pthread_mutex_t log_callback_mutex;
184 | pthread_mutex_t msgtime_mutex;
185 | pthread_mutex_t out_packet_mutex;
186 | pthread_mutex_t current_out_packet_mutex;
187 | pthread_mutex_t state_mutex;
188 | pthread_mutex_t in_message_mutex;
189 | pthread_mutex_t out_message_mutex;
190 | pthread_mutex_t mid_mutex;
191 | pthread_t thread_id;
192 | #endif
193 | bool clean_session;
194 | #ifdef WITH_BROKER
195 | bool is_dropping;
196 | bool is_bridge;
197 | struct _mqtt3_bridge *bridge;
198 | struct mosquitto_client_msg *msgs;
199 | struct mosquitto_client_msg *last_msg;
200 | int msg_count;
201 | int msg_count12;
202 | struct _mosquitto_acl_user *acl_list;
203 | struct _mqtt3_listener *listener;
204 | time_t disconnect_t;
205 | struct _mosquitto_packet *out_packet_last;
206 | struct _mosquitto_subhier **subs;
207 | int sub_count;
208 | int pollfd_index;
209 | # ifdef WITH_WEBSOCKETS
210 | # if defined(LWS_LIBRARY_VERSION_NUMBER)
211 | struct lws *wsi;
212 | # else
213 | struct libwebsocket_context *ws_context;
214 | struct libwebsocket *wsi;
215 | # endif
216 | # endif
217 | #else
218 | # ifdef WITH_SOCKS
219 | char *socks5_host;
220 | int socks5_port;
221 | char *socks5_username;
222 | char *socks5_password;
223 | # endif
224 | void *userdata;
225 | bool in_callback;
226 | unsigned int message_retry;
227 | time_t last_retry_check;
228 | struct mosquitto_message_all *in_messages;
229 | struct mosquitto_message_all *in_messages_last;
230 | struct mosquitto_message_all *out_messages;
231 | struct mosquitto_message_all *out_messages_last;
232 | void (*on_connect)(struct mosquitto *, void *userdata, int rc);
233 | void (*on_disconnect)(struct mosquitto *, void *userdata, int rc);
234 | void (*on_publish)(struct mosquitto *, void *userdata, int mid);
235 | void (*on_message)(struct mosquitto *, void *userdata, const struct mosquitto_message *message);
236 | void (*on_subscribe)(struct mosquitto *, void *userdata, int mid, int qos_count, const int *granted_qos);
237 | void (*on_unsubscribe)(struct mosquitto *, void *userdata, int mid);
238 | void (*on_log)(struct mosquitto *, void *userdata, int level, const char *str);
239 | //void (*on_error)();
240 | char *host;
241 | int port;
242 | int in_queue_len;
243 | int out_queue_len;
244 | char *bind_address;
245 | unsigned int reconnect_delay;
246 | unsigned int reconnect_delay_max;
247 | bool reconnect_exponential_backoff;
248 | bool reconnect_enabled;
249 | bool threaded;
250 | struct _mosquitto_packet *out_packet_last;
251 | int inflight_messages;
252 | int max_inflight_messages;
253 | # ifdef WITH_SRV
254 | ares_channel achan;
255 | # endif
256 | #endif
257 |
258 | #ifdef WITH_BROKER
259 | UT_hash_handle hh_id;
260 | UT_hash_handle hh_sock;
261 | struct mosquitto *for_free_next;
262 | #endif
263 | };
264 |
265 | #define STREMPTY(str) (str[0] == '\0')
266 |
267 | #endif
268 |
--------------------------------------------------------------------------------
/mosquitto/lib/send_client_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #ifdef WITH_BROKER
29 | #include
30 | #endif
31 |
32 | int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session)
33 | {
34 | struct _mosquitto_packet *packet = NULL;
35 | int payloadlen;
36 | uint8_t will = 0;
37 | uint8_t byte;
38 | int rc;
39 | uint8_t version;
40 | char *clientid, *username, *password;
41 | int headerlen;
42 |
43 | assert(mosq);
44 | assert(mosq->id);
45 |
46 | #if defined(WITH_BROKER) && defined(WITH_BRIDGE)
47 | if(mosq->bridge){
48 | clientid = mosq->bridge->remote_clientid;
49 | username = mosq->bridge->remote_username;
50 | password = mosq->bridge->remote_password;
51 | }else{
52 | clientid = mosq->id;
53 | username = mosq->username;
54 | password = mosq->password;
55 | }
56 | #else
57 | clientid = mosq->id;
58 | username = mosq->username;
59 | password = mosq->password;
60 | #endif
61 |
62 | if(mosq->protocol == mosq_p_mqtt31){
63 | version = MQTT_PROTOCOL_V31;
64 | headerlen = 12;
65 | }else if(mosq->protocol == mosq_p_mqtt311){
66 | version = MQTT_PROTOCOL_V311;
67 | headerlen = 10;
68 | }else{
69 | return MOSQ_ERR_INVAL;
70 | }
71 |
72 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
73 | if(!packet) return MOSQ_ERR_NOMEM;
74 |
75 | payloadlen = (int)(2+strlen(clientid));
76 | if(mosq->will){
77 | will = 1;
78 | assert(mosq->will->topic);
79 |
80 | payloadlen += 2+strlen(mosq->will->topic) + 2+mosq->will->payloadlen;
81 | }
82 | if(username){
83 | payloadlen += 2+strlen(username);
84 | if(password){
85 | payloadlen += 2+strlen(password);
86 | }
87 | }
88 |
89 | packet->command = CONNECT;
90 | packet->remaining_length = headerlen+payloadlen;
91 | rc = _mosquitto_packet_alloc(packet);
92 | if(rc){
93 | _mosquitto_free(packet);
94 | return rc;
95 | }
96 |
97 | /* Variable header */
98 | if(version == MQTT_PROTOCOL_V31){
99 | _mosquitto_write_string(packet, PROTOCOL_NAME_v31, strlen(PROTOCOL_NAME_v31));
100 | }else if(version == MQTT_PROTOCOL_V311){
101 | _mosquitto_write_string(packet, PROTOCOL_NAME_v311, strlen(PROTOCOL_NAME_v311));
102 | }
103 | #if defined(WITH_BROKER) && defined(WITH_BRIDGE)
104 | if(mosq->bridge && mosq->bridge->try_private && mosq->bridge->try_private_accepted){
105 | version |= 0x80;
106 | }else{
107 | }
108 | #endif
109 | _mosquitto_write_byte(packet, version);
110 | byte = (clean_session&0x1)<<1;
111 | if(will){
112 | byte = byte | ((mosq->will->retain&0x1)<<5) | ((mosq->will->qos&0x3)<<3) | ((will&0x1)<<2);
113 | }
114 | if(username){
115 | byte = byte | 0x1<<7;
116 | if(mosq->password){
117 | byte = byte | 0x1<<6;
118 | }
119 | }
120 | _mosquitto_write_byte(packet, byte);
121 | _mosquitto_write_uint16(packet, keepalive);
122 |
123 | /* Payload */
124 | _mosquitto_write_string(packet, clientid, strlen(clientid));
125 | if(will){
126 | _mosquitto_write_string(packet, mosq->will->topic, strlen(mosq->will->topic));
127 | _mosquitto_write_string(packet, (const char *)mosq->will->payload, mosq->will->payloadlen);
128 | }
129 | if(username){
130 | _mosquitto_write_string(packet, username, strlen(username));
131 | if(password){
132 | _mosquitto_write_string(packet, password, strlen(password));
133 | }
134 | }
135 |
136 | mosq->keepalive = keepalive;
137 | #ifdef WITH_BROKER
138 | # ifdef WITH_BRIDGE
139 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending CONNECT", clientid);
140 | # endif
141 | #else
142 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending CONNECT", clientid);
143 | #endif
144 | return _mosquitto_packet_queue(mosq, packet);
145 | }
146 |
147 | int _mosquitto_send_disconnect(struct mosquitto *mosq)
148 | {
149 | assert(mosq);
150 | #ifdef WITH_BROKER
151 | # ifdef WITH_BRIDGE
152 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending DISCONNECT", mosq->id);
153 | # endif
154 | #else
155 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending DISCONNECT", mosq->id);
156 | #endif
157 | return _mosquitto_send_simple_command(mosq, DISCONNECT);
158 | }
159 |
160 | int _mosquitto_send_subscribe(struct mosquitto *mosq, int *mid, const char *topic, uint8_t topic_qos)
161 | {
162 | /* FIXME - only deals with a single topic */
163 | struct _mosquitto_packet *packet = NULL;
164 | uint32_t packetlen;
165 | uint16_t local_mid;
166 | int rc;
167 |
168 | assert(mosq);
169 | assert(topic);
170 |
171 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
172 | if(!packet) return MOSQ_ERR_NOMEM;
173 |
174 | packetlen = 2 + 2+strlen(topic) + 1;
175 |
176 | packet->command = SUBSCRIBE | (1<<1);
177 | packet->remaining_length = packetlen;
178 | rc = _mosquitto_packet_alloc(packet);
179 | if(rc){
180 | _mosquitto_free(packet);
181 | return rc;
182 | }
183 |
184 | /* Variable header */
185 | local_mid = _mosquitto_mid_generate(mosq);
186 | if(mid) *mid = (int)local_mid;
187 | _mosquitto_write_uint16(packet, local_mid);
188 |
189 | /* Payload */
190 | _mosquitto_write_string(packet, topic, strlen(topic));
191 | _mosquitto_write_byte(packet, topic_qos);
192 |
193 | #ifdef WITH_BROKER
194 | # ifdef WITH_BRIDGE
195 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d)", mosq->id, local_mid, topic, topic_qos);
196 | # endif
197 | #else
198 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d)", mosq->id, local_mid, topic, topic_qos);
199 | #endif
200 |
201 | return _mosquitto_packet_queue(mosq, packet);
202 | }
203 |
204 |
205 | int _mosquitto_send_unsubscribe(struct mosquitto *mosq, int *mid, const char *topic)
206 | {
207 | /* FIXME - only deals with a single topic */
208 | struct _mosquitto_packet *packet = NULL;
209 | uint32_t packetlen;
210 | uint16_t local_mid;
211 | int rc;
212 |
213 | assert(mosq);
214 | assert(topic);
215 |
216 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
217 | if(!packet) return MOSQ_ERR_NOMEM;
218 |
219 | packetlen = 2 + 2+strlen(topic);
220 |
221 | packet->command = UNSUBSCRIBE | (1<<1);
222 | packet->remaining_length = packetlen;
223 | rc = _mosquitto_packet_alloc(packet);
224 | if(rc){
225 | _mosquitto_free(packet);
226 | return rc;
227 | }
228 |
229 | /* Variable header */
230 | local_mid = _mosquitto_mid_generate(mosq);
231 | if(mid) *mid = (int)local_mid;
232 | _mosquitto_write_uint16(packet, local_mid);
233 |
234 | /* Payload */
235 | _mosquitto_write_string(packet, topic, strlen(topic));
236 |
237 | #ifdef WITH_BROKER
238 | # ifdef WITH_BRIDGE
239 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending UNSUBSCRIBE (Mid: %d, Topic: %s)", mosq->id, local_mid, topic);
240 | # endif
241 | #else
242 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending UNSUBSCRIBE (Mid: %d, Topic: %s)", mosq->id, local_mid, topic);
243 | #endif
244 | return _mosquitto_packet_queue(mosq, packet);
245 | }
246 |
247 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Moscapsule
2 | ==========
3 |
4 | MQTT Client for iOS written in Swift.
5 | This framework is implemented as a wrapper of Mosquitto library and covers almost all mosquitto features.
6 | It uses Mosquitto version 1.4.8.
7 |
8 | Mosquitto
9 | ---------
10 | [Mosquitto](http://mosquitto.org/ "Mosquitto") is an open source message broker that implements the MQ Telemetry Transport protocol versions 3.1 and 3.1.1.
11 | MQTT provides a lightweight method of carrying out messaging using a publish/subscribe model.
12 | Mosquitto is written in C language.
13 |
14 | Installation
15 | ------------
16 |
17 | ### CocoaPods
18 | [CocoaPods](http://cocoapods.org) is a Cocoa project manager. It is a easy way for to install framework, so I recommend to using it.
19 | Create your project on Xcode and specify it in your podfile;
20 | ```ruby
21 | target 'MyApp' do
22 | use_frameworks!
23 |
24 | project 'MyApp.xcodeproj'
25 | platform :ios, '9.0'
26 |
27 | pod 'Moscapsule', :git => 'https://github.com/flightonary/Moscapsule.git'
28 | pod 'OpenSSL-Universal'
29 |
30 | target 'MyAppTests' do
31 | inherit! :search_paths
32 | end
33 |
34 | target 'MyAppUITests' do
35 | inherit! :search_paths
36 | end
37 | end
38 | ```
39 |
40 | and then run;
41 | ```
42 | $ pod install
43 | ```
44 |
45 | Also you can specify old swift version in the podfile, such as the following;
46 | ```ruby
47 | pod 'Moscapsule', :git => 'https://github.com/flightonary/Moscapsule.git', :branch => 'swift2'
48 | ```
49 |
50 | In order to import the framework in tests, you should select configuration files.
51 | a) Select your project and `info`.
52 | b) Change configuration files from none to Pods.debug/release.
53 | 
54 |
55 | ### Manual Installation
56 | If you don't want to use CocoaPods, you can install manually.
57 |
58 | a) Check out Moscapsule.
59 | ```
60 | $ git clone https://github.com/flightonary/Moscapsule.git
61 | ```
62 | b) The framework depends on [OpenSSL](https://github.com/krzyzanowskim/OpenSSL "OpenSSL"). Before building it, you must checkout the submodule.
63 | ```
64 | $ git submodule update --init
65 | ```
66 | c) Create a Xcode project and Workspace if you don't have these.
67 | d) Open workspace and drag & drop your project and Moscapsule.xcodeproj into Navigation.
68 | e) Drag & drop Moscapsule.xcodeproj under your project tree in Navitaion.
69 | f) Select your project and `Build Phases`.
70 | g) Add Moscapsule in `Target Dependencies` and `Link Binary With Libraries` using `+` button.
71 |
72 | 
73 |
74 |
75 | Quick Start
76 | -----
77 | Here is a basic sample.
78 | ```swift
79 | import Moscapsule
80 |
81 | // set MQTT Client Configuration
82 | let mqttConfig = MQTTConfig(clientId: "cid", host: "test.mosquitto.org", port: 1883, keepAlive: 60)
83 | mqttConfig.onConnectCallback = { returnCode in
84 | NSLog("Return Code is \(returnCode.description)")
85 | }
86 | mqttConfig.onMessageCallback = { mqttMessage in
87 | NSLog("MQTT Message received: payload=\(mqttMessage.payloadString)")
88 | }
89 |
90 | // create new MQTT Connection
91 | let mqttClient = MQTT.newConnection(mqttConfig)
92 |
93 | // publish and subscribe
94 | mqttClient.publishString("message", topic: "publish/topic", qos: 2, retain: false)
95 | mqttClient.subscribe("subscribe/topic", qos: 2)
96 |
97 | // disconnect
98 | mqttClient.disconnect()
99 | ```
100 |
101 | The framework supports TLS_PSK, Server and/or Client certification.
102 | Here is a sample for server certificate.
103 | ```swift
104 | import Moscapsule
105 |
106 | // Note that you must initialize framework only once after launch application
107 | // in case that it uses SSL/TLS functions.
108 | moscapsule_init()
109 |
110 | let mqttConfig = MQTTConfig(clientId: "server_cert_test", host: "test.mosquitto.org", port: 8883, keepAlive: 60)
111 |
112 | let bundlePath = NSBundle(forClass: self.dynamicType).bundlePath.stringByAppendingPathComponent("cert.bundle")
113 | let certFile = bundlePath.stringByAppendingPathComponent("mosquitto.org.crt")
114 |
115 | mqttConfig.mqttServerCert = MQTTServerCert(cafile: certFile, capath: nil)
116 |
117 | let mqttClient = MQTT.newConnection(mqttConfig)
118 | ```
119 |
120 | Reference
121 | -------
122 | #### Controlling Connections
123 | Create new connection;
124 | ```swift
125 | // create MQTT Client Configuration with mandatory prameters
126 | let mqttConfig = MQTTConfig(clientId: "cid", host: "test.mosquitto.org", port: 1883, keepAlive: 60)
127 | // create new MQTT Connection
128 | let mqttClient = MQTT.newConnection(mqttConfig)
129 | ```
130 | As soon as MQTTClient instance is created client attempt to connect to the host. It can be delayed by setting connectImmediately to false.
131 | ```swift
132 | let mqttClient = MQTT.newConnection(mqttConfig, connectImmediately = false)
133 | mqttClient.connectTo(host: "test.mosquitto.org", port: 1883, keepAlive: 60)
134 | ```
135 |
136 | Diconnect the connection;
137 | ```swift
138 | mqttClient.disconnect()
139 | ```
140 |
141 | Reconnect to the same host;
142 | ```swift
143 | mqttClient.reconnect()
144 | ```
145 |
146 | #### Messaging
147 |
148 | Publish a string to MQTT broker;
149 | ```swift
150 | let msg = "message"
151 | mqttClient.publish(string: msg, topic: topic, qos: 2, retain: false)
152 | ```
153 |
154 | Publish a data to MQTT broker;
155 | ```swift
156 | let data = Data(bytes: [0x00, 0x01, 0x00, 0x00])
157 | mqttClient.publish(data, topic: topic, qos: 2, retain: false)
158 | ```
159 |
160 | Subscribe a topic on MQTT broker;
161 | ```swift
162 | mqttClient.subscribe("/path/to/topic", qos: 2)
163 | ```
164 | Messages on subscribed topic can be received in callback as mentioned below.
165 |
166 | Unsubscribe a topic;
167 | ```swift
168 | mqttClient.unsubscribe("/path/to/topic")
169 | ```
170 |
171 | #### Callbacks
172 | Callback for result of attempting to connect;
173 | ```swift
174 | mqttConfig.onConnectCallback = { returnCode in
175 | if returnCode == ReturnCode.success {
176 | // something to do in case of successful connection
177 | }
178 | else {
179 | // error handling for connection failure
180 | }
181 | }
182 | ```
183 |
184 | Callback which is called when a client disconnected;
185 | ```swift
186 | mqttConfig.onDisconnectCallback = { reasonCode in
187 | if reasonCode == ReasonCode.disconnect_requested {
188 | // successful disconnection you requested
189 | } else if ... {
190 | // other cases such as unexpected disconnection.
191 | }
192 | }
193 | ```
194 |
195 | Callback which is called when a client published successfuly;
196 | ```swift
197 | mqttConfig.onPublishCallback = { messageId in
198 | // successful publish
199 | }
200 | ```
201 |
202 | Callback which is called when a client received message successfuly;
203 | ```swift
204 | mqttConfig.onMessageCallback = { mqttMessage in
205 | if mqttMessage.topic == "/path/to/subscribed/topic" {
206 | NSLog("MQTT Message received: payload=\(mqttMessage.payloadString)")
207 | } else if ... {
208 | // something to do in case of other topics
209 | }
210 | }
211 | ```
212 |
213 | Callback which is called when a client subscrived topic successfuly;
214 | ```swift
215 | mqttConfig.onSubscribeCallback = { (messageId, grantedQos) in
216 | NSLog("subscribed (mid=\(messageId),grantedQos=\(grantedQos))")
217 | }
218 | ```
219 |
220 | Callback which is called when a client unsubscrived topic successfuly;
221 | ```swift
222 | mqttConfig.onSubscribeCallback = { messageId in
223 | NSLog("unsubscribed (mid=\(messageId)")
224 | }
225 | ```
226 |
227 | #### Connection Options
228 | T.B.D.
229 |
230 |
231 | License
232 | -------
233 | Moscapsule: The MIT License (MIT)
234 | Mosquitto: EPL/EDL license
235 |
236 | Author
237 | ------
238 | tonary <>
239 |
--------------------------------------------------------------------------------
/mosquitto/lib/util_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 | #include
19 |
20 | #ifdef WIN32
21 | #include
22 | #endif
23 |
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #ifdef WITH_BROKER
34 | #include
35 | #endif
36 |
37 | #ifdef WITH_WEBSOCKETS
38 | #include
39 | #endif
40 |
41 | int _mosquitto_packet_alloc(struct _mosquitto_packet *packet)
42 | {
43 | uint8_t remaining_bytes[5], byte;
44 | uint32_t remaining_length;
45 | int i;
46 |
47 | assert(packet);
48 |
49 | remaining_length = packet->remaining_length;
50 | packet->payload = NULL;
51 | packet->remaining_count = 0;
52 | do{
53 | byte = remaining_length % 128;
54 | remaining_length = remaining_length / 128;
55 | /* If there are more digits to encode, set the top bit of this digit */
56 | if(remaining_length > 0){
57 | byte = byte | 0x80;
58 | }
59 | remaining_bytes[packet->remaining_count] = byte;
60 | packet->remaining_count++;
61 | }while(remaining_length > 0 && packet->remaining_count < 5);
62 | if(packet->remaining_count == 5) return MOSQ_ERR_PAYLOAD_SIZE;
63 | packet->packet_length = packet->remaining_length + 1 + packet->remaining_count;
64 | #ifdef WITH_WEBSOCKETS
65 | packet->payload = _mosquitto_malloc(sizeof(uint8_t)*packet->packet_length + LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING);
66 | #else
67 | packet->payload = _mosquitto_malloc(sizeof(uint8_t)*packet->packet_length);
68 | #endif
69 | if(!packet->payload) return MOSQ_ERR_NOMEM;
70 |
71 | packet->payload[0] = packet->command;
72 | for(i=0; iremaining_count; i++){
73 | packet->payload[i+1] = remaining_bytes[i];
74 | }
75 | packet->pos = 1 + packet->remaining_count;
76 |
77 | return MOSQ_ERR_SUCCESS;
78 | }
79 |
80 | #ifdef WITH_BROKER
81 | void _mosquitto_check_keepalive(struct mosquitto_db *db, struct mosquitto *mosq)
82 | #else
83 | void _mosquitto_check_keepalive(struct mosquitto *mosq)
84 | #endif
85 | {
86 | time_t last_msg_out;
87 | time_t last_msg_in;
88 | time_t now = mosquitto_time();
89 | #ifndef WITH_BROKER
90 | int rc;
91 | #endif
92 |
93 | assert(mosq);
94 | #if defined(WITH_BROKER) && defined(WITH_BRIDGE)
95 | /* Check if a lazy bridge should be timed out due to idle. */
96 | if(mosq->bridge && mosq->bridge->start_type == bst_lazy
97 | && mosq->sock != INVALID_SOCKET
98 | && now - mosq->last_msg_out >= mosq->bridge->idle_timeout){
99 |
100 | _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Bridge connection %s has exceeded idle timeout, disconnecting.", mosq->id);
101 | _mosquitto_socket_close(db, mosq);
102 | return;
103 | }
104 | #endif
105 | pthread_mutex_lock(&mosq->msgtime_mutex);
106 | last_msg_out = mosq->last_msg_out;
107 | last_msg_in = mosq->last_msg_in;
108 | pthread_mutex_unlock(&mosq->msgtime_mutex);
109 | if(mosq->keepalive && mosq->sock != INVALID_SOCKET &&
110 | (now - last_msg_out >= mosq->keepalive || now - last_msg_in >= mosq->keepalive)){
111 |
112 | if(mosq->state == mosq_cs_connected && mosq->ping_t == 0){
113 | _mosquitto_send_pingreq(mosq);
114 | /* Reset last msg times to give the server time to send a pingresp */
115 | pthread_mutex_lock(&mosq->msgtime_mutex);
116 | mosq->last_msg_in = now;
117 | mosq->last_msg_out = now;
118 | pthread_mutex_unlock(&mosq->msgtime_mutex);
119 | }else{
120 | #ifdef WITH_BROKER
121 | if(mosq->listener){
122 | mosq->listener->client_count--;
123 | assert(mosq->listener->client_count >= 0);
124 | }
125 | mosq->listener = NULL;
126 | _mosquitto_socket_close(db, mosq);
127 | #else
128 | _mosquitto_socket_close(mosq);
129 | pthread_mutex_lock(&mosq->state_mutex);
130 | if(mosq->state == mosq_cs_disconnecting){
131 | rc = MOSQ_ERR_SUCCESS;
132 | }else{
133 | rc = 1;
134 | }
135 | pthread_mutex_unlock(&mosq->state_mutex);
136 | pthread_mutex_lock(&mosq->callback_mutex);
137 | if(mosq->on_disconnect){
138 | mosq->in_callback = true;
139 | mosq->on_disconnect(mosq, mosq->userdata, rc);
140 | mosq->in_callback = false;
141 | }
142 | pthread_mutex_unlock(&mosq->callback_mutex);
143 | #endif
144 | }
145 | }
146 | }
147 |
148 | uint16_t _mosquitto_mid_generate(struct mosquitto *mosq)
149 | {
150 | /* FIXME - this would be better with atomic increment, but this is safer
151 | * for now for a bug fix release.
152 | *
153 | * If this is changed to use atomic increment, callers of this function
154 | * will have to be aware that they may receive a 0 result, which may not be
155 | * used as a mid.
156 | */
157 | uint16_t mid;
158 | assert(mosq);
159 |
160 | pthread_mutex_lock(&mosq->mid_mutex);
161 | mosq->last_mid++;
162 | if(mosq->last_mid == 0) mosq->last_mid++;
163 | mid = mosq->last_mid;
164 | pthread_mutex_unlock(&mosq->mid_mutex);
165 |
166 | return mid;
167 | }
168 |
169 | /* Check that a topic used for publishing is valid.
170 | * Search for + or # in a topic. Return MOSQ_ERR_INVAL if found.
171 | * Also returns MOSQ_ERR_INVAL if the topic string is too long.
172 | * Returns MOSQ_ERR_SUCCESS if everything is fine.
173 | */
174 | int mosquitto_pub_topic_check(const char *str)
175 | {
176 | int len = 0;
177 | while(str && str[0]){
178 | if(str[0] == '+' || str[0] == '#'){
179 | return MOSQ_ERR_INVAL;
180 | }
181 | len++;
182 | str = &str[1];
183 | }
184 | if(len > 65535) return MOSQ_ERR_INVAL;
185 |
186 | return MOSQ_ERR_SUCCESS;
187 | }
188 |
189 | /* Check that a topic used for subscriptions is valid.
190 | * Search for + or # in a topic, check they aren't in invalid positions such as
191 | * foo/#/bar, foo/+bar or foo/bar#.
192 | * Return MOSQ_ERR_INVAL if invalid position found.
193 | * Also returns MOSQ_ERR_INVAL if the topic string is too long.
194 | * Returns MOSQ_ERR_SUCCESS if everything is fine.
195 | */
196 | int mosquitto_sub_topic_check(const char *str)
197 | {
198 | char c = '\0';
199 | int len = 0;
200 | while(str && str[0]){
201 | if(str[0] == '+'){
202 | if((c != '\0' && c != '/') || (str[1] != '\0' && str[1] != '/')){
203 | return MOSQ_ERR_INVAL;
204 | }
205 | }else if(str[0] == '#'){
206 | if((c != '\0' && c != '/') || str[1] != '\0'){
207 | return MOSQ_ERR_INVAL;
208 | }
209 | }
210 | len++;
211 | c = str[0];
212 | str = &str[1];
213 | }
214 | if(len > 65535) return MOSQ_ERR_INVAL;
215 |
216 | return MOSQ_ERR_SUCCESS;
217 | }
218 |
219 | /* Does a topic match a subscription? */
220 | int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)
221 | {
222 | int slen, tlen;
223 | int spos, tpos;
224 | bool multilevel_wildcard = false;
225 |
226 | if(!sub || !topic || !result) return MOSQ_ERR_INVAL;
227 |
228 | slen = (int)strlen(sub);
229 | tlen = (int)strlen(topic);
230 |
231 | if(slen && tlen){
232 | if((sub[0] == '$' && topic[0] != '$')
233 | || (topic[0] == '$' && sub[0] != '$')){
234 |
235 | *result = false;
236 | return MOSQ_ERR_SUCCESS;
237 | }
238 | }
239 |
240 | spos = 0;
241 | tpos = 0;
242 |
243 | while(spos < slen && tpos < tlen){
244 | if(sub[spos] == topic[tpos]){
245 | if(tpos == tlen-1){
246 | /* Check for e.g. foo matching foo/# */
247 | if(spos == slen-3
248 | && sub[spos+1] == '/'
249 | && sub[spos+2] == '#'){
250 | *result = true;
251 | multilevel_wildcard = true;
252 | return MOSQ_ERR_SUCCESS;
253 | }
254 | }
255 | spos++;
256 | tpos++;
257 | if(spos == slen && tpos == tlen){
258 | *result = true;
259 | return MOSQ_ERR_SUCCESS;
260 | }else if(tpos == tlen && spos == slen-1 && sub[spos] == '+'){
261 | spos++;
262 | *result = true;
263 | return MOSQ_ERR_SUCCESS;
264 | }
265 | }else{
266 | if(sub[spos] == '+'){
267 | spos++;
268 | while(tpos < tlen && topic[tpos] != '/'){
269 | tpos++;
270 | }
271 | if(tpos == tlen && spos == slen){
272 | *result = true;
273 | return MOSQ_ERR_SUCCESS;
274 | }
275 | }else if(sub[spos] == '#'){
276 | multilevel_wildcard = true;
277 | if(spos+1 != slen){
278 | *result = false;
279 | return MOSQ_ERR_SUCCESS;
280 | }else{
281 | *result = true;
282 | return MOSQ_ERR_SUCCESS;
283 | }
284 | }else{
285 | *result = false;
286 | return MOSQ_ERR_SUCCESS;
287 | }
288 | }
289 | }
290 | if(multilevel_wildcard == false && (tpos < tlen || spos < slen)){
291 | *result = false;
292 | }
293 |
294 | return MOSQ_ERR_SUCCESS;
295 | }
296 |
297 | #ifdef REAL_WITH_TLS_PSK
298 | int _mosquitto_hex2bin(const char *hex, unsigned char *bin, int bin_max_len)
299 | {
300 | BIGNUM *bn = NULL;
301 | int len;
302 |
303 | if(BN_hex2bn(&bn, hex) == 0){
304 | if(bn) BN_free(bn);
305 | return 0;
306 | }
307 | if(BN_num_bytes(bn) > bin_max_len){
308 | BN_free(bn);
309 | return 0;
310 | }
311 |
312 | len = BN_bn2bin(bn, bin);
313 | BN_free(bn);
314 | return len;
315 | }
316 | #endif
317 |
318 | FILE *_mosquitto_fopen(const char *path, const char *mode)
319 | {
320 | #ifdef WIN32
321 | char buf[4096];
322 | int rc;
323 | rc = ExpandEnvironmentStrings(path, buf, 4096);
324 | if(rc == 0 || rc > 4096){
325 | return NULL;
326 | }else{
327 | return fopen(buf, mode);
328 | }
329 | #else
330 | return fopen(path, mode);
331 | #endif
332 | }
333 |
334 |
--------------------------------------------------------------------------------
/mosquitto/lib/send_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2009-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 |
31 | #ifdef WITH_BROKER
32 | #include
33 | # ifdef WITH_SYS_TREE
34 | extern uint64_t g_pub_bytes_sent;
35 | # endif
36 | #endif
37 |
38 | int _mosquitto_send_pingreq(struct mosquitto *mosq)
39 | {
40 | int rc;
41 | assert(mosq);
42 | #ifdef WITH_BROKER
43 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGREQ to %s", mosq->id);
44 | #else
45 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGREQ", mosq->id);
46 | #endif
47 | rc = _mosquitto_send_simple_command(mosq, PINGREQ);
48 | if(rc == MOSQ_ERR_SUCCESS){
49 | mosq->ping_t = mosquitto_time();
50 | }
51 | return rc;
52 | }
53 |
54 | int _mosquitto_send_pingresp(struct mosquitto *mosq)
55 | {
56 | #ifdef WITH_BROKER
57 | if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGRESP to %s", mosq->id);
58 | #else
59 | if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGRESP", mosq->id);
60 | #endif
61 | return _mosquitto_send_simple_command(mosq, PINGRESP);
62 | }
63 |
64 | int _mosquitto_send_puback(struct mosquitto *mosq, uint16_t mid)
65 | {
66 | #ifdef WITH_BROKER
67 | if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBACK to %s (Mid: %d)", mosq->id, mid);
68 | #else
69 | if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBACK (Mid: %d)", mosq->id, mid);
70 | #endif
71 | return _mosquitto_send_command_with_mid(mosq, PUBACK, mid, false);
72 | }
73 |
74 | int _mosquitto_send_pubcomp(struct mosquitto *mosq, uint16_t mid)
75 | {
76 | #ifdef WITH_BROKER
77 | if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBCOMP to %s (Mid: %d)", mosq->id, mid);
78 | #else
79 | if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBCOMP (Mid: %d)", mosq->id, mid);
80 | #endif
81 | return _mosquitto_send_command_with_mid(mosq, PUBCOMP, mid, false);
82 | }
83 |
84 | int _mosquitto_send_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup)
85 | {
86 | #ifdef WITH_BROKER
87 | size_t len;
88 | #ifdef WITH_BRIDGE
89 | int i;
90 | struct _mqtt3_bridge_topic *cur_topic;
91 | bool match;
92 | int rc;
93 | char *mapped_topic = NULL;
94 | char *topic_temp = NULL;
95 | #endif
96 | #endif
97 | assert(mosq);
98 | assert(topic);
99 |
100 | #if defined(WITH_BROKER) && defined(WITH_WEBSOCKETS)
101 | if(mosq->sock == INVALID_SOCKET && !mosq->wsi) return MOSQ_ERR_NO_CONN;
102 | #else
103 | if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
104 | #endif
105 |
106 | #ifdef WITH_BROKER
107 | if(mosq->listener && mosq->listener->mount_point){
108 | len = strlen(mosq->listener->mount_point);
109 | if(len < strlen(topic)){
110 | topic += len;
111 | }else{
112 | /* Invalid topic string. Should never happen, but silently swallow the message anyway. */
113 | return MOSQ_ERR_SUCCESS;
114 | }
115 | }
116 | #ifdef WITH_BRIDGE
117 | if(mosq->bridge && mosq->bridge->topics && mosq->bridge->topic_remapping){
118 | for(i=0; ibridge->topic_count; i++){
119 | cur_topic = &mosq->bridge->topics[i];
120 | if((cur_topic->direction == bd_both || cur_topic->direction == bd_out)
121 | && (cur_topic->remote_prefix || cur_topic->local_prefix)){
122 | /* Topic mapping required on this topic if the message matches */
123 |
124 | rc = mosquitto_topic_matches_sub(cur_topic->local_topic, topic, &match);
125 | if(rc){
126 | return rc;
127 | }
128 | if(match){
129 | mapped_topic = _mosquitto_strdup(topic);
130 | if(!mapped_topic) return MOSQ_ERR_NOMEM;
131 | if(cur_topic->local_prefix){
132 | /* This prefix needs removing. */
133 | if(!strncmp(cur_topic->local_prefix, mapped_topic, strlen(cur_topic->local_prefix))){
134 | topic_temp = _mosquitto_strdup(mapped_topic+strlen(cur_topic->local_prefix));
135 | _mosquitto_free(mapped_topic);
136 | if(!topic_temp){
137 | return MOSQ_ERR_NOMEM;
138 | }
139 | mapped_topic = topic_temp;
140 | }
141 | }
142 |
143 | if(cur_topic->remote_prefix){
144 | /* This prefix needs adding. */
145 | len = strlen(mapped_topic) + strlen(cur_topic->remote_prefix)+1;
146 | topic_temp = _mosquitto_malloc(len+1);
147 | if(!topic_temp){
148 | _mosquitto_free(mapped_topic);
149 | return MOSQ_ERR_NOMEM;
150 | }
151 | snprintf(topic_temp, len, "%s%s", cur_topic->remote_prefix, mapped_topic);
152 | topic_temp[len] = '\0';
153 | _mosquitto_free(mapped_topic);
154 | mapped_topic = topic_temp;
155 | }
156 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBLISH to %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, mapped_topic, (long)payloadlen);
157 | #ifdef WITH_SYS_TREE
158 | g_pub_bytes_sent += payloadlen;
159 | #endif
160 | rc = _mosquitto_send_real_publish(mosq, mid, mapped_topic, payloadlen, payload, qos, retain, dup);
161 | _mosquitto_free(mapped_topic);
162 | return rc;
163 | }
164 | }
165 | }
166 | }
167 | #endif
168 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBLISH to %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, topic, (long)payloadlen);
169 | # ifdef WITH_SYS_TREE
170 | g_pub_bytes_sent += payloadlen;
171 | # endif
172 | #else
173 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, topic, (long)payloadlen);
174 | #endif
175 |
176 | return _mosquitto_send_real_publish(mosq, mid, topic, payloadlen, payload, qos, retain, dup);
177 | }
178 |
179 | int _mosquitto_send_pubrec(struct mosquitto *mosq, uint16_t mid)
180 | {
181 | #ifdef WITH_BROKER
182 | if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREC to %s (Mid: %d)", mosq->id, mid);
183 | #else
184 | if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREC (Mid: %d)", mosq->id, mid);
185 | #endif
186 | return _mosquitto_send_command_with_mid(mosq, PUBREC, mid, false);
187 | }
188 |
189 | int _mosquitto_send_pubrel(struct mosquitto *mosq, uint16_t mid)
190 | {
191 | #ifdef WITH_BROKER
192 | if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREL to %s (Mid: %d)", mosq->id, mid);
193 | #else
194 | if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREL (Mid: %d)", mosq->id, mid);
195 | #endif
196 | return _mosquitto_send_command_with_mid(mosq, PUBREL|2, mid, false);
197 | }
198 |
199 | /* For PUBACK, PUBCOMP, PUBREC, and PUBREL */
200 | int _mosquitto_send_command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup)
201 | {
202 | struct _mosquitto_packet *packet = NULL;
203 | int rc;
204 |
205 | assert(mosq);
206 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
207 | if(!packet) return MOSQ_ERR_NOMEM;
208 |
209 | packet->command = command;
210 | if(dup){
211 | packet->command |= 8;
212 | }
213 | packet->remaining_length = 2;
214 | rc = _mosquitto_packet_alloc(packet);
215 | if(rc){
216 | _mosquitto_free(packet);
217 | return rc;
218 | }
219 |
220 | packet->payload[packet->pos+0] = MOSQ_MSB(mid);
221 | packet->payload[packet->pos+1] = MOSQ_LSB(mid);
222 |
223 | return _mosquitto_packet_queue(mosq, packet);
224 | }
225 |
226 | /* For DISCONNECT, PINGREQ and PINGRESP */
227 | int _mosquitto_send_simple_command(struct mosquitto *mosq, uint8_t command)
228 | {
229 | struct _mosquitto_packet *packet = NULL;
230 | int rc;
231 |
232 | assert(mosq);
233 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
234 | if(!packet) return MOSQ_ERR_NOMEM;
235 |
236 | packet->command = command;
237 | packet->remaining_length = 0;
238 |
239 | rc = _mosquitto_packet_alloc(packet);
240 | if(rc){
241 | _mosquitto_free(packet);
242 | return rc;
243 | }
244 |
245 | return _mosquitto_packet_queue(mosq, packet);
246 | }
247 |
248 | int _mosquitto_send_real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup)
249 | {
250 | struct _mosquitto_packet *packet = NULL;
251 | int packetlen;
252 | int rc;
253 |
254 | assert(mosq);
255 | assert(topic);
256 |
257 | packetlen = (int)(2+strlen(topic)) + payloadlen;
258 | if(qos > 0) packetlen += 2; /* For message id */
259 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
260 | if(!packet) return MOSQ_ERR_NOMEM;
261 |
262 | packet->mid = mid;
263 | packet->command = PUBLISH | ((dup&0x1)<<3) | (qos<<1) | retain;
264 | packet->remaining_length = packetlen;
265 | rc = _mosquitto_packet_alloc(packet);
266 | if(rc){
267 | _mosquitto_free(packet);
268 | return rc;
269 | }
270 | /* Variable header (topic string) */
271 | _mosquitto_write_string(packet, topic, strlen(topic));
272 | if(qos > 0){
273 | _mosquitto_write_uint16(packet, mid);
274 | }
275 |
276 | /* Payload */
277 | if(payloadlen){
278 | _mosquitto_write_bytes(packet, payload, payloadlen);
279 | }
280 |
281 | return _mosquitto_packet_queue(mosq, packet);
282 | }
283 |
--------------------------------------------------------------------------------
/MoscapsuleTests/MoscapsuleTests.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import XCTest
3 |
4 | import Moscapsule
5 |
6 |
7 | //
8 | // These are fragile tests!!
9 | // I know it's a bad practice but I'm not going to fix it.
10 | //
11 | class MoscapsuleTests: XCTestCase {
12 |
13 | var initFlag = false
14 |
15 | override func setUp() {
16 | super.setUp()
17 | // Put setup code here. This method is called before the invocation of each test method in the class.
18 | if !initFlag {
19 | initFlag = true
20 | moscapsule_init()
21 | }
22 | }
23 |
24 | override func tearDown() {
25 | // Put teardown code here. This method is called after the invocation of each test method in the class.
26 | super.tearDown()
27 | }
28 |
29 | func testConnectToMQTTServer() {
30 | let clientId = "connect_test 1234567890abcdef"
31 | //XCTAssertTrue(clientId.characters.count > Int(MOSQ_MQTT_ID_MAX_LENGTH))
32 | let mqttConfig = MQTTConfig(clientId: clientId, host: "test.mosquitto.org", port: 1883, keepAlive: 60)
33 |
34 | mqttConfig.onConnectCallback = { returnCode in
35 | NSLog("Return Code is \(returnCode.description) (this callback is declared in swift.)")
36 | }
37 | mqttConfig.onDisconnectCallback = { reasonCode in
38 | NSLog("Reason Code is \(reasonCode.description) (this callback is declared in swift.)")
39 | }
40 |
41 | let mqttClient = MQTT.newConnection(mqttConfig)
42 | sleep(2)
43 | XCTAssertTrue(mqttClient.isConnected)
44 | mqttClient.disconnect()
45 | sleep(2)
46 | XCTAssertFalse(mqttClient.isConnected)
47 | }
48 |
49 | func testReconnect() {
50 | let clientId = "reconnect_test 1234"
51 | let mqttConfig = MQTTConfig(clientId: clientId, host: "test.mosquitto.org", port: 1883, keepAlive: 60)
52 | let mqttClient = MQTT.newConnection(mqttConfig, connectImmediately: false)
53 | XCTAssertFalse(mqttClient.isConnected)
54 | // first connecting
55 | mqttClient.connectTo(host: "test.mosquitto.org", port: 1883, keepAlive: 60)
56 | sleep(5)
57 | XCTAssertTrue(mqttClient.isConnected)
58 | // disconnecting
59 | mqttClient.disconnect()
60 | sleep(5)
61 | XCTAssertFalse(mqttClient.isConnected)
62 | // reconnecting again
63 | mqttClient.reconnect { mosqResult in
64 | print(mosqResult)
65 | }
66 | sleep(5)
67 | XCTAssertTrue(mqttClient.isConnected)
68 | }
69 |
70 | func testReconnectInRunning() {
71 | let clientId = "reconnect_test"
72 | let mqttConfig = MQTTConfig(clientId: clientId, host: "test.mosquitto.org", port: 1883, keepAlive: 60)
73 | let mqttClient = MQTT.newConnection(mqttConfig, connectImmediately: false)
74 |
75 | // first connecting
76 | mqttClient.connectTo(host: "test.mosquitto.org", port: 1883, keepAlive: 60)
77 | sleep(3)
78 | XCTAssertTrue(mqttClient.isConnected)
79 | // reconnecting again
80 | mqttClient.reconnect { mosqResult in
81 | print(mosqResult)
82 | }
83 | sleep(3)
84 | mqttClient.connectTo(host: "test.mosquitto.org", port: 1883, keepAlive: 60) { mosqResult in
85 | print(mosqResult)
86 | }
87 | sleep(3)
88 | XCTAssertTrue(mqttClient.isConnected)
89 | }
90 |
91 | func testPublishAndSubscribe() {
92 | let mqttConfigPub = MQTTConfig(clientId: "pub", host: "test.mosquitto.org", port: 1883, keepAlive: 60)
93 | var published = false
94 | let payload = "ほげほげ"
95 | let topic = "/moscapsule/testPublishAndSubscribe"
96 | mqttConfigPub.onPublishCallback = { messageId in
97 | NSLog("published (mid=\(messageId))")
98 | published = true
99 | }
100 |
101 | let mqttConfigSub = MQTTConfig(clientId: "sub", host: "test.mosquitto.org", port: 1883, keepAlive: 60)
102 | var subscribed = false
103 | var received = false
104 | mqttConfigSub.onSubscribeCallback = { (messageId, grantedQos) in
105 | NSLog("subscribed (mid=\(messageId),grantedQos=\(grantedQos))")
106 | subscribed = true
107 | }
108 | mqttConfigSub.onMessageCallback = { mqttMessage in
109 | received = true
110 | NSLog("MQTT Message received: payload=\(String(describing: mqttMessage.payloadString))")
111 | XCTAssertEqual(mqttMessage.payloadString!, payload, "Received message must be the same as published one!!")
112 | }
113 |
114 | let mqttClientPub = MQTT.newConnection(mqttConfigPub)
115 | let mqttClientSub = MQTT.newConnection(mqttConfigSub)
116 | mqttClientSub.subscribe(topic, qos: 2)
117 | sleep(2)
118 | mqttClientPub.publish(string: payload, topic: topic, qos: 2, retain: false)
119 | sleep(2)
120 |
121 | XCTAssertTrue(published)
122 | XCTAssertTrue(subscribed)
123 | XCTAssertTrue(received)
124 |
125 | mqttClientPub.disconnect()
126 | mqttClientSub.disconnect()
127 | }
128 |
129 | func testPublish() {
130 | let mqttConfigPub = MQTTConfig(clientId: "pub", host: "test.mosquitto.org", port: 1883, keepAlive: 60)
131 | var published = false
132 | let payload = "my message"
133 | let topic = "/moscapsule/testPublish"
134 | mqttConfigPub.onPublishCallback = { messageId in
135 | NSLog("published (mid=\(messageId))")
136 | published = true
137 | }
138 |
139 | let mqttClientPub = MQTT.newConnection(mqttConfigPub)
140 | mqttClientPub.publish(string: payload, topic: topic, qos: 0, retain: false)
141 | sleep(2)
142 | XCTAssertTrue(published)
143 | published = false
144 |
145 | mqttClientPub.publish(string: payload, topic: topic, qos: 1, retain: false)
146 | sleep(2)
147 | XCTAssertTrue(published)
148 | published = false
149 |
150 | mqttClientPub.publish(string: payload, topic: topic, qos: 2, retain: false)
151 | sleep(2)
152 | XCTAssertTrue(published)
153 | published = false
154 |
155 | let data = Data(bytes: [0x00, 0x01, 0x00, 0x00])
156 | mqttClientPub.publish(data, topic: topic, qos: 2, retain: false)
157 | sleep(2)
158 | XCTAssertTrue(published)
159 | published = false
160 |
161 | mqttClientPub.disconnect()
162 | }
163 |
164 | func testUnsubscribe() {
165 | let mqttConfig = MQTTConfig(clientId: "unsubscribe_test", host: "test.mosquitto.org", port: 1883, keepAlive: 60)
166 | var subscribed = false
167 | var unsubscribed = false
168 | mqttConfig.onSubscribeCallback = { (messageId, grantedQos) in
169 | NSLog("subscribed (mid=\(messageId),grantedQos=\(grantedQos))")
170 | subscribed = true
171 | }
172 | mqttConfig.onUnsubscribeCallback = { messageId in
173 | NSLog("unsubscribed (mid=\(messageId))")
174 | unsubscribed = true
175 | }
176 |
177 | let mqttClient = MQTT.newConnection(mqttConfig)
178 | mqttClient.subscribe("testTopic", qos: 2)
179 | sleep(2)
180 | mqttClient.unsubscribe("testTopic")
181 | sleep(2)
182 |
183 | XCTAssertTrue(subscribed)
184 | XCTAssertTrue(unsubscribed)
185 | mqttClient.disconnect()
186 | }
187 |
188 | func testAutoDisconnect() {
189 | var disconnected: Bool = false
190 |
191 | let closure = { () -> Void in
192 | let mqttConfig = MQTTConfig(clientId: "auto_disconnect_test", host: "test.mosquitto.org", port: 1883, keepAlive: 60)
193 | mqttConfig.onDisconnectCallback = { reasonCode in
194 | disconnected = true
195 | }
196 | let _ = MQTT.newConnection(mqttConfig)
197 | }
198 | closure()
199 | sleep(3)
200 |
201 | XCTAssertTrue(disconnected)
202 | }
203 |
204 | func testCompletion() {
205 | let mqttConfig = MQTTConfig(clientId: "completion_test", host: "test.mosquitto.org", port: 1883, keepAlive: 60)
206 | mqttConfig.onPublishCallback = { messageId in
207 | NSLog("published (mid=\(messageId))")
208 | }
209 | mqttConfig.onSubscribeCallback = { (messageId, grantedQos) in
210 | NSLog("subscribed (mid=\(messageId),grantedQos=\(grantedQos))")
211 | }
212 | mqttConfig.onUnsubscribeCallback = { messageId in
213 | NSLog("unsubscribed (mid=\(messageId))")
214 | }
215 | var published = false
216 | var subscribed = false
217 | var unsubscribed = false
218 |
219 | let mqttClient = MQTT.newConnection(mqttConfig)
220 | mqttClient.publish(string: "msg", topic: "topic", qos: 2, retain: false) { mosqReturn, messageId in
221 | published = true
222 | NSLog("publish completion: mosq_return=\(mosqReturn.rawValue) messageId=\(messageId)")
223 | }
224 | mqttClient.awaitRequestCompletion()
225 | XCTAssertTrue(published)
226 |
227 | mqttClient.subscribe("testTopic", qos: 2) { mosqReturn, messageId in
228 | subscribed = true
229 | NSLog("subscribe completion: mosq_return=\(mosqReturn.rawValue) messageId=\(messageId)")
230 | }
231 | mqttClient.awaitRequestCompletion()
232 | XCTAssertTrue(subscribed)
233 |
234 | mqttClient.unsubscribe("testTopic") { mosqReturn, messageId in
235 | unsubscribed = true
236 | NSLog("unsubscribe completion: mosq_return=\(mosqReturn.rawValue) messageId=\(messageId)")
237 | }
238 | mqttClient.awaitRequestCompletion()
239 | XCTAssertTrue(unsubscribed)
240 |
241 | sleep(3)
242 | mqttClient.disconnect()
243 | }
244 |
245 | func testServerCertificate() {
246 | let mqttConfig = MQTTConfig(clientId: "server_cert_test", host: "test.mosquitto.org", port: 8883, keepAlive: 60)
247 | mqttConfig.onConnectCallback = { returnCode in
248 | NSLog("Return Code is \(returnCode.description) (this callback is declared in swift.)")
249 | }
250 |
251 | let bundleURL = URL(fileURLWithPath: Bundle(for: type(of: self)).path(forResource: "cert", ofType: "bundle")!)
252 | let certFile = bundleURL.appendingPathComponent("mosquitto.org.crt").path
253 |
254 | mqttConfig.mqttServerCert = MQTTServerCert(cafile: certFile, capath: nil)
255 | //mqttConfig.mqttTlsOpts = MQTTTlsOpts(tls_insecure: true, cert_reqs: .SSL_VERIFY_NONE, tls_version: nil, ciphers: nil)
256 |
257 | let mqttClient = MQTT.newConnection(mqttConfig)
258 | sleep(10) // so long time needed...
259 | XCTAssertTrue(mqttClient.isConnected)
260 | mqttClient.disconnect()
261 | sleep(2)
262 | XCTAssertFalse(mqttClient.isConnected)
263 | XCTAssertFalse(mqttClient.isRunning)
264 | }
265 |
266 | func testAbnormalOperation() {
267 | let clientId = "reconnect_test 1234"
268 | let topic = "/moscapsule/testAbnormalOperation"
269 | let payload = "payload"
270 | let mqttConfig = MQTTConfig(clientId: clientId, host: "test.mosquitto.org", port: 1883, keepAlive: 60)
271 | let mqttClient = MQTT.newConnection(mqttConfig, connectImmediately: false)
272 |
273 | // do pub/sub in no-runnning state
274 | mqttClient.subscribe(topic, qos: 2)
275 | mqttClient.publish(string: payload, topic: topic, qos: 2, retain: false)
276 |
277 | // first connecting
278 | mqttClient.connectTo(host: "test.mosquitto.org", port: 1883, keepAlive: 60)
279 | // disconnecting
280 | mqttClient.disconnect()
281 | sleep(2)
282 | XCTAssertFalse(mqttClient.isRunning)
283 |
284 | // do pub/sub in no-runnning state
285 | mqttClient.subscribe(topic, qos: 2)
286 | mqttClient.publish(string: payload, topic: topic, qos: 2, retain: false)
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/mosquitto/lib/messages_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2010-2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | void _mosquitto_message_cleanup(struct mosquitto_message_all **message)
29 | {
30 | struct mosquitto_message_all *msg;
31 |
32 | if(!message || !*message) return;
33 |
34 | msg = *message;
35 |
36 | if(msg->msg.topic) _mosquitto_free(msg->msg.topic);
37 | if(msg->msg.payload) _mosquitto_free(msg->msg.payload);
38 | _mosquitto_free(msg);
39 | }
40 |
41 | void _mosquitto_message_cleanup_all(struct mosquitto *mosq)
42 | {
43 | struct mosquitto_message_all *tmp;
44 |
45 | assert(mosq);
46 |
47 | while(mosq->in_messages){
48 | tmp = mosq->in_messages->next;
49 | _mosquitto_message_cleanup(&mosq->in_messages);
50 | mosq->in_messages = tmp;
51 | }
52 | while(mosq->out_messages){
53 | tmp = mosq->out_messages->next;
54 | _mosquitto_message_cleanup(&mosq->out_messages);
55 | mosq->out_messages = tmp;
56 | }
57 | }
58 |
59 | int mosquitto_message_copy(struct mosquitto_message *dst, const struct mosquitto_message *src)
60 | {
61 | if(!dst || !src) return MOSQ_ERR_INVAL;
62 |
63 | dst->mid = src->mid;
64 | dst->topic = _mosquitto_strdup(src->topic);
65 | if(!dst->topic) return MOSQ_ERR_NOMEM;
66 | dst->qos = src->qos;
67 | dst->retain = src->retain;
68 | if(src->payloadlen){
69 | dst->payload = _mosquitto_malloc(src->payloadlen);
70 | if(!dst->payload){
71 | _mosquitto_free(dst->topic);
72 | return MOSQ_ERR_NOMEM;
73 | }
74 | memcpy(dst->payload, src->payload, src->payloadlen);
75 | dst->payloadlen = src->payloadlen;
76 | }else{
77 | dst->payloadlen = 0;
78 | dst->payload = NULL;
79 | }
80 | return MOSQ_ERR_SUCCESS;
81 | }
82 |
83 | int _mosquitto_message_delete(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir)
84 | {
85 | struct mosquitto_message_all *message;
86 | int rc;
87 | assert(mosq);
88 |
89 | rc = _mosquitto_message_remove(mosq, mid, dir, &message);
90 | if(rc == MOSQ_ERR_SUCCESS){
91 | _mosquitto_message_cleanup(&message);
92 | }
93 | return rc;
94 | }
95 |
96 | void mosquitto_message_free(struct mosquitto_message **message)
97 | {
98 | struct mosquitto_message *msg;
99 |
100 | if(!message || !*message) return;
101 |
102 | msg = *message;
103 |
104 | if(msg->topic) _mosquitto_free(msg->topic);
105 | if(msg->payload) _mosquitto_free(msg->payload);
106 | _mosquitto_free(msg);
107 | }
108 |
109 |
110 | /*
111 | * Function: _mosquitto_message_queue
112 | *
113 | * Returns:
114 | * 0 - to indicate an outgoing message can be started
115 | * 1 - to indicate that the outgoing message queue is full (inflight limit has been reached)
116 | */
117 | int _mosquitto_message_queue(struct mosquitto *mosq, struct mosquitto_message_all *message, enum mosquitto_msg_direction dir)
118 | {
119 | int rc = 0;
120 |
121 | /* mosq->*_message_mutex should be locked before entering this function */
122 | assert(mosq);
123 | assert(message);
124 |
125 | if(dir == mosq_md_out){
126 | mosq->out_queue_len++;
127 | message->next = NULL;
128 | if(mosq->out_messages_last){
129 | mosq->out_messages_last->next = message;
130 | }else{
131 | mosq->out_messages = message;
132 | }
133 | mosq->out_messages_last = message;
134 | if(message->msg.qos > 0){
135 | if(mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages){
136 | mosq->inflight_messages++;
137 | }else{
138 | rc = 1;
139 | }
140 | }
141 | }else{
142 | mosq->in_queue_len++;
143 | message->next = NULL;
144 | if(mosq->in_messages_last){
145 | mosq->in_messages_last->next = message;
146 | }else{
147 | mosq->in_messages = message;
148 | }
149 | mosq->in_messages_last = message;
150 | }
151 | return rc;
152 | }
153 |
154 | void _mosquitto_messages_reconnect_reset(struct mosquitto *mosq)
155 | {
156 | struct mosquitto_message_all *message;
157 | struct mosquitto_message_all *prev = NULL;
158 | assert(mosq);
159 |
160 | pthread_mutex_lock(&mosq->in_message_mutex);
161 | message = mosq->in_messages;
162 | mosq->in_queue_len = 0;
163 | while(message){
164 | mosq->in_queue_len++;
165 | message->timestamp = 0;
166 | if(message->msg.qos != 2){
167 | if(prev){
168 | prev->next = message->next;
169 | _mosquitto_message_cleanup(&message);
170 | message = prev;
171 | }else{
172 | mosq->in_messages = message->next;
173 | _mosquitto_message_cleanup(&message);
174 | message = mosq->in_messages;
175 | }
176 | }else{
177 | /* Message state can be preserved here because it should match
178 | * whatever the client has got. */
179 | }
180 | prev = message;
181 | message = message->next;
182 | }
183 | mosq->in_messages_last = prev;
184 | pthread_mutex_unlock(&mosq->in_message_mutex);
185 |
186 |
187 | pthread_mutex_lock(&mosq->out_message_mutex);
188 | mosq->inflight_messages = 0;
189 | message = mosq->out_messages;
190 | mosq->out_queue_len = 0;
191 | while(message){
192 | mosq->out_queue_len++;
193 | message->timestamp = 0;
194 |
195 | if(mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages){
196 | if(message->msg.qos > 0){
197 | mosq->inflight_messages++;
198 | }
199 | if(message->msg.qos == 1){
200 | message->state = mosq_ms_wait_for_puback;
201 | }else if(message->msg.qos == 2){
202 | /* Should be able to preserve state. */
203 | }
204 | }else{
205 | message->state = mosq_ms_invalid;
206 | }
207 | prev = message;
208 | message = message->next;
209 | }
210 | mosq->out_messages_last = prev;
211 | pthread_mutex_unlock(&mosq->out_message_mutex);
212 | }
213 |
214 | int _mosquitto_message_remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, struct mosquitto_message_all **message)
215 | {
216 | struct mosquitto_message_all *cur, *prev = NULL;
217 | bool found = false;
218 | int rc;
219 | assert(mosq);
220 | assert(message);
221 |
222 | if(dir == mosq_md_out){
223 | pthread_mutex_lock(&mosq->out_message_mutex);
224 | cur = mosq->out_messages;
225 | while(cur){
226 | if(cur->msg.mid == mid){
227 | if(prev){
228 | prev->next = cur->next;
229 | }else{
230 | mosq->out_messages = cur->next;
231 | }
232 | *message = cur;
233 | mosq->out_queue_len--;
234 | if(cur->next == NULL){
235 | mosq->out_messages_last = prev;
236 | }else if(!mosq->out_messages){
237 | mosq->out_messages_last = NULL;
238 | }
239 | if(cur->msg.qos > 0){
240 | mosq->inflight_messages--;
241 | }
242 | found = true;
243 | break;
244 | }
245 | prev = cur;
246 | cur = cur->next;
247 | }
248 |
249 | if(found){
250 | cur = mosq->out_messages;
251 | while(cur){
252 | if(mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages){
253 | if(cur->msg.qos > 0 && cur->state == mosq_ms_invalid){
254 | mosq->inflight_messages++;
255 | if(cur->msg.qos == 1){
256 | cur->state = mosq_ms_wait_for_puback;
257 | }else if(cur->msg.qos == 2){
258 | cur->state = mosq_ms_wait_for_pubrec;
259 | }
260 | rc = _mosquitto_send_publish(mosq, cur->msg.mid, cur->msg.topic, cur->msg.payloadlen, cur->msg.payload, cur->msg.qos, cur->msg.retain, cur->dup);
261 | if(rc){
262 | pthread_mutex_unlock(&mosq->out_message_mutex);
263 | return rc;
264 | }
265 | }
266 | }else{
267 | pthread_mutex_unlock(&mosq->out_message_mutex);
268 | return MOSQ_ERR_SUCCESS;
269 | }
270 | cur = cur->next;
271 | }
272 | pthread_mutex_unlock(&mosq->out_message_mutex);
273 | return MOSQ_ERR_SUCCESS;
274 | }else{
275 | pthread_mutex_unlock(&mosq->out_message_mutex);
276 | return MOSQ_ERR_NOT_FOUND;
277 | }
278 | }else{
279 | pthread_mutex_lock(&mosq->in_message_mutex);
280 | cur = mosq->in_messages;
281 | while(cur){
282 | if(cur->msg.mid == mid){
283 | if(prev){
284 | prev->next = cur->next;
285 | }else{
286 | mosq->in_messages = cur->next;
287 | }
288 | *message = cur;
289 | mosq->in_queue_len--;
290 | if(cur->next == NULL){
291 | mosq->in_messages_last = prev;
292 | }else if(!mosq->in_messages){
293 | mosq->in_messages_last = NULL;
294 | }
295 | found = true;
296 | break;
297 | }
298 | prev = cur;
299 | cur = cur->next;
300 | }
301 |
302 | pthread_mutex_unlock(&mosq->in_message_mutex);
303 | if(found){
304 | return MOSQ_ERR_SUCCESS;
305 | }else{
306 | return MOSQ_ERR_NOT_FOUND;
307 | }
308 | }
309 | }
310 |
311 | #ifdef WITH_THREADING
312 | void _mosquitto_message_retry_check_actual(struct mosquitto *mosq, struct mosquitto_message_all *messages, pthread_mutex_t *mutex)
313 | #else
314 | void _mosquitto_message_retry_check_actual(struct mosquitto *mosq, struct mosquitto_message_all *messages)
315 | #endif
316 | {
317 | time_t now = mosquitto_time();
318 | assert(mosq);
319 |
320 | #ifdef WITH_THREADING
321 | pthread_mutex_lock(mutex);
322 | #endif
323 |
324 | while(messages){
325 | if(messages->timestamp + mosq->message_retry < now){
326 | switch(messages->state){
327 | case mosq_ms_wait_for_puback:
328 | case mosq_ms_wait_for_pubrec:
329 | messages->timestamp = now;
330 | messages->dup = true;
331 | _mosquitto_send_publish(mosq, messages->msg.mid, messages->msg.topic, messages->msg.payloadlen, messages->msg.payload, messages->msg.qos, messages->msg.retain, messages->dup);
332 | break;
333 | case mosq_ms_wait_for_pubrel:
334 | messages->timestamp = now;
335 | messages->dup = true;
336 | _mosquitto_send_pubrec(mosq, messages->msg.mid);
337 | break;
338 | case mosq_ms_wait_for_pubcomp:
339 | messages->timestamp = now;
340 | messages->dup = true;
341 | _mosquitto_send_pubrel(mosq, messages->msg.mid);
342 | break;
343 | default:
344 | break;
345 | }
346 | }
347 | messages = messages->next;
348 | }
349 | #ifdef WITH_THREADING
350 | pthread_mutex_unlock(mutex);
351 | #endif
352 | }
353 |
354 | void _mosquitto_message_retry_check(struct mosquitto *mosq)
355 | {
356 | #ifdef WITH_THREADING
357 | _mosquitto_message_retry_check_actual(mosq, mosq->out_messages, &mosq->out_message_mutex);
358 | _mosquitto_message_retry_check_actual(mosq, mosq->in_messages, &mosq->in_message_mutex);
359 | #else
360 | _mosquitto_message_retry_check_actual(mosq, mosq->out_messages);
361 | _mosquitto_message_retry_check_actual(mosq, mosq->in_messages);
362 | #endif
363 | }
364 |
365 | void mosquitto_message_retry_set(struct mosquitto *mosq, unsigned int message_retry)
366 | {
367 | assert(mosq);
368 | if(mosq) mosq->message_retry = message_retry;
369 | }
370 |
371 | int _mosquitto_message_out_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_state state)
372 | {
373 | struct mosquitto_message_all *message;
374 | assert(mosq);
375 |
376 | pthread_mutex_lock(&mosq->out_message_mutex);
377 | message = mosq->out_messages;
378 | while(message){
379 | if(message->msg.mid == mid){
380 | message->state = state;
381 | message->timestamp = mosquitto_time();
382 | pthread_mutex_unlock(&mosq->out_message_mutex);
383 | return MOSQ_ERR_SUCCESS;
384 | }
385 | message = message->next;
386 | }
387 | pthread_mutex_unlock(&mosq->out_message_mutex);
388 | return MOSQ_ERR_NOT_FOUND;
389 | }
390 |
391 | int mosquitto_max_inflight_messages_set(struct mosquitto *mosq, unsigned int max_inflight_messages)
392 | {
393 | if(!mosq) return MOSQ_ERR_INVAL;
394 |
395 | mosq->max_inflight_messages = max_inflight_messages;
396 |
397 | return MOSQ_ERR_SUCCESS;
398 | }
399 |
400 |
--------------------------------------------------------------------------------
/mosquitto/lib/socks_mosq.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2014 Roger Light
3 |
4 | All rights reserved. This program and the accompanying materials
5 | are made available under the terms of the Eclipse Public License v1.0
6 | and Eclipse Distribution License v1.0 which accompany this distribution.
7 |
8 | The Eclipse Public License is available at
9 | http://www.eclipse.org/legal/epl-v10.html
10 | and the Eclipse Distribution License is available at
11 | http://www.eclipse.org/org/documents/edl-v10.php.
12 |
13 | Contributors:
14 | Roger Light - initial implementation and documentation.
15 | */
16 |
17 | #include
18 | #include
19 |
20 | #include "mosquitto_internal.h"
21 | #include "memory_mosq.h"
22 | #include "net_mosq.h"
23 | #include "send_mosq.h"
24 |
25 | #define SOCKS_AUTH_NONE 0x00
26 | #define SOCKS_AUTH_GSS 0x01
27 | #define SOCKS_AUTH_USERPASS 0x02
28 | #define SOCKS_AUTH_NO_ACCEPTABLE 0xFF
29 |
30 | #define SOCKS_ATYPE_IP_V4 1 /* four bytes */
31 | #define SOCKS_ATYPE_DOMAINNAME 3 /* one byte length, followed by fqdn no null, 256 max chars */
32 | #define SOCKS_ATYPE_IP_V6 4 /* 16 bytes */
33 |
34 | #define SOCKS_REPLY_SUCCEEDED 0x00
35 | #define SOCKS_REPLY_GENERAL_FAILURE 0x01
36 | #define SOCKS_REPLY_CONNECTION_NOT_ALLOWED 0x02
37 | #define SOCKS_REPLY_NETWORK_UNREACHABLE 0x03
38 | #define SOCKS_REPLY_HOST_UNREACHABLE 0x04
39 | #define SOCKS_REPLY_CONNECTION_REFUSED 0x05
40 | #define SOCKS_REPLY_TTL_EXPIRED 0x06
41 | #define SOCKS_REPLY_COMMAND_NOT_SUPPORTED 0x07
42 | #define SOCKS_REPLY_ADDRESS_TYPE_NOT_SUPPORTED 0x08
43 |
44 | int mosquitto_socks5_set(struct mosquitto *mosq, const char *host, int port, const char *username, const char *password)
45 | {
46 | #ifdef WITH_SOCKS
47 | if(!mosq) return MOSQ_ERR_INVAL;
48 | if(!host || strlen(host) > 256) return MOSQ_ERR_INVAL;
49 | if(port < 1 || port > 65535) return MOSQ_ERR_INVAL;
50 |
51 | if(mosq->socks5_host){
52 | _mosquitto_free(mosq->socks5_host);
53 | }
54 |
55 | mosq->socks5_host = _mosquitto_strdup(host);
56 | if(!mosq->socks5_host){
57 | return MOSQ_ERR_NOMEM;
58 | }
59 |
60 | mosq->socks5_port = port;
61 |
62 | if(mosq->socks5_username){
63 | _mosquitto_free(mosq->socks5_username);
64 | }
65 | if(mosq->socks5_password){
66 | _mosquitto_free(mosq->socks5_password);
67 | }
68 |
69 | if(username){
70 | mosq->socks5_username = _mosquitto_strdup(username);
71 | if(!mosq->socks5_username){
72 | return MOSQ_ERR_NOMEM;
73 | }
74 |
75 | if(password){
76 | mosq->socks5_password = _mosquitto_strdup(password);
77 | if(!mosq->socks5_password){
78 | _mosquitto_free(mosq->socks5_username);
79 | return MOSQ_ERR_NOMEM;
80 | }
81 | }
82 | }
83 |
84 | return MOSQ_ERR_SUCCESS;
85 | #else
86 | return MOSQ_ERR_NOT_SUPPORTED;
87 | #endif
88 | }
89 |
90 | #ifdef WITH_SOCKS
91 | int mosquitto__socks5_send(struct mosquitto *mosq)
92 | {
93 | struct _mosquitto_packet *packet;
94 | int slen;
95 | int ulen, plen;
96 |
97 | if(mosq->state == mosq_cs_socks5_new){
98 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
99 | if(!packet) return MOSQ_ERR_NOMEM;
100 |
101 | if(mosq->socks5_username){
102 | packet->packet_length = 4;
103 | }else{
104 | packet->packet_length = 3;
105 | }
106 | packet->payload = _mosquitto_malloc(sizeof(uint8_t)*packet->packet_length);
107 |
108 | packet->payload[0] = 0x05;
109 | if(mosq->socks5_username){
110 | packet->payload[1] = 2;
111 | packet->payload[2] = SOCKS_AUTH_NONE;
112 | packet->payload[3] = SOCKS_AUTH_USERPASS;
113 | }else{
114 | packet->payload[1] = 1;
115 | packet->payload[2] = SOCKS_AUTH_NONE;
116 | }
117 |
118 | pthread_mutex_lock(&mosq->state_mutex);
119 | mosq->state = mosq_cs_socks5_start;
120 | pthread_mutex_unlock(&mosq->state_mutex);
121 |
122 | mosq->in_packet.pos = 0;
123 | mosq->in_packet.packet_length = 2;
124 | mosq->in_packet.to_process = 2;
125 | mosq->in_packet.payload = _mosquitto_malloc(sizeof(uint8_t)*2);
126 | if(!mosq->in_packet.payload){
127 | _mosquitto_free(packet->payload);
128 | _mosquitto_free(packet);
129 | return MOSQ_ERR_NOMEM;
130 | }
131 |
132 | return _mosquitto_packet_queue(mosq, packet);
133 | }else if(mosq->state == mosq_cs_socks5_auth_ok){
134 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
135 | if(!packet) return MOSQ_ERR_NOMEM;
136 |
137 | packet->packet_length = 7+strlen(mosq->host);
138 | packet->payload = _mosquitto_malloc(sizeof(uint8_t)*packet->packet_length);
139 |
140 | slen = strlen(mosq->host);
141 |
142 | packet->payload[0] = 0x05;
143 | packet->payload[1] = 1;
144 | packet->payload[2] = 0;
145 | packet->payload[3] = SOCKS_ATYPE_DOMAINNAME;
146 | packet->payload[4] = slen;
147 | memcpy(&(packet->payload[5]), mosq->host, slen);
148 | packet->payload[5+slen] = MOSQ_MSB(mosq->port);
149 | packet->payload[6+slen] = MOSQ_LSB(mosq->port);
150 |
151 | pthread_mutex_lock(&mosq->state_mutex);
152 | mosq->state = mosq_cs_socks5_request;
153 | pthread_mutex_unlock(&mosq->state_mutex);
154 |
155 | mosq->in_packet.pos = 0;
156 | mosq->in_packet.packet_length = 5;
157 | mosq->in_packet.to_process = 5;
158 | mosq->in_packet.payload = _mosquitto_malloc(sizeof(uint8_t)*5);
159 | if(!mosq->in_packet.payload){
160 | _mosquitto_free(packet->payload);
161 | _mosquitto_free(packet);
162 | return MOSQ_ERR_NOMEM;
163 | }
164 |
165 | return _mosquitto_packet_queue(mosq, packet);
166 | }else if(mosq->state == mosq_cs_socks5_send_userpass){
167 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
168 | if(!packet) return MOSQ_ERR_NOMEM;
169 |
170 | ulen = strlen(mosq->socks5_username);
171 | plen = strlen(mosq->socks5_password);
172 | packet->packet_length = 3 + ulen + plen;
173 | packet->payload = _mosquitto_malloc(sizeof(uint8_t)*packet->packet_length);
174 |
175 |
176 | packet->payload[0] = 0x01;
177 | packet->payload[1] = ulen;
178 | memcpy(&(packet->payload[2]), mosq->socks5_username, ulen);
179 | packet->payload[2+ulen] = plen;
180 | memcpy(&(packet->payload[3+ulen]), mosq->socks5_password, plen);
181 |
182 | pthread_mutex_lock(&mosq->state_mutex);
183 | mosq->state = mosq_cs_socks5_userpass_reply;
184 | pthread_mutex_unlock(&mosq->state_mutex);
185 |
186 | mosq->in_packet.pos = 0;
187 | mosq->in_packet.packet_length = 2;
188 | mosq->in_packet.to_process = 2;
189 | mosq->in_packet.payload = _mosquitto_malloc(sizeof(uint8_t)*2);
190 | if(!mosq->in_packet.payload){
191 | _mosquitto_free(packet->payload);
192 | _mosquitto_free(packet);
193 | return MOSQ_ERR_NOMEM;
194 | }
195 |
196 | return _mosquitto_packet_queue(mosq, packet);
197 | }
198 | return MOSQ_ERR_SUCCESS;
199 | }
200 |
201 | int mosquitto__socks5_read(struct mosquitto *mosq)
202 | {
203 | ssize_t len;
204 | uint8_t *payload;
205 | uint8_t i;
206 |
207 | if(mosq->state == mosq_cs_socks5_start){
208 | while(mosq->in_packet.to_process > 0){
209 | len = _mosquitto_net_read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process);
210 | if(len > 0){
211 | mosq->in_packet.pos += len;
212 | mosq->in_packet.to_process -= len;
213 | }else{
214 | #ifdef WIN32
215 | errno = WSAGetLastError();
216 | #endif
217 | if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){
218 | return MOSQ_ERR_SUCCESS;
219 | }else{
220 | _mosquitto_packet_cleanup(&mosq->in_packet);
221 | switch(errno){
222 | case 0:
223 | return MOSQ_ERR_PROXY;
224 | case COMPAT_ECONNRESET:
225 | return MOSQ_ERR_CONN_LOST;
226 | default:
227 | return MOSQ_ERR_ERRNO;
228 | }
229 | }
230 | }
231 | }
232 | if(mosq->in_packet.payload[0] != 5){
233 | _mosquitto_packet_cleanup(&mosq->in_packet);
234 | return MOSQ_ERR_PROXY;
235 | }
236 | switch(mosq->in_packet.payload[1]){
237 | case SOCKS_AUTH_NONE:
238 | _mosquitto_packet_cleanup(&mosq->in_packet);
239 | mosq->state = mosq_cs_socks5_auth_ok;
240 | return mosquitto__socks5_send(mosq);
241 | case SOCKS_AUTH_USERPASS:
242 | _mosquitto_packet_cleanup(&mosq->in_packet);
243 | mosq->state = mosq_cs_socks5_send_userpass;
244 | return mosquitto__socks5_send(mosq);
245 | default:
246 | _mosquitto_packet_cleanup(&mosq->in_packet);
247 | return MOSQ_ERR_AUTH;
248 | }
249 | }else if(mosq->state == mosq_cs_socks5_userpass_reply){
250 | while(mosq->in_packet.to_process > 0){
251 | len = _mosquitto_net_read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process);
252 | if(len > 0){
253 | mosq->in_packet.pos += len;
254 | mosq->in_packet.to_process -= len;
255 | }else{
256 | #ifdef WIN32
257 | errno = WSAGetLastError();
258 | #endif
259 | if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){
260 | return MOSQ_ERR_SUCCESS;
261 | }else{
262 | _mosquitto_packet_cleanup(&mosq->in_packet);
263 | switch(errno){
264 | case 0:
265 | return MOSQ_ERR_PROXY;
266 | case COMPAT_ECONNRESET:
267 | return MOSQ_ERR_CONN_LOST;
268 | default:
269 | return MOSQ_ERR_ERRNO;
270 | }
271 | }
272 | }
273 | }
274 | if(mosq->in_packet.payload[0] != 1){
275 | _mosquitto_packet_cleanup(&mosq->in_packet);
276 | return MOSQ_ERR_PROXY;
277 | }
278 | if(mosq->in_packet.payload[1] == 0){
279 | _mosquitto_packet_cleanup(&mosq->in_packet);
280 | mosq->state = mosq_cs_socks5_auth_ok;
281 | return mosquitto__socks5_send(mosq);
282 | }else{
283 | i = mosq->in_packet.payload[1];
284 | _mosquitto_packet_cleanup(&mosq->in_packet);
285 | switch(i){
286 | case SOCKS_REPLY_CONNECTION_NOT_ALLOWED:
287 | return MOSQ_ERR_AUTH;
288 |
289 | case SOCKS_REPLY_NETWORK_UNREACHABLE:
290 | case SOCKS_REPLY_HOST_UNREACHABLE:
291 | case SOCKS_REPLY_CONNECTION_REFUSED:
292 | return MOSQ_ERR_NO_CONN;
293 |
294 | case SOCKS_REPLY_GENERAL_FAILURE:
295 | case SOCKS_REPLY_TTL_EXPIRED:
296 | case SOCKS_REPLY_COMMAND_NOT_SUPPORTED:
297 | case SOCKS_REPLY_ADDRESS_TYPE_NOT_SUPPORTED:
298 | return MOSQ_ERR_PROXY;
299 |
300 | default:
301 | return MOSQ_ERR_INVAL;
302 | }
303 | return MOSQ_ERR_PROXY;
304 | }
305 | }else if(mosq->state == mosq_cs_socks5_request){
306 | while(mosq->in_packet.to_process > 0){
307 | len = _mosquitto_net_read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process);
308 | if(len > 0){
309 | mosq->in_packet.pos += len;
310 | mosq->in_packet.to_process -= len;
311 | }else{
312 | #ifdef WIN32
313 | errno = WSAGetLastError();
314 | #endif
315 | if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){
316 | return MOSQ_ERR_SUCCESS;
317 | }else{
318 | _mosquitto_packet_cleanup(&mosq->in_packet);
319 | switch(errno){
320 | case 0:
321 | return MOSQ_ERR_PROXY;
322 | case COMPAT_ECONNRESET:
323 | return MOSQ_ERR_CONN_LOST;
324 | default:
325 | return MOSQ_ERR_ERRNO;
326 | }
327 | }
328 | }
329 | }
330 |
331 | if(mosq->in_packet.packet_length == 5){
332 | /* First part of the packet has been received, we now know what else to expect. */
333 | if(mosq->in_packet.payload[3] == SOCKS_ATYPE_IP_V4){
334 | mosq->in_packet.to_process += 4+2-1; /* 4 bytes IPv4, 2 bytes port, -1 byte because we've already read the first byte */
335 | mosq->in_packet.packet_length += 4+2-1;
336 | }else if(mosq->in_packet.payload[3] == SOCKS_ATYPE_IP_V6){
337 | mosq->in_packet.to_process += 16+2-1; /* 16 bytes IPv6, 2 bytes port, -1 byte because we've already read the first byte */
338 | mosq->in_packet.packet_length += 16+2-1;
339 | }else if(mosq->in_packet.payload[3] == SOCKS_ATYPE_DOMAINNAME){
340 | if(mosq->in_packet.payload[4] > 0 && mosq->in_packet.payload[4] <= 255){
341 | mosq->in_packet.to_process += mosq->in_packet.payload[4];
342 | mosq->in_packet.packet_length += mosq->in_packet.payload[4];
343 | }
344 | }else{
345 | _mosquitto_packet_cleanup(&mosq->in_packet);
346 | return MOSQ_ERR_PROTOCOL;
347 | }
348 | payload = _mosquitto_realloc(mosq->in_packet.payload, mosq->in_packet.packet_length);
349 | if(payload){
350 | mosq->in_packet.payload = payload;
351 | }else{
352 | _mosquitto_packet_cleanup(&mosq->in_packet);
353 | return MOSQ_ERR_NOMEM;
354 | }
355 | return MOSQ_ERR_SUCCESS;
356 | }
357 |
358 | /* Entire packet is now read. */
359 | if(mosq->in_packet.payload[0] != 5){
360 | _mosquitto_packet_cleanup(&mosq->in_packet);
361 | return MOSQ_ERR_PROXY;
362 | }
363 | if(mosq->in_packet.payload[1] == 0){
364 | /* Auth passed */
365 | _mosquitto_packet_cleanup(&mosq->in_packet);
366 | mosq->state = mosq_cs_new;
367 | return _mosquitto_send_connect(mosq, mosq->keepalive, mosq->clean_session);
368 | }else{
369 | i = mosq->in_packet.payload[1];
370 | _mosquitto_packet_cleanup(&mosq->in_packet);
371 | mosq->state = mosq_cs_socks5_new;
372 | switch(i){
373 | case SOCKS_REPLY_CONNECTION_NOT_ALLOWED:
374 | return MOSQ_ERR_AUTH;
375 |
376 | case SOCKS_REPLY_NETWORK_UNREACHABLE:
377 | case SOCKS_REPLY_HOST_UNREACHABLE:
378 | case SOCKS_REPLY_CONNECTION_REFUSED:
379 | return MOSQ_ERR_NO_CONN;
380 |
381 | case SOCKS_REPLY_GENERAL_FAILURE:
382 | case SOCKS_REPLY_TTL_EXPIRED:
383 | case SOCKS_REPLY_COMMAND_NOT_SUPPORTED:
384 | case SOCKS_REPLY_ADDRESS_TYPE_NOT_SUPPORTED:
385 | return MOSQ_ERR_PROXY;
386 |
387 | default:
388 | return MOSQ_ERR_INVAL;
389 | }
390 | }
391 | }else{
392 | return _mosquitto_packet_read(mosq);
393 | }
394 | return MOSQ_ERR_SUCCESS;
395 | }
396 | #endif
397 |
--------------------------------------------------------------------------------
/Moscapsule/Moscapsule.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public enum ReturnCode: Int {
4 | case success = 0
5 | case unacceptable_protocol_version = 1
6 | case identifier_rejected = 2
7 | case broker_unavailable = 3
8 | case unknown = 256
9 |
10 | public var description: String {
11 | switch self {
12 | case .success:
13 | return "Success"
14 | case .unacceptable_protocol_version:
15 | return "Unacceptable_Protocol_Version"
16 | case .identifier_rejected:
17 | return "Identifier_Rejected"
18 | case .broker_unavailable:
19 | return "Broker_Unavailable"
20 | case .unknown:
21 | return "Unknown"
22 | }
23 | }
24 | }
25 |
26 | public enum ReasonCode: Int {
27 | case disconnect_requested = 0
28 | case keepAlive_timeout = 1
29 |
30 | // Mosquitto confuses ReasonCode with MosqResult.
31 | // These are possibly returned as ReasonCode in _mosquitto_loop_rc_handle.
32 | case mosq_protocol = 2
33 | case mosq_inval = 3
34 | case mosq_no_conn = 4
35 | case mosq_conn_refused = 5
36 | case mosq_not_found = 6
37 | case mosq_conn_lost = 7
38 | case mosq_tls = 8
39 | case mosq_payload_size = 9
40 | case mosq_not_supported = 10
41 | case mosq_auth = 11
42 | case mosq_acl_denied = 12
43 | case mosq_unknown = 13
44 | case mosq_errno = 14
45 | case mosq_eai = 15
46 | case mosq_err_proxy = 16
47 |
48 | case unknown = 256
49 |
50 | public var description: String {
51 | switch self {
52 | case .disconnect_requested:
53 | return "Disconnect_Requested"
54 | case .keepAlive_timeout:
55 | return "KeepAlive_Timeout"
56 | case .mosq_no_conn:
57 | return "MOSQ_NO_CONN"
58 | case .mosq_conn_lost:
59 | return "MOSQ_CONN_LOST"
60 | case .mosq_errno:
61 | return "MOSQ_ERRNO"
62 | case .unknown:
63 | return "Unknown"
64 | default:
65 | return self.rawValue.description
66 | }
67 | }
68 | }
69 |
70 | public enum MosqResult: Int {
71 | case mosq_conn_pending = -1
72 | case mosq_success = 0
73 | case mosq_nomem = 1
74 | case mosq_protocol = 2
75 | case mosq_inval = 3
76 | case mosq_no_conn = 4
77 | case mosq_conn_refused = 5
78 | case mosq_not_found = 6
79 | case mosq_conn_lost = 7
80 | case mosq_tls = 8
81 | case mosq_payload_size = 9
82 | case mosq_not_supported = 10
83 | case mosq_auth = 11
84 | case mosq_acl_denied = 12
85 | case mosq_unknown = 13
86 | case mosq_errno = 14
87 | case mosq_eai = 15
88 | case mosq_err_proxy = 16
89 | }
90 |
91 | public struct Qos {
92 | public static let at_most_once: Int32 = 0 // Fire and Forget, i.e. <=1
93 | public static let at_least_once: Int32 = 1 // Acknowledged delivery, i.e. >=1
94 | public static let exactly_once: Int32 = 2 // Assured delivery, i.e. =1
95 | }
96 |
97 | public func moscapsule_init() {
98 | mosquitto_lib_init()
99 | }
100 |
101 | public func moscapsule_cleanup() {
102 | mosquitto_lib_cleanup()
103 | }
104 |
105 | public struct MQTTReconnOpts {
106 | public let reconnect_delay_s: UInt32
107 | public let reconnect_delay_max_s: UInt32
108 | public let reconnect_exponential_backoff: Bool
109 |
110 | public init(delay: UInt32, max: UInt32, exponentialBackoff: Bool) {
111 | reconnect_delay_max_s = max
112 | reconnect_exponential_backoff = exponentialBackoff
113 | reconnect_delay_s = delay
114 | }
115 | }
116 |
117 | public struct MQTTWillOpts {
118 | public let topic: String
119 | public let payload: Data
120 | public let qos: Int32
121 | public let retain: Bool
122 |
123 | public init(topic: String, payload: Data, qos: Int32, retain: Bool) {
124 | self.topic = topic
125 | self.payload = payload
126 | self.qos = qos
127 | self.retain = retain
128 | }
129 |
130 | public init(topic: String, payload: String, qos: Int32, retain: Bool) {
131 | let rawPayload = payload.data(using: .utf8)!
132 | self.init(topic: topic, payload: rawPayload, qos: qos, retain: retain)
133 | }
134 | }
135 |
136 | public struct MQTTAuthOpts {
137 | public let username: String
138 | public let password: String
139 |
140 | public init(username: String, password: String) {
141 | self.username = username
142 | self.password = password
143 | }
144 | }
145 |
146 | public struct MQTTPublishOpts {
147 | public let max_inflight_messages: UInt32
148 | public let message_retry: UInt32
149 |
150 | public init(max_inflight_messages: UInt32, message_retry: UInt32) {
151 | self.max_inflight_messages = max_inflight_messages
152 | self.message_retry = message_retry
153 | }
154 | }
155 |
156 | public struct MQTTServerCert {
157 | public let cafile: String?
158 | public let capath: String?
159 |
160 | public init(cafile: String?, capath: String?) {
161 | self.cafile = cafile
162 | self.capath = capath
163 | }
164 | }
165 |
166 | public struct MQTTClientCert {
167 | public let certfile: String
168 | public let keyfile: String
169 | public let keyfile_passwd: String?
170 |
171 | public init(certfile: String, keyfile: String, keyfile_passwd: String?) {
172 | self.certfile = certfile
173 | self.keyfile = keyfile
174 | self.keyfile_passwd = keyfile_passwd
175 | }
176 | }
177 |
178 | public enum CertReqs: Int32 {
179 | case ssl_verify_none = 0
180 | case ssl_verify_peer = 1
181 | }
182 |
183 | public struct MQTTTlsOpts {
184 | public let tls_insecure: Bool
185 | public let cert_reqs: CertReqs
186 | public let tls_version: String?
187 | public let ciphers: String?
188 |
189 | public init(tls_insecure: Bool, cert_reqs: CertReqs, tls_version: String?, ciphers: String?) {
190 | self.tls_insecure = tls_insecure
191 | self.cert_reqs = cert_reqs
192 | self.tls_version = tls_version
193 | self.ciphers = ciphers
194 | }
195 | }
196 |
197 | public struct MQTTPsk {
198 | public let psk: String
199 | public let identity: String
200 | public let ciphers: String?
201 |
202 | public init(psk: String, identity: String, ciphers: String?) {
203 | self.psk = psk
204 | self.identity = identity
205 | self.ciphers = ciphers
206 | }
207 | }
208 |
209 | public struct MQTTMessage {
210 | public let messageId: Int
211 | public let topic: String
212 | public let payload: Data?
213 | public let qos: Int32
214 | public let retain: Bool
215 |
216 | public init(messageId: Int, topic: String, payload: Data?, qos: Int32, retain: Bool) {
217 | self.messageId = messageId
218 | self.topic = topic
219 | self.payload = payload
220 | self.qos = qos
221 | self.retain = retain
222 | }
223 |
224 | public var payloadString: String? {
225 | guard let payload = payload else {
226 | return nil
227 | }
228 |
229 | let encodingsToTry: [String.Encoding] = [
230 | .utf8, .ascii, .utf16, .utf16BigEndian,
231 | .utf16LittleEndian, .utf32, .utf32BigEndian,
232 | .utf32LittleEndian, .nextstep, .japaneseEUC,
233 | .isoLatin1, .symbol, .nonLossyASCII, .shiftJIS,
234 | .isoLatin2, .unicode, .windowsCP1250, .windowsCP1251,
235 | .windowsCP1252, .windowsCP1253, .windowsCP1254,
236 | .iso2022JP, .macOSRoman
237 | ]
238 |
239 | for encoding in encodingsToTry {
240 | if let string = String(data: payload, encoding: encoding) {
241 | return string
242 | }
243 | }
244 |
245 | let hexString = (payload as Data).map { String(format: "%02.2hhx", $0) }.joined()
246 | return hexString
247 | }
248 | }
249 |
250 | public enum MQTTProtocol: Int32 {
251 | case v3_1 = 0
252 | case v3_1_1 = 1
253 | }
254 |
255 | public final class MQTTConfig {
256 | public let clientId: String
257 | public let host: String
258 | public let port: Int32
259 | public let keepAlive: Int32
260 | public let protocolVersion: MQTTProtocol
261 | public var cleanSession: Bool
262 | public var mqttReconnOpts: MQTTReconnOpts?
263 | public var mqttWillOpts: MQTTWillOpts?
264 | public var mqttAuthOpts: MQTTAuthOpts?
265 | public var mqttPublishOpts: MQTTPublishOpts?
266 | public var mqttServerCert: MQTTServerCert?
267 | public var mqttClientCert: MQTTClientCert?
268 | public var mqttTlsOpts: MQTTTlsOpts?
269 | public var mqttPsk: MQTTPsk?
270 |
271 | public var onConnectCallback: ((_ returnCode: ReturnCode) -> ())!
272 | public var onDisconnectCallback: ((_ reasonCode: ReasonCode) -> ())!
273 | public var onPublishCallback: ((_ messageId: Int) -> ())!
274 | public var onMessageCallback: ((_ mqttMessage: MQTTMessage) -> ())!
275 | public var onSubscribeCallback: ((_ messageId: Int, _ grantedQos: Array) -> ())!
276 | public var onUnsubscribeCallback: ((_ messageId: Int) -> ())!
277 |
278 | public init(clientId: String, host: String, port: Int32, keepAlive: Int32, protocolVersion: MQTTProtocol = .v3_1) {
279 | self.clientId = clientId
280 | self.host = host
281 | self.port = port
282 | self.keepAlive = keepAlive
283 | self.protocolVersion = protocolVersion
284 | self.cleanSession = true
285 | mqttReconnOpts = MQTTReconnOpts(delay: 1, max: 60 * 30, exponentialBackoff: true)
286 | }
287 | }
288 |
289 | public final class __MosquittoContext : NSObject {
290 | @objc public var mosquittoHandler: OpaquePointer? = nil
291 | @objc public var isConnected: Bool = false
292 | @objc public var onConnectCallback: ((_ returnCode: Int) -> ())!
293 | @objc public var onDisconnectCallback: ((_ reasonCode: Int) -> ())!
294 | @objc public var onPublishCallback: ((_ messageId: Int) -> ())!
295 | @objc public var onMessageCallback: ((_ message: UnsafePointer) -> ())!
296 | @objc public var onSubscribeCallback: ((_ messageId: Int, _ qosCount: Int, _ grantedQos: UnsafePointer) -> ())!
297 | @objc public var onUnsubscribeCallback: ((_ messageId: Int) -> ())!
298 | @objc public var keyfile_passwd: String = ""
299 | internal override init(){}
300 | }
301 |
302 | public final class MQTT {
303 | public class func newConnection(_ mqttConfig: MQTTConfig, connectImmediately: Bool = true) -> MQTTClient {
304 | let mosquittoContext = __MosquittoContext()
305 | mosquittoContext.onConnectCallback = onConnectAdapter(mqttConfig.onConnectCallback)
306 | mosquittoContext.onDisconnectCallback = onDisconnectAdapter(mqttConfig.onDisconnectCallback)
307 | mosquittoContext.onPublishCallback = mqttConfig.onPublishCallback
308 | mosquittoContext.onMessageCallback = onMessageAdapter(mqttConfig.onMessageCallback)
309 | mosquittoContext.onSubscribeCallback = onSubscribeAdapter(mqttConfig.onSubscribeCallback)
310 | mosquittoContext.onUnsubscribeCallback = mqttConfig.onUnsubscribeCallback
311 |
312 | let protocolVersion: Int32
313 | switch mqttConfig.protocolVersion {
314 | case .v3_1:
315 | protocolVersion = MQTT_PROTOCOL_V31
316 | case .v3_1_1:
317 | protocolVersion = MQTT_PROTOCOL_V311
318 | }
319 |
320 | // setup mosquittoHandler
321 | mosquitto_context_setup(mqttConfig.clientId.cCharArray, mqttConfig.cleanSession, mosquittoContext, protocolVersion)
322 | // set MQTT Reconnection Options
323 | if let options = mqttConfig.mqttReconnOpts {
324 | mosquitto_reconnect_delay_set(mosquittoContext.mosquittoHandler,
325 | options.reconnect_delay_s,
326 | options.reconnect_delay_max_s,
327 | options.reconnect_exponential_backoff)
328 | } else {
329 | mosquitto_reconnect_disable(mosquittoContext.mosquittoHandler)
330 | }
331 |
332 | // set MQTT Will Options
333 | if let mqttWillOpts = mqttConfig.mqttWillOpts {
334 | mqttWillOpts.payload.withUnsafeBytes { p -> Void in
335 | mosquitto_will_set(mosquittoContext.mosquittoHandler, mqttWillOpts.topic.cCharArray,
336 | Int32(mqttWillOpts.payload.count), p,
337 | mqttWillOpts.qos, mqttWillOpts.retain)
338 | }
339 | }
340 |
341 | // set MQTT Authentication Options
342 | if let mqttAuthOpts = mqttConfig.mqttAuthOpts {
343 | mosquitto_username_pw_set(mosquittoContext.mosquittoHandler, mqttAuthOpts.username.cCharArray, mqttAuthOpts.password.cCharArray)
344 | }
345 |
346 | // set MQTT Publish Options
347 | if let mqttPublishOpts = mqttConfig.mqttPublishOpts {
348 | mosquitto_max_inflight_messages_set(mosquittoContext.mosquittoHandler, mqttPublishOpts.max_inflight_messages)
349 | mosquitto_message_retry_set(mosquittoContext.mosquittoHandler, mqttPublishOpts.message_retry)
350 | }
351 |
352 | // set Server/Client Certificate
353 | if mqttConfig.mqttServerCert != nil || mqttConfig.mqttClientCert != nil {
354 | let sc = mqttConfig.mqttServerCert
355 | let cc = mqttConfig.mqttClientCert
356 | mosquittoContext.keyfile_passwd = cc?.keyfile_passwd ?? ""
357 | mosquitto_tls_set_bridge(sc?.cafile, sc?.capath, cc?.certfile, cc?.keyfile, mosquittoContext)
358 | }
359 |
360 | // set TLS Options
361 | if let mqttTlsOpts = mqttConfig.mqttTlsOpts {
362 | mosquitto_tls_insecure_set(mosquittoContext.mosquittoHandler, mqttTlsOpts.tls_insecure)
363 | mosquitto_tls_opts_set_bridge(mqttTlsOpts.cert_reqs.rawValue, mqttTlsOpts.tls_version, mqttTlsOpts.ciphers, mosquittoContext)
364 | }
365 |
366 | // set PSK
367 | if let mqttPsk = mqttConfig.mqttPsk {
368 | mosquitto_tls_psk_set_bridge(mqttPsk.psk, mqttPsk.identity, mqttPsk.ciphers, mosquittoContext)
369 | }
370 |
371 | // start MQTTClient
372 | let mqttClient = MQTTClient(mosquittoContext: mosquittoContext, clientId: mqttConfig.clientId)
373 | if connectImmediately {
374 | mqttClient.connectTo(host: mqttConfig.host, port: mqttConfig.port, keepAlive: mqttConfig.keepAlive)
375 | }
376 |
377 | return mqttClient
378 | }
379 |
380 | private class func onConnectAdapter(_ callback: ((ReturnCode) -> ())!) -> ((_ returnCode: Int) -> ())! {
381 | return callback == nil ? nil : { (rawReturnCode: Int) in
382 | callback(ReturnCode(rawValue: rawReturnCode) ?? ReturnCode.unknown)
383 | }
384 | }
385 |
386 | private class func onDisconnectAdapter(_ callback: ((ReasonCode) -> ())!) -> ((_ reasonCode: Int) -> ())! {
387 | return callback == nil ? nil : { (rawReasonCode: Int) in
388 | callback(ReasonCode(rawValue: rawReasonCode) ?? ReasonCode.unknown)
389 | }
390 | }
391 |
392 | private class func onMessageAdapter(_ callback: ((MQTTMessage) -> ())!) -> ((UnsafePointer) -> ())! {
393 | return callback == nil ? nil : { (rawMessage: UnsafePointer) in
394 | let message = rawMessage.pointee
395 | // If there are issues with topic string, drop message on the floor
396 | let topic = String(cString: message.topic)
397 | let payload: Data? = message.payload != nil ?
398 | Data(bytes: message.payload, count: Int(message.payloadlen)) : nil
399 | let mqttMessage = MQTTMessage(messageId: Int(message.mid), topic: topic, payload: payload, qos: message.qos, retain: message.retain)
400 | callback(mqttMessage)
401 | }
402 | }
403 |
404 | private class func onSubscribeAdapter(_ callback: ((Int, Array) -> ())!) -> ((Int, Int, UnsafePointer) -> ())! {
405 | return callback == nil ? nil : { (messageId: Int, qosCount: Int, grantedQos: UnsafePointer) in
406 | var grantedQosList = [Int32](repeating: Qos.at_least_once, count: qosCount)
407 | let _ = Array(0.. ()) {
427 | let mosqContext = self.mosquittoContext
428 | serialQueue.addOperation {
429 | operation(mosqContext)
430 | }
431 | }
432 |
433 | internal init(mosquittoContext: __MosquittoContext, clientId: String) {
434 | self.mosquittoContext = mosquittoContext
435 | self.clientId = clientId
436 | self.isRunning = false
437 | self.serialQueue = OperationQueue()
438 | self.serialQueue.name = "MQTT Client Operation Queue (\(clientId))"
439 | self.serialQueue.maxConcurrentOperationCount = 1
440 | }
441 |
442 | deinit {
443 | disconnect()
444 | addRequestToQueue { mosqContext in
445 | mosquitto_context_cleanup(mosqContext)
446 | }
447 | }
448 |
449 | public func publish(_ payload: Data, topic: String, qos: Int32, retain: Bool, requestCompletion: ((MosqResult, Int) -> ())? = nil) {
450 | addRequestToQueue { mosqContext in
451 | var messageId: Int32 = 0
452 | let bytes = Array(payload)
453 | let mosqReturn = mosquitto_publish(mosqContext.mosquittoHandler, &messageId, topic.cCharArray, Int32(payload.count), bytes, qos, retain)
454 | requestCompletion?(MosqResult(rawValue: Int(mosqReturn)) ?? MosqResult.mosq_unknown, Int(messageId))
455 | }
456 | }
457 |
458 | public func publish(string payload: String, topic: String, qos: Int32, retain: Bool, requestCompletion: ((MosqResult, Int) -> ())? = nil) {
459 | if let payloadData = payload.data(using: .utf8) {
460 | publish(payloadData, topic: topic, qos: qos, retain: retain, requestCompletion: requestCompletion)
461 | }
462 | }
463 |
464 | public func subscribe(_ topic: String, qos: Int32, requestCompletion: ((MosqResult, Int) -> ())? = nil) {
465 | addRequestToQueue { mosqContext in
466 | var messageId: Int32 = 0
467 | let mosqReturn = mosquitto_subscribe(mosqContext.mosquittoHandler, &messageId, topic.cCharArray, qos)
468 | requestCompletion?(MosqResult(rawValue: Int(mosqReturn)) ?? MosqResult.mosq_unknown, Int(messageId))
469 | }
470 | }
471 |
472 | public func unsubscribe(_ topic: String, requestCompletion: ((MosqResult, Int) -> ())? = nil) {
473 | addRequestToQueue { mosqContext in
474 | var messageId: Int32 = 0
475 | let mosqReturn = mosquitto_unsubscribe(mosqContext.mosquittoHandler, &messageId, topic.cCharArray)
476 | requestCompletion?(MosqResult(rawValue: Int(mosqReturn)) ?? MosqResult.mosq_unknown, Int(messageId))
477 | }
478 | }
479 |
480 | public func connectTo(host: String, port: Int32, keepAlive: Int32, requestCompletion: ((MosqResult) -> ())? = nil) {
481 | self.isRunning = true
482 | addRequestToQueue { mosqContext in
483 | // mosquitto_connect should be called before mosquitto_loop_start.
484 | let mosqReturn = mosquitto_connect(mosqContext.mosquittoHandler, host, port, keepAlive)
485 | mosquitto_loop_start(mosqContext.mosquittoHandler)
486 | requestCompletion?(MosqResult(rawValue: Int(mosqReturn)) ?? MosqResult.mosq_unknown)
487 | }
488 | }
489 |
490 | public func reconnect(_ requestCompletion: ((MosqResult) -> ())? = nil) {
491 | self.isRunning = true
492 | addRequestToQueue { mosqContext in
493 | // mosquitto_reconnect should be called before mosquitto_loop_start.
494 | let mosqReturn = mosquitto_reconnect(mosqContext.mosquittoHandler)
495 | mosquitto_loop_start(mosqContext.mosquittoHandler)
496 | requestCompletion?(MosqResult(rawValue: Int(mosqReturn)) ?? MosqResult.mosq_unknown)
497 | }
498 | }
499 |
500 | public func disconnect(_ requestCompletion: ((MosqResult) -> ())? = nil) {
501 | guard isRunning == true
502 | else { requestCompletion?(.mosq_success); return }
503 |
504 | self.isRunning = false
505 | addRequestToQueue { mosqContext in
506 | let mosqReturn = mosquitto_disconnect(mosqContext.mosquittoHandler)
507 | mosquitto_loop_stop(mosqContext.mosquittoHandler, false)
508 | requestCompletion?(MosqResult(rawValue: Int(mosqReturn)) ?? MosqResult.mosq_unknown)
509 | }
510 | }
511 |
512 | public func awaitRequestCompletion() {
513 | serialQueue.waitUntilAllOperationsAreFinished()
514 | }
515 |
516 | public var socket: Int32? {
517 | let sock = mosquitto_socket(mosquittoContext.mosquittoHandler)
518 | return (sock == -1 ? nil : sock)
519 | }
520 | }
521 |
522 | private extension String {
523 | var cCharArray: [CChar] {
524 | return self.cString(using: .utf8)!
525 | }
526 | }
527 |
--------------------------------------------------------------------------------
/Moscapsule.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 094821041B0E2EB600099178 /* socks_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 094821021B0E2EB600099178 /* socks_mosq.c */; };
11 | 094821051B0E2EB600099178 /* socks_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 094821031B0E2EB600099178 /* socks_mosq.h */; };
12 | 09CF6B191A21F78700A97383 /* Moscapsule.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B181A21F78700A97383 /* Moscapsule.h */; settings = {ATTRIBUTES = (Public, ); }; };
13 | 09CF6B1F1A21F78700A97383 /* Moscapsule.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09CF6B131A21F78700A97383 /* Moscapsule.framework */; };
14 | 09CF6B261A21F78700A97383 /* MoscapsuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B251A21F78700A97383 /* MoscapsuleTests.swift */; };
15 | 09CF6B4F1A21F7E600A97383 /* dummypthread.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B311A21F7E600A97383 /* dummypthread.h */; };
16 | 09CF6B501A21F7E600A97383 /* logging_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B321A21F7E600A97383 /* logging_mosq.c */; };
17 | 09CF6B511A21F7E600A97383 /* logging_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B331A21F7E600A97383 /* logging_mosq.h */; };
18 | 09CF6B521A21F7E600A97383 /* memory_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B341A21F7E600A97383 /* memory_mosq.c */; };
19 | 09CF6B531A21F7E600A97383 /* memory_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B351A21F7E600A97383 /* memory_mosq.h */; };
20 | 09CF6B541A21F7E600A97383 /* messages_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B361A21F7E600A97383 /* messages_mosq.c */; };
21 | 09CF6B551A21F7E600A97383 /* messages_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B371A21F7E600A97383 /* messages_mosq.h */; };
22 | 09CF6B561A21F7E600A97383 /* mosquitto_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B381A21F7E600A97383 /* mosquitto_internal.h */; };
23 | 09CF6B571A21F7E600A97383 /* mosquitto.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B391A21F7E600A97383 /* mosquitto.c */; };
24 | 09CF6B581A21F7E600A97383 /* mosquitto.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B3A1A21F7E600A97383 /* mosquitto.h */; settings = {ATTRIBUTES = (Public, ); }; };
25 | 09CF6B591A21F7E600A97383 /* mqtt3_protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B3B1A21F7E600A97383 /* mqtt3_protocol.h */; };
26 | 09CF6B5A1A21F7E600A97383 /* net_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B3C1A21F7E600A97383 /* net_mosq.c */; };
27 | 09CF6B5B1A21F7E600A97383 /* net_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B3D1A21F7E600A97383 /* net_mosq.h */; };
28 | 09CF6B5C1A21F7E600A97383 /* read_handle_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B3E1A21F7E600A97383 /* read_handle_client.c */; };
29 | 09CF6B5D1A21F7E600A97383 /* read_handle_shared.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B3F1A21F7E600A97383 /* read_handle_shared.c */; };
30 | 09CF6B5E1A21F7E600A97383 /* read_handle.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B401A21F7E600A97383 /* read_handle.c */; };
31 | 09CF6B5F1A21F7E600A97383 /* read_handle.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B411A21F7E600A97383 /* read_handle.h */; };
32 | 09CF6B601A21F7E600A97383 /* send_client_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B421A21F7E600A97383 /* send_client_mosq.c */; };
33 | 09CF6B611A21F7E600A97383 /* send_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B431A21F7E600A97383 /* send_mosq.c */; };
34 | 09CF6B621A21F7E600A97383 /* send_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B441A21F7E600A97383 /* send_mosq.h */; };
35 | 09CF6B631A21F7E600A97383 /* srv_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B451A21F7E600A97383 /* srv_mosq.c */; };
36 | 09CF6B641A21F7E600A97383 /* thread_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B461A21F7E600A97383 /* thread_mosq.c */; };
37 | 09CF6B651A21F7E600A97383 /* time_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B471A21F7E600A97383 /* time_mosq.c */; };
38 | 09CF6B661A21F7E600A97383 /* time_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B481A21F7E600A97383 /* time_mosq.h */; };
39 | 09CF6B671A21F7E600A97383 /* tls_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B491A21F7E600A97383 /* tls_mosq.c */; };
40 | 09CF6B681A21F7E600A97383 /* tls_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B4A1A21F7E600A97383 /* tls_mosq.h */; };
41 | 09CF6B691A21F7E600A97383 /* util_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B4B1A21F7E600A97383 /* util_mosq.c */; };
42 | 09CF6B6A1A21F7E600A97383 /* util_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B4C1A21F7E600A97383 /* util_mosq.h */; };
43 | 09CF6B6B1A21F7E600A97383 /* will_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B4D1A21F7E600A97383 /* will_mosq.c */; };
44 | 09CF6B6C1A21F7E600A97383 /* will_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B4E1A21F7E600A97383 /* will_mosq.h */; };
45 | 09CF6B6E1A21F82600A97383 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 09CF6B6D1A21F82600A97383 /* config.h */; };
46 | 09CF6B701A21F88000A97383 /* Moscapsule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09CF6B6F1A21F88000A97383 /* Moscapsule.swift */; };
47 | 09FB79171BB6FA4100B22BAA /* cert.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 09FB79161BB6FA4100B22BAA /* cert.bundle */; };
48 | C7360CC31A2435A8001F490F /* MosquittoCallbackBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = C7360CC21A2435A8001F490F /* MosquittoCallbackBridge.m */; };
49 | C7360CC51A243AB9001F490F /* MosquittoCallbackBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = C7360CC41A243949001F490F /* MosquittoCallbackBridge.h */; settings = {ATTRIBUTES = (Public, ); }; };
50 | /* End PBXBuildFile section */
51 |
52 | /* Begin PBXContainerItemProxy section */
53 | 09CF6B201A21F78700A97383 /* PBXContainerItemProxy */ = {
54 | isa = PBXContainerItemProxy;
55 | containerPortal = 09CF6B0A1A21F78700A97383 /* Project object */;
56 | proxyType = 1;
57 | remoteGlobalIDString = 09CF6B121A21F78700A97383;
58 | remoteInfo = Moscapsule;
59 | };
60 | /* End PBXContainerItemProxy section */
61 |
62 | /* Begin PBXFileReference section */
63 | 094821021B0E2EB600099178 /* socks_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = socks_mosq.c; path = mosquitto/lib/socks_mosq.c; sourceTree = ""; };
64 | 094821031B0E2EB600099178 /* socks_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = socks_mosq.h; path = mosquitto/lib/socks_mosq.h; sourceTree = ""; };
65 | 09CF6B131A21F78700A97383 /* Moscapsule.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Moscapsule.framework; sourceTree = BUILT_PRODUCTS_DIR; };
66 | 09CF6B171A21F78700A97383 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
67 | 09CF6B181A21F78700A97383 /* Moscapsule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Moscapsule.h; sourceTree = ""; };
68 | 09CF6B1E1A21F78700A97383 /* MoscapsuleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MoscapsuleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
69 | 09CF6B241A21F78700A97383 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
70 | 09CF6B251A21F78700A97383 /* MoscapsuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoscapsuleTests.swift; sourceTree = ""; };
71 | 09CF6B311A21F7E600A97383 /* dummypthread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dummypthread.h; path = mosquitto/lib/dummypthread.h; sourceTree = ""; };
72 | 09CF6B321A21F7E600A97383 /* logging_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = logging_mosq.c; path = mosquitto/lib/logging_mosq.c; sourceTree = ""; };
73 | 09CF6B331A21F7E600A97383 /* logging_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = logging_mosq.h; path = mosquitto/lib/logging_mosq.h; sourceTree = ""; };
74 | 09CF6B341A21F7E600A97383 /* memory_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = memory_mosq.c; path = mosquitto/lib/memory_mosq.c; sourceTree = ""; };
75 | 09CF6B351A21F7E600A97383 /* memory_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = memory_mosq.h; path = mosquitto/lib/memory_mosq.h; sourceTree = ""; };
76 | 09CF6B361A21F7E600A97383 /* messages_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = messages_mosq.c; path = mosquitto/lib/messages_mosq.c; sourceTree = ""; };
77 | 09CF6B371A21F7E600A97383 /* messages_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = messages_mosq.h; path = mosquitto/lib/messages_mosq.h; sourceTree = ""; };
78 | 09CF6B381A21F7E600A97383 /* mosquitto_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mosquitto_internal.h; path = mosquitto/lib/mosquitto_internal.h; sourceTree = ""; };
79 | 09CF6B391A21F7E600A97383 /* mosquitto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mosquitto.c; path = mosquitto/lib/mosquitto.c; sourceTree = ""; };
80 | 09CF6B3A1A21F7E600A97383 /* mosquitto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mosquitto.h; path = mosquitto/lib/mosquitto.h; sourceTree = ""; };
81 | 09CF6B3B1A21F7E600A97383 /* mqtt3_protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mqtt3_protocol.h; path = mosquitto/lib/mqtt3_protocol.h; sourceTree = ""; };
82 | 09CF6B3C1A21F7E600A97383 /* net_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = net_mosq.c; path = mosquitto/lib/net_mosq.c; sourceTree = ""; };
83 | 09CF6B3D1A21F7E600A97383 /* net_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = net_mosq.h; path = mosquitto/lib/net_mosq.h; sourceTree = ""; };
84 | 09CF6B3E1A21F7E600A97383 /* read_handle_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = read_handle_client.c; path = mosquitto/lib/read_handle_client.c; sourceTree = ""; };
85 | 09CF6B3F1A21F7E600A97383 /* read_handle_shared.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = read_handle_shared.c; path = mosquitto/lib/read_handle_shared.c; sourceTree = ""; };
86 | 09CF6B401A21F7E600A97383 /* read_handle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = read_handle.c; path = mosquitto/lib/read_handle.c; sourceTree = ""; };
87 | 09CF6B411A21F7E600A97383 /* read_handle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = read_handle.h; path = mosquitto/lib/read_handle.h; sourceTree = ""; };
88 | 09CF6B421A21F7E600A97383 /* send_client_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = send_client_mosq.c; path = mosquitto/lib/send_client_mosq.c; sourceTree = ""; };
89 | 09CF6B431A21F7E600A97383 /* send_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = send_mosq.c; path = mosquitto/lib/send_mosq.c; sourceTree = ""; };
90 | 09CF6B441A21F7E600A97383 /* send_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = send_mosq.h; path = mosquitto/lib/send_mosq.h; sourceTree = ""; };
91 | 09CF6B451A21F7E600A97383 /* srv_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srv_mosq.c; path = mosquitto/lib/srv_mosq.c; sourceTree = ""; };
92 | 09CF6B461A21F7E600A97383 /* thread_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = thread_mosq.c; path = mosquitto/lib/thread_mosq.c; sourceTree = ""; };
93 | 09CF6B471A21F7E600A97383 /* time_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = time_mosq.c; path = mosquitto/lib/time_mosq.c; sourceTree = ""; };
94 | 09CF6B481A21F7E600A97383 /* time_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = time_mosq.h; path = mosquitto/lib/time_mosq.h; sourceTree = ""; };
95 | 09CF6B491A21F7E600A97383 /* tls_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tls_mosq.c; path = mosquitto/lib/tls_mosq.c; sourceTree = ""; };
96 | 09CF6B4A1A21F7E600A97383 /* tls_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tls_mosq.h; path = mosquitto/lib/tls_mosq.h; sourceTree = ""; };
97 | 09CF6B4B1A21F7E600A97383 /* util_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = util_mosq.c; path = mosquitto/lib/util_mosq.c; sourceTree = ""; };
98 | 09CF6B4C1A21F7E600A97383 /* util_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util_mosq.h; path = mosquitto/lib/util_mosq.h; sourceTree = ""; };
99 | 09CF6B4D1A21F7E600A97383 /* will_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = will_mosq.c; path = mosquitto/lib/will_mosq.c; sourceTree = ""; };
100 | 09CF6B4E1A21F7E600A97383 /* will_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = will_mosq.h; path = mosquitto/lib/will_mosq.h; sourceTree = ""; };
101 | 09CF6B6D1A21F82600A97383 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = Moscapsule/config.h; sourceTree = ""; };
102 | 09CF6B6F1A21F88000A97383 /* Moscapsule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Moscapsule.swift; sourceTree = ""; };
103 | 09FB79161BB6FA4100B22BAA /* cert.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = cert.bundle; sourceTree = ""; };
104 | C7360CC21A2435A8001F490F /* MosquittoCallbackBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MosquittoCallbackBridge.m; sourceTree = ""; };
105 | C7360CC41A243949001F490F /* MosquittoCallbackBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MosquittoCallbackBridge.h; sourceTree = ""; };
106 | C7D24C911A3E94AC00C33384 /* download_mosquitto.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = download_mosquitto.sh; sourceTree = SOURCE_ROOT; };
107 | /* End PBXFileReference section */
108 |
109 | /* Begin PBXFrameworksBuildPhase section */
110 | 09CF6B0F1A21F78700A97383 /* Frameworks */ = {
111 | isa = PBXFrameworksBuildPhase;
112 | buildActionMask = 2147483647;
113 | files = (
114 | );
115 | runOnlyForDeploymentPostprocessing = 0;
116 | };
117 | 09CF6B1B1A21F78700A97383 /* Frameworks */ = {
118 | isa = PBXFrameworksBuildPhase;
119 | buildActionMask = 2147483647;
120 | files = (
121 | 09CF6B1F1A21F78700A97383 /* Moscapsule.framework in Frameworks */,
122 | );
123 | runOnlyForDeploymentPostprocessing = 0;
124 | };
125 | /* End PBXFrameworksBuildPhase section */
126 |
127 | /* Begin PBXGroup section */
128 | 09CF6B091A21F78700A97383 = {
129 | isa = PBXGroup;
130 | children = (
131 | 09CF6B2F1A21F7C600A97383 /* mosquitto */,
132 | 09CF6B151A21F78700A97383 /* Moscapsule */,
133 | 09CF6B221A21F78700A97383 /* MoscapsuleTests */,
134 | 09CF6B141A21F78700A97383 /* Products */,
135 | );
136 | sourceTree = "";
137 | };
138 | 09CF6B141A21F78700A97383 /* Products */ = {
139 | isa = PBXGroup;
140 | children = (
141 | 09CF6B131A21F78700A97383 /* Moscapsule.framework */,
142 | 09CF6B1E1A21F78700A97383 /* MoscapsuleTests.xctest */,
143 | );
144 | name = Products;
145 | sourceTree = "";
146 | };
147 | 09CF6B151A21F78700A97383 /* Moscapsule */ = {
148 | isa = PBXGroup;
149 | children = (
150 | 09CF6B6F1A21F88000A97383 /* Moscapsule.swift */,
151 | 09CF6B181A21F78700A97383 /* Moscapsule.h */,
152 | 09CF6B161A21F78700A97383 /* Supporting Files */,
153 | C7360CC21A2435A8001F490F /* MosquittoCallbackBridge.m */,
154 | C7360CC41A243949001F490F /* MosquittoCallbackBridge.h */,
155 | );
156 | path = Moscapsule;
157 | sourceTree = "";
158 | };
159 | 09CF6B161A21F78700A97383 /* Supporting Files */ = {
160 | isa = PBXGroup;
161 | children = (
162 | C7D24C911A3E94AC00C33384 /* download_mosquitto.sh */,
163 | 09CF6B171A21F78700A97383 /* Info.plist */,
164 | );
165 | name = "Supporting Files";
166 | sourceTree = "";
167 | };
168 | 09CF6B221A21F78700A97383 /* MoscapsuleTests */ = {
169 | isa = PBXGroup;
170 | children = (
171 | 09CF6B251A21F78700A97383 /* MoscapsuleTests.swift */,
172 | 09FB79161BB6FA4100B22BAA /* cert.bundle */,
173 | 09CF6B231A21F78700A97383 /* Supporting Files */,
174 | );
175 | path = MoscapsuleTests;
176 | sourceTree = "";
177 | };
178 | 09CF6B231A21F78700A97383 /* Supporting Files */ = {
179 | isa = PBXGroup;
180 | children = (
181 | 09CF6B241A21F78700A97383 /* Info.plist */,
182 | );
183 | name = "Supporting Files";
184 | sourceTree = "";
185 | };
186 | 09CF6B2F1A21F7C600A97383 /* mosquitto */ = {
187 | isa = PBXGroup;
188 | children = (
189 | 09CF6B301A21F7D100A97383 /* lib */,
190 | );
191 | name = mosquitto;
192 | sourceTree = "";
193 | };
194 | 09CF6B301A21F7D100A97383 /* lib */ = {
195 | isa = PBXGroup;
196 | children = (
197 | 09CF6B6D1A21F82600A97383 /* config.h */,
198 | 09CF6B311A21F7E600A97383 /* dummypthread.h */,
199 | 09CF6B321A21F7E600A97383 /* logging_mosq.c */,
200 | 09CF6B331A21F7E600A97383 /* logging_mosq.h */,
201 | 09CF6B341A21F7E600A97383 /* memory_mosq.c */,
202 | 09CF6B351A21F7E600A97383 /* memory_mosq.h */,
203 | 09CF6B361A21F7E600A97383 /* messages_mosq.c */,
204 | 09CF6B371A21F7E600A97383 /* messages_mosq.h */,
205 | 09CF6B381A21F7E600A97383 /* mosquitto_internal.h */,
206 | 09CF6B391A21F7E600A97383 /* mosquitto.c */,
207 | 09CF6B3A1A21F7E600A97383 /* mosquitto.h */,
208 | 09CF6B3B1A21F7E600A97383 /* mqtt3_protocol.h */,
209 | 09CF6B3C1A21F7E600A97383 /* net_mosq.c */,
210 | 09CF6B3D1A21F7E600A97383 /* net_mosq.h */,
211 | 09CF6B3E1A21F7E600A97383 /* read_handle_client.c */,
212 | 09CF6B3F1A21F7E600A97383 /* read_handle_shared.c */,
213 | 09CF6B401A21F7E600A97383 /* read_handle.c */,
214 | 09CF6B411A21F7E600A97383 /* read_handle.h */,
215 | 09CF6B421A21F7E600A97383 /* send_client_mosq.c */,
216 | 09CF6B431A21F7E600A97383 /* send_mosq.c */,
217 | 09CF6B441A21F7E600A97383 /* send_mosq.h */,
218 | 094821021B0E2EB600099178 /* socks_mosq.c */,
219 | 094821031B0E2EB600099178 /* socks_mosq.h */,
220 | 09CF6B451A21F7E600A97383 /* srv_mosq.c */,
221 | 09CF6B461A21F7E600A97383 /* thread_mosq.c */,
222 | 09CF6B471A21F7E600A97383 /* time_mosq.c */,
223 | 09CF6B481A21F7E600A97383 /* time_mosq.h */,
224 | 09CF6B491A21F7E600A97383 /* tls_mosq.c */,
225 | 09CF6B4A1A21F7E600A97383 /* tls_mosq.h */,
226 | 09CF6B4B1A21F7E600A97383 /* util_mosq.c */,
227 | 09CF6B4C1A21F7E600A97383 /* util_mosq.h */,
228 | 09CF6B4D1A21F7E600A97383 /* will_mosq.c */,
229 | 09CF6B4E1A21F7E600A97383 /* will_mosq.h */,
230 | );
231 | name = lib;
232 | sourceTree = "";
233 | };
234 | /* End PBXGroup section */
235 |
236 | /* Begin PBXHeadersBuildPhase section */
237 | 09CF6B101A21F78700A97383 /* Headers */ = {
238 | isa = PBXHeadersBuildPhase;
239 | buildActionMask = 2147483647;
240 | files = (
241 | 09CF6B191A21F78700A97383 /* Moscapsule.h in Headers */,
242 | 09CF6B581A21F7E600A97383 /* mosquitto.h in Headers */,
243 | 09CF6B591A21F7E600A97383 /* mqtt3_protocol.h in Headers */,
244 | C7360CC51A243AB9001F490F /* MosquittoCallbackBridge.h in Headers */,
245 | 09CF6B4F1A21F7E600A97383 /* dummypthread.h in Headers */,
246 | 09CF6B621A21F7E600A97383 /* send_mosq.h in Headers */,
247 | 09CF6B681A21F7E600A97383 /* tls_mosq.h in Headers */,
248 | 09CF6B6E1A21F82600A97383 /* config.h in Headers */,
249 | 09CF6B6A1A21F7E600A97383 /* util_mosq.h in Headers */,
250 | 09CF6B551A21F7E600A97383 /* messages_mosq.h in Headers */,
251 | 09CF6B511A21F7E600A97383 /* logging_mosq.h in Headers */,
252 | 09CF6B561A21F7E600A97383 /* mosquitto_internal.h in Headers */,
253 | 094821051B0E2EB600099178 /* socks_mosq.h in Headers */,
254 | 09CF6B661A21F7E600A97383 /* time_mosq.h in Headers */,
255 | 09CF6B6C1A21F7E600A97383 /* will_mosq.h in Headers */,
256 | 09CF6B5F1A21F7E600A97383 /* read_handle.h in Headers */,
257 | 09CF6B531A21F7E600A97383 /* memory_mosq.h in Headers */,
258 | 09CF6B5B1A21F7E600A97383 /* net_mosq.h in Headers */,
259 | );
260 | runOnlyForDeploymentPostprocessing = 0;
261 | };
262 | /* End PBXHeadersBuildPhase section */
263 |
264 | /* Begin PBXNativeTarget section */
265 | 09CF6B121A21F78700A97383 /* Moscapsule */ = {
266 | isa = PBXNativeTarget;
267 | buildConfigurationList = 09CF6B291A21F78700A97383 /* Build configuration list for PBXNativeTarget "Moscapsule" */;
268 | buildPhases = (
269 | 09CF6B0E1A21F78700A97383 /* Sources */,
270 | 09CF6B0F1A21F78700A97383 /* Frameworks */,
271 | 09CF6B101A21F78700A97383 /* Headers */,
272 | 09CF6B111A21F78700A97383 /* Resources */,
273 | );
274 | buildRules = (
275 | );
276 | dependencies = (
277 | );
278 | name = Moscapsule;
279 | productName = Moscapsule;
280 | productReference = 09CF6B131A21F78700A97383 /* Moscapsule.framework */;
281 | productType = "com.apple.product-type.framework";
282 | };
283 | 09CF6B1D1A21F78700A97383 /* MoscapsuleTests */ = {
284 | isa = PBXNativeTarget;
285 | buildConfigurationList = 09CF6B2C1A21F78700A97383 /* Build configuration list for PBXNativeTarget "MoscapsuleTests" */;
286 | buildPhases = (
287 | 09CF6B1A1A21F78700A97383 /* Sources */,
288 | 09CF6B1B1A21F78700A97383 /* Frameworks */,
289 | 09CF6B1C1A21F78700A97383 /* Resources */,
290 | );
291 | buildRules = (
292 | );
293 | dependencies = (
294 | 09CF6B211A21F78700A97383 /* PBXTargetDependency */,
295 | );
296 | name = MoscapsuleTests;
297 | productName = MoscapsuleTests;
298 | productReference = 09CF6B1E1A21F78700A97383 /* MoscapsuleTests.xctest */;
299 | productType = "com.apple.product-type.bundle.unit-test";
300 | };
301 | /* End PBXNativeTarget section */
302 |
303 | /* Begin PBXProject section */
304 | 09CF6B0A1A21F78700A97383 /* Project object */ = {
305 | isa = PBXProject;
306 | attributes = {
307 | LastSwiftMigration = 0700;
308 | LastSwiftUpdateCheck = 0700;
309 | LastUpgradeCheck = 1030;
310 | ORGANIZATIONNAME = flightonary;
311 | TargetAttributes = {
312 | 09CF6B121A21F78700A97383 = {
313 | CreatedOnToolsVersion = 6.1;
314 | DevelopmentTeam = 2N39544D78;
315 | LastSwiftMigration = 1030;
316 | };
317 | 09CF6B1D1A21F78700A97383 = {
318 | CreatedOnToolsVersion = 6.1;
319 | DevelopmentTeam = 2N39544D78;
320 | LastSwiftMigration = 1030;
321 | };
322 | };
323 | };
324 | buildConfigurationList = 09CF6B0D1A21F78700A97383 /* Build configuration list for PBXProject "Moscapsule" */;
325 | compatibilityVersion = "Xcode 3.2";
326 | developmentRegion = en;
327 | hasScannedForEncodings = 0;
328 | knownRegions = (
329 | en,
330 | Base,
331 | );
332 | mainGroup = 09CF6B091A21F78700A97383;
333 | productRefGroup = 09CF6B141A21F78700A97383 /* Products */;
334 | projectDirPath = "";
335 | projectRoot = "";
336 | targets = (
337 | 09CF6B121A21F78700A97383 /* Moscapsule */,
338 | 09CF6B1D1A21F78700A97383 /* MoscapsuleTests */,
339 | );
340 | };
341 | /* End PBXProject section */
342 |
343 | /* Begin PBXResourcesBuildPhase section */
344 | 09CF6B111A21F78700A97383 /* Resources */ = {
345 | isa = PBXResourcesBuildPhase;
346 | buildActionMask = 2147483647;
347 | files = (
348 | );
349 | runOnlyForDeploymentPostprocessing = 0;
350 | };
351 | 09CF6B1C1A21F78700A97383 /* Resources */ = {
352 | isa = PBXResourcesBuildPhase;
353 | buildActionMask = 2147483647;
354 | files = (
355 | 09FB79171BB6FA4100B22BAA /* cert.bundle in Resources */,
356 | );
357 | runOnlyForDeploymentPostprocessing = 0;
358 | };
359 | /* End PBXResourcesBuildPhase section */
360 |
361 | /* Begin PBXSourcesBuildPhase section */
362 | 09CF6B0E1A21F78700A97383 /* Sources */ = {
363 | isa = PBXSourcesBuildPhase;
364 | buildActionMask = 2147483647;
365 | files = (
366 | 09CF6B5D1A21F7E600A97383 /* read_handle_shared.c in Sources */,
367 | 09CF6B651A21F7E600A97383 /* time_mosq.c in Sources */,
368 | 09CF6B611A21F7E600A97383 /* send_mosq.c in Sources */,
369 | 09CF6B6B1A21F7E600A97383 /* will_mosq.c in Sources */,
370 | 09CF6B701A21F88000A97383 /* Moscapsule.swift in Sources */,
371 | 094821041B0E2EB600099178 /* socks_mosq.c in Sources */,
372 | 09CF6B5A1A21F7E600A97383 /* net_mosq.c in Sources */,
373 | 09CF6B541A21F7E600A97383 /* messages_mosq.c in Sources */,
374 | 09CF6B631A21F7E600A97383 /* srv_mosq.c in Sources */,
375 | 09CF6B571A21F7E600A97383 /* mosquitto.c in Sources */,
376 | C7360CC31A2435A8001F490F /* MosquittoCallbackBridge.m in Sources */,
377 | 09CF6B671A21F7E600A97383 /* tls_mosq.c in Sources */,
378 | 09CF6B601A21F7E600A97383 /* send_client_mosq.c in Sources */,
379 | 09CF6B521A21F7E600A97383 /* memory_mosq.c in Sources */,
380 | 09CF6B5E1A21F7E600A97383 /* read_handle.c in Sources */,
381 | 09CF6B641A21F7E600A97383 /* thread_mosq.c in Sources */,
382 | 09CF6B5C1A21F7E600A97383 /* read_handle_client.c in Sources */,
383 | 09CF6B691A21F7E600A97383 /* util_mosq.c in Sources */,
384 | 09CF6B501A21F7E600A97383 /* logging_mosq.c in Sources */,
385 | );
386 | runOnlyForDeploymentPostprocessing = 0;
387 | };
388 | 09CF6B1A1A21F78700A97383 /* Sources */ = {
389 | isa = PBXSourcesBuildPhase;
390 | buildActionMask = 2147483647;
391 | files = (
392 | 09CF6B261A21F78700A97383 /* MoscapsuleTests.swift in Sources */,
393 | );
394 | runOnlyForDeploymentPostprocessing = 0;
395 | };
396 | /* End PBXSourcesBuildPhase section */
397 |
398 | /* Begin PBXTargetDependency section */
399 | 09CF6B211A21F78700A97383 /* PBXTargetDependency */ = {
400 | isa = PBXTargetDependency;
401 | target = 09CF6B121A21F78700A97383 /* Moscapsule */;
402 | targetProxy = 09CF6B201A21F78700A97383 /* PBXContainerItemProxy */;
403 | };
404 | /* End PBXTargetDependency section */
405 |
406 | /* Begin XCBuildConfiguration section */
407 | 09CF6B271A21F78700A97383 /* Debug */ = {
408 | isa = XCBuildConfiguration;
409 | buildSettings = {
410 | ALWAYS_SEARCH_USER_PATHS = NO;
411 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
412 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
413 | CLANG_CXX_LIBRARY = "libc++";
414 | CLANG_ENABLE_MODULES = YES;
415 | CLANG_ENABLE_OBJC_ARC = YES;
416 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
417 | CLANG_WARN_BOOL_CONVERSION = YES;
418 | CLANG_WARN_COMMA = YES;
419 | CLANG_WARN_CONSTANT_CONVERSION = YES;
420 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
421 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
422 | CLANG_WARN_EMPTY_BODY = YES;
423 | CLANG_WARN_ENUM_CONVERSION = YES;
424 | CLANG_WARN_INFINITE_RECURSION = YES;
425 | CLANG_WARN_INT_CONVERSION = YES;
426 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
427 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
428 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
429 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
430 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
431 | CLANG_WARN_STRICT_PROTOTYPES = YES;
432 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
433 | CLANG_WARN_UNREACHABLE_CODE = YES;
434 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
435 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
436 | COPY_PHASE_STRIP = NO;
437 | CURRENT_PROJECT_VERSION = 1;
438 | ENABLE_STRICT_OBJC_MSGSEND = YES;
439 | ENABLE_TESTABILITY = YES;
440 | GCC_C_LANGUAGE_STANDARD = gnu99;
441 | GCC_DYNAMIC_NO_PIC = NO;
442 | GCC_NO_COMMON_BLOCKS = YES;
443 | GCC_OPTIMIZATION_LEVEL = 0;
444 | GCC_PREPROCESSOR_DEFINITIONS = (
445 | "DEBUG=1",
446 | "$(inherited)",
447 | );
448 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
449 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
450 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
451 | GCC_WARN_UNDECLARED_SELECTOR = YES;
452 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
453 | GCC_WARN_UNUSED_FUNCTION = YES;
454 | GCC_WARN_UNUSED_VARIABLE = YES;
455 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
456 | MTL_ENABLE_DEBUG_INFO = YES;
457 | ONLY_ACTIVE_ARCH = YES;
458 | SDKROOT = iphoneos;
459 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
460 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
461 | SWIFT_VERSION = 4.0;
462 | TARGETED_DEVICE_FAMILY = "1,2";
463 | VERSIONING_SYSTEM = "apple-generic";
464 | VERSION_INFO_PREFIX = "";
465 | };
466 | name = Debug;
467 | };
468 | 09CF6B281A21F78700A97383 /* Release */ = {
469 | isa = XCBuildConfiguration;
470 | buildSettings = {
471 | ALWAYS_SEARCH_USER_PATHS = NO;
472 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
473 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
474 | CLANG_CXX_LIBRARY = "libc++";
475 | CLANG_ENABLE_MODULES = YES;
476 | CLANG_ENABLE_OBJC_ARC = YES;
477 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
478 | CLANG_WARN_BOOL_CONVERSION = YES;
479 | CLANG_WARN_COMMA = YES;
480 | CLANG_WARN_CONSTANT_CONVERSION = YES;
481 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
482 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
483 | CLANG_WARN_EMPTY_BODY = YES;
484 | CLANG_WARN_ENUM_CONVERSION = YES;
485 | CLANG_WARN_INFINITE_RECURSION = YES;
486 | CLANG_WARN_INT_CONVERSION = YES;
487 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
488 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
489 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
490 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
491 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
492 | CLANG_WARN_STRICT_PROTOTYPES = YES;
493 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
494 | CLANG_WARN_UNREACHABLE_CODE = YES;
495 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
496 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
497 | COPY_PHASE_STRIP = YES;
498 | CURRENT_PROJECT_VERSION = 1;
499 | ENABLE_NS_ASSERTIONS = NO;
500 | ENABLE_STRICT_OBJC_MSGSEND = YES;
501 | GCC_C_LANGUAGE_STANDARD = gnu99;
502 | GCC_NO_COMMON_BLOCKS = YES;
503 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
504 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
505 | GCC_WARN_UNDECLARED_SELECTOR = YES;
506 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
507 | GCC_WARN_UNUSED_FUNCTION = YES;
508 | GCC_WARN_UNUSED_VARIABLE = YES;
509 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
510 | MTL_ENABLE_DEBUG_INFO = NO;
511 | SDKROOT = iphoneos;
512 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
513 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
514 | SWIFT_VERSION = 4.0;
515 | TARGETED_DEVICE_FAMILY = "1,2";
516 | VALIDATE_PRODUCT = YES;
517 | VERSIONING_SYSTEM = "apple-generic";
518 | VERSION_INFO_PREFIX = "";
519 | };
520 | name = Release;
521 | };
522 | 09CF6B2A1A21F78700A97383 /* Debug */ = {
523 | isa = XCBuildConfiguration;
524 | buildSettings = {
525 | APPLICATION_EXTENSION_API_ONLY = YES;
526 | CLANG_ENABLE_MODULES = YES;
527 | CODE_SIGN_IDENTITY = "iPhone Developer";
528 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
529 | DEFINES_MODULE = YES;
530 | DEVELOPMENT_TEAM = 2N39544D78;
531 | DYLIB_COMPATIBILITY_VERSION = 1;
532 | DYLIB_CURRENT_VERSION = 1;
533 | DYLIB_INSTALL_NAME_BASE = "@rpath";
534 | ENABLE_BITCODE = NO;
535 | HEADER_SEARCH_PATHS = (
536 | "$(inherited)",
537 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
538 | "./submodules/OpenSSL/include-ios",
539 | );
540 | INFOPLIST_FILE = Moscapsule/Info.plist;
541 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
542 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
543 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
544 | LIBRARY_SEARCH_PATHS = "./submodules/OpenSSL/lib-ios";
545 | OTHER_CFLAGS = (
546 | "-DWITH_THREADING",
547 | "-DWITH_TLS",
548 | "-DWITH_TLS_PSK",
549 | );
550 | OTHER_LDFLAGS = (
551 | "-lssl",
552 | "-lcrypto",
553 | );
554 | PRODUCT_BUNDLE_IDENTIFIER = "com.github.flightonary.$(PRODUCT_NAME:rfc1034identifier)";
555 | PRODUCT_NAME = "$(TARGET_NAME)";
556 | SKIP_INSTALL = YES;
557 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
558 | SWIFT_VERSION = 5.0;
559 | USER_HEADER_SEARCH_PATHS = "";
560 | };
561 | name = Debug;
562 | };
563 | 09CF6B2B1A21F78700A97383 /* Release */ = {
564 | isa = XCBuildConfiguration;
565 | buildSettings = {
566 | APPLICATION_EXTENSION_API_ONLY = YES;
567 | CLANG_ENABLE_MODULES = YES;
568 | CODE_SIGN_IDENTITY = "iPhone Developer";
569 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
570 | DEFINES_MODULE = YES;
571 | DEVELOPMENT_TEAM = 2N39544D78;
572 | DYLIB_COMPATIBILITY_VERSION = 1;
573 | DYLIB_CURRENT_VERSION = 1;
574 | DYLIB_INSTALL_NAME_BASE = "@rpath";
575 | ENABLE_BITCODE = NO;
576 | HEADER_SEARCH_PATHS = (
577 | "$(inherited)",
578 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
579 | "./submodules/OpenSSL/include-ios",
580 | );
581 | INFOPLIST_FILE = Moscapsule/Info.plist;
582 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
583 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
584 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
585 | LIBRARY_SEARCH_PATHS = "./submodules/OpenSSL/lib-ios";
586 | OTHER_CFLAGS = (
587 | "-DWITH_THREADING",
588 | "-DWITH_TLS",
589 | "-DWITH_TLS_PSK",
590 | );
591 | OTHER_LDFLAGS = (
592 | "-lssl",
593 | "-lcrypto",
594 | );
595 | PRODUCT_BUNDLE_IDENTIFIER = "com.github.flightonary.$(PRODUCT_NAME:rfc1034identifier)";
596 | PRODUCT_NAME = "$(TARGET_NAME)";
597 | SKIP_INSTALL = YES;
598 | SWIFT_VERSION = 5.0;
599 | USER_HEADER_SEARCH_PATHS = "";
600 | };
601 | name = Release;
602 | };
603 | 09CF6B2D1A21F78700A97383 /* Debug */ = {
604 | isa = XCBuildConfiguration;
605 | buildSettings = {
606 | DEVELOPMENT_TEAM = 2N39544D78;
607 | FRAMEWORK_SEARCH_PATHS = "$(inherited)";
608 | GCC_PREPROCESSOR_DEFINITIONS = (
609 | "DEBUG=1",
610 | "$(inherited)",
611 | );
612 | INFOPLIST_FILE = MoscapsuleTests/Info.plist;
613 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
614 | PRODUCT_BUNDLE_IDENTIFIER = "com.github.flightonary.$(PRODUCT_NAME:rfc1034identifier)";
615 | PRODUCT_NAME = "$(TARGET_NAME)";
616 | SWIFT_VERSION = 5.0;
617 | };
618 | name = Debug;
619 | };
620 | 09CF6B2E1A21F78700A97383 /* Release */ = {
621 | isa = XCBuildConfiguration;
622 | buildSettings = {
623 | DEVELOPMENT_TEAM = 2N39544D78;
624 | FRAMEWORK_SEARCH_PATHS = "$(inherited)";
625 | INFOPLIST_FILE = MoscapsuleTests/Info.plist;
626 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
627 | PRODUCT_BUNDLE_IDENTIFIER = "com.github.flightonary.$(PRODUCT_NAME:rfc1034identifier)";
628 | PRODUCT_NAME = "$(TARGET_NAME)";
629 | SWIFT_VERSION = 5.0;
630 | };
631 | name = Release;
632 | };
633 | /* End XCBuildConfiguration section */
634 |
635 | /* Begin XCConfigurationList section */
636 | 09CF6B0D1A21F78700A97383 /* Build configuration list for PBXProject "Moscapsule" */ = {
637 | isa = XCConfigurationList;
638 | buildConfigurations = (
639 | 09CF6B271A21F78700A97383 /* Debug */,
640 | 09CF6B281A21F78700A97383 /* Release */,
641 | );
642 | defaultConfigurationIsVisible = 0;
643 | defaultConfigurationName = Release;
644 | };
645 | 09CF6B291A21F78700A97383 /* Build configuration list for PBXNativeTarget "Moscapsule" */ = {
646 | isa = XCConfigurationList;
647 | buildConfigurations = (
648 | 09CF6B2A1A21F78700A97383 /* Debug */,
649 | 09CF6B2B1A21F78700A97383 /* Release */,
650 | );
651 | defaultConfigurationIsVisible = 0;
652 | defaultConfigurationName = Release;
653 | };
654 | 09CF6B2C1A21F78700A97383 /* Build configuration list for PBXNativeTarget "MoscapsuleTests" */ = {
655 | isa = XCConfigurationList;
656 | buildConfigurations = (
657 | 09CF6B2D1A21F78700A97383 /* Debug */,
658 | 09CF6B2E1A21F78700A97383 /* Release */,
659 | );
660 | defaultConfigurationIsVisible = 0;
661 | defaultConfigurationName = Release;
662 | };
663 | /* End XCConfigurationList section */
664 | };
665 | rootObject = 09CF6B0A1A21F78700A97383 /* Project object */;
666 | }
667 |
--------------------------------------------------------------------------------