├── HomeWatch ├── en.lproj │ └── InfoPlist.strings ├── Default.png ├── lite-off.png ├── lite-red.png ├── Default@2x.png ├── lite-green.png ├── lite-green@2x.png ├── lite-off@2x.png ├── lite-red@2x.png ├── Default-568h@2x.png ├── MosquittoMessage.m ├── HomeWatch-Prefix.pch ├── ViewController.h ├── main.m ├── AppDelegate.h ├── MosquittoMessage.h ├── Sensor.h ├── HomeWatch-Info.plist ├── AppDelegate.m ├── MosquittoClient.h ├── ViewController.m ├── Sensor.m └── MosquittoClient.m ├── HomeWatch.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── libmosquitto ├── dummypthread.h ├── config.h ├── logging_mosq.h ├── will_mosq.h ├── util_mosq.h ├── memory_mosq.h ├── read_handle.h ├── messages_mosq.h ├── mqtt3_protocol.h ├── logging_mosq.c ├── read_handle_client.c ├── send_mosq.h ├── thread_mosq.c ├── memory_mosq.c ├── net_mosq.h ├── will_mosq.c ├── mosquitto_internal.h ├── read_handle.c ├── messages_mosq.c ├── send_client_mosq.c ├── read_handle_shared.c ├── util_mosq.c ├── send_mosq.c ├── net_mosq.c └── mosquitto.c ├── README.md └── monitor.py /HomeWatch/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /HomeWatch/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basuke/homewatch/master/HomeWatch/Default.png -------------------------------------------------------------------------------- /HomeWatch/lite-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basuke/homewatch/master/HomeWatch/lite-off.png -------------------------------------------------------------------------------- /HomeWatch/lite-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basuke/homewatch/master/HomeWatch/lite-red.png -------------------------------------------------------------------------------- /HomeWatch/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basuke/homewatch/master/HomeWatch/Default@2x.png -------------------------------------------------------------------------------- /HomeWatch/lite-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basuke/homewatch/master/HomeWatch/lite-green.png -------------------------------------------------------------------------------- /HomeWatch/lite-green@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basuke/homewatch/master/HomeWatch/lite-green@2x.png -------------------------------------------------------------------------------- /HomeWatch/lite-off@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basuke/homewatch/master/HomeWatch/lite-off@2x.png -------------------------------------------------------------------------------- /HomeWatch/lite-red@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basuke/homewatch/master/HomeWatch/lite-red@2x.png -------------------------------------------------------------------------------- /HomeWatch/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basuke/homewatch/master/HomeWatch/Default-568h@2x.png -------------------------------------------------------------------------------- /HomeWatch.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HomeWatch/MosquittoMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // MosquittoMessage.m 3 | // Marquette 4 | // 5 | // Created by horace on 11/10/12. 6 | // Modified by Basuke Suzuki 2013. 7 | // 8 | // 9 | 10 | #import "MosquittoMessage.h" 11 | 12 | @implementation MosquittoMessage 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /libmosquitto/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 | -------------------------------------------------------------------------------- /HomeWatch/HomeWatch-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'MonHome' target in the 'MonHome' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /HomeWatch/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // MonHome 4 | // 5 | // Created by Yosuke Suzuki on 2013/05/03. 6 | // Copyright (c) 2013年 Basuke. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Sensor.h" 11 | 12 | @class MosquittoMessage; 13 | 14 | @interface ViewController : UIViewController 15 | 16 | @property(nonatomic) Sensor *sensor; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /HomeWatch/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MonHome 4 | // 5 | // Created by Yosuke Suzuki on 2013/05/03. 6 | // Copyright (c) 2013年 Basuke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Home Watch 2 | ========== 3 | 4 | MQTT server script and iPhone Client application to monitor gas range status of my kitchen. 5 | 6 | Requirement 7 | ----------- 8 | - mosquitto 1.1.3 - MQTT broker, C library and python module 9 | - Gas ranges with rotary knob. 10 | - Raspberry Pi or any server that can be placed at the kitchen. 11 | - A device with iOS 6.1. 12 | 13 | See also 14 | -------- 15 | http://www.basuke.com/2013/04/27/gas-range-watcher-3/ 16 | -------------------------------------------------------------------------------- /HomeWatch/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MonHome 4 | // 5 | // Created by Yosuke Suzuki on 2013/05/03. 6 | // Copyright (c) 2013年 Basuke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ViewController; 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /HomeWatch/MosquittoMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // MosquittoMessage.h 3 | // Marquette 4 | // 5 | // Created by horace on 11/10/12. 6 | // Modified by Basuke Suzuki 2013. 7 | // 8 | // 9 | 10 | #import 11 | 12 | @interface MosquittoMessage : NSObject 13 | 14 | @property (readwrite) unsigned short mid; 15 | @property (readwrite) NSString *topic; 16 | @property (readwrite) NSString *payload; 17 | @property (readwrite) unsigned short qos; 18 | @property (readwrite) BOOL retained; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /libmosquitto/config.h: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * Control compile time options. 3 | * ============================================================ 4 | * 5 | * Compile time options have moved to config.mk. 6 | */ 7 | 8 | 9 | #define WITH_THREADING 1 10 | 11 | /* ============================================================ 12 | * Compatibility defines 13 | * 14 | * Generally for Windows native support. 15 | * ============================================================ */ 16 | #ifdef WIN32 17 | #define snprintf sprintf_s 18 | #define strcasecmp strcmpi 19 | #define strtok_r strtok_s 20 | #define strerror_r(e, b, l) strerror_s(b, l, e) 21 | #endif 22 | -------------------------------------------------------------------------------- /HomeWatch/Sensor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sensor.h 3 | // MonHome 4 | // 5 | // Created by Yosuke Suzuki on 2013/05/04. 6 | // Copyright (c) 2013年 Basuke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, LogLevel) { 12 | LogNone = 0, 13 | LogMessage, 14 | LogWarning, 15 | LogError, 16 | }; 17 | 18 | @class Sensor; 19 | 20 | 21 | @protocol SensorDelegate 22 | 23 | - (void)sensor:(Sensor *)sensor log:(NSString *)message level:(LogLevel)level timestamp:(NSDate *)timestamp; 24 | - (void)sensor:(Sensor *)sensor monitorDidChange:(BOOL)state timestamp:(NSDate *)timestamp; 25 | - (void)sensor:(Sensor *)sensor gasRange:(NSInteger)range didChange:(BOOL)state timestamp:(NSDate *)timestamp; 26 | 27 | @end 28 | 29 | 30 | @interface Sensor : NSObject 31 | 32 | - (id)initWithHost:(NSString *)host port:(NSInteger)port; 33 | 34 | @property(weak) id delegate; 35 | 36 | @property(readonly) NSString *clientId; 37 | @property(readonly) NSString *host; 38 | @property(readonly) NSInteger port; 39 | 40 | - (void)connect; 41 | - (void)disconnect; 42 | 43 | - (BOOL)isConnected; 44 | 45 | @property(readonly, assign) BOOL monitor; 46 | 47 | @property(readonly, assign) BOOL gas1; 48 | @property(readonly, assign) BOOL gas2; 49 | @property(readonly, assign) BOOL gas3; 50 | @property(readonly, assign) BOOL gas4; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /libmosquitto/logging_mosq.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009,2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef _LOGGING_MOSQ_H_ 30 | #define _LOGGING_MOSQ_H_ 31 | 32 | #include 33 | 34 | int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /HomeWatch/HomeWatch-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIcons 12 | 13 | CFBundlePrimaryIcon 14 | 15 | CFBundleIconFiles 16 | 17 | Icon@2x.png 18 | Icon.png 19 | 20 | UIPrerenderedIcon 21 | 22 | 23 | 24 | CFBundleIdentifier 25 | com.basuke.iphoneapp.${PRODUCT_NAME:rfc1034identifier} 26 | CFBundleInfoDictionaryVersion 27 | 6.0 28 | CFBundleName 29 | ${PRODUCT_NAME} 30 | CFBundlePackageType 31 | APPL 32 | CFBundleShortVersionString 33 | 1.0 34 | CFBundleSignature 35 | ???? 36 | CFBundleVersion 37 | 1.0 38 | LSRequiresIPhoneOS 39 | 40 | UIPrerenderedIcon 41 | 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | 50 | UISupportedInterfaceOrientations~ipad 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationPortraitUpsideDown 54 | UIInterfaceOrientationLandscapeLeft 55 | UIInterfaceOrientationLandscapeRight 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /HomeWatch/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MonHome 4 | // 5 | // Created by Yosuke Suzuki on 2013/05/03. 6 | // Copyright (c) 2013年 Basuke. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | #import "Sensor.h" 12 | 13 | @implementation AppDelegate { 14 | Sensor *_sensor; 15 | UIBackgroundTaskIdentifier _disconnectTask; 16 | } 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 21 | self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 22 | 23 | _sensor = [[Sensor alloc] initWithHost:@"mqtt.example.com" port:1883]; 24 | [_sensor connect]; 25 | 26 | self.viewController.sensor = _sensor; 27 | _sensor.delegate = self.viewController; 28 | 29 | self.window.rootViewController = self.viewController; 30 | [self.window makeKeyAndVisible]; 31 | return YES; 32 | } 33 | 34 | - (void)applicationDidEnterBackground:(UIApplication *)application 35 | { 36 | _disconnectTask = [application beginBackgroundTaskWithExpirationHandler:^{ 37 | [application endBackgroundTask:_disconnectTask]; 38 | _disconnectTask = UIBackgroundTaskInvalid; 39 | }]; 40 | 41 | [_sensor disconnect]; 42 | [self waitSensorDisconnected:application]; 43 | } 44 | 45 | - (void)waitSensorDisconnected:(UIApplication *)application 46 | { 47 | if ([_sensor isConnected] == NO) { 48 | [application endBackgroundTask:_disconnectTask]; 49 | _disconnectTask = UIBackgroundTaskInvalid; 50 | return; 51 | } 52 | 53 | NSLog(@"waiting disconnection"); 54 | [self performSelector:@selector(waitSensorDisconnected:) withObject:application afterDelay:0.5]; 55 | } 56 | 57 | - (void)applicationWillEnterForeground:(UIApplication *)application 58 | { 59 | [_sensor connect]; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /libmosquitto/will_mosq.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010,2011 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #ifndef _WILL_MOSQ_H_ 31 | #define _WILL_MOSQ_H_ 32 | 33 | #include 34 | #include 35 | 36 | int _mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain); 37 | int _mosquitto_will_clear(struct mosquitto *mosq); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /HomeWatch/MosquittoClient.h: -------------------------------------------------------------------------------- 1 | // 2 | // MosquittoClient.h 3 | // 4 | // Copyright 2012 Nicholas Humfrey. All rights reserved. 5 | // Modified by Basuke Suzuki 2013. 6 | // 7 | 8 | #import 9 | #import "MosquittoMessage.h" 10 | #import "mosquitto.h" 11 | 12 | @class MosquittoClient; 13 | 14 | @protocol MosquittoClientDelegate 15 | 16 | - (void)mosquitto:(MosquittoClient *)client didConnect:(NSUInteger)code; 17 | - (void)mosquitto:(MosquittoClient *)client didFailToConnectWithError:(NSError *)error; 18 | - (void)mosquittoDidDisconnect:(MosquittoClient *)client; 19 | - (void)mosquitto:(MosquittoClient *)client didPublish:(NSUInteger)messageId; 20 | 21 | - (void)mosquitto:(MosquittoClient *)client didReceiveMessage:(MosquittoMessage*)message; 22 | - (void)mosquitto:(MosquittoClient *)client didSubscribe:(NSUInteger)messageId grantedQos:(NSArray*)qos; 23 | - (void)mosquitto:(MosquittoClient *)client didUnsubscribe:(NSUInteger)messageId; 24 | 25 | - (void)mosquitto:(MosquittoClient *)client log:(NSString *)message level:(NSInteger)level; 26 | 27 | @end 28 | 29 | 30 | @interface MosquittoClient : NSObject 31 | 32 | @property (readwrite,retain) NSString *host; 33 | @property (readwrite,assign) unsigned short port; 34 | @property (readwrite,retain) NSString *username; 35 | @property (readwrite,retain) NSString *password; 36 | @property (readwrite,assign) unsigned short keepAlive; 37 | @property (readwrite,assign) id delegate; 38 | 39 | + (void) initialize; 40 | + (NSString*) version; 41 | 42 | - (MosquittoClient*)initWithClientId:(NSString *)clientId cleanSession:(BOOL)isCleanSession; 43 | - (void)setMessageRetry:(NSUInteger)seconds; 44 | - (BOOL)connect; 45 | - (void)disconnect; 46 | - (BOOL)isConnected; 47 | 48 | - (void)setWill:(NSString *)payload toTopic:(NSString *)topic withQos:(NSUInteger)qos retained:(BOOL)retain; 49 | - (void)clearWill; 50 | 51 | - (void)publish:(NSString *)payload toTopic:(NSString *)topic withQos:(NSUInteger)qos retained:(BOOL)retain; 52 | 53 | - (void)subscribe:(NSString *)topic; 54 | - (void)subscribe:(NSString *)topic withQos:(NSUInteger)qos; 55 | - (void)unsubscribe:(NSString *)topic; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /libmosquitto/util_mosq.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009-2012 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef _UTIL_MOSQ_H_ 30 | #define _UTIL_MOSQ_H_ 31 | 32 | #include 33 | 34 | int _mosquitto_packet_alloc(struct _mosquitto_packet *packet); 35 | void _mosquitto_check_keepalive(struct mosquitto *mosq); 36 | int _mosquitto_fix_sub_topic(char **subtopic); 37 | uint16_t _mosquitto_mid_generate(struct mosquitto *mosq); 38 | int _mosquitto_topic_wildcard_len_check(const char *str); 39 | 40 | #if defined(WITH_TLS) && defined(WITH_TLS_PSK) 41 | int _mosquitto_hex2bin(const char *hex, unsigned char *bin, int bin_max_len); 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /libmosquitto/memory_mosq.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #ifndef _MEMORY_MOSQ_H_ 31 | #define _MEMORY_MOSQ_H_ 32 | 33 | #include 34 | 35 | #if defined(WITH_MEMORY_TRACKING) && defined(WITH_BROKER) && !defined(WIN32) && !defined(__SYMBIAN32__) 36 | #define REAL_WITH_MEMORY_TRACKING 37 | #endif 38 | 39 | void *_mosquitto_calloc(size_t nmemb, size_t size); 40 | void _mosquitto_free(void *mem); 41 | void *_mosquitto_malloc(size_t size); 42 | #ifdef REAL_WITH_MEMORY_TRACKING 43 | unsigned long _mosquitto_memory_used(void); 44 | unsigned long _mosquitto_max_memory_used(void); 45 | #endif 46 | void *_mosquitto_realloc(void *ptr, size_t size); 47 | char *_mosquitto_strdup(const char *s); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /HomeWatch/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // MonHome 4 | // 5 | // Created by Yosuke Suzuki on 2013/05/03. 6 | // Copyright (c) 2013年 Basuke. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "MosquittoMessage.h" 11 | 12 | @interface ViewController () 13 | 14 | @property (weak, nonatomic) IBOutlet UIImageView *status; 15 | 16 | @property (weak, nonatomic) IBOutlet UISwitch *gas1; 17 | @property (weak, nonatomic) IBOutlet UISwitch *gas2; 18 | @property (weak, nonatomic) IBOutlet UISwitch *gas3; 19 | @property (weak, nonatomic) IBOutlet UISwitch *gas4; 20 | 21 | @property (weak, nonatomic) IBOutlet UITextView *logView; 22 | 23 | @end 24 | 25 | @implementation ViewController { 26 | NSString *_log; 27 | } 28 | 29 | - (void)viewDidLoad 30 | { 31 | [super viewDidLoad]; 32 | 33 | [self setStatusIcon:self.sensor.monitor]; 34 | 35 | self.gas1.on = self.sensor.gas1; 36 | self.gas2.on = self.sensor.gas2; 37 | self.gas3.on = self.sensor.gas3; 38 | self.gas4.on = self.sensor.gas4; 39 | 40 | self.logView.text = _log; 41 | } 42 | 43 | - (void)setStatusIcon:(BOOL)status 44 | { 45 | self.status.image = [UIImage imageNamed:(status ? @"lite-green" : @"lite-red")]; 46 | } 47 | 48 | - (void)sensor:(Sensor *)sensor monitorDidChange:(BOOL)state timestamp:(NSDate *)timestamp 49 | { 50 | [self setStatusIcon:state]; 51 | } 52 | 53 | - (void)sensor:(Sensor *)sensor gasRange:(NSInteger)range didChange:(BOOL)state timestamp:(NSDate *)timestamp 54 | { 55 | switch (range) { 56 | case 1: 57 | self.gas1.on = state; 58 | break; 59 | 60 | case 2: 61 | self.gas2.on = state; 62 | break; 63 | 64 | case 3: 65 | self.gas3.on = state; 66 | break; 67 | 68 | case 4: 69 | self.gas4.on = state; 70 | break; 71 | } 72 | } 73 | 74 | - (void)sensor:(Sensor *)sensor log:(NSString *)message level:(LogLevel)level timestamp:(NSDate *)timestamp 75 | { 76 | NSRange selection; 77 | 78 | if (_log) { 79 | selection.location = [_log length] + 1; 80 | _log = [[_log stringByAppendingString:@"\n"] stringByAppendingString:message]; 81 | } else { 82 | selection.location = 0; 83 | _log = message; 84 | } 85 | selection.length = [_log length] - selection.location; 86 | 87 | self.logView.text = _log; 88 | [self.logView scrollRangeToVisible:selection]; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /libmosquitto/read_handle.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef _READ_HANDLE_H_ 30 | #define _READ_HANDLE_H_ 31 | 32 | #include 33 | struct mosquitto_db; 34 | 35 | int _mosquitto_packet_handle(struct mosquitto *mosq); 36 | int _mosquitto_handle_connack(struct mosquitto *mosq); 37 | int _mosquitto_handle_pingreq(struct mosquitto *mosq); 38 | int _mosquitto_handle_pingresp(struct mosquitto *mosq); 39 | int _mosquitto_handle_pubackcomp(struct mosquitto *mosq, const char *type); 40 | int _mosquitto_handle_publish(struct mosquitto *mosq); 41 | int _mosquitto_handle_pubrec(struct mosquitto *mosq); 42 | int _mosquitto_handle_pubrel(struct mosquitto_db *db, struct mosquitto *mosq); 43 | int _mosquitto_handle_suback(struct mosquitto *mosq); 44 | int _mosquitto_handle_unsuback(struct mosquitto *mosq); 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /libmosquitto/messages_mosq.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef _MESSAGES_MOSQ_H_ 30 | #define _MESSAGES_MOSQ_H_ 31 | 32 | #include 33 | #include 34 | 35 | void _mosquitto_message_cleanup_all(struct mosquitto *mosq); 36 | void _mosquitto_message_cleanup(struct mosquitto_message_all **message); 37 | int _mosquitto_message_delete(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir); 38 | void _mosquitto_message_queue(struct mosquitto *mosq, struct mosquitto_message_all *message); 39 | void _mosquitto_messages_reconnect_reset(struct mosquitto *mosq); 40 | int _mosquitto_message_remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, struct mosquitto_message_all **message); 41 | void _mosquitto_message_retry_check(struct mosquitto *mosq); 42 | int _mosquitto_message_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, enum mosquitto_msg_state state); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /libmosquitto/mqtt3_protocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009,2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #ifndef _MQTT3_PROTOCOL_H_ 31 | #define _MQTT3_PROTOCOL_H_ 32 | 33 | /* For version 3 of the MQTT protocol */ 34 | 35 | #define PROTOCOL_NAME "MQIsdp" 36 | #define PROTOCOL_VERSION 3 37 | 38 | /* Message types */ 39 | #define CONNECT 0x10 40 | #define CONNACK 0x20 41 | #define PUBLISH 0x30 42 | #define PUBACK 0x40 43 | #define PUBREC 0x50 44 | #define PUBREL 0x60 45 | #define PUBCOMP 0x70 46 | #define SUBSCRIBE 0x80 47 | #define SUBACK 0x90 48 | #define UNSUBSCRIBE 0xA0 49 | #define UNSUBACK 0xB0 50 | #define PINGREQ 0xC0 51 | #define PINGRESP 0xD0 52 | #define DISCONNECT 0xE0 53 | 54 | #define CONNACK_ACCEPTED 0 55 | #define CONNACK_REFUSED_PROTOCOL_VERSION 1 56 | #define CONNACK_REFUSED_IDENTIFIER_REJECTED 2 57 | #define CONNACK_REFUSED_SERVER_UNAVAILABLE 3 58 | #define CONNACK_REFUSED_BAD_USERNAME_PASSWORD 4 59 | #define CONNACK_REFUSED_NOT_AUTHORIZED 5 60 | 61 | #define MQTT_MAX_PAYLOAD 268435455 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /libmosquitto/logging_mosq.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009,2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...) 39 | { 40 | va_list va; 41 | char *s; 42 | int len; 43 | 44 | assert(mosq); 45 | assert(fmt); 46 | 47 | pthread_mutex_lock(&mosq->log_callback_mutex); 48 | if(mosq->on_log){ 49 | len = strlen(fmt) + 500; 50 | s = _mosquitto_malloc(len*sizeof(char)); 51 | if(!s){ 52 | pthread_mutex_unlock(&mosq->log_callback_mutex); 53 | return MOSQ_ERR_NOMEM; 54 | } 55 | 56 | va_start(va, fmt); 57 | vsnprintf(s, len, fmt, va); 58 | va_end(va); 59 | s[len-1] = '\0'; /* Ensure string is null terminated. */ 60 | 61 | mosq->on_log(mosq, mosq->userdata, priority, s); 62 | 63 | _mosquitto_free(s); 64 | } 65 | pthread_mutex_unlock(&mosq->log_callback_mutex); 66 | 67 | return MOSQ_ERR_SUCCESS; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /libmosquitto/read_handle_client.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009,2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | int _mosquitto_handle_connack(struct mosquitto *mosq) 39 | { 40 | uint8_t byte; 41 | uint8_t result; 42 | int rc; 43 | 44 | assert(mosq); 45 | #ifdef WITH_STRICT_PROTOCOL 46 | if(mosq->in_packet.remaining_length != 2){ 47 | return MOSQ_ERR_PROTOCOL; 48 | } 49 | #endif 50 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK", mosq->id); 51 | rc = _mosquitto_read_byte(&mosq->in_packet, &byte); // Reserved byte, not used 52 | if(rc) return rc; 53 | rc = _mosquitto_read_byte(&mosq->in_packet, &result); 54 | if(rc) return rc; 55 | pthread_mutex_lock(&mosq->callback_mutex); 56 | if(mosq->on_connect){ 57 | mosq->in_callback = true; 58 | mosq->on_connect(mosq, mosq->userdata, result); 59 | mosq->in_callback = false; 60 | } 61 | pthread_mutex_unlock(&mosq->callback_mutex); 62 | switch(result){ 63 | case 0: 64 | mosq->state = mosq_cs_connected; 65 | return MOSQ_ERR_SUCCESS; 66 | case 1: 67 | case 2: 68 | case 3: 69 | case 4: 70 | case 5: 71 | return MOSQ_ERR_CONN_REFUSED; 72 | default: 73 | return MOSQ_ERR_PROTOCOL; 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /libmosquitto/send_mosq.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef _SEND_MOSQ_H_ 30 | #define _SEND_MOSQ_H_ 31 | 32 | #include 33 | 34 | int _mosquitto_send_simple_command(struct mosquitto *mosq, uint8_t command); 35 | int _mosquitto_send_command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup); 36 | 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); 37 | 38 | int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session); 39 | int _mosquitto_send_disconnect(struct mosquitto *mosq); 40 | int _mosquitto_send_pingreq(struct mosquitto *mosq); 41 | int _mosquitto_send_pingresp(struct mosquitto *mosq); 42 | int _mosquitto_send_puback(struct mosquitto *mosq, uint16_t mid); 43 | int _mosquitto_send_pubcomp(struct mosquitto *mosq, uint16_t mid); 44 | 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); 45 | int _mosquitto_send_pubrec(struct mosquitto *mosq, uint16_t mid); 46 | int _mosquitto_send_pubrel(struct mosquitto *mosq, uint16_t mid, bool dup); 47 | int _mosquitto_send_subscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic, uint8_t topic_qos); 48 | int _mosquitto_send_unsubscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /libmosquitto/thread_mosq.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | 32 | #ifndef WIN32 33 | #include 34 | #endif 35 | 36 | #include 37 | 38 | void *_mosquitto_thread_main(void *obj); 39 | 40 | int mosquitto_loop_start(struct mosquitto *mosq) 41 | { 42 | #ifdef WITH_THREADING 43 | if(!mosq) return MOSQ_ERR_INVAL; 44 | 45 | pthread_create(&mosq->thread_id, NULL, _mosquitto_thread_main, mosq); 46 | return MOSQ_ERR_SUCCESS; 47 | #else 48 | return MOSQ_ERR_NOT_SUPPORTED; 49 | #endif 50 | } 51 | 52 | int mosquitto_loop_stop(struct mosquitto *mosq, bool force) 53 | { 54 | #ifdef WITH_THREADING 55 | if(!mosq) return MOSQ_ERR_INVAL; 56 | 57 | if(force){ 58 | pthread_cancel(mosq->thread_id); 59 | } 60 | pthread_join(mosq->thread_id, NULL); 61 | mosq->thread_id = pthread_self(); 62 | 63 | return MOSQ_ERR_SUCCESS; 64 | #else 65 | return MOSQ_ERR_NOT_SUPPORTED; 66 | #endif 67 | } 68 | 69 | #ifdef WITH_THREADING 70 | void *_mosquitto_thread_main(void *obj) 71 | { 72 | struct mosquitto *mosq = obj; 73 | int run = 1; 74 | int rc; 75 | 76 | if(!mosq) return NULL; 77 | 78 | pthread_mutex_lock(&mosq->state_mutex); 79 | if(mosq->state == mosq_cs_connect_async){ 80 | pthread_mutex_unlock(&mosq->state_mutex); 81 | mosquitto_reconnect(mosq); 82 | }else{ 83 | pthread_mutex_unlock(&mosq->state_mutex); 84 | } 85 | 86 | while(run){ 87 | do{ 88 | rc = mosquitto_loop(mosq, -1, 1); 89 | }while(rc == MOSQ_ERR_SUCCESS); 90 | pthread_mutex_lock(&mosq->state_mutex); 91 | if(mosq->state == mosq_cs_disconnecting){ 92 | run = 0; 93 | pthread_mutex_unlock(&mosq->state_mutex); 94 | }else{ 95 | pthread_mutex_unlock(&mosq->state_mutex); 96 | #ifdef WIN32 97 | Sleep(1000); 98 | #else 99 | sleep(1); 100 | #endif 101 | mosquitto_reconnect(mosq); 102 | } 103 | } 104 | return obj; 105 | } 106 | #endif 107 | 108 | -------------------------------------------------------------------------------- /monitor.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | import RPi.GPIO as GPIO 4 | import mosquitto 5 | import sys 6 | from datetime import datetime 7 | 8 | 9 | PINS = (18, 23, 24, 25) # GPIO ports 10 | SERVER = "mqtt.example.com" # MQTT Server 11 | 12 | 13 | def main(): 14 | # setup MQTT 15 | conn = MQTTServer(SERVER) 16 | 17 | # setup GPIO 18 | GPIO.setmode(GPIO.BCM) 19 | [GPIO.setup(pin, GPIO.IN) for pin in PINS] 20 | 21 | labels = range(1, len(PINS) + 1) 22 | sensors = [Sensor(label, pin) for label, pin in zip(labels, PINS)] 23 | 24 | def on_connect(): 25 | # send initial state 26 | for sensor in sensors: 27 | conn.publish(*sensor.event()) 28 | 29 | conn.publish("home/kitchen/monitor", "ON") 30 | 31 | conn.set_will("home/kitchen/monitor", "OFF") 32 | conn.connect(on_connect) 33 | 34 | while True: 35 | conn.loop() 36 | 37 | for sensor in sensors: 38 | if sensor.check(): 39 | conn.publish(*sensor.event()) 40 | 41 | 42 | class Sensor(object): 43 | def __init__(self, label, pin): 44 | self.pin = pin 45 | self.state = GPIO.input(self.pin) 46 | self.topic = "home/kitchen/gas/%s" % label 47 | 48 | def check(self): 49 | state = self.state 50 | self.state = GPIO.input(self.pin) 51 | return (state != self.state) 52 | 53 | def event(self): 54 | state = "ON" if self.state else "OFF" 55 | msg = ' '.join([state, utctimestamp()]) 56 | 57 | return (self.topic, msg) 58 | 59 | 60 | class MQTTServer(object): 61 | def __init__(self, server): 62 | self.server = server 63 | self.client = mosquitto.Mosquitto("Daidokoro-monitor", userdata=self) 64 | self.connected = False 65 | self.on_connect = None 66 | 67 | def on_connect(mosq, self, rc): 68 | if rc != 0: 69 | log("Cannot connect to server. Exit.") 70 | sys.exit(255) 71 | 72 | log("Connected successfully.") 73 | self.connected = True 74 | 75 | if self.on_connect: 76 | self.on_connect() 77 | 78 | def on_disconnect(mosq, self, rc): 79 | log("Disconnected. Try to connect again.") 80 | self.connected = False 81 | 82 | self.reconnect() 83 | 84 | self.client.on_connect = on_connect 85 | self.client.on_disconnect = on_disconnect 86 | 87 | def connect(self, on_connect): 88 | log("Connecting to MQTT server.") 89 | self.on_connect = on_connect 90 | 91 | self.client.connect(self.server, keepalive=10) 92 | self.wait_connection() 93 | 94 | def reconnect(self): 95 | log("Reconnecting to MQTT server.") 96 | self.client.reconnect() 97 | self.wait_connection() 98 | 99 | def publish(self, topic, payload): 100 | log("Publish %s => %s" % (topic, payload)) 101 | self.client.publish(topic, payload, retain=True) 102 | 103 | def set_will(self, topic, payload): 104 | log("Set Will %s => %s" % (topic, payload)) 105 | self.client.will_set(topic, payload, retain=True) 106 | 107 | def loop(self, timeout=0.1): 108 | self.client.loop(timeout=timeout) 109 | 110 | def wait_connection(self): 111 | while not self.connected: 112 | self.loop() 113 | 114 | 115 | def utctimestamp(): 116 | now = datetime.utcnow().replace(microsecond = 0) 117 | return now.isoformat() + 'Z' 118 | 119 | def log(msg): 120 | print msg 121 | 122 | 123 | if __name__ == '__main__': 124 | main() 125 | -------------------------------------------------------------------------------- /libmosquitto/memory_mosq.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009,2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | #ifdef REAL_WITH_MEMORY_TRACKING 38 | # if defined(__APPLE__) 39 | # define malloc_usable_size malloc_good_size 40 | # elif defined(__FreeBSD__) 41 | # include 42 | # else 43 | # include 44 | # endif 45 | #endif 46 | 47 | #include 48 | 49 | #ifdef REAL_WITH_MEMORY_TRACKING 50 | static unsigned long memcount = 0; 51 | static unsigned long max_memcount = 0; 52 | #endif 53 | 54 | void *_mosquitto_calloc(size_t nmemb, size_t size) 55 | { 56 | void *mem = calloc(nmemb, size); 57 | 58 | #ifdef REAL_WITH_MEMORY_TRACKING 59 | memcount += malloc_usable_size(mem); 60 | if(memcount > max_memcount){ 61 | max_memcount = memcount; 62 | } 63 | #endif 64 | 65 | return mem; 66 | } 67 | 68 | void _mosquitto_free(void *mem) 69 | { 70 | #ifdef REAL_WITH_MEMORY_TRACKING 71 | memcount -= malloc_usable_size(mem); 72 | #endif 73 | free(mem); 74 | } 75 | 76 | void *_mosquitto_malloc(size_t size) 77 | { 78 | void *mem = malloc(size); 79 | 80 | #ifdef REAL_WITH_MEMORY_TRACKING 81 | memcount += malloc_usable_size(mem); 82 | if(memcount > max_memcount){ 83 | max_memcount = memcount; 84 | } 85 | #endif 86 | 87 | return mem; 88 | } 89 | 90 | #ifdef REAL_WITH_MEMORY_TRACKING 91 | unsigned long _mosquitto_memory_used(void) 92 | { 93 | return memcount; 94 | } 95 | 96 | unsigned long _mosquitto_max_memory_used(void) 97 | { 98 | return max_memcount; 99 | } 100 | #endif 101 | 102 | void *_mosquitto_realloc(void *ptr, size_t size) 103 | { 104 | void *mem; 105 | #ifdef REAL_WITH_MEMORY_TRACKING 106 | if(ptr){ 107 | memcount -= malloc_usable_size(ptr); 108 | } 109 | #endif 110 | mem = realloc(ptr, size); 111 | 112 | #ifdef REAL_WITH_MEMORY_TRACKING 113 | memcount += malloc_usable_size(mem); 114 | if(memcount > max_memcount){ 115 | max_memcount = memcount; 116 | } 117 | #endif 118 | 119 | return mem; 120 | } 121 | 122 | char *_mosquitto_strdup(const char *s) 123 | { 124 | char *str = strdup(s); 125 | 126 | #ifdef REAL_WITH_MEMORY_TRACKING 127 | memcount += malloc_usable_size(str); 128 | if(memcount > max_memcount){ 129 | max_memcount = memcount; 130 | } 131 | #endif 132 | 133 | return str; 134 | } 135 | 136 | -------------------------------------------------------------------------------- /libmosquitto/net_mosq.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010,2011 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef _NET_MOSQ_H_ 30 | #define _NET_MOSQ_H_ 31 | 32 | #ifndef WIN32 33 | #include 34 | #else 35 | #include 36 | typedef int ssize_t; 37 | #endif 38 | 39 | #include 40 | #include 41 | 42 | #ifdef WITH_BROKER 43 | struct mosquitto_db; 44 | #endif 45 | 46 | #ifdef WIN32 47 | # define COMPAT_CLOSE(a) closesocket(a) 48 | # define COMPAT_ECONNRESET WSAECONNRESET 49 | # define COMPAT_EWOULDBLOCK WSAEWOULDBLOCK 50 | #else 51 | # define COMPAT_CLOSE(a) close(a) 52 | # define COMPAT_ECONNRESET ECONNRESET 53 | # define COMPAT_EWOULDBLOCK EWOULDBLOCK 54 | #endif 55 | 56 | #ifndef WIN32 57 | #else 58 | #endif 59 | 60 | /* For when not using winsock libraries. */ 61 | #ifndef INVALID_SOCKET 62 | #define INVALID_SOCKET -1 63 | #endif 64 | 65 | /* Macros for accessing the MSB and LSB of a uint16_t */ 66 | #define MOSQ_MSB(A) (uint8_t)((A & 0xFF00) >> 8) 67 | #define MOSQ_LSB(A) (uint8_t)(A & 0x00FF) 68 | 69 | void _mosquitto_net_init(void); 70 | void _mosquitto_net_cleanup(void); 71 | 72 | void _mosquitto_packet_cleanup(struct _mosquitto_packet *packet); 73 | int _mosquitto_packet_queue(struct mosquitto *mosq, struct _mosquitto_packet *packet); 74 | int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port); 75 | int _mosquitto_socket_close(struct mosquitto *mosq); 76 | 77 | int _mosquitto_read_byte(struct _mosquitto_packet *packet, uint8_t *byte); 78 | int _mosquitto_read_bytes(struct _mosquitto_packet *packet, void *bytes, uint32_t count); 79 | int _mosquitto_read_string(struct _mosquitto_packet *packet, char **str); 80 | int _mosquitto_read_uint16(struct _mosquitto_packet *packet, uint16_t *word); 81 | 82 | void _mosquitto_write_byte(struct _mosquitto_packet *packet, uint8_t byte); 83 | void _mosquitto_write_bytes(struct _mosquitto_packet *packet, const void *bytes, uint32_t count); 84 | void _mosquitto_write_string(struct _mosquitto_packet *packet, const char *str, uint16_t length); 85 | void _mosquitto_write_uint16(struct _mosquitto_packet *packet, uint16_t word); 86 | 87 | ssize_t _mosquitto_net_read(struct mosquitto *mosq, void *buf, size_t count); 88 | ssize_t _mosquitto_net_write(struct mosquitto *mosq, void *buf, size_t count); 89 | 90 | int _mosquitto_packet_write(struct mosquitto *mosq); 91 | #ifdef WITH_BROKER 92 | int _mosquitto_packet_read(struct mosquitto_db *db, struct mosquitto *mosq); 93 | #else 94 | int _mosquitto_packet_read(struct mosquitto *mosq); 95 | #endif 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /libmosquitto/will_mosq.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010,2011 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #ifndef WIN32 35 | #include 36 | #include 37 | #else 38 | #include 39 | typedef int ssize_t; 40 | #endif 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | int _mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain) 54 | { 55 | int rc = MOSQ_ERR_SUCCESS; 56 | 57 | if(!mosq || !topic) return MOSQ_ERR_INVAL; 58 | if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE; 59 | if(payloadlen > 0 && !payload) return MOSQ_ERR_INVAL; 60 | 61 | if(mosq->will){ 62 | if(mosq->will->topic){ 63 | _mosquitto_free(mosq->will->topic); 64 | mosq->will->topic = NULL; 65 | } 66 | if(mosq->will->payload){ 67 | _mosquitto_free(mosq->will->payload); 68 | mosq->will->payload = NULL; 69 | } 70 | _mosquitto_free(mosq->will); 71 | mosq->will = NULL; 72 | } 73 | 74 | mosq->will = _mosquitto_calloc(1, sizeof(struct mosquitto_message)); 75 | if(!mosq->will) return MOSQ_ERR_NOMEM; 76 | mosq->will->topic = _mosquitto_strdup(topic); 77 | if(!mosq->will->topic){ 78 | rc = MOSQ_ERR_NOMEM; 79 | goto cleanup; 80 | } 81 | mosq->will->payloadlen = payloadlen; 82 | if(mosq->will->payloadlen > 0){ 83 | if(!payload){ 84 | rc = MOSQ_ERR_INVAL; 85 | goto cleanup; 86 | } 87 | mosq->will->payload = _mosquitto_malloc(sizeof(char)*mosq->will->payloadlen); 88 | if(!mosq->will->payload){ 89 | rc = MOSQ_ERR_NOMEM; 90 | goto cleanup; 91 | } 92 | 93 | memcpy(mosq->will->payload, payload, payloadlen); 94 | } 95 | mosq->will->qos = qos; 96 | mosq->will->retain = retain; 97 | 98 | return MOSQ_ERR_SUCCESS; 99 | 100 | cleanup: 101 | if(mosq->will){ 102 | if(mosq->will->topic) _mosquitto_free(mosq->will->topic); 103 | if(mosq->will->payload) _mosquitto_free(mosq->will->payload); 104 | } 105 | _mosquitto_free(mosq->will); 106 | mosq->will = NULL; 107 | 108 | return rc; 109 | } 110 | 111 | int _mosquitto_will_clear(struct mosquitto *mosq) 112 | { 113 | if(!mosq->will) return MOSQ_ERR_SUCCESS; 114 | 115 | if(mosq->will->topic){ 116 | _mosquitto_free(mosq->will->topic); 117 | mosq->will->topic = NULL; 118 | } 119 | if(mosq->will->payload){ 120 | _mosquitto_free(mosq->will->payload); 121 | mosq->will->payload = NULL; 122 | } 123 | _mosquitto_free(mosq->will); 124 | mosq->will = NULL; 125 | 126 | return MOSQ_ERR_SUCCESS; 127 | } 128 | 129 | -------------------------------------------------------------------------------- /HomeWatch/Sensor.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sensor.m 3 | // MonHome 4 | // 5 | // Created by Yosuke Suzuki on 2013/05/04. 6 | // Copyright (c) 2013年 Basuke. All rights reserved. 7 | // 8 | 9 | #import "Sensor.h" 10 | #import "MosquittoClient.h" 11 | 12 | @interface Sensor() 13 | 14 | @property(readwrite, assign) BOOL monitor; 15 | 16 | @property(readwrite, assign) BOOL gas1; 17 | @property(readwrite, assign) BOOL gas2; 18 | @property(readwrite, assign) BOOL gas3; 19 | @property(readwrite, assign) BOOL gas4; 20 | 21 | @end 22 | 23 | @implementation Sensor { 24 | MosquittoClient *_mosquitto; 25 | NSInteger _logLevel; 26 | NSDateFormatter *_timestampFormatter; 27 | NSRegularExpression *_gasRangeTopicRE; 28 | } 29 | 30 | @synthesize host=_host, port=_port, clientId=_clientId; 31 | 32 | - (id)initWithHost:(NSString *)host port:(NSInteger)port 33 | { 34 | self = [super init]; 35 | if (self) { 36 | _host = host; 37 | _port = port; 38 | 39 | // Create unique serial 40 | NSString *uuid = [[[NSUUID UUID] UUIDString] substringToIndex:16]; 41 | _clientId = [NSString stringWithFormat:@"HomeWatch-%@", uuid]; 42 | 43 | // Create Mosquitto instance 44 | _mosquitto = [[MosquittoClient alloc] initWithClientId:_clientId cleanSession:YES]; 45 | _mosquitto.delegate = self; 46 | 47 | // Date Formatter for parsing timestamp 48 | NSDateFormatter *f = [[NSDateFormatter alloc] init]; 49 | f.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'Z'"; 50 | f.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; 51 | f.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 52 | f.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; 53 | 54 | _timestampFormatter = f; 55 | 56 | // Regular Expression for Topic parsing 57 | NSError *error; 58 | _gasRangeTopicRE = [NSRegularExpression regularExpressionWithPattern:@"^home/kitchen/(gas/(\\d+)|monitor)$" options:0 error:&error]; 59 | } 60 | return self; 61 | } 62 | 63 | - (void)connect 64 | { 65 | _mosquitto.host = _host; 66 | if (_port) _mosquitto.port = _port; 67 | 68 | [_mosquitto connect]; 69 | } 70 | 71 | - (void)disconnect 72 | { 73 | [_mosquitto disconnect]; 74 | } 75 | 76 | - (BOOL)isConnected 77 | { 78 | return [_mosquitto isConnected]; 79 | } 80 | 81 | - (void)log:(NSString *)message level:(LogLevel)level 82 | { 83 | [self.delegate sensor:self log:message level:level timestamp:[NSDate date]]; 84 | } 85 | 86 | - (void)log:(NSString *)message 87 | { 88 | [self log:message level:LogMessage]; 89 | 90 | #if DEBUG 91 | NSLog(@"%@", message); 92 | #endif 93 | } 94 | 95 | #pragma mark - Mosquitto Delegate 96 | 97 | - (void)mosquitto:(MosquittoClient *)client didConnect:(NSUInteger)code 98 | { 99 | [self log:[NSString stringWithFormat:@"connected to %@ port %d", _host, _port]]; 100 | 101 | [client subscribe:@"home/kitchen/gas/+"]; 102 | [client subscribe:@"home/kitchen/monitor"]; 103 | } 104 | 105 | - (void)mosquitto:(MosquittoClient *)client didFailToConnectWithError:(NSError *)error 106 | { 107 | 108 | } 109 | 110 | - (void)mosquittoDidDisconnect:(MosquittoClient *)client 111 | { 112 | [self log:@"disconnected"]; 113 | } 114 | 115 | - (void)mosquitto:(MosquittoClient *)client didReceiveMessage:(MosquittoMessage*)message 116 | { 117 | #if DEBUG 118 | [self log:[NSString stringWithFormat:@"%@ : %@ qos:%d%@", message.topic, message.payload, message.qos, (message.retained ? @" RETAIN" : @"")]]; 119 | #endif 120 | 121 | BOOL on; 122 | NSDate *timestamp; 123 | 124 | NSArray *values = [message.payload componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 125 | 126 | if ([values count] >= 1) { 127 | on = [values[0] isEqualToString:@"ON"]; 128 | } 129 | 130 | if ([values count] >= 2) { 131 | timestamp = [_timestampFormatter dateFromString:values[1]]; 132 | } 133 | 134 | NSTextCheckingResult *match = [_gasRangeTopicRE firstMatchInString:message.topic options:0 range:NSMakeRange(0, message.topic.length)]; 135 | if (match) { 136 | NSString *what = [message.topic substringWithRange:[match rangeAtIndex:1]]; 137 | 138 | if ([what isEqualToString:@"monitor"]) { 139 | [self.delegate sensor:self monitorDidChange:on timestamp:timestamp]; 140 | } else { 141 | NSInteger range = [[message.topic substringWithRange:[match rangeAtIndex:2]] integerValue]; 142 | 143 | [self.delegate sensor:self gasRange:range didChange:on timestamp:timestamp]; 144 | } 145 | } 146 | } 147 | 148 | - (void)mosquitto:(MosquittoClient *)client didPublish:(NSUInteger)messageId 149 | { 150 | } 151 | 152 | - (void)mosquitto:(MosquittoClient *)client didSubscribe:(NSUInteger)messageId grantedQos:(NSArray*)qos 153 | { 154 | [self log:[NSString stringWithFormat:@"subscribed (mid=%d)", messageId]]; 155 | } 156 | 157 | - (void)mosquitto:(MosquittoClient *)client didUnsubscribe:(NSUInteger)messageId 158 | { 159 | [self log:[NSString stringWithFormat:@"unsubscribed (mid=%d)", messageId]]; 160 | } 161 | 162 | - (void)mosquitto:(MosquittoClient *)client log:(NSString *)message level:(NSInteger)level 163 | { 164 | LogLevel logLevel = LogNone; 165 | 166 | switch (level) { 167 | case MOSQ_LOG_INFO: 168 | logLevel = LogMessage; 169 | break; 170 | 171 | case MOSQ_LOG_NOTICE: 172 | logLevel = LogMessage; 173 | break; 174 | 175 | case MOSQ_LOG_WARNING: 176 | logLevel = LogWarning; 177 | break; 178 | 179 | case MOSQ_LOG_ERR: 180 | logLevel = LogError; 181 | break; 182 | 183 | #if DEBUG 184 | case MOSQ_LOG_DEBUG: 185 | logLevel = LogMessage; 186 | break; 187 | #endif 188 | default: 189 | break; 190 | } 191 | 192 | if (logLevel != LogNone) { 193 | [self log:message level:logLevel]; 194 | } 195 | } 196 | 197 | @end 198 | -------------------------------------------------------------------------------- /libmosquitto/mosquitto_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010,2011 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #ifndef _MOSQUITTO_INTERNAL_H_ 31 | #define _MOSQUITTO_INTERNAL_H_ 32 | 33 | #include 34 | 35 | #ifdef WIN32 36 | # include 37 | #endif 38 | 39 | #ifdef WITH_TLS 40 | #include 41 | #endif 42 | #include 43 | #include 44 | 45 | #if defined(WITH_THREADING) && !defined(WITH_BROKER) 46 | # include 47 | #else 48 | # include 49 | #endif 50 | 51 | #ifdef WIN32 52 | # if _MSC_VER < 1600 53 | typedef unsigned char uint8_t; 54 | typedef unsigned short uint16_t; 55 | typedef unsigned int uint32_t; 56 | typedef unsigned long long uint64_t; 57 | # else 58 | # include 59 | # endif 60 | #else 61 | # include 62 | #endif 63 | 64 | #include 65 | #ifdef WITH_BROKER 66 | struct mosquitto_client_msg; 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_wait_puback = 1, 77 | mosq_ms_wait_pubrec = 2, 78 | mosq_ms_wait_pubrel = 3, 79 | mosq_ms_wait_pubcomp = 4 80 | }; 81 | 82 | enum mosquitto_client_state { 83 | mosq_cs_new = 0, 84 | mosq_cs_connected = 1, 85 | mosq_cs_disconnecting = 2, 86 | mosq_cs_connect_async = 3 87 | }; 88 | 89 | struct _mosquitto_packet{ 90 | uint8_t command; 91 | uint8_t have_remaining; 92 | uint8_t remaining_count; 93 | uint16_t mid; 94 | uint32_t remaining_mult; 95 | uint32_t remaining_length; 96 | uint32_t packet_length; 97 | uint32_t to_process; 98 | uint32_t pos; 99 | uint8_t *payload; 100 | struct _mosquitto_packet *next; 101 | }; 102 | 103 | struct mosquitto_message_all{ 104 | struct mosquitto_message_all *next; 105 | time_t timestamp; 106 | enum mosquitto_msg_direction direction; 107 | enum mosquitto_msg_state state; 108 | bool dup; 109 | struct mosquitto_message msg; 110 | }; 111 | 112 | struct mosquitto { 113 | #ifndef WIN32 114 | int sock; 115 | #else 116 | SOCKET sock; 117 | #endif 118 | char *address; 119 | char *id; 120 | char *username; 121 | char *password; 122 | uint16_t keepalive; 123 | bool clean_session; 124 | enum mosquitto_client_state state; 125 | time_t last_msg_in; 126 | time_t last_msg_out; 127 | time_t ping_t; 128 | uint16_t last_mid; 129 | struct _mosquitto_packet in_packet; 130 | struct _mosquitto_packet *current_out_packet; 131 | struct _mosquitto_packet *out_packet; 132 | struct mosquitto_message *will; 133 | #ifdef WITH_TLS 134 | SSL *ssl; 135 | SSL_CTX *ssl_ctx; 136 | char *tls_cafile; 137 | char *tls_capath; 138 | char *tls_certfile; 139 | char *tls_keyfile; 140 | int (*tls_pw_callback)(char *buf, int size, int rwflag, void *userdata); 141 | int tls_cert_reqs; 142 | char *tls_version; 143 | char *tls_ciphers; 144 | char *tls_psk; 145 | char *tls_psk_identity; 146 | #endif 147 | bool want_read; 148 | bool want_write; 149 | #if defined(WITH_THREADING) && !defined(WITH_BROKER) 150 | pthread_mutex_t callback_mutex; 151 | pthread_mutex_t log_callback_mutex; 152 | pthread_mutex_t msgtime_mutex; 153 | pthread_mutex_t out_packet_mutex; 154 | pthread_mutex_t current_out_packet_mutex; 155 | pthread_mutex_t state_mutex; 156 | pthread_t thread_id; 157 | #endif 158 | #ifdef WITH_BROKER 159 | bool is_bridge; 160 | struct _mqtt3_bridge *bridge; 161 | struct mosquitto_client_msg *msgs; 162 | struct _mosquitto_acl_user *acl_list; 163 | struct _mqtt3_listener *listener; 164 | time_t disconnect_t; 165 | int pollfd_index; 166 | #else 167 | void *userdata; 168 | bool in_callback; 169 | unsigned int message_retry; 170 | time_t last_retry_check; 171 | struct mosquitto_message_all *messages; 172 | void (*on_connect)(struct mosquitto *, void *userdata, int rc); 173 | void (*on_disconnect)(struct mosquitto *, void *userdata, int rc); 174 | void (*on_publish)(struct mosquitto *, void *userdata, int mid); 175 | void (*on_message)(struct mosquitto *, void *userdata, const struct mosquitto_message *message); 176 | void (*on_subscribe)(struct mosquitto *, void *userdata, int mid, int qos_count, const int *granted_qos); 177 | void (*on_unsubscribe)(struct mosquitto *, void *userdata, int mid); 178 | void (*on_log)(struct mosquitto *, void *userdata, int level, const char *str); 179 | //void (*on_error)(); 180 | char *host; 181 | int port; 182 | int queue_len; 183 | #endif 184 | }; 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /libmosquitto/read_handle.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009,2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | int _mosquitto_packet_handle(struct mosquitto *mosq) 45 | { 46 | assert(mosq); 47 | 48 | switch((mosq->in_packet.command)&0xF0){ 49 | case PINGREQ: 50 | return _mosquitto_handle_pingreq(mosq); 51 | case PINGRESP: 52 | return _mosquitto_handle_pingresp(mosq); 53 | case PUBACK: 54 | return _mosquitto_handle_pubackcomp(mosq, "PUBACK"); 55 | case PUBCOMP: 56 | return _mosquitto_handle_pubackcomp(mosq, "PUBCOMP"); 57 | case PUBLISH: 58 | return _mosquitto_handle_publish(mosq); 59 | case PUBREC: 60 | return _mosquitto_handle_pubrec(mosq); 61 | case PUBREL: 62 | return _mosquitto_handle_pubrel(NULL, mosq); 63 | case CONNACK: 64 | return _mosquitto_handle_connack(mosq); 65 | case SUBACK: 66 | return _mosquitto_handle_suback(mosq); 67 | case UNSUBACK: 68 | return _mosquitto_handle_unsuback(mosq); 69 | default: 70 | /* If we don't recognise the command, return an error straight away. */ 71 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unrecognised command %d\n", (mosq->in_packet.command)&0xF0); 72 | return MOSQ_ERR_PROTOCOL; 73 | } 74 | } 75 | 76 | int _mosquitto_handle_publish(struct mosquitto *mosq) 77 | { 78 | uint8_t header; 79 | struct mosquitto_message_all *message; 80 | int rc = 0; 81 | uint16_t mid; 82 | 83 | assert(mosq); 84 | 85 | message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all)); 86 | if(!message) return MOSQ_ERR_NOMEM; 87 | 88 | header = mosq->in_packet.command; 89 | 90 | message->direction = mosq_md_in; 91 | message->dup = (header & 0x08)>>3; 92 | message->msg.qos = (header & 0x06)>>1; 93 | message->msg.retain = (header & 0x01); 94 | 95 | rc = _mosquitto_read_string(&mosq->in_packet, &message->msg.topic); 96 | if(rc){ 97 | _mosquitto_message_cleanup(&message); 98 | return rc; 99 | } 100 | rc = _mosquitto_fix_sub_topic(&message->msg.topic); 101 | if(rc){ 102 | _mosquitto_message_cleanup(&message); 103 | return rc; 104 | } 105 | if(!strlen(message->msg.topic)){ 106 | _mosquitto_message_cleanup(&message); 107 | return MOSQ_ERR_PROTOCOL; 108 | } 109 | 110 | if(message->msg.qos > 0){ 111 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid); 112 | if(rc){ 113 | _mosquitto_message_cleanup(&message); 114 | return rc; 115 | } 116 | message->msg.mid = (int)mid; 117 | } 118 | 119 | message->msg.payloadlen = mosq->in_packet.remaining_length - mosq->in_packet.pos; 120 | if(message->msg.payloadlen){ 121 | message->msg.payload = _mosquitto_calloc(message->msg.payloadlen+1, sizeof(uint8_t)); 122 | rc = _mosquitto_read_bytes(&mosq->in_packet, message->msg.payload, message->msg.payloadlen); 123 | if(rc){ 124 | _mosquitto_message_cleanup(&message); 125 | return rc; 126 | } 127 | } 128 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, 129 | "Client %s received PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", 130 | mosq->id, message->dup, message->msg.qos, message->msg.retain, 131 | message->msg.mid, message->msg.topic, 132 | (long)message->msg.payloadlen); 133 | 134 | message->timestamp = time(NULL); 135 | switch(message->msg.qos){ 136 | case 0: 137 | pthread_mutex_lock(&mosq->callback_mutex); 138 | if(mosq->on_message){ 139 | mosq->in_callback = true; 140 | mosq->on_message(mosq, mosq->userdata, &message->msg); 141 | mosq->in_callback = false; 142 | } 143 | pthread_mutex_unlock(&mosq->callback_mutex); 144 | _mosquitto_message_cleanup(&message); 145 | return MOSQ_ERR_SUCCESS; 146 | case 1: 147 | rc = _mosquitto_send_puback(mosq, message->msg.mid); 148 | pthread_mutex_lock(&mosq->callback_mutex); 149 | if(mosq->on_message){ 150 | mosq->in_callback = true; 151 | mosq->on_message(mosq, mosq->userdata, &message->msg); 152 | mosq->in_callback = false; 153 | } 154 | pthread_mutex_unlock(&mosq->callback_mutex); 155 | _mosquitto_message_cleanup(&message); 156 | return rc; 157 | case 2: 158 | rc = _mosquitto_send_pubrec(mosq, message->msg.mid); 159 | message->state = mosq_ms_wait_pubrel; 160 | _mosquitto_message_queue(mosq, message); 161 | return rc; 162 | default: 163 | return MOSQ_ERR_PROTOCOL; 164 | } 165 | } 166 | 167 | -------------------------------------------------------------------------------- /HomeWatch/MosquittoClient.m: -------------------------------------------------------------------------------- 1 | // 2 | // MosquittoClient.m 3 | // 4 | // Copyright 2012 Nicholas Humfrey. All rights reserved. 5 | // Modified by Basuke Suzuki 2013. 6 | // 7 | 8 | #import "MosquittoClient.h" 9 | 10 | // C Callbacks 11 | static void on_connect(struct mosquitto *mosq, void *obj, int rc); 12 | static void on_disconnect(struct mosquitto *mosq, void *obj, int rc); 13 | static void on_publish(struct mosquitto *mosq, void *obj, int message_id); 14 | static void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message); 15 | static void on_subscribe(struct mosquitto *mosq, void *obj, int message_id, int qos_count, const int *granted_qos); 16 | static void on_unsubscribe(struct mosquitto *mosq, void *obj, int message_id); 17 | static void on_log(struct mosquitto *mosq, void *obj, int level, const char *str); 18 | 19 | 20 | @implementation MosquittoClient { 21 | struct mosquitto *_mosq; 22 | BOOL _connected; 23 | NSTimer *_idleTimer; 24 | } 25 | 26 | // Initialize is called just before the first object is allocated 27 | + (void)initialize { 28 | mosquitto_lib_init(); 29 | } 30 | 31 | + (NSString*)version { 32 | int major, minor, revision; 33 | mosquitto_lib_version(&major, &minor, &revision); 34 | return [NSString stringWithFormat:@"%d.%d.%d", major, minor, revision]; 35 | } 36 | 37 | - (MosquittoClient*)initWithClientId:(NSString*)clientId cleanSession:(BOOL)isCleanSession { 38 | if ((self = [super init])) { 39 | const char* cstrClientId = [clientId UTF8String]; 40 | [self setHost: @"localhost"]; 41 | [self setPort: 1883]; 42 | [self setKeepAlive: 60]; 43 | 44 | _mosq = mosquitto_new(cstrClientId, isCleanSession, (__bridge void *)(self)); 45 | mosquitto_connect_callback_set(_mosq, on_connect); 46 | mosquitto_disconnect_callback_set(_mosq, on_disconnect); 47 | mosquitto_publish_callback_set(_mosq, on_publish); 48 | mosquitto_message_callback_set(_mosq, on_message); 49 | mosquitto_subscribe_callback_set(_mosq, on_subscribe); 50 | mosquitto_unsubscribe_callback_set(_mosq, on_unsubscribe); 51 | } 52 | return self; 53 | } 54 | 55 | - (void)dealloc { 56 | if (_mosq) { 57 | [self disconnect]; 58 | 59 | mosquitto_destroy(_mosq); 60 | _mosq = NULL; 61 | } 62 | } 63 | 64 | - (BOOL)connect { 65 | if (_connected) return YES; 66 | 67 | const char *cstrHost = [_host cStringUsingEncoding:NSASCIIStringEncoding]; 68 | const char *cstrUsername = NULL, *cstrPassword = NULL; 69 | 70 | if (_username) 71 | cstrUsername = [_username UTF8String]; 72 | 73 | if (_password) 74 | cstrPassword = [_password UTF8String]; 75 | 76 | mosquitto_username_pw_set(_mosq, cstrUsername, cstrPassword); 77 | 78 | int rc = mosquitto_connect(_mosq, cstrHost, _port, _keepAlive); 79 | if (rc == MOSQ_ERR_ERRNO) { 80 | NSError *err = [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithUTF8String:strerror(errno)]}]; 81 | [self.delegate mosquitto:self didFailToConnectWithError:err]; 82 | return NO; 83 | } 84 | 85 | _connected = YES; 86 | _idleTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(onIdle:) userInfo:nil repeats:YES]; 87 | 88 | return YES; 89 | } 90 | 91 | - (void)disconnect { 92 | if (_connected) { 93 | mosquitto_disconnect(_mosq); 94 | } 95 | } 96 | 97 | - (BOOL)isConnected 98 | { 99 | return _connected; 100 | } 101 | 102 | - (void)setWill:(NSString *)payload toTopic:(NSString *)topic withQos:(NSUInteger)qos retained:(BOOL)retained; 103 | { 104 | const char* cstrTopic = [topic UTF8String]; 105 | const uint8_t* cstrPayload = (const uint8_t*)[payload UTF8String]; 106 | size_t cstrlen = [payload lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 107 | mosquitto_will_set(_mosq, cstrTopic, cstrlen, cstrPayload, qos, retained); 108 | } 109 | 110 | 111 | - (void)clearWill 112 | { 113 | mosquitto_will_clear(_mosq); 114 | } 115 | 116 | - (void)publish:(NSString *)payload toTopic:(NSString *)topic withQos:(NSUInteger)qos retained:(BOOL)retained { 117 | const char* cstrTopic = [topic UTF8String]; 118 | const uint8_t* cstrPayload = (const uint8_t*)[payload UTF8String]; 119 | size_t cstrlen = [payload lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 120 | mosquitto_publish(_mosq, NULL, cstrTopic, cstrlen, cstrPayload, qos, retained); 121 | 122 | } 123 | 124 | - (void)subscribe: (NSString *)topic { 125 | [self subscribe:topic withQos:0]; 126 | } 127 | 128 | - (void)subscribe: (NSString *)topic withQos:(NSUInteger)qos { 129 | const char* cstrTopic = [topic UTF8String]; 130 | mosquitto_subscribe(_mosq, NULL, cstrTopic, qos); 131 | } 132 | 133 | - (void)unsubscribe: (NSString *)topic { 134 | const char* cstrTopic = [topic UTF8String]; 135 | mosquitto_unsubscribe(_mosq, NULL, cstrTopic); 136 | } 137 | 138 | - (void)setMessageRetry: (NSUInteger)seconds 139 | { 140 | mosquitto_message_retry_set(_mosq, (unsigned int)seconds); 141 | } 142 | 143 | - (void)onMessage:(const struct mosquitto_message *)message 144 | { 145 | MosquittoMessage *mosq_msg = [[MosquittoMessage alloc] init]; 146 | 147 | mosq_msg.mid = message->mid; 148 | mosq_msg.qos = message->qos; 149 | mosq_msg.retained = message->retain; 150 | 151 | mosq_msg.topic = [NSString stringWithUTF8String: message->topic]; 152 | mosq_msg.payload = [[NSString alloc] initWithBytes:message->payload 153 | length:message->payloadlen 154 | encoding:NSUTF8StringEncoding]; 155 | 156 | [self.delegate mosquitto:self didReceiveMessage:mosq_msg]; 157 | } 158 | 159 | - (void)onDisconnected 160 | { 161 | [_idleTimer invalidate]; 162 | _idleTimer = nil; 163 | _connected = NO; 164 | 165 | [self.delegate mosquittoDidDisconnect:self]; 166 | } 167 | 168 | - (void)onIdle:(NSTimer *)timer 169 | { 170 | mosquitto_loop(_mosq, 1, 1); 171 | } 172 | 173 | @end 174 | 175 | static void on_connect(struct mosquitto *mosq, void *obj, int rc) 176 | { 177 | MosquittoClient* client = (__bridge MosquittoClient*)obj; 178 | [[client delegate] mosquitto:client didConnect:(NSUInteger)rc]; 179 | } 180 | 181 | static void on_disconnect(struct mosquitto *mosq, void *obj, int rc) 182 | { 183 | MosquittoClient* client = (__bridge MosquittoClient*)obj; 184 | [client onDisconnected]; 185 | } 186 | 187 | static void on_publish(struct mosquitto *mosq, void *obj, int message_id) 188 | { 189 | MosquittoClient* client = (__bridge MosquittoClient*)obj; 190 | [[client delegate] mosquitto:client didPublish:(NSUInteger)message_id]; 191 | } 192 | 193 | static void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message) 194 | { 195 | MosquittoClient* client = (__bridge MosquittoClient*)obj; 196 | [client onMessage:message]; 197 | } 198 | 199 | static void on_subscribe(struct mosquitto *mosq, void *obj, int message_id, int qos_count, const int *granted_qos) 200 | { 201 | MosquittoClient* client = (__bridge MosquittoClient*)obj; 202 | // FIXME: implement this 203 | [[client delegate] mosquitto:client didSubscribe:message_id grantedQos:nil]; 204 | } 205 | 206 | static void on_unsubscribe(struct mosquitto *mosq, void *obj, int message_id) 207 | { 208 | MosquittoClient* client = (__bridge MosquittoClient*)obj; 209 | [[client delegate] mosquitto:client didUnsubscribe:message_id]; 210 | } 211 | 212 | static void on_log(struct mosquitto *mosq, void *obj, int level, const char *str) 213 | { 214 | MosquittoClient* client = (__bridge MosquittoClient*)obj; 215 | NSString *message = [NSString stringWithUTF8String:str]; 216 | [[client delegate] mosquitto:client log:message level:level]; 217 | } 218 | 219 | -------------------------------------------------------------------------------- /libmosquitto/messages_mosq.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | void _mosquitto_message_cleanup(struct mosquitto_message_all **message) 41 | { 42 | struct mosquitto_message_all *msg; 43 | 44 | if(!message || !*message) return; 45 | 46 | msg = *message; 47 | 48 | if(msg->msg.topic) _mosquitto_free(msg->msg.topic); 49 | if(msg->msg.payload) _mosquitto_free(msg->msg.payload); 50 | _mosquitto_free(msg); 51 | } 52 | 53 | void _mosquitto_message_cleanup_all(struct mosquitto *mosq) 54 | { 55 | struct mosquitto_message_all *tmp; 56 | 57 | assert(mosq); 58 | 59 | while(mosq->messages){ 60 | tmp = mosq->messages->next; 61 | _mosquitto_message_cleanup(&mosq->messages); 62 | mosq->messages = tmp; 63 | } 64 | } 65 | 66 | int mosquitto_message_copy(struct mosquitto_message *dst, const struct mosquitto_message *src) 67 | { 68 | if(!dst || !src) return MOSQ_ERR_INVAL; 69 | 70 | dst->mid = src->mid; 71 | dst->topic = _mosquitto_strdup(src->topic); 72 | if(!dst->topic) return MOSQ_ERR_NOMEM; 73 | dst->qos = src->qos; 74 | dst->retain = src->retain; 75 | if(src->payloadlen){ 76 | dst->payload = _mosquitto_malloc(src->payloadlen); 77 | if(!dst->payload){ 78 | _mosquitto_free(dst->topic); 79 | return MOSQ_ERR_NOMEM; 80 | } 81 | memcpy(dst->payload, src->payload, src->payloadlen); 82 | dst->payloadlen = src->payloadlen; 83 | }else{ 84 | dst->payloadlen = 0; 85 | dst->payload = NULL; 86 | } 87 | return MOSQ_ERR_SUCCESS; 88 | } 89 | 90 | int _mosquitto_message_delete(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir) 91 | { 92 | struct mosquitto_message_all *message; 93 | int rc; 94 | assert(mosq); 95 | 96 | rc = _mosquitto_message_remove(mosq, mid, dir, &message); 97 | if(rc == MOSQ_ERR_SUCCESS){ 98 | _mosquitto_message_cleanup(&message); 99 | } 100 | return rc; 101 | } 102 | 103 | void mosquitto_message_free(struct mosquitto_message **message) 104 | { 105 | struct mosquitto_message *msg; 106 | 107 | if(!message || !*message) return; 108 | 109 | msg = *message; 110 | 111 | if(msg->topic) _mosquitto_free(msg->topic); 112 | if(msg->payload) _mosquitto_free(msg->payload); 113 | _mosquitto_free(msg); 114 | } 115 | 116 | void _mosquitto_message_queue(struct mosquitto *mosq, struct mosquitto_message_all *message) 117 | { 118 | struct mosquitto_message_all *tail; 119 | 120 | assert(mosq); 121 | assert(message); 122 | 123 | mosq->queue_len++; 124 | message->next = NULL; 125 | if(mosq->messages){ 126 | tail = mosq->messages; 127 | while(tail->next){ 128 | tail = tail->next; 129 | } 130 | tail->next = message; 131 | }else{ 132 | mosq->messages = message; 133 | } 134 | } 135 | 136 | void _mosquitto_messages_reconnect_reset(struct mosquitto *mosq) 137 | { 138 | struct mosquitto_message_all *message; 139 | struct mosquitto_message_all *prev = NULL; 140 | assert(mosq); 141 | 142 | mosq->queue_len = 0; 143 | message = mosq->messages; 144 | while(message){ 145 | message->timestamp = 0; 146 | if(message->direction == mosq_md_out){ 147 | if(message->msg.qos == 1){ 148 | message->state = mosq_ms_wait_puback; 149 | }else if(message->msg.qos == 2){ 150 | message->state = mosq_ms_wait_pubrec; 151 | } 152 | mosq->queue_len++; 153 | }else{ 154 | if(prev){ 155 | prev->next = message->next; 156 | _mosquitto_message_cleanup(&message); 157 | message = prev; 158 | }else{ 159 | mosq->messages = message->next; 160 | _mosquitto_message_cleanup(&message); 161 | message = mosq->messages; 162 | } 163 | } 164 | prev = message; 165 | message = message->next; 166 | } 167 | } 168 | 169 | int _mosquitto_message_remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, struct mosquitto_message_all **message) 170 | { 171 | struct mosquitto_message_all *cur, *prev = NULL; 172 | assert(mosq); 173 | assert(message); 174 | 175 | cur = mosq->messages; 176 | while(cur){ 177 | if(cur->msg.mid == mid && cur->direction == dir){ 178 | if(prev){ 179 | prev->next = cur->next; 180 | }else{ 181 | mosq->messages = cur->next; 182 | } 183 | *message = cur; 184 | mosq->queue_len--; 185 | return MOSQ_ERR_SUCCESS; 186 | } 187 | prev = cur; 188 | cur = cur->next; 189 | } 190 | return MOSQ_ERR_NOT_FOUND; 191 | } 192 | 193 | void _mosquitto_message_retry_check(struct mosquitto *mosq) 194 | { 195 | struct mosquitto_message_all *message; 196 | time_t now = time(NULL); 197 | assert(mosq); 198 | 199 | message = mosq->messages; 200 | while(message){ 201 | if(message->timestamp + mosq->message_retry < now){ 202 | switch(message->state){ 203 | case mosq_ms_wait_puback: 204 | case mosq_ms_wait_pubrec: 205 | message->timestamp = now; 206 | message->dup = true; 207 | _mosquitto_send_publish(mosq, message->msg.mid, message->msg.topic, message->msg.payloadlen, message->msg.payload, message->msg.qos, message->msg.retain, message->dup); 208 | break; 209 | case mosq_ms_wait_pubrel: 210 | message->timestamp = now; 211 | message->dup = true; 212 | _mosquitto_send_pubrec(mosq, message->msg.mid); 213 | break; 214 | case mosq_ms_wait_pubcomp: 215 | message->timestamp = now; 216 | message->dup = true; 217 | _mosquitto_send_pubrel(mosq, message->msg.mid, true); 218 | break; 219 | default: 220 | break; 221 | } 222 | } 223 | message = message->next; 224 | } 225 | } 226 | 227 | void mosquitto_message_retry_set(struct mosquitto *mosq, unsigned int message_retry) 228 | { 229 | assert(mosq); 230 | if(mosq) mosq->message_retry = message_retry; 231 | } 232 | 233 | int _mosquitto_message_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, enum mosquitto_msg_state state) 234 | { 235 | struct mosquitto_message_all *message; 236 | assert(mosq); 237 | 238 | message = mosq->messages; 239 | while(message){ 240 | if(message->msg.mid == mid && message->direction == dir){ 241 | message->state = state; 242 | message->timestamp = time(NULL); 243 | return MOSQ_ERR_SUCCESS; 244 | } 245 | message = message->next; 246 | } 247 | return MOSQ_ERR_NOT_FOUND; 248 | } 249 | 250 | -------------------------------------------------------------------------------- /libmosquitto/send_client_mosq.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009-2011 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #ifdef WITH_BROKER 42 | #include 43 | #endif 44 | 45 | int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session) 46 | { 47 | struct _mosquitto_packet *packet = NULL; 48 | int payloadlen; 49 | uint8_t will = 0; 50 | uint8_t byte; 51 | int rc; 52 | uint8_t version = PROTOCOL_VERSION; 53 | 54 | assert(mosq); 55 | assert(mosq->id); 56 | 57 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet)); 58 | if(!packet) return MOSQ_ERR_NOMEM; 59 | 60 | payloadlen = 2+strlen(mosq->id); 61 | if(mosq->will){ 62 | will = 1; 63 | assert(mosq->will->topic); 64 | 65 | payloadlen += 2+strlen(mosq->will->topic) + 2+mosq->will->payloadlen; 66 | } 67 | if(mosq->username){ 68 | payloadlen += 2+strlen(mosq->username); 69 | if(mosq->password){ 70 | payloadlen += 2+strlen(mosq->password); 71 | } 72 | } 73 | 74 | packet->command = CONNECT; 75 | packet->remaining_length = 12+payloadlen; 76 | rc = _mosquitto_packet_alloc(packet); 77 | if(rc){ 78 | _mosquitto_free(packet); 79 | return rc; 80 | } 81 | 82 | /* Variable header */ 83 | _mosquitto_write_string(packet, PROTOCOL_NAME, strlen(PROTOCOL_NAME)); 84 | #if defined(WITH_BROKER) && defined(WITH_BRIDGE) 85 | if(mosq->bridge && mosq->bridge->try_private && mosq->bridge->try_private_accepted){ 86 | version |= 0x80; 87 | }else{ 88 | } 89 | #endif 90 | _mosquitto_write_byte(packet, version); 91 | byte = (clean_session&0x1)<<1; 92 | if(will){ 93 | byte = byte | ((mosq->will->retain&0x1)<<5) | ((mosq->will->qos&0x3)<<3) | ((will&0x1)<<2); 94 | } 95 | if(mosq->username){ 96 | byte = byte | 0x1<<7; 97 | if(mosq->password){ 98 | byte = byte | 0x1<<6; 99 | } 100 | } 101 | _mosquitto_write_byte(packet, byte); 102 | _mosquitto_write_uint16(packet, keepalive); 103 | 104 | /* Payload */ 105 | _mosquitto_write_string(packet, mosq->id, strlen(mosq->id)); 106 | if(will){ 107 | _mosquitto_write_string(packet, mosq->will->topic, strlen(mosq->will->topic)); 108 | _mosquitto_write_string(packet, (const char *)mosq->will->payload, mosq->will->payloadlen); 109 | } 110 | if(mosq->username){ 111 | _mosquitto_write_string(packet, mosq->username, strlen(mosq->username)); 112 | if(mosq->password){ 113 | _mosquitto_write_string(packet, mosq->password, strlen(mosq->password)); 114 | } 115 | } 116 | 117 | mosq->keepalive = keepalive; 118 | #ifdef WITH_BROKER 119 | # ifdef WITH_BRIDGE 120 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending CONNECT", mosq->id); 121 | # endif 122 | #else 123 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending CONNECT", mosq->id); 124 | #endif 125 | return _mosquitto_packet_queue(mosq, packet); 126 | } 127 | 128 | int _mosquitto_send_disconnect(struct mosquitto *mosq) 129 | { 130 | assert(mosq); 131 | #ifdef WITH_BROKER 132 | # ifdef WITH_BRIDGE 133 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending DISCONNECT", mosq->id); 134 | # endif 135 | #else 136 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending DISCONNECT", mosq->id); 137 | #endif 138 | return _mosquitto_send_simple_command(mosq, DISCONNECT); 139 | } 140 | 141 | int _mosquitto_send_subscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic, uint8_t topic_qos) 142 | { 143 | /* FIXME - only deals with a single topic */ 144 | struct _mosquitto_packet *packet = NULL; 145 | uint32_t packetlen; 146 | uint16_t local_mid; 147 | int rc; 148 | 149 | assert(mosq); 150 | assert(topic); 151 | 152 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet)); 153 | if(!packet) return MOSQ_ERR_NOMEM; 154 | 155 | packetlen = 2 + 2+strlen(topic) + 1; 156 | 157 | packet->command = SUBSCRIBE | (dup<<3) | (1<<1); 158 | packet->remaining_length = packetlen; 159 | rc = _mosquitto_packet_alloc(packet); 160 | if(rc){ 161 | _mosquitto_free(packet); 162 | return rc; 163 | } 164 | 165 | /* Variable header */ 166 | local_mid = _mosquitto_mid_generate(mosq); 167 | if(mid) *mid = (int)local_mid; 168 | _mosquitto_write_uint16(packet, local_mid); 169 | 170 | /* Payload */ 171 | _mosquitto_write_string(packet, topic, strlen(topic)); 172 | _mosquitto_write_byte(packet, topic_qos); 173 | 174 | #ifdef WITH_BROKER 175 | # ifdef WITH_BRIDGE 176 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d)", mosq->id, local_mid, topic, topic_qos); 177 | # endif 178 | #else 179 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d)", mosq->id, local_mid, topic, topic_qos); 180 | #endif 181 | 182 | return _mosquitto_packet_queue(mosq, packet); 183 | } 184 | 185 | 186 | int _mosquitto_send_unsubscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic) 187 | { 188 | /* FIXME - only deals with a single topic */ 189 | struct _mosquitto_packet *packet = NULL; 190 | uint32_t packetlen; 191 | uint16_t local_mid; 192 | int rc; 193 | 194 | assert(mosq); 195 | assert(topic); 196 | 197 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet)); 198 | if(!packet) return MOSQ_ERR_NOMEM; 199 | 200 | packetlen = 2 + 2+strlen(topic); 201 | 202 | packet->command = UNSUBSCRIBE | (dup<<3) | (1<<1); 203 | packet->remaining_length = packetlen; 204 | rc = _mosquitto_packet_alloc(packet); 205 | if(rc){ 206 | _mosquitto_free(packet); 207 | return rc; 208 | } 209 | 210 | /* Variable header */ 211 | local_mid = _mosquitto_mid_generate(mosq); 212 | if(mid) *mid = (int)local_mid; 213 | _mosquitto_write_uint16(packet, local_mid); 214 | 215 | /* Payload */ 216 | _mosquitto_write_string(packet, topic, strlen(topic)); 217 | 218 | #ifdef WITH_BROKER 219 | # ifdef WITH_BRIDGE 220 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending UNSUBSCRIBE (Mid: %d, Topic: %s)", mosq->id, local_mid, topic); 221 | # endif 222 | #else 223 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending UNSUBSCRIBE (Mid: %d, Topic: %s)", mosq->id, local_mid, topic); 224 | #endif 225 | return _mosquitto_packet_queue(mosq, packet); 226 | } 227 | 228 | -------------------------------------------------------------------------------- /libmosquitto/read_handle_shared.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009-2012 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #ifdef WITH_BROKER 44 | #include 45 | #endif 46 | 47 | int _mosquitto_handle_pingreq(struct mosquitto *mosq) 48 | { 49 | assert(mosq); 50 | #ifdef WITH_STRICT_PROTOCOL 51 | if(mosq->in_packet.remaining_length != 0){ 52 | return MOSQ_ERR_PROTOCOL; 53 | } 54 | #endif 55 | #ifdef WITH_BROKER 56 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PINGREQ from %s", mosq->id); 57 | #else 58 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PINGREQ", mosq->id); 59 | #endif 60 | return _mosquitto_send_pingresp(mosq); 61 | } 62 | 63 | int _mosquitto_handle_pingresp(struct mosquitto *mosq) 64 | { 65 | assert(mosq); 66 | #ifdef WITH_STRICT_PROTOCOL 67 | if(mosq->in_packet.remaining_length != 0){ 68 | return MOSQ_ERR_PROTOCOL; 69 | } 70 | #endif 71 | mosq->ping_t = 0; /* No longer waiting for a PINGRESP. */ 72 | #ifdef WITH_BROKER 73 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PINGRESP from %s", mosq->id); 74 | #else 75 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PINGRESP", mosq->id); 76 | #endif 77 | return MOSQ_ERR_SUCCESS; 78 | } 79 | 80 | int _mosquitto_handle_pubackcomp(struct mosquitto *mosq, const char *type) 81 | { 82 | uint16_t mid; 83 | int rc; 84 | 85 | assert(mosq); 86 | #ifdef WITH_STRICT_PROTOCOL 87 | if(mosq->in_packet.remaining_length != 2){ 88 | return MOSQ_ERR_PROTOCOL; 89 | } 90 | #endif 91 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid); 92 | if(rc) return rc; 93 | #ifdef WITH_BROKER 94 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received %s from %s (Mid: %d)", type, mosq->id, mid); 95 | 96 | if(mid){ 97 | rc = mqtt3_db_message_delete(mosq, mid, mosq_md_out); 98 | if(rc) return rc; 99 | } 100 | #else 101 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received %s (Mid: %d)", mosq->id, type, mid); 102 | 103 | if(!_mosquitto_message_delete(mosq, mid, mosq_md_out)){ 104 | /* Only inform the client the message has been sent once. */ 105 | pthread_mutex_lock(&mosq->callback_mutex); 106 | if(mosq->on_publish){ 107 | mosq->in_callback = true; 108 | mosq->on_publish(mosq, mosq->userdata, mid); 109 | mosq->in_callback = false; 110 | } 111 | pthread_mutex_unlock(&mosq->callback_mutex); 112 | } 113 | #endif 114 | 115 | return MOSQ_ERR_SUCCESS; 116 | } 117 | 118 | int _mosquitto_handle_pubrec(struct mosquitto *mosq) 119 | { 120 | uint16_t mid; 121 | int rc; 122 | 123 | assert(mosq); 124 | #ifdef WITH_STRICT_PROTOCOL 125 | if(mosq->in_packet.remaining_length != 2){ 126 | return MOSQ_ERR_PROTOCOL; 127 | } 128 | #endif 129 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid); 130 | if(rc) return rc; 131 | #ifdef WITH_BROKER 132 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREC from %s (Mid: %d)", mosq->id, mid); 133 | 134 | rc = mqtt3_db_message_update(mosq, mid, mosq_md_out, ms_wait_for_pubcomp); 135 | #else 136 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREC (Mid: %d)", mosq->id, mid); 137 | 138 | rc = _mosquitto_message_update(mosq, mid, mosq_md_out, mosq_ms_wait_pubcomp); 139 | #endif 140 | if(rc) return rc; 141 | rc = _mosquitto_send_pubrel(mosq, mid, false); 142 | if(rc) return rc; 143 | 144 | return MOSQ_ERR_SUCCESS; 145 | } 146 | 147 | int _mosquitto_handle_pubrel(struct mosquitto_db *db, struct mosquitto *mosq) 148 | { 149 | uint16_t mid; 150 | #ifndef WITH_BROKER 151 | struct mosquitto_message_all *message = NULL; 152 | #endif 153 | int rc; 154 | 155 | assert(mosq); 156 | #ifdef WITH_STRICT_PROTOCOL 157 | if(mosq->in_packet.remaining_length != 2){ 158 | return MOSQ_ERR_PROTOCOL; 159 | } 160 | #endif 161 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid); 162 | if(rc) return rc; 163 | #ifdef WITH_BROKER 164 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREL from %s (Mid: %d)", mosq->id, mid); 165 | 166 | if(mqtt3_db_message_release(db, mosq, mid, mosq_md_in)){ 167 | /* Message not found. */ 168 | return MOSQ_ERR_SUCCESS; 169 | } 170 | #else 171 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREL (Mid: %d)", mosq->id, mid); 172 | 173 | if(!_mosquitto_message_remove(mosq, mid, mosq_md_in, &message)){ 174 | /* Only pass the message on if we have removed it from the queue - this 175 | * prevents multiple callbacks for the same message. */ 176 | pthread_mutex_lock(&mosq->callback_mutex); 177 | if(mosq->on_message){ 178 | mosq->in_callback = true; 179 | mosq->on_message(mosq, mosq->userdata, &message->msg); 180 | mosq->in_callback = false; 181 | } 182 | pthread_mutex_unlock(&mosq->callback_mutex); 183 | _mosquitto_message_cleanup(&message); 184 | } 185 | #endif 186 | rc = _mosquitto_send_pubcomp(mosq, mid); 187 | if(rc) return rc; 188 | 189 | return MOSQ_ERR_SUCCESS; 190 | } 191 | 192 | int _mosquitto_handle_suback(struct mosquitto *mosq) 193 | { 194 | uint16_t mid; 195 | uint8_t qos; 196 | int *granted_qos; 197 | int qos_count; 198 | int i = 0; 199 | int rc; 200 | 201 | assert(mosq); 202 | #ifdef WITH_BROKER 203 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received SUBACK from %s", mosq->id); 204 | #else 205 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received SUBACK", mosq->id); 206 | #endif 207 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid); 208 | if(rc) return rc; 209 | 210 | qos_count = mosq->in_packet.remaining_length - mosq->in_packet.pos; 211 | granted_qos = _mosquitto_malloc(qos_count*sizeof(int)); 212 | if(!granted_qos) return MOSQ_ERR_NOMEM; 213 | while(mosq->in_packet.pos < mosq->in_packet.remaining_length){ 214 | rc = _mosquitto_read_byte(&mosq->in_packet, &qos); 215 | if(rc){ 216 | _mosquitto_free(granted_qos); 217 | return rc; 218 | } 219 | granted_qos[i] = (int)qos; 220 | i++; 221 | } 222 | #ifndef WITH_BROKER 223 | pthread_mutex_lock(&mosq->callback_mutex); 224 | if(mosq->on_subscribe){ 225 | mosq->in_callback = true; 226 | mosq->on_subscribe(mosq, mosq->userdata, mid, qos_count, granted_qos); 227 | mosq->in_callback = false; 228 | } 229 | pthread_mutex_unlock(&mosq->callback_mutex); 230 | #endif 231 | _mosquitto_free(granted_qos); 232 | 233 | return MOSQ_ERR_SUCCESS; 234 | } 235 | 236 | int _mosquitto_handle_unsuback(struct mosquitto *mosq) 237 | { 238 | uint16_t mid; 239 | int rc; 240 | 241 | assert(mosq); 242 | #ifdef WITH_STRICT_PROTOCOL 243 | if(mosq->in_packet.remaining_length != 2){ 244 | return MOSQ_ERR_PROTOCOL; 245 | } 246 | #endif 247 | #ifdef WITH_BROKER 248 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received UNSUBACK from %s", mosq->id); 249 | #else 250 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received UNSUBACK", mosq->id); 251 | #endif 252 | rc = _mosquitto_read_uint16(&mosq->in_packet, &mid); 253 | if(rc) return rc; 254 | #ifndef WITH_BROKER 255 | pthread_mutex_lock(&mosq->callback_mutex); 256 | if(mosq->on_unsubscribe){ 257 | mosq->in_callback = true; 258 | mosq->on_unsubscribe(mosq, mosq->userdata, mid); 259 | mosq->in_callback = false; 260 | } 261 | pthread_mutex_unlock(&mosq->callback_mutex); 262 | #endif 263 | 264 | return MOSQ_ERR_SUCCESS; 265 | } 266 | 267 | -------------------------------------------------------------------------------- /libmosquitto/util_mosq.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009-2012 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #ifdef WIN32 35 | #include 36 | #endif 37 | 38 | #if defined(WITH_TLS) && defined(WITH_TLS_PSK) 39 | #include 40 | #endif 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #ifdef WITH_BROKER 49 | #include 50 | #endif 51 | 52 | int _mosquitto_packet_alloc(struct _mosquitto_packet *packet) 53 | { 54 | uint8_t remaining_bytes[5], byte; 55 | uint32_t remaining_length; 56 | int i; 57 | 58 | assert(packet); 59 | 60 | remaining_length = packet->remaining_length; 61 | packet->payload = NULL; 62 | packet->remaining_count = 0; 63 | do{ 64 | byte = remaining_length % 128; 65 | remaining_length = remaining_length / 128; 66 | /* If there are more digits to encode, set the top bit of this digit */ 67 | if(remaining_length > 0){ 68 | byte = byte | 0x80; 69 | } 70 | remaining_bytes[packet->remaining_count] = byte; 71 | packet->remaining_count++; 72 | }while(remaining_length > 0 && packet->remaining_count < 5); 73 | if(packet->remaining_count == 5) return MOSQ_ERR_PAYLOAD_SIZE; 74 | packet->packet_length = packet->remaining_length + 1 + packet->remaining_count; 75 | packet->payload = _mosquitto_malloc(sizeof(uint8_t)*packet->packet_length); 76 | if(!packet->payload) return MOSQ_ERR_NOMEM; 77 | 78 | packet->payload[0] = packet->command; 79 | for(i=0; iremaining_count; i++){ 80 | packet->payload[i+1] = remaining_bytes[i]; 81 | } 82 | packet->pos = 1 + packet->remaining_count; 83 | 84 | return MOSQ_ERR_SUCCESS; 85 | } 86 | 87 | void _mosquitto_check_keepalive(struct mosquitto *mosq) 88 | { 89 | time_t last_msg_out; 90 | time_t last_msg_in; 91 | time_t now = time(NULL); 92 | #ifndef WITH_BROKER 93 | int rc; 94 | #endif 95 | 96 | assert(mosq); 97 | #if defined(WITH_BROKER) && defined(WITH_BRIDGE) 98 | /* Check if a lazy bridge should be timed out due to idle. */ 99 | if(mosq->bridge && mosq->bridge->start_type == bst_lazy 100 | && mosq->sock != INVALID_SOCKET 101 | && now - mosq->last_msg_out >= mosq->bridge->idle_timeout){ 102 | 103 | _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Bridge connection %s has exceeded idle timeout, disconnecting.", mosq->id); 104 | _mosquitto_socket_close(mosq); 105 | return; 106 | } 107 | #endif 108 | pthread_mutex_lock(&mosq->msgtime_mutex); 109 | last_msg_out = mosq->last_msg_out; 110 | last_msg_in = mosq->last_msg_in; 111 | pthread_mutex_unlock(&mosq->msgtime_mutex); 112 | if(mosq->sock != INVALID_SOCKET && 113 | (now - last_msg_out >= mosq->keepalive || now - last_msg_in >= mosq->keepalive)){ 114 | 115 | if(mosq->state == mosq_cs_connected && mosq->ping_t == 0){ 116 | _mosquitto_send_pingreq(mosq); 117 | /* Reset last msg times to give the server time to send a pingresp */ 118 | pthread_mutex_lock(&mosq->msgtime_mutex); 119 | mosq->last_msg_in = now; 120 | mosq->last_msg_out = now; 121 | pthread_mutex_unlock(&mosq->msgtime_mutex); 122 | }else{ 123 | #ifdef WITH_BROKER 124 | if(mosq->listener){ 125 | mosq->listener->client_count--; 126 | assert(mosq->listener->client_count >= 0); 127 | } 128 | mosq->listener = NULL; 129 | #endif 130 | _mosquitto_socket_close(mosq); 131 | #ifndef WITH_BROKER 132 | pthread_mutex_lock(&mosq->state_mutex); 133 | if(mosq->state == mosq_cs_disconnecting){ 134 | rc = MOSQ_ERR_SUCCESS; 135 | }else{ 136 | rc = 1; 137 | } 138 | pthread_mutex_unlock(&mosq->state_mutex); 139 | pthread_mutex_lock(&mosq->callback_mutex); 140 | if(mosq->on_disconnect){ 141 | mosq->in_callback = true; 142 | mosq->on_disconnect(mosq, mosq->userdata, rc); 143 | mosq->in_callback = false; 144 | } 145 | pthread_mutex_unlock(&mosq->callback_mutex); 146 | #endif 147 | } 148 | } 149 | } 150 | 151 | /* Convert ////some////over/slashed///topic/etc/etc// 152 | * into some/over/slashed/topic/etc/etc 153 | */ 154 | int _mosquitto_fix_sub_topic(char **subtopic) 155 | { 156 | char *fixed = NULL; 157 | char *token; 158 | char *saveptr = NULL; 159 | 160 | assert(subtopic); 161 | assert(*subtopic); 162 | 163 | if(strlen(*subtopic) == 0) return MOSQ_ERR_SUCCESS; 164 | /* size of fixed here is +1 for the terminating 0 and +1 for the spurious / 165 | * that gets appended. */ 166 | fixed = _mosquitto_calloc(strlen(*subtopic)+2, 1); 167 | if(!fixed) return MOSQ_ERR_NOMEM; 168 | 169 | if((*subtopic)[0] == '/'){ 170 | fixed[0] = '/'; 171 | } 172 | token = strtok_r(*subtopic, "/", &saveptr); 173 | while(token){ 174 | strcat(fixed, token); 175 | strcat(fixed, "/"); 176 | token = strtok_r(NULL, "/", &saveptr); 177 | } 178 | 179 | fixed[strlen(fixed)-1] = '\0'; 180 | _mosquitto_free(*subtopic); 181 | *subtopic = fixed; 182 | return MOSQ_ERR_SUCCESS; 183 | } 184 | 185 | uint16_t _mosquitto_mid_generate(struct mosquitto *mosq) 186 | { 187 | assert(mosq); 188 | 189 | mosq->last_mid++; 190 | if(mosq->last_mid == 0) mosq->last_mid++; 191 | 192 | return mosq->last_mid; 193 | } 194 | 195 | /* Search for + or # in a topic. Return MOSQ_ERR_INVAL if found. 196 | * Also returns MOSQ_ERR_INVAL if the topic string is too long. 197 | * Returns MOSQ_ERR_SUCCESS if everything is fine. 198 | */ 199 | int _mosquitto_topic_wildcard_len_check(const char *str) 200 | { 201 | int len = 0; 202 | while(str && str[0]){ 203 | if(str[0] == '+' || str[0] == '#'){ 204 | return MOSQ_ERR_INVAL; 205 | } 206 | len++; 207 | str = &str[1]; 208 | } 209 | if(len > 65535) return MOSQ_ERR_INVAL; 210 | 211 | return MOSQ_ERR_SUCCESS; 212 | } 213 | 214 | /* Does a topic match a subscription? */ 215 | int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result) 216 | { 217 | char *local_sub, *local_topic; 218 | int slen, tlen; 219 | int spos, tpos; 220 | int rc; 221 | bool multilevel_wildcard = false; 222 | 223 | if(!sub || !topic || !result) return MOSQ_ERR_INVAL; 224 | 225 | local_sub = _mosquitto_strdup(sub); 226 | if(!local_sub) return MOSQ_ERR_NOMEM; 227 | rc = _mosquitto_fix_sub_topic(&local_sub); 228 | if(rc){ 229 | _mosquitto_free(local_sub); 230 | return rc; 231 | } 232 | 233 | local_topic = _mosquitto_strdup(topic); 234 | if(!local_topic){ 235 | _mosquitto_free(local_sub); 236 | return MOSQ_ERR_NOMEM; 237 | } 238 | rc = _mosquitto_fix_sub_topic(&local_topic); 239 | if(rc){ 240 | _mosquitto_free(local_sub); 241 | _mosquitto_free(local_topic); 242 | return rc; 243 | } 244 | 245 | slen = strlen(local_sub); 246 | tlen = strlen(local_topic); 247 | 248 | spos = 0; 249 | tpos = 0; 250 | 251 | while(spos < slen && tpos < tlen){ 252 | if(local_sub[spos] == local_topic[tpos]){ 253 | spos++; 254 | tpos++; 255 | if(spos == slen && tpos == tlen){ 256 | *result = true; 257 | break; 258 | } 259 | }else{ 260 | if(local_sub[spos] == '+'){ 261 | spos++; 262 | while(tpos < tlen && local_topic[tpos] != '/'){ 263 | tpos++; 264 | } 265 | if(tpos == tlen && spos == slen){ 266 | *result = true; 267 | break; 268 | } 269 | }else if(local_sub[spos] == '#'){ 270 | multilevel_wildcard = true; 271 | if(spos+1 != slen){ 272 | *result = false; 273 | break; 274 | }else{ 275 | *result = true; 276 | break; 277 | } 278 | }else{ 279 | *result = false; 280 | break; 281 | } 282 | } 283 | if(tpos == tlen-1){ 284 | /* Check for e.g. foo matching foo/# */ 285 | if(spos == slen-3 286 | && local_sub[spos+1] == '/' 287 | && local_sub[spos+2] == '#'){ 288 | *result = true; 289 | multilevel_wildcard = true; 290 | break; 291 | } 292 | } 293 | } 294 | if(multilevel_wildcard == false && (tpos < tlen || spos < slen)){ 295 | *result = false; 296 | } 297 | 298 | _mosquitto_free(local_sub); 299 | _mosquitto_free(local_topic); 300 | return MOSQ_ERR_SUCCESS; 301 | } 302 | 303 | #if defined(WITH_TLS) && defined(WITH_TLS_PSK) 304 | int _mosquitto_hex2bin(const char *hex, unsigned char *bin, int bin_max_len) 305 | { 306 | BIGNUM *bn = NULL; 307 | int len; 308 | 309 | if(BN_hex2bn(&bn, hex) == 0){ 310 | if(bn) BN_free(bn); 311 | return 0; 312 | } 313 | if(BN_num_bytes(bn) > bin_max_len){ 314 | BN_free(bn); 315 | return 0; 316 | } 317 | 318 | len = BN_bn2bin(bn, bin); 319 | BN_free(bn); 320 | return len; 321 | } 322 | #endif 323 | -------------------------------------------------------------------------------- /libmosquitto/send_mosq.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009-2011 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #ifdef WITH_BROKER 44 | #include 45 | extern uint64_t g_pub_bytes_sent; 46 | #endif 47 | 48 | int _mosquitto_send_pingreq(struct mosquitto *mosq) 49 | { 50 | int rc; 51 | assert(mosq); 52 | #ifdef WITH_BROKER 53 | _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGREQ to %s", mosq->id); 54 | #else 55 | _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGREQ", mosq->id); 56 | #endif 57 | rc = _mosquitto_send_simple_command(mosq, PINGREQ); 58 | if(rc == MOSQ_ERR_SUCCESS){ 59 | mosq->ping_t = time(NULL); 60 | } 61 | return rc; 62 | } 63 | 64 | int _mosquitto_send_pingresp(struct mosquitto *mosq) 65 | { 66 | #ifdef WITH_BROKER 67 | if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGRESP to %s", mosq->id); 68 | #else 69 | if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGRESP", mosq->id); 70 | #endif 71 | return _mosquitto_send_simple_command(mosq, PINGRESP); 72 | } 73 | 74 | int _mosquitto_send_puback(struct mosquitto *mosq, uint16_t mid) 75 | { 76 | #ifdef WITH_BROKER 77 | if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBACK to %s (Mid: %d)", mosq->id, mid); 78 | #else 79 | if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBACK (Mid: %d)", mosq->id, mid); 80 | #endif 81 | return _mosquitto_send_command_with_mid(mosq, PUBACK, mid, false); 82 | } 83 | 84 | int _mosquitto_send_pubcomp(struct mosquitto *mosq, uint16_t mid) 85 | { 86 | #ifdef WITH_BROKER 87 | if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBCOMP to %s (Mid: %d)", mosq->id, mid); 88 | #else 89 | if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBCOMP (Mid: %d)", mosq->id, mid); 90 | #endif 91 | return _mosquitto_send_command_with_mid(mosq, PUBCOMP, mid, false); 92 | } 93 | 94 | 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) 95 | { 96 | #ifdef WITH_BROKER 97 | size_t len; 98 | #ifdef WITH_BRIDGE 99 | int i; 100 | struct _mqtt3_bridge_topic *cur_topic; 101 | bool match; 102 | int rc; 103 | char *mapped_topic = NULL; 104 | char *topic_temp = NULL; 105 | #endif 106 | #endif 107 | assert(mosq); 108 | assert(topic); 109 | 110 | if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; 111 | #ifdef WITH_BROKER 112 | if(mosq->listener && mosq->listener->mount_point){ 113 | len = strlen(mosq->listener->mount_point); 114 | if(len > strlen(topic)){ 115 | topic += strlen(mosq->listener->mount_point); 116 | }else{ 117 | /* Invalid topic string. Should never happen, but silently swallow the message anyway. */ 118 | return MOSQ_ERR_SUCCESS; 119 | } 120 | } 121 | #ifdef WITH_BRIDGE 122 | if(mosq->bridge && mosq->bridge->topics && mosq->bridge->topic_remapping){ 123 | for(i=0; ibridge->topic_count; i++){ 124 | cur_topic = &mosq->bridge->topics[i]; 125 | if(cur_topic->remote_prefix || cur_topic->local_prefix){ 126 | /* Topic mapping required on this topic if the message matches */ 127 | 128 | rc = mosquitto_topic_matches_sub(cur_topic->local_topic, topic, &match); 129 | if(rc){ 130 | return rc; 131 | } 132 | if(match){ 133 | mapped_topic = _mosquitto_strdup(topic); 134 | if(!mapped_topic) return MOSQ_ERR_NOMEM; 135 | if(cur_topic->local_prefix){ 136 | /* This prefix needs removing. */ 137 | if(!strncmp(cur_topic->local_prefix, mapped_topic, strlen(cur_topic->local_prefix))){ 138 | topic_temp = _mosquitto_strdup(mapped_topic+strlen(cur_topic->local_prefix)); 139 | _mosquitto_free(mapped_topic); 140 | if(!topic_temp){ 141 | return MOSQ_ERR_NOMEM; 142 | } 143 | mapped_topic = topic_temp; 144 | } 145 | } 146 | 147 | if(cur_topic->remote_prefix){ 148 | /* This prefix needs adding. */ 149 | len = strlen(mapped_topic) + strlen(cur_topic->remote_prefix)+1; 150 | topic_temp = _mosquitto_calloc(len+1, sizeof(char)); 151 | if(!topic_temp){ 152 | _mosquitto_free(mapped_topic); 153 | return MOSQ_ERR_NOMEM; 154 | } 155 | snprintf(topic_temp, len, "%s%s", cur_topic->remote_prefix, mapped_topic); 156 | _mosquitto_free(mapped_topic); 157 | mapped_topic = topic_temp; 158 | } 159 | _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); 160 | g_pub_bytes_sent += payloadlen; 161 | rc = _mosquitto_send_real_publish(mosq, mid, mapped_topic, payloadlen, payload, qos, retain, dup); 162 | _mosquitto_free(mapped_topic); 163 | return rc; 164 | } 165 | } 166 | } 167 | } 168 | #endif 169 | _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); 170 | g_pub_bytes_sent += payloadlen; 171 | #else 172 | _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); 173 | #endif 174 | 175 | return _mosquitto_send_real_publish(mosq, mid, topic, payloadlen, payload, qos, retain, dup); 176 | } 177 | 178 | int _mosquitto_send_pubrec(struct mosquitto *mosq, uint16_t mid) 179 | { 180 | #ifdef WITH_BROKER 181 | if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREC to %s (Mid: %d)", mosq->id, mid); 182 | #else 183 | if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREC (Mid: %d)", mosq->id, mid); 184 | #endif 185 | return _mosquitto_send_command_with_mid(mosq, PUBREC, mid, false); 186 | } 187 | 188 | int _mosquitto_send_pubrel(struct mosquitto *mosq, uint16_t mid, bool dup) 189 | { 190 | #ifdef WITH_BROKER 191 | if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREL to %s (Mid: %d)", mosq->id, mid); 192 | #else 193 | if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREL (Mid: %d)", mosq->id, mid); 194 | #endif 195 | return _mosquitto_send_command_with_mid(mosq, PUBREL|2, mid, dup); 196 | } 197 | 198 | /* For PUBACK, PUBCOMP, PUBREC, and PUBREL */ 199 | int _mosquitto_send_command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup) 200 | { 201 | struct _mosquitto_packet *packet = NULL; 202 | int rc; 203 | 204 | assert(mosq); 205 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet)); 206 | if(!packet) return MOSQ_ERR_NOMEM; 207 | 208 | packet->command = command; 209 | if(dup){ 210 | packet->command |= 8; 211 | } 212 | packet->remaining_length = 2; 213 | rc = _mosquitto_packet_alloc(packet); 214 | if(rc){ 215 | _mosquitto_free(packet); 216 | return rc; 217 | } 218 | 219 | packet->payload[packet->pos+0] = MOSQ_MSB(mid); 220 | packet->payload[packet->pos+1] = MOSQ_LSB(mid); 221 | 222 | return _mosquitto_packet_queue(mosq, packet); 223 | } 224 | 225 | /* For DISCONNECT, PINGREQ and PINGRESP */ 226 | int _mosquitto_send_simple_command(struct mosquitto *mosq, uint8_t command) 227 | { 228 | struct _mosquitto_packet *packet = NULL; 229 | int rc; 230 | 231 | assert(mosq); 232 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet)); 233 | if(!packet) return MOSQ_ERR_NOMEM; 234 | 235 | packet->command = command; 236 | packet->remaining_length = 0; 237 | 238 | rc = _mosquitto_packet_alloc(packet); 239 | if(rc){ 240 | _mosquitto_free(packet); 241 | return rc; 242 | } 243 | 244 | return _mosquitto_packet_queue(mosq, packet); 245 | } 246 | 247 | 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) 248 | { 249 | struct _mosquitto_packet *packet = NULL; 250 | int packetlen; 251 | int rc; 252 | 253 | assert(mosq); 254 | assert(topic); 255 | 256 | packetlen = 2+strlen(topic) + payloadlen; 257 | if(qos > 0) packetlen += 2; /* For message id */ 258 | packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet)); 259 | if(!packet) return MOSQ_ERR_NOMEM; 260 | 261 | packet->mid = mid; 262 | packet->command = PUBLISH | ((dup&0x1)<<3) | (qos<<1) | retain; 263 | packet->remaining_length = packetlen; 264 | rc = _mosquitto_packet_alloc(packet); 265 | if(rc){ 266 | _mosquitto_free(packet); 267 | return rc; 268 | } 269 | /* Variable header (topic string) */ 270 | _mosquitto_write_string(packet, topic, strlen(topic)); 271 | if(qos > 0){ 272 | _mosquitto_write_uint16(packet, mid); 273 | } 274 | 275 | /* Payload */ 276 | if(payloadlen){ 277 | _mosquitto_write_bytes(packet, payload, payloadlen); 278 | } 279 | 280 | return _mosquitto_packet_queue(mosq, packet); 281 | } 282 | -------------------------------------------------------------------------------- /libmosquitto/net_mosq.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009-2012 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #ifndef WIN32 36 | #include 37 | #include 38 | #include 39 | #else 40 | #include 41 | #include 42 | #endif 43 | 44 | #ifdef __FreeBSD__ 45 | # include 46 | #endif 47 | 48 | #ifdef __SYMBIAN32__ 49 | #include 50 | #endif 51 | 52 | #ifdef __QNX__ 53 | #ifndef AI_ADDRCONFIG 54 | #define AI_ADDRCONFIG 0 55 | #endif 56 | #include 57 | #include 58 | #endif 59 | 60 | #ifdef WITH_TLS 61 | #include 62 | #endif 63 | 64 | #ifdef WITH_BROKER 65 | # include 66 | extern uint64_t g_bytes_received; 67 | extern uint64_t g_bytes_sent; 68 | extern unsigned long g_msgs_received; 69 | extern unsigned long g_msgs_sent; 70 | extern unsigned long g_pub_msgs_received; 71 | extern unsigned long g_pub_msgs_sent; 72 | #else 73 | # include 74 | #endif 75 | 76 | #include "logging_mosq.h" 77 | #include 78 | #include 79 | #include 80 | #include 81 | 82 | #ifdef WITH_TLS 83 | static int tls_ex_index_mosq = -1; 84 | #endif 85 | 86 | void _mosquitto_net_init(void) 87 | { 88 | #ifdef WIN32 89 | WSADATA wsaData; 90 | WSAStartup(MAKEWORD(2,2), &wsaData); 91 | #endif 92 | 93 | #ifdef WITH_TLS 94 | SSL_load_error_strings(); 95 | SSL_library_init(); 96 | OpenSSL_add_all_algorithms(); 97 | if(tls_ex_index_mosq == -1){ 98 | tls_ex_index_mosq = SSL_get_ex_new_index(0, "client context", NULL, NULL, NULL); 99 | } 100 | #endif 101 | } 102 | 103 | void _mosquitto_net_cleanup(void) 104 | { 105 | #ifdef WITH_TLS 106 | ERR_free_strings(); 107 | EVP_cleanup(); 108 | #endif 109 | 110 | #ifdef WIN32 111 | WSACleanup(); 112 | #endif 113 | } 114 | 115 | void _mosquitto_packet_cleanup(struct _mosquitto_packet *packet) 116 | { 117 | if(!packet) return; 118 | 119 | /* Free data and reset values */ 120 | packet->command = 0; 121 | packet->have_remaining = 0; 122 | packet->remaining_count = 0; 123 | packet->remaining_mult = 1; 124 | packet->remaining_length = 0; 125 | if(packet->payload) _mosquitto_free(packet->payload); 126 | packet->payload = NULL; 127 | packet->to_process = 0; 128 | packet->pos = 0; 129 | } 130 | 131 | int _mosquitto_packet_queue(struct mosquitto *mosq, struct _mosquitto_packet *packet) 132 | { 133 | struct _mosquitto_packet *tail; 134 | 135 | assert(mosq); 136 | assert(packet); 137 | 138 | packet->pos = 0; 139 | packet->to_process = packet->packet_length; 140 | 141 | packet->next = NULL; 142 | pthread_mutex_lock(&mosq->out_packet_mutex); 143 | if(mosq->out_packet){ 144 | tail = mosq->out_packet; 145 | while(tail->next){ 146 | tail = tail->next; 147 | } 148 | tail->next = packet; 149 | }else{ 150 | mosq->out_packet = packet; 151 | } 152 | pthread_mutex_unlock(&mosq->out_packet_mutex); 153 | #ifdef WITH_BROKER 154 | return _mosquitto_packet_write(mosq); 155 | #else 156 | if(mosq->in_callback == false){ 157 | return _mosquitto_packet_write(mosq); 158 | }else{ 159 | return MOSQ_ERR_SUCCESS; 160 | } 161 | #endif 162 | } 163 | 164 | /* Close a socket associated with a context and set it to -1. 165 | * Returns 1 on failure (context is NULL) 166 | * Returns 0 on success. 167 | */ 168 | int _mosquitto_socket_close(struct mosquitto *mosq) 169 | { 170 | int rc = 0; 171 | 172 | assert(mosq); 173 | #ifdef WITH_TLS 174 | if(mosq->ssl){ 175 | SSL_shutdown(mosq->ssl); 176 | SSL_free(mosq->ssl); 177 | mosq->ssl = NULL; 178 | } 179 | if(mosq->ssl_ctx){ 180 | SSL_CTX_free(mosq->ssl_ctx); 181 | mosq->ssl_ctx = NULL; 182 | } 183 | #endif 184 | 185 | if(mosq->sock != INVALID_SOCKET){ 186 | rc = COMPAT_CLOSE(mosq->sock); 187 | mosq->sock = INVALID_SOCKET; 188 | } 189 | 190 | return rc; 191 | } 192 | 193 | #ifdef WITH_TLS_PSK 194 | static unsigned int psk_client_callback(SSL *ssl, const char *hint, 195 | char *identity, unsigned int max_identity_len, 196 | unsigned char *psk, unsigned int max_psk_len) 197 | { 198 | struct mosquitto *mosq; 199 | int len; 200 | 201 | mosq = SSL_get_ex_data(ssl, tls_ex_index_mosq); 202 | if(!mosq) return 0; 203 | 204 | snprintf(identity, max_identity_len, "%s", mosq->tls_psk_identity); 205 | 206 | len = _mosquitto_hex2bin(mosq->tls_psk, psk, max_psk_len); 207 | if (len < 0) return 0; 208 | return len; 209 | } 210 | #endif 211 | 212 | /* Create a socket and connect it to 'ip' on port 'port'. 213 | * Returns -1 on failure (ip is NULL, socket creation/connection error) 214 | * Returns sock number on success. 215 | */ 216 | int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port) 217 | { 218 | int sock = INVALID_SOCKET; 219 | #ifndef WIN32 220 | int opt; 221 | #endif 222 | struct addrinfo hints; 223 | struct addrinfo *ainfo, *rp; 224 | int s; 225 | #ifdef WIN32 226 | uint32_t val = 1; 227 | #endif 228 | #ifdef WITH_TLS 229 | int ret; 230 | BIO *bio; 231 | #endif 232 | 233 | if(!mosq || !host || !port) return MOSQ_ERR_INVAL; 234 | 235 | memset(&hints, 0, sizeof(struct addrinfo)); 236 | hints.ai_family = PF_UNSPEC; 237 | hints.ai_flags = AI_ADDRCONFIG; 238 | hints.ai_socktype = SOCK_STREAM; 239 | 240 | s = getaddrinfo(host, NULL, &hints, &ainfo); 241 | if(s) return MOSQ_ERR_UNKNOWN; 242 | 243 | for(rp = ainfo; rp != NULL; rp = rp->ai_next){ 244 | sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 245 | if(sock == INVALID_SOCKET) continue; 246 | 247 | if(rp->ai_family == PF_INET){ 248 | ((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port); 249 | }else if(rp->ai_family == PF_INET6){ 250 | ((struct sockaddr_in6 *)rp->ai_addr)->sin6_port = htons(port); 251 | }else{ 252 | continue; 253 | } 254 | if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1){ 255 | break; 256 | } 257 | 258 | #ifdef WIN32 259 | errno = WSAGetLastError(); 260 | #endif 261 | COMPAT_CLOSE(sock); 262 | } 263 | freeaddrinfo(ainfo); 264 | if(!rp){ 265 | return MOSQ_ERR_ERRNO; 266 | } 267 | 268 | /* Set non-blocking */ 269 | #ifndef WIN32 270 | opt = fcntl(sock, F_GETFL, 0); 271 | if(opt == -1 || fcntl(sock, F_SETFL, opt | O_NONBLOCK) == -1){ 272 | #ifdef WITH_TLS 273 | if(mosq->ssl){ 274 | SSL_shutdown(mosq->ssl); 275 | SSL_free(mosq->ssl); 276 | mosq->ssl = NULL; 277 | } 278 | if(mosq->ssl_ctx){ 279 | SSL_CTX_free(mosq->ssl_ctx); 280 | mosq->ssl_ctx = NULL; 281 | } 282 | #endif 283 | COMPAT_CLOSE(sock); 284 | return MOSQ_ERR_ERRNO; 285 | } 286 | #else 287 | if(ioctlsocket(sock, FIONBIO, &val)){ 288 | errno = WSAGetLastError(); 289 | #ifdef WITH_TLS 290 | if(mosq->ssl){ 291 | SSL_shutdown(mosq->ssl); 292 | SSL_free(mosq->ssl); 293 | mosq->ssl = NULL; 294 | } 295 | if(mosq->ssl_ctx){ 296 | SSL_CTX_free(mosq->ssl_ctx); 297 | mosq->ssl_ctx = NULL; 298 | } 299 | #endif 300 | COMPAT_CLOSE(sock); 301 | return MOSQ_ERR_ERRNO; 302 | } 303 | #endif 304 | 305 | #ifdef WITH_TLS 306 | if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){ 307 | if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1")){ 308 | mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); 309 | if(!mosq->ssl_ctx){ 310 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context."); 311 | COMPAT_CLOSE(sock); 312 | return MOSQ_ERR_TLS; 313 | } 314 | }else{ 315 | COMPAT_CLOSE(sock); 316 | return MOSQ_ERR_INVAL; 317 | } 318 | 319 | #if OPENSSL_VERSION_NUMBER >= 0x10000000 320 | /* Disable compression */ 321 | SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_COMPRESSION); 322 | #endif 323 | #ifdef SSL_MODE_RELEASE_BUFFERS 324 | /* Use even less memory per SSL connection. */ 325 | SSL_CTX_set_mode(mosq->ssl_ctx, SSL_MODE_RELEASE_BUFFERS); 326 | #endif 327 | 328 | if(mosq->tls_ciphers){ 329 | ret = SSL_CTX_set_cipher_list(mosq->ssl_ctx, mosq->tls_ciphers); 330 | if(ret == 0){ 331 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", mosq->tls_ciphers); 332 | COMPAT_CLOSE(sock); 333 | return MOSQ_ERR_TLS; 334 | } 335 | } 336 | if(mosq->tls_cafile || mosq->tls_capath){ 337 | ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath); 338 | if(ret == 0){ 339 | #ifdef WITH_BROKER 340 | if(mosq->tls_cafile && mosq->tls_capath){ 341 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath); 342 | }else if(mosq->tls_cafile){ 343 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile); 344 | }else{ 345 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath); 346 | } 347 | #else 348 | if(mosq->tls_cafile && mosq->tls_capath){ 349 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath); 350 | }else if(mosq->tls_cafile){ 351 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile); 352 | }else{ 353 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath); 354 | } 355 | #endif 356 | COMPAT_CLOSE(sock); 357 | return MOSQ_ERR_TLS; 358 | } 359 | if(mosq->tls_cert_reqs == 0){ 360 | SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_NONE, NULL); 361 | }else{ 362 | SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_PEER, NULL); 363 | } 364 | 365 | if(mosq->tls_pw_callback){ 366 | SSL_CTX_set_default_passwd_cb(mosq->ssl_ctx, mosq->tls_pw_callback); 367 | SSL_CTX_set_default_passwd_cb_userdata(mosq->ssl_ctx, mosq); 368 | } 369 | 370 | if(mosq->tls_certfile){ 371 | ret = SSL_CTX_use_certificate_file(mosq->ssl_ctx, mosq->tls_certfile, SSL_FILETYPE_PEM); 372 | if(ret != 1){ 373 | #ifdef WITH_BROKER 374 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate, check bridge_certfile \"%s\".", mosq->tls_certfile); 375 | #else 376 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate \"%s\".", mosq->tls_certfile); 377 | #endif 378 | COMPAT_CLOSE(sock); 379 | return MOSQ_ERR_TLS; 380 | } 381 | } 382 | if(mosq->tls_keyfile){ 383 | ret = SSL_CTX_use_PrivateKey_file(mosq->ssl_ctx, mosq->tls_keyfile, SSL_FILETYPE_PEM); 384 | if(ret != 1){ 385 | #ifdef WITH_BROKER 386 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file, check bridge_keyfile \"%s\".", mosq->tls_keyfile); 387 | #else 388 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file \"%s\".", mosq->tls_keyfile); 389 | #endif 390 | COMPAT_CLOSE(sock); 391 | return MOSQ_ERR_TLS; 392 | } 393 | ret = SSL_CTX_check_private_key(mosq->ssl_ctx); 394 | if(ret != 1){ 395 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Client certificate/key are inconsistent."); 396 | COMPAT_CLOSE(sock); 397 | return MOSQ_ERR_TLS; 398 | } 399 | } 400 | #ifdef WITH_TLS_PSK 401 | }else if(mosq->tls_psk){ 402 | SSL_CTX_set_psk_client_callback(mosq->ssl_ctx, psk_client_callback); 403 | #endif 404 | } 405 | 406 | mosq->ssl = SSL_new(mosq->ssl_ctx); 407 | if(!mosq->ssl){ 408 | COMPAT_CLOSE(sock); 409 | return MOSQ_ERR_TLS; 410 | } 411 | SSL_set_ex_data(mosq->ssl, tls_ex_index_mosq, mosq); 412 | bio = BIO_new_socket(sock, BIO_NOCLOSE); 413 | if(!bio){ 414 | COMPAT_CLOSE(sock); 415 | return MOSQ_ERR_TLS; 416 | } 417 | SSL_set_bio(mosq->ssl, bio, bio); 418 | 419 | ret = SSL_connect(mosq->ssl); 420 | if(ret != 1){ 421 | ret = SSL_get_error(mosq->ssl, ret); 422 | if(ret == SSL_ERROR_WANT_READ){ 423 | mosq->want_read = true; 424 | }else if(ret == SSL_ERROR_WANT_WRITE){ 425 | mosq->want_write = true; 426 | }else{ 427 | COMPAT_CLOSE(sock); 428 | return MOSQ_ERR_TLS; 429 | } 430 | } 431 | } 432 | #endif 433 | 434 | mosq->sock = sock; 435 | 436 | return MOSQ_ERR_SUCCESS; 437 | } 438 | 439 | int _mosquitto_read_byte(struct _mosquitto_packet *packet, uint8_t *byte) 440 | { 441 | assert(packet); 442 | if(packet->pos+1 > packet->remaining_length) return MOSQ_ERR_PROTOCOL; 443 | 444 | *byte = packet->payload[packet->pos]; 445 | packet->pos++; 446 | 447 | return MOSQ_ERR_SUCCESS; 448 | } 449 | 450 | void _mosquitto_write_byte(struct _mosquitto_packet *packet, uint8_t byte) 451 | { 452 | assert(packet); 453 | assert(packet->pos+1 <= packet->packet_length); 454 | 455 | packet->payload[packet->pos] = byte; 456 | packet->pos++; 457 | } 458 | 459 | int _mosquitto_read_bytes(struct _mosquitto_packet *packet, void *bytes, uint32_t count) 460 | { 461 | assert(packet); 462 | if(packet->pos+count > packet->remaining_length) return MOSQ_ERR_PROTOCOL; 463 | 464 | memcpy(bytes, &(packet->payload[packet->pos]), count); 465 | packet->pos += count; 466 | 467 | return MOSQ_ERR_SUCCESS; 468 | } 469 | 470 | void _mosquitto_write_bytes(struct _mosquitto_packet *packet, const void *bytes, uint32_t count) 471 | { 472 | assert(packet); 473 | assert(packet->pos+count <= packet->packet_length); 474 | 475 | memcpy(&(packet->payload[packet->pos]), bytes, count); 476 | packet->pos += count; 477 | } 478 | 479 | int _mosquitto_read_string(struct _mosquitto_packet *packet, char **str) 480 | { 481 | uint16_t len; 482 | int rc; 483 | 484 | assert(packet); 485 | rc = _mosquitto_read_uint16(packet, &len); 486 | if(rc) return rc; 487 | 488 | if(packet->pos+len > packet->remaining_length) return MOSQ_ERR_PROTOCOL; 489 | 490 | *str = _mosquitto_calloc(len+1, sizeof(char)); 491 | if(*str){ 492 | memcpy(*str, &(packet->payload[packet->pos]), len); 493 | packet->pos += len; 494 | }else{ 495 | return MOSQ_ERR_NOMEM; 496 | } 497 | 498 | return MOSQ_ERR_SUCCESS; 499 | } 500 | 501 | void _mosquitto_write_string(struct _mosquitto_packet *packet, const char *str, uint16_t length) 502 | { 503 | assert(packet); 504 | _mosquitto_write_uint16(packet, length); 505 | _mosquitto_write_bytes(packet, str, length); 506 | } 507 | 508 | int _mosquitto_read_uint16(struct _mosquitto_packet *packet, uint16_t *word) 509 | { 510 | uint8_t msb, lsb; 511 | 512 | assert(packet); 513 | if(packet->pos+2 > packet->remaining_length) return MOSQ_ERR_PROTOCOL; 514 | 515 | msb = packet->payload[packet->pos]; 516 | packet->pos++; 517 | lsb = packet->payload[packet->pos]; 518 | packet->pos++; 519 | 520 | *word = (msb<<8) + lsb; 521 | 522 | return MOSQ_ERR_SUCCESS; 523 | } 524 | 525 | void _mosquitto_write_uint16(struct _mosquitto_packet *packet, uint16_t word) 526 | { 527 | _mosquitto_write_byte(packet, MOSQ_MSB(word)); 528 | _mosquitto_write_byte(packet, MOSQ_LSB(word)); 529 | } 530 | 531 | ssize_t _mosquitto_net_read(struct mosquitto *mosq, void *buf, size_t count) 532 | { 533 | #ifdef WITH_TLS 534 | int ret; 535 | int err; 536 | char ebuf[256]; 537 | unsigned long e; 538 | #endif 539 | assert(mosq); 540 | errno = 0; 541 | #ifdef WITH_TLS 542 | if(mosq->ssl){ 543 | ret = SSL_read(mosq->ssl, buf, count); 544 | if(ret <= 0){ 545 | err = SSL_get_error(mosq->ssl, ret); 546 | if(err == SSL_ERROR_WANT_READ){ 547 | ret = -1; 548 | mosq->want_read = true; 549 | errno = EAGAIN; 550 | }else if(err == SSL_ERROR_WANT_WRITE){ 551 | ret = -1; 552 | mosq->want_write = true; 553 | errno = EAGAIN; 554 | }else{ 555 | e = ERR_get_error(); 556 | while(e){ 557 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "OpenSSL Error: %s", ERR_error_string(e, ebuf)); 558 | e = ERR_get_error(); 559 | } 560 | errno = EPROTO; 561 | } 562 | } 563 | return (ssize_t )ret; 564 | }else{ 565 | /* Call normal read/recv */ 566 | 567 | #endif 568 | 569 | #ifndef WIN32 570 | return read(mosq->sock, buf, count); 571 | #else 572 | return recv(mosq->sock, buf, count, 0); 573 | #endif 574 | 575 | #ifdef WITH_TLS 576 | } 577 | #endif 578 | } 579 | 580 | ssize_t _mosquitto_net_write(struct mosquitto *mosq, void *buf, size_t count) 581 | { 582 | #ifdef WITH_TLS 583 | int ret; 584 | int err; 585 | char ebuf[256]; 586 | unsigned long e; 587 | #endif 588 | assert(mosq); 589 | 590 | errno = 0; 591 | #ifdef WITH_TLS 592 | if(mosq->ssl){ 593 | ret = SSL_write(mosq->ssl, buf, count); 594 | if(ret < 0){ 595 | err = SSL_get_error(mosq->ssl, ret); 596 | if(err == SSL_ERROR_WANT_READ){ 597 | ret = -1; 598 | mosq->want_read = true; 599 | errno = EAGAIN; 600 | }else if(err == SSL_ERROR_WANT_WRITE){ 601 | ret = -1; 602 | mosq->want_write = true; 603 | errno = EAGAIN; 604 | }else{ 605 | e = ERR_get_error(); 606 | while(e){ 607 | _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "OpenSSL Error: %s", ERR_error_string(e, ebuf)); 608 | e = ERR_get_error(); 609 | } 610 | errno = EPROTO; 611 | } 612 | } 613 | return (ssize_t )ret; 614 | }else{ 615 | /* Call normal write/send */ 616 | #endif 617 | 618 | #ifndef WIN32 619 | return write(mosq->sock, buf, count); 620 | #else 621 | return send(mosq->sock, buf, count, 0); 622 | #endif 623 | 624 | #ifdef WITH_TLS 625 | } 626 | #endif 627 | } 628 | 629 | int _mosquitto_packet_write(struct mosquitto *mosq) 630 | { 631 | ssize_t write_length; 632 | struct _mosquitto_packet *packet; 633 | 634 | if(!mosq) return MOSQ_ERR_INVAL; 635 | if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; 636 | 637 | pthread_mutex_lock(&mosq->current_out_packet_mutex); 638 | pthread_mutex_lock(&mosq->out_packet_mutex); 639 | if(mosq->out_packet && !mosq->current_out_packet){ 640 | mosq->current_out_packet = mosq->out_packet; 641 | mosq->out_packet = mosq->out_packet->next; 642 | } 643 | pthread_mutex_unlock(&mosq->out_packet_mutex); 644 | 645 | while(mosq->current_out_packet){ 646 | packet = mosq->current_out_packet; 647 | 648 | while(packet->to_process > 0){ 649 | write_length = _mosquitto_net_write(mosq, &(packet->payload[packet->pos]), packet->to_process); 650 | if(write_length > 0){ 651 | #ifdef WITH_BROKER 652 | g_bytes_sent += write_length; 653 | #endif 654 | packet->to_process -= write_length; 655 | packet->pos += write_length; 656 | }else{ 657 | #ifdef WIN32 658 | errno = WSAGetLastError(); 659 | #endif 660 | if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ 661 | pthread_mutex_unlock(&mosq->current_out_packet_mutex); 662 | return MOSQ_ERR_SUCCESS; 663 | }else{ 664 | pthread_mutex_unlock(&mosq->current_out_packet_mutex); 665 | switch(errno){ 666 | case COMPAT_ECONNRESET: 667 | return MOSQ_ERR_CONN_LOST; 668 | default: 669 | return MOSQ_ERR_ERRNO; 670 | } 671 | } 672 | } 673 | } 674 | 675 | #ifdef WITH_BROKER 676 | g_msgs_sent++; 677 | if(((packet->command)&0xF6) == PUBLISH){ 678 | g_pub_msgs_sent++; 679 | } 680 | #else 681 | if(((packet->command)&0xF6) == PUBLISH){ 682 | pthread_mutex_lock(&mosq->callback_mutex); 683 | if(mosq->on_publish){ 684 | /* This is a QoS=0 message */ 685 | mosq->in_callback = true; 686 | mosq->on_publish(mosq, mosq->userdata, packet->mid); 687 | mosq->in_callback = false; 688 | } 689 | pthread_mutex_unlock(&mosq->callback_mutex); 690 | } 691 | #endif 692 | 693 | /* Free data and reset values */ 694 | pthread_mutex_lock(&mosq->out_packet_mutex); 695 | mosq->current_out_packet = mosq->out_packet; 696 | if(mosq->out_packet){ 697 | mosq->out_packet = mosq->out_packet->next; 698 | } 699 | pthread_mutex_unlock(&mosq->out_packet_mutex); 700 | 701 | _mosquitto_packet_cleanup(packet); 702 | _mosquitto_free(packet); 703 | 704 | pthread_mutex_lock(&mosq->msgtime_mutex); 705 | mosq->last_msg_out = time(NULL); 706 | pthread_mutex_unlock(&mosq->msgtime_mutex); 707 | } 708 | pthread_mutex_unlock(&mosq->current_out_packet_mutex); 709 | return MOSQ_ERR_SUCCESS; 710 | } 711 | 712 | #ifdef WITH_BROKER 713 | int _mosquitto_packet_read(struct mosquitto_db *db, struct mosquitto *mosq) 714 | #else 715 | int _mosquitto_packet_read(struct mosquitto *mosq) 716 | #endif 717 | { 718 | uint8_t byte; 719 | ssize_t read_length; 720 | int rc = 0; 721 | 722 | if(!mosq) return MOSQ_ERR_INVAL; 723 | if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; 724 | /* This gets called if pselect() indicates that there is network data 725 | * available - ie. at least one byte. What we do depends on what data we 726 | * already have. 727 | * If we've not got a command, attempt to read one and save it. This should 728 | * always work because it's only a single byte. 729 | * Then try to read the remaining length. This may fail because it is may 730 | * be more than one byte - will need to save data pending next read if it 731 | * does fail. 732 | * Then try to read the remaining payload, where 'payload' here means the 733 | * combined variable header and actual payload. This is the most likely to 734 | * fail due to longer length, so save current data and current position. 735 | * After all data is read, send to _mosquitto_handle_packet() to deal with. 736 | * Finally, free the memory and reset everything to starting conditions. 737 | */ 738 | if(!mosq->in_packet.command){ 739 | read_length = _mosquitto_net_read(mosq, &byte, 1); 740 | if(read_length == 1){ 741 | mosq->in_packet.command = byte; 742 | #ifdef WITH_BROKER 743 | g_bytes_received++; 744 | /* Clients must send CONNECT as their first command. */ 745 | if(!(mosq->bridge) && mosq->state == mosq_cs_new && (byte&0xF0) != CONNECT) return MOSQ_ERR_PROTOCOL; 746 | #endif 747 | }else{ 748 | if(read_length == 0) return MOSQ_ERR_CONN_LOST; /* EOF */ 749 | #ifdef WIN32 750 | errno = WSAGetLastError(); 751 | #endif 752 | if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ 753 | return MOSQ_ERR_SUCCESS; 754 | }else{ 755 | switch(errno){ 756 | case COMPAT_ECONNRESET: 757 | return MOSQ_ERR_CONN_LOST; 758 | default: 759 | return MOSQ_ERR_ERRNO; 760 | } 761 | } 762 | } 763 | } 764 | if(!mosq->in_packet.have_remaining){ 765 | /* Read remaining 766 | * Algorithm for decoding taken from pseudo code at 767 | * http://publib.boulder.ibm.com/infocenter/wmbhelp/v6r0m0/topic/com.ibm.etools.mft.doc/ac10870_.htm 768 | */ 769 | do{ 770 | read_length = _mosquitto_net_read(mosq, &byte, 1); 771 | if(read_length == 1){ 772 | mosq->in_packet.remaining_count++; 773 | /* Max 4 bytes length for remaining length as defined by protocol. 774 | * Anything more likely means a broken/malicious client. 775 | */ 776 | if(mosq->in_packet.remaining_count > 4) return MOSQ_ERR_PROTOCOL; 777 | 778 | #ifdef WITH_BROKER 779 | g_bytes_received++; 780 | #endif 781 | mosq->in_packet.remaining_length += (byte & 127) * mosq->in_packet.remaining_mult; 782 | mosq->in_packet.remaining_mult *= 128; 783 | }else{ 784 | if(read_length == 0) return MOSQ_ERR_CONN_LOST; /* EOF */ 785 | #ifdef WIN32 786 | errno = WSAGetLastError(); 787 | #endif 788 | if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ 789 | return MOSQ_ERR_SUCCESS; 790 | }else{ 791 | switch(errno){ 792 | case COMPAT_ECONNRESET: 793 | return MOSQ_ERR_CONN_LOST; 794 | default: 795 | return MOSQ_ERR_ERRNO; 796 | } 797 | } 798 | } 799 | }while((byte & 128) != 0); 800 | 801 | if(mosq->in_packet.remaining_length > 0){ 802 | mosq->in_packet.payload = _mosquitto_malloc(mosq->in_packet.remaining_length*sizeof(uint8_t)); 803 | if(!mosq->in_packet.payload) return MOSQ_ERR_NOMEM; 804 | mosq->in_packet.to_process = mosq->in_packet.remaining_length; 805 | } 806 | mosq->in_packet.have_remaining = 1; 807 | } 808 | while(mosq->in_packet.to_process>0){ 809 | read_length = _mosquitto_net_read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process); 810 | if(read_length > 0){ 811 | #ifdef WITH_BROKER 812 | g_bytes_received += read_length; 813 | #endif 814 | mosq->in_packet.to_process -= read_length; 815 | mosq->in_packet.pos += read_length; 816 | }else{ 817 | #ifdef WIN32 818 | errno = WSAGetLastError(); 819 | #endif 820 | if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ 821 | return MOSQ_ERR_SUCCESS; 822 | }else{ 823 | switch(errno){ 824 | case COMPAT_ECONNRESET: 825 | return MOSQ_ERR_CONN_LOST; 826 | default: 827 | return MOSQ_ERR_ERRNO; 828 | } 829 | } 830 | } 831 | } 832 | 833 | /* All data for this packet is read. */ 834 | mosq->in_packet.pos = 0; 835 | #ifdef WITH_BROKER 836 | g_msgs_received++; 837 | if(((mosq->in_packet.command)&0xF5) == PUBLISH){ 838 | g_pub_msgs_received++; 839 | } 840 | rc = mqtt3_packet_handle(db, mosq); 841 | #else 842 | rc = _mosquitto_packet_handle(mosq); 843 | #endif 844 | 845 | /* Free data and reset values */ 846 | _mosquitto_packet_cleanup(&mosq->in_packet); 847 | 848 | pthread_mutex_lock(&mosq->msgtime_mutex); 849 | mosq->last_msg_in = time(NULL); 850 | pthread_mutex_unlock(&mosq->msgtime_mutex); 851 | return rc; 852 | } 853 | 854 | -------------------------------------------------------------------------------- /HomeWatch.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | EB030DC61734DE4E00EDFADA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB030DC51734DE4E00EDFADA /* UIKit.framework */; }; 11 | EB030DC81734DE4E00EDFADA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB030DC71734DE4E00EDFADA /* Foundation.framework */; }; 12 | EB030DCA1734DE4E00EDFADA /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB030DC91734DE4E00EDFADA /* CoreGraphics.framework */; }; 13 | EB030DD01734DE4E00EDFADA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EB030DCE1734DE4E00EDFADA /* InfoPlist.strings */; }; 14 | EB030DD21734DE4E00EDFADA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EB030DD11734DE4E00EDFADA /* main.m */; }; 15 | EB030DD61734DE4E00EDFADA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EB030DD51734DE4E00EDFADA /* AppDelegate.m */; }; 16 | EB030DD81734DE4E00EDFADA /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = EB030DD71734DE4E00EDFADA /* Default.png */; }; 17 | EB030DDA1734DE4E00EDFADA /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EB030DD91734DE4E00EDFADA /* Default@2x.png */; }; 18 | EB030DDC1734DE4E00EDFADA /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EB030DDB1734DE4E00EDFADA /* Default-568h@2x.png */; }; 19 | EB030DDF1734DE4E00EDFADA /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EB030DDE1734DE4E00EDFADA /* ViewController.m */; }; 20 | EB030DE21734DE4E00EDFADA /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = EB030DE01734DE4E00EDFADA /* ViewController.xib */; }; 21 | EB030E2E1734DFC800EDFADA /* logging_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E161734DFC800EDFADA /* logging_mosq.c */; }; 22 | EB030E2F1734DFC800EDFADA /* memory_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E181734DFC800EDFADA /* memory_mosq.c */; }; 23 | EB030E301734DFC800EDFADA /* messages_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E1A1734DFC800EDFADA /* messages_mosq.c */; }; 24 | EB030E311734DFC800EDFADA /* mosquitto.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E1C1734DFC800EDFADA /* mosquitto.c */; }; 25 | EB030E321734DFC800EDFADA /* net_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E201734DFC800EDFADA /* net_mosq.c */; }; 26 | EB030E331734DFC800EDFADA /* read_handle.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E221734DFC800EDFADA /* read_handle.c */; }; 27 | EB030E341734DFC800EDFADA /* read_handle_client.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E241734DFC800EDFADA /* read_handle_client.c */; }; 28 | EB030E351734DFC800EDFADA /* read_handle_shared.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E251734DFC800EDFADA /* read_handle_shared.c */; }; 29 | EB030E361734DFC800EDFADA /* send_client_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E261734DFC800EDFADA /* send_client_mosq.c */; }; 30 | EB030E371734DFC800EDFADA /* send_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E271734DFC800EDFADA /* send_mosq.c */; }; 31 | EB030E381734DFC800EDFADA /* thread_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E291734DFC800EDFADA /* thread_mosq.c */; }; 32 | EB030E391734DFC800EDFADA /* util_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E2A1734DFC800EDFADA /* util_mosq.c */; }; 33 | EB030E3A1734DFC800EDFADA /* will_mosq.c in Sources */ = {isa = PBXBuildFile; fileRef = EB030E2C1734DFC800EDFADA /* will_mosq.c */; }; 34 | EB030E401734E04D00EDFADA /* MosquittoClient.m in Sources */ = {isa = PBXBuildFile; fileRef = EB030E3D1734E04D00EDFADA /* MosquittoClient.m */; }; 35 | EB030E411734E04D00EDFADA /* MosquittoMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = EB030E3F1734E04D00EDFADA /* MosquittoMessage.m */; }; 36 | EB030E441735F5BE00EDFADA /* Sensor.m in Sources */ = {isa = PBXBuildFile; fileRef = EB030E431735F5BE00EDFADA /* Sensor.m */; }; 37 | EBAC0E33175095F300A0B864 /* lite-green.png in Resources */ = {isa = PBXBuildFile; fileRef = EBAC0E2D175095F300A0B864 /* lite-green.png */; }; 38 | EBAC0E34175095F300A0B864 /* lite-green@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EBAC0E2E175095F300A0B864 /* lite-green@2x.png */; }; 39 | EBAC0E35175095F300A0B864 /* lite-off.png in Resources */ = {isa = PBXBuildFile; fileRef = EBAC0E2F175095F300A0B864 /* lite-off.png */; }; 40 | EBAC0E36175095F300A0B864 /* lite-off@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EBAC0E30175095F300A0B864 /* lite-off@2x.png */; }; 41 | EBAC0E37175095F300A0B864 /* lite-red.png in Resources */ = {isa = PBXBuildFile; fileRef = EBAC0E31175095F300A0B864 /* lite-red.png */; }; 42 | EBAC0E38175095F300A0B864 /* lite-red@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EBAC0E32175095F300A0B864 /* lite-red@2x.png */; }; 43 | EBE0003C173C0C82004BE1AF /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE0003B173C0C82004BE1AF /* AudioToolbox.framework */; }; 44 | EBE0003E173C0C8B004BE1AF /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE0003D173C0C8B004BE1AF /* CFNetwork.framework */; }; 45 | EBE00040173C0C98004BE1AF /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE0003F173C0C98004BE1AF /* CoreLocation.framework */; }; 46 | EBE00042173C0CA4004BE1AF /* libz.1.1.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE00041173C0CA4004BE1AF /* libz.1.1.3.dylib */; }; 47 | EBE00044173C0CAB004BE1AF /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE00043173C0CAB004BE1AF /* MobileCoreServices.framework */; }; 48 | EBE00046173C0CB6004BE1AF /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE00045173C0CB6004BE1AF /* QuartzCore.framework */; }; 49 | EBE00048173C0CBC004BE1AF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE00047173C0CBC004BE1AF /* Security.framework */; }; 50 | EBE0004C173C0CC9004BE1AF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE0004B173C0CC9004BE1AF /* SystemConfiguration.framework */; }; 51 | /* End PBXBuildFile section */ 52 | 53 | /* Begin PBXFileReference section */ 54 | EB030DC21734DE4E00EDFADA /* HomeWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HomeWatch.app; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | EB030DC51734DE4E00EDFADA /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 56 | EB030DC71734DE4E00EDFADA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 57 | EB030DC91734DE4E00EDFADA /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 58 | EB030DCD1734DE4E00EDFADA /* HomeWatch-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HomeWatch-Info.plist"; sourceTree = ""; }; 59 | EB030DCF1734DE4E00EDFADA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 60 | EB030DD11734DE4E00EDFADA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 61 | EB030DD31734DE4E00EDFADA /* HomeWatch-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HomeWatch-Prefix.pch"; sourceTree = ""; }; 62 | EB030DD41734DE4E00EDFADA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 63 | EB030DD51734DE4E00EDFADA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 64 | EB030DD71734DE4E00EDFADA /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 65 | EB030DD91734DE4E00EDFADA /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 66 | EB030DDB1734DE4E00EDFADA /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 67 | EB030DDD1734DE4E00EDFADA /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 68 | EB030DDE1734DE4E00EDFADA /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 69 | EB030DE11734DE4E00EDFADA /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController.xib; sourceTree = ""; }; 70 | EB030E141734DFC800EDFADA /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; 71 | EB030E151734DFC800EDFADA /* dummypthread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dummypthread.h; sourceTree = ""; }; 72 | EB030E161734DFC800EDFADA /* logging_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = logging_mosq.c; sourceTree = ""; }; 73 | EB030E171734DFC800EDFADA /* logging_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logging_mosq.h; sourceTree = ""; }; 74 | EB030E181734DFC800EDFADA /* memory_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = memory_mosq.c; sourceTree = ""; }; 75 | EB030E191734DFC800EDFADA /* memory_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_mosq.h; sourceTree = ""; }; 76 | EB030E1A1734DFC800EDFADA /* messages_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = messages_mosq.c; sourceTree = ""; }; 77 | EB030E1B1734DFC800EDFADA /* messages_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = messages_mosq.h; sourceTree = ""; }; 78 | EB030E1C1734DFC800EDFADA /* mosquitto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mosquitto.c; sourceTree = ""; }; 79 | EB030E1D1734DFC800EDFADA /* mosquitto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mosquitto.h; sourceTree = ""; }; 80 | EB030E1E1734DFC800EDFADA /* mosquitto_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mosquitto_internal.h; sourceTree = ""; }; 81 | EB030E1F1734DFC800EDFADA /* mqtt3_protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mqtt3_protocol.h; sourceTree = ""; }; 82 | EB030E201734DFC800EDFADA /* net_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = net_mosq.c; sourceTree = ""; }; 83 | EB030E211734DFC800EDFADA /* net_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = net_mosq.h; sourceTree = ""; }; 84 | EB030E221734DFC800EDFADA /* read_handle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = read_handle.c; sourceTree = ""; }; 85 | EB030E231734DFC800EDFADA /* read_handle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = read_handle.h; sourceTree = ""; }; 86 | EB030E241734DFC800EDFADA /* read_handle_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = read_handle_client.c; sourceTree = ""; }; 87 | EB030E251734DFC800EDFADA /* read_handle_shared.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = read_handle_shared.c; sourceTree = ""; }; 88 | EB030E261734DFC800EDFADA /* send_client_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = send_client_mosq.c; sourceTree = ""; }; 89 | EB030E271734DFC800EDFADA /* send_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = send_mosq.c; sourceTree = ""; }; 90 | EB030E281734DFC800EDFADA /* send_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = send_mosq.h; sourceTree = ""; }; 91 | EB030E291734DFC800EDFADA /* thread_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thread_mosq.c; sourceTree = ""; }; 92 | EB030E2A1734DFC800EDFADA /* util_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = util_mosq.c; sourceTree = ""; }; 93 | EB030E2B1734DFC800EDFADA /* util_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util_mosq.h; sourceTree = ""; }; 94 | EB030E2C1734DFC800EDFADA /* will_mosq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = will_mosq.c; sourceTree = ""; }; 95 | EB030E2D1734DFC800EDFADA /* will_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = will_mosq.h; sourceTree = ""; }; 96 | EB030E3C1734E04D00EDFADA /* MosquittoClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MosquittoClient.h; sourceTree = ""; }; 97 | EB030E3D1734E04D00EDFADA /* MosquittoClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MosquittoClient.m; sourceTree = ""; }; 98 | EB030E3E1734E04D00EDFADA /* MosquittoMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MosquittoMessage.h; sourceTree = ""; }; 99 | EB030E3F1734E04D00EDFADA /* MosquittoMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MosquittoMessage.m; sourceTree = ""; }; 100 | EB030E421735F5BE00EDFADA /* Sensor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sensor.h; sourceTree = ""; }; 101 | EB030E431735F5BE00EDFADA /* Sensor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sensor.m; sourceTree = ""; }; 102 | EB5645261751549C004445F7 /* monitor.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = monitor.py; sourceTree = ""; }; 103 | EBAC0E2D175095F300A0B864 /* lite-green.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lite-green.png"; sourceTree = ""; }; 104 | EBAC0E2E175095F300A0B864 /* lite-green@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lite-green@2x.png"; sourceTree = ""; }; 105 | EBAC0E2F175095F300A0B864 /* lite-off.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lite-off.png"; sourceTree = ""; }; 106 | EBAC0E30175095F300A0B864 /* lite-off@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lite-off@2x.png"; sourceTree = ""; }; 107 | EBAC0E31175095F300A0B864 /* lite-red.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lite-red.png"; sourceTree = ""; }; 108 | EBAC0E32175095F300A0B864 /* lite-red@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lite-red@2x.png"; sourceTree = ""; }; 109 | EBE0003B173C0C82004BE1AF /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 110 | EBE0003D173C0C8B004BE1AF /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 111 | EBE0003F173C0C98004BE1AF /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; 112 | EBE00041173C0CA4004BE1AF /* libz.1.1.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.1.3.dylib; path = usr/lib/libz.1.1.3.dylib; sourceTree = SDKROOT; }; 113 | EBE00043173C0CAB004BE1AF /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 114 | EBE00045173C0CB6004BE1AF /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 115 | EBE00047173C0CBC004BE1AF /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 116 | EBE0004B173C0CC9004BE1AF /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 117 | /* End PBXFileReference section */ 118 | 119 | /* Begin PBXFrameworksBuildPhase section */ 120 | EB030DBF1734DE4E00EDFADA /* Frameworks */ = { 121 | isa = PBXFrameworksBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | EBE0004C173C0CC9004BE1AF /* SystemConfiguration.framework in Frameworks */, 125 | EBE00048173C0CBC004BE1AF /* Security.framework in Frameworks */, 126 | EBE00046173C0CB6004BE1AF /* QuartzCore.framework in Frameworks */, 127 | EBE00044173C0CAB004BE1AF /* MobileCoreServices.framework in Frameworks */, 128 | EBE00042173C0CA4004BE1AF /* libz.1.1.3.dylib in Frameworks */, 129 | EBE00040173C0C98004BE1AF /* CoreLocation.framework in Frameworks */, 130 | EBE0003E173C0C8B004BE1AF /* CFNetwork.framework in Frameworks */, 131 | EBE0003C173C0C82004BE1AF /* AudioToolbox.framework in Frameworks */, 132 | EB030DC61734DE4E00EDFADA /* UIKit.framework in Frameworks */, 133 | EB030DC81734DE4E00EDFADA /* Foundation.framework in Frameworks */, 134 | EB030DCA1734DE4E00EDFADA /* CoreGraphics.framework in Frameworks */, 135 | ); 136 | runOnlyForDeploymentPostprocessing = 0; 137 | }; 138 | /* End PBXFrameworksBuildPhase section */ 139 | 140 | /* Begin PBXGroup section */ 141 | EB030DB91734DE4E00EDFADA = { 142 | isa = PBXGroup; 143 | children = ( 144 | EB5645261751549C004445F7 /* monitor.py */, 145 | EB030DCB1734DE4E00EDFADA /* HomeWatch */, 146 | EB030DC41734DE4E00EDFADA /* Frameworks */, 147 | EB030DC31734DE4E00EDFADA /* Products */, 148 | ); 149 | sourceTree = ""; 150 | }; 151 | EB030DC31734DE4E00EDFADA /* Products */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | EB030DC21734DE4E00EDFADA /* HomeWatch.app */, 155 | ); 156 | name = Products; 157 | sourceTree = ""; 158 | }; 159 | EB030DC41734DE4E00EDFADA /* Frameworks */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | EB030DC51734DE4E00EDFADA /* UIKit.framework */, 163 | EB030DC71734DE4E00EDFADA /* Foundation.framework */, 164 | EB030DC91734DE4E00EDFADA /* CoreGraphics.framework */, 165 | EBE0004B173C0CC9004BE1AF /* SystemConfiguration.framework */, 166 | EBE00047173C0CBC004BE1AF /* Security.framework */, 167 | EBE00045173C0CB6004BE1AF /* QuartzCore.framework */, 168 | EBE00043173C0CAB004BE1AF /* MobileCoreServices.framework */, 169 | EBE00041173C0CA4004BE1AF /* libz.1.1.3.dylib */, 170 | EBE0003F173C0C98004BE1AF /* CoreLocation.framework */, 171 | EBE0003D173C0C8B004BE1AF /* CFNetwork.framework */, 172 | EBE0003B173C0C82004BE1AF /* AudioToolbox.framework */, 173 | ); 174 | name = Frameworks; 175 | sourceTree = ""; 176 | }; 177 | EB030DCB1734DE4E00EDFADA /* HomeWatch */ = { 178 | isa = PBXGroup; 179 | children = ( 180 | EB030DD41734DE4E00EDFADA /* AppDelegate.h */, 181 | EB030DD51734DE4E00EDFADA /* AppDelegate.m */, 182 | EB030E421735F5BE00EDFADA /* Sensor.h */, 183 | EB030E431735F5BE00EDFADA /* Sensor.m */, 184 | EB030DDD1734DE4E00EDFADA /* ViewController.h */, 185 | EB030DDE1734DE4E00EDFADA /* ViewController.m */, 186 | EB030DE01734DE4E00EDFADA /* ViewController.xib */, 187 | EB030E3B1734E02C00EDFADA /* Marquette */, 188 | EB030E131734DFC800EDFADA /* libmosquitto */, 189 | EB030DCC1734DE4E00EDFADA /* Supporting Files */, 190 | ); 191 | path = HomeWatch; 192 | sourceTree = ""; 193 | }; 194 | EB030DCC1734DE4E00EDFADA /* Supporting Files */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | EB030DCD1734DE4E00EDFADA /* HomeWatch-Info.plist */, 198 | EB030DCE1734DE4E00EDFADA /* InfoPlist.strings */, 199 | EB030DD11734DE4E00EDFADA /* main.m */, 200 | EB030DD31734DE4E00EDFADA /* HomeWatch-Prefix.pch */, 201 | EB030DD71734DE4E00EDFADA /* Default.png */, 202 | EB030DD91734DE4E00EDFADA /* Default@2x.png */, 203 | EB030DDB1734DE4E00EDFADA /* Default-568h@2x.png */, 204 | EBAC0E2D175095F300A0B864 /* lite-green.png */, 205 | EBAC0E2E175095F300A0B864 /* lite-green@2x.png */, 206 | EBAC0E2F175095F300A0B864 /* lite-off.png */, 207 | EBAC0E30175095F300A0B864 /* lite-off@2x.png */, 208 | EBAC0E31175095F300A0B864 /* lite-red.png */, 209 | EBAC0E32175095F300A0B864 /* lite-red@2x.png */, 210 | ); 211 | name = "Supporting Files"; 212 | sourceTree = ""; 213 | }; 214 | EB030E131734DFC800EDFADA /* libmosquitto */ = { 215 | isa = PBXGroup; 216 | children = ( 217 | EB030E141734DFC800EDFADA /* config.h */, 218 | EB030E151734DFC800EDFADA /* dummypthread.h */, 219 | EB030E161734DFC800EDFADA /* logging_mosq.c */, 220 | EB030E171734DFC800EDFADA /* logging_mosq.h */, 221 | EB030E181734DFC800EDFADA /* memory_mosq.c */, 222 | EB030E191734DFC800EDFADA /* memory_mosq.h */, 223 | EB030E1A1734DFC800EDFADA /* messages_mosq.c */, 224 | EB030E1B1734DFC800EDFADA /* messages_mosq.h */, 225 | EB030E1C1734DFC800EDFADA /* mosquitto.c */, 226 | EB030E1D1734DFC800EDFADA /* mosquitto.h */, 227 | EB030E1E1734DFC800EDFADA /* mosquitto_internal.h */, 228 | EB030E1F1734DFC800EDFADA /* mqtt3_protocol.h */, 229 | EB030E201734DFC800EDFADA /* net_mosq.c */, 230 | EB030E211734DFC800EDFADA /* net_mosq.h */, 231 | EB030E221734DFC800EDFADA /* read_handle.c */, 232 | EB030E231734DFC800EDFADA /* read_handle.h */, 233 | EB030E241734DFC800EDFADA /* read_handle_client.c */, 234 | EB030E251734DFC800EDFADA /* read_handle_shared.c */, 235 | EB030E261734DFC800EDFADA /* send_client_mosq.c */, 236 | EB030E271734DFC800EDFADA /* send_mosq.c */, 237 | EB030E281734DFC800EDFADA /* send_mosq.h */, 238 | EB030E291734DFC800EDFADA /* thread_mosq.c */, 239 | EB030E2A1734DFC800EDFADA /* util_mosq.c */, 240 | EB030E2B1734DFC800EDFADA /* util_mosq.h */, 241 | EB030E2C1734DFC800EDFADA /* will_mosq.c */, 242 | EB030E2D1734DFC800EDFADA /* will_mosq.h */, 243 | ); 244 | path = libmosquitto; 245 | sourceTree = SOURCE_ROOT; 246 | }; 247 | EB030E3B1734E02C00EDFADA /* Marquette */ = { 248 | isa = PBXGroup; 249 | children = ( 250 | EB030E3C1734E04D00EDFADA /* MosquittoClient.h */, 251 | EB030E3D1734E04D00EDFADA /* MosquittoClient.m */, 252 | EB030E3E1734E04D00EDFADA /* MosquittoMessage.h */, 253 | EB030E3F1734E04D00EDFADA /* MosquittoMessage.m */, 254 | ); 255 | name = Marquette; 256 | sourceTree = ""; 257 | }; 258 | /* End PBXGroup section */ 259 | 260 | /* Begin PBXNativeTarget section */ 261 | EB030DC11734DE4E00EDFADA /* HomeWatch */ = { 262 | isa = PBXNativeTarget; 263 | buildConfigurationList = EB030DE81734DE4E00EDFADA /* Build configuration list for PBXNativeTarget "HomeWatch" */; 264 | buildPhases = ( 265 | EB030DBE1734DE4E00EDFADA /* Sources */, 266 | EB030DBF1734DE4E00EDFADA /* Frameworks */, 267 | EB030DC01734DE4E00EDFADA /* Resources */, 268 | ); 269 | buildRules = ( 270 | ); 271 | dependencies = ( 272 | ); 273 | name = HomeWatch; 274 | productName = MonHome; 275 | productReference = EB030DC21734DE4E00EDFADA /* HomeWatch.app */; 276 | productType = "com.apple.product-type.application"; 277 | }; 278 | /* End PBXNativeTarget section */ 279 | 280 | /* Begin PBXProject section */ 281 | EB030DBA1734DE4E00EDFADA /* Project object */ = { 282 | isa = PBXProject; 283 | attributes = { 284 | LastUpgradeCheck = 0460; 285 | ORGANIZATIONNAME = Basuke; 286 | }; 287 | buildConfigurationList = EB030DBD1734DE4E00EDFADA /* Build configuration list for PBXProject "HomeWatch" */; 288 | compatibilityVersion = "Xcode 3.2"; 289 | developmentRegion = English; 290 | hasScannedForEncodings = 0; 291 | knownRegions = ( 292 | en, 293 | ); 294 | mainGroup = EB030DB91734DE4E00EDFADA; 295 | productRefGroup = EB030DC31734DE4E00EDFADA /* Products */; 296 | projectDirPath = ""; 297 | projectRoot = ""; 298 | targets = ( 299 | EB030DC11734DE4E00EDFADA /* HomeWatch */, 300 | ); 301 | }; 302 | /* End PBXProject section */ 303 | 304 | /* Begin PBXResourcesBuildPhase section */ 305 | EB030DC01734DE4E00EDFADA /* Resources */ = { 306 | isa = PBXResourcesBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | EB030DD01734DE4E00EDFADA /* InfoPlist.strings in Resources */, 310 | EB030DD81734DE4E00EDFADA /* Default.png in Resources */, 311 | EB030DDA1734DE4E00EDFADA /* Default@2x.png in Resources */, 312 | EB030DDC1734DE4E00EDFADA /* Default-568h@2x.png in Resources */, 313 | EB030DE21734DE4E00EDFADA /* ViewController.xib in Resources */, 314 | EBAC0E33175095F300A0B864 /* lite-green.png in Resources */, 315 | EBAC0E34175095F300A0B864 /* lite-green@2x.png in Resources */, 316 | EBAC0E35175095F300A0B864 /* lite-off.png in Resources */, 317 | EBAC0E36175095F300A0B864 /* lite-off@2x.png in Resources */, 318 | EBAC0E37175095F300A0B864 /* lite-red.png in Resources */, 319 | EBAC0E38175095F300A0B864 /* lite-red@2x.png in Resources */, 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | }; 323 | /* End PBXResourcesBuildPhase section */ 324 | 325 | /* Begin PBXSourcesBuildPhase section */ 326 | EB030DBE1734DE4E00EDFADA /* Sources */ = { 327 | isa = PBXSourcesBuildPhase; 328 | buildActionMask = 2147483647; 329 | files = ( 330 | EB030DD21734DE4E00EDFADA /* main.m in Sources */, 331 | EB030DD61734DE4E00EDFADA /* AppDelegate.m in Sources */, 332 | EB030DDF1734DE4E00EDFADA /* ViewController.m in Sources */, 333 | EB030E2E1734DFC800EDFADA /* logging_mosq.c in Sources */, 334 | EB030E2F1734DFC800EDFADA /* memory_mosq.c in Sources */, 335 | EB030E301734DFC800EDFADA /* messages_mosq.c in Sources */, 336 | EB030E311734DFC800EDFADA /* mosquitto.c in Sources */, 337 | EB030E321734DFC800EDFADA /* net_mosq.c in Sources */, 338 | EB030E331734DFC800EDFADA /* read_handle.c in Sources */, 339 | EB030E341734DFC800EDFADA /* read_handle_client.c in Sources */, 340 | EB030E351734DFC800EDFADA /* read_handle_shared.c in Sources */, 341 | EB030E361734DFC800EDFADA /* send_client_mosq.c in Sources */, 342 | EB030E371734DFC800EDFADA /* send_mosq.c in Sources */, 343 | EB030E381734DFC800EDFADA /* thread_mosq.c in Sources */, 344 | EB030E391734DFC800EDFADA /* util_mosq.c in Sources */, 345 | EB030E3A1734DFC800EDFADA /* will_mosq.c in Sources */, 346 | EB030E401734E04D00EDFADA /* MosquittoClient.m in Sources */, 347 | EB030E411734E04D00EDFADA /* MosquittoMessage.m in Sources */, 348 | EB030E441735F5BE00EDFADA /* Sensor.m in Sources */, 349 | ); 350 | runOnlyForDeploymentPostprocessing = 0; 351 | }; 352 | /* End PBXSourcesBuildPhase section */ 353 | 354 | /* Begin PBXVariantGroup section */ 355 | EB030DCE1734DE4E00EDFADA /* InfoPlist.strings */ = { 356 | isa = PBXVariantGroup; 357 | children = ( 358 | EB030DCF1734DE4E00EDFADA /* en */, 359 | ); 360 | name = InfoPlist.strings; 361 | sourceTree = ""; 362 | }; 363 | EB030DE01734DE4E00EDFADA /* ViewController.xib */ = { 364 | isa = PBXVariantGroup; 365 | children = ( 366 | EB030DE11734DE4E00EDFADA /* en */, 367 | ); 368 | name = ViewController.xib; 369 | sourceTree = ""; 370 | }; 371 | /* End PBXVariantGroup section */ 372 | 373 | /* Begin XCBuildConfiguration section */ 374 | EB030DE61734DE4E00EDFADA /* Debug */ = { 375 | isa = XCBuildConfiguration; 376 | buildSettings = { 377 | ALWAYS_SEARCH_USER_PATHS = NO; 378 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 379 | CLANG_CXX_LIBRARY = "libc++"; 380 | CLANG_ENABLE_OBJC_ARC = YES; 381 | CLANG_WARN_CONSTANT_CONVERSION = YES; 382 | CLANG_WARN_EMPTY_BODY = YES; 383 | CLANG_WARN_ENUM_CONVERSION = YES; 384 | CLANG_WARN_INT_CONVERSION = YES; 385 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 386 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 387 | COPY_PHASE_STRIP = NO; 388 | GCC_C_LANGUAGE_STANDARD = gnu99; 389 | GCC_DYNAMIC_NO_PIC = NO; 390 | GCC_OPTIMIZATION_LEVEL = 0; 391 | GCC_PREPROCESSOR_DEFINITIONS = ( 392 | "DEBUG=1", 393 | "$(inherited)", 394 | ); 395 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 396 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 397 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 398 | GCC_WARN_UNUSED_VARIABLE = YES; 399 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 400 | ONLY_ACTIVE_ARCH = YES; 401 | SDKROOT = iphoneos; 402 | TARGETED_DEVICE_FAMILY = "1,2"; 403 | }; 404 | name = Debug; 405 | }; 406 | EB030DE71734DE4E00EDFADA /* Release */ = { 407 | isa = XCBuildConfiguration; 408 | buildSettings = { 409 | ALWAYS_SEARCH_USER_PATHS = NO; 410 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 411 | CLANG_CXX_LIBRARY = "libc++"; 412 | CLANG_ENABLE_OBJC_ARC = YES; 413 | CLANG_WARN_CONSTANT_CONVERSION = YES; 414 | CLANG_WARN_EMPTY_BODY = YES; 415 | CLANG_WARN_ENUM_CONVERSION = YES; 416 | CLANG_WARN_INT_CONVERSION = YES; 417 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 418 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 419 | COPY_PHASE_STRIP = YES; 420 | GCC_C_LANGUAGE_STANDARD = gnu99; 421 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 422 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 423 | GCC_WARN_UNUSED_VARIABLE = YES; 424 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 425 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 426 | SDKROOT = iphoneos; 427 | TARGETED_DEVICE_FAMILY = "1,2"; 428 | VALIDATE_PRODUCT = YES; 429 | }; 430 | name = Release; 431 | }; 432 | EB030DE91734DE4E00EDFADA /* Debug */ = { 433 | isa = XCBuildConfiguration; 434 | buildSettings = { 435 | CODE_SIGN_ENTITLEMENTS = ""; 436 | CODE_SIGN_IDENTITY = "iPhone Developer"; 437 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 438 | FRAMEWORK_SEARCH_PATHS = ( 439 | "$(inherited)", 440 | "\"$(SRCROOT)\"", 441 | ); 442 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 443 | GCC_PREFIX_HEADER = "HomeWatch/HomeWatch-Prefix.pch"; 444 | HEADER_SEARCH_PATHS = libmosquitto; 445 | INFOPLIST_FILE = "HomeWatch/HomeWatch-Info.plist"; 446 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 447 | PRODUCT_NAME = "$(TARGET_NAME)"; 448 | PROVISIONING_PROFILE = ""; 449 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 450 | TARGETED_DEVICE_FAMILY = 1; 451 | WRAPPER_EXTENSION = app; 452 | }; 453 | name = Debug; 454 | }; 455 | EB030DEA1734DE4E00EDFADA /* Release */ = { 456 | isa = XCBuildConfiguration; 457 | buildSettings = { 458 | CODE_SIGN_ENTITLEMENTS = ""; 459 | CODE_SIGN_IDENTITY = "iPhone Distribution"; 460 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; 461 | FRAMEWORK_SEARCH_PATHS = ( 462 | "$(inherited)", 463 | "\"$(SRCROOT)\"", 464 | ); 465 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 466 | GCC_PREFIX_HEADER = "HomeWatch/HomeWatch-Prefix.pch"; 467 | HEADER_SEARCH_PATHS = libmosquitto; 468 | INFOPLIST_FILE = "HomeWatch/HomeWatch-Info.plist"; 469 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 470 | PRODUCT_NAME = "$(TARGET_NAME)"; 471 | PROVISIONING_PROFILE = ""; 472 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 473 | TARGETED_DEVICE_FAMILY = 1; 474 | WRAPPER_EXTENSION = app; 475 | }; 476 | name = Release; 477 | }; 478 | /* End XCBuildConfiguration section */ 479 | 480 | /* Begin XCConfigurationList section */ 481 | EB030DBD1734DE4E00EDFADA /* Build configuration list for PBXProject "HomeWatch" */ = { 482 | isa = XCConfigurationList; 483 | buildConfigurations = ( 484 | EB030DE61734DE4E00EDFADA /* Debug */, 485 | EB030DE71734DE4E00EDFADA /* Release */, 486 | ); 487 | defaultConfigurationIsVisible = 0; 488 | defaultConfigurationName = Release; 489 | }; 490 | EB030DE81734DE4E00EDFADA /* Build configuration list for PBXNativeTarget "HomeWatch" */ = { 491 | isa = XCConfigurationList; 492 | buildConfigurations = ( 493 | EB030DE91734DE4E00EDFADA /* Debug */, 494 | EB030DEA1734DE4E00EDFADA /* Release */, 495 | ); 496 | defaultConfigurationIsVisible = 0; 497 | defaultConfigurationName = Release; 498 | }; 499 | /* End XCConfigurationList section */ 500 | }; 501 | rootObject = EB030DBA1734DE4E00EDFADA /* Project object */; 502 | } 503 | -------------------------------------------------------------------------------- /libmosquitto/mosquitto.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010-2012 Roger Light 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of mosquitto nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #ifndef WIN32 36 | #include 37 | #include 38 | #include 39 | #else 40 | #include 41 | #include 42 | typedef int ssize_t; 43 | #endif 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | #if !defined(WIN32) && defined(__SYMBIAN32__) 58 | #define HAVE_PSELECT 59 | #endif 60 | 61 | void _mosquitto_destroy(struct mosquitto *mosq); 62 | 63 | int mosquitto_lib_version(int *major, int *minor, int *revision) 64 | { 65 | if(major) *major = LIBMOSQUITTO_MAJOR; 66 | if(minor) *minor = LIBMOSQUITTO_MINOR; 67 | if(revision) *revision = LIBMOSQUITTO_REVISION; 68 | return LIBMOSQUITTO_VERSION_NUMBER; 69 | } 70 | 71 | int mosquitto_lib_init(void) 72 | { 73 | #ifdef WIN32 74 | srand(GetTickCount()); 75 | #else 76 | struct timeval tv; 77 | 78 | gettimeofday(&tv, NULL); 79 | srand(tv.tv_sec*1000 + tv.tv_usec/1000); 80 | #endif 81 | 82 | _mosquitto_net_init(); 83 | 84 | return MOSQ_ERR_SUCCESS; 85 | } 86 | 87 | int mosquitto_lib_cleanup(void) 88 | { 89 | _mosquitto_net_cleanup(); 90 | 91 | return MOSQ_ERR_SUCCESS; 92 | } 93 | 94 | struct mosquitto *mosquitto_new(const char *id, bool clean_session, void *userdata) 95 | { 96 | struct mosquitto *mosq = NULL; 97 | int rc; 98 | 99 | if(clean_session == false && id == NULL){ 100 | errno = EINVAL; 101 | return NULL; 102 | } 103 | 104 | #ifndef WIN32 105 | signal(SIGPIPE, SIG_IGN); 106 | #endif 107 | 108 | mosq = (struct mosquitto *)_mosquitto_calloc(1, sizeof(struct mosquitto)); 109 | if(mosq){ 110 | mosq->sock = INVALID_SOCKET; 111 | #ifdef WITH_THREADING 112 | mosq->thread_id = pthread_self(); 113 | #endif 114 | rc = mosquitto_reinitialise(mosq, id, clean_session, userdata); 115 | if(rc){ 116 | mosquitto_destroy(mosq); 117 | if(rc == MOSQ_ERR_INVAL){ 118 | errno = EINVAL; 119 | }else if(rc == MOSQ_ERR_NOMEM){ 120 | errno = ENOMEM; 121 | } 122 | return NULL; 123 | } 124 | }else{ 125 | errno = ENOMEM; 126 | } 127 | return mosq; 128 | } 129 | 130 | int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_session, void *userdata) 131 | { 132 | int i; 133 | 134 | if(!mosq) return MOSQ_ERR_INVAL; 135 | 136 | if(clean_session == false && id == NULL){ 137 | return MOSQ_ERR_INVAL; 138 | } 139 | 140 | _mosquitto_destroy(mosq); 141 | memset(mosq, 0, sizeof(struct mosquitto)); 142 | 143 | if(userdata){ 144 | mosq->userdata = userdata; 145 | }else{ 146 | mosq->userdata = mosq; 147 | } 148 | mosq->sock = INVALID_SOCKET; 149 | mosq->keepalive = 60; 150 | mosq->message_retry = 20; 151 | mosq->last_retry_check = 0; 152 | mosq->clean_session = clean_session; 153 | if(id){ 154 | if(strlen(id) == 0){ 155 | return MOSQ_ERR_INVAL; 156 | } 157 | mosq->id = _mosquitto_strdup(id); 158 | }else{ 159 | mosq->id = (char *)_mosquitto_calloc(24, sizeof(char)); 160 | if(!mosq->id){ 161 | return MOSQ_ERR_NOMEM; 162 | } 163 | mosq->id[0] = 'm'; 164 | mosq->id[1] = 'o'; 165 | mosq->id[2] = 's'; 166 | mosq->id[3] = 'q'; 167 | mosq->id[4] = '/'; 168 | 169 | for(i=5; i<23; i++){ 170 | mosq->id[i] = (rand()%73)+48; 171 | } 172 | } 173 | mosq->in_packet.payload = NULL; 174 | _mosquitto_packet_cleanup(&mosq->in_packet); 175 | mosq->out_packet = NULL; 176 | mosq->current_out_packet = NULL; 177 | mosq->last_msg_in = time(NULL); 178 | mosq->last_msg_out = time(NULL); 179 | mosq->ping_t = 0; 180 | mosq->last_mid = 0; 181 | mosq->state = mosq_cs_new; 182 | mosq->messages = NULL; 183 | mosq->will = NULL; 184 | mosq->on_connect = NULL; 185 | mosq->on_publish = NULL; 186 | mosq->on_message = NULL; 187 | mosq->on_subscribe = NULL; 188 | mosq->on_unsubscribe = NULL; 189 | mosq->host = NULL; 190 | mosq->port = 1883; 191 | mosq->in_callback = false; 192 | mosq->queue_len = 0; 193 | #ifdef WITH_TLS 194 | mosq->ssl = NULL; 195 | mosq->tls_cert_reqs = SSL_VERIFY_PEER; 196 | #endif 197 | #ifdef WITH_THREADING 198 | pthread_mutex_init(&mosq->callback_mutex, NULL); 199 | pthread_mutex_init(&mosq->log_callback_mutex, NULL); 200 | pthread_mutex_init(&mosq->state_mutex, NULL); 201 | pthread_mutex_init(&mosq->out_packet_mutex, NULL); 202 | pthread_mutex_init(&mosq->current_out_packet_mutex, NULL); 203 | pthread_mutex_init(&mosq->msgtime_mutex, NULL); 204 | mosq->thread_id = pthread_self(); 205 | #endif 206 | 207 | return MOSQ_ERR_SUCCESS; 208 | } 209 | 210 | int mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain) 211 | { 212 | if(!mosq) return MOSQ_ERR_INVAL; 213 | return _mosquitto_will_set(mosq, topic, payloadlen, payload, qos, retain); 214 | } 215 | 216 | int mosquitto_will_clear(struct mosquitto *mosq) 217 | { 218 | if(!mosq) return MOSQ_ERR_INVAL; 219 | return _mosquitto_will_clear(mosq); 220 | } 221 | 222 | int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password) 223 | { 224 | if(!mosq) return MOSQ_ERR_INVAL; 225 | 226 | if(username){ 227 | mosq->username = _mosquitto_strdup(username); 228 | if(!mosq->username) return MOSQ_ERR_NOMEM; 229 | if(mosq->password){ 230 | _mosquitto_free(mosq->password); 231 | mosq->password = NULL; 232 | } 233 | if(password){ 234 | mosq->password = _mosquitto_strdup(password); 235 | if(!mosq->password){ 236 | _mosquitto_free(mosq->username); 237 | mosq->username = NULL; 238 | return MOSQ_ERR_NOMEM; 239 | } 240 | } 241 | }else{ 242 | if(mosq->username){ 243 | _mosquitto_free(mosq->username); 244 | mosq->username = NULL; 245 | } 246 | if(mosq->password){ 247 | _mosquitto_free(mosq->password); 248 | mosq->password = NULL; 249 | } 250 | } 251 | return MOSQ_ERR_SUCCESS; 252 | } 253 | 254 | 255 | void _mosquitto_destroy(struct mosquitto *mosq) 256 | { 257 | struct _mosquitto_packet *packet; 258 | if(!mosq) return; 259 | 260 | #ifdef WITH_THREADING 261 | if(!pthread_equal(mosq->thread_id, pthread_self())){ 262 | pthread_cancel(mosq->thread_id); 263 | pthread_join(mosq->thread_id, NULL); 264 | } 265 | 266 | if(mosq->id){ 267 | /* If mosq->id is not NULL then the client has already been initialised 268 | * and so the mutexes need destroying. If mosq->id is NULL, the mutexes 269 | * haven't been initialised. */ 270 | pthread_mutex_destroy(&mosq->callback_mutex); 271 | pthread_mutex_destroy(&mosq->log_callback_mutex); 272 | pthread_mutex_destroy(&mosq->state_mutex); 273 | pthread_mutex_destroy(&mosq->out_packet_mutex); 274 | pthread_mutex_destroy(&mosq->current_out_packet_mutex); 275 | pthread_mutex_destroy(&mosq->msgtime_mutex); 276 | } 277 | #endif 278 | if(mosq->sock != INVALID_SOCKET){ 279 | _mosquitto_socket_close(mosq); 280 | } 281 | _mosquitto_message_cleanup_all(mosq); 282 | _mosquitto_will_clear(mosq); 283 | #ifdef WITH_TLS 284 | if(mosq->ssl){ 285 | SSL_free(mosq->ssl); 286 | } 287 | if(mosq->ssl_ctx){ 288 | SSL_CTX_free(mosq->ssl_ctx); 289 | } 290 | if(mosq->tls_cafile) _mosquitto_free(mosq->tls_cafile); 291 | if(mosq->tls_capath) _mosquitto_free(mosq->tls_capath); 292 | if(mosq->tls_certfile) _mosquitto_free(mosq->tls_certfile); 293 | if(mosq->tls_keyfile) _mosquitto_free(mosq->tls_keyfile); 294 | if(mosq->tls_pw_callback) mosq->tls_pw_callback = NULL; 295 | if(mosq->tls_version) _mosquitto_free(mosq->tls_version); 296 | if(mosq->tls_ciphers) _mosquitto_free(mosq->tls_ciphers); 297 | if(mosq->tls_psk) _mosquitto_free(mosq->tls_psk); 298 | if(mosq->tls_psk_identity) _mosquitto_free(mosq->tls_psk_identity); 299 | #endif 300 | 301 | if(mosq->address) _mosquitto_free(mosq->address); 302 | if(mosq->id) _mosquitto_free(mosq->id); 303 | if(mosq->username) _mosquitto_free(mosq->username); 304 | if(mosq->password) _mosquitto_free(mosq->password); 305 | if(mosq->host) _mosquitto_free(mosq->host); 306 | 307 | /* Out packet cleanup */ 308 | if(mosq->out_packet && !mosq->current_out_packet){ 309 | mosq->current_out_packet = mosq->out_packet; 310 | mosq->out_packet = mosq->out_packet->next; 311 | } 312 | while(mosq->current_out_packet){ 313 | packet = mosq->current_out_packet; 314 | /* Free data and reset values */ 315 | mosq->current_out_packet = mosq->out_packet; 316 | if(mosq->out_packet){ 317 | mosq->out_packet = mosq->out_packet->next; 318 | } 319 | 320 | _mosquitto_packet_cleanup(packet); 321 | _mosquitto_free(packet); 322 | } 323 | 324 | _mosquitto_packet_cleanup(&mosq->in_packet); 325 | } 326 | 327 | void mosquitto_destroy(struct mosquitto *mosq) 328 | { 329 | _mosquitto_destroy(mosq); 330 | _mosquitto_free(mosq); 331 | } 332 | 333 | int mosquitto_socket(struct mosquitto *mosq) 334 | { 335 | if(!mosq) return MOSQ_ERR_INVAL; 336 | return mosq->sock; 337 | } 338 | 339 | int mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive) 340 | { 341 | int rc; 342 | rc = mosquitto_connect_async(mosq, host, port, keepalive); 343 | if(rc) return rc; 344 | 345 | return mosquitto_reconnect(mosq); 346 | } 347 | 348 | int mosquitto_connect_async(struct mosquitto *mosq, const char *host, int port, int keepalive) 349 | { 350 | if(!mosq) return MOSQ_ERR_INVAL; 351 | if(!host || port <= 0) return MOSQ_ERR_INVAL; 352 | 353 | if(mosq->host) _mosquitto_free(mosq->host); 354 | mosq->host = _mosquitto_strdup(host); 355 | if(!mosq->host) return MOSQ_ERR_NOMEM; 356 | mosq->port = port; 357 | 358 | mosq->keepalive = keepalive; 359 | pthread_mutex_lock(&mosq->state_mutex); 360 | mosq->state = mosq_cs_connect_async; 361 | pthread_mutex_unlock(&mosq->state_mutex); 362 | 363 | return MOSQ_ERR_SUCCESS; 364 | } 365 | 366 | int mosquitto_reconnect(struct mosquitto *mosq) 367 | { 368 | int rc; 369 | struct _mosquitto_packet *packet; 370 | if(!mosq) return MOSQ_ERR_INVAL; 371 | if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL; 372 | 373 | pthread_mutex_lock(&mosq->state_mutex); 374 | mosq->state = mosq_cs_new; 375 | pthread_mutex_unlock(&mosq->state_mutex); 376 | 377 | pthread_mutex_lock(&mosq->msgtime_mutex); 378 | mosq->last_msg_in = time(NULL); 379 | mosq->last_msg_out = time(NULL); 380 | pthread_mutex_unlock(&mosq->msgtime_mutex); 381 | 382 | mosq->ping_t = 0; 383 | 384 | _mosquitto_packet_cleanup(&mosq->in_packet); 385 | 386 | pthread_mutex_lock(&mosq->current_out_packet_mutex); 387 | pthread_mutex_lock(&mosq->out_packet_mutex); 388 | 389 | if(mosq->out_packet && !mosq->current_out_packet){ 390 | mosq->current_out_packet = mosq->out_packet; 391 | mosq->out_packet = mosq->out_packet->next; 392 | } 393 | 394 | while(mosq->current_out_packet){ 395 | packet = mosq->current_out_packet; 396 | /* Free data and reset values */ 397 | mosq->current_out_packet = mosq->out_packet; 398 | if(mosq->out_packet){ 399 | mosq->out_packet = mosq->out_packet->next; 400 | } 401 | 402 | _mosquitto_packet_cleanup(packet); 403 | _mosquitto_free(packet); 404 | } 405 | pthread_mutex_unlock(&mosq->out_packet_mutex); 406 | pthread_mutex_unlock(&mosq->current_out_packet_mutex); 407 | 408 | _mosquitto_messages_reconnect_reset(mosq); 409 | 410 | rc = _mosquitto_socket_connect(mosq, mosq->host, mosq->port); 411 | if(rc){ 412 | return rc; 413 | } 414 | 415 | return _mosquitto_send_connect(mosq, mosq->keepalive, mosq->clean_session); 416 | } 417 | 418 | int mosquitto_disconnect(struct mosquitto *mosq) 419 | { 420 | if(!mosq) return MOSQ_ERR_INVAL; 421 | if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; 422 | 423 | pthread_mutex_lock(&mosq->state_mutex); 424 | mosq->state = mosq_cs_disconnecting; 425 | pthread_mutex_unlock(&mosq->state_mutex); 426 | 427 | return _mosquitto_send_disconnect(mosq); 428 | } 429 | 430 | int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain) 431 | { 432 | struct mosquitto_message_all *message; 433 | uint16_t local_mid; 434 | 435 | if(!mosq || !topic || qos<0 || qos>2) return MOSQ_ERR_INVAL; 436 | if(strlen(topic) == 0) return MOSQ_ERR_INVAL; 437 | if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE; 438 | 439 | if(_mosquitto_topic_wildcard_len_check(topic) != MOSQ_ERR_SUCCESS){ 440 | return MOSQ_ERR_INVAL; 441 | } 442 | 443 | local_mid = _mosquitto_mid_generate(mosq); 444 | if(mid){ 445 | *mid = local_mid; 446 | } 447 | 448 | if(qos == 0){ 449 | return _mosquitto_send_publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false); 450 | }else{ 451 | message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all)); 452 | if(!message) return MOSQ_ERR_NOMEM; 453 | 454 | message->next = NULL; 455 | message->timestamp = time(NULL); 456 | message->direction = mosq_md_out; 457 | if(qos == 1){ 458 | message->state = mosq_ms_wait_puback; 459 | }else if(qos == 2){ 460 | message->state = mosq_ms_wait_pubrec; 461 | } 462 | message->msg.mid = local_mid; 463 | message->msg.topic = _mosquitto_strdup(topic); 464 | if(!message->msg.topic){ 465 | _mosquitto_message_cleanup(&message); 466 | return MOSQ_ERR_NOMEM; 467 | } 468 | if(payloadlen){ 469 | message->msg.payloadlen = payloadlen; 470 | message->msg.payload = _mosquitto_malloc(payloadlen*sizeof(uint8_t)); 471 | if(!message->msg.payload){ 472 | _mosquitto_message_cleanup(&message); 473 | return MOSQ_ERR_NOMEM; 474 | } 475 | memcpy(message->msg.payload, payload, payloadlen*sizeof(uint8_t)); 476 | }else{ 477 | message->msg.payloadlen = 0; 478 | message->msg.payload = NULL; 479 | } 480 | message->msg.qos = qos; 481 | message->msg.retain = retain; 482 | message->dup = false; 483 | 484 | _mosquitto_message_queue(mosq, message); 485 | return _mosquitto_send_publish(mosq, message->msg.mid, message->msg.topic, message->msg.payloadlen, message->msg.payload, message->msg.qos, message->msg.retain, message->dup); 486 | } 487 | } 488 | 489 | int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int qos) 490 | { 491 | if(!mosq) return MOSQ_ERR_INVAL; 492 | if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; 493 | 494 | return _mosquitto_send_subscribe(mosq, mid, false, sub, qos); 495 | } 496 | 497 | int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const char *sub) 498 | { 499 | if(!mosq) return MOSQ_ERR_INVAL; 500 | if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; 501 | 502 | return _mosquitto_send_unsubscribe(mosq, mid, false, sub); 503 | } 504 | 505 | int mosquitto_tls_set(struct mosquitto *mosq, const char *cafile, const char *capath, const char *certfile, const char *keyfile, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)) 506 | { 507 | #ifdef WITH_TLS 508 | FILE *fptr; 509 | 510 | if(!mosq || (!cafile && !capath) || (certfile && !keyfile) || (!certfile && keyfile)) return MOSQ_ERR_INVAL; 511 | 512 | if(cafile){ 513 | fptr = fopen(cafile, "rt"); 514 | if(fptr){ 515 | fclose(fptr); 516 | }else{ 517 | return MOSQ_ERR_INVAL; 518 | } 519 | mosq->tls_cafile = _mosquitto_strdup(cafile); 520 | 521 | if(!mosq->tls_cafile){ 522 | return MOSQ_ERR_NOMEM; 523 | } 524 | }else if(mosq->tls_cafile){ 525 | _mosquitto_free(mosq->tls_cafile); 526 | mosq->tls_cafile = NULL; 527 | } 528 | 529 | if(capath){ 530 | mosq->tls_capath = _mosquitto_strdup(capath); 531 | if(!mosq->tls_capath){ 532 | return MOSQ_ERR_NOMEM; 533 | } 534 | }else if(mosq->tls_capath){ 535 | _mosquitto_free(mosq->tls_capath); 536 | mosq->tls_capath = NULL; 537 | } 538 | 539 | if(certfile){ 540 | fptr = fopen(certfile, "rt"); 541 | if(fptr){ 542 | fclose(fptr); 543 | }else{ 544 | if(mosq->tls_cafile){ 545 | _mosquitto_free(mosq->tls_cafile); 546 | mosq->tls_cafile = NULL; 547 | } 548 | if(mosq->tls_capath){ 549 | _mosquitto_free(mosq->tls_capath); 550 | mosq->tls_capath = NULL; 551 | } 552 | return MOSQ_ERR_INVAL; 553 | } 554 | mosq->tls_certfile = _mosquitto_strdup(certfile); 555 | if(!mosq->tls_certfile){ 556 | return MOSQ_ERR_NOMEM; 557 | } 558 | }else{ 559 | if(mosq->tls_certfile) _mosquitto_free(mosq->tls_certfile); 560 | mosq->tls_certfile = NULL; 561 | } 562 | 563 | if(keyfile){ 564 | fptr = fopen(keyfile, "rt"); 565 | if(fptr){ 566 | fclose(fptr); 567 | }else{ 568 | if(mosq->tls_cafile){ 569 | _mosquitto_free(mosq->tls_cafile); 570 | mosq->tls_cafile = NULL; 571 | } 572 | if(mosq->tls_capath){ 573 | _mosquitto_free(mosq->tls_capath); 574 | mosq->tls_capath = NULL; 575 | } 576 | if(mosq->tls_certfile){ 577 | _mosquitto_free(mosq->tls_certfile); 578 | mosq->tls_capath = NULL; 579 | } 580 | return MOSQ_ERR_INVAL; 581 | } 582 | mosq->tls_keyfile = _mosquitto_strdup(keyfile); 583 | if(!mosq->tls_keyfile){ 584 | return MOSQ_ERR_NOMEM; 585 | } 586 | }else{ 587 | if(mosq->tls_keyfile) _mosquitto_free(mosq->tls_keyfile); 588 | mosq->tls_keyfile = NULL; 589 | } 590 | 591 | mosq->tls_pw_callback = pw_callback; 592 | 593 | 594 | return MOSQ_ERR_SUCCESS; 595 | #else 596 | return MOSQ_ERR_NOT_SUPPORTED; 597 | 598 | #endif 599 | } 600 | 601 | int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers) 602 | { 603 | #ifdef WITH_TLS 604 | if(!mosq) return MOSQ_ERR_INVAL; 605 | 606 | mosq->tls_cert_reqs = cert_reqs; 607 | if(tls_version){ 608 | if(!strcasecmp(tls_version, "tlsv1")){ 609 | mosq->tls_version = _mosquitto_strdup(tls_version); 610 | if(!mosq->tls_version) return MOSQ_ERR_NOMEM; 611 | }else{ 612 | return MOSQ_ERR_INVAL; 613 | } 614 | }else{ 615 | mosq->tls_version = _mosquitto_strdup("tlsv1"); 616 | if(!mosq->tls_version) return MOSQ_ERR_NOMEM; 617 | } 618 | if(ciphers){ 619 | mosq->tls_ciphers = _mosquitto_strdup(ciphers); 620 | if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM; 621 | }else{ 622 | mosq->tls_ciphers = NULL; 623 | } 624 | 625 | 626 | return MOSQ_ERR_SUCCESS; 627 | #else 628 | return MOSQ_ERR_NOT_SUPPORTED; 629 | 630 | #endif 631 | } 632 | 633 | 634 | int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers) 635 | { 636 | #if defined(WITH_TLS) && defined(WITH_TLS_PSK) 637 | if(!mosq || !psk || !identity) return MOSQ_ERR_INVAL; 638 | 639 | /* Check for hex only digits */ 640 | if(strspn(psk, "0123456789abcdefABCDEF") < strlen(psk)){ 641 | return MOSQ_ERR_INVAL; 642 | } 643 | mosq->tls_psk = _mosquitto_strdup(psk); 644 | if(!mosq->tls_psk) return MOSQ_ERR_NOMEM; 645 | 646 | mosq->tls_psk_identity = _mosquitto_strdup(identity); 647 | if(!mosq->tls_psk_identity){ 648 | _mosquitto_free(mosq->tls_psk); 649 | return MOSQ_ERR_NOMEM; 650 | } 651 | if(ciphers){ 652 | mosq->tls_ciphers = _mosquitto_strdup(ciphers); 653 | if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM; 654 | }else{ 655 | mosq->tls_ciphers = NULL; 656 | } 657 | 658 | return MOSQ_ERR_SUCCESS; 659 | #else 660 | return MOSQ_ERR_NOT_SUPPORTED; 661 | #endif 662 | } 663 | 664 | 665 | int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets) 666 | { 667 | #ifdef HAVE_PSELECT 668 | struct timespec local_timeout; 669 | #else 670 | struct timeval local_timeout; 671 | #endif 672 | fd_set readfds, writefds; 673 | int fdcount; 674 | int rc; 675 | 676 | if(!mosq || max_packets < 1) return MOSQ_ERR_INVAL; 677 | if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; 678 | 679 | FD_ZERO(&readfds); 680 | FD_SET(mosq->sock, &readfds); 681 | FD_ZERO(&writefds); 682 | pthread_mutex_lock(&mosq->out_packet_mutex); 683 | if(mosq->out_packet || mosq->current_out_packet){ 684 | FD_SET(mosq->sock, &writefds); 685 | #ifdef WITH_TLS 686 | }else if(mosq->ssl && mosq->want_write){ 687 | FD_SET(mosq->sock, &writefds); 688 | #endif 689 | } 690 | pthread_mutex_unlock(&mosq->out_packet_mutex); 691 | if(timeout >= 0){ 692 | local_timeout.tv_sec = timeout/1000; 693 | #ifdef HAVE_PSELECT 694 | local_timeout.tv_nsec = (timeout-local_timeout.tv_sec*1000)*1e6; 695 | #else 696 | local_timeout.tv_usec = (timeout-local_timeout.tv_sec*1000)*1000; 697 | #endif 698 | }else{ 699 | local_timeout.tv_sec = 1; 700 | #ifdef HAVE_PSELECT 701 | local_timeout.tv_nsec = 0; 702 | #else 703 | local_timeout.tv_usec = 0; 704 | #endif 705 | } 706 | 707 | #ifdef HAVE_PSELECT 708 | fdcount = pselect(mosq->sock+1, &readfds, &writefds, NULL, &local_timeout, NULL); 709 | #else 710 | fdcount = select(mosq->sock+1, &readfds, &writefds, NULL, &local_timeout); 711 | #endif 712 | if(fdcount == -1){ 713 | #ifdef WIN32 714 | errno = WSAGetLastError(); 715 | #endif 716 | if(errno == EINTR){ 717 | return MOSQ_ERR_SUCCESS; 718 | }else{ 719 | return MOSQ_ERR_ERRNO; 720 | } 721 | }else{ 722 | if(FD_ISSET(mosq->sock, &readfds)){ 723 | rc = mosquitto_loop_read(mosq, max_packets); 724 | if(rc || mosq->sock == INVALID_SOCKET){ 725 | return rc; 726 | } 727 | } 728 | if(FD_ISSET(mosq->sock, &writefds)){ 729 | rc = mosquitto_loop_write(mosq, max_packets); 730 | if(rc || mosq->sock == INVALID_SOCKET){ 731 | return rc; 732 | } 733 | } 734 | } 735 | return mosquitto_loop_misc(mosq); 736 | } 737 | 738 | int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets) 739 | { 740 | int run = 1; 741 | int rc; 742 | 743 | if(!mosq) return MOSQ_ERR_INVAL; 744 | 745 | if(mosq->state == mosq_cs_connect_async){ 746 | mosquitto_reconnect(mosq); 747 | } 748 | 749 | while(run){ 750 | do{ 751 | rc = mosquitto_loop(mosq, timeout, max_packets); 752 | }while(rc == MOSQ_ERR_SUCCESS); 753 | if(errno == EPROTO){ 754 | return rc; 755 | } 756 | if(mosq->state == mosq_cs_disconnecting){ 757 | run = 0; 758 | }else{ 759 | #ifdef WIN32 760 | Sleep(1000); 761 | #else 762 | sleep(1); 763 | #endif 764 | mosquitto_reconnect(mosq); 765 | } 766 | } 767 | return rc; 768 | } 769 | 770 | int mosquitto_loop_misc(struct mosquitto *mosq) 771 | { 772 | time_t now = time(NULL); 773 | int rc; 774 | 775 | if(!mosq) return MOSQ_ERR_INVAL; 776 | if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; 777 | 778 | _mosquitto_check_keepalive(mosq); 779 | if(mosq->last_retry_check+1 < now){ 780 | _mosquitto_message_retry_check(mosq); 781 | mosq->last_retry_check = now; 782 | } 783 | if(mosq->ping_t && now - mosq->ping_t >= mosq->keepalive){ 784 | /* mosq->ping_t != 0 means we are waiting for a pingresp. 785 | * This hasn't happened in the keepalive time so we should disconnect. 786 | */ 787 | _mosquitto_socket_close(mosq); 788 | pthread_mutex_lock(&mosq->state_mutex); 789 | if(mosq->state == mosq_cs_disconnecting){ 790 | rc = MOSQ_ERR_SUCCESS; 791 | }else{ 792 | rc = 1; 793 | } 794 | pthread_mutex_unlock(&mosq->state_mutex); 795 | pthread_mutex_lock(&mosq->callback_mutex); 796 | if(mosq->on_disconnect){ 797 | mosq->in_callback = true; 798 | mosq->on_disconnect(mosq, mosq->userdata, rc); 799 | mosq->in_callback = false; 800 | } 801 | pthread_mutex_unlock(&mosq->callback_mutex); 802 | return MOSQ_ERR_CONN_LOST; 803 | } 804 | return MOSQ_ERR_SUCCESS; 805 | } 806 | 807 | static int _mosquitto_loop_rc_handle(struct mosquitto *mosq, int rc) 808 | { 809 | if(rc){ 810 | _mosquitto_socket_close(mosq); 811 | pthread_mutex_lock(&mosq->state_mutex); 812 | if(mosq->state == mosq_cs_disconnecting){ 813 | rc = MOSQ_ERR_SUCCESS; 814 | } 815 | pthread_mutex_unlock(&mosq->state_mutex); 816 | pthread_mutex_lock(&mosq->callback_mutex); 817 | if(mosq->on_disconnect){ 818 | mosq->in_callback = true; 819 | mosq->on_disconnect(mosq, mosq->userdata, rc); 820 | mosq->in_callback = false; 821 | } 822 | pthread_mutex_unlock(&mosq->callback_mutex); 823 | return rc; 824 | } 825 | return rc; 826 | } 827 | 828 | int mosquitto_loop_read(struct mosquitto *mosq, int max_packets) 829 | { 830 | int rc; 831 | int i; 832 | if(max_packets < 1) return MOSQ_ERR_INVAL; 833 | 834 | max_packets = mosq->queue_len; 835 | if(max_packets < 1) max_packets = 1; 836 | /* Queue len here tells us how many messages are awaiting processing and 837 | * have QoS > 0. We should try to deal with that many in this loop in order 838 | * to keep up. */ 839 | for(i=0; iqueue_len; 855 | if(max_packets < 1) max_packets = 1; 856 | /* Queue len here tells us how many messages are awaiting processing and 857 | * have QoS > 0. We should try to deal with that many in this loop in order 858 | * to keep up. */ 859 | for(i=0; iout_packet){ 871 | return true; 872 | }else{ 873 | return false; 874 | } 875 | } 876 | 877 | void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int)) 878 | { 879 | pthread_mutex_lock(&mosq->callback_mutex); 880 | mosq->on_connect = on_connect; 881 | pthread_mutex_unlock(&mosq->callback_mutex); 882 | } 883 | 884 | void mosquitto_disconnect_callback_set(struct mosquitto *mosq, void (*on_disconnect)(struct mosquitto *, void *, int)) 885 | { 886 | pthread_mutex_lock(&mosq->callback_mutex); 887 | mosq->on_disconnect = on_disconnect; 888 | pthread_mutex_unlock(&mosq->callback_mutex); 889 | } 890 | 891 | void mosquitto_publish_callback_set(struct mosquitto *mosq, void (*on_publish)(struct mosquitto *, void *, int)) 892 | { 893 | pthread_mutex_lock(&mosq->callback_mutex); 894 | mosq->on_publish = on_publish; 895 | pthread_mutex_unlock(&mosq->callback_mutex); 896 | } 897 | 898 | void mosquitto_message_callback_set(struct mosquitto *mosq, void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *)) 899 | { 900 | pthread_mutex_lock(&mosq->callback_mutex); 901 | mosq->on_message = on_message; 902 | pthread_mutex_unlock(&mosq->callback_mutex); 903 | } 904 | 905 | void mosquitto_subscribe_callback_set(struct mosquitto *mosq, void (*on_subscribe)(struct mosquitto *, void *, int, int, const int *)) 906 | { 907 | pthread_mutex_lock(&mosq->callback_mutex); 908 | mosq->on_subscribe = on_subscribe; 909 | pthread_mutex_unlock(&mosq->callback_mutex); 910 | } 911 | 912 | void mosquitto_unsubscribe_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(struct mosquitto *, void *, int)) 913 | { 914 | pthread_mutex_lock(&mosq->callback_mutex); 915 | mosq->on_unsubscribe = on_unsubscribe; 916 | pthread_mutex_unlock(&mosq->callback_mutex); 917 | } 918 | 919 | void mosquitto_log_callback_set(struct mosquitto *mosq, void (*on_log)(struct mosquitto *, void *, int, const char *)) 920 | { 921 | pthread_mutex_lock(&mosq->log_callback_mutex); 922 | mosq->on_log = on_log; 923 | pthread_mutex_unlock(&mosq->log_callback_mutex); 924 | } 925 | 926 | void mosquitto_user_data_set(struct mosquitto *mosq, void *userdata) 927 | { 928 | if(mosq){ 929 | mosq->userdata = userdata; 930 | } 931 | } 932 | 933 | const char *mosquitto_strerror(int mosq_errno) 934 | { 935 | switch(mosq_errno){ 936 | case MOSQ_ERR_SUCCESS: 937 | return "No error."; 938 | case MOSQ_ERR_NOMEM: 939 | return "Out of memory."; 940 | case MOSQ_ERR_PROTOCOL: 941 | return "A network protocol error occurred when communicating with the broker."; 942 | case MOSQ_ERR_INVAL: 943 | return "Invalid function arguments provided."; 944 | case MOSQ_ERR_NO_CONN: 945 | return "The client is not currently connected."; 946 | case MOSQ_ERR_CONN_REFUSED: 947 | return "The connection was refused."; 948 | case MOSQ_ERR_NOT_FOUND: 949 | return "Message not found (internal error)."; 950 | case MOSQ_ERR_CONN_LOST: 951 | return "The connection was lost."; 952 | case MOSQ_ERR_TLS: 953 | return "A TLS error occurred."; 954 | case MOSQ_ERR_PAYLOAD_SIZE: 955 | return "Payload too large."; 956 | case MOSQ_ERR_NOT_SUPPORTED: 957 | return "This feature is not supported."; 958 | case MOSQ_ERR_AUTH: 959 | return "Authorisation failed."; 960 | case MOSQ_ERR_ACL_DENIED: 961 | return "Access denied by ACL."; 962 | case MOSQ_ERR_UNKNOWN: 963 | return "Unknown error."; 964 | case MOSQ_ERR_ERRNO: 965 | return "Error defined by errno."; 966 | default: 967 | return "Unknown error."; 968 | } 969 | } 970 | 971 | const char *mosquitto_connack_string(int connack_code) 972 | { 973 | switch(connack_code){ 974 | case 0: 975 | return "Connection Accepted."; 976 | case 1: 977 | return "Connection Refused: unacceptable protocol version."; 978 | case 2: 979 | return "Connection Refused: identifier rejected."; 980 | case 3: 981 | return "Connection Refused: broker unavailable."; 982 | case 4: 983 | return "Connection Refused: bad user name or password."; 984 | case 5: 985 | return "Connection Refused: not authorised."; 986 | default: 987 | return "Connection Refused: unknown reason."; 988 | } 989 | } 990 | 991 | int mosquitto_sub_topic_tokenise(const char *subtopic, char ***topics, int *count) 992 | { 993 | int len; 994 | int hier_count = 1; 995 | int start, stop; 996 | int hier; 997 | int tlen; 998 | int i, j; 999 | 1000 | if(!subtopic || !topics || !count) return MOSQ_ERR_INVAL; 1001 | 1002 | len = strlen(subtopic); 1003 | 1004 | for(i=0; i= len-1){ 1011 | /* Separator at end of line */ 1012 | }else{ 1013 | hier_count++; 1014 | } 1015 | } 1016 | } 1017 | 1018 | (*topics) = _mosquitto_calloc(hier_count, sizeof(char *)); 1019 | if(!(*topics)) return MOSQ_ERR_NOMEM; 1020 | 1021 | start = 0; 1022 | stop = 0; 1023 | hier = 0; 1024 | 1025 | for(i=0; i0 && subtopic[i] == '/' && subtopic[i-1] == '/'){ 1028 | start = i+1; 1029 | continue; 1030 | } 1031 | stop = i; 1032 | if(start != stop){ 1033 | tlen = stop-start + 1; 1034 | (*topics)[hier] = _mosquitto_calloc(tlen, sizeof(char)); 1035 | if(!(*topics)[hier]){ 1036 | for(i=0; i