├── .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 | ![Configuration File](https://flightonary.github.io/img/inst_with_cocoapods.png) 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 | ![Moscapsule Manual Installation](https://flightonary.github.io/img/mosq_install.png) 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 | --------------------------------------------------------------------------------