1) Cleaned unnecsssary files.
2) Changed plugin manager to support C/C++ and Java Plugin. Java plugin manager is not completed yet.
This commit only have template code for Java.
3) Created plugin manager as a separate library(libpm.a) to be linked by application directly.
And separated plugin manager implementation as shared library(libpmimpl.so) to support out-proc mode with same libpm.a in the future.
Change-Id: I5a80faa0546da1832e15a75dacc7f916faedd868
Signed-off-by: Lee Jun Ho <junho13.lee@samsung.com>
-mkdir release
resource:
- cd $(PROTOCOL_ROOT)../../resource/build/linux && $(MAKE)
+ cd $(PROTOCOL_ROOT)../../resource && $(MAKE)
plugin-manager:
cd $(PROTOCOL_ROOT)plugin-manager/build/linux && $(MAKE)
- cp -Rdp $(PROTOCOL_ROOT)plugin-manager/build/linux/ppm release/
+ cp -Rdp $(PROTOCOL_ROOT)plugin-manager/build/linux/libppm.a release/
+ cp -Rdp $(PROTOCOL_ROOT)plugin-manager/build/linux/libpmimpl.so release/
plugins:
- cd $(PROTOCOL_ROOT)plugins/mqtt/build/linux && $(MAKE)
- cd $(PROTOCOL_ROOT)plugins/hue/build/linux && $(MAKE)
+ cd $(PROTOCOL_ROOT)plugins/mqtt-fan/build/linux && $(MAKE)
+ cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE)
sample-app:
cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE)
clean:
cd $(PROTOCOL_ROOT)plugin-manager/build/linux && $(MAKE) clean
- cd $(PROTOCOL_ROOT)plugins/mqtt/build/linux && $(MAKE) clean
+ cd $(PROTOCOL_ROOT)plugins/mqtt-fan/build/linux && $(MAKE) clean
+ cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE) clean
cd $(PROTOCOL_ROOT)plugins/hue/build/linux && $(MAKE) clean
cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE) clean
rm -rf release
-include ../../../config.mk
-
CXX = g++
CXX_FLAGS = -std=c++0x -Wall
CPLUFF_DIR = ../../../lib/cpluff/libcpluff
-LIB_DIR = ../../../../../resource
-
SRC = ../../src/
-CXX_INC = -I. -I$(CPLUFF_DIR)
-CXX_INC += -I$(BOOST_DIR)
-CXX_INC += -I$(LIB_DIR)/include/
-CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
-CXX_INC += -I$(LIB_DIR)/csdk/ocsocket/include/
-CXX_INC += -I$(LIB_DIR)/csdk/ocrandom/include/
-CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
+CXX_INC = -I. -I$(CPLUFF_DIR)
-LINK_LIB = -ldl -lexpat -lboost_thread -lboost_system
+LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread
+CXX_LIBS = $(CPLUFF_DIR)/.libs/libcpluff.a
-PHONY : ppm
-#PluginLifecycleManager.o
+PHONY :libppm.a libpmimpl.so
all: .PHONY
+
+libppm.a:PluginManager.o Plugin.o
+ ar -cvr libppm.a PluginManager.o Plugin.o
+
+PluginManager.o : $(SRC)PluginManager.cpp
+ $(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManager.cpp
-ppm: PluginManager.o Plugin.o PluginManagerService.o
- $(CXX) $(CXX_INC) -o $@ $^ $(CPLUFF_DIR)/.libs/libcpluff.a $(LIB_DIR)/build/linux/release/obj/liboc.a $(LIB_DIR)/csdk/build/linux/release/liboctbstack.a $(LINK_LIB)
-PluginManagerService.o : $(SRC)PluginManagerService.cpp
- $(CXX) $(CXX_INC) -c -fpermissive $(CXX_FLAGS) $(SRC)PluginManagerService.cpp
+libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CPLUFF_DIR)/.libs/libcpluff.a
+ $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CXX_LIBS) $(LINK_LIB)
-PluginManager.o : $(SRC)PluginManager.cpp
- $(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManager.cpp
+PluginManagerImpl.o : $(SRC)PluginManagerImpl.cpp
+ $(CXX) $(CXX_INC) -fPIC -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManagerImpl.cpp
Plugin.o : $(SRC)Plugin.cpp
- $(CXX) $(CXX_INC) -c $(SRC)Plugin.cpp
+ $(CXX) $(CXX_INC) -fPIC -c $(SRC)Plugin.cpp
+
+CpluffAdapter.o : $(SRC)CpluffAdapter.cpp
+ $(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)CpluffAdapter.cpp
-#PluginLifecycleManager.o : PluginLifecycleManager.cpp
-# $(CXX) $(CXX_INC) -c PluginLifecycleManager.cpp
+FelixAdapter.o : $(SRC)FelixAdapter.cpp
+ $(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)FelixAdapter.cpp
-clean:
+clean:
rm -rf *.o
- rm -f ppm
+ rm -rf *.a
+ rm -rf *.so
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file CpluffAdapter.cpp
+
+/// @brief
+
+#include "CpluffAdapter.h"
+
+using namespace OIC;
+
+CpluffAdapter *CpluffAdapter::s_pinstance;
+
+CpluffAdapter::CpluffAdapter()
+{
+ m_status = cp_init();
+ m_context = cp_create_context(&m_status);
+ m_cp_plugins = nullptr;
+ m_plugin = nullptr;
+ registerAllPlugin("../../../plugins");
+}
+
+CpluffAdapter::~CpluffAdapter(void)
+{
+ cp_release_info(m_context, m_cp_plugins);
+ m_thread_g.interrupt_all();
+ m_thread_g.join_all();
+ s_pinstance->deleteinstance();
+ s_pinstance = nullptr;
+}
+
+int CpluffAdapter::installPlugin(const std::string path)
+{
+ char *argv = const_cast<char *>(path.c_str());
+
+ if ((m_plugin = cp_load_plugin_descriptor(m_context, argv, &m_status)) == nullptr)
+ {
+ printf("cp_load_plugin_descriptor failed\n");
+ return false;
+ }
+ else if ((m_status = cp_install_plugin(m_context, m_plugin)) != 0)
+ {
+ printf("cp_install_plugin failed\n");
+ return false;
+ }
+
+ return true;
+}
+
+int CpluffAdapter::findPluginRecursive(const std::string path)
+{
+ ////////FILELIST////////////
+ File_list file_list;
+ getFileList(file_list, path);
+ File_list::iterator itr;
+ int flag = FALSE;
+
+ for (itr = file_list.begin(); itr != file_list.end(); itr++)
+ {
+ if (itr->second == true)
+ {
+ //printf("[Direcotry] %s\n",itr->first.c_str());
+ }
+ else
+ {
+ //printf("[FILE] = %s\n" , itr->first.c_str());
+ std::string filepath = itr->first.c_str();
+ int count = 0;
+ for (unsigned int i = 0 ; i < filepath.size(); i++)
+ {
+ if (filepath.at(i) == '/')
+ {
+ count = i;
+ }
+ }
+ std::string filename = filepath.substr(0, count );
+ //char *temp_char = const_cast<char *>(filename.c_str());
+ flag = installPlugin(filename);
+ //printf("plugin file path %s \n", plugin->plugin_path);
+ }
+ }
+
+ return flag;
+}
+
+int CpluffAdapter::loadPluginInfoToManager(const std::string path)
+{
+ //get plugins information.
+ if ((m_cp_plugins = cp_get_plugins_info(m_context, &m_status, nullptr)) == nullptr)
+ {
+ printf("cp_get_plugins_infor failed\n");
+ return FALSE;
+ }
+ else
+ {
+ printPluginList(m_cp_plugins);
+ }
+
+ for (int i = 0 ; m_cp_plugins[i] != nullptr; i++)
+ {
+ Plugin *plugin = new Plugin;
+ plugin->setValue("Path", m_cp_plugins[i]->plugin_path);
+ plugin->setValue("Language", "CPP");
+ //printf("add filepath %s\n",m_cp_plugins[i]->plugin_path);
+ if (m_cp_plugins[i]->identifier != nullptr)
+ {
+ plugin->setValue("Id", m_cp_plugins[i]->identifier );
+ }
+ else
+ {
+ plugin->setValue("Id", "");
+ }
+
+ if (m_cp_plugins[i]->url != nullptr)
+ {
+ plugin->setValue("Url", m_cp_plugins[i]->url);
+ }
+ else
+ {
+ plugin->setValue("Url", "");
+ }
+
+ if (m_cp_plugins[i]->name != nullptr)
+ {
+ plugin->setValue("Name", m_cp_plugins[i]->name);
+ }
+ else
+ {
+ plugin->setValue("Name", "");
+ }
+
+ if (m_cp_plugins[i]->resourcetype != nullptr)
+ {
+ plugin->setValue("ResourceType", m_cp_plugins[i]->resourcetype);
+ }
+ else
+ {
+ plugin->setValue("ResourceType", "");
+ }
+
+ if (m_cp_plugins[i]->version != nullptr)
+ {
+ plugin->setValue("Version", m_cp_plugins[i]->version);
+ }
+ else
+ {
+ plugin->setValue("Version", "");
+ }
+
+ bool plugin_compare_flag = true;
+ for (unsigned int i = 0 ; i < m_plugins.size(); i++)
+ {
+ if (*plugin == m_plugins[i])
+ {
+ delete(plugin);
+ plugin_compare_flag = false;
+ break;
+ }
+ }
+ if (plugin_compare_flag)
+ {
+ m_plugins.push_back(*plugin);
+ try
+ {
+ boost::thread *t = new boost::thread(boost::bind(&CpluffAdapter::observePluginPath,
+ //this, (void *)path.c_str()));
+ this, (void *)m_cp_plugins[i]->plugin_path));
+ m_thread_g.add_thread(t);
+ }
+ catch (...)
+ {
+ printf("thread throw exception\n");
+ }
+ delete(plugin);
+ }
+ //printf("plugin size = %d\n",m_plugins.size());
+ }
+
+ return TRUE;
+}
+
+int CpluffAdapter::registerPlugin(const std::string path)
+{
+ //printf("CpluffAdapter register\n");
+ int flag = FALSE;
+
+ if (path == "")
+ {
+ printf("CpluffAdapter path == null\n");
+ return flag;
+ }
+
+ //non recursive
+
+ flag = installPlugin(path);
+
+ flag = loadPluginInfoToManager(path);
+
+ return flag;
+}
+
+int CpluffAdapter::registerAllPlugin(const std::string path)
+{
+ //printf("CpluffAdapter register\n");
+ int flag = FALSE;
+ if (path == "")
+ {
+ printf("CpluffAdapter path == null\n");
+ return flag;
+ }
+
+ //recursive
+
+ flag = findPluginRecursive(path);
+
+ flag = loadPluginInfoToManager(path);
+
+ return flag;
+}
+
+int CpluffAdapter::unregisterPlugin(Plugin *const plugin)
+{
+ cp_status_t status;
+ char *argv = nullptr;
+ std::string id = "";
+
+ for (unsigned int i = 0; i < m_plugins.size(); i++)
+ {
+
+ if (*plugin == m_plugins[i])
+ {
+ id = m_plugins[i].getID().c_str();
+ argv = const_cast<char *>(id.c_str());
+ if ((status = cp_uninstall_plugin(m_context, argv)) != 0)
+ {
+ printf("unregister failed\n");
+ return FALSE;
+ }
+ m_plugins.erase(m_plugins.begin() + i);
+ }
+ }
+ return TRUE;
+}
+
+int CpluffAdapter::unregisterAllPlugin(void)
+{
+ cp_status_t status;
+ char *argv = nullptr;
+ std::string id = "";
+
+ while (true)
+ {
+ id = m_plugins[0].getID().c_str();
+ argv = const_cast<char *>(id.c_str());
+ if ((status = cp_uninstall_plugin(m_context, argv)) != 0)
+ {
+ printf("unregister failed\n");
+ return FALSE;
+ }
+ m_plugins.erase(m_plugins.begin());
+ if (m_plugins.size() == 0)
+ {
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+std::vector<Plugin> &CpluffAdapter::getAllPlugins(void)
+{
+ return m_plugins;
+}
+
+std::vector<Plugin> *CpluffAdapter::findPlugins(const std::string key, const std::string value)
+{
+ std::vector<Plugin> *re_plugins;
+
+ re_plugins = new std::vector<Plugin>;
+
+ for (unsigned int i = 0; i < m_plugins.size(); i++)
+ {
+ if (!m_plugins[i].getValueByAttribute(key).compare(value))
+ {
+ re_plugins->push_back(m_plugins[i]);
+ }
+ }
+
+ return re_plugins;
+}
+/*
+Plugin *CpluffAdapter::getPlugin(const std::string plugID)
+{
+ for (unsigned int i = 0; i < m_plugins.size(); i++)
+ {
+ if (!(m_plugins[i].getID().compare(plugID)))
+ {
+ return &(m_plugins[i]);
+ }
+ }
+
+ return nullptr;
+}
+*/
+bool CpluffAdapter::getFileList(File_list &list, const std::string strDir)
+{
+ struct stat statinfo;
+ memset(&statinfo, 0, sizeof(statinfo));
+ std::string path = strDir;
+ if (0 != lstat(path.c_str(), &statinfo))
+ {
+ printf("OICPlugManager lstat is 0\n");
+ return false;
+ }
+ if (!S_ISDIR(statinfo.st_mode))
+ {
+ printf("%s is not directory", strDir.c_str());
+ return false;
+ }
+
+ DIR *dir;
+ struct dirent *entry;
+
+ if ((dir = opendir(strDir.c_str())) == nullptr)
+ {
+ printf("%s open error", strDir.c_str());
+ return false;
+ }
+
+ while ((entry = readdir(dir)) != nullptr)
+ {
+ memset(&statinfo, 0, sizeof(statinfo));
+ std::string strFilePath = strDir + "/" + entry->d_name;
+ while (strFilePath.find("//") != std::string::npos)
+ strFilePath.replace(strFilePath.find("//"), 2, "/");
+
+ if (0 != lstat(strFilePath.c_str(), &statinfo))
+ {
+ printf("OICPlugManager lstat is 0\n");
+ closedir(dir);
+ return false;
+ }
+
+ if (S_ISDIR(statinfo.st_mode))
+ {
+ if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+ continue;
+
+ list.insert(std::pair<std::string, bool>(strFilePath, true));
+ std::string strSubDir = strDir + "/" + entry->d_name;
+ getFileList(list, strSubDir);
+ }
+ else
+ {
+ int size = strFilePath.size();
+ std::string so = strFilePath.substr(size - 2, size - 1);
+ if (so == "so")
+ {
+ list.insert(std::pair<std::string, bool>(strFilePath, false));
+ }
+ }
+ }
+ closedir(dir);
+
+ return true;
+}
+
+const char *CpluffAdapter::state_to_string(int state)
+{
+ switch (state)
+ {
+ case 0:
+ return "UNINTALLED";
+ case 1:
+ return "INSTALLED";
+ case 2:
+ return "RESOLVED";
+ case 3:
+ return "STARTING";
+ case 4:
+ return "STOPPING";
+ case 5:
+ return "ACTIVE";
+ default:
+ return "Unknown";
+ }
+}
+
+void CpluffAdapter::printPluginList(cp_plugin_info_t **plugins)
+{
+ const char format[] = " %-30s %-15s %-15s %-20s\n";
+ printf("\n====== Plugins List ======\n");
+ printf(format,
+ "ID",
+ "NAME",
+ "STATE",
+ "TYPE");
+
+ for (int i = 0; m_cp_plugins[i] != nullptr; i++)
+ {
+ printf(format,
+ m_cp_plugins[i]->identifier,
+ m_cp_plugins[i]->name != nullptr ? m_cp_plugins[i]->name : "",
+ state_to_string(cp_get_plugin_state(m_context, m_cp_plugins[i]->identifier)),
+ m_cp_plugins[i]->resourcetype != nullptr ? m_cp_plugins[i]->resourcetype : "");
+ }
+ printf("\n");
+}
+
+int CpluffAdapter::start(Plugin *const plugin, void *const arg)
+{
+ //printf("start\n");
+ std::string id;
+ cp_status_t status;
+ cp_context_t *ctx;
+
+ id = plugin->getID();
+ for (unsigned int i = 0 ; i < m_plugins.size(); i++)
+ {
+ if (*plugin == m_plugins[i])
+ {
+ ctx = cpi_new_context((cp_plugin_t *)hnode_get(hash_lookup(m_context->env->plugins, id.c_str())),
+ m_context->env, &status);
+ cp_define_symbol(ctx, "START_ARGUMENT", arg);
+ //printf("start ocplatform address : %x\n", arg);
+
+ if ((status = cp_start_plugin(m_context, (char *)id.c_str()) ) != CP_OK)
+ {
+ printf("API function CpluffAdapter::start() faild with error code.\n");
+ return FALSE;
+ }
+ else
+ {
+ printf("start plug-in %s.\n", (char *)id.c_str());
+ }
+
+ break;
+ }
+ }
+ return TRUE;
+}
+
+int CpluffAdapter::stop(Plugin *const plugin)
+{
+ std::string id;
+ cp_status_t status;
+
+ id = plugin->getID();
+ printf("stop plugin id = %s\n", id.c_str());
+ if ((status = cp_stop_plugin(m_context, (char *)id.c_str())) != CP_OK)
+ {
+ printf("API function CpluffAdapter::stop() faild with error code.\n");
+ return FALSE;
+ }
+ else
+ {
+ printf("Stop plug-in %s.\n", (char *)id.c_str());
+ }
+
+ return TRUE;
+}
+
+bool CpluffAdapter::isStarted(Plugin *plugin)
+{
+ std::string id;
+ cp_plugin_state_t state;
+
+ id = plugin->getID();
+
+ state = cp_get_plugin_state(m_context, (char *)id.c_str());
+ if (state == CP_PLUGIN_STARTING || state == CP_PLUGIN_ACTIVE)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void CpluffAdapter::observePluginPath(void *str)
+{
+ //printf("start observePluginPath\n");
+ int length;
+ int i = 0;
+ int fd;
+ int wd;
+ char *str1 = (char *)str;
+ std::string original_path(str1);
+ //printf("Directory is %s\n",(char*)str1));
+ char buffer[BUF_LEN];
+
+ fd = inotify_init();
+
+ if ( fd < 0 )
+ {
+ printf("inotify_init\n");
+ }
+
+ wd = inotify_add_watch( fd, str1,
+ IN_MODIFY | IN_CREATE | IN_DELETE | IN_DELETE_SELF
+ | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
+
+ while (true)
+ {
+ //printf("read start\n");
+ i = 0;
+ length = read( fd, buffer, BUF_LEN );
+
+ if ( length < 0 )
+ {
+ printf("observePluginPath read\n");
+ }
+ std::string filepath = original_path;
+ //printf("filepath = %s\n",filepath.c_str());
+ while ( i < length )
+ {
+ if (i < (signed)(BUF_LEN - ( sizeof( struct inotify_event) + 16)) && i > -1)
+ {
+ struct inotify_event *event = ( struct inotify_event *) &buffer[ i ];
+
+ if ((event->mask & IN_CREATE) || (event->mask & IN_MODIFY) || (event->mask & IN_MOVED_TO))
+ {
+ registerAllPlugin(str1);
+ }
+ else
+ {
+ //filepath += "/";
+ //filepath += std::string(event->name);
+ std::vector<Plugin> *resource_plugin = findPlugins("Path", filepath.c_str()); //add foldername
+
+ //printf("plugin size is %d\n",resource_plugin->size());
+ //printf("plugin file path is %s\n",resource_plugin->());
+ if (resource_plugin->size() == 1)
+ {
+ unregisterPlugin(&(resource_plugin->at(0)));
+ }
+ else
+ {
+ registerAllPlugin(str1);
+ }
+ delete(resource_plugin);
+ resource_plugin = nullptr;
+ }
+ //printf("observePluginPath path = %s \n",str1);
+ //printf("observePluginPath directory name = %s \n",event->name);
+ i += EVENT_SIZE + event->len;
+ }
+ }
+
+
+ }
+ ( void ) inotify_rm_watch( fd, wd );
+ ( void ) close( fd );
+ //printf("observePluginPath end\n");
+}
+
+const std::string CpluffAdapter::getState(const std::string plugID)
+{
+ return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
+}
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file CpluffAdapter.h
+
+/// @brief
+
+#ifndef __CPLUFFADAPTER_H
+#define __CPLUFFADAPTER_H
+#define DLOPEN_POSIX
+
+#include <vector>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/inotify.h>
+#include <unistd.h>
+#include <boost/thread.hpp>
+#include <boost/bind.hpp>
+#include <internal.h>
+
+#include "Plugin.h"
+
+#define EVENT_SIZE ( sizeof (struct inotify_event) )
+#define BUF_LEN (int)( 1024 * ( EVENT_SIZE + 16 ) )
+
+namespace OIC
+{
+ /**
+ * @brief After installing a plug-in in a directory, each plug-ins can be managed by this class.
+ *
+ *
+ */
+ class CpluffAdapter
+ {
+ public:
+ /**
+ * A function to register pluins in the path.
+ * This function will load plugins in plugin manager table.
+ *
+ * @param path plugin file path to be registered.
+ * @return int, 1 is success, 0 is fail.
+ *
+ * NOTE:
+ *
+ */
+ int registerPlugin(const std::string path);
+
+
+ /**
+ * A function to register pluins in the path.
+ * This function will load plugins in plugin manager table.
+ *
+ * @param path plugin file path to be registered.
+ * recursive load plugins sub folders recursively.
+ * @return int, 1 is success, 0 is fail.
+ *
+ * NOTE:
+ *
+ */
+ int registerAllPlugin(const std::string path);
+
+
+ /**
+ * Unregister plugin.
+ *
+ * @param plugin plugin object to be unregistered.
+ * @return int, 1 is success, 0 is fail.
+ */
+ int unregisterPlugin(Plugin *const plugin);
+
+
+ /**
+ * Unregister All plugin.
+ *
+ * @return int, 1 is success, 0 is fail.
+ */
+ int unregisterAllPlugin(void);
+
+
+ /**
+ * get all plugins which currently registered.
+ *
+ * @return vector of currently registered plugins
+ *
+ */
+ std::vector<Plugin> &getAllPlugins(void);
+
+
+ /**
+ * find plugins which have the key and value
+ *
+ * @return vector of currently registered plugins
+ */
+ std::vector<Plugin> *findPlugins(const std::string key, const std::string value);
+
+
+ /**
+ * Get plugin which has the id
+ *
+ * @param pluginID plugin id to find
+ * @return Plugin instance
+ */
+ //Plugin *getPlugin(const std::string pluginID);
+
+ /**
+ * Start plugin
+ * This function will load dynamic plugin library on memory and call start function of plugin to be initialized.
+ *
+ * @param Plugin
+ * @param Platform pointer.
+ * @return int, 1 is success, 0 is fail.
+ */
+ int start(Plugin *const plugin, void *const arg);
+
+
+ /**
+ * Stop Plugin.
+ * This function will call stop function of plugin and unload dynamic plugin library from memory.
+ *
+ * @param Plugin
+ * @return int, 1 is success, 0 is fail.
+ */
+ int stop(Plugin *const plugin);
+
+
+ /**
+ * Check whether the plugin started or not
+ *
+ * @param Plugin to identify the Starting.
+ * @return true if started, false is stop.
+ *
+ */
+ bool isStarted(Plugin *plugin);
+
+
+ /**
+ * Get Plugin state.
+ *
+ * @param Plugin ID
+ * @return Plugin state.
+ */
+ const std::string getState(const std::string plugID);
+
+
+ /**
+ *
+ * new Singleton pattern instance.
+ *
+ * @return OICPluginManager pointer Address.
+ */
+ static CpluffAdapter *Getinstance()
+ {
+ if (NULL == s_pinstance)
+ {
+ s_pinstance = new CpluffAdapter();
+ }
+
+ return s_pinstance;
+ }
+
+
+
+ private:
+
+ typedef std::map<std::string, bool> File_list;
+ std::vector<Plugin> m_plugins;
+ cp_context_t *m_context;
+ cp_status_t m_status;
+ cp_plugin_info_t **m_cp_plugins;
+ cp_plugin_info_t *m_plugin;
+ boost::thread m_file_detect_thread;
+ boost::thread_group m_thread_g;
+ std::string m_path;
+ static CpluffAdapter *s_pinstance;
+
+ /**
+ * Constructor for CpluffAdapter.
+ * During construction time, all plugins under the root plugin path will be loaded.
+ *
+ */
+ CpluffAdapter();
+
+ /**
+ * Virtual destructor
+ */
+ virtual ~CpluffAdapter(void);
+
+ /**
+ * delete Singleton pattern instance.
+ */
+ static void deleteinstance()
+ {
+ if (NULL != s_pinstance)
+ {
+ delete s_pinstance;
+ s_pinstance = NULL;
+ }
+ }
+
+ /**
+ * detect plugins(add, delete, move)
+ *
+ * @param plugin file path.
+ * @return void
+ */
+ void observePluginPath(void *);
+
+
+ /**
+ * change Number to String.
+ *
+ * @param int.
+ * @return State String.
+ */
+ const char *state_to_string(int state);
+
+ /**
+ * Get whole "SO" file list.
+ *
+ * @param OUT, SO file list.
+ * @param Root path.
+ * @return true or false.
+ */
+ bool getFileList(File_list &list, const std::string strDir);
+
+ /**
+ * print whole plugin info.
+ *
+ * @param cpluff plugins
+ */
+ void printPluginList(cp_plugin_info_t **plugins);
+
+ /**
+ * install plugin using c-pluff.
+ *
+ * @param Root path.
+ * @return int, 1 is success, 0 is fail.
+ */
+ int installPlugin(const std::string path);
+
+
+ /**
+ * find Plugin and install plugin.(Recursive)
+ *
+ * @param Root path.
+ * @return int, 1 is success, 0 is fail.
+ */
+ int findPluginRecursive(const std::string path);
+
+ /**
+ * load Plugin information to PluginManager table.
+ *
+ * @param path to observe
+ * @return int, 1 is success, 0 is fail.
+ */
+ int loadPluginInfoToManager(const std::string path);
+ };
+}
+
+#endif //__CPLUFFADAPTER_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file FelixAdapter.cpp
+
+/// @brief
+
+#include "FelixAdapter.h"
+
+using namespace OIC;
+
+FelixAdapter *FelixAdapter::s_pinstance;
+
+FelixAdapter::FelixAdapter()
+{
+
+}
+
+FelixAdapter::~FelixAdapter(void)
+{
+ s_pinstance->deleteinstance();
+}
+
+int FelixAdapter::installPlugin(const std::string path)
+{
+ return 1;
+}
+
+int FelixAdapter::findPluginRecursive(const std::string path)
+{
+ return 1;
+}
+
+int FelixAdapter::loadPluginInfoToManager(const std::string path)
+{
+ return 1;
+}
+
+int FelixAdapter::registerPlugin(const std::string path)
+{
+ return 1;
+}
+
+int FelixAdapter::registerAllPlugin(const std::string path)
+{
+ return 1;
+}
+
+int FelixAdapter::unregisterPlugin(Plugin *const plugin)
+{
+ return 1;
+}
+
+int FelixAdapter::unregisterAllPlugin(void)
+{
+ return 1;
+}
+
+std::vector<Plugin> &FelixAdapter::getAllPlugins(void)
+{
+ return m_plugins;
+}
+
+std::vector<Plugin> *FelixAdapter::findPlugins(const std::string key, const std::string value)
+{
+ return nullptr;
+}
+/*
+Plugin *FelixAdapter::getPlugin(const std::string plugID)
+{
+ return nullptr;
+}
+*/
+bool FelixAdapter::getFileList(File_list &list, const std::string strDir)
+{
+ return true;
+}
+
+
+void FelixAdapter::printPluginList(cp_plugin_info_t **plugins)
+{
+
+}
+
+int FelixAdapter::start(Plugin *const plugin, void *const arg)
+{
+ return TRUE;
+}
+
+int FelixAdapter::stop(Plugin *const plugin)
+{
+ return TRUE;
+}
+
+bool FelixAdapter::isStarted(Plugin *plugin)
+{
+ return FALSE;
+}
+
+void FelixAdapter::observePluginPath(void *str)
+{
+
+}
+
+const std::string FelixAdapter::getState(const std::string plugID)
+{
+ return "";
+}
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file FelixAdapter.h
+
+/// @brief
+
+#ifndef __FELIXADAPTER_H__
+#define __FELIXADAPTER_H__
+#define DLOPEN_POSIX
+
+#include <vector>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/inotify.h>
+#include <unistd.h>
+#include <boost/thread.hpp>
+#include <boost/bind.hpp>
+#include <internal.h>
+
+#include "Plugin.h"
+
+#define EVENT_SIZE ( sizeof (struct inotify_event) )
+#define BUF_LEN (int)( 1024 * ( EVENT_SIZE + 16 ) )
+
+namespace OIC
+{
+ /**
+ * @brief After installing a plug-in in a directory, each plug-ins can be managed by this class.
+ *
+ *
+ */
+ class FelixAdapter
+ {
+ public:
+ /**
+ * A function to register pluins in the path.
+ * This function will load plugins in plugin manager table.
+ *
+ * @param path plugin file path to be registered.
+ * @return int, 1 is success, 0 is fail.
+ *
+ * NOTE:
+ *
+ */
+ int registerPlugin(const std::string path);
+
+
+ /**
+ * A function to register pluins in the path.
+ * This function will load plugins in plugin manager table.
+ *
+ * @param path plugin file path to be registered.
+ * recursive load plugins sub folders recursively.
+ * @return int, 1 is success, 0 is fail.
+ *
+ * NOTE:
+ *
+ */
+ int registerAllPlugin(const std::string path);
+
+
+ /**
+ * Unregister plugin.
+ *
+ * @param plugin plugin object to be unregistered.
+ * @return int, 1 is success, 0 is fail.
+ */
+ int unregisterPlugin(Plugin *const plugin);
+
+
+ /**
+ * Unregister All plugin.
+ *
+ * @return int, 1 is success, 0 is fail.
+ */
+ int unregisterAllPlugin(void);
+
+
+ /**
+ * get all plugins which currently registered.
+ *
+ * @return vector of currently registered plugins
+ *
+ */
+ std::vector<Plugin> &getAllPlugins(void);
+
+
+ /**
+ * find plugins which have the key and value
+ *
+ * @return vector of currently registered plugins
+ */
+ std::vector<Plugin> *findPlugins(const std::string key, const std::string value);
+
+
+ /**
+ * Get plugin which has the id
+ *
+ * @param pluginID plugin id to find
+ * @return Plugin instance
+ */
+ //Plugin *getPlugin(const std::string pluginID);
+
+ /**
+ * Start plugin
+ * This function will load dynamic plugin library on memory and call start function of plugin to be initialized.
+ *
+ * @param Plugin
+ * @param Platform pointer.
+ * @return int, 1 is success, 0 is fail.
+ */
+ int start(Plugin *const plugin, void *const arg);
+
+
+ /**
+ * Stop Plugin.
+ * This function will call stop function of plugin and unload dynamic plugin library from memory.
+ *
+ * @param Plugin
+ * @return int, 1 is success, 0 is fail.
+ */
+ int stop(Plugin *const plugin);
+
+
+ /**
+ * Check whether the plugin started or not
+ *
+ * @param Plugin to identify the Starting.
+ * @return true if started, false is stop.
+ *
+ */
+ bool isStarted(Plugin *plugin);
+
+
+ /**
+ * Get Plugin state.
+ *
+ * @param Plugin ID
+ * @return Plugin state.
+ */
+ const std::string getState(const std::string plugID);
+
+
+ /**
+ *
+ * new Singleton pattern instance.
+ *
+ * @return OICPluginManager pointer Address.
+ */
+ static FelixAdapter *Getinstance()
+ {
+ if (NULL == s_pinstance)
+ {
+ s_pinstance = new FelixAdapter();
+ }
+
+ return s_pinstance;
+ }
+
+
+
+ private:
+
+ typedef std::map<std::string, bool> File_list;
+ std::vector<Plugin> m_plugins;
+ boost::thread m_file_detect_thread;
+ /*
+ cp_context_t *m_context;
+ cp_status_t m_status;
+ cp_plugin_info_t **m_cp_plugins;
+ cp_plugin_info_t *m_plugin;
+ boost::thread_group m_thread_g;
+ std::string m_path;
+ */
+ static FelixAdapter *s_pinstance;
+
+ /**
+ * Constructor for FelixAdapter.
+ * During construction time, all plugins under the root plugin path will be loaded.
+ *
+ */
+ FelixAdapter();
+
+ /**
+ * Virtual destructor
+ */
+ virtual ~FelixAdapter(void);
+
+ /**
+ * delete Singleton pattern instance.
+ */
+ static void deleteinstance()
+ {
+ if (NULL != s_pinstance)
+ {
+ delete s_pinstance;
+ s_pinstance = NULL;
+ }
+ }
+
+ /**
+ * detect plugins(add, delete, move)
+ *
+ * @param plugin file path.
+ * @return void
+ */
+ void observePluginPath(void *);
+
+ /**
+ * Get whole "SO" file list.
+ *
+ * @param OUT, SO file list.
+ * @param Root path.
+ * @return true or false.
+ */
+ bool getFileList(File_list &list, const std::string strDir);
+
+ /**
+ * print whole plugin info.
+ *
+ * @param Felix plugins
+ */
+ void printPluginList(cp_plugin_info_t **plugins);
+
+ /**
+ * install plugin using c-pluff.
+ *
+ * @param Root path.
+ * @return int, 1 is success, 0 is fail.
+ */
+ int installPlugin(const std::string path);
+
+
+ /**
+ * find Plugin and install plugin.(Recursive)
+ *
+ * @param Root path.
+ * @return int, 1 is success, 0 is fail.
+ */
+ int findPluginRecursive(const std::string path);
+
+ /**
+ * load Plugin information to PluginManager table.
+ *
+ * @param path to observe
+ * @return int, 1 is success, 0 is fail.
+ */
+ int loadPluginInfoToManager(const std::string path);
+ };
+}
+
+#endif //__FELIXADAPTER_H__
/// @brief
-#ifndef __OCPLUGIN_H__
-#define __OCPLUGIN_H__
+#ifndef __Plugin_H__
+#define __Plugin_H__
#define TRUE 1
#define FALSE 0
}
-#endif //__OCPLUGIN_H__
+#endif //__Plugin_H__
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file PluginLifecycleManager.cpp
-
-/// @brief
-
-#include <PluginLifecycleManager.h>
-
-using namespace OIC;
-
-PluginLifeCycleManager::PluginLifeCycleManager()
-{
- //struct PluginManagerConfig pmconfig;
- //pmconfig.rootPluinPath = "./../plugins";
- pm = new PluginManager();
-}
-
-PluginLifeCycleManager::~PluginLifeCycleManager()
-{
- delete(pm);
-}
-
-void PluginLifeCycleManager::startPluginsByResourceType(const std::string type)
-{
- std::string resourcetype = "";
- int size = type.size();
-
- //Parsing Resource_Type
- for (int i = size - 1; i > -1 ; i--)
- {
- if (type.at(i) == '.' && type.at(i) == '/')
- {
- break;
- }
- resourcetype += type.at(i);
- }
-
- //Reverse string(Resource type)
-
- reverse(resourcetype.begin(), resourcetype.end());
-
- // printf("resource type = %s\n", resourcetype.c_str());
-
- //Search Plugin
- std::vector<Plugin> resource_plugin = pm->getPlugins("ResourceType", resourcetype);
-
- //start Plugin
- std::vector<Plugin>::iterator it;
- for (it = resource_plugin.begin(); it != resource_plugin.end(); it++)
- {
- if (!pm->isStarted(&(*it))) // started : 1, stop : 0
- {
- pm->start(&(*it));
- }
- }
-}
-
-void PluginLifeCycleManager::stopPluginsByResourceType(const std::string type)
-{
- std::string resourcetype = "";
- int size = type.size();
-
- //Parsing Resource_Type
- for (int i = size - 1; i > -1 ; i--)
- {
- if (type.at(i) == '.' && type.at(i) == '/')
- {
- break;
- }
- resourcetype += type.at(i);
- }
-
- //Reverse string(Resource type)
-
- reverse(resourcetype.begin(), resourcetype.end());
-
- // printf("resource type = %s\n", resourcetype.c_str());
-
- //Search Plugin
- std::vector<Plugin> resource_plugin = pm->getPlugins("ResourceType", resourcetype);
-
- //stop Plugin
- std::vector<Plugin>::iterator it;
- for (it = resource_plugin.begin(); it != resource_plugin.end(); it++)
- {
- if (pm->isStarted(&(*it))) // started : 1, stop : 0
- {
- pm->stop(&(*it));
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file ProtocolLifecycleManager.h
-
-/// @brief
-
-#ifndef __PLUGINLIFECYCLEMANAGER_H
-#define __PLUGINLIFECYCLEMANAGER_H
-
-#include <PluginManager.h>
-#include <Plugin.h>
-
-namespace OIC
-{
-
- /**
- * @brief Protocol plugin's lifecycle can be controlled by this class.
- *
- *
- */
- class PluginLifeCycleManager
- {
- public:
-
- PluginLifeCycleManager();
-
- ~PluginLifeCycleManager();
-
-
- /**
- * Start protocol plugins by resource type
- *
- * @param type resouce type string to be started.
- *
- */
- void startPluginsByResourceType(const std::string type);
-
- /**
- * Stop protocol plugins by resource type
- *
- * @param type resouce type string to be started.
- *
- */
- void stopPluginsByResourceType(const std::string type);
- private:
- PluginManager *pm;
-
- };
-}
-
-#endif __PLUGINLIFECYCLEMANAGER_H
-
/// @brief
+
#include "PluginManager.h"
using namespace OIC;
PluginManager::PluginManager()
{
- //printf("PluginManager construct\n");
- m_status = cp_init();
- m_context = cp_create_context(&m_status);
- m_cp_plugins = NULL;
- m_plugin = NULL;
-}
-
-PluginManager::~PluginManager(void)
-{
- //printf("~PlugingManager\n");
- cp_release_info(m_context, m_cp_plugins);
- m_thread_g.interrupt_all();
- m_thread_g.join_all();
- s_pinstance->deleteinstance();
- s_pinstance = NULL;
-}
-
-int PluginManager::installPlugin(const std::string path)
-{
- char *argv = const_cast<char *>(path.c_str());
-
- if ((m_plugin = cp_load_plugin_descriptor(m_context, argv, &m_status)) == NULL)
- {
- printf("cp_load_plugin_descriptor failed\n");
- return false;
- }
- else if ((m_status = cp_install_plugin(m_context, m_plugin)) != 0)
- {
- printf("cp_install_plugin failed\n");
- return false;
- }
-
- return true;
-}
-
-int PluginManager::findPluginRecursive(const std::string path)
-{
- ////////FILELIST////////////
- File_list file_list;
- getFileList(file_list, path);
- File_list::iterator itr;
- int flag = FALSE;
-
- for (itr = file_list.begin(); itr != file_list.end(); itr++)
- {
- if (itr->second == true)
- {
- //printf("[Direcotry] %s\n",itr->first.c_str());
- }
- else
- {
- //printf("[FILE] = %s\n" , itr->first.c_str());
- std::string filepath = itr->first.c_str();
- int count = 0;
- for (unsigned int i = 0 ; i < filepath.size(); i++)
- {
- if (filepath.at(i) == '/')
- {
- count = i;
- }
- }
- std::string filename = filepath.substr(0, count );
- //char *temp_char = const_cast<char *>(filename.c_str());
- flag = installPlugin(filename);
- //printf("plugin file path %s \n", plugin->plugin_path);
- }
- }
-
- return flag;
-}
-
-int PluginManager::loadPluginInfoToManager(const std::string path)
-{
- //get plugins information.
- if ((m_cp_plugins = cp_get_plugins_info(m_context, &m_status, NULL)) == NULL)
- {
- printf("cp_get_plugins_infor failed\n");
- return FALSE;
- }
- else
- {
- printPluginList(m_cp_plugins);
- }
-
- for (int i = 0 ; m_cp_plugins[i] != NULL; i++)
- {
- Plugin *plugin = new Plugin;
- plugin->setValue("Path", m_cp_plugins[i]->plugin_path);
- //printf("add filepath %s\n",m_cp_plugins[i]->plugin_path);
- if (m_cp_plugins[i]->identifier != NULL)
- {
- plugin->setValue("Id", m_cp_plugins[i]->identifier );
- }
- else
- {
- plugin->setValue("Id", "");
- }
-
- if (m_cp_plugins[i]->url != NULL)
- {
- plugin->setValue("Url", m_cp_plugins[i]->url);
- }
- else
- {
- plugin->setValue("Url", "");
- }
-
- if (m_cp_plugins[i]->name != NULL)
- {
- plugin->setValue("Name", m_cp_plugins[i]->name);
- }
- else
- {
- plugin->setValue("Name", "");
- }
-
- if (m_cp_plugins[i]->resourcetype != NULL)
- {
- plugin->setValue("ResourceType", m_cp_plugins[i]->resourcetype);
- }
- else
- {
- plugin->setValue("ResourceType", "");
- }
-
- if (m_cp_plugins[i]->version != NULL)
- {
- plugin->setValue("Version", m_cp_plugins[i]->version);
- }
- else
- {
- plugin->setValue("Version", "");
- }
-
- bool plugin_compare_flag = true;
- for (unsigned int i = 0 ; i < m_plugins.size(); i++)
- {
- if (*plugin == m_plugins[i])
- {
- delete(plugin);
- plugin_compare_flag = false;
- break;
- }
- }
- if (plugin_compare_flag)
- {
- m_plugins.push_back(*plugin);
- try
- {
- boost::thread *t = new boost::thread(boost::bind(&PluginManager::observePluginPath,
- //this, (void *)path.c_str()));
- this, (void *)m_cp_plugins[i]->plugin_path));
- m_thread_g.add_thread(t);
- }
- catch (...)
- {
- printf("thread throw exception\n");
- }
- delete(plugin);
- }
- //printf("plugin size = %d\n",m_plugins.size());
- }
-
- return TRUE;
-}
-
-int PluginManager::registerPlugin(const std::string path)
-{
- //printf("PluginManager register\n");
- int flag = FALSE;
-
- if (path == "")
- {
- printf("PluginManager path == null\n");
- return flag;
- }
-
- //non recursive
-
- flag = installPlugin(path);
-
- flag = loadPluginInfoToManager(path);
-
- return flag;
-}
-
-int PluginManager::registerAllPlugin(const std::string path)
-{
- //printf("PluginManager register\n");
- int flag = FALSE;
- if (path == "")
- {
- printf("PluginManager path == null\n");
- return flag;
- }
-
- //recursive
-
- flag = findPluginRecursive(path);
-
- flag = loadPluginInfoToManager(path);
-
- return flag;
-}
-
-int PluginManager::unregisterPlugin(Plugin *const plugin)
-{
- cp_status_t status;
- char *argv = NULL;
- std::string id = "";
-
- for (unsigned int i = 0; i < m_plugins.size(); i++)
- {
-
- if (*plugin == m_plugins[i])
- {
- id = m_plugins[i].getID().c_str();
- argv = const_cast<char *>(id.c_str());
- if ((status = cp_uninstall_plugin(m_context, argv)) != 0)
- {
- printf("unregister failed\n");
- return FALSE;
- }
- m_plugins.erase(m_plugins.begin() + i);
- }
- }
- return TRUE;
-}
-
-int PluginManager::unregisterAllPlugin(void)
-{
- cp_status_t status;
- char *argv = NULL;
- std::string id = "";
-
- while (true)
+ void *handle = dlopen("./libpmimpl.so", RTLD_LAZY);
+ if (!handle)
{
- id = m_plugins[0].getID().c_str();
- argv = const_cast<char *>(id.c_str());
- if ((status = cp_uninstall_plugin(m_context, argv)) != 0)
- {
- printf("unregister failed\n");
- return FALSE;
- }
- m_plugins.erase(m_plugins.begin());
- if (m_plugins.size() == 0)
- {
- break;
- }
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
}
-
- return TRUE;
+ PluginManagerImpl* (*create)();
+ create = (PluginManagerImpl * (*)())dlsym(handle, "create_object");
+ destroy = (void (*)(PluginManagerImpl *))dlsym(handle, "destroy_object");
+ pluginManagerImpl = (PluginManagerImpl *)create();
}
-std::vector<Plugin> &PluginManager::getAllPlugins(void)
-{
- return m_plugins;
-}
-
-std::vector<Plugin> *PluginManager::findPlugins(const std::string key,
- const std::string value)
-{
- std::vector<Plugin> *re_plugins;
-
- re_plugins = new std::vector<Plugin>;
-
- for (unsigned int i = 0; i < m_plugins.size(); i++)
- {
- if (!m_plugins[i].getValueByAttribute(key).compare(value))
- {
- re_plugins->push_back(m_plugins[i]);
- }
- }
-
- return re_plugins;
-}
-
-
-
-Plugin *PluginManager::getPlugin(const std::string plugID)
-{
- for (unsigned int i = 0; i < m_plugins.size(); i++)
- {
- if (!(m_plugins[i].getID().compare(plugID)))
- {
- return &(m_plugins[i]);
- }
- }
-
- return NULL;
-}
-
-bool PluginManager::getFileList(File_list &list, const std::string strDir)
-{
- struct stat statinfo;
- memset(&statinfo, 0, sizeof(statinfo));
- std::string path = strDir;
- if (0 != lstat(path.c_str(), &statinfo))
- {
- printf("PlugManager lstat is 0\n");
- return false;
- }
- if (!S_ISDIR(statinfo.st_mode))
- {
- printf("%s is not directory", strDir.c_str());
- return false;
- }
-
- DIR *dir;
- struct dirent *entry;
-
- if ((dir = opendir(strDir.c_str())) == NULL)
- {
- printf("%s open error", strDir.c_str());
- return false;
- }
-
- while ((entry = readdir(dir)) != NULL)
- {
- memset(&statinfo, 0, sizeof(statinfo));
- std::string strFilePath = strDir + "/" + entry->d_name;
- while (strFilePath.find("//") != std::string::npos)
- strFilePath.replace(strFilePath.find("//"), 2, "/");
-
- if (0 != lstat(strFilePath.c_str(), &statinfo))
- {
- printf("PlugManager lstat is 0\n");
- closedir(dir);
- return false;
- }
-
- if (S_ISDIR(statinfo.st_mode))
- {
- if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
- continue;
-
- list.insert(std::pair<std::string, bool>(strFilePath, true));
- std::string strSubDir = strDir + "/" + entry->d_name;
- getFileList(list, strSubDir);
- }
- else
- {
- int size = strFilePath.size();
- std::string so = strFilePath.substr(size - 2, size - 1);
- if (so == "so")
- {
- list.insert(std::pair<std::string, bool>(strFilePath, false));
- }
- }
- }
- closedir(dir);
-
- return true;
-}
-
-const char *PluginManager::state_to_string(int state)
-{
- switch (state)
- {
- case 0:
- return "uninstalled";
- case 1:
- return "installed";
- case 2:
- return "resolved";
- case 3:
- return "starting";
- case 4:
- return "stopping";
- case 5:
- return "active";
- default:
- return "unknown";
- }
-}
-
-void PluginManager::printPluginList(cp_plugin_info_t **plugins)
+PluginManager::~PluginManager(void)
{
- const char format[] = " %-30s %-15s %-15s %-20s\n";
- printf("\n====== Plugins List ======\n");
- printf(format,
- "ID",
- "NAME",
- "STATE",
- "TYPE");
-
- for (int i = 0; m_cp_plugins[i] != NULL; i++)
- {
- printf(format,
- m_cp_plugins[i]->identifier,
- m_cp_plugins[i]->name != NULL ? m_cp_plugins[i]->name : "",
- state_to_string(cp_get_plugin_state(m_context, m_cp_plugins[i]->identifier)),
- m_cp_plugins[i]->resourcetype != NULL ? m_cp_plugins[i]->resourcetype : "");
- }
- printf("\n");
+ destroy(pluginManagerImpl);
}
-int PluginManager::start(Plugin *const plugin, void *const arg)
+int PluginManager::startPlugins(const std::string key, const std::string value)
{
- //printf("start\n");
- std::string id;
- cp_status_t status;
- cp_context_t *ctx;
-
- id = plugin->getID();
- for (unsigned int i = 0 ; i < m_plugins.size(); i++)
- {
- if (*plugin == m_plugins[i])
- {
- ctx = cpi_new_context((cp_plugin_t *)hnode_get(hash_lookup(m_context->env->plugins, id.c_str())),
- m_context->env, &status);
- cp_define_symbol(ctx, "START_ARGUMENT", arg);
- //printf("start ocplatform address : %x\n", arg);
-
- if ((status = cp_start_plugin(m_context, (char *)id.c_str()) ) != CP_OK)
- {
- printf("API function PluginManager::start() faild with error code.\n");
- return FALSE;
- }
- else
- {
- printf("start plug-in %s.\n", (char *)id.c_str());
- }
-
- break;
- }
- }
- return TRUE;
+ return pluginManagerImpl->startPlugins(key, value);
}
-int PluginManager::stop(Plugin *const plugin)
+int PluginManager::stopPlugins(const std::string key, const std::string value)
{
- std::string id;
- cp_status_t status;
-
- id = plugin->getID();
- printf("stop plugin id = %s\n", id.c_str());
- if ((status = cp_stop_plugin(m_context, (char *)id.c_str())) != CP_OK)
- {
- printf("API function PluginManager::stop() faild with error code.\n");
- return FALSE;
- }
- else
- {
- printf("Stop plug-in %s.\n", (char *)id.c_str());
- }
-
- return TRUE;
+ return pluginManagerImpl->stopPlugins(key, value);
}
-bool PluginManager::isStarted(Plugin *plugin)
+int PluginManager::startPlugins(Plugin *const plugin)
{
- std::string id;
- cp_plugin_state_t state;
-
- id = plugin->getID();
-
- state = cp_get_plugin_state(m_context, (char *)id.c_str());
- if (state == CP_PLUGIN_STARTING || state == CP_PLUGIN_ACTIVE)
- {
- return TRUE;
- }
- return FALSE;
+ printf("PluginManager::startPlugins\n");
+ return pluginManagerImpl->startPlugins(plugin);
}
-void PluginManager::observePluginPath(void *str)
+int PluginManager::stopPlugins(Plugin *const plugin)
{
- //printf("start observePluginPath\n");
- int length;
- int i = 0;
- int fd;
- int wd;
- char *str1 = (char *)str;
- std::string original_path(str1);
- //printf("Directory is %s\n",(char*)str1));
- char buffer[BUF_LEN];
-
- fd = inotify_init();
-
- if ( fd < 0 )
- {
- printf("inotify_init\n");
- }
-
- wd = inotify_add_watch( fd, str1,
- IN_MODIFY | IN_CREATE | IN_DELETE | IN_DELETE_SELF
- | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
-
- while (true)
- {
- //printf("read start\n");
- i = 0;
- length = read( fd, buffer, BUF_LEN );
-
- if ( length < 0 )
- {
- printf("observePluginPath read\n");
- }
- std::string filepath = original_path;
- //printf("filepath = %s\n",filepath.c_str());
- while ( i < length )
- {
- if (i < (signed)(BUF_LEN - ( sizeof( struct inotify_event) + 16)) && i > -1)
- {
- struct inotify_event *event = ( struct inotify_event *) &buffer[ i ];
-
- if ((event->mask & IN_CREATE) || (event->mask & IN_MODIFY) || (event->mask & IN_MOVED_TO))
- {
- registerAllPlugin(str1);
- }
- else
- {
- //filepath += "/";
- //filepath += std::string(event->name);
- std::vector<Plugin> *resource_plugin = findPlugins("Path", filepath.c_str()); //add foldername
-
- //printf("plugin size is %d\n",resource_plugin->size());
- //printf("plugin file path is %s\n",resource_plugin->());
- if (resource_plugin->size() == 1)
- {
- unregisterPlugin(&(resource_plugin->at(0)));
- }
- else
- {
- registerAllPlugin(str1);
- }
- delete(resource_plugin);
- resource_plugin = NULL;
- }
- //printf("observePluginPath path = %s \n",str1);
- //printf("observePluginPath directory name = %s \n",event->name);
- i += EVENT_SIZE + event->len;
- }
- }
-
-
- }
- ( void ) inotify_rm_watch( fd, wd );
- ( void ) close( fd );
- //printf("observePluginPath end\n");
+ return pluginManagerImpl->stopPlugins(plugin);
}
-const std::string PluginManager::getState(const std::string plugID)
+std::vector<Plugin> PluginManager::getPlugins(void)
{
- return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
-}
+ return pluginManagerImpl->getAllPlugins();
+}
\ No newline at end of file
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
-#include <sys/types.h>
-#include <sys/inotify.h>
-#include <unistd.h>
-#include <boost/thread.hpp>
-#include <boost/bind.hpp>
-#include <internal.h>
-
+#include <dlfcn.h>
+#include "PluginManagerImpl.h"
#include "Plugin.h"
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-#define EVENT_SIZE ( sizeof (struct inotify_event) )
-#define BUF_LEN (int)( 1024 * ( EVENT_SIZE + 16 ) )
namespace OIC
{
-
- struct PluginManagerConfig
- {
- std::string rootPluinPath;
- };
-
/**
* @brief After installing a plug-in in a directory, each plug-ins can be managed by this class.
*
class PluginManager
{
public:
- /**
- * A function to register pluins in the path.
- * This function will load plugins in plugin manager table.
- *
- * @param path plugin file path to be registered.
- * @return int, 1 is success, 0 is fail.
- *
- * NOTE:
- *
- */
- int registerPlugin(const std::string path);
-
-
- /**
- * A function to register pluins in the path.
- * This function will load plugins in plugin manager table.
- *
- * @param path plugin file path to be registered.
- * recursive load plugins sub folders recursively.
- * @return int, 1 is success, 0 is fail.
- *
- * NOTE:
- *
- */
- int registerAllPlugin(const std::string path);
-
-
- /**
- * Unregister plugin.
- *
- * @param plugin plugin object to be unregistered.
- * @return int, 1 is success, 0 is fail.
- */
- int unregisterPlugin(Plugin *const plugin);
-
+ PluginManager();
/**
- * Unregister All plugin.
- *
- * @return int, 1 is success, 0 is fail.
+ * Virtual destructor
*/
- int unregisterAllPlugin(void);
-
-
+ ~PluginManager(void);
/**
- * get all plugins which currently registered.
+ * Start plugins by resource type
*
- * @return vector of currently registered plugins
+ * @param type resouce type string to be started.
*
*/
- std::vector<Plugin> &getAllPlugins(void);
-
+ int startPlugins(const std::string key, const std::string value);
/**
- * find plugins which have the key and value
+ * Stop plugins by resource type
*
- * @return vector of currently registered plugins
- */
- std::vector<Plugin> *findPlugins(const std::string key, const std::string value);
-
-
- /**
- * Get plugin which has the id
+ * @param type resouce type string to be started.
*
- * @param pluginID plugin id to find
- * @return Plugin instance
*/
- Plugin *getPlugin(const std::string pluginID);
+ int stopPlugins(const std::string key, const std::string value);
/**
* Start plugin
* This function will load dynamic plugin library on memory and call start function of plugin to be initialized.
*
* @param Plugin
- * @param Platform pointer.
* @return int, 1 is success, 0 is fail.
*/
- int start(Plugin *const plugin, void *const arg);
+ int startPlugins(Plugin *const plugin);
/**
* @param Plugin
* @return int, 1 is success, 0 is fail.
*/
- int stop(Plugin *const plugin);
-
-
- /**
- * Check whether the plugin started or not
- *
- * @param Plugin to identify the Starting.
- * @return true if started, false is stop.
- *
- */
- bool isStarted(Plugin *plugin);
+ int stopPlugins(Plugin *const plugin);
/**
- * Get Plugin state.
+ * Get Plugin list.
*
- * @param Plugin ID
- * @return Plugin state.
- */
- const std::string getState(const std::string plugID);
-
-
- /**
*
- * new Singleton pattern instance.
*
- * @return PluginManager pointer Address.
+ * @return
*/
- static PluginManager *Getinstance()
- {
- if (NULL == s_pinstance)
- {
- s_pinstance = new PluginManager();
- }
-
- return s_pinstance;
- }
-
-
+ std::vector<Plugin> getPlugins(void);
private:
-
- typedef std::map<std::string, bool> File_list;
- std::vector<Plugin> m_plugins;
- cp_context_t *m_context;
- cp_status_t m_status;
- cp_plugin_info_t **m_cp_plugins;
- cp_plugin_info_t *m_plugin;
- boost::thread m_file_detect_thread;
- boost::thread_group m_thread_g;
- std::string m_path;
- static PluginManager *s_pinstance;
-
- /**
- * Constructor for PluginManager.
- * During construction time, all plugins under the root plugin path will be loaded.
- *
- */
- PluginManager();
-
- /**
- * Virtual destructor
- */
- virtual ~PluginManager(void);
-
- /**
- * delete Singleton pattern instance.
- */
- static void deleteinstance()
- {
- if (NULL != s_pinstance)
- {
- delete s_pinstance;
- s_pinstance = NULL;
- }
- }
-
- /**
- * detect plugins(add, delete, move)
- *
- * @param plugin file path.
- * @return void
- */
- void observePluginPath(void *);
-
-
- /**
- * change Number to String.
- *
- * @param int.
- * @return State String.
- */
- const char *state_to_string(int state);
-
- /**
- * Get whole "SO" file list.
- *
- * @param OUT, SO file list.
- * @param Root path.
- * @return true or false.
- */
- bool getFileList(File_list &list, const std::string strDir);
-
- /**
- * print whole plugin info.
- *
- * @param cpluff plugins
- */
- void printPluginList(cp_plugin_info_t **plugins);
-
- /**
- * install plugin using c-pluff.
- *
- * @param Root path.
- * @return int, 1 is success, 0 is fail.
- */
- int installPlugin(const std::string path);
-
-
- /**
- * find Plugin and install plugin.(Recursive)
- *
- * @param Root path.
- * @return int, 1 is success, 0 is fail.
- */
- int findPluginRecursive(const std::string path);
-
- /**
- * load Plugin information to PluginManager table.
- *
- * @param path to observe
- * @return int, 1 is success, 0 is fail.
- */
- int loadPluginInfoToManager(const std::string path);
+ PluginManagerImpl *pluginManagerImpl;
+ void (*destroy)(PluginManagerImpl *);
};
}
-
#endif //__PLUGINMANAGER_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file PluginManagerImpl.cpp
+
+/// @brief
+
+#include "PluginManagerImpl.h"
+
+using namespace OIC;
+
+PluginManagerImpl *PluginManagerImpl::s_pinstance = nullptr;
+
+extern "C" PluginManagerImpl *create_object()
+{
+ PluginManagerImpl *newobj;
+ newobj = new PluginManagerImpl;
+ return newobj;
+}
+
+extern "C" void destroy_object( PluginManagerImpl *object )
+{
+ delete object;
+}
+
+PluginManagerImpl::PluginManagerImpl()
+{
+ cppm = CpluffAdapter::Getinstance();
+ javappm = FelixAdapter::Getinstance();
+ refreshPluginInfo();
+}
+
+PluginManagerImpl::~PluginManagerImpl()
+{
+
+}
+
+int PluginManagerImpl::registerPlugin(std::string path)
+{
+ int flag = 0;
+ flag = cppm->registerPlugin(path);
+ flag = javappm->registerPlugin(path);
+ refreshPluginInfo();
+ return flag;
+}
+
+int PluginManagerImpl::registerAllPlugin(std::string path)
+{
+ int flag = 0;
+ flag = cppm->registerAllPlugin(path);
+ flag = javappm->registerAllPlugin(path);
+ refreshPluginInfo();
+ return flag;
+}
+
+int PluginManagerImpl::unregisterPlugin(std::string id)
+{
+ int flag = 0;
+
+ Plugin *plugin = new Plugin;
+ plugin->setValue("Id", id);
+
+ for (unsigned int i = 0 ; i < m_plugins.size(); i++)
+ {
+ if (!m_plugins[i].getID().compare(id))
+ {
+ if (!m_plugins[i].getValueByAttribute("Language").compare("CPP"))
+ {
+ if ((flag = cppm->unregisterPlugin(&m_plugins[i])))
+ {
+ m_plugins.erase(m_plugins.begin() + i);
+ }
+ }
+ else if (!m_plugins[i].getValueByAttribute("Language").compare("JAVA"))
+ {
+ if ((flag = javappm->unregisterPlugin(&m_plugins[i])))
+ {
+ m_plugins.erase(m_plugins.begin() + i);
+ }
+ }
+ }
+ }
+
+ return flag;
+}
+
+int PluginManagerImpl::unregisterAllPlugin()
+{
+ int flag = 0;
+ flag = cppm->unregisterAllPlugin();
+ flag = javappm->unregisterAllPlugin();
+ m_plugins.clear();
+ return flag;
+}
+
+
+std::vector<Plugin> &PluginManagerImpl::getAllPlugins(void)
+{
+ return m_plugins;
+}
+
+std::vector<Plugin> *PluginManagerImpl::findPlugins(const std::string key,
+ const std::string value)
+{
+ std::vector<Plugin> *re_plugins;
+ re_plugins = new std::vector<Plugin>;
+ for (unsigned int i = 0; i < m_plugins.size(); i++)
+ {
+ if (!m_plugins[i].getValueByAttribute(key).compare(value))
+ {
+ re_plugins->push_back(m_plugins[i]);
+ }
+ }
+
+ return re_plugins;
+}
+
+Plugin *PluginManagerImpl::getPlugin(const std::string pluginID)
+{
+ for (unsigned int i = 0; i < m_plugins.size(); i++)
+ {
+ if (!(m_plugins[i].getID().compare(pluginID)))
+ {
+ return &(m_plugins[i]);
+ }
+ }
+
+ return nullptr;
+}
+int PluginManagerImpl::startPlugins(const std::string key, const std::string value)
+{
+ int flag = FALSE;
+ std::string resourcetype = "";
+ int size = value.size();
+
+ //Parsing Resource_Type
+ for (int i = size - 1; i > -1 ; i--)
+ {
+ if (value.at(i) == '.' && value.at(i) == '/')
+ {
+ break;
+ }
+ resourcetype += value.at(i);
+ }
+
+ //Reverse string(Resource value)
+ reverse(resourcetype.begin(), resourcetype.end());
+
+ //Search Plugin
+ std::vector<Plugin> *resource_plugin = findPlugins(key, resourcetype);
+
+ //start Plugin
+ std::vector<Plugin>::iterator it;
+ for (it = resource_plugin->begin(); it != resource_plugin->end(); it++)
+ {
+ if (!isStarted(&(*it))) // started : 1, stop : 0
+ {
+ flag = startPlugins(&(*it));//TODO PASS the OCPlatform
+ }
+ }
+ delete(resource_plugin);
+ resource_plugin = nullptr;
+ return flag;
+}
+
+int PluginManagerImpl::startPlugins(Plugin *const plugin)
+{
+ int flag = FALSE;
+ void *arg = nullptr;
+
+ flag = startbyPlatform(plugin, arg);
+
+ return flag;
+}
+
+int PluginManagerImpl::stopPlugins(const std::string key, const std::string value)
+{
+ int flag = FALSE;
+ std::string resourcetype = "";
+ int size = value.size();
+
+ //Parsing Resource_Type
+ for (int i = size - 1; i > -1 ; i--)
+ {
+ if (value.at(i) == '.' && value.at(i) == '/')
+ {
+ break;
+ }
+ resourcetype += value.at(i);
+ }
+
+ //Reverse string(Resource value)
+
+ reverse(resourcetype.begin(), resourcetype.end());
+
+ // printf("resource value = %s\n", resourcetype.c_str());
+
+ //Search Plugin
+ std::vector<Plugin> *resource_plugin = findPlugins(key, resourcetype);
+
+ //stop Plugin
+ std::vector<Plugin>::iterator it;
+ for (it = resource_plugin->begin(); it != resource_plugin->end(); it++)
+ {
+ if (isStarted(&(*it))) // started : 1, stop : 0
+ {
+ flag = stopPlugins(&(*it));//TODO PASS the OCPlatform
+ }
+ }
+ delete(resource_plugin);
+ resource_plugin = nullptr;
+ return flag;
+}
+
+int PluginManagerImpl::stopPlugins(Plugin *const plugin)
+{
+ int flag = FALSE;
+
+ flag = stopbyPlatform(plugin);
+
+ return flag;
+}
+
+int PluginManagerImpl::startbyPlatform(Plugin *const plugin, void *const arg)
+{
+ int flag = 0;
+
+ for (unsigned int i = 0 ; i < m_plugins.size(); i++)
+ {
+ if (!m_plugins[i].getID().compare(plugin->getID()))
+ {
+ if (!m_plugins[i].getValueByAttribute("Language").compare("CPP"))
+ {
+ flag = cppm->start(plugin, arg);
+ }
+ else if (!m_plugins[i].getValueByAttribute("Language").compare("JAVA"))
+ {
+ flag = javappm->start(plugin, arg);
+ }
+ }
+ }
+
+ if (flag)
+ {
+ refreshPluginInfo();
+ }
+ return flag;
+}
+
+int PluginManagerImpl::stopbyPlatform(Plugin *const plugin)
+{
+ int flag = 0;
+
+ for (unsigned int i = 0 ; i < m_plugins.size(); i++)
+ {
+ if (!m_plugins[i].getID().compare(plugin->getID()))
+ {
+ if (!m_plugins[i].getValueByAttribute("Language").compare("CPP"))
+ {
+ flag = cppm->stop(plugin);
+ }
+ else if (!m_plugins[i].getValueByAttribute("Language").compare("JAVA"))
+ {
+ flag = javappm->stop(plugin);
+ }
+ }
+ }
+
+ if (flag)
+ {
+ refreshPluginInfo();
+ }
+ return flag;
+}
+
+bool PluginManagerImpl::isStarted(Plugin *plugin)
+{
+ bool flag = 0;
+ if (cppm->isStarted(plugin))
+ {
+ flag = TRUE;
+ return flag;
+ }
+
+ if (javappm->isStarted(plugin))
+ {
+ flag = TRUE;
+ return flag;
+ }
+ return flag;
+}
+
+std::string PluginManagerImpl::getState(std::string plugID)
+{
+ std::string str = "";
+
+ for (unsigned int i = 0 ; i < m_plugins.size(); i++)
+ {
+ if (!m_plugins[i].getID().compare(plugID))
+ {
+ if (!m_plugins[i].getValueByAttribute("Language").compare("CPP"))
+ {
+ str = cppm->getState(plugID);
+ }
+ else if (!m_plugins[i].getValueByAttribute("Language").compare("JAVA"))
+ {
+ str = javappm->getState(plugID);
+ }
+ }
+ }
+
+ return str;
+}
+
+std::vector<Plugin> PluginManagerImpl::refreshPluginInfo()
+{
+ m_plugins.clear();
+ m_plugins = cppm->getAllPlugins();
+
+ std::vector<Plugin> java_plugins = javappm->getAllPlugins();
+ int size = java_plugins.size();
+
+ for (int i = 0 ; i < size ; i++)
+ {
+ m_plugins.push_back(java_plugins[i]);
+ }
+
+ return m_plugins;
+}
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file PluginManagerImpl.h
+
+/// @brief
+
+#ifndef __PLUGINMANAGERIMPL_H__
+#define __PLUGINMANAGERIMPL_H__
+
+#include "Plugin.h"
+#include "CpluffAdapter.h"
+#include "FelixAdapter.h"
+
+namespace OIC
+{
+ class PluginManagerImpl
+ {
+ public:
+
+ /**
+ * Constructor for PluginManagerImpl.
+ * During construction time, all plugins under the root plugin path will be loaded.
+ *
+ */
+ PluginManagerImpl();
+
+ /**
+ * Virtual destructor
+ */
+ virtual ~PluginManagerImpl(void);
+
+
+ /**
+ * A function to register pluins in the path.
+ * This function will load plugins in plugin manager table.
+ *
+ * @param path plugin file path to be registered.
+ * @return int, 1 is success, 0 is fail.
+ *
+ * NOTE:
+ *
+ */
+ int registerPlugin(std::string path);
+
+
+
+ /**
+ * A function to register pluins in the path.
+ * This function will load plugins in plugin manager table.
+ *
+ * @param path plugin file path to be registered.
+ * recursive load plugins sub folders recursively.
+ * @return int, 1 is success, 0 is fail.
+ *
+ * NOTE:
+ *
+ */
+ int registerAllPlugin(std::string path);
+
+ /**
+ * Unregister plugin.
+ *
+ * @param plugin plugin object to be unregistered.
+ * @return int, 1 is success, 0 is fail.
+ */
+ int unregisterPlugin(std::string path);
+
+ /**
+ * Unregister All plugin.
+ *
+ * @return int, 1 is success, 0 is fail.
+ */
+ int unregisterAllPlugin(void);
+
+ /**
+ * find plugins which have the key and value
+ *
+ * @return vector of currently registered plugins
+ */
+ std::vector<Plugin> *findPlugins(const std::string key, const std::string value);
+
+ /**
+ * Get plugin which has the id
+ *
+ * @param pluginID plugin id to find
+ * @return Plugin instance
+ */
+ Plugin *getPlugin(const std::string pluginID);
+
+ /**
+ * Check whether the plugin started or not
+ *
+ * @param Plugin to identify the Starting.
+ * @return true if started, false is stop.
+ *
+ */
+ bool isStarted(Plugin *plugin);
+
+ /**
+ * Get Plugin state.
+ *
+ * @param Plugin ID
+ * @return Plugin state.
+ */
+ std::string getState(const std::string plugID);
+
+ /**
+ * Start plugins by resource type
+ *
+ * @param type resouce type string to be started.
+ *
+ */
+ virtual int startPlugins(const std::string key, const std::string value);
+
+ /**
+ * Stop plugins by resource type
+ *
+ * @param type resouce type string to be started.
+ *
+ */
+ virtual int stopPlugins(const std::string key, const std::string value);
+
+ /**
+ * Start plugin
+ * This function will load dynamic plugin library on memory and call start function of plugin to be initialized.
+ *
+ * @param Plugin
+ * @return int, 1 is success, 0 is fail.
+ */
+ virtual int startPlugins(Plugin *const plugin);
+
+
+ /**
+ * Stop Plugin.
+ * This function will call stop function of plugin and unload dynamic plugin library from memory.
+ *
+ * @param Plugin
+ * @return int, 1 is success, 0 is fail.
+ */
+ virtual int stopPlugins(Plugin *const plugin);
+
+ /**
+ * get all plugins which currently registered.
+ *
+ * @return vector of currently registered plugins
+ *
+ */
+ virtual std::vector<Plugin> &getAllPlugins(void);
+
+ static PluginManagerImpl *Getinstance()
+ {
+ if (NULL == s_pinstance)
+ {
+ s_pinstance = new PluginManagerImpl();
+ }
+
+ return s_pinstance;
+ }
+
+ private:
+
+ CpluffAdapter *cppm;
+ FelixAdapter *javappm;
+
+ std::vector<Plugin> m_plugins;
+ static PluginManagerImpl *s_pinstance;
+
+ static void deleteinstance()
+ {
+ if (NULL != s_pinstance)
+ {
+ delete s_pinstance;
+ s_pinstance = NULL;
+ }
+ }
+
+ /*
+ * refresh All Plugin information.
+ *
+ * @return vector<Plugin> is all Plugin.
+ */
+ std::vector<Plugin> refreshPluginInfo();
+
+ /**
+ * Start plugin by platform.
+ * This function will load dynamic plugin library on memory and call start function of plugin to be initialized.
+ *
+ * @param Plugin
+ * @param Platform pointer.
+ * @return int, 1 is success, 0 is fail.
+ */
+ int startbyPlatform(Plugin *const plugin, void *const arg);
+
+ /**
+ * Stop Plugin by platform.
+ * This function will call stop function of plugin and unload dynamic plugin library from memory.
+ *
+ * @param Plugin
+ * @return int, 1 is success, 0 is fail.
+ */
+ int stopbyPlatform(Plugin *const plugin);
+ };
+}
+
+#endif //__PLUGINMANAGERIMPL_H__
\ No newline at end of file
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file PluginManagerService.cpp
-
-/// @brief
-
-#include "PluginManager.h"
-#include <iostream>
-
-using namespace OIC;
-using namespace std;
-using namespace OC;
-
-OCPlatform *g_platform;
-
-void printMenu()
-{
- cout << endl << "====== Menu ======" << endl;
- cout << "1. Set Plugins Directory" << endl;
- cout << "2. Add a Plugin " << endl;
- cout << "3. Delete a Plugin" << endl;
- cout << "4. Start " << endl;
- cout << "5. Stop" << endl;
- cout << "6. List" << endl;
- cout << "0. Exit " << endl << endl;
-}
-
-void loading(const int recursive)
-{
- PluginManager *pm = PluginManager::Getinstance();
- string str;
- if (recursive == 1)
- {
- cout << "Enter Plugins Directory Path = ";
- cin >> str;
- cout << "All plugins in all sub-directories of the path will be added and new ";
- cout << "plugins will be automatically detected and added from now on." << endl;
- cout << "To see the current list of plugins, select \"List\" menu." << endl;
- pm->registerAllPlugin(str);
- }
- else
- {
- cout << "Enter Path of the plugin = ";
- cin >> str;
- pm->registerPlugin(str);
- }
-
-}
-
-void unregister()
-{
- PluginManager *pm = PluginManager::Getinstance();
- Plugin *plugin = new Plugin;
- string str1;
- cout << "Enter Plugin ID = " ;
- cin >> str1;
- plugin->setValue("Id", str1);
- //pm->unregisterPlugin(plugin);
- pm->unregisterAllPlugin();
- delete plugin;
-}
-
-void pluginstart()
-{
- PluginManager *pm = PluginManager::Getinstance();
- Plugin *plugin = new Plugin;
- string str1;
- cout << "Enter the id of the plugin = ";
- cin >> str1;
- plugin->setValue("Id", str1);
- pm->start(plugin, (void *)g_platform);
- delete plugin;
-}
-
-void pluginstop()
-{
- PluginManager *pm = PluginManager::Getinstance();
- Plugin *plugin = new Plugin;
- string str1;
- cout << "Enter the id of the plugin = ";
- cin >> str1;
- plugin->setValue("Id", str1);
- pm->stop(plugin);
- delete plugin;
-}
-
-void printfplugs()
-{
- PluginManager *pm = PluginManager::Getinstance();
- const char format[] = " %-30s %-15s %-15s %-20s\n";
- printf("\n====== Plugins List ======\n");
- printf(format,
- "ID",
- "NAME",
- "STATE",
- "TYPE");
- std::vector<Plugin> plugins = pm->getAllPlugins();
- std::vector<Plugin>::iterator it;
-
- for (it = plugins.begin(); it != plugins.end() ; it++)
- {
- printf(format,
- it->getID().c_str(),
- it->getName().c_str() != NULL ? it->getName().c_str() : "",
- pm->getState(it->getID()).c_str(),
- it->getValueByAttribute("ResourceType").c_str() != NULL ?
- it->getValueByAttribute("ResourceType").c_str() : "");
- }
- printf("\n");
-}
-
-PluginManager *PluginManager::s_pinstance = NULL;
-
-int main(int argc, char *argv[])
-{
- //PluginManager *pm = PluginManager::Getinstance();
- //Setting OCPlatform
- /////////////////////////////////
-
- PlatformConfig cfg
- {
- OC::ServiceType::InProc,
- OC::ModeType::Server,
- "192.168.2.5",
- 5683,
- OC::QualityOfService::NonConfirmable
- };
- /////////////////////////////////
-
- g_platform = new OCPlatform(cfg);
- int num = 0;
- while (true)
- {
- printMenu();
- cout << "Enter the number of Menu = ";
- cin >> num;
- switch (num)
- {
- case 1:
- loading(1);
- break;
- case 2:
- loading(0);
- break;
- case 3:
- unregister();
- break;
- case 4:
- pluginstart();
- break;
- case 5:
- pluginstop();
- break;
- case 6:
- printfplugs();
- break;
- case 0:
- return 0;
- break;
- default:
- cout << "Wrong number." << endl;
- break;
- }
- }
- return 0;
-}
+++ /dev/null
-COMMON_DIR = ../..
-include $(COMMON_DIR)/../../config.mk
-BUILD = release
-
-CXX = g++
-CXX_FLAGS = -g3 -std=c++0x -Wall -pthread
-LDFLAGS = -fPIC -shared
-LIBS = -lpthread -lcurl
-INC = .
-INC+=-I../ -I$(COMMON_DIR)/lib/curl
-
-SRC_DIR = $(COMMON_DIR)/src
-
-SRC_CPP := $(SRC_DIR)/hue_light_sample.cpp
-SRC_CPP += $(SRC_DIR)/HuePlugin.cpp
-SRC_CPP += $(SRC_DIR)/simple_parse.cpp
-SRC_CPP += $(SRC_DIR)/OCResourceDesc.cpp
-SRC_CPP += $(SRC_DIR)/http_curl.cpp
-SRC_CPP += $(SRC_DIR)/HueLightHandler.cpp
-SRC_CPP += $(SRC_DIR)/HueBridge.cpp
-
-OIC_DIR = $(COMMON_DIR)/../../../../resource
-OCLIB_DIR = $(OIC_DIR)/build/linux/$(BUILD)/obj
-CSDK_DIR = $(OIC_DIR)/csdk/build/linux/$(BUILD)
-
-CXX_INC := -I$(OIC_DIR)/include/
-CXX_INC += -I$(OIC_DIR)/csdk/stack/include
-CXX_INC += -I$(OIC_DIR)/csdk/ocsocket/include
-CXX_INC += -I$(OIC_DIR)/csdk/ocrandom/include
-CXX_INC += -I$(OIC_DIR)/csdk/logger/include
-CXX_INC += -I$(BOOST_DIR)
-CXX_INC += -I$(OIC_DIR)/examples/lib
-CXX_INC += -I../../../../lib/cpluff/libcpluff
-
-TARGET_DY_LIB=libplugin-hue-light.so
-
-
-LDFLAGS=-fPIC -shared
-
-
-.PHONY: hue-environment oic-light-client oic-light-server hue-light-plugin
-all: .PHONY
-
-hue-environment:
- -mkdir $(BUILD)
- cp plugin.xml $(BUILD)/
-
-oic-light-client: $(SRC_DIR)/test/client_test.cpp $(OCLIB_DIR)/liboc.a
- $(CXX) $(CXX_FLAGS) -o $(BUILD)/oic-light-client $(SRC_DIR)/test/client_test.cpp $(OCLIB_DIR)/liboc.a $(CSDK_DIR)/liboctbstack.a $(CXX_INC)
-
-oic-light-server: $(SRC_DIR)/test/server_test.cpp $(OCLIB_DIR)/liboc.a
- $(CXX) $(CXX_FLAGS) -o $(BUILD)/oic-light-server $(SRC_DIR)/test/server_test.cpp $(OCLIB_DIR)/liboc.a $(CSDK_DIR)/liboctbstack.a $(CXX_INC)
-
-hue-light-plugin: $(SRC_CPP) $(OCLIB_DIR)/liboc.a
- $(CXX) $(CXX_FLAGS) -o $(BUILD)/$(TARGET_DY_LIB) $^ $(CSDK_DIR)/liboctbstack.a $(CXX_INC) -I $(INC) $(LDFLAGS) $(LIBS)
-
-clean:
- rm -rf release debug
-
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Copyright 2007 Johannes Lehtinen
- * This file is free software; Johannes Lehtinen gives unlimited
- * permission to copy, distribute and modify it.
--->
-<plugin
- id="oic.plugin.hue"
- version="0.1"
- name="hue"
- url="192.168.1.100"
- resourcetype="oic.light"
- provider-name="wallace">
- <runtime library="libplugin-hue-light" funcs="hue_light"/>
-</plugin>
+++ /dev/null
-#ifndef __CURL_CURL_H
-#define __CURL_CURL_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-/*
- * If you have libcurl problems, all docs and details are found here:
- * http://curl.haxx.se/libcurl/
- *
- * curl-library mailing list subscription and unsubscription web interface:
- * http://cool.haxx.se/mailman/listinfo/curl-library/
- */
-
-#include "curlver.h" /* libcurl version defines */
-#include "curlbuild.h" /* libcurl build definitions */
-#include "curlrules.h" /* libcurl rules enforcement */
-
-/*
- * Define WIN32 when build target is Win32 API
- */
-
-#if (defined(_WIN32) || defined(__WIN32__)) && \
- !defined(WIN32) && !defined(__SYMBIAN32__)
-#define WIN32
-#endif
-
-#include <stdio.h>
-#include <limits.h>
-
-#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
-/* Needed for __FreeBSD_version symbol definition */
-#include <osreldate.h>
-#endif
-
-/* The include stuff here below is mainly for time_t! */
-#include <sys/types.h>
-#include <time.h>
-
-#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
-#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || defined(__LWIP_OPT_H__))
-/* The check above prevents the winsock2 inclusion if winsock.h already was
- included, since they can't co-exist without problems */
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#endif
-#endif
-
-/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
- libc5-based Linux systems. Only include it on systems that are known to
- require it! */
-#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
- defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
- defined(ANDROID) || \
- (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
-#include <sys/select.h>
-#endif
-
-#if !defined(WIN32) && !defined(_WIN32_WCE)
-#include <sys/socket.h>
-#endif
-
-#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
-#include <sys/time.h>
-#endif
-
-#ifdef __BEOS__
-#include <support/SupportDefs.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void CURL;
-
-/*
- * Decorate exportable functions for Win32 and Symbian OS DLL linking.
- * This avoids using a .def file for building libcurl.dll.
- */
-#if (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) && \
- !defined(CURL_STATICLIB)
-#if defined(BUILDING_LIBCURL)
-#define CURL_EXTERN __declspec(dllexport)
-#else
-#define CURL_EXTERN __declspec(dllimport)
-#endif
-#else
-
-#ifdef CURL_HIDDEN_SYMBOLS
-/*
- * This definition is used to make external definitions visible in the
- * shared library when symbols are hidden by default. It makes no
- * difference when compiling applications whether this is set or not,
- * only when compiling the library.
- */
-#define CURL_EXTERN CURL_EXTERN_SYMBOL
-#else
-#define CURL_EXTERN
-#endif
-#endif
-
-#ifndef curl_socket_typedef
-/* socket typedef */
-#if defined(WIN32) && !defined(__LWIP_OPT_H__)
-typedef SOCKET curl_socket_t;
-#define CURL_SOCKET_BAD INVALID_SOCKET
-#else
-typedef int curl_socket_t;
-#define CURL_SOCKET_BAD -1
-#endif
-#define curl_socket_typedef
-#endif /* curl_socket_typedef */
-
-struct curl_httppost
-{
- struct curl_httppost *next; /* next entry in the list */
- char *name; /* pointer to allocated name */
- long namelength; /* length of name length */
- char *contents; /* pointer to allocated data contents */
- long contentslength; /* length of contents field */
- char *buffer; /* pointer to allocated buffer contents */
- long bufferlength; /* length of buffer field */
- char *contenttype; /* Content-Type */
- struct curl_slist *contentheader; /* list of extra headers for this form */
- struct curl_httppost *more; /* if one field name has more than one
- file, this link should link to following
- files */
- long flags; /* as defined below */
-#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */
-#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */
-#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer
- do not free in formfree */
-#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer
- do not free in formfree */
-#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */
-#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */
-#define HTTPPOST_CALLBACK (1<<6) /* upload file contents by using the
- regular read callback to get the data
- and pass the given pointer as custom
- pointer */
-
- char *showfilename; /* The file name to show. If not set, the
- actual file name will be used (if this
- is a file part) */
- void *userp; /* custom pointer used for
- HTTPPOST_CALLBACK posts */
-};
-
-typedef int (*curl_progress_callback)(void *clientp,
- double dltotal,
- double dlnow,
- double ultotal,
- double ulnow);
-
-#ifndef CURL_MAX_WRITE_SIZE
-/* Tests have proven that 20K is a very bad buffer size for uploads on
- Windows, while 16K for some odd reason performed a lot better.
- We do the ifndef check to allow this value to easier be changed at build
- time for those who feel adventurous. The practical minimum is about
- 400 bytes since libcurl uses a buffer of this size as a scratch area
- (unrelated to network send operations). */
-#define CURL_MAX_WRITE_SIZE 16384
-#endif
-
-#ifndef CURL_MAX_HTTP_HEADER
-/* The only reason to have a max limit for this is to avoid the risk of a bad
- server feeding libcurl with a never-ending header that will cause reallocs
- infinitely */
-#define CURL_MAX_HTTP_HEADER (100*1024)
-#endif
-
-
-/* This is a magic return code for the write callback that, when returned,
- will signal libcurl to pause receiving on the current transfer. */
-#define CURL_WRITEFUNC_PAUSE 0x10000001
-typedef size_t (*curl_write_callback)(char *buffer,
- size_t size,
- size_t nitems,
- void *outstream);
-
-
-
-/* enumeration of file types */
-typedef enum
-{
- CURLFILETYPE_FILE = 0,
- CURLFILETYPE_DIRECTORY,
- CURLFILETYPE_SYMLINK,
- CURLFILETYPE_DEVICE_BLOCK,
- CURLFILETYPE_DEVICE_CHAR,
- CURLFILETYPE_NAMEDPIPE,
- CURLFILETYPE_SOCKET,
- CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
-
- CURLFILETYPE_UNKNOWN /* should never occur */
-} curlfiletype;
-
-#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0)
-#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1)
-#define CURLFINFOFLAG_KNOWN_TIME (1<<2)
-#define CURLFINFOFLAG_KNOWN_PERM (1<<3)
-#define CURLFINFOFLAG_KNOWN_UID (1<<4)
-#define CURLFINFOFLAG_KNOWN_GID (1<<5)
-#define CURLFINFOFLAG_KNOWN_SIZE (1<<6)
-#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7)
-
-/* Content of this structure depends on information which is known and is
- achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
- page for callbacks returning this structure -- some fields are mandatory,
- some others are optional. The FLAG field has special meaning. */
-struct curl_fileinfo
-{
- char *filename;
- curlfiletype filetype;
- time_t time;
- unsigned int perm;
- int uid;
- int gid;
- curl_off_t size;
- long int hardlinks;
-
- struct
- {
- /* If some of these fields is not NULL, it is a pointer to b_data. */
- char *time;
- char *perm;
- char *user;
- char *group;
- char *target; /* pointer to the target filename of a symlink */
- } strings;
-
- unsigned int flags;
-
- /* used internally */
- char *b_data;
- size_t b_size;
- size_t b_used;
-};
-
-/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
-#define CURL_CHUNK_BGN_FUNC_OK 0
-#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */
-#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */
-
-/* if splitting of data transfer is enabled, this callback is called before
- download of an individual chunk started. Note that parameter "remains" works
- only for FTP wildcard downloading (for now), otherwise is not used */
-typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
- void *ptr,
- int remains);
-
-/* return codes for CURLOPT_CHUNK_END_FUNCTION */
-#define CURL_CHUNK_END_FUNC_OK 0
-#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */
-
-/* If splitting of data transfer is enabled this callback is called after
- download of an individual chunk finished.
- Note! After this callback was set then it have to be called FOR ALL chunks.
- Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
- This is the reason why we don't need "transfer_info" parameter in this
- callback and we are not interested in "remains" parameter too. */
-typedef long (*curl_chunk_end_callback)(void *ptr);
-
-/* return codes for FNMATCHFUNCTION */
-#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */
-#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */
-#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */
-
-/* callback type for wildcard downloading pattern matching. If the
- string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
-typedef int (*curl_fnmatch_callback)(void *ptr,
- const char *pattern,
- const char *string);
-
-/* These are the return codes for the seek callbacks */
-#define CURL_SEEKFUNC_OK 0
-#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */
-#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
- libcurl might try other means instead */
-typedef int (*curl_seek_callback)(void *instream,
- curl_off_t offset,
- int origin); /* 'whence' */
-
-/* This is a return code for the read callback that, when returned, will
- signal libcurl to immediately abort the current transfer. */
-#define CURL_READFUNC_ABORT 0x10000000
-/* This is a return code for the read callback that, when returned, will
- signal libcurl to pause sending data on the current transfer. */
-#define CURL_READFUNC_PAUSE 0x10000001
-
-typedef size_t (*curl_read_callback)(char *buffer,
- size_t size,
- size_t nitems,
- void *instream);
-
-typedef enum
-{
- CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
- CURLSOCKTYPE_LAST /* never use */
-} curlsocktype;
-
-/* The return code from the sockopt_callback can signal information back
- to libcurl: */
-#define CURL_SOCKOPT_OK 0
-#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
- CURLE_ABORTED_BY_CALLBACK */
-#define CURL_SOCKOPT_ALREADY_CONNECTED 2
-
-typedef int (*curl_sockopt_callback)(void *clientp,
- curl_socket_t curlfd,
- curlsocktype purpose);
-
-struct curl_sockaddr
-{
- int family;
- int socktype;
- int protocol;
- unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
- turned really ugly and painful on the systems that
- lack this type */
- struct sockaddr addr;
-};
-
-typedef curl_socket_t
-(*curl_opensocket_callback)(void *clientp,
- curlsocktype purpose,
- struct curl_sockaddr *address);
-
-typedef int
-(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
-
-typedef enum
-{
- CURLIOE_OK, /* I/O operation successful */
- CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
- CURLIOE_FAILRESTART, /* failed to restart the read */
- CURLIOE_LAST /* never use */
-} curlioerr;
-
-typedef enum
-{
- CURLIOCMD_NOP, /* no operation */
- CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
- CURLIOCMD_LAST /* never use */
-} curliocmd;
-
-typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
- int cmd,
- void *clientp);
-
-/*
- * The following typedef's are signatures of malloc, free, realloc, strdup and
- * calloc respectively. Function pointers of these types can be passed to the
- * curl_global_init_mem() function to set user defined memory management
- * callback routines.
- */
-typedef void *(*curl_malloc_callback)(size_t size);
-typedef void (*curl_free_callback)(void *ptr);
-typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
-typedef char *(*curl_strdup_callback)(const char *str);
-typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
-
-/* the kind of data that is passed to information_callback*/
-typedef enum
-{
- CURLINFO_TEXT = 0,
- CURLINFO_HEADER_IN, /* 1 */
- CURLINFO_HEADER_OUT, /* 2 */
- CURLINFO_DATA_IN, /* 3 */
- CURLINFO_DATA_OUT, /* 4 */
- CURLINFO_SSL_DATA_IN, /* 5 */
- CURLINFO_SSL_DATA_OUT, /* 6 */
- CURLINFO_END
-} curl_infotype;
-
-typedef int (*curl_debug_callback)
-(CURL *handle, /* the handle/transfer this concerns */
- curl_infotype type, /* what kind of data */
- char *data, /* points to the data */
- size_t size, /* size of the data pointed to */
- void *userptr); /* whatever the user please */
-
-/* All possible error codes from all sorts of curl functions. Future versions
- may return other values, stay prepared.
-
- Always add new return codes last. Never *EVER* remove any. The return
- codes must remain the same!
- */
-
-typedef enum
-{
- CURLE_OK = 0,
- CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
- CURLE_FAILED_INIT, /* 2 */
- CURLE_URL_MALFORMAT, /* 3 */
- CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for
- 7.17.0, reused in April 2011 for 7.21.5] */
- CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
- CURLE_COULDNT_RESOLVE_HOST, /* 6 */
- CURLE_COULDNT_CONNECT, /* 7 */
- CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
- CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server
- due to lack of access - when login fails
- this is not returned. */
- CURLE_OBSOLETE10, /* 10 - NOT USED */
- CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
- CURLE_OBSOLETE12, /* 12 - NOT USED */
- CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
- CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
- CURLE_FTP_CANT_GET_HOST, /* 15 */
- CURLE_OBSOLETE16, /* 16 - NOT USED */
- CURLE_FTP_COULDNT_SET_TYPE, /* 17 */
- CURLE_PARTIAL_FILE, /* 18 */
- CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
- CURLE_OBSOLETE20, /* 20 - NOT USED */
- CURLE_QUOTE_ERROR, /* 21 - quote command failure */
- CURLE_HTTP_RETURNED_ERROR, /* 22 */
- CURLE_WRITE_ERROR, /* 23 */
- CURLE_OBSOLETE24, /* 24 - NOT USED */
- CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */
- CURLE_READ_ERROR, /* 26 - couldn't open/read from file */
- CURLE_OUT_OF_MEMORY, /* 27 */
- /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
- instead of a memory allocation error if CURL_DOES_CONVERSIONS
- is defined
- */
- CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */
- CURLE_OBSOLETE29, /* 29 - NOT USED */
- CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
- CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */
- CURLE_OBSOLETE32, /* 32 - NOT USED */
- CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */
- CURLE_HTTP_POST_ERROR, /* 34 */
- CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */
- CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */
- CURLE_FILE_COULDNT_READ_FILE, /* 37 */
- CURLE_LDAP_CANNOT_BIND, /* 38 */
- CURLE_LDAP_SEARCH_FAILED, /* 39 */
- CURLE_OBSOLETE40, /* 40 - NOT USED */
- CURLE_FUNCTION_NOT_FOUND, /* 41 */
- CURLE_ABORTED_BY_CALLBACK, /* 42 */
- CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
- CURLE_OBSOLETE44, /* 44 - NOT USED */
- CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */
- CURLE_OBSOLETE46, /* 46 - NOT USED */
- CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
- CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
- CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
- CURLE_OBSOLETE50, /* 50 - NOT USED */
- CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
- wasn't verified fine */
- CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
- CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
- CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as
- default */
- CURLE_SEND_ERROR, /* 55 - failed sending network data */
- CURLE_RECV_ERROR, /* 56 - failure in receiving network data */
- CURLE_OBSOLETE57, /* 57 - NOT IN USE */
- CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */
- CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */
- CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */
- CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */
- CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
- CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
- CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
- CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind
- that failed */
- CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
- CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
- accepted and we failed to login */
- CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */
- CURLE_TFTP_PERM, /* 69 - permission problem on server */
- CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */
- CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */
- CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
- CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */
- CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
- CURLE_CONV_FAILED, /* 75 - conversion failed */
- CURLE_CONV_REQD, /* 76 - caller must register conversion
- callbacks using curl_easy_setopt options
- CURLOPT_CONV_FROM_NETWORK_FUNCTION,
- CURLOPT_CONV_TO_NETWORK_FUNCTION, and
- CURLOPT_CONV_FROM_UTF8_FUNCTION */
- CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
- or wrong format */
- CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */
- CURLE_SSH, /* 79 - error from the SSH layer, somewhat
- generic so the error message will be of
- interest when this has happened */
-
- CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL
- connection */
- CURLE_AGAIN, /* 81 - socket is not ready for send/recv,
- wait till it's ready and try again (Added
- in 7.18.2) */
- CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or
- wrong format (Added in 7.19.0) */
- CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in
- 7.19.0) */
- CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
- CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */
- CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */
- CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */
- CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */
-
- CURL_LAST /* never use! */
-} CURLcode;
-
-#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
- the obsolete stuff removed! */
-
-/* compatibility with older names */
-#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
-
-/* The following were added in 7.21.5, April 2011 */
-#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
-
-/* The following were added in 7.17.1 */
-/* These are scheduled to disappear by 2009 */
-#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
-
-/* The following were added in 7.17.0 */
-/* These are scheduled to disappear by 2009 */
-#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */
-#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
-#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
-#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
-#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16
-#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32
-#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29
-#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12
-#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20
-#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40
-#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24
-#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57
-#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN
-
-#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED
-#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE
-#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
-#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
-#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
-#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
-#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
-
-/* The following were added earlier */
-
-#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT
-
-#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
-#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
-#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED
-
-#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
-#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
-
-/* This was the error code 50 in 7.7.3 and a few earlier versions, this
- is no longer used by libcurl but is instead #defined here only to not
- make programs break */
-#define CURLE_ALREADY_COMPLETE 99999
-
-#endif /*!CURL_NO_OLDIES*/
-
-/* This prototype applies to all conversion callbacks */
-typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
-
-typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
- void *ssl_ctx, /* actually an
- OpenSSL SSL_CTX */
- void *userptr);
-
-typedef enum
-{
- CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use
- CONNECT HTTP/1.1 */
- CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
- HTTP/1.0 */
- CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
- in 7.10 */
- CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
- CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
- CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
- host name rather than the IP address. added
- in 7.18.0 */
-} curl_proxytype; /* this enum was added in 7.10 */
-
-#define CURLAUTH_NONE 0 /* nothing */
-#define CURLAUTH_BASIC (1<<0) /* Basic (default) */
-#define CURLAUTH_DIGEST (1<<1) /* Digest */
-#define CURLAUTH_GSSNEGOTIATE (1<<2) /* GSS-Negotiate */
-#define CURLAUTH_NTLM (1<<3) /* NTLM */
-#define CURLAUTH_DIGEST_IE (1<<4) /* Digest with IE flavour */
-#define CURLAUTH_NTLM_WB (1<<5) /* NTLM delegating to winbind helper */
-#define CURLAUTH_ONLY (1<<31) /* used together with a single other
- type to force no auth or just that
- single type */
-#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) /* all fine types set */
-#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
-
-#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */
-#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */
-#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */
-#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */
-#define CURLSSH_AUTH_HOST (1<<2) /* host key files */
-#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */
-#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
-
-#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */
-#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */
-#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */
-
-#define CURL_ERROR_SIZE 256
-
-struct curl_khkey
-{
- const char *key; /* points to a zero-terminated string encoded with base64
- if len is zero, otherwise to the "raw" data */
- size_t len;
- enum type
- {
- CURLKHTYPE_UNKNOWN,
- CURLKHTYPE_RSA1,
- CURLKHTYPE_RSA,
- CURLKHTYPE_DSS
- } keytype;
-};
-
-/* this is the set of return values expected from the curl_sshkeycallback
- callback */
-enum curl_khstat
-{
- CURLKHSTAT_FINE_ADD_TO_FILE,
- CURLKHSTAT_FINE,
- CURLKHSTAT_REJECT, /* reject the connection, return an error */
- CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so
- this causes a CURLE_DEFER error but otherwise the
- connection will be left intact etc */
- CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */
-};
-
-/* this is the set of status codes pass in to the callback */
-enum curl_khmatch
-{
- CURLKHMATCH_OK, /* match */
- CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
- CURLKHMATCH_MISSING, /* no matching host/key found */
- CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */
-};
-
-typedef int
-(*curl_sshkeycallback) (CURL *easy, /* easy handle */
- const struct curl_khkey *knownkey, /* known */
- const struct curl_khkey *foundkey, /* found */
- enum curl_khmatch, /* libcurl's view on the keys */
- void *clientp); /* custom pointer passed from app */
-
-/* parameter for the CURLOPT_USE_SSL option */
-typedef enum
-{
- CURLUSESSL_NONE, /* do not attempt to use SSL */
- CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */
- CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
- CURLUSESSL_ALL, /* SSL for all communication or fail */
- CURLUSESSL_LAST /* not an option, never use */
-} curl_usessl;
-
-#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
- the obsolete stuff removed! */
-
-/* Backwards compatibility with older names */
-/* These are scheduled to disappear by 2009 */
-
-#define CURLFTPSSL_NONE CURLUSESSL_NONE
-#define CURLFTPSSL_TRY CURLUSESSL_TRY
-#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL
-#define CURLFTPSSL_ALL CURLUSESSL_ALL
-#define CURLFTPSSL_LAST CURLUSESSL_LAST
-#define curl_ftpssl curl_usessl
-#endif /*!CURL_NO_OLDIES*/
-
-/* parameter for the CURLOPT_FTP_SSL_CCC option */
-typedef enum
-{
- CURLFTPSSL_CCC_NONE, /* do not send CCC */
- CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
- CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */
- CURLFTPSSL_CCC_LAST /* not an option, never use */
-} curl_ftpccc;
-
-/* parameter for the CURLOPT_FTPSSLAUTH option */
-typedef enum
-{
- CURLFTPAUTH_DEFAULT, /* let libcurl decide */
- CURLFTPAUTH_SSL, /* use "AUTH SSL" */
- CURLFTPAUTH_TLS, /* use "AUTH TLS" */
- CURLFTPAUTH_LAST /* not an option, never use */
-} curl_ftpauth;
-
-/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
-typedef enum
-{
- CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */
- CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD
- again if MKD succeeded, for SFTP this does
- similar magic */
- CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD
- again even if MKD failed! */
- CURLFTP_CREATE_DIR_LAST /* not an option, never use */
-} curl_ftpcreatedir;
-
-/* parameter for the CURLOPT_FTP_FILEMETHOD option */
-typedef enum
-{
- CURLFTPMETHOD_DEFAULT, /* let libcurl pick */
- CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */
- CURLFTPMETHOD_NOCWD, /* no CWD at all */
- CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
- CURLFTPMETHOD_LAST /* not an option, never use */
-} curl_ftpmethod;
-
-/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
-#define CURLPROTO_HTTP (1<<0)
-#define CURLPROTO_HTTPS (1<<1)
-#define CURLPROTO_FTP (1<<2)
-#define CURLPROTO_FTPS (1<<3)
-#define CURLPROTO_SCP (1<<4)
-#define CURLPROTO_SFTP (1<<5)
-#define CURLPROTO_TELNET (1<<6)
-#define CURLPROTO_LDAP (1<<7)
-#define CURLPROTO_LDAPS (1<<8)
-#define CURLPROTO_DICT (1<<9)
-#define CURLPROTO_FILE (1<<10)
-#define CURLPROTO_TFTP (1<<11)
-#define CURLPROTO_IMAP (1<<12)
-#define CURLPROTO_IMAPS (1<<13)
-#define CURLPROTO_POP3 (1<<14)
-#define CURLPROTO_POP3S (1<<15)
-#define CURLPROTO_SMTP (1<<16)
-#define CURLPROTO_SMTPS (1<<17)
-#define CURLPROTO_RTSP (1<<18)
-#define CURLPROTO_RTMP (1<<19)
-#define CURLPROTO_RTMPT (1<<20)
-#define CURLPROTO_RTMPE (1<<21)
-#define CURLPROTO_RTMPTE (1<<22)
-#define CURLPROTO_RTMPS (1<<23)
-#define CURLPROTO_RTMPTS (1<<24)
-#define CURLPROTO_GOPHER (1<<25)
-#define CURLPROTO_ALL (~0) /* enable everything */
-
-/* long may be 32 or 64 bits, but we should never depend on anything else
- but 32 */
-#define CURLOPTTYPE_LONG 0
-#define CURLOPTTYPE_OBJECTPOINT 10000
-#define CURLOPTTYPE_FUNCTIONPOINT 20000
-#define CURLOPTTYPE_OFF_T 30000
-
-/* name is uppercase CURLOPT_<name>,
- type is one of the defined CURLOPTTYPE_<type>
- number is unique identifier */
-#ifdef CINIT
-#undef CINIT
-#endif
-
-#ifdef CURL_ISOCPP
-#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
-#else
-/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
-#define LONG CURLOPTTYPE_LONG
-#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
-#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
-#define OFF_T CURLOPTTYPE_OFF_T
-#define CINIT(name,type,number) CURLOPT_/**/name = type + number
-#endif
-
-/*
- * This macro-mania below setups the CURLOPT_[what] enum, to be used with
- * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
- * word.
- */
-
-typedef enum
-{
- /* This is the FILE * or void * the regular output should be written to. */
- CINIT(FILE, OBJECTPOINT, 1),
-
- /* The full URL to get/put */
- CINIT(URL, OBJECTPOINT, 2),
-
- /* Port number to connect to, if other than default. */
- CINIT(PORT, LONG, 3),
-
- /* Name of proxy to use. */
- CINIT(PROXY, OBJECTPOINT, 4),
-
- /* "name:password" to use when fetching. */
- CINIT(USERPWD, OBJECTPOINT, 5),
-
- /* "name:password" to use with proxy. */
- CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
-
- /* Range to get, specified as an ASCII string. */
- CINIT(RANGE, OBJECTPOINT, 7),
-
- /* not used */
-
- /* Specified file stream to upload from (use as input): */
- CINIT(INFILE, OBJECTPOINT, 9),
-
- /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
- * bytes big. If this is not used, error messages go to stderr instead: */
- CINIT(ERRORBUFFER, OBJECTPOINT, 10),
-
- /* Function that will be called to store the output (instead of fwrite). The
- * parameters will use fwrite() syntax, make sure to follow them. */
- CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
-
- /* Function that will be called to read the input (instead of fread). The
- * parameters will use fread() syntax, make sure to follow them. */
- CINIT(READFUNCTION, FUNCTIONPOINT, 12),
-
- /* Time-out the read operation after this amount of seconds */
- CINIT(TIMEOUT, LONG, 13),
-
- /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
- * how large the file being sent really is. That allows better error
- * checking and better verifies that the upload was successful. -1 means
- * unknown size.
- *
- * For large file support, there is also a _LARGE version of the key
- * which takes an off_t type, allowing platforms with larger off_t
- * sizes to handle larger files. See below for INFILESIZE_LARGE.
- */
- CINIT(INFILESIZE, LONG, 14),
-
- /* POST static input fields. */
- CINIT(POSTFIELDS, OBJECTPOINT, 15),
-
- /* Set the referrer page (needed by some CGIs) */
- CINIT(REFERER, OBJECTPOINT, 16),
-
- /* Set the FTP PORT string (interface name, named or numerical IP address)
- Use i.e '-' to use default address. */
- CINIT(FTPPORT, OBJECTPOINT, 17),
-
- /* Set the User-Agent string (examined by some CGIs) */
- CINIT(USERAGENT, OBJECTPOINT, 18),
-
- /* If the download receives less than "low speed limit" bytes/second
- * during "low speed time" seconds, the operations is aborted.
- * You could i.e if you have a pretty high speed connection, abort if
- * it is less than 2000 bytes/sec during 20 seconds.
- */
-
- /* Set the "low speed limit" */
- CINIT(LOW_SPEED_LIMIT, LONG, 19),
-
- /* Set the "low speed time" */
- CINIT(LOW_SPEED_TIME, LONG, 20),
-
- /* Set the continuation offset.
- *
- * Note there is also a _LARGE version of this key which uses
- * off_t types, allowing for large file offsets on platforms which
- * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE.
- */
- CINIT(RESUME_FROM, LONG, 21),
-
- /* Set cookie in request: */
- CINIT(COOKIE, OBJECTPOINT, 22),
-
- /* This points to a linked list of headers, struct curl_slist kind */
- CINIT(HTTPHEADER, OBJECTPOINT, 23),
-
- /* This points to a linked list of post entries, struct curl_httppost */
- CINIT(HTTPPOST, OBJECTPOINT, 24),
-
- /* name of the file keeping your private SSL-certificate */
- CINIT(SSLCERT, OBJECTPOINT, 25),
-
- /* password for the SSL or SSH private key */
- CINIT(KEYPASSWD, OBJECTPOINT, 26),
-
- /* send TYPE parameter? */
- CINIT(CRLF, LONG, 27),
-
- /* send linked-list of QUOTE commands */
- CINIT(QUOTE, OBJECTPOINT, 28),
-
- /* send FILE * or void * to store headers to, if you use a callback it
- is simply passed to the callback unmodified */
- CINIT(WRITEHEADER, OBJECTPOINT, 29),
-
- /* point to a file to read the initial cookies from, also enables
- "cookie awareness" */
- CINIT(COOKIEFILE, OBJECTPOINT, 31),
-
- /* What version to specifically try to use.
- See CURL_SSLVERSION defines below. */
- CINIT(SSLVERSION, LONG, 32),
-
- /* What kind of HTTP time condition to use, see defines */
- CINIT(TIMECONDITION, LONG, 33),
-
- /* Time to use with the above condition. Specified in number of seconds
- since 1 Jan 1970 */
- CINIT(TIMEVALUE, LONG, 34),
-
- /* 35 = OBSOLETE */
-
- /* Custom request, for customizing the get command like
- HTTP: DELETE, TRACE and others
- FTP: to use a different list command
- */
- CINIT(CUSTOMREQUEST, OBJECTPOINT, 36),
-
- /* HTTP request, for odd commands like DELETE, TRACE and others */
- CINIT(STDERR, OBJECTPOINT, 37),
-
- /* 38 is not used */
-
- /* send linked-list of post-transfer QUOTE commands */
- CINIT(POSTQUOTE, OBJECTPOINT, 39),
-
- CINIT(WRITEINFO, OBJECTPOINT, 40), /* DEPRECATED, do not use! */
-
- CINIT(VERBOSE, LONG, 41), /* talk a lot */
- CINIT(HEADER, LONG, 42), /* throw the header out too */
- CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */
- CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */
- CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */
- CINIT(UPLOAD, LONG, 46), /* this is an upload */
- CINIT(POST, LONG, 47), /* HTTP POST method */
- CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */
-
- CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */
-
- /* Specify whether to read the user+password from the .netrc or the URL.
- * This must be one of the CURL_NETRC_* enums below. */
- CINIT(NETRC, LONG, 51),
-
- CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
-
- CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
- CINIT(PUT, LONG, 54), /* HTTP PUT */
-
- /* 55 = OBSOLETE */
-
- /* Function that will be called instead of the internal progress display
- * function. This function should be defined as the curl_progress_callback
- * prototype defines. */
- CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
-
- /* Data passed to the progress callback */
- CINIT(PROGRESSDATA, OBJECTPOINT, 57),
-
- /* We want the referrer field set automatically when following locations */
- CINIT(AUTOREFERER, LONG, 58),
-
- /* Port of the proxy, can be set in the proxy string as well with:
- "[host]:[port]" */
- CINIT(PROXYPORT, LONG, 59),
-
- /* size of the POST input data, if strlen() is not good to use */
- CINIT(POSTFIELDSIZE, LONG, 60),
-
- /* tunnel non-http operations through a HTTP proxy */
- CINIT(HTTPPROXYTUNNEL, LONG, 61),
-
- /* Set the interface string to use as outgoing network interface */
- CINIT(INTERFACE, OBJECTPOINT, 62),
-
- /* Set the krb4/5 security level, this also enables krb4/5 awareness. This
- * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string
- * is set but doesn't match one of these, 'private' will be used. */
- CINIT(KRBLEVEL, OBJECTPOINT, 63),
-
- /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
- CINIT(SSL_VERIFYPEER, LONG, 64),
-
- /* The CApath or CAfile used to validate the peer certificate
- this option is used only if SSL_VERIFYPEER is true */
- CINIT(CAINFO, OBJECTPOINT, 65),
-
- /* 66 = OBSOLETE */
- /* 67 = OBSOLETE */
-
- /* Maximum number of http redirects to follow */
- CINIT(MAXREDIRS, LONG, 68),
-
- /* Pass a long set to 1 to get the date of the requested document (if
- possible)! Pass a zero to shut it off. */
- CINIT(FILETIME, LONG, 69),
-
- /* This points to a linked list of telnet options */
- CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
-
- /* Max amount of cached alive connections */
- CINIT(MAXCONNECTS, LONG, 71),
-
- CINIT(CLOSEPOLICY, LONG, 72), /* DEPRECATED, do not use! */
-
- /* 73 = OBSOLETE */
-
- /* Set to explicitly use a new connection for the upcoming transfer.
- Do not use this unless you're absolutely sure of this, as it makes the
- operation slower and is less friendly for the network. */
- CINIT(FRESH_CONNECT, LONG, 74),
-
- /* Set to explicitly forbid the upcoming transfer's connection to be re-used
- when done. Do not use this unless you're absolutely sure of this, as it
- makes the operation slower and is less friendly for the network. */
- CINIT(FORBID_REUSE, LONG, 75),
-
- /* Set to a file name that contains random data for libcurl to use to
- seed the random engine when doing SSL connects. */
- CINIT(RANDOM_FILE, OBJECTPOINT, 76),
-
- /* Set to the Entropy Gathering Daemon socket pathname */
- CINIT(EGDSOCKET, OBJECTPOINT, 77),
-
- /* Time-out connect operations after this amount of seconds, if connects
- are OK within this time, then fine... This only aborts the connect
- phase. [Only works on unix-style/SIGALRM operating systems] */
- CINIT(CONNECTTIMEOUT, LONG, 78),
-
- /* Function that will be called to store headers (instead of fwrite). The
- * parameters will use fwrite() syntax, make sure to follow them. */
- CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
-
- /* Set this to force the HTTP request to get back to GET. Only really usable
- if POST, PUT or a custom request have been used first.
- */
- CINIT(HTTPGET, LONG, 80),
-
- /* Set if we should verify the Common name from the peer certificate in ssl
- * handshake, set 1 to check existence, 2 to ensure that it matches the
- * provided hostname. */
- CINIT(SSL_VERIFYHOST, LONG, 81),
-
- /* Specify which file name to write all known cookies in after completed
- operation. Set file name to "-" (dash) to make it go to stdout. */
- CINIT(COOKIEJAR, OBJECTPOINT, 82),
-
- /* Specify which SSL ciphers to use */
- CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83),
-
- /* Specify which HTTP version to use! This must be set to one of the
- CURL_HTTP_VERSION* enums set below. */
- CINIT(HTTP_VERSION, LONG, 84),
-
- /* Specifically switch on or off the FTP engine's use of the EPSV command. By
- default, that one will always be attempted before the more traditional
- PASV command. */
- CINIT(FTP_USE_EPSV, LONG, 85),
-
- /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
- CINIT(SSLCERTTYPE, OBJECTPOINT, 86),
-
- /* name of the file keeping your private SSL-key */
- CINIT(SSLKEY, OBJECTPOINT, 87),
-
- /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
- CINIT(SSLKEYTYPE, OBJECTPOINT, 88),
-
- /* crypto engine for the SSL-sub system */
- CINIT(SSLENGINE, OBJECTPOINT, 89),
-
- /* set the crypto engine for the SSL-sub system as default
- the param has no meaning...
- */
- CINIT(SSLENGINE_DEFAULT, LONG, 90),
-
- /* Non-zero value means to use the global dns cache */
- CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
-
- /* DNS cache timeout */
- CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
-
- /* send linked-list of pre-transfer QUOTE commands */
- CINIT(PREQUOTE, OBJECTPOINT, 93),
-
- /* set the debug function */
- CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
-
- /* set the data for the debug function */
- CINIT(DEBUGDATA, OBJECTPOINT, 95),
-
- /* mark this as start of a cookie session */
- CINIT(COOKIESESSION, LONG, 96),
-
- /* The CApath directory used to validate the peer certificate
- this option is used only if SSL_VERIFYPEER is true */
- CINIT(CAPATH, OBJECTPOINT, 97),
-
- /* Instruct libcurl to use a smaller receive buffer */
- CINIT(BUFFERSIZE, LONG, 98),
-
- /* Instruct libcurl to not use any signal/alarm handlers, even when using
- timeouts. This option is useful for multi-threaded applications.
- See libcurl-the-guide for more background information. */
- CINIT(NOSIGNAL, LONG, 99),
-
- /* Provide a CURLShare for mutexing non-ts data */
- CINIT(SHARE, OBJECTPOINT, 100),
-
- /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
- CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
- CINIT(PROXYTYPE, LONG, 101),
-
- /* Set the Accept-Encoding string. Use this to tell a server you would like
- the response to be compressed. Before 7.21.6, this was known as
- CURLOPT_ENCODING */
- CINIT(ACCEPT_ENCODING, OBJECTPOINT, 102),
-
- /* Set pointer to private data */
- CINIT(PRIVATE, OBJECTPOINT, 103),
-
- /* Set aliases for HTTP 200 in the HTTP Response header */
- CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
-
- /* Continue to send authentication (user+password) when following locations,
- even when hostname changed. This can potentially send off the name
- and password to whatever host the server decides. */
- CINIT(UNRESTRICTED_AUTH, LONG, 105),
-
- /* Specifically switch on or off the FTP engine's use of the EPRT command (
- it also disables the LPRT attempt). By default, those ones will always be
- attempted before the good old traditional PORT command. */
- CINIT(FTP_USE_EPRT, LONG, 106),
-
- /* Set this to a bitmask value to enable the particular authentications
- methods you like. Use this in combination with CURLOPT_USERPWD.
- Note that setting multiple bits may cause extra network round-trips. */
- CINIT(HTTPAUTH, LONG, 107),
-
- /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx
- in second argument. The function must be matching the
- curl_ssl_ctx_callback proto. */
- CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
-
- /* Set the userdata for the ssl context callback function's third
- argument */
- CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
-
- /* FTP Option that causes missing dirs to be created on the remote server.
- In 7.19.4 we introduced the convenience enums for this option using the
- CURLFTP_CREATE_DIR prefix.
- */
- CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
-
- /* Set this to a bitmask value to enable the particular authentications
- methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
- Note that setting multiple bits may cause extra network round-trips. */
- CINIT(PROXYAUTH, LONG, 111),
-
- /* FTP option that changes the timeout, in seconds, associated with
- getting a response. This is different from transfer timeout time and
- essentially places a demand on the FTP server to acknowledge commands
- in a timely manner. */
- CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
-#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
-
- /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
- tell libcurl to resolve names to those IP versions only. This only has
- affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
- CINIT(IPRESOLVE, LONG, 113),
-
- /* Set this option to limit the size of a file that will be downloaded from
- an HTTP or FTP server.
-
- Note there is also _LARGE version which adds large file support for
- platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */
- CINIT(MAXFILESIZE, LONG, 114),
-
- /* See the comment for INFILESIZE above, but in short, specifies
- * the size of the file being uploaded. -1 means unknown.
- */
- CINIT(INFILESIZE_LARGE, OFF_T, 115),
-
- /* Sets the continuation offset. There is also a LONG version of this;
- * look above for RESUME_FROM.
- */
- CINIT(RESUME_FROM_LARGE, OFF_T, 116),
-
- /* Sets the maximum size of data that will be downloaded from
- * an HTTP or FTP server. See MAXFILESIZE above for the LONG version.
- */
- CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
-
- /* Set this option to the file name of your .netrc file you want libcurl
- to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
- a poor attempt to find the user's home directory and check for a .netrc
- file in there. */
- CINIT(NETRC_FILE, OBJECTPOINT, 118),
-
- /* Enable SSL/TLS for FTP, pick one of:
- CURLFTPSSL_TRY - try using SSL, proceed anyway otherwise
- CURLFTPSSL_CONTROL - SSL for the control connection or fail
- CURLFTPSSL_ALL - SSL for all communication or fail
- */
- CINIT(USE_SSL, LONG, 119),
-
- /* The _LARGE version of the standard POSTFIELDSIZE option */
- CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
-
- /* Enable/disable the TCP Nagle algorithm */
- CINIT(TCP_NODELAY, LONG, 121),
-
- /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
- /* 123 OBSOLETE. Gone in 7.16.0 */
- /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
- /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
- /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
- /* 127 OBSOLETE. Gone in 7.16.0 */
- /* 128 OBSOLETE. Gone in 7.16.0 */
-
- /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option
- can be used to change libcurl's default action which is to first try
- "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
- response has been received.
-
- Available parameters are:
- CURLFTPAUTH_DEFAULT - let libcurl decide
- CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS
- CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL
- */
- CINIT(FTPSSLAUTH, LONG, 129),
-
- CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
- CINIT(IOCTLDATA, OBJECTPOINT, 131),
-
- /* 132 OBSOLETE. Gone in 7.16.0 */
- /* 133 OBSOLETE. Gone in 7.16.0 */
-
- /* zero terminated string for pass on to the FTP server when asked for
- "account" info */
- CINIT(FTP_ACCOUNT, OBJECTPOINT, 134),
-
- /* feed cookies into cookie engine */
- CINIT(COOKIELIST, OBJECTPOINT, 135),
-
- /* ignore Content-Length */
- CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
-
- /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
- response. Typically used for FTP-SSL purposes but is not restricted to
- that. libcurl will then instead use the same IP address it used for the
- control connection. */
- CINIT(FTP_SKIP_PASV_IP, LONG, 137),
-
- /* Select "file method" to use when doing FTP, see the curl_ftpmethod
- above. */
- CINIT(FTP_FILEMETHOD, LONG, 138),
-
- /* Local port number to bind the socket to */
- CINIT(LOCALPORT, LONG, 139),
-
- /* Number of ports to try, including the first one set with LOCALPORT.
- Thus, setting it to 1 will make no additional attempts but the first.
- */
- CINIT(LOCALPORTRANGE, LONG, 140),
-
- /* no transfer, set up connection and let application use the socket by
- extracting it with CURLINFO_LASTSOCKET */
- CINIT(CONNECT_ONLY, LONG, 141),
-
- /* Function that will be called to convert from the
- network encoding (instead of using the iconv calls in libcurl) */
- CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
-
- /* Function that will be called to convert to the
- network encoding (instead of using the iconv calls in libcurl) */
- CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
-
- /* Function that will be called to convert from UTF8
- (instead of using the iconv calls in libcurl)
- Note that this is used only for SSL certificate processing */
- CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
-
- /* if the connection proceeds too quickly then need to slow it down */
- /* limit-rate: maximum number of bytes per second to send or receive */
- CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
- CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
-
- /* Pointer to command string to send if USER/PASS fails. */
- CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147),
-
- /* callback function for setting socket options */
- CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
- CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
-
- /* set to 0 to disable session ID re-use for this transfer, default is
- enabled (== 1) */
- CINIT(SSL_SESSIONID_CACHE, LONG, 150),
-
- /* allowed SSH authentication methods */
- CINIT(SSH_AUTH_TYPES, LONG, 151),
-
- /* Used by scp/sftp to do public/private key authentication */
- CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152),
- CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153),
-
- /* Send CCC (Clear Command Channel) after authentication */
- CINIT(FTP_SSL_CCC, LONG, 154),
-
- /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
- CINIT(TIMEOUT_MS, LONG, 155),
- CINIT(CONNECTTIMEOUT_MS, LONG, 156),
-
- /* set to zero to disable the libcurl's decoding and thus pass the raw body
- data to the application even when it is encoded/compressed */
- CINIT(HTTP_TRANSFER_DECODING, LONG, 157),
- CINIT(HTTP_CONTENT_DECODING, LONG, 158),
-
- /* Permission used when creating new files and directories on the remote
- server for protocols that support it, SFTP/SCP/FILE */
- CINIT(NEW_FILE_PERMS, LONG, 159),
- CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
-
- /* Set the behaviour of POST when redirecting. Values must be set to one
- of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
- CINIT(POSTREDIR, LONG, 161),
-
- /* used by scp/sftp to verify the host's public key */
- CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162),
-
- /* Callback function for opening socket (instead of socket(2)). Optionally,
- callback is able change the address or refuse to connect returning
- CURL_SOCKET_BAD. The callback should have type
- curl_opensocket_callback */
- CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
- CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
-
- /* POST volatile input fields. */
- CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
-
- /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
- CINIT(PROXY_TRANSFER_MODE, LONG, 166),
-
- /* Callback function for seeking in the input stream */
- CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
- CINIT(SEEKDATA, OBJECTPOINT, 168),
-
- /* CRL file */
- CINIT(CRLFILE, OBJECTPOINT, 169),
-
- /* Issuer certificate */
- CINIT(ISSUERCERT, OBJECTPOINT, 170),
-
- /* (IPv6) Address scope */
- CINIT(ADDRESS_SCOPE, LONG, 171),
-
- /* Collect certificate chain info and allow it to get retrievable with
- CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only
- working with OpenSSL-powered builds. */
- CINIT(CERTINFO, LONG, 172),
-
- /* "name" and "pwd" to use when fetching. */
- CINIT(USERNAME, OBJECTPOINT, 173),
- CINIT(PASSWORD, OBJECTPOINT, 174),
-
- /* "name" and "pwd" to use with Proxy when fetching. */
- CINIT(PROXYUSERNAME, OBJECTPOINT, 175),
- CINIT(PROXYPASSWORD, OBJECTPOINT, 176),
-
- /* Comma separated list of hostnames defining no-proxy zones. These should
- match both hostnames directly, and hostnames within a domain. For
- example, local.com will match local.com and www.local.com, but NOT
- notlocal.com or www.notlocal.com. For compatibility with other
- implementations of this, .local.com will be considered to be the same as
- local.com. A single * is the only valid wildcard, and effectively
- disables the use of proxy. */
- CINIT(NOPROXY, OBJECTPOINT, 177),
-
- /* block size for TFTP transfers */
- CINIT(TFTP_BLKSIZE, LONG, 178),
-
- /* Socks Service */
- CINIT(SOCKS5_GSSAPI_SERVICE, OBJECTPOINT, 179),
-
- /* Socks Service */
- CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
-
- /* set the bitmask for the protocols that are allowed to be used for the
- transfer, which thus helps the app which takes URLs from users or other
- external inputs and want to restrict what protocol(s) to deal
- with. Defaults to CURLPROTO_ALL. */
- CINIT(PROTOCOLS, LONG, 181),
-
- /* set the bitmask for the protocols that libcurl is allowed to follow to,
- as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
- to be set in both bitmasks to be allowed to get redirected to. Defaults
- to all protocols except FILE and SCP. */
- CINIT(REDIR_PROTOCOLS, LONG, 182),
-
- /* set the SSH knownhost file name to use */
- CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183),
-
- /* set the SSH host key callback, must point to a curl_sshkeycallback
- function */
- CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
-
- /* set the SSH host key callback custom pointer */
- CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
-
- /* set the SMTP mail originator */
- CINIT(MAIL_FROM, OBJECTPOINT, 186),
-
- /* set the SMTP mail receiver(s) */
- CINIT(MAIL_RCPT, OBJECTPOINT, 187),
-
- /* FTP: send PRET before PASV */
- CINIT(FTP_USE_PRET, LONG, 188),
-
- /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
- CINIT(RTSP_REQUEST, LONG, 189),
-
- /* The RTSP session identifier */
- CINIT(RTSP_SESSION_ID, OBJECTPOINT, 190),
-
- /* The RTSP stream URI */
- CINIT(RTSP_STREAM_URI, OBJECTPOINT, 191),
-
- /* The Transport: header to use in RTSP requests */
- CINIT(RTSP_TRANSPORT, OBJECTPOINT, 192),
-
- /* Manually initialize the client RTSP CSeq for this handle */
- CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
-
- /* Manually initialize the server RTSP CSeq for this handle */
- CINIT(RTSP_SERVER_CSEQ, LONG, 194),
-
- /* The stream to pass to INTERLEAVEFUNCTION. */
- CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
-
- /* Let the application define a custom write method for RTP data */
- CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
-
- /* Turn on wildcard matching */
- CINIT(WILDCARDMATCH, LONG, 197),
-
- /* Directory matching callback called before downloading of an
- individual file (chunk) started */
- CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
-
- /* Directory matching callback called after the file (chunk)
- was downloaded, or skipped */
- CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
-
- /* Change match (fnmatch-like) callback for wildcard matching */
- CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
-
- /* Let the application define custom chunk data pointer */
- CINIT(CHUNK_DATA, OBJECTPOINT, 201),
-
- /* FNMATCH_FUNCTION user pointer */
- CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
-
- /* send linked-list of name:port:address sets */
- CINIT(RESOLVE, OBJECTPOINT, 203),
-
- /* Set a username for authenticated TLS */
- CINIT(TLSAUTH_USERNAME, OBJECTPOINT, 204),
-
- /* Set a password for authenticated TLS */
- CINIT(TLSAUTH_PASSWORD, OBJECTPOINT, 205),
-
- /* Set authentication type for authenticated TLS */
- CINIT(TLSAUTH_TYPE, OBJECTPOINT, 206),
-
- /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
- compressed transfer-encoded responses. Set to 0 to disable the use of TE:
- in outgoing requests. The current default is 0, but it might change in a
- future libcurl release.
-
- libcurl will ask for the compressed methods it knows of, and if that
- isn't any, it will not ask for transfer-encoding at all even if this
- option is set to 1.
-
- */
- CINIT(TRANSFER_ENCODING, LONG, 207),
-
- /* Callback function for closing socket (instead of close(2)). The callback
- should have type curl_closesocket_callback */
- CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
- CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
-
- /* allow GSSAPI credential delegation */
- CINIT(GSSAPI_DELEGATION, LONG, 210),
-
- CURLOPT_LASTENTRY /* the last unused */
-} CURLoption;
-
-#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
- the obsolete stuff removed! */
-
-/* Backwards compatibility with older names */
-/* These are scheduled to disappear by 2011 */
-
-/* This was added in version 7.19.1 */
-#define CURLOPT_POST301 CURLOPT_POSTREDIR
-
-/* These are scheduled to disappear by 2009 */
-
-/* The following were added in 7.17.0 */
-#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
-#define CURLOPT_FTPAPPEND CURLOPT_APPEND
-#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
-#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
-
-/* The following were added earlier */
-
-#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
-#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
-
-#else
-/* This is set if CURL_NO_OLDIES is defined at compile-time */
-#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
-#endif
-
-
-/* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
- name resolves addresses using more than one IP protocol version, this
- option might be handy to force libcurl to use a specific IP version. */
-#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
- versions that your system allows */
-#define CURL_IPRESOLVE_V4 1 /* resolve to ipv4 addresses */
-#define CURL_IPRESOLVE_V6 2 /* resolve to ipv6 addresses */
-
-/* three convenient "aliases" that follow the name scheme better */
-#define CURLOPT_WRITEDATA CURLOPT_FILE
-#define CURLOPT_READDATA CURLOPT_INFILE
-#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER
-#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
-
-/* These enums are for use with the CURLOPT_HTTP_VERSION option. */
-enum
-{
- CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
- like the library to choose the best possible
- for us! */
- CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
- CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
-
- CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
-};
-
-/*
- * Public API enums for RTSP requests
- */
-enum
-{
- CURL_RTSPREQ_NONE, /* first in list */
- CURL_RTSPREQ_OPTIONS,
- CURL_RTSPREQ_DESCRIBE,
- CURL_RTSPREQ_ANNOUNCE,
- CURL_RTSPREQ_SETUP,
- CURL_RTSPREQ_PLAY,
- CURL_RTSPREQ_PAUSE,
- CURL_RTSPREQ_TEARDOWN,
- CURL_RTSPREQ_GET_PARAMETER,
- CURL_RTSPREQ_SET_PARAMETER,
- CURL_RTSPREQ_RECORD,
- CURL_RTSPREQ_RECEIVE,
- CURL_RTSPREQ_LAST /* last in list */
-};
-
-/* These enums are for use with the CURLOPT_NETRC option. */
-enum CURL_NETRC_OPTION
-{
- CURL_NETRC_IGNORED, /* The .netrc will never be read.
- * This is the default. */
- CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred
- * to one in the .netrc. */
- CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored.
- * Unless one is set programmatically, the .netrc
- * will be queried. */
- CURL_NETRC_LAST
-};
-
-enum
-{
- CURL_SSLVERSION_DEFAULT,
- CURL_SSLVERSION_TLSv1,
- CURL_SSLVERSION_SSLv2,
- CURL_SSLVERSION_SSLv3,
-
- CURL_SSLVERSION_LAST /* never use, keep last */
-};
-
-enum CURL_TLSAUTH
-{
- CURL_TLSAUTH_NONE,
- CURL_TLSAUTH_SRP,
- CURL_TLSAUTH_LAST /* never use, keep last */
-};
-
-/* symbols to use with CURLOPT_POSTREDIR.
- CURL_REDIR_POST_301 and CURL_REDIR_POST_302 can be bitwise ORed so that
- CURL_REDIR_POST_301 | CURL_REDIR_POST_302 == CURL_REDIR_POST_ALL */
-
-#define CURL_REDIR_GET_ALL 0
-#define CURL_REDIR_POST_301 1
-#define CURL_REDIR_POST_302 2
-#define CURL_REDIR_POST_ALL (CURL_REDIR_POST_301|CURL_REDIR_POST_302)
-
-typedef enum
-{
- CURL_TIMECOND_NONE,
-
- CURL_TIMECOND_IFMODSINCE,
- CURL_TIMECOND_IFUNMODSINCE,
- CURL_TIMECOND_LASTMOD,
-
- CURL_TIMECOND_LAST
-} curl_TimeCond;
-
-
-/* curl_strequal() and curl_strnequal() are subject for removal in a future
- libcurl, see lib/README.curlx for details */
-CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
-CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
-
-/* name is uppercase CURLFORM_<name> */
-#ifdef CFINIT
-#undef CFINIT
-#endif
-
-#ifdef CURL_ISOCPP
-#define CFINIT(name) CURLFORM_ ## name
-#else
-/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
-#define CFINIT(name) CURLFORM_/**/name
-#endif
-
-typedef enum
-{
- CFINIT(NOTHING), /********* the first one is unused ************/
-
- /* */
- CFINIT(COPYNAME),
- CFINIT(PTRNAME),
- CFINIT(NAMELENGTH),
- CFINIT(COPYCONTENTS),
- CFINIT(PTRCONTENTS),
- CFINIT(CONTENTSLENGTH),
- CFINIT(FILECONTENT),
- CFINIT(ARRAY),
- CFINIT(OBSOLETE),
- CFINIT(FILE),
-
- CFINIT(BUFFER),
- CFINIT(BUFFERPTR),
- CFINIT(BUFFERLENGTH),
-
- CFINIT(CONTENTTYPE),
- CFINIT(CONTENTHEADER),
- CFINIT(FILENAME),
- CFINIT(END),
- CFINIT(OBSOLETE2),
-
- CFINIT(STREAM),
-
- CURLFORM_LASTENTRY /* the last unused */
-} CURLformoption;
-
-#undef CFINIT /* done */
-
-/* structure to be used as parameter for CURLFORM_ARRAY */
-struct curl_forms
-{
- CURLformoption option;
- const char *value;
-};
-
-/* use this for multipart formpost building */
-/* Returns code for curl_formadd()
- *
- * Returns:
- * CURL_FORMADD_OK on success
- * CURL_FORMADD_MEMORY if the FormInfo allocation fails
- * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
- * CURL_FORMADD_NULL if a null pointer was given for a char
- * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
- * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
- * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
- * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated
- * CURL_FORMADD_MEMORY if some allocation for string copying failed.
- * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
- *
- ***************************************************************************/
-typedef enum
-{
- CURL_FORMADD_OK, /* first, no error */
-
- CURL_FORMADD_MEMORY,
- CURL_FORMADD_OPTION_TWICE,
- CURL_FORMADD_NULL,
- CURL_FORMADD_UNKNOWN_OPTION,
- CURL_FORMADD_INCOMPLETE,
- CURL_FORMADD_ILLEGAL_ARRAY,
- CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
-
- CURL_FORMADD_LAST /* last */
-} CURLFORMcode;
-
-/*
- * NAME curl_formadd()
- *
- * DESCRIPTION
- *
- * Pretty advanced function for building multi-part formposts. Each invoke
- * adds one part that together construct a full post. Then use
- * CURLOPT_HTTPPOST to send it off to libcurl.
- */
-CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
- struct curl_httppost **last_post,
- ...);
-
-/*
- * callback function for curl_formget()
- * The void *arg pointer will be the one passed as second argument to
- * curl_formget().
- * The character buffer passed to it must not be freed.
- * Should return the buffer length passed to it as the argument "len" on
- * success.
- */
-typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
- size_t len);
-
-/*
- * NAME curl_formget()
- *
- * DESCRIPTION
- *
- * Serialize a curl_httppost struct built with curl_formadd().
- * Accepts a void pointer as second argument which will be passed to
- * the curl_formget_callback function.
- * Returns 0 on success.
- */
-CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
- curl_formget_callback append);
-/*
- * NAME curl_formfree()
- *
- * DESCRIPTION
- *
- * Free a multipart formpost previously built with curl_formadd().
- */
-CURL_EXTERN void curl_formfree(struct curl_httppost *form);
-
-/*
- * NAME curl_getenv()
- *
- * DESCRIPTION
- *
- * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
- * complete. DEPRECATED - see lib/README.curlx
- */
-CURL_EXTERN char *curl_getenv(const char *variable);
-
-/*
- * NAME curl_version()
- *
- * DESCRIPTION
- *
- * Returns a static ascii string of the libcurl version.
- */
-CURL_EXTERN char *curl_version(void);
-
-/*
- * NAME curl_easy_escape()
- *
- * DESCRIPTION
- *
- * Escapes URL strings (converts all letters consider illegal in URLs to their
- * %XX versions). This function returns a new allocated string or NULL if an
- * error occurred.
- */
-CURL_EXTERN char *curl_easy_escape(CURL *handle,
- const char *string,
- int length);
-
-/* the previous version: */
-CURL_EXTERN char *curl_escape(const char *string,
- int length);
-
-
-/*
- * NAME curl_easy_unescape()
- *
- * DESCRIPTION
- *
- * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
- * versions). This function returns a new allocated string or NULL if an error
- * occurred.
- * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
- * converted into the host encoding.
- */
-CURL_EXTERN char *curl_easy_unescape(CURL *handle,
- const char *string,
- int length,
- int *outlength);
-
-/* the previous version */
-CURL_EXTERN char *curl_unescape(const char *string,
- int length);
-
-/*
- * NAME curl_free()
- *
- * DESCRIPTION
- *
- * Provided for de-allocation in the same translation unit that did the
- * allocation. Added in libcurl 7.10
- */
-CURL_EXTERN void curl_free(void *p);
-
-/*
- * NAME curl_global_init()
- *
- * DESCRIPTION
- *
- * curl_global_init() should be invoked exactly once for each application that
- * uses libcurl and before any call of other libcurl functions.
- *
- * This function is not thread-safe!
- */
-CURL_EXTERN CURLcode curl_global_init(long flags);
-
-/*
- * NAME curl_global_init_mem()
- *
- * DESCRIPTION
- *
- * curl_global_init() or curl_global_init_mem() should be invoked exactly once
- * for each application that uses libcurl. This function can be used to
- * initialize libcurl and set user defined memory management callback
- * functions. Users can implement memory management routines to check for
- * memory leaks, check for mis-use of the curl library etc. User registered
- * callback routines with be invoked by this library instead of the system
- * memory management routines like malloc, free etc.
- */
-CURL_EXTERN CURLcode curl_global_init_mem(long flags,
- curl_malloc_callback m,
- curl_free_callback f,
- curl_realloc_callback r,
- curl_strdup_callback s,
- curl_calloc_callback c);
-
-/*
- * NAME curl_global_cleanup()
- *
- * DESCRIPTION
- *
- * curl_global_cleanup() should be invoked exactly once for each application
- * that uses libcurl
- */
-CURL_EXTERN void curl_global_cleanup(void);
-
-/* linked-list structure for the CURLOPT_QUOTE option (and other) */
-struct curl_slist
-{
- char *data;
- struct curl_slist *next;
-};
-
-/*
- * NAME curl_slist_append()
- *
- * DESCRIPTION
- *
- * Appends a string to a linked list. If no list exists, it will be created
- * first. Returns the new list, after appending.
- */
-CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
- const char *);
-
-/*
- * NAME curl_slist_free_all()
- *
- * DESCRIPTION
- *
- * free a previously built curl_slist.
- */
-CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
-
-/*
- * NAME curl_getdate()
- *
- * DESCRIPTION
- *
- * Returns the time, in seconds since 1 Jan 1970 of the time string given in
- * the first argument. The time argument in the second parameter is unused
- * and should be set to NULL.
- */
-CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
-
-/* info about the certificate chain, only for OpenSSL builds. Asked
- for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
-struct curl_certinfo
-{
- int num_of_certs; /* number of certificates with information */
- struct curl_slist **certinfo; /* for each index in this array, there's a
- linked list with textual information in the
- format "name: value" */
-};
-
-#define CURLINFO_STRING 0x100000
-#define CURLINFO_LONG 0x200000
-#define CURLINFO_DOUBLE 0x300000
-#define CURLINFO_SLIST 0x400000
-#define CURLINFO_MASK 0x0fffff
-#define CURLINFO_TYPEMASK 0xf00000
-
-typedef enum
-{
- CURLINFO_NONE, /* first, never use this */
- CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1,
- CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2,
- CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3,
- CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4,
- CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5,
- CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
- CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7,
- CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8,
- CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9,
- CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10,
- CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11,
- CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
- CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
- CURLINFO_FILETIME = CURLINFO_LONG + 14,
- CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
- CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
- CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
- CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
- CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19,
- CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20,
- CURLINFO_PRIVATE = CURLINFO_STRING + 21,
- CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22,
- CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23,
- CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24,
- CURLINFO_OS_ERRNO = CURLINFO_LONG + 25,
- CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
- CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
- CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
- CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
- CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
- CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
- CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
- CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
- CURLINFO_CERTINFO = CURLINFO_SLIST + 34,
- CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
- CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36,
- CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
- CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38,
- CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39,
- CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
- CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
- CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
- /* Fill in new entries below here! */
-
- CURLINFO_LASTONE = 42
-} CURLINFO;
-
-/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
- CURLINFO_HTTP_CODE */
-#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
-
-typedef enum
-{
- CURLCLOSEPOLICY_NONE, /* first, never use this */
-
- CURLCLOSEPOLICY_OLDEST,
- CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
- CURLCLOSEPOLICY_LEAST_TRAFFIC,
- CURLCLOSEPOLICY_SLOWEST,
- CURLCLOSEPOLICY_CALLBACK,
-
- CURLCLOSEPOLICY_LAST /* last, never use this */
-} curl_closepolicy;
-
-#define CURL_GLOBAL_SSL (1<<0)
-#define CURL_GLOBAL_WIN32 (1<<1)
-#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
-#define CURL_GLOBAL_NOTHING 0
-#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
-
-
-/*****************************************************************************
- * Setup defines, protos etc for the sharing stuff.
- */
-
-/* Different data locks for a single share */
-typedef enum
-{
- CURL_LOCK_DATA_NONE = 0,
- /* CURL_LOCK_DATA_SHARE is used internally to say that
- * the locking is just made to change the internal state of the share
- * itself.
- */
- CURL_LOCK_DATA_SHARE,
- CURL_LOCK_DATA_COOKIE,
- CURL_LOCK_DATA_DNS,
- CURL_LOCK_DATA_SSL_SESSION,
- CURL_LOCK_DATA_CONNECT,
- CURL_LOCK_DATA_LAST
-} curl_lock_data;
-
-/* Different lock access types */
-typedef enum
-{
- CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */
- CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
- CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
- CURL_LOCK_ACCESS_LAST /* never use */
-} curl_lock_access;
-
-typedef void (*curl_lock_function)(CURL *handle,
- curl_lock_data data,
- curl_lock_access locktype,
- void *userptr);
-typedef void (*curl_unlock_function)(CURL *handle,
- curl_lock_data data,
- void *userptr);
-
-typedef void CURLSH;
-
-typedef enum
-{
- CURLSHE_OK, /* all is fine */
- CURLSHE_BAD_OPTION, /* 1 */
- CURLSHE_IN_USE, /* 2 */
- CURLSHE_INVALID, /* 3 */
- CURLSHE_NOMEM, /* out of memory */
- CURLSHE_LAST /* never use */
-} CURLSHcode;
-
-typedef enum
-{
- CURLSHOPT_NONE, /* don't use */
- CURLSHOPT_SHARE, /* specify a data type to share */
- CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */
- CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */
- CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
- CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock
- callback functions */
- CURLSHOPT_LAST /* never use */
-} CURLSHoption;
-
-CURL_EXTERN CURLSH *curl_share_init(void);
-CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
-CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
-
-/****************************************************************************
- * Structures for querying information about the curl library at runtime.
- */
-
-typedef enum
-{
- CURLVERSION_FIRST,
- CURLVERSION_SECOND,
- CURLVERSION_THIRD,
- CURLVERSION_FOURTH,
- CURLVERSION_LAST /* never actually use this */
-} CURLversion;
-
-/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
- basically all programs ever that want to get version information. It is
- meant to be a built-in version number for what kind of struct the caller
- expects. If the struct ever changes, we redefine the NOW to another enum
- from above. */
-#define CURLVERSION_NOW CURLVERSION_FOURTH
-
-typedef struct
-{
- CURLversion age; /* age of the returned struct */
- const char *version; /* LIBCURL_VERSION */
- unsigned int version_num; /* LIBCURL_VERSION_NUM */
- const char *host; /* OS/host/cpu/machine when configured */
- int features; /* bitmask, see defines below */
- const char *ssl_version; /* human readable string */
- long ssl_version_num; /* not used anymore, always 0 */
- const char *libz_version; /* human readable string */
- /* protocols is terminated by an entry with a NULL protoname */
- const char *const *protocols;
-
- /* The fields below this were added in CURLVERSION_SECOND */
- const char *ares;
- int ares_num;
-
- /* This field was added in CURLVERSION_THIRD */
- const char *libidn;
-
- /* These field were added in CURLVERSION_FOURTH */
-
- /* Same as '_libiconv_version' if built with HAVE_ICONV */
- int iconv_ver_num;
-
- const char *libssh_version; /* human readable string */
-
-} curl_version_info_data;
-
-#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
-#define CURL_VERSION_KERBEROS4 (1<<1) /* kerberos auth is supported */
-#define CURL_VERSION_SSL (1<<2) /* SSL options are present */
-#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */
-#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */
-#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth support */
-#define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */
-#define CURL_VERSION_ASYNCHDNS (1<<7) /* asynchronous dns resolves */
-#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth */
-#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */
-#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */
-#define CURL_VERSION_SSPI (1<<11) /* SSPI is supported */
-#define CURL_VERSION_CONV (1<<12) /* character conversions supported */
-#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */
-#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
-#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegating to winbind helper */
-
-/*
-* NAME curl_version_info()
-*
-* DESCRIPTION
-*
-* This function returns a pointer to a static copy of the version info
-* struct. See above.
-*/
-CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
-
-/*
- * NAME curl_easy_strerror()
- *
- * DESCRIPTION
- *
- * The curl_easy_strerror function may be used to turn a CURLcode value
- * into the equivalent human readable error string. This is useful
- * for printing meaningful error messages.
- */
-CURL_EXTERN const char *curl_easy_strerror(CURLcode);
-
-/*
- * NAME curl_share_strerror()
- *
- * DESCRIPTION
- *
- * The curl_share_strerror function may be used to turn a CURLSHcode value
- * into the equivalent human readable error string. This is useful
- * for printing meaningful error messages.
- */
-CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
-
-/*
- * NAME curl_easy_pause()
- *
- * DESCRIPTION
- *
- * The curl_easy_pause function pauses or unpauses transfers. Select the new
- * state by setting the bitmask, use the convenience defines below.
- *
- */
-CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
-
-#define CURLPAUSE_RECV (1<<0)
-#define CURLPAUSE_RECV_CONT (0)
-
-#define CURLPAUSE_SEND (1<<2)
-#define CURLPAUSE_SEND_CONT (0)
-
-#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND)
-#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
-
-#ifdef __cplusplus
-}
-#endif
-
-/* unfortunately, the easy.h and multi.h include files need options and info
- stuff before they can be included! */
-#include "easy.h" /* nothing in curl is fun without the easy stuff */
-#include "multi.h"
-
-/* the typechecker doesn't work in C++ (yet) */
-#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
- ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
- !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
-#include "typecheck-gcc.h"
-#else
-#if defined(__STDC__) && (__STDC__ >= 1)
-/* This preprocessor magic that replaces a call with the exact same call is
- only done to make sure application authors pass exactly three arguments
- to these functions. */
-#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
-#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
-#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
-#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
-#endif /* __STDC__ >= 1 */
-#endif /* gcc >= 4.3 && !__cplusplus */
-
-#endif /* __CURL_CURL_H */
+++ /dev/null
-/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */
-#ifndef __CURL_CURLBUILD_H
-#define __CURL_CURLBUILD_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-/* ================================================================ */
-/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
-/* ================================================================ */
-
-/*
- * NOTE 1:
- * -------
- *
- * Nothing in this file is intended to be modified or adjusted by the
- * curl library user nor by the curl library builder.
- *
- * If you think that something actually needs to be changed, adjusted
- * or fixed in this file, then, report it on the libcurl development
- * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
- *
- * This header file shall only export symbols which are 'curl' or 'CURL'
- * prefixed, otherwise public name space would be polluted.
- *
- * NOTE 2:
- * -------
- *
- * Right now you might be staring at file include/curl/curlbuild.h.in or
- * at file include/curl/curlbuild.h, this is due to the following reason:
- *
- * On systems capable of running the configure script, the configure process
- * will overwrite the distributed include/curl/curlbuild.h file with one that
- * is suitable and specific to the library being configured and built, which
- * is generated from the include/curl/curlbuild.h.in template file.
- *
- */
-
-/* ================================================================ */
-/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
-/* ================================================================ */
-
-#ifdef CURL_SIZEOF_LONG
-#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
-Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
-#endif
-
-#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
-#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
-Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
-#endif
-
-#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
-#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
-Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
-#endif
-
-#ifdef CURL_TYPEOF_CURL_OFF_T
-#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
-Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
-#endif
-
-#ifdef CURL_FORMAT_CURL_OFF_T
-#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
-Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
-#endif
-
-#ifdef CURL_FORMAT_CURL_OFF_TU
-#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
-Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
-#endif
-
-#ifdef CURL_FORMAT_OFF_T
-#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
-Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
-#endif
-
-#ifdef CURL_SIZEOF_CURL_OFF_T
-#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
-Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
-#endif
-
-#ifdef CURL_SUFFIX_CURL_OFF_T
-#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
-Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
-#endif
-
-#ifdef CURL_SUFFIX_CURL_OFF_TU
-#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
-Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
-#endif
-
-/* ================================================================ */
-/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */
-/* ================================================================ */
-
-/* Configure process defines this to 1 when it finds out that system */
-/* header file ws2tcpip.h must be included by the external interface. */
-/* #undef CURL_PULL_WS2TCPIP_H */
-#ifdef CURL_PULL_WS2TCPIP_H
-# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-# endif
-# include <windows.h>
-# include <winsock2.h>
-# include <ws2tcpip.h>
-#endif
-
-/* Configure process defines this to 1 when it finds out that system */
-/* header file sys/types.h must be included by the external interface. */
-#define CURL_PULL_SYS_TYPES_H 1
-#ifdef CURL_PULL_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-/* Configure process defines this to 1 when it finds out that system */
-/* header file stdint.h must be included by the external interface. */
-/* #undef CURL_PULL_STDINT_H */
-#ifdef CURL_PULL_STDINT_H
-# include <stdint.h>
-#endif
-
-/* Configure process defines this to 1 when it finds out that system */
-/* header file inttypes.h must be included by the external interface. */
-/* #undef CURL_PULL_INTTYPES_H */
-#ifdef CURL_PULL_INTTYPES_H
-# include <inttypes.h>
-#endif
-
-/* Configure process defines this to 1 when it finds out that system */
-/* header file sys/socket.h must be included by the external interface. */
-#define CURL_PULL_SYS_SOCKET_H 1
-#ifdef CURL_PULL_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
-/* The size of `long', as computed by sizeof. */
-#define CURL_SIZEOF_LONG 4
-
-/* Integral data type used for curl_socklen_t. */
-#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-
-/* The size of `curl_socklen_t', as computed by sizeof. */
-#define CURL_SIZEOF_CURL_SOCKLEN_T 4
-
-/* Data type definition of curl_socklen_t. */
-typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
-
-/* Signed integral data type used for curl_off_t. */
-#define CURL_TYPEOF_CURL_OFF_T long
-
-/* Data type definition of curl_off_t. */
-typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
-
-/* curl_off_t formatting string directive without "%" conversion specifier. */
-#define CURL_FORMAT_CURL_OFF_T "ld"
-
-/* unsigned curl_off_t formatting string without "%" conversion specifier. */
-#define CURL_FORMAT_CURL_OFF_TU "lu"
-
-/* curl_off_t formatting string directive with "%" conversion specifier. */
-#define CURL_FORMAT_OFF_T "%ld"
-
-/* The size of `curl_off_t', as computed by sizeof. */
-#define CURL_SIZEOF_CURL_OFF_T 4
-
-/* curl_off_t constant suffix. */
-#define CURL_SUFFIX_CURL_OFF_T L
-
-/* unsigned curl_off_t constant suffix. */
-#define CURL_SUFFIX_CURL_OFF_TU UL
-
-#endif /* __CURL_CURLBUILD_H */
+++ /dev/null
-#ifndef __CURL_CURLRULES_H
-#define __CURL_CURLRULES_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-/* ================================================================ */
-/* COMPILE TIME SANITY CHECKS */
-/* ================================================================ */
-
-/*
- * NOTE 1:
- * -------
- *
- * All checks done in this file are intentionally placed in a public
- * header file which is pulled by curl/curl.h when an application is
- * being built using an already built libcurl library. Additionally
- * this file is also included and used when building the library.
- *
- * If compilation fails on this file it is certainly sure that the
- * problem is elsewhere. It could be a problem in the curlbuild.h
- * header file, or simply that you are using different compilation
- * settings than those used to build the library.
- *
- * Nothing in this file is intended to be modified or adjusted by the
- * curl library user nor by the curl library builder.
- *
- * Do not deactivate any check, these are done to make sure that the
- * library is properly built and used.
- *
- * You can find further help on the libcurl development mailing list:
- * http://cool.haxx.se/mailman/listinfo/curl-library/
- *
- * NOTE 2
- * ------
- *
- * Some of the following compile time checks are based on the fact
- * that the dimension of a constant array can not be a negative one.
- * In this way if the compile time verification fails, the compilation
- * will fail issuing an error. The error description wording is compiler
- * dependent but it will be quite similar to one of the following:
- *
- * "negative subscript or subscript is too large"
- * "array must have at least one element"
- * "-1 is an illegal array size"
- * "size of array is negative"
- *
- * If you are building an application which tries to use an already
- * built libcurl library and you are getting this kind of errors on
- * this file, it is a clear indication that there is a mismatch between
- * how the library was built and how you are trying to use it for your
- * application. Your already compiled or binary library provider is the
- * only one who can give you the details you need to properly use it.
- */
-
-/*
- * Verify that some macros are actually defined.
- */
-
-#ifndef CURL_SIZEOF_LONG
-# error "CURL_SIZEOF_LONG definition is missing!"
-Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing
-#endif
-
-#ifndef CURL_TYPEOF_CURL_SOCKLEN_T
-# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!"
-Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing
-#endif
-
-#ifndef CURL_SIZEOF_CURL_SOCKLEN_T
-# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!"
-Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing
-#endif
-
-#ifndef CURL_TYPEOF_CURL_OFF_T
-# error "CURL_TYPEOF_CURL_OFF_T definition is missing!"
-Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing
-#endif
-
-#ifndef CURL_FORMAT_CURL_OFF_T
-# error "CURL_FORMAT_CURL_OFF_T definition is missing!"
-Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing
-#endif
-
-#ifndef CURL_FORMAT_CURL_OFF_TU
-# error "CURL_FORMAT_CURL_OFF_TU definition is missing!"
-Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing
-#endif
-
-#ifndef CURL_FORMAT_OFF_T
-# error "CURL_FORMAT_OFF_T definition is missing!"
-Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing
-#endif
-
-#ifndef CURL_SIZEOF_CURL_OFF_T
-# error "CURL_SIZEOF_CURL_OFF_T definition is missing!"
-Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing
-#endif
-
-#ifndef CURL_SUFFIX_CURL_OFF_T
-# error "CURL_SUFFIX_CURL_OFF_T definition is missing!"
-Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing
-#endif
-
-#ifndef CURL_SUFFIX_CURL_OFF_TU
-# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!"
-Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing
-#endif
-
-/*
- * Macros private to this header file.
- */
-
-#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1
-
-#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1
-
-/*
- * Verify that the size previously defined and expected for long
- * is the same as the one reported by sizeof() at compile time.
- */
-
-typedef char
-__curl_rule_01__
-[CurlchkszEQ(long, CURL_SIZEOF_LONG)];
-
-/*
- * Verify that the size previously defined and expected for
- * curl_off_t is actually the the same as the one reported
- * by sizeof() at compile time.
- */
-
-typedef char
-__curl_rule_02__
-[CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)];
-
-/*
- * Verify at compile time that the size of curl_off_t as reported
- * by sizeof() is greater or equal than the one reported for long
- * for the current compilation.
- */
-
-typedef char
-__curl_rule_03__
-[CurlchkszGE(curl_off_t, long)];
-
-/*
- * Verify that the size previously defined and expected for
- * curl_socklen_t is actually the the same as the one reported
- * by sizeof() at compile time.
- */
-
-typedef char
-__curl_rule_04__
-[CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)];
-
-/*
- * Verify at compile time that the size of curl_socklen_t as reported
- * by sizeof() is greater or equal than the one reported for int for
- * the current compilation.
- */
-
-typedef char
-__curl_rule_05__
-[CurlchkszGE(curl_socklen_t, int)];
-
-/* ================================================================ */
-/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */
-/* ================================================================ */
-
-/*
- * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
- * these to be visible and exported by the external libcurl interface API,
- * while also making them visible to the library internals, simply including
- * setup.h, without actually needing to include curl.h internally.
- * If some day this section would grow big enough, all this should be moved
- * to its own header file.
- */
-
-/*
- * Figure out if we can use the ## preprocessor operator, which is supported
- * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
- * or __cplusplus so we need to carefully check for them too.
- */
-
-#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
- defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
- defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
- defined(__ILEC400__)
-/* This compiler is believed to have an ISO compatible preprocessor */
-#define CURL_ISOCPP
-#else
-/* This compiler is believed NOT to have an ISO compatible preprocessor */
-#undef CURL_ISOCPP
-#endif
-
-/*
- * Macros for minimum-width signed and unsigned curl_off_t integer constants.
- */
-
-#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
-# define __CURL_OFF_T_C_HLPR2(x) x
-# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
-# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
- __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
-# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
- __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
-#else
-# ifdef CURL_ISOCPP
-# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
-# else
-# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
-# endif
-# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
-# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
-# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
-#endif
-
-/*
- * Get rid of macros private to this header file.
- */
-
-#undef CurlchkszEQ
-#undef CurlchkszGE
-
-/*
- * Get rid of macros not intended to exist beyond this point.
- */
-
-#undef CURL_PULL_WS2TCPIP_H
-#undef CURL_PULL_SYS_TYPES_H
-#undef CURL_PULL_SYS_SOCKET_H
-#undef CURL_PULL_STDINT_H
-#undef CURL_PULL_INTTYPES_H
-
-#undef CURL_TYPEOF_CURL_SOCKLEN_T
-#undef CURL_TYPEOF_CURL_OFF_T
-
-#ifdef CURL_NO_OLDIES
-#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */
-#endif
-
-#endif /* __CURL_CURLRULES_H */
+++ /dev/null
-#ifndef __CURL_CURLVER_H
-#define __CURL_CURLVER_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-/* This header file contains nothing but libcurl version info, generated by
- a script at release-time. This was made its own header file in 7.11.2 */
-
-/* This is the global package copyright */
-#define LIBCURL_COPYRIGHT "1996 - 2011 Daniel Stenberg, <daniel@haxx.se>."
-
-/* This is the version number of the libcurl package from which this header
- file origins: */
-#define LIBCURL_VERSION "7.22.0"
-
-/* The numeric version number is also available "in parts" by using these
- defines: */
-#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 22
-#define LIBCURL_VERSION_PATCH 0
-
-/* This is the numeric version of the libcurl version number, meant for easier
- parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
- always follow this syntax:
-
- 0xXXYYZZ
-
- Where XX, YY and ZZ are the main version, release and patch numbers in
- hexadecimal (using 8 bits each). All three numbers are always represented
- using two digits. 1.2 would appear as "0x010200" while version 9.11.7
- appears as "0x090b07".
-
- This 6-digit (24 bits) hexadecimal number does not show pre-release number,
- and it is always a greater number in a more recent release. It makes
- comparisons with greater than and less than work.
-*/
-#define LIBCURL_VERSION_NUM 0x071600
-
-/*
- * This is the date and time when the full source package was created. The
- * timestamp is not stored in git, as the timestamp is properly set in the
- * tarballs by the maketgz script.
- *
- * The format of the date should follow this template:
- *
- * "Mon Feb 12 11:35:33 UTC 2007"
- */
-#define LIBCURL_TIMESTAMP "Tue Sep 13 16:53:51 UTC 2011"
-
-#endif /* __CURL_CURLVER_H */
+++ /dev/null
-#ifndef __CURL_EASY_H
-#define __CURL_EASY_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-CURL_EXTERN CURL *curl_easy_init(void);
-CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
-CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
-CURL_EXTERN void curl_easy_cleanup(CURL *curl);
-
-/*
- * NAME curl_easy_getinfo()
- *
- * DESCRIPTION
- *
- * Request internal information from the curl session with this function. The
- * third argument MUST be a pointer to a long, a pointer to a char * or a
- * pointer to a double (as the documentation describes elsewhere). The data
- * pointed to will be filled in accordingly and can be relied upon only if the
- * function returns CURLE_OK. This function is intended to get used *AFTER* a
- * performed transfer, all results from this function are undefined until the
- * transfer is completed.
- */
-CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
-
-
-/*
- * NAME curl_easy_duphandle()
- *
- * DESCRIPTION
- *
- * Creates a new curl session handle with the same options set for the handle
- * passed in. Duplicating a handle could only be a matter of cloning data and
- * options, internal state info and things like persistent connections cannot
- * be transferred. It is useful in multithreaded applications when you can run
- * curl_easy_duphandle() for each new thread to avoid a series of identical
- * curl_easy_setopt() invokes in every thread.
- */
-CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
-
-/*
- * NAME curl_easy_reset()
- *
- * DESCRIPTION
- *
- * Re-initializes a CURL handle to the default values. This puts back the
- * handle to the same state as it was in when it was just created.
- *
- * It does keep: live connections, the Session ID cache, the DNS cache and the
- * cookies.
- */
-CURL_EXTERN void curl_easy_reset(CURL *curl);
-
-/*
- * NAME curl_easy_recv()
- *
- * DESCRIPTION
- *
- * Receives data from the connected socket. Use after successful
- * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
- */
-CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
- size_t *n);
-
-/*
- * NAME curl_easy_send()
- *
- * DESCRIPTION
- *
- * Sends data over the connected socket. Use after successful
- * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
- */
-CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
- size_t buflen, size_t *n);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-#ifndef __CURL_MPRINTF_H
-#define __CURL_MPRINTF_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#include <stdarg.h>
-#include <stdio.h> /* needed for FILE */
-
-#include "curl.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-CURL_EXTERN int curl_mprintf(const char *format, ...);
-CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
-CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
-CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
- const char *format, ...);
-CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
-CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
-CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
-CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
- const char *format, va_list args);
-CURL_EXTERN char *curl_maprintf(const char *format, ...);
-CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
-
-#ifdef _MPRINTF_REPLACE
-# undef printf
-# undef fprintf
-# undef sprintf
-# undef vsprintf
-# undef snprintf
-# undef vprintf
-# undef vfprintf
-# undef vsnprintf
-# undef aprintf
-# undef vaprintf
-# define printf curl_mprintf
-# define fprintf curl_mfprintf
-#ifdef CURLDEBUG
-/* When built with CURLDEBUG we define away the sprintf() functions since we
- don't want internal code to be using them */
-# define sprintf sprintf_was_used
-# define vsprintf vsprintf_was_used
-#else
-# define sprintf curl_msprintf
-# define vsprintf curl_mvsprintf
-#endif
-# define snprintf curl_msnprintf
-# define vprintf curl_mvprintf
-# define vfprintf curl_mvfprintf
-# define vsnprintf curl_mvsnprintf
-# define aprintf curl_maprintf
-# define vaprintf curl_mvaprintf
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CURL_MPRINTF_H */
+++ /dev/null
-#ifndef __CURL_MULTI_H
-#define __CURL_MULTI_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-/*
- This is an "external" header file. Don't give away any internals here!
-
- GOALS
-
- o Enable a "pull" interface. The application that uses libcurl decides where
- and when to ask libcurl to get/send data.
-
- o Enable multiple simultaneous transfers in the same thread without making it
- complicated for the application.
-
- o Enable the application to select() on its own file descriptors and curl's
- file descriptors simultaneous easily.
-
-*/
-
-/*
- * This header file should not really need to include "curl.h" since curl.h
- * itself includes this file and we expect user applications to do #include
- * <curl/curl.h> without the need for especially including multi.h.
- *
- * For some reason we added this include here at one point, and rather than to
- * break existing (wrongly written) libcurl applications, we leave it as-is
- * but with this warning attached.
- */
-#include "curl.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void CURLM;
-
-typedef enum
-{
- CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
- curl_multi_socket*() soon */
- CURLM_OK,
- CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
- CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
- CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
- CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
- CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
- CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
- CURLM_LAST
-} CURLMcode;
-
-/* just to make code nicer when using curl_multi_socket() you can now check
- for CURLM_CALL_MULTI_SOCKET too in the same style it works for
- curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
-#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
-
-typedef enum
-{
- CURLMSG_NONE, /* first, not used */
- CURLMSG_DONE, /* This easy handle has completed. 'result' contains
- the CURLcode of the transfer */
- CURLMSG_LAST /* last, not used */
-} CURLMSG;
-
-struct CURLMsg
-{
- CURLMSG msg; /* what this message means */
- CURL *easy_handle; /* the handle it concerns */
- union
- {
- void *whatever; /* message-specific data */
- CURLcode result; /* return code for transfer */
- } data;
-};
-typedef struct CURLMsg CURLMsg;
-
-/*
- * Name: curl_multi_init()
- *
- * Desc: inititalize multi-style curl usage
- *
- * Returns: a new CURLM handle to use in all 'curl_multi' functions.
- */
-CURL_EXTERN CURLM *curl_multi_init(void);
-
-/*
- * Name: curl_multi_add_handle()
- *
- * Desc: add a standard curl handle to the multi stack
- *
- * Returns: CURLMcode type, general multi error code.
- */
-CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
- CURL *curl_handle);
-
-/*
- * Name: curl_multi_remove_handle()
- *
- * Desc: removes a curl handle from the multi stack again
- *
- * Returns: CURLMcode type, general multi error code.
- */
-CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
- CURL *curl_handle);
-
-/*
- * Name: curl_multi_fdset()
- *
- * Desc: Ask curl for its fd_set sets. The app can use these to select() or
- * poll() on. We want curl_multi_perform() called as soon as one of
- * them are ready.
- *
- * Returns: CURLMcode type, general multi error code.
- */
-CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
- fd_set *read_fd_set,
- fd_set *write_fd_set,
- fd_set *exc_fd_set,
- int *max_fd);
-
-/*
- * Name: curl_multi_perform()
- *
- * Desc: When the app thinks there's data available for curl it calls this
- * function to read/write whatever there is right now. This returns
- * as soon as the reads and writes are done. This function does not
- * require that there actually is data available for reading or that
- * data can be written, it can be called just in case. It returns
- * the number of handles that still transfer data in the second
- * argument's integer-pointer.
- *
- * Returns: CURLMcode type, general multi error code. *NOTE* that this only
- * returns errors etc regarding the whole multi stack. There might
- * still have occurred problems on invidual transfers even when this
- * returns OK.
- */
-CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
- int *running_handles);
-
-/*
- * Name: curl_multi_cleanup()
- *
- * Desc: Cleans up and removes a whole multi stack. It does not free or
- * touch any individual easy handles in any way. We need to define
- * in what state those handles will be if this function is called
- * in the middle of a transfer.
- *
- * Returns: CURLMcode type, general multi error code.
- */
-CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
-
-/*
- * Name: curl_multi_info_read()
- *
- * Desc: Ask the multi handle if there's any messages/informationals from
- * the individual transfers. Messages include informationals such as
- * error code from the transfer or just the fact that a transfer is
- * completed. More details on these should be written down as well.
- *
- * Repeated calls to this function will return a new struct each
- * time, until a special "end of msgs" struct is returned as a signal
- * that there is no more to get at this point.
- *
- * The data the returned pointer points to will not survive calling
- * curl_multi_cleanup().
- *
- * The 'CURLMsg' struct is meant to be very simple and only contain
- * very basic informations. If more involved information is wanted,
- * we will provide the particular "transfer handle" in that struct
- * and that should/could/would be used in subsequent
- * curl_easy_getinfo() calls (or similar). The point being that we
- * must never expose complex structs to applications, as then we'll
- * undoubtably get backwards compatibility problems in the future.
- *
- * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
- * of structs. It also writes the number of messages left in the
- * queue (after this read) in the integer the second argument points
- * to.
- */
-CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
- int *msgs_in_queue);
-
-/*
- * Name: curl_multi_strerror()
- *
- * Desc: The curl_multi_strerror function may be used to turn a CURLMcode
- * value into the equivalent human readable error string. This is
- * useful for printing meaningful error messages.
- *
- * Returns: A pointer to a zero-terminated error message.
- */
-CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
-
-/*
- * Name: curl_multi_socket() and
- * curl_multi_socket_all()
- *
- * Desc: An alternative version of curl_multi_perform() that allows the
- * application to pass in one of the file descriptors that have been
- * detected to have "action" on them and let libcurl perform.
- * See man page for details.
- */
-#define CURL_POLL_NONE 0
-#define CURL_POLL_IN 1
-#define CURL_POLL_OUT 2
-#define CURL_POLL_INOUT 3
-#define CURL_POLL_REMOVE 4
-
-#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
-
-#define CURL_CSELECT_IN 0x01
-#define CURL_CSELECT_OUT 0x02
-#define CURL_CSELECT_ERR 0x04
-
-typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
- curl_socket_t s, /* socket */
- int what, /* see above */
- void *userp, /* private callback
- pointer */
- void *socketp); /* private socket
- pointer */
-/*
- * Name: curl_multi_timer_callback
- *
- * Desc: Called by libcurl whenever the library detects a change in the
- * maximum number of milliseconds the app is allowed to wait before
- * curl_multi_socket() or curl_multi_perform() must be called
- * (to allow libcurl's timed events to take place).
- *
- * Returns: The callback should return zero.
- */
-typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
- long timeout_ms, /* see above */
- void *userp); /* private callback
- pointer */
-
-CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
- int *running_handles);
-
-CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
- curl_socket_t s,
- int ev_bitmask,
- int *running_handles);
-
-CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
- int *running_handles);
-
-#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
-/* This macro below was added in 7.16.3 to push users who recompile to use
- the new curl_multi_socket_action() instead of the old curl_multi_socket()
-*/
-#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
-#endif
-
-/*
- * Name: curl_multi_timeout()
- *
- * Desc: Returns the maximum number of milliseconds the app is allowed to
- * wait before curl_multi_socket() or curl_multi_perform() must be
- * called (to allow libcurl's timed events to take place).
- *
- * Returns: CURLM error code.
- */
-CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
- long *milliseconds);
-
-#undef CINIT /* re-using the same name as in curl.h */
-
-#ifdef CURL_ISOCPP
-#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
-#else
-/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
-#define LONG CURLOPTTYPE_LONG
-#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
-#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
-#define OFF_T CURLOPTTYPE_OFF_T
-#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
-#endif
-
-typedef enum
-{
- /* This is the socket callback function pointer */
- CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
-
- /* This is the argument passed to the socket callback */
- CINIT(SOCKETDATA, OBJECTPOINT, 2),
-
- /* set to 1 to enable pipelining for this multi handle */
- CINIT(PIPELINING, LONG, 3),
-
- /* This is the timer callback function pointer */
- CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
-
- /* This is the argument passed to the timer callback */
- CINIT(TIMERDATA, OBJECTPOINT, 5),
-
- /* maximum number of entries in the connection cache */
- CINIT(MAXCONNECTS, LONG, 6),
-
- CURLMOPT_LASTENTRY /* the last unused */
-} CURLMoption;
-
-
-/*
- * Name: curl_multi_setopt()
- *
- * Desc: Sets options for the multi handle.
- *
- * Returns: CURLM error code.
- */
-CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
- CURLMoption option, ...);
-
-
-/*
- * Name: curl_multi_assign()
- *
- * Desc: This function sets an association in the multi handle between the
- * given socket and a private pointer of the application. This is
- * (only) useful for curl_multi_socket uses.
- *
- * Returns: CURLM error code.
- */
-CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
- curl_socket_t sockfd, void *sockp);
-
-#ifdef __cplusplus
-} /* end of extern "C" */
-#endif
-
-#endif
+++ /dev/null
-#ifndef __STDC_HEADERS_H
-#define __STDC_HEADERS_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#include <sys/types.h>
-
-size_t fread (void *, size_t, size_t, FILE *);
-size_t fwrite (const void *, size_t, size_t, FILE *);
-
-int strcasecmp(const char *, const char *);
-int strncasecmp(const char *, const char *, size_t);
-
-#endif /* __STDC_HEADERS_H */
+++ /dev/null
-#ifndef __CURL_TYPECHECK_GCC_H
-#define __CURL_TYPECHECK_GCC_H
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-/* wraps curl_easy_setopt() with typechecking */
-
-/* To add a new kind of warning, add an
- * if(_curl_is_sometype_option(_curl_opt))
- * if(!_curl_is_sometype(value))
- * _curl_easy_setopt_err_sometype();
- * block and define _curl_is_sometype_option, _curl_is_sometype and
- * _curl_easy_setopt_err_sometype below
- *
- * NOTE: We use two nested 'if' statements here instead of the && operator, in
- * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
- * when compiling with -Wlogical-op.
- *
- * To add an option that uses the same type as an existing option, you'll just
- * need to extend the appropriate _curl_*_option macro
- */
-#define curl_easy_setopt(handle, option, value) \
-__extension__ ({ \
- __typeof__ (option) _curl_opt = option; \
- if(__builtin_constant_p(_curl_opt)) { \
- if(_curl_is_long_option(_curl_opt)) \
- if(!_curl_is_long(value)) \
- _curl_easy_setopt_err_long(); \
- if(_curl_is_off_t_option(_curl_opt)) \
- if(!_curl_is_off_t(value)) \
- _curl_easy_setopt_err_curl_off_t(); \
- if(_curl_is_string_option(_curl_opt)) \
- if(!_curl_is_string(value)) \
- _curl_easy_setopt_err_string(); \
- if(_curl_is_write_cb_option(_curl_opt)) \
- if(!_curl_is_write_cb(value)) \
- _curl_easy_setopt_err_write_callback(); \
- if((_curl_opt) == CURLOPT_READFUNCTION) \
- if(!_curl_is_read_cb(value)) \
- _curl_easy_setopt_err_read_cb(); \
- if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
- if(!_curl_is_ioctl_cb(value)) \
- _curl_easy_setopt_err_ioctl_cb(); \
- if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
- if(!_curl_is_sockopt_cb(value)) \
- _curl_easy_setopt_err_sockopt_cb(); \
- if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
- if(!_curl_is_opensocket_cb(value)) \
- _curl_easy_setopt_err_opensocket_cb(); \
- if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
- if(!_curl_is_progress_cb(value)) \
- _curl_easy_setopt_err_progress_cb(); \
- if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
- if(!_curl_is_debug_cb(value)) \
- _curl_easy_setopt_err_debug_cb(); \
- if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
- if(!_curl_is_ssl_ctx_cb(value)) \
- _curl_easy_setopt_err_ssl_ctx_cb(); \
- if(_curl_is_conv_cb_option(_curl_opt)) \
- if(!_curl_is_conv_cb(value)) \
- _curl_easy_setopt_err_conv_cb(); \
- if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
- if(!_curl_is_seek_cb(value)) \
- _curl_easy_setopt_err_seek_cb(); \
- if(_curl_is_cb_data_option(_curl_opt)) \
- if(!_curl_is_cb_data(value)) \
- _curl_easy_setopt_err_cb_data(); \
- if((_curl_opt) == CURLOPT_ERRORBUFFER) \
- if(!_curl_is_error_buffer(value)) \
- _curl_easy_setopt_err_error_buffer(); \
- if((_curl_opt) == CURLOPT_STDERR) \
- if(!_curl_is_FILE(value)) \
- _curl_easy_setopt_err_FILE(); \
- if(_curl_is_postfields_option(_curl_opt)) \
- if(!_curl_is_postfields(value)) \
- _curl_easy_setopt_err_postfields(); \
- if((_curl_opt) == CURLOPT_HTTPPOST) \
- if(!_curl_is_arr((value), struct curl_httppost)) \
- _curl_easy_setopt_err_curl_httpost(); \
- if(_curl_is_slist_option(_curl_opt)) \
- if(!_curl_is_arr((value), struct curl_slist)) \
- _curl_easy_setopt_err_curl_slist(); \
- if((_curl_opt) == CURLOPT_SHARE) \
- if(!_curl_is_ptr((value), CURLSH)) \
- _curl_easy_setopt_err_CURLSH(); \
- } \
- curl_easy_setopt(handle, _curl_opt, value); \
-})
-
-/* wraps curl_easy_getinfo() with typechecking */
-/* FIXME: don't allow const pointers */
-#define curl_easy_getinfo(handle, info, arg) \
-__extension__ ({ \
- __typeof__ (info) _curl_info = info; \
- if(__builtin_constant_p(_curl_info)) { \
- if(_curl_is_string_info(_curl_info)) \
- if(!_curl_is_arr((arg), char *)) \
- _curl_easy_getinfo_err_string(); \
- if(_curl_is_long_info(_curl_info)) \
- if(!_curl_is_arr((arg), long)) \
- _curl_easy_getinfo_err_long(); \
- if(_curl_is_double_info(_curl_info)) \
- if(!_curl_is_arr((arg), double)) \
- _curl_easy_getinfo_err_double(); \
- if(_curl_is_slist_info(_curl_info)) \
- if(!_curl_is_arr((arg), struct curl_slist *)) \
- _curl_easy_getinfo_err_curl_slist(); \
- } \
- curl_easy_getinfo(handle, _curl_info, arg); \
-})
-
-/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
- * for now just make sure that the functions are called with three
- * arguments
- */
-#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
-#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
-
-
-/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
- * functions */
-
-/* To define a new warning, use _CURL_WARNING(identifier, "message") */
-#define _CURL_WARNING(id, message) \
- static void __attribute__((warning(message))) __attribute__((unused)) \
- __attribute__((noinline)) id(void) { __asm__(""); }
-
-_CURL_WARNING(_curl_easy_setopt_err_long,
- "curl_easy_setopt expects a long argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
- "curl_easy_setopt expects a curl_off_t argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_string,
- "curl_easy_setopt expects a "
- "string (char* or char[]) argument for this option"
- )
-_CURL_WARNING(_curl_easy_setopt_err_write_callback,
- "curl_easy_setopt expects a curl_write_callback argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_read_cb,
- "curl_easy_setopt expects a curl_read_callback argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
- "curl_easy_setopt expects a curl_ioctl_callback argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
- "curl_easy_setopt expects a curl_sockopt_callback argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
- "curl_easy_setopt expects a "
- "curl_opensocket_callback argument for this option"
- )
-_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
- "curl_easy_setopt expects a curl_progress_callback argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
- "curl_easy_setopt expects a curl_debug_callback argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
- "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
- "curl_easy_setopt expects a curl_conv_callback argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
- "curl_easy_setopt expects a curl_seek_callback argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_cb_data,
- "curl_easy_setopt expects a "
- "private data pointer as argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
- "curl_easy_setopt expects a "
- "char buffer of CURL_ERROR_SIZE as argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_FILE,
- "curl_easy_setopt expects a FILE* argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_postfields,
- "curl_easy_setopt expects a void* or char* argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
- "curl_easy_setopt expects a struct curl_httppost* argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
- "curl_easy_setopt expects a struct curl_slist* argument for this option")
-_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
- "curl_easy_setopt expects a CURLSH* argument for this option")
-
-_CURL_WARNING(_curl_easy_getinfo_err_string,
- "curl_easy_getinfo expects a pointer to char * for this info")
-_CURL_WARNING(_curl_easy_getinfo_err_long,
- "curl_easy_getinfo expects a pointer to long for this info")
-_CURL_WARNING(_curl_easy_getinfo_err_double,
- "curl_easy_getinfo expects a pointer to double for this info")
-_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
- "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
-
-/* groups of curl_easy_setops options that take the same type of argument */
-
-/* To add a new option to one of the groups, just add
- * (option) == CURLOPT_SOMETHING
- * to the or-expression. If the option takes a long or curl_off_t, you don't
- * have to do anything
- */
-
-/* evaluates to true if option takes a long argument */
-#define _curl_is_long_option(option) \
- (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
-
-#define _curl_is_off_t_option(option) \
- ((option) > CURLOPTTYPE_OFF_T)
-
-/* evaluates to true if option takes a char* argument */
-#define _curl_is_string_option(option) \
- ((option) == CURLOPT_URL || \
- (option) == CURLOPT_PROXY || \
- (option) == CURLOPT_INTERFACE || \
- (option) == CURLOPT_NETRC_FILE || \
- (option) == CURLOPT_USERPWD || \
- (option) == CURLOPT_USERNAME || \
- (option) == CURLOPT_PASSWORD || \
- (option) == CURLOPT_PROXYUSERPWD || \
- (option) == CURLOPT_PROXYUSERNAME || \
- (option) == CURLOPT_PROXYPASSWORD || \
- (option) == CURLOPT_NOPROXY || \
- (option) == CURLOPT_ACCEPT_ENCODING || \
- (option) == CURLOPT_REFERER || \
- (option) == CURLOPT_USERAGENT || \
- (option) == CURLOPT_COOKIE || \
- (option) == CURLOPT_COOKIEFILE || \
- (option) == CURLOPT_COOKIEJAR || \
- (option) == CURLOPT_COOKIELIST || \
- (option) == CURLOPT_FTPPORT || \
- (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
- (option) == CURLOPT_FTP_ACCOUNT || \
- (option) == CURLOPT_RANGE || \
- (option) == CURLOPT_CUSTOMREQUEST || \
- (option) == CURLOPT_SSLCERT || \
- (option) == CURLOPT_SSLCERTTYPE || \
- (option) == CURLOPT_SSLKEY || \
- (option) == CURLOPT_SSLKEYTYPE || \
- (option) == CURLOPT_KEYPASSWD || \
- (option) == CURLOPT_SSLENGINE || \
- (option) == CURLOPT_CAINFO || \
- (option) == CURLOPT_CAPATH || \
- (option) == CURLOPT_RANDOM_FILE || \
- (option) == CURLOPT_EGDSOCKET || \
- (option) == CURLOPT_SSL_CIPHER_LIST || \
- (option) == CURLOPT_KRBLEVEL || \
- (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
- (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
- (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
- (option) == CURLOPT_CRLFILE || \
- (option) == CURLOPT_ISSUERCERT || \
- (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
- (option) == CURLOPT_SSH_KNOWNHOSTS || \
- (option) == CURLOPT_MAIL_FROM || \
- (option) == CURLOPT_RTSP_SESSION_ID || \
- (option) == CURLOPT_RTSP_STREAM_URI || \
- (option) == CURLOPT_RTSP_TRANSPORT || \
- 0)
-
-/* evaluates to true if option takes a curl_write_callback argument */
-#define _curl_is_write_cb_option(option) \
- ((option) == CURLOPT_HEADERFUNCTION || \
- (option) == CURLOPT_WRITEFUNCTION)
-
-/* evaluates to true if option takes a curl_conv_callback argument */
-#define _curl_is_conv_cb_option(option) \
- ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
- (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
- (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
-
-/* evaluates to true if option takes a data argument to pass to a callback */
-#define _curl_is_cb_data_option(option) \
- ((option) == CURLOPT_WRITEDATA || \
- (option) == CURLOPT_READDATA || \
- (option) == CURLOPT_IOCTLDATA || \
- (option) == CURLOPT_SOCKOPTDATA || \
- (option) == CURLOPT_OPENSOCKETDATA || \
- (option) == CURLOPT_PROGRESSDATA || \
- (option) == CURLOPT_WRITEHEADER || \
- (option) == CURLOPT_DEBUGDATA || \
- (option) == CURLOPT_SSL_CTX_DATA || \
- (option) == CURLOPT_SEEKDATA || \
- (option) == CURLOPT_PRIVATE || \
- (option) == CURLOPT_SSH_KEYDATA || \
- (option) == CURLOPT_INTERLEAVEDATA || \
- (option) == CURLOPT_CHUNK_DATA || \
- (option) == CURLOPT_FNMATCH_DATA || \
- 0)
-
-/* evaluates to true if option takes a POST data argument (void* or char*) */
-#define _curl_is_postfields_option(option) \
- ((option) == CURLOPT_POSTFIELDS || \
- (option) == CURLOPT_COPYPOSTFIELDS || \
- 0)
-
-/* evaluates to true if option takes a struct curl_slist * argument */
-#define _curl_is_slist_option(option) \
- ((option) == CURLOPT_HTTPHEADER || \
- (option) == CURLOPT_HTTP200ALIASES || \
- (option) == CURLOPT_QUOTE || \
- (option) == CURLOPT_POSTQUOTE || \
- (option) == CURLOPT_PREQUOTE || \
- (option) == CURLOPT_TELNETOPTIONS || \
- (option) == CURLOPT_MAIL_RCPT || \
- 0)
-
-/* groups of curl_easy_getinfo infos that take the same type of argument */
-
-/* evaluates to true if info expects a pointer to char * argument */
-#define _curl_is_string_info(info) \
- (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
-
-/* evaluates to true if info expects a pointer to long argument */
-#define _curl_is_long_info(info) \
- (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
-
-/* evaluates to true if info expects a pointer to double argument */
-#define _curl_is_double_info(info) \
- (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
-
-/* true if info expects a pointer to struct curl_slist * argument */
-#define _curl_is_slist_info(info) \
- (CURLINFO_SLIST < (info))
-
-
-/* typecheck helpers -- check whether given expression has requested type*/
-
-/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
- * otherwise define a new macro. Search for __builtin_types_compatible_p
- * in the GCC manual.
- * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
- * the actual expression passed to the curl_easy_setopt macro. This
- * means that you can only apply the sizeof and __typeof__ operators, no
- * == or whatsoever.
- */
-
-/* XXX: should evaluate to true iff expr is a pointer */
-#define _curl_is_any_ptr(expr) \
- (sizeof(expr) == sizeof(void*))
-
-/* evaluates to true if expr is NULL */
-/* XXX: must not evaluate expr, so this check is not accurate */
-#define _curl_is_NULL(expr) \
- (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
-
-/* evaluates to true if expr is type*, const type* or NULL */
-#define _curl_is_ptr(expr, type) \
- (_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), type *) || \
- __builtin_types_compatible_p(__typeof__(expr), const type *))
-
-/* evaluates to true if expr is one of type[], type*, NULL or const type* */
-#define _curl_is_arr(expr, type) \
- (_curl_is_ptr((expr), type) || \
- __builtin_types_compatible_p(__typeof__(expr), type []))
-
-/* evaluates to true if expr is a string */
-#define _curl_is_string(expr) \
- (_curl_is_arr((expr), char) || \
- _curl_is_arr((expr), signed char) || \
- _curl_is_arr((expr), unsigned char))
-
-/* evaluates to true if expr is a long (no matter the signedness)
- * XXX: for now, int is also accepted (and therefore short and char, which
- * are promoted to int when passed to a variadic function) */
-#define _curl_is_long(expr) \
- (__builtin_types_compatible_p(__typeof__(expr), long) || \
- __builtin_types_compatible_p(__typeof__(expr), signed long) || \
- __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
- __builtin_types_compatible_p(__typeof__(expr), int) || \
- __builtin_types_compatible_p(__typeof__(expr), signed int) || \
- __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
- __builtin_types_compatible_p(__typeof__(expr), short) || \
- __builtin_types_compatible_p(__typeof__(expr), signed short) || \
- __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
- __builtin_types_compatible_p(__typeof__(expr), char) || \
- __builtin_types_compatible_p(__typeof__(expr), signed char) || \
- __builtin_types_compatible_p(__typeof__(expr), unsigned char))
-
-/* evaluates to true if expr is of type curl_off_t */
-#define _curl_is_off_t(expr) \
- (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
-
-/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
-/* XXX: also check size of an char[] array? */
-#define _curl_is_error_buffer(expr) \
- (__builtin_types_compatible_p(__typeof__(expr), char *) || \
- __builtin_types_compatible_p(__typeof__(expr), char[]))
-
-/* evaluates to true if expr is of type (const) void* or (const) FILE* */
-#if 0
-#define _curl_is_cb_data(expr) \
- (_curl_is_ptr((expr), void) || \
- _curl_is_ptr((expr), FILE))
-#else /* be less strict */
-#define _curl_is_cb_data(expr) \
- _curl_is_any_ptr(expr)
-#endif
-
-/* evaluates to true if expr is of type FILE* */
-#define _curl_is_FILE(expr) \
- (__builtin_types_compatible_p(__typeof__(expr), FILE *))
-
-/* evaluates to true if expr can be passed as POST data (void* or char*) */
-#define _curl_is_postfields(expr) \
- (_curl_is_ptr((expr), void) || \
- _curl_is_arr((expr), char))
-
-/* FIXME: the whole callback checking is messy...
- * The idea is to tolerate char vs. void and const vs. not const
- * pointers in arguments at least
- */
-/* helper: __builtin_types_compatible_p distinguishes between functions and
- * function pointers, hide it */
-#define _curl_callback_compatible(func, type) \
- (__builtin_types_compatible_p(__typeof__(func), type) || \
- __builtin_types_compatible_p(__typeof__(func), type*))
-
-/* evaluates to true if expr is of type curl_read_callback or "similar" */
-#define _curl_is_read_cb(expr) \
- (_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \
- _curl_callback_compatible((expr), _curl_read_callback1) || \
- _curl_callback_compatible((expr), _curl_read_callback2) || \
- _curl_callback_compatible((expr), _curl_read_callback3) || \
- _curl_callback_compatible((expr), _curl_read_callback4) || \
- _curl_callback_compatible((expr), _curl_read_callback5) || \
- _curl_callback_compatible((expr), _curl_read_callback6))
-typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void *);
-typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void *);
-typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE *);
-typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void *);
-typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void *);
-typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE *);
-
-/* evaluates to true if expr is of type curl_write_callback or "similar" */
-#define _curl_is_write_cb(expr) \
- (_curl_is_read_cb(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \
- _curl_callback_compatible((expr), _curl_write_callback1) || \
- _curl_callback_compatible((expr), _curl_write_callback2) || \
- _curl_callback_compatible((expr), _curl_write_callback3) || \
- _curl_callback_compatible((expr), _curl_write_callback4) || \
- _curl_callback_compatible((expr), _curl_write_callback5) || \
- _curl_callback_compatible((expr), _curl_write_callback6))
-typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void *);
-typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
- const void *);
-typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE *);
-typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void *);
-typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
- const void *);
-typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE *);
-
-/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
-#define _curl_is_ioctl_cb(expr) \
- (_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \
- _curl_callback_compatible((expr), _curl_ioctl_callback1) || \
- _curl_callback_compatible((expr), _curl_ioctl_callback2) || \
- _curl_callback_compatible((expr), _curl_ioctl_callback3) || \
- _curl_callback_compatible((expr), _curl_ioctl_callback4))
-typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void *);
-typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void *);
-typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void *);
-typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
-
-/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
-#define _curl_is_sockopt_cb(expr) \
- (_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \
- _curl_callback_compatible((expr), _curl_sockopt_callback1) || \
- _curl_callback_compatible((expr), _curl_sockopt_callback2))
-typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
-typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
- curlsocktype);
-
-/* evaluates to true if expr is of type curl_opensocket_callback or
- "similar" */
-#define _curl_is_opensocket_cb(expr) \
- (_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
- _curl_callback_compatible((expr), _curl_opensocket_callback1) || \
- _curl_callback_compatible((expr), _curl_opensocket_callback2) || \
- _curl_callback_compatible((expr), _curl_opensocket_callback3) || \
- _curl_callback_compatible((expr), _curl_opensocket_callback4))
-typedef curl_socket_t (_curl_opensocket_callback1)
-(void *, curlsocktype, struct curl_sockaddr *);
-typedef curl_socket_t (_curl_opensocket_callback2)
-(void *, curlsocktype, const struct curl_sockaddr *);
-typedef curl_socket_t (_curl_opensocket_callback3)
-(const void *, curlsocktype, struct curl_sockaddr *);
-typedef curl_socket_t (_curl_opensocket_callback4)
-(const void *, curlsocktype, const struct curl_sockaddr *);
-
-/* evaluates to true if expr is of type curl_progress_callback or "similar" */
-#define _curl_is_progress_cb(expr) \
- (_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \
- _curl_callback_compatible((expr), _curl_progress_callback1) || \
- _curl_callback_compatible((expr), _curl_progress_callback2))
-typedef int (_curl_progress_callback1)(void *,
- double, double, double, double);
-typedef int (_curl_progress_callback2)(const void *,
- double, double, double, double);
-
-/* evaluates to true if expr is of type curl_debug_callback or "similar" */
-#define _curl_is_debug_cb(expr) \
- (_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \
- _curl_callback_compatible((expr), _curl_debug_callback1) || \
- _curl_callback_compatible((expr), _curl_debug_callback2) || \
- _curl_callback_compatible((expr), _curl_debug_callback3) || \
- _curl_callback_compatible((expr), _curl_debug_callback4))
-typedef int (_curl_debug_callback1) (CURL *,
- curl_infotype, char *, size_t, void *);
-typedef int (_curl_debug_callback2) (CURL *,
- curl_infotype, char *, size_t, const void *);
-typedef int (_curl_debug_callback3) (CURL *,
- curl_infotype, const char *, size_t, void *);
-typedef int (_curl_debug_callback4) (CURL *,
- curl_infotype, const char *, size_t, const void *);
-
-/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
-/* this is getting even messier... */
-#define _curl_is_ssl_ctx_cb(expr) \
- (_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \
- _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
- _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
- _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
- _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
- _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
- _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
- _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
- _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
-typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
-typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
-typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
-typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
-#ifdef HEADER_SSL_H
-/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
- * this will of course break if we're included before OpenSSL headers...
- */
-typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
-typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
-typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
-typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
- const void *);
-#else
-typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
-typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
-typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
-typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
-#endif
-
-/* evaluates to true if expr is of type curl_conv_callback or "similar" */
-#define _curl_is_conv_cb(expr) \
- (_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \
- _curl_callback_compatible((expr), _curl_conv_callback1) || \
- _curl_callback_compatible((expr), _curl_conv_callback2) || \
- _curl_callback_compatible((expr), _curl_conv_callback3) || \
- _curl_callback_compatible((expr), _curl_conv_callback4))
-typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
-typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
-typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
-typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
-
-/* evaluates to true if expr is of type curl_seek_callback or "similar" */
-#define _curl_is_seek_cb(expr) \
- (_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \
- _curl_callback_compatible((expr), _curl_seek_callback1) || \
- _curl_callback_compatible((expr), _curl_seek_callback2))
-typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
-typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
-
-
-#endif /* __CURL_TYPECHECK_GCC_H */
+++ /dev/null
-1.Put the plugin library "libplugin-hue-light.so" ,xml file "plugin.xml", in a prepared folder, such as "/root/hue_plugin/"
-2.Set the hue bridge user to "newdeveloper"
-3.Using plugin manager tool
- ./cpluff-console /root/hue_plugin run
-
-!!!for the hub network enviroment, you should add a route list for multicast
-#route add default gw 192.168.0.1 eth0
-
+++ /dev/null
-#include <stdio.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <string.h>
-#include <iostream>
-#include <boost/algorithm/string.hpp>
-#include "HueBridge.h"
-using namespace std;
-
-HueBridgeConnection::HueBridgeConnection()
-{
- //TODO
-}
-
-HueBridgeConnection::~HueBridgeConnection()
-{
- //TODO
-}
-
-string HueBridgeConnection::UpnpDiscovery()
-{
- struct sockaddr_in addrin, localaddr ;
- struct timeval rtime ;
- int newsock ;
- int ret ;
- char buf[1024] ;
- int i = 0 ;
- int yes = 1 ;
- socklen_t addr_len = sizeof(struct sockaddr_in);
-
- rtime.tv_sec = 2 ;
- rtime.tv_usec = 0 ;
-
- string host = "HOST: 239.255.255.250:1900\r\n";
- string st = "ST: upnp:rootdevice\r\n";
-// string st = "ST: ssdp:all\r\n";
- string mx = "MX: 3\r\n";
- string man = "MAN: ssdp:discover\r\n";
- string ssdp_msg = "M-SEARCH * HTTP/1.1\r\n";
-
- ssdp_msg.append(host).append(man).append(mx).append(st);
-
- bzero(&addrin, sizeof(addrin));
- addrin.sin_family = AF_INET;
- addrin.sin_addr.s_addr = inet_addr("239.255.255.250"); //htonl(INADDR_ANY)
-// addrin.sin_addr.s_addr = htonl(INADDR_ANY);
- addrin.sin_port = htons(1900);
-
- bzero(&localaddr, sizeof(localaddr));
- localaddr.sin_family = AF_INET;
- localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- localaddr.sin_port = htons(1901);
-
- newsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if ( newsock < 0) {return "";}
-
- ret = setsockopt( newsock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&rtime, sizeof(struct timeval));
- if (ret == -1)
- {
- close(newsock);
- return "";
- }
- ret = setsockopt( newsock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) ;
- if (ret == -1)
- {
- close(newsock);
- return "";
- }
-
- bind(newsock, (struct sockaddr *)&localaddr, addr_len);
-
- string hue_bridge;
- while (i < 10)
- {
- i++;
- yes = sizeof(struct sockaddr_in);
- memset(buf, 0, sizeof(buf));
- ssize_t ret_num;
- ret_num = sendto(newsock, ssdp_msg.c_str(), ssdp_msg.size(), 0, (struct sockaddr *)&addrin,
- addr_len);
- if (ret_num == -1)
- {
- close(newsock);
- return "";
- }
- ret = recvfrom( newsock, buf, sizeof(buf), 0, (struct sockaddr *)&addrin, &addr_len);
- if ( ret < 0 ) {continue;}
- else
- {
- hue_bridge = inet_ntoa(addrin.sin_addr);
- break;
- }
- }
- close(newsock);
- return hue_bridge;
-}
-
-
-
-vector<string> GetBridges()
-{
- vector<string> bridge_list;
- int i = 0;
- while (i < 5)
- {
- HueBridgeConnection *p = new HueBridgeConnection();
- string hue_bridge = p->UpnpDiscovery();
- vector<string>::iterator findit = find(bridge_list.begin(), bridge_list.end(), hue_bridge);
- if (findit == bridge_list.end())
- bridge_list.push_back(hue_bridge);
- delete p;
- i++;
- }
- return bridge_list;
-}
-
+++ /dev/null
-#ifndef __HUE_BRIDGE_H__
-#define __HUE_BRIDGE_H__
-#include<string>
-#include<vector>
-using namespace std;
-
-class HueBridgeConnection
-{
- public:
- HueBridgeConnection();
- virtual ~HueBridgeConnection();
- string UpnpDiscovery();
-};
-
-extern "C" {
- vector<string> GetBridges();
-}
-#endif //__HUE_BRIDGE_H__
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Intel Corporation All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-///
-/// This sample provides steps to define an interface for a resource
-/// (properties and methods) and host this resource on the server.
-///
-
-#include "HueLightHandler.h"
-
-namespace OIC
-{
-
- void resourceHandler(std::shared_ptr<OC::OCResource> resource);
-
-
- /// This class represents a single resource named 'lightResource'. This resource has
- /// two simple properties named 'state'
-
- LightResource::LightResource(string &resUrl, string &resType, string &resInterface,
- string e_url): m_state(false), m_color(0), m_bright(0)
- {
- std::cout << "create LightResource ......." << std::endl;
- resourceURL = resUrl;
- resourceTypeName = resType;
- resourceInterface = resInterface;
- ext_url = e_url;
- std::cout << "ResUrl = " << resourceURL << std::endl;
- std::cout << "resType = " << resType << std::endl;
- std::cout << "resInterface = " << resInterface << std::endl;
- std::cout << "m_state = " << m_state << std::endl;
- std::cout << "m_color = " << m_color << std::endl;
- std::cout << "m_bright = " << m_bright << std::endl;
- std::cout << "ext_url = " << ext_url << std::endl;
- m_resourceHandle = NULL;
-
- resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- }
-
- LightResource::~LightResource() {std::cout << "Leave LightResource" << std::endl;}
-
- /* To find if the resource instance is in the platform */
-
- OCStackResult LightResource::findResource(OC::OCPlatform &platform)
- {
- string host = "";
- std::cout << "ResUrl = " << resourceURL << std::endl;
- OCStackResult result = platform.findResource(host, resourceURL, &resourceHandler);
- if (OC_STACK_OK != result)
- {
- cout << "findResource unsuccessful\n";
- }
- else { cout << "findResource successful\n"; }
- return result;
- }
-
-
- OCStackResult LightResource::addType(const OC::OCPlatform &platform, const std::string &type)
- {
- OCStackResult result = platform.bindTypeToResource(m_resourceHandle, type);
- if (OC_STACK_OK != result)
- {
- cout << "Binding TypeName to Resource was unsuccessful\n";
- }
- return result;
- }
-
- OCStackResult LightResource::addInterface(const OC::OCPlatform &platform,
- const std::string &interface)
- {
- OCStackResult result = platform.bindInterfaceToResource(m_resourceHandle, interface);
- if (OC_STACK_OK != result)
- {
- cout << "Binding Interface to Resource was unsuccessful\n";
- }
- return result;
- }
-
-// /* This function internally calls intel registerResource API to unregister a leaved resource*/
-// void LightResource::unregisterResource(OC::OCPlatform& platform)
-// {
-// OC::OCStackResult result = platform.unregisterResource(
-// m_resourceHandle, resourceURL, resourceTypeName,
-// resourceInterface, &entityHandler, resourceProperty);
-// if (OC::OC_STACK_OK != result)
-// {
-// cout << "Resource destory was unsuccessful\n";
-// }
-// }
-//
-///*
- OCResourceHandle LightResource::getHandle()
- {
- return m_resourceHandle;
- }
-
-
- void LightResource::setRepresentation(OC::OCRepresentation &light)
- {
- OC::AttributeMap attributeMap = light.getAttributeMap();
- std::cout << "Enter setRepresentation" << std::endl;
- cout << "\t\t\t" << "Received representation: " << endl;
- cout << "\t\t\t\t" << "state: " << attributeMap["state"][0] << endl;
- cout << "\t\t\t\t" << "color: " << attributeMap["color"][0] << endl;
- cout << "\t\t\t\t" << "bright: " << attributeMap["bright"][0] << endl;
-
- m_state = attributeMap["state"][0].compare("true") == 0;
- m_color = std::stoi(attributeMap["color"][0]);
- m_bright = std::stoi(attributeMap["bright"][0]);
- }
-
- OC::OCRepresentation LightResource::getRepresentation()
- {
- OC::OCRepresentation light;
- light.setUri(resourceURL);
-
- std::cout << "Enter getRepresentation" << std::endl;
-
- std::vector<std::string> interfaces;
- light.setResourceInterfaces(interfaces);
-
- std::vector<std::string> types;
- //types.push_back(m_lightType);
- light.setResourceTypes(types);
-
- OC::AttributeMap attributeMap;
- OC::AttributeValues stateVal;
- if (m_state)
- {
- stateVal.push_back("true");
- }
- else
- {
- stateVal.push_back("false");
- }
- OC::AttributeValues colorVal;
- colorVal.push_back(to_string(m_color));
-
- OC::AttributeValues brightVal;
- brightVal.push_back(to_string(m_bright));
-
- attributeMap["state"] = stateVal;
- attributeMap["color"] = colorVal;
- attributeMap["bright"] = brightVal;
- light.setAttributeMap(attributeMap);
-
- return light;
- }
-
-
- void resourceHandler(std::shared_ptr<OC::OCResource> resource)
- {
- std::cout << "Enter resourceHandler" << std::endl;
- }
-
-
- /* This function internally calls intel registerResource API to register a new joined resource */
- OCStackResult LightResource::registerResource(OC::OCPlatform &platform,
- std::function<void(const OC::OCResourceRequest::Ptr, const OC::OCResourceResponse::Ptr)>
- entityHandler)
- {
- OCStackResult result = platform.registerResource(
- m_resourceHandle, resourceURL, resourceTypeName,
- resourceInterface, entityHandler, resourceProperty);
- if (OC_STACK_OK != result)
- {
- cout << "Resource register was unsuccessful\n";
- }
- else { cout << "RegisterResource successful\n"; }
- return result;
- }
-
- LightContainer::LightContainer(string &resUrl, string &resType,
- string &resInterface): LightResource(resUrl, resType, resInterface, "")
- {
- std::cout << "Enter Constructor Container" << std::endl;
- }
- LightContainer::~LightContainer()
- {
- std::cout << "Enter Disonstructor Container" << std::endl;
- if (m_container.empty()) std::cout << "Empty---- No need disconnstrator" << std::endl;
- else m_container.clear();
- std::cout << "LightContainer disconstrator end ...." << std::endl;
- }
-}
-
-
-
-
-// Entity handler can be implemented in several ways by the manufacturer
-
-
+++ /dev/null
-#include <functional>
-
-#include <pthread.h>
-
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-
-namespace OIC
-{
- void resourceHandler(std::shared_ptr<OC::OCResource> resource);
- class LightResource
- {
- public:
- bool m_state;
- int m_color;
- int m_bright;
- OCResourceHandle m_resourceHandle;
-
- std::string resourceURL; // URI of the resource
- std::string resourceTypeName; // resource type name. In this case, it is light
- std::string resourceInterface; // resource interface.
- std::string ext_url;
-
- // OCResourceProperty is defined ocstack.h
- uint8_t resourceProperty;
-
- public:
- /// Constructor
- LightResource(string &resUrl, string &resType, string &resInterface, string e_url);
- LightResource();
- virtual ~LightResource();
-
- /* Note that this does not need to be a member function: for classes you do not have
- access to, you can accomplish this with a free function: */
-
- // This function internally calls registerResource API.
- OCStackResult findResource(OC::OCPlatform &platform);
- OCStackResult registerResource(OC::OCPlatform &platform,
- std::function<void(const OC::OCResourceRequest::Ptr, const OC::OCResourceResponse::Ptr)>
- entityHandler);
-// void unregisterResource(OC::OCPlatform& platform);
-//
- OCResourceHandle getHandle();
- void setRepresentation(OC::OCRepresentation &light);
- OC::OCRepresentation getRepresentation();
- OCStackResult addType(const OC::OCPlatform &platform, const std::string &type);
- OCStackResult addInterface(const OC::OCPlatform &platform, const std::string &interface);
- };
-
- class LightContainer: public LightResource
- {
- public:
- vector<LightResource> m_container;
- LightContainer(string &resUrl, string &resType, string &resInterface);
- virtual ~LightContainer();
- };
-
-}
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file HuePlugin.cpp
-
-/// @brief
-
-
-#include <typeinfo>
-#include "curl/curl.h"
-#include <unistd.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <string.h>
-#include "HueBridge.h"
-
-#include "HuePlugin.h"
-#include "json_parse.h"
-#include "simple_parse.h"
-
-
-using namespace std;
-using namespace boost::property_tree;
-using namespace boost;
-
-using namespace OIC;
-
-
-/**
- * Response Data for curl handler to hue bridge
- * @return Return the number of response data
- *
- */
-static size_t OnWriteData(void *buffer, size_t size, size_t nmemb, void *lpVoid)
-{
- std::string *str = dynamic_cast<std::string *>((std::string *)lpVoid);
- if ( NULL == str || NULL == buffer )
- {
- return -1;
- }
- char *pData = (char *)buffer;
- str->append(pData, size * nmemb);
- return nmemb;
-}
-
-
-HuePlugin::HuePlugin() {cout << "HuePlugin::HuePlugin()" << endl;}
-HuePlugin::~HuePlugin() { cout << "HuePlugin::~HuePlugin()" << endl;}
-
-
-/**
- * convert received json object to our defined resource info
- *
- */
-void HuePlugin::ConvertOcRes(string &hueRes, map<string, string> &dictmap)
-{
- stringstream stream;
- ptree pt;
- cout << "ConvertOcRes --" << hueRes.c_str() << endl;
- if (hueRes.size())
- {
-
- replace_all(hueRes, "u\'", "\"");
- replace_all(hueRes, "\'", "\"");
-
- stream << hueRes;
- read_json<ptree>(stream, pt);
- string lig_id, lig_name;
- for (ptree::iterator it = pt.begin(); it != pt.end(); ++it)
- {
- lig_id = it->first;
- lig_name = it->second.get<string>("name"); //first为空
- dictmap.insert(make_pair(lig_id, lig_name));
- }
- }
-}
-
-
-/**
- * Found the changed hue resources
- *
- * @param oldR the vector for the last search result
- * @param newR the vector for the current search result
- * @param comm the vector for both oldR and newR contain
- * @return the map for changed resrouces
- */
-
-map<string, string> HuePlugin::ResourcesChange(vector<string> &oldR, vector<string> &newR,
- vector<string> &comm)
-{
- vector<string>tempR;
- vector<string>::iterator iter = oldR.begin();
- vector<string>::iterator tempiter;
- while (iter != oldR.end())
- {
- tempiter = find(newR.begin(), newR.end(), iter->c_str());
- if (tempiter != newR.end())
- {
- comm.push_back(tempiter->c_str());
- }
- iter++;
- }
- iter = comm.begin();
- while (iter != comm.end())
- {
- tempiter = find(oldR.begin(), oldR.end(), iter->c_str());
- if (tempiter != oldR.end())
- {
- oldR.erase(tempiter);
- }
- tempiter = find(newR.begin(), newR.end(), iter->c_str());
- if (tempiter != newR.end())
- {
- newR.erase(tempiter);
- }
- iter++;
- }
- map<string, string>res_changed; // return the changed resource info
- for (iter = oldR.begin(); iter != oldR.end(); iter++)
- res_changed.insert(make_pair(*iter, "leave"));
- for (iter = newR.begin(); iter != newR.end(); iter++)
- res_changed.insert(make_pair(*iter, "join"));
-
- return res_changed;
-}
-
-
-/**
- * create a local xml file to mark the resources information
- *
- */
-
-//void HuePlugin::CreateResourcesFile(vector<OCResourceDesc>& resources, string& template_file)
-//{
-// OCResourceDescManager* pi = new OCResourceDescManager();
-// if(resources.size())
-// pi->CreateResourcesXMl(resources, template_file);
-// cout<<"After create xml file"<<endl;
-// delete pi;
-//}
-//
-
-/**
- * Search Resources by philips hue protocol.
- *
- * @return Return a vector, which members are ResourceDesc type, a inner defined structure
- *
- */
-
-vector<OCResourceDesc> HuePlugin::SearchDeviceResources(vector<string> &pool)
-{
- cout << "HuePlugin::SearchDeviceResources()" << endl;
-
- res_pool = pool;
-
-
- vector<string>dev_url;
- vector<string>new_res_pool;
-
- vector<OCResourceDesc> change_resources;
- vector<OCResourceDesc> template_resources;
-
- vector<string> bridge_list;
- bridge_list = GetBridges();
- if (bridge_list.empty())
- {
- cout << "No hue bridge found" << endl;
- return change_resources;
- }
- vector<string>::iterator it;
- cout << "the result: " << endl;
- for (it = bridge_list.begin(); it != bridge_list.end(); it++)
- {
- cout << *it << "," << endl;
- string hue_bridge_url;
- hue_bridge_url.append("http://").append(*it).append("/api/newdeveloper/lights");
- cout << "total url ---" << hue_bridge_url << endl;
- dev_url.push_back(hue_bridge_url);
- }
-
- vector<string>::iterator url_iter;
- vector<pthread_t> tids;
- for (url_iter = dev_url.begin(); url_iter != dev_url.end(); url_iter++)
- {
- string strUrl = *url_iter;
- string strResponse;
- cout << "ready to get_all_lights: " << strUrl << endl;
-
- CURLcode res;
- struct curl_slist *headers = NULL;
- headers = curl_slist_append(headers, "Content-Type: application/json");
-
- cout << "ready to curl" << endl;
- CURL *curl = curl_easy_init();
- if (NULL == curl)
- {
- cout << "error" << endl;
- }
-
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
- curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
- res = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
- curl_slist_free_all(headers);
-
- cout << "response " << strResponse.c_str() << endl;
-
- map<string, string> dictmap;
- HuePlugin::ConvertOcRes((string &) strResponse, dictmap);
- map<string, string>::iterator it;
- for (it = dictmap.begin(); it != dictmap.end(); it++)
- {
- string res_url = strUrl;
- res_url.append("/").append(it->first).append("/state");
- new_res_pool.push_back(res_url);
- }
-
- }
-
- vector<string> res_comm_pool;
-
- pool = new_res_pool;
- map<string, string> res_changed = ResourcesChange(res_pool, new_res_pool, res_comm_pool);
-
- for (map<string, string>::iterator m_it = res_changed.begin(); m_it != res_changed.end(); m_it++)
- {
- string resUrl = m_it->first;
- cout << "Changed resource: " << resUrl << endl;
- size_t l_pos, r_pos;
- l_pos = resUrl.find("//");
- r_pos = resUrl.find("/", l_pos + 2);
- string br_ip = resUrl.substr(l_pos + 2, r_pos - l_pos - 2);
- size_t index = resUrl.find_last_of("/");
- string add_res = resUrl.substr(index);
- string res_id = br_ip.append(add_res);
-
- string res_state = m_it->second;
- string res_type = "light";
-
- OCResourceDesc r(res_id, res_type, resUrl, res_state);
- change_resources.push_back(r);
- template_resources.push_back(r);
- }
-
- for (vector<string>::iterator iter = res_comm_pool.begin(); iter != res_comm_pool.end(); iter++)
- {
- string resUrl = *iter;
- size_t l_pos, r_pos;
- l_pos = resUrl.find("//");
- r_pos = resUrl.find("/", l_pos + 2);
- string br_ip = resUrl.substr(l_pos + 2, r_pos - l_pos - 2);
- size_t index = resUrl.find_last_of("/");
- string add_res = resUrl.substr(index);
- string res_id = br_ip.append(add_res);
-
- string res_state = "keep";
- string res_type = "light";
-
- OCResourceDesc r(res_id, res_type, resUrl, res_state);
- template_resources.push_back(r);
- }
-
-// cout << "ready to create Xml file"<<endl;
-// size_t rpos = real_conf_file.find_last_of("/");
-// string abs_path = real_conf_file.substr(0,rpos+1);
-// string template_file = abs_path.append("test.xml");
-// CreateResourcesFile(template_resources,template_file);
-
-// cout << "Create Xml file OK "<<endl;
- return change_resources;
-}
-
-
-/**
- * Read config file to fetch the Hue bridge search info
- *
- * @return Return a vector, which members are hue url type
- *
- */
-
-//vector<string> HuePlugin::ReadConfig(const char* filepath)
-//{
-// string filename(filepath);
-// vector<string> devUrl;
-//
-// if(filename.find(".json") != string::npos){
-// cout<<"json file !"<<endl;
-// ptree pt, p1, p2;
-// string hue_ip,hue_user, hue_res, hue_ext;
-//
-// read_json<ptree>(filename, pt);
-// p1 = pt.get_child("bridges");
-// hue_res = pt.get<string>("resource");
-// hue_ext = pt.get<string>("extra");
-//
-// for (ptree::iterator it = p1.begin(); it != p1.end(); ++it)
-// {
-// p2 = it->second; //first为空
-// hue_ip = p2.get<string>("ip");
-// hue_user = p2.get<string>("username");
-//
-// string hue_url;
-//
-// hue_url.append("http://");
-// hue_url.append(hue_ip);
-//// hue_url.append(":8080/");
-// hue_url.append("/");
-// hue_url.append(hue_ext);
-// hue_url.append("/");
-// hue_url.append(hue_user);
-// hue_url.append("/");
-// hue_url.append(hue_res);
-// cout<<"Hue Url --- "<<hue_url<<endl;
-// devUrl.push_back(hue_url);
-// }
-// }else if(filename.find(".ini") != string::npos){
-// cout<<"ini file !"<<endl;
-// cout<<"filepath = "<<filepath<<endl;
-// string ip_lst, uname_lst, res, ext;
-//
-// string key="ip";
-// readConfigFile(filepath,(const string&)key, (string&)ip_lst);
-// vector<string> ip_vc;
-// ip_vc = NormalizedOut((string&)ip_lst);
-//
-// key="username";
-// readConfigFile(filepath,(const string&)key, (string&)uname_lst);
-// vector<string> uname_vc;
-// uname_vc = NormalizedOut((string&)uname_lst);
-//
-// vector<string>::iterator iter1, iter2;
-// map<string, string> dictmap;
-// for(iter1 = ip_vc.begin(), iter2 = uname_vc.begin(); iter1 != ip_vc.end(), iter2 != uname_vc.end(); iter1++,iter2++)
-// {
-//// dictmap.insert(make_pair(*iter1, *iter2));
-// dictmap.insert(make_pair(*iter2, *iter1));
-// }
-//
-// key = "extra";
-// readConfigFile(filepath,(const string&)key, (string&)ext);
-//
-// key = "resource";
-// readConfigFile(filepath,(const string&)key, (string&)res);
-//
-// map<string, string>::iterator it;
-// for (it=dictmap.begin();it!=dictmap.end();it++)
-// {
-// string hue_url;
-//
-// hue_url.append("http://");
-//// hue_url.append(it->first);
-// hue_url.append(it->second);
-//// hue_url.append(":8080/");
-// hue_url.append("/");
-// hue_url.append(ext);
-// hue_url.append("/");
-//// hue_url.append(it->second);
-// hue_url.append(it->first);
-// hue_url.append("/");
-// hue_url.append(res);
-// cout<<"Hue Url --- "<<hue_url<<endl;
-// devUrl.push_back(hue_url);
-// }
-// }
-// return devUrl;
-//}
-
-
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file HuePlugin.h
-
-/// @brief
-
-#ifndef __HUEPlUGIN_H__
-#define __HUEPlUGIN_H__
-#include <iostream>
-#include <vector>
-#include <map>
-#include <string>
-#include "OCResourceDesc.h"
-
-namespace OIC
-{
- class HuePlugin
- {
- public:
- HuePlugin();
- virtual ~HuePlugin();
-
- /**
- * Search Resources by philips hue protocol.
- *
- *@return Return a vector, which members are ResourceDesc type
- *
- */
- std::vector<OCResourceDesc> SearchDeviceResources(std::vector<string> &pool);
-
- /**
- * Read config file to fetch the Hue bridge search info
- *
- *@return Return a vector, which members are hue url type
- *
- */
-// std::vector<string> ReadConfig(const char* filepath);
-
- /**
- * convert received json object to we defined resource info struct
- */
- void ConvertOcRes(string &hueRes, std::map<string, string> &dictmap);
-
- /**
- * create a local xml file to mark the resources information
- *@resources Resources info
- *@template_file the xml file
- *
- */
- void CreateResourcesFile(std::vector<OCResourceDesc> &resources, string &template_file);
-
- /**
- * fetch Resources change information
- *@param oldR the vector for the last search result
- @param newR the vector for the current search result
- @param comm the vector for both oldR and newR contain
- @return the map for changed resrouces
- */
- std::map<string, string> ResourcesChange(std::vector<string> &oldR, std::vector<string> &newR,
- std::vector<string> &comm);
- private:
- std::vector<string> res_pool;
- };
-}
-#endif //__HUEPlUGIN_H__
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file OCResourceDesc.cpp
-
-/// @brief
-
-#include "OCResourceDesc.h"
-
-
-OCResourceDesc::OCResourceDesc()
-{
- // TODO
-}
-OCResourceDesc::~OCResourceDesc()
-{
- // TODO
-}
-OCResourceDesc::OCResourceDesc(string t_res_id, string t_type, string t_res_url, string t_res_state)
-{
- resource_id = t_res_id;
- type = t_type;
- resource_url = t_res_url;
- resource_state = t_res_state;
-}
-void OCResourceDesc::SetResource_id(string id)
-{
- this->resource_id = id;
-}
-void OCResourceDesc::SetType(string type)
-{
- this->type = type;
-}
-void OCResourceDesc::SetResource_url(string url)
-{
- this->resource_url = url;
-}
-void OCResourceDesc::SetResource_state(string state)
-{
- this->resource_state = state;
-}
-string OCResourceDesc::GetResource_id()
-{
- return this->resource_id;
-};
-string OCResourceDesc::GetType()
-{
- return this->type;
-}
-string OCResourceDesc::GetResource_url()
-{
- return this->resource_url;
-}
-string OCResourceDesc::GetResource_state()
-{
- return this->resource_state;
-}
-
-
-//OCResourceDescManager::OCResourceDescManager(){
-// //todo
-//}
-//OCResourceDescManager::~OCResourceDescManager(){
-// //todo
-//}
-//void OCResourceDescManager::setresources(vector<OCResourceDesc>& resources){
-// this->ocResources=resources;
-//};
-//vector<OCResourceDesc> OCResourceDescManager::GetResources(){
-// return this->ocResources;
-//}
-//
-//vector<OCResourceDesc>* OCResourceDescManager::InitResources(string filename){
-// vector<OCResourceDesc>* resources=new vector<OCResourceDesc>();
-// TiXmlDocument *resourcesDoc = new TiXmlDocument();
-// resourcesDoc->LoadFile(filename.c_str());
-// TiXmlElement *RootElement = resourcesDoc->RootElement();
-// TiXmlElement *Resource = RootElement->FirstChildElement();
-// while(Resource){
-// OCResourceDesc* ocResource=new OCResourceDesc();
-// ocResource->SetResource_id(Resource->Attribute("id"));
-// TiXmlElement *ResourceChild=Resource->FirstChildElement();
-// while(ResourceChild){
-// if (strcmp( ResourceChild->Value(), "type")==0){
-// ocResource->SetType(ResourceChild->FirstChild()->Value());
-// }else if (strcmp(ResourceChild->Value(), "resource_url") == 0) {
-// ocResource->SetResource_url(ResourceChild->FirstChild()->Value());
-// }else if (strcmp(ResourceChild->Value(), "resource_state") == 0) {
-// ocResource->SetResource_state(ResourceChild->FirstChild()->Value());
-// } else{
-// cout<<"error xml";
-// }
-// ResourceChild=ResourceChild->NextSiblingElement();
-// }
-// //cout<<ocResource->GetDrive_name()<<endl;
-// resources->push_back(*ocResource);
-// Resource=Resource->NextSiblingElement();
-// }
-// delete resourcesDoc;
-// return resources;
-//}
-//
-//TiXmlElement* OCResourceDescManager::CreateResource(OCResourceDesc& resource) {
-// TiXmlElement *Resource = new TiXmlElement("resource");
-// Resource->SetAttribute("id", resource.GetResource_id().c_str());
-// TiXmlElement *type = new TiXmlElement("type");
-// TiXmlElement *url = new TiXmlElement("resource_url");
-// TiXmlElement *state = new TiXmlElement("resource_state");
-//
-// TiXmlText *typeContent = new TiXmlText(resource.GetType().c_str());
-// TiXmlText *urlContent = new TiXmlText(resource.GetResource_url().c_str());
-// TiXmlText *stateContent = new TiXmlText(resource.GetResource_state().c_str());
-//
-// type->LinkEndChild(typeContent);
-// url->LinkEndChild(urlContent);
-// state->LinkEndChild(stateContent);
-//
-// Resource->LinkEndChild(type);
-// Resource->LinkEndChild(url);
-// Resource->LinkEndChild(state);
-// if (NULL != Resource) {
-// return Resource;
-// } else {
-// return NULL;
-// }
-// return NULL;
-//}
-//
-//void OCResourceDescManager::CreateResourcesXMl(vector<OCResourceDesc>& resources,string filename){
-// TiXmlDocument *resourcesDoc = new TiXmlDocument();
-// resourcesDoc->LoadFile();
-// TiXmlDeclaration *pDeclaration = new TiXmlDeclaration(("1.0"), (""),(""));
-// TiXmlElement* resourcesElement = new TiXmlElement("resources");
-// vector<OCResourceDesc>::iterator iter;
-// iter = resources.begin();
-// TiXmlElement* element;
-// while (iter != resources.end()) {
-// element=this->CreateResource(*iter);
-// //cout<<element->Attribute("id");
-// resourcesElement->LinkEndChild(element);
-// *iter++;
-// }
-// resourcesDoc->LinkEndChild(pDeclaration);
-// resourcesDoc->LinkEndChild(resourcesElement);
-// resourcesDoc->SaveFile(filename.c_str());
-// delete element;
-// delete pDeclaration;
-//}
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file OCResourceDesc.h
-
-/// @brief
-
-#ifndef __OCRESOURCEDESC_H__
-#define __OCRESOURCEDESC_H__
-#include <string>
-#include <vector>
-#include <algorithm>
-#include <iostream>
-using namespace std;
-
-class OCResourceDesc
-{
- private:
- string resource_id, type, resource_url, resource_state;
-
- public:
- OCResourceDesc();
- virtual ~OCResourceDesc();
- OCResourceDesc(string, string, string, string);
- void SetResource_id(string);
- void SetType(string);
- void SetResource_url(string);
- void SetResource_state(string);
- string GetResource_id();
- string GetType();
- string GetResource_url();
- string GetResource_state();
-};
-
-//class OCResourceDescManager{
-//private:
-// vector<OCResourceDesc> ocResources;
-//private:
-// TiXmlElement* CreateResource(OCResourceDesc&);
-//public:
-//
-// void setresources(vector<OCResourceDesc>&);
-// vector<OCResourceDesc> GetResources();
-// OCResourceDescManager();
-//
-// vector<OCResourceDesc>* InitResources(string);
-//
-// void CreateResourcesXMl(vector<OCResourceDesc>&,string);
-//
-//
-// ~OCResourceDescManager();
-//};
-
-#endif //__OCRESOURCEDESC_H__
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file PluginProvider.h
-
-/// @brief
-
-#ifndef __PLUGIN_PROVIDER_H__
-#define __PLUGIN_PROVIDER_H__
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "cpluff.h"
-#include <unistd.h>
-
-
-
-/**
- * Creates a new plug-in instance. We use classifier instance as plug-in
- * instance because it includes all the data our plug-in instance needs.
- */
-static void *create(cp_context_t *ctx);
-
-/**
- * Initializes and starts the plug-in.
- */
-static int start(void *d);
-
-/**
- * Destroys a plug-in instance.
- */
-static void destroy(void *d);
-
-
-#endif //__PLUGIN_PROVIDER_H__
-
+++ /dev/null
-#include "http_curl.h"
-#include <string>
-#include <iostream>
-using namespace std;
-
-CHttpClient::CHttpClient(void): m_bDebug(false)
-{
-
-}
-
-CHttpClient::~CHttpClient(void)
-{
-
-}
-
-static int OnDebug(CURL *, curl_infotype itype, char *pData, size_t size, void *)
-{
- if (itype == CURLINFO_TEXT)
- {
- //printf("[TEXT]%s\n", pData);
- }
- else if (itype == CURLINFO_HEADER_IN)
- {
- printf("[HEADER_IN]%s\n", pData);
- }
- else if (itype == CURLINFO_HEADER_OUT)
- {
- printf("[HEADER_OUT]%s\n", pData);
- }
- else if (itype == CURLINFO_DATA_IN)
- {
- printf("[DATA_IN]%s\n", pData);
- }
- else if (itype == CURLINFO_DATA_OUT)
- {
- printf("[DATA_OUT]%s\n", pData);
- }
- return 0;
-}
-
-static size_t OnWriteData(void *buffer, size_t size, size_t nmemb, void *lpVoid)
-{
- std::string *str = dynamic_cast<std::string *>((std::string *)lpVoid);
- if ( NULL == str || NULL == buffer )
- {
- return -1;
- }
-
- char *pData = (char *)buffer;
- str->append(pData, size * nmemb);
- return nmemb;
-}
-
-int CHttpClient::Post(const std::string &strUrl, const std::string &strPost,
- std::string &strResponse)
-{
- CURLcode res;
- struct curl_slist *headers = NULL;
- headers = curl_slist_append(headers, "Content-Type: application/json");
-
- CURL *curl = curl_easy_init();
- if (NULL == curl)
- {
- return CURLE_FAILED_INIT;
- }
- if (m_bDebug)
- {
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
- curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
- }
-
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
- curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
- curl_easy_setopt(curl, CURLOPT_POST, 1);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
- return res;
-}
-
-int CHttpClient::Get(const std::string &strUrl, std::string &strResponse)
-{
- CURLcode res;
- struct curl_slist *headers = NULL;
- headers = curl_slist_append(headers, "Content-Type: application/json");
-
- CURL *curl = curl_easy_init();
- if (NULL == curl)
- {
- return CURLE_FAILED_INIT;
- }
- if (m_bDebug)
- {
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
- curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
- }
-
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
- curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
- /**
- * 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
- * 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
- */
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
- return res;
-}
-
-int CHttpClient::Put(const std::string &strUrl, const std::string &strPut, std::string &strResponse)
-{
- CURLcode res;
- struct curl_slist *headers = NULL;
- headers = curl_slist_append(headers, "Content-Type: application/json");
-
- CURL *curl = curl_easy_init();
- if (NULL == curl)
- {
- return CURLE_FAILED_INIT;
- }
- if (m_bDebug)
- {
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
- curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
- }
-
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
- curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPut.c_str());
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
- return res;
-}
-
-
-int CHttpClient::Delete(const std::string &strUrl, std::string &strResponse)
-{
- CURLcode res;
- struct curl_slist *headers = NULL;
- headers = curl_slist_append(headers, "Content-Type: application/json");
-
- CURL *curl = curl_easy_init();
- if (NULL == curl)
- {
- return CURLE_FAILED_INIT;
- }
- if (m_bDebug)
- {
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
- curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
- }
-
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
- curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
- return res;
-}
-
-
-void CHttpClient::SetDebug(bool bDebug)
-{
- m_bDebug = bDebug;
-}
+++ /dev/null
-#ifndef __HTTP_CURL_H__
-#define __HTTP_CURL_H__
-
-#include <string>
-#include <curl/curl.h>
-using namespace std;
-
-class CHttpClient
-{
- public:
- CHttpClient(void);
- ~CHttpClient(void);
-
- public:
-
- int Post(const std::string &strUrl, const std::string &strPost, std::string &strResponse);
-
-
- int Get(const std::string &strUrl, std::string &strResponse);
-
- int Put(const std::string &strUrl, const std::string &strPost, std::string &strResponse);
-
- int Delete(const std::string &strUrl, std::string &strResponse);
-
- public:
- void SetDebug(bool bDebug);
-
- private:
- bool m_bDebug;
-};
-
-#endif
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file hue_light_sample.cpp
-
-/// @brief
-
-
-#include <boost/algorithm/string.hpp>
-#include <signal.h>
-
-#include "PluginProvider.h"
-#include "HuePlugin.h"
-#include "HueLightHandler.h"
-#include "json_parse.h"
-#include "http_curl.h"
-
-
-
-/**
- * If you set ENV variable "CONF_PATH", then it will be the default path of configure file, otherwise you can set the default path here
- *
- */
-
-using namespace OIC;
-using namespace boost::property_tree;
-using namespace boost;
-using namespace std;
-using namespace OC;
-
-
-pthread_t tid ;
-
-typedef struct classifier_t classifier_t;
-struct classifier_t
-{
- /** Classifier specific runtime data */
- cp_context_t *data;
-
- /** The classifying args */
- char *path;
-};
-
-
-
-/**
-*handler of pluginmanager as a resource
-*handle find resource or plugin managerment operations
-*it would be trigger by Iotivity core
-**/
-
-int gObservation = 0;
-void entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response);
-
-
-void *ChangeLightRepresentation (void *param)
-{
- std::cout << "Enter ChangeLightRepresentation" << std::endl;
- return NULL;
-}
-
-std::string light_url;
-
-
-string c_light_url = "/a/container";
-string c_resType = "core.container";
-string c_resInterface = OC::DEFAULT_INTERFACE;
-
-//LightContainer myLightContainer(c_light_url,c_resType,c_resInterface);
-LightContainer *myLightContainer = new LightContainer(c_light_url, c_resType, c_resInterface);
-OC::OCPlatform *platform_s;
-
-
-void entityHandler(std::shared_ptr<OC::OCResourceRequest> request,
- std::shared_ptr<OC::OCResourceResponse> response)
-{
- std::cout << "\tIn Server CPP entity handler:\n";
- if (request)
- {
- // Get the request type and request flag
- std::string requestType = request->getRequestType();
- OC::RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
- if (requestFlag == OC::RequestHandlerFlag::InitFlag)
- {
- std::cout << "\t\trequestFlag : Init\n";
-
- // entity handler to perform resource initialization operations
- }
- else if (requestFlag == OC::RequestHandlerFlag::RequestFlag)
- {
- std::cout << "\t\trequestFlag : Request\n";
-
- CHttpClient *client = new CHttpClient();
-// std::shared_ptr<CHttpClient> client;
- std::string resp;
-
- // If the request type is GET
- if (requestType == "GET")
- {
- std::cout << "\t\t\trequestType : GET\n";
-
- // Check for query params (if any)
- OC::QueryParamsMap queryParamsMap = request->getQueryParameters();
- cout << "\t\t\tquery params: \n";
- for (OC::QueryParamsMap::iterator it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
- {
- cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
- }
-
- // Process query params and do required operations ..
-
- // Get the representation of this resource at this point and send it as response
- // ShortCut need all resource in the same state !!!
- OC::OCRepresentation rep;
- rep = myLightContainer->getRepresentation();
-
- OC::AttributeMap attributeMap;
- std::cout << "..... container has " << myLightContainer->m_container.size() << std::endl;
- if (myLightContainer->m_container.empty())
- {
- cout << "no lights to get" << endl;
- delete client;
- return;
- }
- vector<LightResource>::iterator iter;
- iter = myLightContainer->m_container.begin();
- light_url = iter->ext_url;
- size_t index = light_url.find_last_of("/");
- string light_get_url = light_url.substr(0, index);
-
- if (response)
- {
- response->setErrorCode(200);
- //TODO restful with hue light
-
- std::cout << "ready to send rest api to light" << std::endl;
- OC::AttributeValues stateVal;
- OC::AttributeValues colorVal;
- OC::AttributeValues brightVal;
-
- std::cout << "ready to connect url ---- light_get_url " << light_get_url << std::endl;
- client->Get((string &)light_get_url, (string &)resp);
-// std::cout<<"<<<<<<<<<response ----"<<resp<<std::endl;
-
- if (resp.size())
- {
- stringstream stream;
- ptree pt;
- replace_all(resp, "u\'", "\"");
- replace_all(resp, "\'", "\"");
- if (resp.find("True") != string::npos)
- replace_all(resp, "True", "\"true\"");
- else replace_all(resp, "true", "\"true\"");
- if (resp.find("False") != string::npos)
- replace_all(resp, "False", "\"false\"");
- else replace_all(resp, "false", "\"false\"");
-
- stream << resp;
- read_json<ptree>(stream, pt);
- string lig_status = pt.get<string>("state.on");
- int lig_color = pt.get<int>("state.hue");
- int lig_bri = pt.get<int>("state.bri");
-
- if (lig_status == "true") stateVal.push_back("true");
- else stateVal.push_back("false");
- colorVal.push_back(to_string(lig_color));
- brightVal.push_back(to_string(lig_bri));
- }
- attributeMap["state"] = stateVal;
- attributeMap["color"] = colorVal;
- attributeMap["bright"] = brightVal;
-
- rep.setAttributeMap(attributeMap);
-// std::cout<<"<<<<<<<<<after rep.setAttributeMap ----"<<std::endl;
- auto findRes = queryParamsMap.find("if");
- if (findRes != queryParamsMap.end())
- {
-// std::cout<<"<<<<<<<<<Enter setResourceRepresentation found if ----"<<std::endl;
- response->setResourceRepresentation(rep, findRes->second);
- }
- else
- {
-// std::cout<<"<<<<<<<<<Enter setResourceRepresentation found no if,using default interface ----"<<std::endl;
- response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
- }
- }
- }
- else if (requestType == "PUT")
- {
- std::cout << "\t\t\trequestType : PUT\n";
- std::cout << "..... container has " << myLightContainer->m_container.size() << std::endl;
- if (myLightContainer->m_container.empty())
- {
- cout << "no lights to put" << endl;
- delete client;
- return;
- }
-
- // Check for query params (if any)
- OC::QueryParamsMap queryParamsMap = request->getQueryParameters();
- cout << "\t\t\tquery params: \n";
- for (auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
- {
- cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
- }
-
- // Check queryParamsMap and do required operations ..
-
- // Get the representation from the request
- OC::OCRepresentation rep = request->getResourceRepresentation();
- OC::AttributeMap attributeMap = rep.getAttributeMap();
-
- vector<LightResource>::iterator iter;
- for (iter = myLightContainer->m_container.begin(); iter != myLightContainer->m_container.end();
- iter++)
- {
- iter->setRepresentation(rep);
- light_url = iter->ext_url;
- // Do related operations related to PUT request
- //TODO restful with hue light
- std::cout << "ready to send rest api to light" << std::endl;
- bool m_state;
- int m_color;
- int m_bright;
-
- m_state = attributeMap["state"][0].compare("true") == 0;
- m_color = std::stoi(attributeMap["color"][0]);
- m_bright = std::stoi(attributeMap["bright"][0]);
-
- if (m_state)
- {
- string putbody = "{\"hue\": " + to_string(m_color) + ", \"on\": true, \"bri\": " + to_string(
- m_bright) + "}";
- client->Put((string &)light_url, (string &)putbody, (string &)resp);
- }
- else
- {
- string putbody = "{\"hue\": 0, \"on\": false, \"bri\": 0}";
- client->Put((string &)light_url, (string &)putbody, (string &)resp);
- }
- rep = iter->getRepresentation();
- }
-
- if (response)
- {
- response->setErrorCode(200);
- auto findRes = queryParamsMap.find("if");
-
- if (findRes != queryParamsMap.end())
- {
- response->setResourceRepresentation(rep, findRes->second);
- }
- else
- {
- std::cout <<
- "<<<<<<<<<PUT ...Enter setResourceRepresentation found no if,using default interface ----" <<
- std::endl;
- response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
- }
- //TODO restful with hue light
- }
- }
- else if (requestType == "POST")
- {
- // POST request operations
- }
- else if (requestType == "DELETE")
- {
- // DELETE request operations
- }
- delete client;
- }
- else if (requestFlag == OC::RequestHandlerFlag::ObserverFlag)
- {
- pthread_t threadId;
-
- std::cout << "\t\trequestFlag : Observer\n";
- gObservation = 1;
-
- static int startedThread = 0;
-
- // Observation happens on a different thread in ChangeLightRepresentation function.
- // If we have not created the thread already, we will create one here.
- if (!startedThread)
- {
- pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
- startedThread = 1;
- }
-
- }
- }
- else
- {
- std::cout << "Request invalid" << std::endl;
- }
-}
-
-
-
-/**
- * Handler for hue light resources to intel core:
- *
- * register new resource and unregister lost resource
- *
- */
-
-void *hue_light_handler(void *args)
-{
- cout << "Enter the new hue_light_handler thread" << endl;
- HuePlugin *device = new HuePlugin();
- vector<string> res_pool;
-
- /* OC::PlatformConfig cfg;
-// cfg.ipAddress = "134.134.161.33";
- cfg.ipAddress = "192.168.27.124";
- cfg.port = 56832;
- cfg.mode = OC::ModeType::Server;
- cfg.serviceType = OC::ServiceType::InProc;*/
-
- PlatformConfig cfg {
- OC::ServiceType::InProc,
- OC::ModeType::Server,
- "192.168.2.5",
- 56832,
- OC::QualityOfService::NonConfirmable
- };
-
-
- platform_s = new OC::OCPlatform(cfg);
- cout << "Create OCPlatform OK" << endl;
- myLightContainer->registerResource(*platform_s, &entityHandler);
-
- string resURL = "/a/light"; //should /**/**/ type
- while (1)
- {
-
- vector<OCResourceDesc> ret = device->SearchDeviceResources(res_pool);
- cout << "Search resources OK" << endl;
- vector<OCResourceDesc>::iterator iter;
-
- if (ret.empty())
- {
- cout << "Not found new lights" << endl;
- sleep(10);
- continue;
- }
- else
- {
- cout << "ready to get all lights info" << endl;
-
- // TO CONTROL ALL Lights
- for (iter = ret.begin(); iter != ret.end(); iter++)
- {
- std::string res_id = iter->GetResource_id();
- std::string url = iter->GetResource_url();
- std::string state = iter->GetResource_state();
-
- cout << "res_id = " << res_id << endl;
- cout << "url = " << url << endl;
- cout << "status = " << state << endl;
-
- //TO do register and unregister with Intel API
- // adding new resource
- if (state == "join")
- {
- light_url = url;
- string resType = "core.light";
- string resInterface = OC::DEFAULT_INTERFACE;
- LightResource *myLightResource = new LightResource(resURL, resType, resInterface, light_url);
-
- int abc;
- do
- {
-// abc = myLightResource->registerResource(platform_s, &entityHandler);
- abc = myLightResource->registerResource(*platform_s, NULL);
-// myLightResource->addType(platform_s, "core.brightlight");
-// myLightResource->addInterface(platform_s, "oc.mi.ll");
- std::cout << "register result = " << abc << std::endl;
- sleep(2);
- }
- while (abc != 0);
- cout << "Notifying observers with resource handle: " << myLightResource->getHandle() << endl;
-
- myLightContainer->m_container.push_back(*myLightResource);
- // modify the next light url
- char *data;
- int len = resURL.length();
- data = (char *)malloc((len + 1) * sizeof(char));
- if (!data)
- {
- delete myLightResource;
- break;
- }
- resURL.copy(data, len, 0);
- data[1]++;
- resURL = data;
- free(data);
- delete myLightResource;
- }
- // remove leaving resource
- else if (state == "leave")
- {
- light_url = url;
- vector<LightResource>::iterator l_iter;
- for (l_iter = myLightContainer->m_container.begin(); l_iter != myLightContainer->m_container.end();)
- {
- if (l_iter->ext_url == light_url)
- {
- myLightContainer->m_container.erase(l_iter);
- break;
- }
- else l_iter++;
- }
- }
- }
- }
- sleep(10);
- }
- delete device;
-}
-
-
-
-/* ------------------------------------------------------------------------
- * Exported classifier information
- * ----------------------------------------------------------------------*/
-
-/**
- * Plug-in runtime information for the framework. The name of this symbol
- * is stored in the plug-in descriptor.
- */
-static void *mycreate(cp_context_t *ctx)
-{
- cout << "Test create!" << endl;
- classifier_t *cl;
- cl = (classifier_t *)malloc(sizeof(classifier_t));
- if (cl != NULL)
- {
- cl->data = ctx;
- }
- else
- {
- printf("Insufficient memory for plug-in data.\n");
- }
- return cl;
-}
-
-static int mystart(void *d)
-{
- classifier_t *cl = (classifier_t *)d;
- cp_context_t *data = cl->data;
- cout << "Test started!" << endl;
-
-
- int ret;
- ret = pthread_create(&tid, NULL, hue_light_handler, NULL);
- if (ret != 0)
- {
- cout << "Create Hue Light Handler Thread failed!" << endl;
- return -1;
- }
- cout << "after create a thread....." << endl;
- return 0;
-}
-
-static void mydestroy(void *d)
-{
-}
-
-
-static void mystop(void *d)
-{
-// int kill_ret = pthread_kill(tid, SIGKILL);
- std::cout<<"test"<<std::endl;
- int kill_ret = pthread_cancel(tid);
-
- std::cout<<"test"<<std::endl;
- void *p;
- pthread_join(tid, &p);
- std::cout << "ready to delete platform resource,Lightcontainer and stop plugin" << std::endl;
- std::cout<<"test"<<std::endl;
-// delete platform_s;
- delete myLightContainer;
-
- classifier_t *cl = (classifier_t *)d;
- if (cl->data != NULL)
- {
- free(cl->data);
- }
-}
-
-
-CP_EXPORT cp_plugin_runtime_t hue_light =
-{
- mycreate,
- mystart,
- mystop,
- mydestroy
-};
-
-
-/*
-int main(int argc, char* argv[])
-{
- std::cout<<"hello"<<std::endl;
- hue_light_handler(NULL);
- return 0;
-}*/
+++ /dev/null
-#include <iostream>
-#include <string>
-#include <vector>
-#include <fstream>
-
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-#include <boost/foreach.hpp>
+++ /dev/null
-#include <typeinfo>
-#include "curl/curl.h"
-#include <unistd.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <string.h>
-#include "HueBridge.h"
-
-#include "HuePlugin.h"
-
-
-int main()
-{
- vector<string> bridge_list;
- bridge_list = GetBridges();
- if (bridge_list.empty())
- {
- cout << "No hue bridge found" << endl;
- }
- vector<string>::iterator it;
- cout << "the result: " << endl;
- for (it = bridge_list.begin(); it != bridge_list.end(); it++)
- {
- cout << *it << "," << endl;
- string hue_bridge_url;
- hue_bridge_url.append("http://").append(*it).append("/api/newdeveloper/lights");
- cout << "total url ---" << hue_bridge_url << endl;
- }
-}
+++ /dev/null
-#include "simple_parse.h"
-
-using namespace std;
-using namespace boost;
-
-
-
-bool readConfigFile(const char *cfgfilepath, const string &key, string &value)
-{
- fstream cfgFile;
- cfgFile.open(cfgfilepath);
- if ( ! cfgFile.is_open())
- {
- cout << "can not open cfg file!" << endl;
- return false;
- }
- char tmp[1000];
- while (!cfgFile.eof())
- {
- cfgFile.getline(tmp, 1000);
- string line(tmp);
- size_t pos;
- if ((pos = line.find('#')) != -1)
- {
- if (0 == pos) continue;
- }
- pos = line.find('=');
- if (pos == string::npos) continue;
- string tmpKey = line.substr(0, pos);
- trim(tmpKey);
-
- if (key == tmpKey)
- {
- size_t lscrap, rscrap;
- if (((lscrap = line.find('[')) != string::npos) && ((rscrap = line.find(']')) != string::npos))
- {
- value = line.substr(lscrap + 1, rscrap - lscrap - 1);
- }
- else value = line.substr(pos + 1);
- trim(value);
- return true;
- }
- }
- return false;
-}
-
-
-vector<string> NormalizedOut(string &input)
-{
- char *outer_ptr = NULL;
- char *p[20];
- int in = 0;
- vector<string> vecStr;
- char *buf = (char *)input.c_str();
-
- while ((p[in] = strtok_r(buf, ",", &outer_ptr)) != NULL)
- {
- string out = p[in];
- trim(out);
- vecStr.push_back(out);
- in++;
- buf = NULL;
- }
- return vecStr;
-}
+++ /dev/null
-#ifndef _SIMPLE_PARSE_H_
-#define _SIMPLE_PARSE_H_
-
-#include <iostream>
-#include <string>
-#include <fstream>
-#include <vector>
-#include <boost/algorithm/string.hpp>
-
-using namespace std;
-
-bool readConfigFile(const char *cfgfilepath, const string &key, string &value);
-vector<string> NormalizedOut(string &input);
-
-#endif
-
-
+++ /dev/null
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-* : Initialization Part has been referenced from OCClient.cpp file of Intel copyright.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-*******************************************************************/
-
-// Client_test.cpp : Defines the entry point for the console application.
-//
-#include <string>
-#include <cstdlib>
-#include <pthread.h>
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-using namespace OC;
-
-const int SUCCESS_RESPONSE = 0;
-std::shared_ptr<OCResource> curResource;
-static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
-int color;
-int bri;
-
-
-int observe_count()
-{
- static int oc = 0;
- return ++oc;
-}
-
-void onObserve(const OCRepresentation &rep, const int &eCode, const int &sequenceNumber)
-{
- if (eCode == SUCCESS_RESPONSE)
- {
- AttributeMap attributeMap = rep.getAttributeMap();
- std::cout << "OBSERVE RESULT:" << std::endl;
- std::cout << "\tSequenceNumber: " << sequenceNumber << endl;
- for (auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
- {
- std::cout << "\tAttribute name: " << it->first << " value: ";
- for (auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
- {
- std::cout << "\t" << *valueItr << " ";
- }
-
- std::cout << std::endl;
- }
-
- if (observe_count() > 3)
- {
- std::cout << "Cancelling Observe..." << std::endl;
- OCStackResult result = curResource->cancelObserve();
-
- std::cout << "Cancel result: " << result << std::endl;
- sleep(10);
- std::cout << "DONE" << std::endl;
- std::exit(0);
- }
- }
- else
- {
- std::cout << "onObserve Response error: " << eCode << std::endl;
- std::exit(-1);
- }
-}
-
-// callback handler on PUT request
-void onPut(const OCRepresentation &rep, const int eCode)
-{
- if (eCode == SUCCESS_RESPONSE)
- {
- std::cout << "PUT request was successful" << std::endl;
-
- AttributeMap attributeMap = rep.getAttributeMap();
-
- for (auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
- {
- std::cout << "\tAttribute name: " << it->first << " value: ";
- for (auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
- {
- std::cout << "\t" << *valueItr << " ";
- }
-
- std::cout << std::endl;
- }
- std::vector<OCRepresentation> children = rep.getChildren();
-
- for (auto oit = children.begin(); oit != children.end(); ++oit)
- {
- attributeMap = oit->getAttributeMap();
-
- for (auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
- {
- std::cout << "\tAttribute name: " << it->first << " value: ";
- for (auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
- {
- std::cout << "\t" << *valueItr << " ";
- }
-
- std::cout << std::endl;
- }
- }
- if (OBSERVE_TYPE_TO_USE == ObserveType::Observe)
- std::cout << endl << "Observe is used." << endl << endl;
- else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
- std::cout << endl << "ObserveAll is used." << endl << endl;
-
-// QueryParamsMap test;
-// curResource->observe(OBSERVE_TYPE_TO_USE, test,&onObserve);
- }
- else
- {
- std::cout << "onPut Response error: " << eCode << std::endl;
- std::exit(-1);
- }
-}
-
-// Local function to put a different state for this resource
-void putLightRepresentation(std::shared_ptr<OCResource> resource, char *action, int color,
- int bright)
-{
- if (resource)
- {
- OCRepresentation rep;
- std::cout << "Putting light representation..." << std::endl;
- // Create AttributeMap
- AttributeMap attributeMap;
- // Add the attribute name and values in the attribute map
- AttributeValues stateVal;
- AttributeValues colorVal;
- AttributeValues brightVal;
- stateVal.push_back(action);
- colorVal.push_back(to_string(color));
- brightVal.push_back(to_string(bright));
-
- attributeMap["state"] = stateVal;
- attributeMap["color"] = colorVal;
- attributeMap["bright"] = brightVal;
-
- // Create QueryParameters Map and add query params (if any)
- QueryParamsMap queryParamsMap;
- rep.setAttributeMap(attributeMap);
-
- // Invoke resource's pit API with attribute map, query map and the callback parameter
- resource->put(rep, queryParamsMap, &onPut);
- }
-}
-
-// callback handler on GET request
-void onGet(const OCRepresentation &rep, const int eCode)
-{
- if (eCode == SUCCESS_RESPONSE)
- {
- std::cout << "GET Succeeded:" << std::endl;
- AttributeMap attributeMap = rep.getAttributeMap();
- std::cout << "Resource URI: " << rep.getUri() << std::endl;
-
- for (auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
- {
- std::cout << "\tAttribute name: " << it->first << " value: ";
- for (auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
- {
- std::cout << "\t" << *valueItr << " ";
- }
-
- std::cout << std::endl;
- }
- std::vector<OCRepresentation> children = rep.getChildren();
-
- for (auto oit = children.begin(); oit != children.end(); ++oit)
- {
- std::cout << "Child Resource URI: " << oit->getUri() << std::endl;
-
- attributeMap = oit->getAttributeMap();
-
- for (auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
- {
- std::cout << "\tAttribute name: " << it->first << " value: ";
- for (auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
- {
- std::cout << "\t" << *valueItr << " ";
- }
-
- std::cout << std::endl;
- }
- }
-
-// putLightRepresentation(curResource);
- }
- else
- {
- std::cout << "onGet Response error: " << eCode << std::endl;
- std::exit(-1);
- }
-}
-// Local function to get representation of light resource
-void getLightRepresentation(std::shared_ptr<OCResource> resource)
-{
- if (resource)
- {
- std::cout << "Getting Light Representation..." << std::endl;
- // Invoke resource's get API with the callback parameter
- QueryParamsMap test;
- resource->get(test, &onGet);
- }
-}
-
-// Callback to found resources
-void foundResource(std::shared_ptr<OCResource> resource)
-{
- if (curResource)
- {
- std::cout << "Found another resource, ignoring" << std::endl;
- exit(-1);
- }
-
- std::string resourceURI;
- std::string hostAddress;
- try
- {
- // Do some operations with resource object.
- if (resource)
- {
- std::cout << "DISCOVERED Resource:" << std::endl;
- // Get the resource URI
- resourceURI = resource->uri();
- std::cout << "\tURI of the resource: " << resourceURI << std::endl;
-
- // Get the resource host address
- hostAddress = resource->host();
- std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
-
- // Get the resource types
- std::cout << "\tList of resource types: " << std::endl;
- for (auto &resourceTypes : resource->getResourceTypes())
- {
- std::cout << "\t\t" << resourceTypes << std::endl;
- }
-
- // Get the resource interfaces
- std::cout << "\tList of resource interfaces: " << std::endl;
- for (auto &resourceInterfaces : resource->getResourceInterfaces())
- {
- std::cout << "\t\t" << resourceInterfaces << std::endl;
- }
-
- if (!resourceURI.empty())
- {
- curResource = resource;
- // Call a local function which will internally invoke get API on the resource pointer
- getLightRepresentation(resource);
- }
- }
- else
- {
- // Resource is invalid
- std::cout << "Resource is invalid" << std::endl;
- }
-
- }
- catch (std::exception &e)
- {
- //log(e.what());
- }
-}
-
-
-void UpResource(std::shared_ptr<OCResource> resource)
-{
- foundResource(resource);
- putLightRepresentation(resource, "true", color, bri);
-}
-
-
-void DownResource(std::shared_ptr<OCResource> resource)
-{
- foundResource(resource);
- putLightRepresentation(resource, "false", 0, 0);
-}
-
-
-int main(int argc, char *argv[])
-{
- // Create PlatformConfig object
-/*
- PlatformConfig cfg;
- cfg.ipAddress = "192.168.1.10";
- cfg.port = 5683;
- cfg.mode = ModeType::Client;
- cfg.serviceType = ServiceType::InProc;
-*/
- PlatformConfig cfg {
- OC::ServiceType::InProc,
- OC::ModeType::Client,
- "192.168.2.5",
- 56832,
- OC::QualityOfService::NonConfirmable
- };
- // Create a OCPlatform instance.
- // Note: Platform creation is synchronous call.
- try
- {
- OCPlatform platform(cfg);
- if (argc == 1)
- {
- std::cout << "Created Platform..." << std::endl;
- // Find all resources
- platform.findResource("", "coap://224.0.1.187/oc/core?rt=core.container", &foundResource);
- std::cout << "Finding Resource... " << std::endl;
- }
- else if ((argc == 2) && strcmp(argv[1], "off") == 0)
- {
- std::cout << "Created Platform..." << std::endl;
- // Find all resources
- platform.findResource("", "coap://224.0.1.187/oc/core?rt=core.container", &DownResource);
- std::cout << "Finding Resource and Down... " << std::endl;
- }
- else if ((argc == 4) && strcmp(argv[1], "on") == 0)
- {
- std::cout << "Created Platform..." << std::endl;
- // Find all resources
- color = atoi(argv[2]);
- bri = atoi(argv[3]);
- platform.findResource("", "coap://224.0.1.187/oc/core?rt=core.container", &UpResource);
- std::cout << "Finding Resource Up and Set color and bright... " << std::endl;
- }
- else
- {
- std::cout <<
- "Usage: oic-light-client off \n oic-light-client on 20000 200 [color:0~65535, bri:0~255]" <<
- std::endl;
- }
- sleep(5);
- }
- catch (OCException e)
- {
- //log(e.what());
- }
-
- return 0;
-}
-
+++ /dev/null
-import web
-import sys
-import json
-
-render = web.template.render('templates/')
-urls = ( r'/api/newdeveloper/lights/1(.*)', 'LightIndex1',
- r'/api/newdeveloper/lights', 'LightIndex2',
- r'/api/zmc/lights', 'LightIndex3',
- r'/api/zmc2/lights', 'LightIndex4',
-)
-
-
-ret_status = """{
- "state": {
- "hue": 50000,
- "on": true,
- "effect": "none",
- "alert": "none",
- "bri": 200,
- "sat": 200,
- "ct": 500,
- "xy": [0.5, 0.5],
- "reachable": true,
- "colormode": "hs"
- },
- "type": "Living Colors",
- "name": "LC 1",
- "modelid": "LC0015",
- "swversion": "1.0.3",
- "pointsymbol": {
- "1": "none",
- "2": "none",
- "3": "none",
- "4": "none",
- "5": "none",
- "6": "none",
- "7": "none",
- "8": "none"
- }
-}"""
-ret_status = json.loads(ret_status)
-
-
-class LightIndex1:
- def GET(self, name=None):
- return ret_status
-
-
- def POST(self, name=None):
- print "Post ......"
- data = web.data()
- print data
- return data
-
- def PUT(self, name=None):
- print "Put ......"
- data= web.data()
- print data
- r_data = json.loads(data)
- ret_status["state"]["on"] = r_data["on"]
- return data
-
- def DELETE(self, name=None):
- print "DELETE ......"
- return render.index(name)
-
-class LightIndex2:
- def GET(self, name=None):
- lights = """{
- "1": {
- "name": "Bedroom"
- },
- "2": {
- "name": "Kitchen"
- }
- }"""
- lights = json.loads(lights)
- print type(lights)
- return lights
-
-class LightIndex3:
- def GET(self, name=None):
- lights = """{
- "3": {
- "name": "Whitehouse"
- },
- "4": {
- "name": "Desktop"
- }
- }"""
- lights = json.loads(lights)
- print type(lights)
- return lights
-
-
-class LightIndex4:
- def GET(self, name=None):
- lights = """{
- "5": {
- "name": "test1"
- },
- "6": {
- "name": "test2"
- }
- }"""
- lights = json.loads(lights)
- print type(lights)
- return lights
-
-
-if __name__ =="__main__":
- sys.argv.append("80")
- app = web.application(urls, globals())
- app.run()
+++ /dev/null
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-* : Initialization Part has been referenced from OCClient.cpp file of Intel copyright.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-*******************************************************************/
-
-///
-/// This sample provides steps to define an interface for a resource
-/// (properties and methods) and host this resource on the server.
-///
-
-#include <functional>
-
-#include <pthread.h>
-
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-using namespace OC;
-using namespace std;
-
-int gObservation = 0;
-
-// Forward declaring the entityHandler
-void entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response);
-
-/// This class represents a single resource named 'lightResource'. This resource has
-/// two simple properties named 'state'
-
-class LightResource
-{
- public:
- /// Access this property from a TB client
- bool m_state;
- int m_color;
- int m_bright;
- std::string m_lightUri;
- OCResourceHandle m_resourceHandle;
-
- public:
- /// Constructor
- LightResource(): m_state(false), m_color(0), m_bright(0) {m_resourceHandle = NULL;}
-
- /* Note that this does not need to be a member function: for classes you do not have
- access to, you can accomplish this with a free function: */
-
- /// This function internally calls registerResource API.
- void createResource(OC::OCPlatform &platform, string url, string res_type,
- std::function<void(const OCResourceRequest::Ptr, const OCResourceResponse::Ptr)> Handler)
- {
- std::string resourceURI = url; // URI of the resource
- std::string resourceTypeName = res_type; // resource type name. In this case, it is light
- std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
-
- // OCResourceProperty is defined ocstack.h
- uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
-
- // This will internally create and register the resource.
- OCStackResult result = platform.registerResource(
- m_resourceHandle, resourceURI, resourceTypeName,
- resourceInterface, Handler, resourceProperty);
-
- if (OC_STACK_OK != result)
- {
- cout << "Resource creation was unsuccessful\n";
- }
- }
-
- OCResourceHandle getHandle()
- {
- return m_resourceHandle;
- }
-
- void setRepresentation(OCRepresentation &light)
- {
- AttributeMap attributeMap = light.getAttributeMap();
- cout << "\t\t\t" << "Received representation: " << endl;
- cout << "\t\t\t\t" << "state: " << attributeMap["state"][0] << endl;
- cout << "\t\t\t\t" << "color: " << attributeMap["color"][0] << endl;
- cout << "\t\t\t\t" << "bright: " << attributeMap["bright"][0] << endl;
-
- m_state = attributeMap["state"][0].compare("true") == 0;
- m_color = std::stoi(attributeMap["color"][0]);
- m_bright = std::stoi(attributeMap["bright"][0]);
- }
-
- OCRepresentation getRepresentation()
- {
- OCRepresentation light;
- light.setUri(m_lightUri);
- std::vector<std::string> interfaces;
- //interfaces.push_back(m_lightInterface);
-
- light.setResourceInterfaces(interfaces);
-
- std::vector<std::string> types;
- //types.push_back(m_lightType);
-
- light.setResourceTypes(types);
-
- AttributeMap attributeMap;
- AttributeValues stateVal;
- if (m_state)
- {
- stateVal.push_back("true");
- }
- else
- {
- stateVal.push_back("false");
- }
- AttributeValues colorVal;
- colorVal.push_back(to_string(m_color));
- AttributeValues brightVal;
- brightVal.push_back(to_string(m_bright));
-
- attributeMap["state"] = stateVal;
- attributeMap["color"] = colorVal;
- attributeMap["bright"] = brightVal;
-
- light.setAttributeMap(attributeMap);
- return light;
- }
-
- void addType(const OC::OCPlatform &platform, const std::string &type) const
- {
- OCStackResult result = platform.bindTypeToResource(m_resourceHandle, type);
- if (OC_STACK_OK != result)
- {
- cout << "Binding TypeName to Resource was unsuccessful\n";
- }
- }
-
- void addInterface(const OC::OCPlatform &platform, const std::string &interface) const
- {
- OCStackResult result = platform.bindInterfaceToResource(m_resourceHandle, interface);
- if (OC_STACK_OK != result)
- {
- cout << "Binding TypeName to Resource was unsuccessful\n";
- }
- }
-};
-
-
-
-// Create the instance of the resource class (in this case instance of class 'LightResource').
-LightResource myLightResource;
-LightResource otherLightResource;
-
-// ChangeLightRepresentaion is an observation function,
-// which notifies any changes to the resource to stack
-// via notifyObservers
-void *ChangeLightRepresentation (void *param)
-{
- // This function continuously monitors for the changes
- while (1)
- {
- sleep (5);
-
- if (gObservation)
- {
- // If under observation if there are any changes to the light resource
- // we call notifyObservors
- //
- // For demostration we are changing the power value and notifying.
- myLightResource.m_color += 10;
- cout << "\nState updated to : " << myLightResource.m_color << endl;
- cout << "Notifying observers with resource handle: " << myLightResource.getHandle() << endl;
-
- OCStackResult result = OCPlatform::notifyObservers(myLightResource.getHandle());
-
- if (OC_STACK_NO_OBSERVERS == result)
- {
- cout << "No More observers, stopping notifications" << endl;
- gObservation = 0;
- }
- }
- }
- return NULL;
-}
-
-
-// This is just a sample implementation of entity handler.
-// Entity handler can be implemented in several ways by the manufacturer
-void entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
-{
- cout << "\tIn Server CPP entity handler:\n";
-
- if (request)
- {
- // Get the request type and request flag
- std::string requestType = request->getRequestType();
- RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
-
- if (requestFlag == RequestHandlerFlag::InitFlag)
- {
- cout << "\t\trequestFlag : Init\n";
-
- // entity handler to perform resource initialization operations
- }
- else if (requestFlag == RequestHandlerFlag::RequestFlag)
- {
- cout << "\t\trequestFlag : Request\n";
-
- // If the request type is GET
- if (requestType == "GET")
- {
- cout << "\t\t\trequestType : GET\n";
-
- // Check for query params (if any)
- QueryParamsMap queryParamsMap = request->getQueryParameters();
-
- cout << "\t\t\tquery params: \n";
- for (QueryParamsMap::iterator it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
- {
- cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
- }
-
-
- // Process query params and do required operations ..
-
- // Get the representation of this resource at this point and send it as response
- OCRepresentation rep;
- rep = myLightResource.getRepresentation();
- AttributeMap attributeMap;
-
- if (response)
- {
- // TODO Error Code
- response->setErrorCode(200);
- auto findRes = queryParamsMap.find("if");
- if (findRes != queryParamsMap.end())
- {
- cout << "<<<<<<< found if....." << endl;
- response->setResourceRepresentation(rep, findRes->second);
- }
- else
- {
- cout << "<<<<<<< not found if using default....." << endl;
- response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
- }
- }
- }
- else if (requestType == "PUT")
- {
- cout << "\t\t\trequestType : PUT\n";
-
- // Check for query params (if any)
- QueryParamsMap queryParamsMap = request->getQueryParameters();
- cout << "\t\t\tquery params: \n";
- for (auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
- {
- cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
- }
-
- // Check queryParamsMap and do required operations ..
-
- // Get the representation from the request
- OCRepresentation rep = request->getResourceRepresentation();
- myLightResource.setRepresentation(rep);
-
- rep = myLightResource.getRepresentation();
-
- // Do related operations related to PUT request
-
- if (response)
- {
- response->setErrorCode(200);
- response->setResourceRepresentation(rep, LINK_INTERFACE);
- }
- }
- else if (requestType == "POST")
- {
- // POST request operations
- }
- else if (requestType == "DELETE")
- {
- // DELETE request operations
- }
- }
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
- {
- pthread_t threadId;
-
- cout << "\t\trequestFlag : Observer\n";
- gObservation = 1;
-
- static int startedThread = 0;
-
- // Observation happens on a different thread in ChangeLightRepresentation function.
- // If we have not created the thread already, we will create one here.
- if (!startedThread)
- {
- pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
- startedThread = 1;
- }
-
- }
- }
- else
- {
- std::cout << "Request invalid" << std::endl;
- }
-}
-
-int main()
-{
- // Create PlatformConfig object
-
- /*PlatformConfig cfg;
- cfg.ipAddress = "192.168.1.10";
- cfg.port = 56832;
- cfg.mode = ModeType::Server;
- cfg.serviceType = ServiceType::InProc;
-*/
- PlatformConfig cfg {
- OC::ServiceType::InProc,
- OC::ModeType::Server,
- "192.168.2.5",
- 56832,
- OC::QualityOfService::NonConfirmable
- };
-
- // Create a OCPlatform instance.
- // Note: Platform creation is synchronous call.
- try
- {
- OCPlatform platform(cfg);
-
- // Invoke createResource function of class light.
-
- string abc = "/a/light";
-
- myLightResource.createResource(platform, abc, "core.light", &entityHandler);
-// myLightResource.addType(platform, std::string("core.brightlight"));
-// myLightResource.addInterface(platform, std::string("oc.mi.ll"));
-
-
- // Perform app tasks
- while (true)
- {
- // some tasks
- }
- }
- catch (OCException e)
- {
- std::cout << e.what() << std::endl;
- }
-
-
- // No explicit call to stop the platform.
- // When OCPlatform destructor is invoked, internally we do platform cleanup
-}
SRC_DIR = ../../src
CXX_INC := -I$(LIB_DIR)/include/
+CXX_INC += -I$(LIB_DIR)/oc_logger/include/
CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
CXX_INC += -I$(LIB_DIR)/csdk/ocsocket/include/
CXX_INC += -I$(LIB_DIR)/csdk/ocrandom/include/
CXX_INC += -I../../lib
CXX_INC += -I../../../../lib/cpluff/libcpluff
+LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
+CXX_LIBS := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+
.PHONY: lib release_build ./release/fanserver_mqtt_plugin.so
all: .PHONY
cp plugin.xml release
./release/fanserver_mqtt_plugin.so: ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o
- $(CXX) -shared -o ./release/fanserver_mqtt_plugin.so ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o $(LIB_DIR)/build/linux/release/obj/liboc.a $(LIB_DIR)/csdk/build/linux/release/liboctbstack.a ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a -L../../lib -lmosquitto -lssl -lrt
+ $(CXX) -shared -o ./release/fanserver_mqtt_plugin.so ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o $(CXX_LIBS) -L../../lib -lmosquitto -lssl -lrt
./release/obj/fanserver_mqtt_plugin.o: $(SRC_DIR)/fanserver_mqtt_plugin.cpp
$(CXX) $(CXX_INC) -fPIC -o ./release/obj/fanserver_mqtt_plugin.o -c $(SRC_DIR)/fanserver_mqtt_plugin.cpp
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+///
+/// This sample provides steps to define an interface for a resource
+/// (properties and methods) and host this resource on the server.
+///
+
+#include <functional>
+#include <pthread.h>
+#include <cpluff.h>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "../lib/mosquitto.h"
+#include "fanserver.h"
+
+#include <time.h>
+
+
+using namespace OC;
+using namespace std;
+namespace PH = std::placeholders;
+
+time_t timer; // Define the timer
+struct tm *tblock; // Define a structure for time block
+
+
+int gObservation = 0;
+void *ChangeFanRepresentation (void *param);
+
+// Specifies where to notify all observers or list of observers
+// 0 - notifies all observers
+// 1 - notifies list of observers
+int isListOfObservers = 0;
+
+// Forward declaring the entityHandler
+
+/// This class represents a single resource named 'fanResource'. This resource has
+/// two simple properties named 'state' and 'power'
+
+
+
+// Forward declaring the entityHandler
+// void entityHandler(std::shared_ptr<OCResourceRequest> request,
+// std::shared_ptr<OCResourceResponse> response);
+
+/// This class represents a single resource named 'fanResource'. This resource has
+/// two simple properties named 'state' and 'power'
+typedef struct plugin_data_t plugin_data_t;
+
+struct plugin_data_t
+{
+ cp_context_t *ctx;
+ pthread_t m_thread; // 2
+ void *str;
+ bool flag;
+};
+
+
+class FanResource
+{
+ public:
+ /// Access this property from a TB client
+ std::string m_name;
+ bool m_state;
+ int m_power;
+ int m_health;
+ std::string m_fanUri;
+ OCResourceHandle m_resourceHandle;
+ OCRepresentation m_fanRep;
+ ObservationIds m_interestedObservers;
+
+ public:
+ /// Constructor
+ FanResource(): m_name("John's fan"), m_state(false), m_power(0), m_fanUri("/a/fan")
+ {
+ // Initialize representation
+ m_fanRep.setUri(m_fanUri);
+
+ m_fanRep.setValue("state", m_state);
+ m_fanRep.setValue("power", m_power);
+ m_fanRep.setValue("name", m_name);
+ }
+
+
+ /* Note that this does not need to be a member function: for classes you do not have
+ access to, you can accomplish this with a free function: */
+
+ /// This function internally calls registerResource API.
+ void createResource()
+ {
+ std::string resourceURI = m_fanUri; // URI of the resource
+ std::string resourceTypeName = "core.fan"; // resource type name. In this case, it is fan
+ std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
+
+ // OCResourceProperty is defined ocstack.h
+ uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
+
+ EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+
+ // This will internally create and register the resource.
+ OCStackResult result = OCPlatform::registerResource(
+ m_resourceHandle, resourceURI, resourceTypeName,
+ resourceInterface, cb, resourceProperty);
+
+ if (OC_STACK_OK != result)
+ {
+ cout << "Resource creation was unsuccessful\n";
+ }
+ }
+
+ OCStackResult createResource1()
+ {
+ std::string resourceURI = "/a/fan1"; // URI of the resource
+ std::string resourceTypeName = "core.fan"; // resource type name. In this case, it is fan
+ std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
+
+ // OCResourceProperty is defined ocstack.h
+ uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
+
+ EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+
+ OCResourceHandle resHandle;
+
+ // This will internally create and register the resource.
+ OCStackResult result = OCPlatform::registerResource(
+ resHandle, resourceURI, resourceTypeName,
+ resourceInterface, cb, resourceProperty);
+
+ if (OC_STACK_OK != result)
+ {
+ cout << "Resource creation was unsuccessful\n";
+ }
+
+ return result;
+ }
+
+ OCResourceHandle getHandle()
+ {
+ return m_resourceHandle;
+ }
+
+ // Puts representation.
+ // Gets values from the representation and
+ // updates the internal state
+ void put(OCRepresentation &rep)
+ {
+ try
+ {
+ if (rep.getValue("state", m_state))
+ {
+ cout << "\t\t\t\t" << "state: " << m_state << endl;
+ }
+ else
+ {
+ cout << "\t\t\t\t" << "state not found in the representation" << endl;
+ }
+
+ if (rep.getValue("power", m_power))
+ {
+ cout << "\t\t\t\t" << "power: " << m_power << endl;
+ }
+ else
+ {
+ cout << "\t\t\t\t" << "power not found in the representation" << endl;
+ }
+ }
+ catch (exception &e)
+ {
+ cout << e.what() << endl;
+ }
+
+ }
+
+ // Post representation.
+ // Post can create new resource or simply act like put.
+ // Gets values from the representation and
+ // updates the internal state
+ OCRepresentation post(OCRepresentation &rep)
+ {
+ static int first = 1;
+
+ // for the first time it tries to create a resource
+ if (first)
+ {
+ first = 0;
+
+ if (OC_STACK_OK == createResource1())
+ {
+ OCRepresentation rep1;
+ rep1.setValue("createduri", std::string("/a/fan1"));
+
+ return rep1;
+ }
+ }
+
+ // from second time onwards it just puts
+ put(rep);
+ return get();
+ }
+
+
+ // gets the updated representation.
+ // Updates the representation with latest internal state before
+ // sending out.
+ OCRepresentation get()
+ {
+ m_fanRep.setValue("state", m_state);
+ m_fanRep.setValue("power", m_power);
+
+ return m_fanRep;
+ }
+
+
+ void addType(const std::string &type) const
+ {
+ OCStackResult result = OCPlatform::bindTypeToResource(m_resourceHandle, type);
+ if (OC_STACK_OK != result)
+ {
+ cout << "Binding TypeName to Resource was unsuccessful\n";
+ }
+ }
+
+ void addInterface(const std::string &interface) const
+ {
+ OCStackResult result = OCPlatform::bindInterfaceToResource(m_resourceHandle, interface);
+ if (OC_STACK_OK != result)
+ {
+ cout << "Binding TypeName to Resource was unsuccessful\n";
+ }
+ }
+
+ private:
+ // This is just a sample implementation of entity handler.
+ // Entity handler can be implemented in several ways by the manufacturer
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
+ std::shared_ptr<OCResourceResponse> response)
+ {
+ OCEntityHandlerResult result = OC_EH_OK;
+
+ cout << "\tIn Server CPP entity handler:\n";
+
+ if (request)
+ {
+ // Get the request type and request flag
+ std::string requestType = request->getRequestType();
+ int requestFlag = request->getRequestHandlerFlag();
+
+ if (requestFlag & RequestHandlerFlag::InitFlag)
+ {
+ cout << "\t\trequestFlag : Init\n";
+
+ // entity handler to perform resource initialization operations
+ }
+ if (requestFlag & RequestHandlerFlag::RequestFlag)
+ {
+ cout << "\t\trequestFlag : Request === Handle by FanServer\n";
+
+ // If the request type is GET
+ if (requestType == "GET")
+ {
+ cout << "\t\t\trequestType : GET\n";
+
+ if (response)
+ {
+ // TODO Error Code
+ response->setErrorCode(200);
+
+ response->setResourceRepresentation(get());
+ }
+ }
+ else if (requestType == "PUT")
+ {
+ cout << "\t\t\trequestType : PUT\n";
+
+ OCRepresentation rep = request->getResourceRepresentation();
+
+ // Do related operations related to PUT request
+
+ // Update the fanResource
+ put(rep);
+
+ if (response)
+ {
+ // TODO Error Code
+ response->setErrorCode(200);
+
+ response->setResourceRepresentation(get());
+ }
+
+ }
+ else if (requestType == "POST")
+ {
+ cout << "\t\t\trequestType : POST\n";
+
+ OCRepresentation rep = request->getResourceRepresentation();
+
+ // Do related operations related to POST request
+
+ OCRepresentation rep_post = post(rep);
+
+ if (response)
+ {
+ // TODO Error Code
+ response->setErrorCode(200);
+
+ response->setResourceRepresentation(rep_post);
+
+ if (rep_post.hasAttribute("createduri"))
+ {
+ result = OC_EH_RESOURCE_CREATED;
+
+ response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
+ }
+
+ }
+
+ // POST request operations
+ }
+ else if (requestType == "DELETE")
+ {
+ // DELETE request operations
+ }
+ }
+
+ if (requestFlag & RequestHandlerFlag::ObserverFlag)
+ {
+ ObservationInfo observationInfo = request->getObservationInfo();
+ if (ObserveAction::ObserveRegister == observationInfo.action)
+ {
+ m_interestedObservers.push_back(observationInfo.obsId);
+ }
+ else if (ObserveAction::ObserveUnregister == observationInfo.action)
+ {
+ m_interestedObservers.erase(std::remove(
+ m_interestedObservers.begin(),
+ m_interestedObservers.end(),
+ observationInfo.obsId),
+ m_interestedObservers.end());
+ }
+
+ pthread_t threadId;
+
+ cout << "\t\trequestFlag : Observer\n";
+ gObservation = 1;
+ static int startedThread = 0;
+
+ // Observation happens on a different thread in ChangeFanRepresentation function.
+ // If we have not created the thread already, we will create one here.
+ if (!startedThread)
+ {
+ pthread_create (&threadId, NULL, ChangeFanRepresentation, (void *)this);
+ startedThread = 1;
+ }
+ }
+ }
+ else
+ {
+ std::cout << "Request invalid" << std::endl;
+ }
+
+ return result;
+ }
+};
+
+// Create the instance of the resource class (in this case instance of class 'FanResource').
+struct mosquitto *myMosquitto;
+
+// ChangeFanRepresentaion is an observation function,
+// which notifies any changes to the resource to stack
+// via notifyObservers
+void *ChangeFanRepresentation (void *param)
+{
+ FanResource *fanPtr = (FanResource *) param;
+
+ // This function continuously monitors for the changes
+ while (1)
+ {
+ sleep (5);
+
+ if (gObservation)
+ {
+ // If under observation if there are any changes to the fan resource
+ // we call notifyObservors
+ //
+ // For demostration we are changing the power value and notifying.
+ fanPtr->m_power += 10;
+
+ cout << "\nPower updated to : " << fanPtr->m_power << endl;
+ cout << "Notifying observers with resource handle: " << fanPtr->getHandle() << endl;
+
+ OCStackResult result = OC_STACK_OK;
+
+ if (isListOfObservers)
+ {
+ std::shared_ptr<OCResourceResponse> resourceResponse(new OCResourceResponse());
+
+ resourceResponse->setErrorCode(200);
+ resourceResponse->setResourceRepresentation(fanPtr->get(), DEFAULT_INTERFACE);
+
+ result = OCPlatform::notifyListOfObservers( fanPtr->getHandle(),
+ fanPtr->m_interestedObservers,
+ resourceResponse);
+ }
+ else
+ {
+ result = OCPlatform::notifyAllObservers(fanPtr->getHandle());
+ }
+
+ if (OC_STACK_NO_OBSERVERS == result)
+ {
+ cout << "No More observers, stopping notifications" << endl;
+ gObservation = 0;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+//int start_fanserver(void*) // 1
+void *start_fanserver(void *d) // 2
+{
+ /*PlatformConfig cfg;
+ cfg.ipAddress = "192.168.2.5";
+ cfg.port = 56832;
+ cfg.mode = ModeType::Server;
+ cfg.serviceType = ServiceType::InProc;*/
+ // PlatformConfig cfg
+ // {
+ // OC::ServiceType::InProc,
+ // OC::ModeType::Server,
+ // "192.168.2.5",
+ // 56832,
+ // OC::QualityOfService::NonConfirmable
+ // };
+
+ // Create PlatformConfig object
+
+ // Create a OCPlatform instance.
+ // Note: Platform creation is synchronous call.
+
+ // Create PlatformConfig object
+ PlatformConfig cfg
+ {
+ OC::ServiceType::InProc,
+ OC::ModeType::Server,
+ "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
+ 0, // Uses randomly available port
+ OC::QualityOfService::LowQos
+ };
+
+ OCPlatform::Configure(cfg);
+
+ printf("start_fanserver [mosquitto] Null\n");
+ try
+ {
+ FanResource myFanResource;
+ mosquitto_lib_init();
+ myMosquitto = mosquitto_new("MQTT plug-in", true, NULL);
+ if (!myMosquitto)
+ {
+ printf("[mosquitto] Null\n");
+ printf("You need to install mqtt broker\n");
+ }
+ else
+ {
+ printf("Mosquitto is working\n");
+ }
+
+ //plugin_data_t *data = (plugin_data_t *)d;
+ //OCPlatform *platform = (OCPlatform*)data->str;
+ //myFanResource.m_platform = (OCPlatform*)data->str;
+ //OCPlatform platform(cfg);
+ // Invoke createResource function of class fan.
+
+ //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
+ mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
+ printf("Mosquitto Connection is done\n");
+ myFanResource.createResource();
+ //myFanResource.addType(std::string("core.fan"));
+ //myFanResource.addInterface(std::string("oc.mi.ll"));
+ // Get time of day
+ timer = time(NULL);
+ // Converts date/time to a structure
+ tblock = localtime(&timer);
+ // Output ASCII data/time
+ printf("FanReousrce reigishter time is: %s", asctime(tblock));
+ // Perform app tasks
+ while (true)
+ {
+ // some tasks
+ }
+ }
+ catch (OCException e)
+ {
+ //log(e.what());
+ }
+ // No explicit call to stop the platform.
+ // When OCPlatform destructor is invoked, internally we do platform cleanup
+ mosquitto_destroy(myMosquitto);
+
+ mosquitto_lib_cleanup();
+ printf("start_fanserver finish\n");
+ pthread_exit((void *)0);
+}
static void *create(cp_context_t *ctx)
{
- printf("function_create\n");
-
plugin_data_t *data = (plugin_data_t *)malloc(sizeof(plugin_data_t));
if (data != NULL)
static int start(void *d)
{
- printf("function_start\n");
plugin_data_t *data = (plugin_data_t *)d;
data->str = (void *)cp_resolve_symbol(data->ctx, "fanserver_mqtt_plugin", "START_ARGUMENT", NULL);
--- /dev/null
+include ../../../../config.mk
+
+CXX = g++
+
+CXX_FLAGS = -std=c++0x -Wall -pthread
+
+LIB_DIR = ../../../../../../resource
+
+SRC_DIR = ../../src
+
+CXX_INC := -I$(LIB_DIR)/include/
+CXX_INC += -I$(LIB_DIR)/oc_logger/include/
+CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
+CXX_INC += -I$(LIB_DIR)/csdk/ocsocket/include/
+CXX_INC += -I$(LIB_DIR)/csdk/ocrandom/include/
+CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
+CXX_INC += -I$(BOOST_DIR)
+CXX_INC += -I../../lib
+CXX_INC += -I../../../../lib/cpluff/libcpluff
+
+LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
+CXX_LIBS := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+
+.PHONY: lib release_build ./release/lightserver_mqtt_plugin.so
+
+all: .PHONY
+
+lib:
+ cd ../../lib && $(MAKE)
+
+release_build:
+ -mkdir release
+ -mkdir release/obj
+ cp plugin.xml release
+
+./release/lightserver_mqtt_plugin.so: ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o
+ $(CXX) -shared -o ./release/lightserver_mqtt_plugin.so ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o $(CXX_LIBS) -L../../lib -lmosquitto -lssl -lrt
+
+./release/obj/lightserver_mqtt_plugin.o: $(SRC_DIR)/lightserver_mqtt_plugin.cpp
+ $(CXX) $(CXX_INC) -fPIC -o ./release/obj/lightserver_mqtt_plugin.o -c $(SRC_DIR)/lightserver_mqtt_plugin.cpp
+
+./release/obj/lightserver.o: $(SRC_DIR)/lightserver.cpp
+ $(CXX) $(CXX_FLAGS) -fPIC -o ./release/obj/lightserver.o -c $(SRC_DIR)/lightserver.cpp $(CXX_INC)
+
+clean:
+ cd ../../lib && $(MAKE) clean
+ rm -rf ./release/obj
+ cd ./release && rm -f *.so
--- /dev/null
+<plugin id="oic.plugin.mqtt-light"
+ version="0.1"
+ name="mqtt-light"
+ url="light"
+ resourcetype="oic.light">
+ <runtime library="lightserver_mqtt_plugin" funcs="mqtt_plugin_lightserver_funcs"/>
+</plugin>
--- /dev/null
+add_subdirectory(cpp)
+
+option(WITH_THREADING "Include client library threading support?" ON)
+if (${WITH_THREADING} STREQUAL ON)
+ add_definitions("-DWITH_THREADING")
+ if (WIN32)
+ set (PTHREAD_LIBRARIES C:\\pthreads\\Pre-built.2\\lib\\x86\\pthreadVC2.lib)
+ set (PTHREAD_INCLUDE_DIR C:\\pthreads\\Pre-built.2\\include)
+ else (WIN32)
+ set (PTHREAD_LIBRARIES pthread)
+ set (PTHREAD_INCLUDE_DIR "")
+ endif (WIN32)
+else (${WITH_THREADING} STREQUAL ON)
+ set (PTHREAD_LIBRARIES "")
+ set (PTHREAD_INCLUDE_DIR "")
+endif (${WITH_THREADING} STREQUAL ON)
+
+include_directories(${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/lib
+ ${STDBOOL_H_PATH} ${STDINT_H_PATH}
+ ${OPENSSL_INCLUDE_DIR} ${PTHREAD_INCLUDE_DIR})
+link_directories(${mosquitto_SOURCE_DIR}/lib)
+
+add_library(libmosquitto SHARED
+ logging_mosq.c logging_mosq.h
+ memory_mosq.c memory_mosq.h
+ messages_mosq.c messages_mosq.h
+ mosquitto.c mosquitto.h
+ mosquitto_internal.h
+ mqtt3_protocol.h
+ net_mosq.c net_mosq.h
+ read_handle.c read_handle.h
+ read_handle_client.c
+ read_handle_shared.c
+ send_client_mosq.c
+ send_mosq.c send_mosq.h
+ srv_mosq.c
+ thread_mosq.c
+ time_mosq.c
+ tls_mosq.c
+ util_mosq.c util_mosq.h
+ will_mosq.c will_mosq.h)
+
+set (LIBRARIES ${OPENSSL_LIBRARIES} ${PTHREAD_LIBRARIES})
+
+if (UNIX AND NOT APPLE)
+ set (LIBRARIES ${LIBRARIES} rt)
+endif (UNIX AND NOT APPLE)
+
+if (WIN32)
+ set (LIBRARIES ${LIBRARIES} ws2_32)
+endif (WIN32)
+
+option(WITH_SRV "Include SRV lookup support?" ON)
+if (${WITH_SRV} STREQUAL ON)
+ set (LIBRARIES ${LIBRARIES} cares)
+endif (${WITH_SRV} STREQUAL ON)
+
+target_link_libraries(libmosquitto ${LIBRARIES})
+
+set_target_properties(libmosquitto PROPERTIES
+ OUTPUT_NAME mosquitto
+ VERSION ${VERSION}
+ SOVERSION 1
+)
+
+install(TARGETS libmosquitto RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR})
+install(FILES mosquitto.h DESTINATION ${INCLUDEDIR})
+
+if (UNIX)
+ install(CODE "EXEC_PROGRAM(/sbin/ldconfig)")
+endif (UNIX)
--- /dev/null
+include config.mk
+
+.PHONY : really clean install
+
+MOSQ_OBJS=mosquitto.o \
+ logging_mosq.o \
+ memory_mosq.o \
+ messages_mosq.o \
+ net_mosq.o \
+ read_handle.o \
+ read_handle_client.o \
+ read_handle_shared.o \
+ send_mosq.o \
+ send_client_mosq.o \
+ srv_mosq.o \
+ thread_mosq.o \
+ time_mosq.o \
+ tls_mosq.o \
+ util_mosq.o \
+ will_mosq.o
+
+all : libmosquitto.so.${SOVERSION} libmosquitto.a
+ $(MAKE) -C cpp
+ $(MAKE) -C python
+
+install : all
+ $(INSTALL) -d ${DESTDIR}$(prefix)/lib${LIB_SUFFIX}/
+ $(INSTALL) -s libmosquitto.so.${SOVERSION} ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so.${SOVERSION}
+ ln -sf libmosquitto.so.${SOVERSION} ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so
+ $(INSTALL) -d ${DESTDIR}${prefix}/include/
+ $(INSTALL) mosquitto.h ${DESTDIR}${prefix}/include/mosquitto.h
+ $(MAKE) -C cpp install
+ $(MAKE) -C python install
+
+uninstall :
+ -rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so.${SOVERSION}
+ -rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so
+ -rm -f ${DESTDIR}${prefix}/include/mosquitto.h
+
+reallyclean : clean
+
+clean :
+ -rm -f *.o libmosquitto.so.${SOVERSION} libmosquitto.so libmosquitto.a
+ $(MAKE) -C cpp clean
+ $(MAKE) -C python clean
+
+libmosquitto.so.${SOVERSION} : ${MOSQ_OBJS}
+ $(CC) -shared $(LIB_LDFLAGS) $^ -o $@ ${LIB_LIBS}
+
+libmosquitto.a : ${MOSQ_OBJS}
+ $(AR) cr $@ $^
+mosquitto.o : mosquitto.c mosquitto.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+logging_mosq.o : logging_mosq.c logging_mosq.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+messages_mosq.o : messages_mosq.c messages_mosq.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+memory_mosq.o : memory_mosq.c memory_mosq.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+net_mosq.o : net_mosq.c net_mosq.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+read_handle.o : read_handle.c read_handle.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+read_handle_client.o : read_handle_client.c read_handle.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+read_handle_shared.o : read_handle_shared.c read_handle.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+send_mosq.o : send_mosq.c send_mosq.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+send_client_mosq.o : send_client_mosq.c send_mosq.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+srv_mosq.o : srv_mosq.c
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+thread_mosq.o : thread_mosq.c
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+time_mosq.o : time_mosq.c
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+tls_mosq.o : tls_mosq.c
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+util_mosq.o : util_mosq.c util_mosq.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
+will_mosq.o : will_mosq.c will_mosq.h
+ $(CC) $(LIB_CFLAGS) -c $< -o $@
+
--- /dev/null
+/* ============================================================
+ * Control compile time options.
+ * ============================================================
+ *
+ * Compile time options have moved to config.mk.
+ */
+
+
+/* ============================================================
+ * Compatibility defines
+ *
+ * Generally for Windows native support.
+ * ============================================================ */
+#ifdef WIN32
+#define snprintf sprintf_s
+#define strcasecmp strcmpi
+#define strtok_r strtok_s
+#define strerror_r(e, b, l) strerror_s(b, l, e)
+#endif
--- /dev/null
+# =============================================================================
+# User configuration section.
+#
+# Largely, these are options that are designed to make mosquitto run more
+# easily in restrictive environments by removing features.
+#
+# Modify the variable below to enable/disable features.
+#
+# Can also be overriden at the command line, e.g.:
+#
+# make WITH_TLS=no
+# =============================================================================
+
+# Uncomment to compile the broker with tcpd/libwrap support.
+#WITH_WRAP:=yes
+
+# Comment out to disable SSL/TLS support in the broker and client.
+# Disabling this will also mean that passwords must be stored in plain text. It
+# is strongly recommended that you only disable WITH_TLS if you are not using
+# password authentication at all.
+WITH_TLS:=yes
+
+# Comment out to disable TLS/PSK support in the broker and client. Requires
+# WITH_TLS=yes.
+# This must be disabled if using openssl < 1.0.
+WITH_TLS_PSK:=yes
+
+# Comment out to disable client client threading support.
+WITH_THREADING:=yes
+
+# Uncomment to compile the broker with strict protocol support. This means that
+# both the client library and the broker will be very strict about protocol
+# compliance on incoming data. Neither of them will return an error on
+# incorrect "remaining length" values if this is commented out. The old
+# behaviour (prior to 0.12) is equivalent to compiling with
+# WITH_STRICT_PROTOCOL defined and means that clients will be immediately
+# disconnected from the broker on non-compliance.
+#WITH_STRICT_PROTOCOL:=yes
+
+# Comment out to remove bridge support from the broker. This allow the broker
+# to connect to other brokers and subscribe/publish to topics. You probably
+# want to leave this included unless you want to save a very small amount of
+# memory size and CPU time.
+WITH_BRIDGE:=yes
+
+# Comment out to remove persistent database support from the broker. This
+# allows the broker to store retained messages and durable subscriptions to a
+# file periodically and on shutdown. This is usually desirable (and is
+# suggested by the MQTT spec), but it can be disabled if required.
+WITH_PERSISTENCE:=yes
+
+# Comment out to remove memory tracking support from the broker. If disabled,
+# mosquitto won't track heap memory usage nor export '$SYS/broker/heap/current
+# size', but will use slightly less memory and CPU time.
+WITH_MEMORY_TRACKING:=yes
+
+# Compile with database upgrading support? If disabled, mosquitto won't
+# automatically upgrade old database versions.
+# Not currently supported.
+#WITH_DB_UPGRADE:=yes
+
+# Comment out to remove publishing of the $SYS topic hierarchy containing
+# information about the broker state.
+WITH_SYS_TREE:=yes
+
+# Build with Python module. Comment out if Python is not installed, or required
+# Python modules are not available.
+WITH_PYTHON:=yes
+
+# Build with SRV lookup support.
+WITH_SRV:=no
+
+# =============================================================================
+# End of user configuration
+# =============================================================================
+
+
+# Also bump lib/mosquitto.h, lib/python/setup.py, CMakeLists.txt,
+# installer/mosquitto.nsi, installer/mosquitto-cygwin.nsi
+VERSION=1.3.1
+TIMESTAMP:=$(shell date "+%F %T%z")
+
+# Client library SO version. Bump if incompatible API/ABI changes are made.
+SOVERSION=1
+
+# Man page generation requires xsltproc and docbook-xsl
+XSLTPROC=xsltproc
+# For html generation
+DB_HTML_XSL=man/html.xsl
+
+#MANCOUNTRIES=en_GB
+
+UNAME:=$(shell uname -s)
+ifeq ($(UNAME),SunOS)
+ ifeq ($(CC),cc)
+ CFLAGS?=-O
+ else
+ CFLAGS?=-Wall -ggdb -O2
+ endif
+else
+ CFLAGS?=-Wall -ggdb -O2
+endif
+
+LIB_CFLAGS:=${CFLAGS} ${CPPFLAGS} -I. -I.. -I./lib
+LIB_CXXFLAGS:=$(LIB_CFLAGS) ${CPPFLAGS}
+LIB_LDFLAGS:=${LDFLAGS}
+
+BROKER_CFLAGS:=${LIB_CFLAGS} ${CPPFLAGS} -DVERSION="\"${VERSION}\"" -DTIMESTAMP="\"${TIMESTAMP}\"" -DWITH_BROKER
+CLIENT_CFLAGS:=${CFLAGS} ${CPPFLAGS} -I./lib -DVERSION="\"${VERSION}\""
+
+ifeq ($(UNAME),FreeBSD)
+ BROKER_LIBS:=-lm
+else
+ BROKER_LIBS:=-ldl -lm
+endif
+LIB_LIBS:=
+PASSWD_LIBS:=
+
+ifeq ($(UNAME),Linux)
+ BROKER_LIBS:=$(BROKER_LIBS) -lrt
+ LIB_LIBS:=$(LIB_LIBS) -lrt
+endif
+
+CLIENT_LDFLAGS:=$(LDFLAGS) -L./lib ./lib/libmosquitto.so.${SOVERSION}
+
+ifeq ($(UNAME),SunOS)
+ ifeq ($(CC),cc)
+ LIB_CFLAGS:=$(LIB_CFLAGS) -xc99 -KPIC
+ else
+ LIB_CFLAGS:=$(LIB_CFLAGS) -fPIC
+ endif
+
+ ifeq ($(CXX),CC)
+ LIB_CXXFLAGS:=$(LIB_CXXFLAGS) -KPIC
+ else
+ LIB_CXXFLAGS:=$(LIB_CXXFLAGS) -fPIC
+ endif
+else
+ LIB_CFLAGS:=$(LIB_CFLAGS) -fPIC
+ LIB_CXXFLAGS:=$(LIB_CXXFLAGS) -fPIC
+endif
+
+ifneq ($(UNAME),SunOS)
+ LIB_LDFLAGS:=$(LIB_LDFLAGS) -Wl,-soname,libmosquitto.so.$(SOVERSION)
+endif
+
+ifeq ($(UNAME),QNX)
+ BROKER_LIBS:=$(BROKER_LIBS) -lsocket
+ LIB_LIBS:=$(LIB_LIBS) -lsocket
+endif
+
+ifeq ($(WITH_WRAP),yes)
+ BROKER_LIBS:=$(BROKER_LIBS) -lwrap
+ BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_WRAP
+endif
+
+ifeq ($(WITH_TLS),yes)
+ BROKER_LIBS:=$(BROKER_LIBS) -lssl -lcrypto
+ LIB_LIBS:=$(LIB_LIBS) -lssl -lcrypto
+ BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_TLS
+ LIB_CFLAGS:=$(LIB_CFLAGS) -DWITH_TLS
+ PASSWD_LIBS:=-lcrypto
+ CLIENT_CFLAGS:=$(CLIENT_CFLAGS) -DWITH_TLS
+
+ ifeq ($(WITH_TLS_PSK),yes)
+ BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_TLS_PSK
+ LIB_CFLAGS:=$(LIB_CFLAGS) -DWITH_TLS_PSK
+ CLIENT_CFLAGS:=$(CLIENT_CFLAGS) -DWITH_TLS_PSK
+ endif
+endif
+
+ifeq ($(WITH_THREADING),yes)
+ LIB_LIBS:=$(LIB_LIBS) -lpthread
+ LIB_CFLAGS:=$(LIB_CFLAGS) -DWITH_THREADING
+endif
+
+ifeq ($(WITH_STRICT_PROTOCOL),yes)
+ LIB_CFLAGS:=$(LIB_CFLAGS) -DWITH_STRICT_PROTOCOL
+ BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_STRICT_PROTOCOL
+endif
+
+ifeq ($(WITH_BRIDGE),yes)
+ BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_BRIDGE
+endif
+
+ifeq ($(WITH_PERSISTENCE),yes)
+ BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_PERSISTENCE
+endif
+
+ifeq ($(WITH_MEMORY_TRACKING),yes)
+ ifneq ($(UNAME),SunOS)
+ BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_MEMORY_TRACKING
+ endif
+endif
+
+#ifeq ($(WITH_DB_UPGRADE),yes)
+# BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_DB_UPGRADE
+#endif
+
+ifeq ($(WITH_SYS_TREE),yes)
+ BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_SYS_TREE
+endif
+
+ifeq ($(WITH_SRV),yes)
+ LIB_CFLAGS:=$(LIB_CFLAGS) -DWITH_SRV
+ LIB_LIBS:=$(LIB_LIBS) -lcares
+endif
+
+ifeq ($(UNAME),SunOS)
+ BROKER_LIBS:=$(BROKER_LIBS) -lsocket -lnsl
+ LIB_LIBS:=$(LIB_LIBS) -lsocket -lnsl
+endif
+
+
+INSTALL?=install
+prefix=/usr/local
+mandir=${prefix}/share/man
+localedir=${prefix}/share/locale
--- /dev/null
+include_directories(${mosquitto_SOURCE_DIR}/lib ${mosquitto_SOURCE_DIR}/lib/cpp
+ ${STDBOOL_H_PATH} ${STDINT_H_PATH})
+link_directories(${mosquitto_BINARY_DIR}/lib)
+
+add_library(mosquittopp SHARED
+ mosquittopp.cpp mosquittopp.h)
+
+target_link_libraries(mosquittopp libmosquitto)
+set_target_properties(mosquittopp PROPERTIES
+ VERSION ${VERSION}
+ SOVERSION 1
+)
+install(TARGETS mosquittopp RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR})
+install(FILES mosquittopp.h DESTINATION ${INCLUDEDIR})
+
+if (UNIX)
+ install(CODE "EXEC_PROGRAM(/sbin/ldconfig)")
+endif (UNIX)
--- /dev/null
+include ../config.mk
+
+ifneq ($(UNAME),SunOS)
+ LIB_LDFLAGS:=$(LDFLAGS) -Wl,-soname,libmosquittopp.so.${SOVERSION}
+endif
+
+.PHONY : clean install
+
+all : libmosquittopp.so.${SOVERSION}
+
+install : all
+ $(INSTALL) -d ${DESTDIR}$(prefix)/lib${LIB_SUFFIX}/
+ $(INSTALL) -s libmosquittopp.so.${SOVERSION} ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquittopp.so.${SOVERSION}
+ ln -sf libmosquittopp.so.${SOVERSION} ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquittopp.so
+ $(INSTALL) -d ${DESTDIR}${prefix}/include/
+ $(INSTALL) mosquittopp.h ${DESTDIR}${prefix}/include/mosquittopp.h
+
+uninstall :
+ -rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquittopp.so.${SOVERSION}
+ -rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquittopp.so
+ -rm -f ${DESTDIR}${prefix}/include/mosquittopp.h
+
+clean :
+ -rm -f *.o libmosquittopp.so.${SOVERSION}
+
+libmosquittopp.so.${SOVERSION} : mosquittopp.o
+ $(CXX) -shared $(LIB_LDFLAGS) $< -o $@ ../libmosquitto.so.${SOVERSION}
+
+mosquittopp.o : mosquittopp.cpp mosquittopp.h
+ $(CXX) $(LIB_CXXFLAGS) -c $< -o $@
+
--- /dev/null
+/*
+Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <cstdlib>
+#include <mosquitto.h>
+#include <mosquittopp.h>
+
+namespace mosqpp {
+
+static void on_connect_wrapper(struct mosquitto *mosq, void *userdata, int rc)
+{
+ class mosquittopp *m = (class mosquittopp *)userdata;
+ m->on_connect(rc);
+}
+
+static void on_disconnect_wrapper(struct mosquitto *mosq, void *userdata, int rc)
+{
+ class mosquittopp *m = (class mosquittopp *)userdata;
+ m->on_disconnect(rc);
+}
+
+static void on_publish_wrapper(struct mosquitto *mosq, void *userdata, int mid)
+{
+ class mosquittopp *m = (class mosquittopp *)userdata;
+ m->on_publish(mid);
+}
+
+static void on_message_wrapper(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
+{
+ class mosquittopp *m = (class mosquittopp *)userdata;
+ m->on_message(message);
+}
+
+static void on_subscribe_wrapper(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos)
+{
+ class mosquittopp *m = (class mosquittopp *)userdata;
+ m->on_subscribe(mid, qos_count, granted_qos);
+}
+
+static void on_unsubscribe_wrapper(struct mosquitto *mosq, void *userdata, int mid)
+{
+ class mosquittopp *m = (class mosquittopp *)userdata;
+ m->on_unsubscribe(mid);
+}
+
+
+static void on_log_wrapper(struct mosquitto *mosq, void *userdata, int level, const char *str)
+{
+ class mosquittopp *m = (class mosquittopp *)userdata;
+ m->on_log(level, str);
+}
+
+int lib_version(int *major, int *minor, int *revision)
+{
+ if(major) *major = LIBMOSQUITTO_MAJOR;
+ if(minor) *minor = LIBMOSQUITTO_MINOR;
+ if(revision) *revision = LIBMOSQUITTO_REVISION;
+ return LIBMOSQUITTO_VERSION_NUMBER;
+}
+
+int lib_init()
+{
+ return mosquitto_lib_init();
+}
+
+int lib_cleanup()
+{
+ return mosquitto_lib_cleanup();
+}
+
+const char* strerror(int mosq_errno)
+{
+ return mosquitto_strerror(mosq_errno);
+}
+
+const char* connack_string(int connack_code)
+{
+ return mosquitto_connack_string(connack_code);
+}
+
+int sub_topic_tokenise(const char *subtopic, char ***topics, int *count)
+{
+ return mosquitto_sub_topic_tokenise(subtopic, topics, count);
+}
+
+int sub_topic_tokens_free(char ***topics, int count)
+{
+ return mosquitto_sub_topic_tokens_free(topics, count);
+}
+
+int topic_matches_sub(const char *sub, const char *topic, bool *result)
+{
+ return mosquitto_topic_matches_sub(sub, topic, result);
+}
+
+mosquittopp::mosquittopp(const char *id, bool clean_session)
+{
+ m_mosq = mosquitto_new(id, clean_session, this);
+ mosquitto_connect_callback_set(m_mosq, on_connect_wrapper);
+ mosquitto_disconnect_callback_set(m_mosq, on_disconnect_wrapper);
+ mosquitto_publish_callback_set(m_mosq, on_publish_wrapper);
+ mosquitto_message_callback_set(m_mosq, on_message_wrapper);
+ mosquitto_subscribe_callback_set(m_mosq, on_subscribe_wrapper);
+ mosquitto_unsubscribe_callback_set(m_mosq, on_unsubscribe_wrapper);
+ mosquitto_log_callback_set(m_mosq, on_log_wrapper);
+}
+
+mosquittopp::~mosquittopp()
+{
+ mosquitto_destroy(m_mosq);
+}
+
+int mosquittopp::reinitialise(const char *id, bool clean_session)
+{
+ int rc;
+ rc = mosquitto_reinitialise(m_mosq, id, clean_session, this);
+ if(rc == MOSQ_ERR_SUCCESS){
+ mosquitto_connect_callback_set(m_mosq, on_connect_wrapper);
+ mosquitto_disconnect_callback_set(m_mosq, on_disconnect_wrapper);
+ mosquitto_publish_callback_set(m_mosq, on_publish_wrapper);
+ mosquitto_message_callback_set(m_mosq, on_message_wrapper);
+ mosquitto_subscribe_callback_set(m_mosq, on_subscribe_wrapper);
+ mosquitto_unsubscribe_callback_set(m_mosq, on_unsubscribe_wrapper);
+ mosquitto_log_callback_set(m_mosq, on_log_wrapper);
+ }
+ return rc;
+}
+
+int mosquittopp::connect(const char *host, int port, int keepalive)
+{
+ return mosquitto_connect(m_mosq, host, port, keepalive);
+}
+
+int mosquittopp::connect(const char *host, int port, int keepalive, const char *bind_address)
+{
+ return mosquitto_connect_bind(m_mosq, host, port, keepalive, bind_address);
+}
+
+int mosquittopp::connect_async(const char *host, int port, int keepalive)
+{
+ return mosquitto_connect_async(m_mosq, host, port, keepalive);
+}
+
+int mosquittopp::connect_async(const char *host, int port, int keepalive, const char *bind_address)
+{
+ return mosquitto_connect_bind_async(m_mosq, host, port, keepalive, bind_address);
+}
+
+int mosquittopp::reconnect()
+{
+ return mosquitto_reconnect(m_mosq);
+}
+
+int mosquittopp::reconnect_async()
+{
+ return mosquitto_reconnect_async(m_mosq);
+}
+
+int mosquittopp::disconnect()
+{
+ return mosquitto_disconnect(m_mosq);
+}
+
+int mosquittopp::socket()
+{
+ return mosquitto_socket(m_mosq);
+}
+
+int mosquittopp::will_set(const char *topic, int payloadlen, const void *payload, int qos, bool retain)
+{
+ return mosquitto_will_set(m_mosq, topic, payloadlen, payload, qos, retain);
+}
+
+int mosquittopp::will_clear()
+{
+ return mosquitto_will_clear(m_mosq);
+}
+
+int mosquittopp::username_pw_set(const char *username, const char *password)
+{
+ return mosquitto_username_pw_set(m_mosq, username, password);
+}
+
+int mosquittopp::publish(int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain)
+{
+ return mosquitto_publish(m_mosq, mid, topic, payloadlen, payload, qos, retain);
+}
+
+void mosquittopp::reconnect_delay_set(unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff)
+{
+ mosquitto_reconnect_delay_set(m_mosq, reconnect_delay, reconnect_delay_max, reconnect_exponential_backoff);
+}
+
+int mosquittopp::max_inflight_messages_set(unsigned int max_inflight_messages)
+{
+ return mosquitto_max_inflight_messages_set(m_mosq, max_inflight_messages);
+}
+
+void mosquittopp::message_retry_set(unsigned int message_retry)
+{
+ mosquitto_message_retry_set(m_mosq, message_retry);
+}
+
+int mosquittopp::subscribe(int *mid, const char *sub, int qos)
+{
+ return mosquitto_subscribe(m_mosq, mid, sub, qos);
+}
+
+int mosquittopp::unsubscribe(int *mid, const char *sub)
+{
+ return mosquitto_unsubscribe(m_mosq, mid, sub);
+}
+
+int mosquittopp::loop(int timeout, int max_packets)
+{
+ return mosquitto_loop(m_mosq, timeout, max_packets);
+}
+
+int mosquittopp::loop_misc()
+{
+ return mosquitto_loop_misc(m_mosq);
+}
+
+int mosquittopp::loop_read(int max_packets)
+{
+ return mosquitto_loop_read(m_mosq, max_packets);
+}
+
+int mosquittopp::loop_write(int max_packets)
+{
+ return mosquitto_loop_write(m_mosq, max_packets);
+}
+
+int mosquittopp::loop_forever(int timeout, int max_packets)
+{
+ return mosquitto_loop_forever(m_mosq, timeout, max_packets);
+}
+
+int mosquittopp::loop_start()
+{
+ return mosquitto_loop_start(m_mosq);
+}
+
+int mosquittopp::loop_stop(bool force)
+{
+ return mosquitto_loop_stop(m_mosq, force);
+}
+
+bool mosquittopp::want_write()
+{
+ return mosquitto_want_write(m_mosq);
+}
+
+void mosquittopp::user_data_set(void *userdata)
+{
+ mosquitto_user_data_set(m_mosq, userdata);
+}
+
+int mosquittopp::tls_set(const char *cafile, const char *capath, const char *certfile, const char *keyfile, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata))
+{
+ return mosquitto_tls_set(m_mosq, cafile, capath, certfile, keyfile, pw_callback);
+}
+
+int mosquittopp::tls_opts_set(int cert_reqs, const char *tls_version, const char *ciphers)
+{
+ return mosquitto_tls_opts_set(m_mosq, cert_reqs, tls_version, ciphers);
+}
+
+int mosquittopp::tls_insecure_set(bool value)
+{
+ return mosquitto_tls_insecure_set(m_mosq, value);
+}
+
+int mosquittopp::tls_psk_set(const char *psk, const char *identity, const char *ciphers)
+{
+ return mosquitto_tls_psk_set(m_mosq, psk, identity, ciphers);
+}
+
+}
--- /dev/null
+/*
+Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+This product includes software developed by the OpenSSL Project for use in the
+OpenSSL Toolkit. (http://www.openssl.org/)
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com)
+This product includes software written by Tim Hudson (tjh@cryptsoft.com)
+*/
+
+#ifndef _MOSQUITTOPP_H_
+#define _MOSQUITTOPP_H_
+
+#ifdef _WIN32
+# ifdef mosquittopp_EXPORTS
+# define mosqpp_EXPORT __declspec(dllexport)
+# else
+# define mosqpp_EXPORT __declspec(dllimport)
+# endif
+#else
+# define mosqpp_EXPORT
+#endif
+
+#include <cstdlib>
+#include <time.h>
+#include "../mosquitto.h"
+
+namespace mosqpp {
+
+mosqpp_EXPORT const char *strerror(int mosq_errno);
+mosqpp_EXPORT const char *connack_string(int connack_code);
+mosqpp_EXPORT int sub_topic_tokenise(const char *subtopic, char ***topics, int *count);
+mosqpp_EXPORT int sub_topic_tokens_free(char ***topics, int count);
+mosqpp_EXPORT int lib_version(int *major, int *minor, int *revision);
+mosqpp_EXPORT int lib_init();
+mosqpp_EXPORT int lib_cleanup();
+mosqpp_EXPORT int topic_matches_sub(const char *sub, const char *topic, bool *result);
+
+/*
+ * Class: mosquittopp
+ *
+ * A mosquitto client class. This is a C++ wrapper class for the mosquitto C
+ * library. Please see mosquitto.h for details of the functions.
+ */
+class mosqpp_EXPORT mosquittopp {
+ private:
+ struct mosquitto *m_mosq;
+ public:
+ mosquittopp(const char *id=NULL, bool clean_session=true);
+ ~mosquittopp();
+
+ int reinitialise(const char *id, bool clean_session);
+ int socket();
+ int will_set(const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
+ int will_clear();
+ int username_pw_set(const char *username, const char *password=NULL);
+ int connect(const char *host, int port=1883, int keepalive=60);
+ int connect_async(const char *host, int port=1883, int keepalive=60);
+ int connect(const char *host, int port, int keepalive, const char *bind_address);
+ int connect_async(const char *host, int port, int keepalive, const char *bind_address);
+ int reconnect();
+ int reconnect_async();
+ int disconnect();
+ int publish(int *mid, const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
+ int subscribe(int *mid, const char *sub, int qos=0);
+ int unsubscribe(int *mid, const char *sub);
+ void reconnect_delay_set(unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff);
+ int max_inflight_messages_set(unsigned int max_inflight_messages);
+ void message_retry_set(unsigned int message_retry);
+ void user_data_set(void *userdata);
+ int tls_set(const char *cafile, const char *capath=NULL, const char *certfile=NULL, const char *keyfile=NULL, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)=NULL);
+ int tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL);
+ int tls_insecure_set(bool value);
+ int tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL);
+
+ int loop(int timeout=-1, int max_packets=1);
+ int loop_misc();
+ int loop_read(int max_packets=1);
+ int loop_write(int max_packets=1);
+ int loop_forever(int timeout=-1, int max_packets=1);
+ int loop_start();
+ int loop_stop(bool force=false);
+ bool want_write();
+
+ virtual void on_connect(int rc) {return;};
+ virtual void on_disconnect(int rc) {return;};
+ virtual void on_publish(int mid) {return;};
+ virtual void on_message(const struct mosquitto_message *message) {return;};
+ virtual void on_subscribe(int mid, int qos_count, const int *granted_qos) {return;};
+ virtual void on_unsubscribe(int mid) {return;};
+ virtual void on_log(int level, const char *str) {return;};
+ virtual void on_error() {return;};
+};
+
+}
+#endif
--- /dev/null
+/usr/lib/i386-linux-gnu/mesa-egl:
+ libOpenVG.so.1 -> libOpenVG.so.1.0.0
+ libwayland-egl.so.1 -> libwayland-egl.so.1.0.0
+ libEGL.so.1 -> libEGL.so.1.0.0
+/usr/lib/i386-linux-gnu/mesa:
+ libGL.so.1 -> libGL.so.1.2.0
+/lib/i386-linux-gnu:
+ libblkid.so.1 -> libblkid.so.1.1.0
+ libnss_dns.so.2 -> libnss_dns-2.15.so
+ libnss_compat.so.2 -> libnss_compat-2.15.so
+ libwrap.so.0 -> libwrap.so.0.7.6
+ libpcsclite.so.1 -> libpcsclite.so.1.0.0
+ libkeyutils.so.1 -> libkeyutils.so.1.4
+ libntfs-3g.so.831 -> libntfs-3g.so.831.0.0
+ libpcprofile.so -> libpcprofile.so
+ libext2fs.so.2 -> libext2fs.so.2.4
+ libslang.so.2 -> libslang.so.2.2.4
+ libpci.so.3 -> libpci.so.3.1.8
+ libparted.so.0 -> libparted.so.0.0.1
+ libdl.so.2 -> libdl-2.15.so
+ libutil.so.1 -> libutil-2.15.so
+ libgcc_s.so.1 -> libgcc_s.so.1
+ libnss_nisplus.so.2 -> libnss_nisplus-2.15.so
+ libbsd.so.0 -> libbsd.so.0.3.0
+ libpng12.so.0 -> libpng12.so.0.46.0
+ librt.so.1 -> librt-2.15.so
+ ld-linux.so.2 -> ld-2.15.so
+ libncurses.so.5 -> libncurses.so.5.9
+ libcrypto.so.1.0.0 -> libcrypto.so.1.0.0
+ libacl.so.1 -> libacl.so.1.1.0
+ libgcrypt.so.11 -> libgcrypt.so.11.7.0
+ libnsl.so.1 -> libnsl-2.15.so
+ libpam.so.0 -> libpam.so.0.83.0
+ libmount.so.1 -> libmount.so.1.1.0
+ libselinux.so.1 -> libselinux.so.1
+ libpcre.so.3 -> libpcre.so.3.12.1
+ libdbus-1.so.3 -> libdbus-1.so.3.5.8
+ libuuid.so.1 -> libuuid.so.1.3.0
+ libexpat.so.1 -> libexpat.so.1.5.2
+ libnss_files.so.2 -> libnss_files-2.15.so
+ libcom_err.so.2 -> libcom_err.so.2.1
+ libnss_nis.so.2 -> libnss_nis-2.15.so
+ libatasmart.so.4 -> libatasmart.so.4.0.4
+ libssl.so.1.0.0 -> libssl.so.1.0.0
+ libthread_db.so.1 -> libthread_db-1.0.so
+ libncursesw.so.5 -> libncursesw.so.5.9
+ libgpg-error.so.0 -> libgpg-error.so.0.8.0
+ libe2p.so.2 -> libe2p.so.2.3
+ libss.so.2 -> libss.so.2.0
+ libBrokenLocale.so.1 -> libBrokenLocale-2.15.so
+ libcidn.so.1 -> libcidn-2.15.so
+ libpamc.so.0 -> libpamc.so.0.82.1
+ libmemusage.so -> libmemusage.so
+ libglib-2.0.so.0 -> libglib-2.0.so.0.3200.4
+ libnss_hesiod.so.2 -> libnss_hesiod-2.15.so
+ libanl.so.1 -> libanl-2.15.so
+ libcap.so.2 -> libcap.so.2.22
+ libresolv.so.2 -> libresolv-2.15.so
+ libattr.so.1 -> libattr.so.1.1.0
+ libpthread.so.0 -> libpthread-2.15.so
+ libm.so.6 -> libm-2.15.so
+ libz.so.1 -> libz.so.1.2.3.4
+ libhistory.so.6 -> libhistory.so.6.2
+ libnih-dbus.so.1 -> libnih-dbus.so.1.0.0
+ libSegFault.so -> libSegFault.so
+ libudev.so.0 -> libudev.so.0.13.0
+ libreadline.so.6 -> libreadline.so.6.2
+ libusb-1.0.so.0 -> libusb-1.0.so.0.1.0
+ libcrypt.so.1 -> libcrypt-2.15.so
+ libpam_misc.so.0 -> libpam_misc.so.0.82.0
+ libnih.so.1 -> libnih.so.1.0.0
+ libtinfo.so.5 -> libtinfo.so.5.9
+ libpopt.so.0 -> libpopt.so.0.0.0
+ libbz2.so.1.0 -> libbz2.so.1.0.4
+ libc.so.6 -> libc-2.15.so
+ libusb-0.1.so.4 -> libusb-0.1.so.4.4.4
+/usr/lib/i386-linux-gnu:
+ libnss3.so -> libnss3.so
+ libsmbclient.so.0 -> libsmbclient.so.0
+ libgobject-2.0.so.0 -> libgobject-2.0.so.0.3200.4
+ libpoppler-glib.so.8 -> libpoppler-glib.so.8.2.0
+ libavcodec.so.53 -> libavcodec.so.53.35.0
+ libwbclient.so.0 -> libwbclient.so.0
+ libbonoboui-2.so.0 -> libbonoboui-2.so.0.0.0
+ libjasper.so.1 -> libjasper.so.1.0.0
+ libsqlite3.so.0 -> libsqlite3.so.0.8.6
+ libgstbasevideo-1.0.so.0 -> libgstbasevideo-1.0.so.0.5.0
+ librtmp.so.0 -> librtmp.so.0
+ libframe.so.6 -> libframe.so.6.0.0
+ libnspr4.so -> libnspr4.so
+ libportaudio.so.2 -> libportaudio.so.2.0.0
+ libXdmcp.so.6 -> libXdmcp.so.6.0.0
+ libcanberra-gtk3.so.0 -> libcanberra-gtk3.so.0.1.8
+ libnettle.so.4 -> libnettle.so.4.3
+ libcups.so.2 -> libcups.so.2
+ libxcb-shape.so.0 -> libxcb-shape.so.0.0.0
+ libunistring.so.0 -> libunistring.so.0.1.2
+ libQtDeclarative.so.4 -> libQtDeclarative.so.4.8.1
+ libdbusmenu-gtk3.so.4 -> libdbusmenu-gtk3.so.4.0.13
+ libgsttag-0.10.so.0 -> libgsttag-0.10.so.0.25.0
+ libwmflite-0.2.so.7 -> libwmflite-0.2.so.7.0.1
+ libapt-pkg.so.4.12 -> libapt-pkg.so.4.12.0
+ libQtNetwork.so.4 -> libQtNetwork.so.4.8.1
+ libgnomecanvas-2.so.0 -> libgnomecanvas-2.so.0.3000.3
+ libtheoradec.so.1 -> libtheoradec.so.1.1.4
+ libcanberra.so.0 -> libcanberra.so.0.2.5
+ libgnutls-extra.so.26 -> libgnutls-extra.so.26.21.8
+ libxcb-render.so.0 -> libxcb-render.so.0.0.0
+ libgpm.so.2 -> libgpm.so.2
+ libxcb-util.so.0 -> libxcb-util.so.0.0.0
+ libraw1394.so.11 -> libraw1394.so.11.0.1
+ libpangocairo-1.0.so.0 -> libpangocairo-1.0.so.0.3000.0
+ libssl3.so -> libssl3.so
+ libgstcontroller-0.10.so.0 -> libgstcontroller-0.10.so.0.30.0
+ libcupsimage.so.2 -> libcupsimage.so.2
+ liblcms2.so.2 -> liblcms2.so.2.0.2
+ libgio-2.0.so.0 -> libgio-2.0.so.0.3200.4
+ libtxc_dxtn_s2tc.so.0 -> libtxc_dxtn_s2tc.so.0.0.0
+ libdbus-glib-1.so.2 -> libdbus-glib-1.so.2.2.2
+ libgstallocators-1.0.so.0 -> libgstallocators-1.0.so.0.201.0
+ libXi.so.6 -> libXi.so.6.1.0
+ libsvn_ra_svn-1.so.1 -> libsvn_ra_svn-1.so.1.0.0
+ liblber-2.4.so.2 -> liblber.so
+ libgstsignalprocessor-1.0.so.0 -> libgstsignalprocessor-1.0.so.0.5.0
+ libhcrypto.so.4 -> libhcrypto.so.4.1.0
+ libcanberra-gtk.so.0 -> libcanberra-gtk.so.0.1.8
+ libavahi-glib.so.1 -> libavahi-glib.so.1.0.2
+ libedit.so.2 -> libedit.so.2.11
+ libavahi-ui-gtk3.so.0 -> libavahi-ui-gtk3.so.0.1.4
+ libx264.so.120 -> libx264.so.120
+ libgstsdp-1.0.so.0 -> libgstsdp-1.0.so.0.201.0
+ libgstnet-0.10.so.0 -> libgstnet-0.10.so.0.30.0
+ libfarstream-0.1.so.0 -> libfarstream-0.1.so.0.0.1
+ libgstfft-0.10.so.0 -> libgstfft-0.10.so.0.25.0
+ libgstcdda-0.10.so.0 -> libgstcdda-0.10.so.0.25.0
+ libbamf3.so.0 -> libbamf3.so.0.0.0
+ libgstbasecamerabinsrc-1.0.so.0 -> libgstbasecamerabinsrc-1.0.so.0.7.0
+ libexempi.so.3 -> libexempi.so.3.2.2
+ libXss.so.1 -> libXss.so.1.0.0
+ libffi.so.6 -> libffi.so.6.0.0
+ libavformat.so.53 -> libavformat.so.53.21.1
+ libgstpbutils-0.10.so.0 -> libgstpbutils-0.10.so.0.25.0
+ libcdda_paranoia.so.0 -> libcdda_paranoia.so.0.10.2
+ libavahi-gobject.so.0 -> libavahi-gobject.so.0.0.4
+ libpolkit-gobject-1.so.0 -> libpolkit-gobject-1.so.0.0.0
+ libXfixes.so.3 -> libXfixes.so.3.1.0
+ libp11-kit.so.0 -> libp11-kit.so.0.0.0
+ libpng12.so.0 -> libpng.so
+ libswscale.so.2 -> libswscale.so.2.1.0
+ libxkbfile.so.1 -> libxkbfile.so.1.0.2
+ libcupscgi.so.1 -> libcupscgi.so.1
+ libtic.so.5 -> libtic.so.5.9
+ libSDL-1.2.so.0 -> libSDL-1.2.so.0.11.3
+ libgettextpo.so.0 -> libgettextpo.so.0.5.1
+ libgoa-1.0.so.0 -> libgoa-1.0.so.0.0.0
+ libvisual-0.4.so.0 -> libvisual-0.4.so.0.0.0
+ libQtXml.so.4 -> libQtXml.so.4.8.1
+ libdrm_intel.so.1 -> libdrm_intel.so.1.0.0
+ libltdl.so.7 -> libltdl.so.7.3.0
+ libgomp.so.1 -> libgomp.so.1.0.0
+ libXtst.so.6 -> libXtst.so.6.1.0
+ libgtk-3.so.0 -> libgtk-3.so.0.400.2
+ libogg.so.0 -> libogg.so.0.7.1
+ libXaw.so.7 -> libXaw7.so.7.0.0
+ libssh.so.4 -> libssh.so.4.2.2
+ libtdb.so.1 -> libtdb.so.1.2.9
+ libsvn_ra-1.so.1 -> libsvn_ra-1.so.1.0.0
+ libiec61883.so.0 -> libiec61883.so.0.1.1
+ libk5crypto.so.3 -> libk5crypto.so.3.1
+ libXinerama.so.1 -> libXinerama.so.1.0.0
+ libcupsfilters.so.1 -> libcupsfilters.so.1
+ libfontconfig.so.1 -> libfontconfig.so.1.4.4
+ libXrandr_ltss.so.2 -> libXrandr_ltss.so.2.2.0
+ libcupsdriver.so.1 -> libcupsdriver.so.1
+ libgstcontroller-1.0.so.0 -> libgstcontroller-1.0.so.0.201.0
+ libgnutlsxx.so.27 -> libgnutlsxx.so.27.0.0
+ libICE.so.6 -> libICE.so.6.3.0
+ libQtGui.so.4 -> libQtGui.so.4.8.1
+ libgssrpc.so.4 -> libgssrpc.so.4.1
+ librsvg-2.so.2 -> librsvg-2.so.2.36.1
+ libgdk-x11-2.0.so.0 -> libgdk-x11-2.0.so.0.2400.10
+ libsvn_subr-1.so.1 -> libsvn_subr-1.so.1.0.0
+ libgphoto2.so.2 -> libgphoto2.so.2.4.0
+ libtiff.so.4 -> libtiff.so.4.3.4
+ libv4l1.so.0 -> libv4l1.so.0
+ libgstsdp-0.10.so.0 -> libgstsdp-0.10.so.0.25.0
+ libORBitCosNaming-2.so.0 -> libORBitCosNaming-2.so.0.1.0
+ libdatrie.so.1 -> libdatrie.so.1.1.0
+ libplc4.so -> libplc4.so
+ libwacom.so.2 -> libwacom.so.2.0.0
+ libsoup-gnome-2.4.so.1 -> libsoup-gnome-2.4.so.1.5.0
+ libwayland_ltss-server.so.0 -> libwayland_ltss-server.so.0.0.0
+ libgstpbutils-1.0.so.0 -> libgstpbutils-1.0.so.0.201.0
+ libpangoxft-1.0.so.0 -> libpangoxft-1.0.so.0.3000.0
+ libglibmm-2.4.so.1 -> libglibmm-2.4.so.1.3.0
+ libpulse.so.0 -> libpulse.so.0.13.5
+ libbonobo-activation.so.4 -> libbonobo-activation.so.4.0.0
+ libpolkit-agent-1.so.0 -> libpolkit-agent-1.so.0.0.0
+ libtag.so.1 -> libtag.so.1.7.0
+ libGLEWmx.so.1.6 -> libGLEWmx.so.1.6.0
+ libatspi.so.0 -> libatspi.so.0.0.1
+ libgphoto2_port.so.0 -> libgphoto2_port.so.0.8.0
+ libcurl-gnutls.so.4 -> libcurl.so
+ libgbm.so.1 -> libgbm.so.1.0.0
+ libgstapp-0.10.so.0 -> libgstapp-0.10.so.0.25.0
+ libsndfile.so.1 -> libsndfile.so.1.0.25
+ libgmodule-2.0.so.0 -> libgmodule-2.0.so.0.3200.4
+ libXmu.so.6 -> libXmu.so.6.2.0
+ libaudiofile.so.1 -> libaudiofile.so.1.0.0
+ libexif.so.12 -> libexif.so.12.3.2
+ libXau.so.6 -> libXau.so.6.0.0
+ libglapi.so.0 -> libglapi.so.0.0.0
+ libgtksourceview-3.0.so.0 -> libgtksourceview-3.0.so.0.0.0
+ liborc-0.4.so.0 -> liborc-0.4.so.0.18.0
+ libnotify.so.4 -> libnotify.so.4.0.0
+ libwind.so.0 -> libwind.so.0.0.0
+ libldap_r-2.4.so.2 -> libldap_r.so
+ libpcrecpp.so.0 -> libpcrecpp.so.0.0.0
+ libgstinterfaces-0.10.so.0 -> libgstinterfaces-0.10.so.0.25.0
+ libelf.so.1 -> libelf-0.152.so
+ libdrm_nouveau.so.1 -> libdrm_nouveau1.so
+ libthai.so.0 -> libthai.so.0.1.6
+ libgstnet-1.0.so.0 -> libgstnet-1.0.so.0.201.0
+ libcares.so.2 -> libcares.so.2.0.0
+ liborc-test-0.4.so.0 -> liborc-test-0.4.so.0.18.0
+ libaa.so.1 -> libaa.so.1.0.4
+ libsvn_ra_local-1.so.1 -> libsvn_ra_local-1.so.1.0.0
+ libdrm.so.2 -> libdrm.so.2.4.0
+ libLLVM-3.3.so.1 -> libLLVM-3.3.so.1
+ libpcap.so.0.8 -> libpcap.so.1.1.1
+ libcupsmime.so.1 -> libcupsmime.so.1
+ libxcb.so.1 -> libxcb.so.1.1.0
+ libSM.so.6 -> libSM.so.6.0.1
+ libkms.so.1 -> libkms.so.1.0.0
+ libdbusmenu-gtk.so.4 -> libdbusmenu-gtk.so.4.0.13
+ libFLAC.so.8 -> libFLAC.so.8.2.0
+ libxcb-xfixes.so.0 -> libxcb-xfixes.so.0.0.0
+ libgstriff-1.0.so.0 -> libgstriff-1.0.so.0.201.0
+ libidn.so.11 -> libidn.so.11.6.6
+ libIDL-2.so.0 -> libIDL-2.so.0.0.0
+ libdbusmenu-qt.so.2 -> libdbusmenu-qt.so.2.6.0
+ libQtScript.so.4 -> libQtScript.so.4.8.1
+ libcairo-gobject.so.2 -> libcairo-gobject.so.2.11000.2
+ libluajit-5.1.so.2 -> libluajit-5.1.so.2.0.0
+ libpangomm-1.4.so.1 -> libpangomm-1.4.so.1.0.30
+ libXpm.so.4 -> libXpm.so.4.11.0
+ libsvn_diff-1.so.1 -> libsvn_diff-1.so.1.0.0
+ libdbusmenu-glib.so.4 -> libdbusmenu-glib.so.4.0.13
+ liblua5.1.so.0 -> liblua5.1.so.0.0.0
+ libbonobo-2.so.0 -> libbonobo-2.so.0.0.0
+ libpulse-mainloop-glib.so.0 -> libpulse-mainloop-glib.so.0.0.4
+ libexslt.so.0 -> libexslt.so.0.8.15
+ libmp3lame.so.0 -> libmp3lame.so.0.0.0
+ libpcreposix.so.3 -> libpcreposix.so.3.12.1
+ libquvi.so.7 -> libquvi.so.7.0.0
+ libaudio.so.2 -> libaudio.so.2.4
+ libpulse-simple.so.0 -> libpulse-simple.so.0.0.3
+ liboauth.so.0 -> liboauth.so.0.8.1
+ libQtCore.so.4 -> libQtCore.so.4.8.1
+ libwayland_ltss-client.so.0 -> libwayland_ltss-client.so.0.1.0
+ libQtDBus.so.4 -> libQtDBus.so.4.8.1
+ libtheoraenc.so.1 -> libtheoraenc.so.1.1.2
+ libatkmm-1.6.so.1 -> libatkmm-1.6.so.1.1.0
+ libgailutil-3.so.0 -> libgailutil-3.so.0.0.0
+ libgsttag-1.0.so.0 -> libgsttag-1.0.so.0.201.0
+ libgdk_pixbuf_xlib-2.0.so.0 -> libgdk_pixbuf_xlib-2.0.so.0.2600.1
+ libkrb5.so.3 -> libkrb5.so.3.3
+ libgnome-2.so.0 -> libgnome-2.so.0.3200.1
+ libgallium.so.0 -> libgallium.so.0.0.0
+ libXcomposite.so.1 -> libXcomposite.so.1.0.0
+ libsvn_fs-1.so.1 -> libsvn_fs-1.so.1.0.0
+ libgstreamer-0.10.so.0 -> libgstreamer-0.10.so.0.30.0
+ libXrender.so.1 -> libXrender.so.1.3.0
+ libmng.so.1 -> libmng.so.1.1.0.10
+ libgdu.so.0 -> libgdu.so.0.0.0
+ libxatracker.so.1 -> libxatracker.so.1.0.0
+ librom1394.so.0 -> librom1394.so.0.3.0
+ liblua5.1-c++.so.0 -> liblua5.1-c++.so.0.0.0
+ libplds4.so -> libplds4.so
+ libbamf.so.0 -> libbamf.so.0.0.0
+ libheimntlm.so.0 -> libheimntlm.so.0.1.0
+ libarchive.so.12 -> libarchive.so.12.0.3
+ libmad.so.0 -> libmad.so.0.2.1
+ libgthread-2.0.so.0 -> libgthread-2.0.so.0.3200.4
+ libgstaudio-1.0.so.0 -> libgstaudio-1.0.so.0.201.0
+ libgudev-1.0.so.0 -> libgudev-1.0.so.0.1.1
+ libvpx.so.1 -> libvpx.so.1.2.0
+ libgailutil.so.18 -> libgailutil.so.18.0.1
+ libsvn_client-1.so.1 -> libsvn_client-1.so.1.0.0
+ libdricore9.2.1.so.1 -> libdricore9.2.1.so.1.0.0
+ libQtOpenGL.so.4 -> libQtOpenGL.so.4.8.1
+ libhunspell-1.3.so.0 -> libhunspell-1.3.so.0.0.0
+ libcupsppdc.so.1 -> libcupsppdc.so.1
+ libkdb5.so.6 -> libkdb5.so.6.0
+ libpixman-1.so.0 -> libpixman-1.so.0.30.2
+ libpolkit-backend-1.so.0 -> libpolkit-backend-1.so.0.0.0
+ libibus-1.0.so.0 -> libibus-1.0.so.0.401.0
+ libxcb-dri2.so.0 -> libxcb-dri2.so.0.0.0
+ libgstcheck-0.10.so.0 -> libgstcheck-0.10.so.0.30.0
+ libXp.so.6 -> libXp.so.6.2.0
+ libart_lgpl_2.so.2 -> libart_lgpl_2.so.2.3.21
+ libhx509.so.5 -> libhx509.so.5.0.0
+ libform.so.5 -> libform.so.5.9
+ libgstbase-1.0.so.0 -> libgstbase-1.0.so.0.201.0
+ libX11-xcb.so.1 -> libX11-xcb.so.1.0.0
+ libgstaudio-0.10.so.0 -> libgstaudio-0.10.so.0.25.0
+ libjson-glib-1.0.so.0 -> libjson-glib-1.0.so.0.1400.2
+ libspeex.so.1 -> libspeex.so.1.5.0
+ libsvn_fs_util-1.so.1 -> libsvn_fs_util-1.so.1.0.0
+ libpoppler.so.19 -> libpoppler.so.19.0.0
+ libdconf.so.0 -> libdconf.so.0.0.0
+ libavahi-common.so.3 -> libavahi-common.so.3.5.3
+ libyajl.so.1 -> libyajl.so.1.0.12
+ libvorbis.so.0 -> libvorbis.so.0.4.5
+ libavc1394.so.0 -> libavc1394.so.0.3.0
+ libv4l2.so.0 -> libv4l2.so.0
+ libcolord.so.1 -> libcolord.so.1.0.8
+ libcairo.so.2 -> libcairo.so.2.11000.2
+ libGLEW.so.1.6 -> libGLEW.so.1.6.0
+ libgdbm_compat.so.3 -> libgdbm_compat.so.3.0.0
+ libdb-5.1.so -> libdb-5.1.so
+ libXt.so.6 -> libXt.so.6.0.0
+ libwavpack.so.1 -> libwavpack.so.1.1.4
+ libmpfr.so.4 -> libmpfr.so.4.1.0
+ libpangoft2-1.0.so.0 -> libpangoft2-1.0.so.0.3000.0
+ libieee1284.so.3 -> libieee1284.so.3.2.2
+ libfreetype.so.6 -> libfreetype.so.6.8.0
+ libdrm_nouveau.so.2 -> libdrm_nouveau.so.2.0.0
+ libgssapi.so.3 -> libgssapi.so.3.0.0
+ libspeexdsp.so.1 -> libspeexdsp.so.1.5.0
+ libdconf-dbus-1.so.0 -> libdconf-dbus-1.so.0.0.0
+ libgmp.so.10 -> libgmp.so.10.0.2
+ libcaca.so.0 -> libcucul.so.0.99.17
+ libcairomm-1.0.so.1 -> libcairomm-1.0.so.1.4.0
+ libsvn_repos-1.so.1 -> libsvn_repos-1.so.1.0.0
+ libgupnp-igd-1.0.so.4 -> libgupnp-igd-1.0.so.4.1.0
+ libgstvideo-1.0.so.0 -> libgstvideo-1.0.so.0.201.0
+ libXdamage.so.1 -> libXdamage.so.1.1.0
+ libasn1.so.8 -> libasn1.so.8.0.0
+ libsvn_fs_base-1.so.1 -> libsvn_fs_base-1.so.1.0.0
+ libvorbisenc.so.2 -> libvorbisenc.so.2.0.8
+ libgstapp-1.0.so.0 -> libgstapp-1.0.so.0.201.0
+ libvo-amrwbenc.so.0 -> libvo-amrwbenc.so.0.0.2
+ libtalloc.so.2 -> libtalloc.so.2.0.7
+ libshout.so.3 -> libshout.so.3.2.0
+ libnice.so.10 -> libnice.so.10.0.1
+ libbluetooth.so.3 -> libbluetooth.so.3.11.5
+ libgrail.so.5 -> libgrail.so.5.0.0
+ libgutenprint.so.3 -> libgutenprint.so.3.0.0
+ libmenuw.so.5 -> libmenuw.so.5.9
+ libpanelw.so.5 -> libpanelw.so.5.9
+ libkrb5.so.26 -> libkrb5.so.26.0.0
+ libgdu-gtk.so.0 -> libgdu-gtk.so.0.0.0
+ libgdbm.so.3 -> libgdbm.so.3.0.0
+ libgnutls-openssl.so.27 -> libgnutls-openssl.so.27.0.0
+ libmenu.so.5 -> libmenu.so.5.9
+ libpangox-1.0.so.0 -> libpangox-1.0.so.0.3000.0
+ libXft.so.2 -> libXft.so.2.2.0
+ libsensors.so.4 -> libsensors.so.4.3.1
+ libgstphotography-0.10.so.0 -> libgstphotography-0.10.so.0.0.0
+ libstartup-notification-1.so.0 -> libstartup-notification-1.so.0.0.0
+ libatk-1.0.so.0 -> libatk-1.0.so.0.20409.1
+ libsvn_auth_gnome_keyring-1.so.1 -> libsvn_auth_gnome_keyring-1.so.1.0.0
+ libquadmath.so.0 -> libquadmath.so.0.0.0
+ libgif.so.4 -> libungif.so.4.1.6
+ libstdc++.so.6 -> libstdc++.so.6.0.16
+ liblzma.so.5 -> liblzma.so.5.0.0
+ libass.so.4 -> libass.so.4.1.0
+ libproxy.so.1 -> libproxy.so.1.0.0
+ libcaca++.so.0 -> libcucul++.so.0.99.17
+ libglade-2.0.so.0 -> libglade-2.0.so.0.0.7
+ libavutil.so.51 -> libavutil.so.51.22.2
+ libxslt.so.1 -> libxslt.so.1.1.26
+ libva.so.1 -> libva.so.1.3200.0
+ libsmime3.so -> libsmime3.so
+ libdv.so.4 -> libdv.so.4.0.3
+ libavahi-client.so.3 -> libavahi-client.so.3.2.9
+ libsvn_fs_fs-1.so.1 -> libsvn_fs_fs-1.so.1.0.0
+ libgiomm-2.4.so.1 -> libgiomm-2.4.so.1.3.0
+ libgstrtp-1.0.so.0 -> libgstrtp-1.0.so.0.201.0
+ libgnutls.so.26 -> libgnutls.so.26.21.8
+ libQtXmlPatterns.so.4 -> libQtXmlPatterns.so.4.8.1
+ libao.so.4 -> libao.so.4.0.0
+ libpulsecommon-1.1.so -> libpulsecommon-1.1.so
+ libQtCLucene.so.4 -> libQtCLucene.so.4.8.1
+ libgstbase-0.10.so.0 -> libgstbase-0.10.so.0.30.0
+ libsvn_auth_kwallet-1.so.1 -> libsvn_auth_kwallet-1.so.1.0.0
+ libjpeg.so.8 -> libjpeg.so.8.0.2
+ libsamplerate.so.0 -> libsamplerate.so.0.1.8
+ libcurl.so.4 -> libcurl.so.4.2.0
+ libpipeline.so.1 -> libpipeline.so.1.2.1
+ libglamor_ltss.so.0 -> libglamor_ltss.so.0.0.0
+ libpciaccess.so.0 -> libpciaccess.so.0.11.0
+ libnssutil3.so -> libnssutil3.so
+ libgstriff-0.10.so.0 -> libgstriff-0.10.so.0.25.0
+ libXcursor.so.1 -> libXcursor.so.1.0.2
+ libformw.so.5 -> libformw.so.5.9
+ libjson.so.0 -> libjson.so.0.0.1
+ libgconf-2.so.4 -> libgconf-2.so.4.1.5
+ libkrb5support.so.0 -> libkrb5support.so.0.1
+ libwmf-0.2.so.7 -> libwmf-0.2.so.7.1.0
+ libdiscid.so.0 -> libdiscid.so.0.2.1
+ libjacknet.so.0 -> libjacknet.so.0.1.0
+ libgstbasecamerabinsrc-0.10.so.0 -> libgstbasecamerabinsrc-0.10.so.0.0.0
+ libgee.so.2 -> libgee.so.2.0.0
+ libavahi-core.so.7 -> libavahi-core.so.7.0.2
+ liblcms.so.1 -> liblcms.so.1.0.19
+ liblockfile.so.1 -> liblockfile.so.1.0
+ libdb-4.8.so -> libdb-4.8.so
+ libxcb-glx.so.0 -> libxcb-glx.so.0.0.0
+ libtiffxx.so.0 -> libtiffxx.so.0.0.8
+ libasyncns.so.0 -> libasyncns.so.0.3.1
+ libcdda_interface.so.0 -> libcdda_interface.so.0.10.2
+ libgstrtsp-0.10.so.0 -> libgstrtsp-0.10.so.0.25.0
+ libtheora.so.0 -> libtheora.so.0.3.10
+ libvo-aacenc.so.0 -> libvo-aacenc.so.0.0.2
+ libORBit-2.so.0 -> libORBit-2.so.0.1.0
+ libv4lconvert.so.0 -> libv4lconvert.so.0
+ libXv.so.1 -> libXv.so.1.0.0
+ libgnomeui-2.so.0 -> libgnomeui-2.so.0.2400.5
+ libsvn_wc-1.so.1 -> libsvn_wc-1.so.1.0.0
+ libgstphotography-1.0.so.0 -> libgstphotography-1.0.so.0.7.0
+ libasound.so.2 -> libasound.so.2.0.0
+ libsvn_ra_neon-1.so.1 -> libsvn_ra_neon-1.so.1.0.0
+ libcroco-0.6.so.3 -> libcroco-0.6.so.3.0.1
+ libopus.so.0 -> libopus.so.0.5.0
+ libXext.so.6 -> libXext.so.6.4.0
+ libXrandr.so.2 -> libXrandr.so.2.2.0
+ libQtSql.so.4 -> libQtSql.so.4.8.1
+ libsonic.so.0 -> libsonic.so.0.1.17
+ libapt-inst.so.1.4 -> libapt-inst.so.1.4.0
+ libgstvideo-0.10.so.0 -> libgstvideo-0.10.so.0.25.0
+ libpanel.so.5 -> libpanel.so.5.9
+ libSoundTouch.so.0 -> libSoundTouch.so.0.0.0
+ libgd.so.2 -> libgd.so.2.0.0
+ libXxf86vm.so.1 -> libXxf86vm.so.1.0.0
+ libpulsedsp.so -> libpulsedsp.so
+ libGLU.so.1 -> libGLU.so.1.3.08004
+ libmpc.so.2 -> libmpc.so.2.0.0
+ libgdk_pixbuf-2.0.so.0 -> libgdk_pixbuf-2.0.so.0.2600.1
+ libroken.so.18 -> libroken.so.18.1.0
+ libtasn1.so.3 -> libtasn1.so.3.1.12
+ libsvn_delta-1.so.1 -> libsvn_delta-1.so.1.0.0
+ libgstrtp-0.10.so.0 -> libgstrtp-0.10.so.0.25.0
+ libgstnetbuffer-0.10.so.0 -> libgstnetbuffer-0.10.so.0.25.0
+ libgstfft-1.0.so.0 -> libgstfft-1.0.so.0.201.0
+ libORBit-imodule-2.so.0 -> libORBit-imodule-2.so.0.0.0
+ libkadm5srv_mit.so.8 -> libkadm5srv_mit.so.8.0
+ libgssapi_krb5.so.2 -> libgssapi_krb5.so.2.2
+ libdrm_radeon.so.1 -> libdrm_radeon.so.1.0.1
+ libgoa-backend-1.0.so.0 -> libgoa-backend-1.0.so.0.0.0
+ libXmuu.so.1 -> libXmuu.so.1.0.0
+ libpango-1.0.so.0 -> libpango-1.0.so.0.3000.0
+ libsigc-2.0.so.0 -> libsigc-2.0.so.0.0.0
+ libsoup-2.4.so.1 -> libsoup-2.4.so.1.5.0
+ libssh_threads.so.4 -> libssh_threads.so.4.2.2
+ libkadm5clnt_mit.so.8 -> libkadm5clnt_mit.so.8.0
+ libgstcodecparsers-1.0.so.0 -> libgstcodecparsers-1.0.so.0.5.0
+ libgstrtsp-1.0.so.0 -> libgstrtsp-1.0.so.0.201.0
+ libgtk-x11-2.0.so.0 -> libgtk-x11-2.0.so.0.2400.10
+ libespeak.so.1 -> libespeak.so.1.1.46
+ libjack.so.0 -> libjack.so.0.1.0
+ libxcb-shm.so.0 -> libxcb-shm.so.0.0.0
+ libQtSvg.so.4 -> libQtSvg.so.4.8.1
+ libglibmm_generate_extra_defs-2.4.so.1 -> libglibmm_generate_extra_defs-2.4.so.1.3.0
+ libcurl-nss.so.4 -> libcurl-nss.so.4.2.0
+ libtelepathy-logger.so.2 -> libtelepathy-logger.so.2.2.1
+ libX11.so.6 -> libX11.so.6.3.0
+ libexpatw.so.1 -> libexpatw.so.1.5.2
+ libxml2.so.2 -> libxml2.so.2.7.8
+ libsane.so.1 -> libsane.so.1.0.22
+ libgeis.so.1 -> libgeis.so.1.3.0
+ libgnome-keyring.so.0 -> libgnome-keyring.so.0.2.0
+ libgdk-3.so.0 -> libgdk-3.so.0.400.2
+ libgstreamer-1.0.so.0 -> libgstreamer-1.0.so.0.201.0
+ libgstcheck-1.0.so.0 -> libgstcheck-1.0.so.0.201.0
+ libheimbase.so.1 -> libheimbase.so.1.0.0
+ libsasl2.so.2 -> libsasl2.so.2.0.25
+ liblouis.so.2 -> liblouis.so.2.2.3
+ libgnomevfs-2.so.0 -> libgnomevfs-2.so.0.2400.4
+ libgstdataprotocol-0.10.so.0 -> libgstdataprotocol-0.10.so.0.30.0
+ libvorbisfile.so.3 -> libvorbisfile.so.3.3.4
+/usr/local/lib:
+ libefreet.so.1 -> libefreet.so.1.9.3
+ libecore_ipc.so.1 -> libecore_ipc.so.1.9.3
+ libefreet_trash.so.1 -> libefreet_trash.so.1.9.3
+ libecore_evas.so.1 -> libecore_evas.so.1.9.3
+ libecore.so.1 -> libecore.so.1.9.3
+ libmosquittopp.so.1 -> libmosquittopp.so.1
+ libeina.so.1 -> libeina.so.1.9.3
+ libeet.so.1 -> libeet.so.1.9.3
+ libecore_imf_evas.so.1 -> libecore_imf_evas.so.1.9.3
+ libembryo.so.1 -> libembryo.so.1.9.3
+ libecore_avahi.so.1 -> libecore_avahi.so.1.9.3
+ libeldbus.so.1 -> libeldbus.so.1.9.3
+ libethumb.so.1 -> libethumb.so.1.9.3
+ libemotion.so.1 -> libemotion.so.1.9.3
+ libecore_con.so.1 -> libecore_con.so.1.9.3
+ libecore_imf.so.1 -> libecore_imf.so.1.9.3
+ libeeze.so.1 -> libeeze.so.1.9.3
+ libecore_input.so.1 -> libecore_input.so.1.9.3
+ libedje.so.1 -> libedje.so.1.9.3
+ libeo.so.1 -> libeo.so.1.9.3
+ libethumb_client.so.1 -> libethumb_client.so.1.9.3
+ libecore_file.so.1 -> libecore_file.so.1.9.3
+ libeio.so.1 -> libeio.so.1.9.3
+ libmosquitto.so.1 -> libmosquitto.so.1
+ libelementary.so.1 -> libelementary.so.1.9.3
+ libecore_audio.so.1 -> libecore_audio.so.1.9.3
+ libevas.so.1 -> libevas.so.1.9.3
+ libecore_input_evas.so.1 -> libecore_input_evas.so.1.9.3
+ libefreet_mime.so.1 -> libefreet_mime.so.1.9.3
+ libecore_x.so.1 -> libecore_x.so.1.9.3
+/lib:
+ libnl-genl-3.so.200 -> libnl-genl-3.so.200.3.0
+ libnss_mdns6_minimal.so.2 -> libnss_mdns6_minimal.so.2
+ libip6tc.so.0 -> libip6tc.so.0.0.0
+ libply.so.2 -> libply.so.2.0.0
+ libnss_mdns6.so.2 -> libnss_mdns6.so.2
+ libipq_pic.so.0 -> libipq_pic.so.0.0.0
+ liblvm2app.so.2.2 -> liblvm2app.so.2.2
+ libdevmapper.so.1.02.1 -> libdevmapper.so.1.02.1
+ libcryptsetup.so.4 -> libcryptsetup.so.4.0.0
+ libnss_mdns.so.2 -> libnss_mdns.so.2
+ libnss_mdns_minimal.so.2 -> libnss_mdns_minimal.so.2
+ libfuse.so.2 -> libfuse.so.2.8.6
+ libiw.so.30 -> libiw.so.30
+ libdevmapper-event.so.1.02.1 -> libdevmapper-event.so.1.02.1
+ libply-splash-graphics.so.2 -> libply-splash-graphics.so.2.0.0
+ libply-splash-core.so.2 -> libply-splash-core.so.2.0.0
+ libsysfs.so.2 -> libsysfs.so.2.0.1
+ libply-boot-client.so.2 -> libply-boot-client.so.2.0.0
+ libnss_mdns4.so.2 -> libnss_mdns4.so.2
+ libnss_mdns4_minimal.so.2 -> libnss_mdns4_minimal.so.2
+ libproc-3.2.8.so -> libproc-3.2.8.so
+ libbrlapi.so.0.5 -> libbrlapi.so.0.5.6
+ libnewt.so.0.52 -> libnewt.so.0.52.11
+ libipq.so.0 -> libipq.so.0.0.0
+ libiptc.so.0 -> libiptc.so.0.0.0
+ libulockmgr.so.1 -> libulockmgr.so.1.0.1
+ libnl-3.so.200 -> libnl-3.so.200.3.0
+ libxtables.so.7 -> libxtables.so.7.0.0
+ libip4tc.so.0 -> libip4tc.so.0.0.0
+ libx86.so.1 -> libx86.so.1
+/usr/lib:
+ liba52-0.7.4.so -> liba52-0.7.4.so
+ libvncserver.so.0 -> libvncserver.so.0.0.0
+ libspandsp.so.2 -> libspandsp.so.2.0.0
+ libflite_usenglish.so.1 -> libflite_usenglish.so.1.4
+ libido3-0.1.so.0 -> libido3-0.1.so.0.0.0
+ libicui18n.so.48 -> libicui18n.so.48.1.1
+ libXvMC.so.1 -> libXvMC.so.1.0.0
+ libdmapsharing-3.0.so.2 -> libdmapsharing-3.0.so.2.9.14
+ libgmime-2.6.so.0 -> libgmime-2.6.so.0.600.7
+ libefreet_trash.so.1 -> libefreet_trash.so.1.0.0
+ libQtGConf.so.1 -> libQtGConf.so.1.0.0
+ libbfd-2.22-system.so -> libbfd-2.22-system.so
+ libgs.so.9 -> libgs.so.9.05
+ libedbus.so.1 -> libedbus.so.1.0.0
+ libperl.so.5.14 -> libperl.so.5.14.2
+ libgdkmm-3.0.so.1 -> libgdkmm-3.0.so.1.1.0
+ libeconnman.so.1 -> libeconnman.so.1.0.0
+ libxklavier.so.16 -> libxklavier.so.16.2.0
+ libnux-2.0.so.0 -> libnux-2.0.so.0.1401.0
+ libvlccore.so.5 -> libvlccore.so.5.1.1
+ libopcodes-2.22-system.so -> libopcodes-2.22-system.so
+ libaccountsservice.so.0 -> libaccountsservice.so.0.0.0
+ libnm-util.so.2 -> libnm-util.so.2.3.0
+ libjavascriptcoregtk-1.0.so.0 -> libjavascriptcoregtk-1.0.so.0.13.4
+ libpulsecore-1.1.so -> libpulsecore-1.1.so
+ libflite_cmu_us_slt.so.1 -> libflite_cmu_us_slt.so.1.4
+ libkeybinder.so.0 -> libkeybinder.so.0.0.1
+ libguile-srfi-srfi-1-v-3.so.3 -> libguile-srfi-srfi-1-v-3.so.3.0.2
+ libindicator-messages-status-provider.so.1 -> libindicator-messages-status-provider.so.1.0.0
+ libopencore-amrwb.so.0 -> libopencore-amrwb.so.0.0.2
+ libfolks.so.25 -> libfolks.so.25.7.0
+ libisccc.so.80 -> libisccc.so.80.0.0
+ libutempter.so.0 -> libutempter.so.1.1.5
+ libijs-0.35.so -> libijs-0.35.so
+ libefreet.so.1 -> libefreet.so.1.0.0
+ libflite_cmu_us_awb.so.1 -> libflite_cmu_us_awb.so.1.4
+ libwpg-0.2.so.2 -> libwpg-0.2.so.2.0.1
+ libvte2_90.so.9 -> libvte2_90.so.9.3200.1
+ libvncclient.so.0 -> libvncclient.so.0.0.0
+ libtcl8.5.so.0 -> libtcl8.5.so.0
+ libgnome-control-center.so.1 -> libgnome-control-center.so.1.0.0
+ libpyglib-gi-2.0-python2.7.so.0 -> libpyglib-gi-2.0-python2.7.so.0.0.0
+ libisc.so.83 -> libisc.so.83.0.1
+ libenotify.so.1 -> libenotify.so.1.0.0
+ libwps-0.2.so.2 -> libwps-0.2.so.2.0.4
+ libschroedinger-1.0.so.0 -> libschroedinger-1.0.so.0.11.0
+ libgtkmm-3.0.so.1 -> libgtkmm-3.0.so.1.1.0
+ librest-0.7.so.0 -> librest-0.7.so.0.0.0
+ libicalss.so.0 -> libicalss.so.0.48.0
+ libgrip.so.0 -> libgrip.so.0.305.0
+ libtimezonemap.so.1 -> libtimezonemap.so.1.0.0
+ libecore_evas.so.1 -> libecore_evas.so.1.0.0
+ libvte.so.9 -> libvte.so.9.2800.2
+ libmetacity-private.so.0 -> libmetacity-private.so.0.0.0
+ libXxf86dga.so.1 -> libXxf86dga.so.1.0.0
+ libgck-1.so.0 -> libgck-1.so.0.0.0
+ libicutu.so.48 -> libicutu.so.48.1.1
+ libedje.so.1 -> libedje.so.1.0.0
+ libgwibber-gtk.so.2 -> libgwibber-gtk.so.2.0.0
+ libpurple-client.so.0 -> libpurple-client.so.0.10.3
+ libhpip.so.0 -> libhpip.so.0.0.1
+ libwnck-1.so.22 -> libwnck-1.so.22.3.31
+ libfreerdp-core.so.1.0 -> libfreerdp-core.so.1.0.1
+ libmhash.so.2 -> libmhash.so.2.0.1
+ libindicator3.so.7 -> libindicator3.so.7.0.0
+ libfreerdp-codec.so.1.0 -> libfreerdp-codec.so.1.0.1
+ libflite.so.1 -> libflite.so.1.4
+ libgweather-3.so.0 -> libgweather-3.so.0.0.6
+ libpeas-1.0.so.0 -> libpeas-1.0.so.0.200.0
+ libbind9.so.80 -> libbind9.so.80.0.3
+ libgnomekbd.so.7 -> libgnomekbd.so.7.0.0
+ libcrypto.so.1.0.0 -> libcrypto.so.1.0.0
+ libwnck-3.so.0 -> libwnck-3.so.0.2.0
+ libeina.so.1 -> libeina.so.1.0.0
+ libebook-1.2.so.12 -> libebook-1.2.so.12.3.1
+ libFS.so.6 -> libFS.so.6.0.0
+ libnetsnmpagent.so.15 -> libnetsnmpagent.so.15.1.2
+ libdaemon.so.0 -> libdaemon.so.0.5.0
+ libfribidi.so.0 -> libfribidi.so.0.3.1
+ libeet.so.1 -> libeet.so.1.4.0
+ libunity-misc.so.4 -> libunity-misc.so.4.1.0
+ libbulletml.so.0d2 -> libbulletml.so.0d2.0
+ libebluez.so.1 -> libebluez.so.1.0.0
+ libindicate.so.5 -> libindicate.so.5.0.7
+ libicule.so.48 -> libicule.so.48.1.1
+ libmtdev.so.1 -> libmtdev.so.1.0.0
+ libgnome-media-profiles-3.0.so.0 -> libgnome-media-profiles-3.0.so.0.0.0
+ libnetsnmpmibs.so.15 -> libnetsnmpmibs.so.15.1.2
+ liboverlay-scrollbar-0.2.so.0 -> liboverlay-scrollbar-0.2.so.0.0.16
+ libecore_imf_evas.so.1 -> libecore_imf_evas.so.1.0.0
+ libpaper.so.1 -> libpaper.so.1.1.2
+ libjte.so.1 -> libjte.so.1.0.0
+ libdotconf-1.0.so.0 -> libdotconf-1.0.so.0.10.4
+ libicutest.so.48 -> libicutest.so.48.1.1
+ libmimic.so.0 -> libmimic.so.0.0.1
+ libeukit.so.1 -> libeukit.so.1.0.0
+ libtotem-plparser.so.17 -> libtotem-plparser.so.17.0.3
+ libfolks-telepathy.so.25 -> libfolks-telepathy.so.25.7.0
+ libgtop-2.0.so.7 -> libgtop-2.0.so.7.2.0
+ libtwolame.so.0 -> libtwolame.so.0.0.0
+ libgwibber.so.2 -> libgwibber.so.2.0.0
+ libfreerdp-utils.so.1.0 -> libfreerdp-utils.so.1.0.1
+ libgnome-menu.so.2 -> libgnome-menu.so.2.4.13
+ libecore_file.so.1 -> libecore_file.so.1.0.0
+ libedataserver-1.2.so.15 -> libedataserver-1.2.so.15.0.0
+ librasqal.so.3 -> librasqal.so.3.0.0
+ libgexiv2.so.1 -> libgexiv2.so.1.0.0
+ libgettextlib-0.18.1.so -> libgettextlib.so
+ libmythes-1.2.so.0 -> libmythes-1.2.so.0.0.0
+ libprotoc.so.7 -> libprotoc.so.7.0.0
+ libfreerdp-rail.so.1.0 -> libfreerdp-rail.so.1.0.1
+ libsgutils2.so.2 -> libsgutils2.so.2.0.0
+ libaprutil-1.so.0 -> libaprutil-1.so.0.3.12
+ libraptor2.so.0 -> libraptor2.so.0.0.0
+ libgirepository-1.0.so.1 -> libgirepository-1.0.so.1.0.0
+ libunity-core-5.0.so.5 -> libunity-core-5.0.so.5.0.0
+ libflite_cmu_us_kal16.so.1 -> libflite_cmu_us_kal16.so.1.4
+ libecore_con.so.1 -> libecore_con.so.1.0.0
+ libecore_input_evas.so.1 -> libecore_input_evas.so.1.0.0
+ libjbig2dec.so.0 -> libjbig2dec.so.0.0.0
+ libnetsnmp.so.15 -> libnetsnmp.so.15.1.2
+ libzbar.so.0 -> libzbar.so.0.2.0
+ libXRes.so.1 -> libXRes.so.1.0.0
+ libcdio_paranoia.so.1 -> libcdio_paranoia.so.1.0.0
+ libedata-book-1.2.so.11 -> libedata-book-1.2.so.11.0.0
+ libnetsnmphelpers.so.15 -> libnetsnmphelpers.so.15.1.2
+ libgksu2.so.0 -> libgksu2.so.0.0.2
+ libQtBamf.so.1 -> libQtBamf.so.1.0.0
+ libnautilus-extension.so.1 -> libnautilus-extension.so.1.4.0
+ libebackend-1.2.so.1 -> libebackend-1.2.so.1.0.0
+ libI810XvMC.so.1 -> libI810XvMC.so.1.0.0
+ libembryo.so.1 -> libembryo.so.1.0.0
+ libmission-control-plugins.so.0 -> libmission-control-plugins.so.0.3.1
+ libguilereadline-v-17.so.17 -> libguilereadline-v-17.so.17.0.3
+ libsox.so.1 -> libsox.so.1.0.0
+ libcdio.so.13 -> libcdio.so.13.0.0
+ libsqlite.so.0 -> libsqlite.so.0.8.6
+ libecore_imf.so.1 -> libecore_imf.so.1.0.0
+ libevdocument3.so.4 -> libevdocument3.so.4.0.0
+ libehal.so.1 -> libehal.so.1.0.0
+ libt1.so.5 -> libt1.so.5.1.2
+ libdconf-qt.so.0 -> libdconf-qt.so.0.0.0
+ libboost_wserialization.so.1.46.1 -> libboost_wserialization.so.1.46.1
+ libaspell.so.15 -> libaspell.so.15.2.0
+ libusbmuxd.so.1 -> libusbmuxd.so.1.0.7
+ libevent-2.0.so.5 -> libevent-2.0.so.5.1.4
+ libdee-1.0.so.4 -> libdee-1.0.so.4.1.1
+ libimobiledevice.so.2 -> libimobiledevice.so.2.0.1
+ libtotem.so.0 -> libtotem.so.0.0.0
+ libopencore-amrnb.so.0 -> libopencore-amrnb.so.0.0.2
+ libgtkspell-3.so.0 -> libgtkspell-3.so.0.0.0
+ libsyncdaemon-1.0.so.1 -> libsyncdaemon-1.0.so.1.0.0
+ libid3tag.so.0 -> libid3tag.so.0.3.0
+ libxcb-keysyms.so.1 -> libxcb-keysyms.so.1.0.0
+ liblwres.so.80 -> liblwres.so.80.0.1
+ libgnome-menu-3.so.0 -> libgnome-menu-3.so.0.0.1
+ libgpgme-pthread.so.11 -> libgpgme-pthread.so.11.7.0
+ libXvMCW.so.1 -> libXvMCW.so.1.0.0
+ libenchant.so.1 -> libenchant.so.1.6.0
+ libgupnp-1.0.so.4 -> libgupnp-1.0.so.4.0.0
+ liblightdm-gobject-1.so.0 -> liblightdm-gobject-1.so.0.0.0
+ libasprintf.so.0 -> libasprintf.so.0.0.0
+ libprotobuf.so.7 -> libprotobuf.so.7.0.0
+ libwebkitgtk-1.0.so.0 -> libwebkitgtk-1.0.so.0.13.4
+ libmpeg2.so.0 -> libmpeg2.so.0.0.0
+ libssl.so.1.0.0 -> libssl.so.1.0.0
+ libfreerdp-gdi.so.1.0 -> libfreerdp-gdi.so.1.0.1
+ libgpgme.so.11 -> libgpgme.so.11.7.0
+ libplist.so.1 -> libplist.so.1.1.8
+ libmtp.so.9 -> libmtp.so.9.0.3
+ libecore_x.so.1 -> libecore_x.so.1.0.0
+ libcap-ng.so.0 -> libcap-ng.so.0.0.0
+ libnux-core-2.0.so.0 -> libnux-core-2.0.so.0.1401.0
+ libpyglib-2.0-python2.7.so.0 -> libpyglib-2.0-python2.7.so.0.0.0
+ libsidplay.so.1 -> libsidplay.so.1.0.3
+ libXfont.so.1 -> libXfont.so.1.4.1
+ libical.so.0 -> libical.so.0.48.0
+ libdvdnav.so.4 -> libdvdnav.so.4.2.0
+ libfreerdp-cache.so.1.0 -> libfreerdp-cache.so.1.0.1
+ libexttextcat.so.0 -> libexttextcat.so.0.0.0
+ libboost_serialization.so.1.46.1 -> libboost_serialization.so.1.46.1
+ libmagic.so.1 -> libmagic.so.1.0.0
+ libcamel-provider-1.2.so.29 -> libcamel-provider-1.2.so.29.0.0
+ libedata-cal-1.2.so.13 -> libedata-cal-1.2.so.13.0.0
+ libxcb-image.so.0 -> libxcb-image.so.0.0.0
+ librpmbuild.so.2 -> librpmbuild.so.2.0.1
+ libzeitgeist-1.0.so.1 -> libzeitgeist-1.0.so.1.1.4
+ libmpeg2convert.so.0 -> libmpeg2convert.so.0.0.0
+ libecore.so.1 -> libecore.so.1.0.0
+ libwpd-0.9.so.9 -> libwpd-0.9.so.9.0.4
+ libmms.so.0 -> libmms.so.0.0.2
+ libstlport_gcc.so.4.6 -> libstlport_gcc.so.4.6
+ libopencc.so.1 -> libopencc.so.1.0.0
+ libck-connector.so.0 -> libck-connector.so.0.0.0
+ libcdio_cdda.so.1 -> libcdio_cdda.so.1.0.0
+ librdf.so.0 -> librdf.so.0.0.0
+ libtelepathy-glib.so.0 -> libtelepathy-glib.so.0.70.2
+ libGeoIPUpdate.so.0 -> libGeoIPUpdate.so.0.0.0
+ libraw_r.so.5 -> libraw_r.so.5.0.0
+ libwebkitgtk-3.0.so.0 -> libwebkitgtk-3.0.so.0.13.4
+ libbrasero-utils3.so.1 -> libbrasero-utils3.so.1.2.3
+ libgcr-3.so.1 -> libgcr-3.so.1.0.0
+ libdca.so.0 -> libdca.so.0.0.0
+ libcompizconfig.so.0 -> libcompizconfig.so.0.0.0
+ librpmsign.so.0 -> librpmsign.so.0.0.1
+ libburn.so.4 -> libburn.so.4.71.0
+ libzephyr.so.4 -> libzephyr.so.4.0.0
+ libcamel-1.2.so.29 -> libcamel-1.2.so.29.0.0
+ libmodplug.so.1 -> libmodplug.so.1.0.0
+ liblrdf.so.0 -> liblrdf.so.0.0.0
+ libflite_cmu_us_kal.so.1 -> libflite_cmu_us_kal.so.1.4
+ libjavascriptcoregtk-3.0.so.0 -> libjavascriptcoregtk-3.0.so.0.13.4
+ libiculx.so.48 -> libiculx.so.48.1.1
+ libgdata.so.13 -> libgdata.so.13.2.0
+ libedataserverui-3.0.so.1 -> libedataserverui-3.0.so.1.0.0
+ libecore_ipc.so.1 -> libecore_ipc.so.1.0.0
+ libindicate-gtk.so.3 -> libindicate-gtk.so.3.0.3
+ libexiv2.so.11 -> libexiv2.so.11.0.0
+ libyelp.so.0 -> libyelp.so.0.0.0
+ libxapian.so.22 -> libxapian.so.22.4.2
+ libnm-glib.so.4 -> libnm-glib.so.4.3.0
+ libflite_cmu_time_awb.so.1 -> libflite_cmu_time_awb.so.1.4
+ libhpmud.so.0 -> libhpmud.so.0.0.6
+ librarian.so.0 -> librarian.so.0.0.0
+ libnetsnmptrapd.so.15 -> libnetsnmptrapd.so.15.1.2
+ libGeoIP.so.1 -> libGeoIP.so.1.4.8
+ libgettextsrc-0.18.1.so -> libgettextsrc.so
+ libpackagekit-glib2.so.14 -> libpackagekit-glib2.so.14.0.11
+ libecore_fb.so.1 -> libecore_fb.so.1.0.0
+ libgnome-bluetooth.so.8 -> libgnome-bluetooth.so.8.0.0
+ libminiupnpc.so.8 -> libminiupnpc.so.8
+ libguile-srfi-srfi-13-14-v-3.so.3 -> libguile-srfi-srfi-13-14-v-3.so.3.0.1
+ libraw.so.5 -> libraw.so.5.0.0
+ librhythmbox-core.so.5 -> librhythmbox-core.so.5.0.0
+ libxdelta.so.2 -> libxdelta.so.2.0.0
+ libgeoclue.so.0 -> libgeoclue.so.0.0.0
+ libfreerdp-channels.so.1.0 -> libfreerdp-channels.so.1.0.1
+ libgsm.so.1 -> libgsm.so.1.0.12
+ libgme.so.0 -> libgme.so.0.5.3
+ librpmio.so.2 -> librpmio.so.2.0.1
+ libnetfilter_conntrack.so.3 -> libnetfilter_conntrack.so.3.1.3
+ libappindicator3.so.1 -> libappindicator3.so.1.0.0
+ libicudata.so.48 -> libicudata.so.48.1.1
+ libnl-route-3.so.200 -> libnl-route-3.so.200.3.0
+ libicuuc.so.48 -> libicuuc.so.48.1.1
+ libIntelXvMC.so.1 -> libIntelXvMC.so.1.0.0
+ libraptor.so.1 -> libraptor.so.1.2.0
+ libgedit-private.so.0 -> libgedit-private.so.0.0.0
+ libindicator.so.7 -> libindicator.so.7.0.0
+ libsnmp.so.15 -> libsnmp.so.15.1.2
+ libguile.so.17 -> libguile.so.17.4.0
+ libcompiz_core.so.ABI-20120305 -> libcompiz_core.so.0.9.7.12
+ libunique-3.0.so.0 -> libunique-3.0.so.0.0.2
+ libfaad.so.2 -> libfaad.so.2.0.0
+ libneon-gnutls.so.27 -> libneon-gnutls.so.27.2.6
+ libpython2.7.so.1.0 -> libpython2.7.so.1.0
+ libspeechd.so.2 -> libspeechd.so.2.3.0
+ libecal-1.2.so.10 -> libecal-1.2.so.10.2.2
+ libwpd-stream-0.9.so.9 -> libwpd-stream-0.9.so.9.0.4
+ liboverlay-scrollbar3-0.2.so.0 -> liboverlay-scrollbar3-0.2.so.0.0.16
+ libunity.so.9 -> libunity.so.9.0.2
+ libhyphen.so.0 -> libhyphen.so.0.2.1
+ libbrasero-media3.so.1 -> libbrasero-media3.so.1.2.3
+ libelementary-ver-pre-svn-09.so.0 -> libelementary.so
+ libkpathsea.so.5 -> libkpathsea.so.5.0.0
+ libvlc.so.5 -> libvlc.so.5.3.2
+ libflite_cmulex.so.1 -> libflite_cmulex.so.1.4
+ libopenobex.so.1 -> libopenobex.so.1.5.0
+ libdns.so.81 -> libdns.so.81.3.1
+ libfreerdp-kbd.so.1.0 -> libfreerdp-kbd.so.1.0.1
+ libpspell.so.15 -> libpspell.so.15.2.0
+ libfolks-eds.so.25 -> libfolks-eds.so.25.7.0
+ libisofs.so.6 -> libisofs.so.6.54.0
+ libecore_input.so.1 -> libecore_input.so.1.0.0
+ libpurple.so.0 -> libpurple.so.0.10.3
+ librsync.so.1 -> librsync.so.1.0.2
+ librpm.so.2 -> librpm.so.2.0.1
+ libmeanwhile.so.1 -> libmeanwhile.so.1.0.2
+ libevas.so.1 -> libevas.so.1.0.0
+ libapr-1.so.0 -> libapr-1.so.0.4.6
+ liblirc_client.so.0 -> liblirc_client.so.0.2.1
+ libexpect.so.5.45 -> libexpect.so.5.45
+ libgucharmap_2_90.so.7 -> libgucharmap_2_90.so.7.0.0
+ libicuio.so.48 -> libicuio.so.48.1.1
+ libgpod.so.4 -> libgpod.so.4.3.2
+ libfontenc.so.1 -> libfontenc.so.1.0.0
+ libchromeXvMC.so.1 -> libchromeXvMC.so.1.0.0
+ libgssdp-1.0.so.3 -> libgssdp-1.0.so.3.0.0
+ libguile-srfi-srfi-4-v-3.so.3 -> libguile-srfi-srfi-4-v-3.so.3.0.1
+ libflite_cmu_us_rms.so.1 -> libflite_cmu_us_rms.so.1.4
+ liblaunchpad-integration-3.0.so.1 -> liblaunchpad-integration-3.0.so.1.0.0
+ libdjvulibre.so.21 -> libdjvulibre.so.21.3.0
+ libdecoration.so.0 -> libdecoration.so.0.0.0
+ libnm-gtk.so.0 -> libnm-gtk.so.0.0.0
+ libcmis-0.2.so.0 -> libcmis-0.2.so.0.0.0
+ libgpgme-pth.so.11 -> libgpgme-pth.so.11.7.0
+ libguile-srfi-srfi-60-v-2.so.2 -> libguile-srfi-srfi-60-v-2.so.2.0.2
+ libgnome-desktop-3.so.2 -> libgnome-desktop-3.so.2.1.4
+ libnfnetlink.so.0 -> libnfnetlink.so.0.2.0
+ libpeas-gtk-1.0.so.0 -> libpeas-gtk-1.0.so.0.200.0
+ libevview3.so.3 -> libevview3.so.3.0.0
+ libappindicator.so.1 -> libappindicator.so.1.0.0
+ libisccfg.so.82 -> libisccfg.so.82.0.0
+ libt1x.so.5 -> libt1x.so.5.1.2
+ libtotem-plparser-mini.so.17 -> libtotem-plparser-mini.so.17.0.3
+ libgnomekbdui.so.7 -> libgnomekbdui.so.7.0.0
+ libspectre.so.1 -> libspectre.so.1.1.6
+ libnm-glib-vpn.so.1 -> libnm-glib-vpn.so.1.1.0
+ libdvdread.so.4 -> libdvdread.so.4.2.0
+ libQtDee.so.2 -> libQtDee.so.2.0.0
+ libnux-graphics-2.0.so.0 -> libnux-graphics-2.0.so.0.1401.0
+ libslp.so.1 -> libslp.so.1.0.1
+ libdvdnavmini.so.4 -> libdvdnavmini.so.4.2.0
+ libnux-image-2.0.so.0 -> libnux-image-2.0.so.0.1401.0
+ libunity-2d-private.so.0 -> libunity-2d-private.so.0.0.0
+ libtelepathy-farstream.so.2 -> libtelepathy-farstream.so.2.0.1
+ libedsio.so.0 -> libedsio.so.0.0.0
+ libmusicbrainz3.so.6 -> libmusicbrainz3.so.6.2.0
+ libefreet_mime.so.1 -> libefreet_mime.so.1.0.0
+ libenca.so.0 -> libenca.so.0.5.1
+ libpth.so.20 -> libpth.so.20.0.27
+ libchromeXvMCPro.so.1 -> libchromeXvMCPro.so.1.0.0
+ libicalvcal.so.0 -> libicalvcal.so.0.48.0
+ libbrasero-burn3.so.1 -> libbrasero-burn3.so.1.2.3
+ libupower-glib.so.1 -> libupower-glib.so.1.0.1
+/usr/lib/i386-linux-gnu/sse2: (hwcap: 0x0000000004000000)
+ libspeex.so.1 -> libspeex.so.1.5.0
+ libspeexdsp.so.1 -> libspeexdsp.so.1.5.0
+/usr/lib/i386-linux-gnu/i686: (hwcap: 0x0008000000000000)
+/usr/lib/sse2: (hwcap: 0x0000000004000000)
+ libxapian.so.22 -> libxapian.so.22.4.2
+/usr/lib/i386-linux-gnu/i686/sse2: (hwcap: 0x0008000004000000)
+ libx264.so.120 -> libx264.so.120
+/usr/lib/i386-linux-gnu/i686/cmov: (hwcap: 0x0008000000008000)
+ libavcodec.so.53 -> libavcodec.so.53.35.0
+ libavformat.so.53 -> libavformat.so.53.21.1
+ libswscale.so.2 -> libswscale.so.2.1.0
+ libavutil.so.51 -> libavutil.so.51.22.2
--- /dev/null
+#ifndef _DUMMYPTHREAD_H_
+#define _DUMMYPTHREAD_H_
+
+#define pthread_create(A, B, C, D)
+#define pthread_join(A, B)
+#define pthread_cancel(A)
+
+#define pthread_mutex_init(A, B)
+#define pthread_mutex_destroy(A)
+#define pthread_mutex_lock(A)
+#define pthread_mutex_unlock(A)
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2012 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* Mosquitto MQTT Javascript/Websocket client */
+/* Provides complete support for QoS 0.
+ * Will not cause an error on QoS 1/2 packets.
+ */
+
+var CONNECT = 0x10;
+var CONNACK = 0x20;
+var PUBLISH = 0x30;
+var PUBACK = 0x40;
+var PUBREC = 0x50;
+var PUBREL = 0x60;
+var PUBCOMP = 0x70;
+var SUBSCRIBE = 0x80;
+var SUBACK = 0x90;
+var UNSUBSCRIBE = 0xA0;
+var UNSUBACK = 0xB0;
+var PINGREQ = 0xC0;
+var PINGRESP = 0xD0;
+var DISCONNECT = 0xE0;
+
+function AB2S(buffer) {
+ var binary = '';
+ var bytes = new Uint8Array(buffer);
+ var len = bytes.byteLength;
+ for(var i=0; i<len; i++){
+ binary += String.fromCharCode(bytes[i]);
+ }
+ return binary;
+}
+
+function Mosquitto()
+{
+ this.ws = null;
+ this.onconnect = null;
+ this.ondisconnect = null;
+ this.onmessage = null;
+}
+
+Mosquitto.prototype = {
+ mqtt_ping : function()
+ {
+ var buffer = new ArrayBuffer(2);
+ var i8V = new Int8Array(buffer);
+ i8V[0] = PINGREQ;
+ i8V[1] = 0;
+ if(this.ws.readyState == 1){
+ this.ws.send(buffer);
+ }else{
+ this.queue(buffer);
+ }
+ setTimeout(function(_this){_this.mqtt_ping();}, 60000, this);
+ },
+
+ connect : function(url, keepalive){
+
+ this.url = url;
+ this.keepalive = keepalive;
+ this.mid = 1;
+ this.out_queue = new Array();
+
+ this.ws = new WebSocket(url, 'mqttv3.1');
+ this.ws.binaryType = "arraybuffer";
+ this.ws.onopen = this.ws_onopen;
+ this.ws.onclose = this.ws_onclose;
+ this.ws.onmessage = this.ws_onmessage;
+ this.ws.m = this;
+ this.ws.onerror = function(evt){
+ alert(evt.data);
+ }
+ },
+
+ disconnect : function(){
+ if(this.ws.readyState == 1){
+ var buffer = new ArrayBuffer(2);
+ var i8V = new Int8Array(buffer);
+
+ i8V[0] = DISCONNECT;
+ i8V[1] = 0;
+ this.ws.send(buffer);
+ this.ws.close();
+ }
+ },
+
+ ws_onopen : function(evt) {
+ var buffer = new ArrayBuffer(1+1+12+2+20);
+ var i8V = new Int8Array(buffer);
+
+ i=0;
+ i8V[i++] = CONNECT;
+ i8V[i++] = 12+2+20;
+ i8V[i++] = 0;
+ i8V[i++] = 6;
+ str = "MQIsdp";
+ for(var j=0; j<str.length; j++){
+ i8V[i++] = str.charCodeAt(j);
+ }
+ i8V[i++] = 3;
+ i8V[i++] = 2;
+ i8V[i++] = 0;
+ i8V[i++] = 60;
+ i8V[i++] = 0;
+ i8V[i++] = 20;
+ var str = "mjsws/";
+ for(var j=0; j<str.length; j++){
+ i8V[i++] = str.charCodeAt(j);
+ }
+ var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ for(var j=0; j<14; j++){
+ i8V[i++] = chars.charCodeAt(Math.floor(Math.random()*chars.length));
+ }
+
+ this.send(buffer);
+ while(this.m.out_queue.length > 0){
+ this.send(this.m.out_queue.pop());
+ }
+ setTimeout(function(_this){_this.mqtt_ping();}, 60000, this.m);
+ },
+
+ ws_onclose : function(evt) {
+ if(this.m.ondisconnect){
+ this.m.ondisconnect(evt.data);
+ }
+ },
+
+ ws_onmessage : function(evt) {
+ var i8V = new Int8Array(evt.data);
+ buffer = evt.data;
+ var q=0;
+ while(i8V.length > 0 && q < 1000){
+ q++;
+ switch(i8V[0] & 0xF0){
+ case CONNACK:
+ var rl = i8V[1];
+ var rc = i8V[2];
+ if(this.m.onconnect){
+ this.m.onconnect(rc);
+ }
+ buffer = buffer.slice(rl+2);
+ i8V = new Int8Array(buffer);
+ break;
+ case PUBLISH:
+ var i=1;
+ var mult = 1;
+ var rl = 0;
+ var count = 0;
+ var digit;
+ var qos = (i8V[0] & 0x06) >> 1;
+ var retain = (i8V[0] & 0x01);
+ var mid = 0;
+ do{
+ count++;
+ digit = i8V[i++];
+ rl += (digit & 127)*mult;
+ mult *= 128;
+ }while((digit & 128) != 0);
+
+ var topiclen = i8V[i++]*256 + i8V[i++];
+ var atopic = buffer.slice(i, i+topiclen);
+ i+=topiclen;
+ var topic = AB2S(atopic);
+ if(qos > 0){
+ mid = i8V[i++]*256 + i8V[i++];
+ }
+ var apayload = buffer.slice(i, rl+count+1);
+ var payload = AB2S(apayload);
+
+ buffer = buffer.slice(rl+1+count);
+ i8V = new Int8Array(buffer);
+
+ if(this.m.onmessage){
+ this.m.onmessage(topic, payload, qos, retain);
+ }
+ break;
+ case PUBREC:
+ case PUBREL:
+ case PUBACK:
+ case PUBCOMP:
+ case SUBACK:
+ case UNSUBACK:
+ case PINGRESP:
+ var rl = i8V[1];
+ buffer = buffer.slice(rl+2);
+ i8V = new Int8Array(buffer);
+ break;
+ }
+ }
+ },
+
+ get_remaining_count : function(remaining_length)
+ {
+ if(remaining_length >= 0 && remaining_length < 128){
+ return 1;
+ }else if(remaining_length >= 128 && remaining_length < 16384){
+ return 2;
+ }else if(remaining_length >= 16384 && remaining_length < 2097152){
+ return 3;
+ }else if(remaining_length >= 2097152 && remaining_length < 268435456){
+ return 4;
+ }else{
+ return -1;
+ }
+ },
+
+ generate_mid : function()
+ {
+ var mid = this.mid;
+ this.mid++;
+ if(this.mid == 256) this.mid = 0;
+ return mid;
+ },
+
+ queue : function(buffer)
+ {
+ this.out_queue.push(buffer);
+ },
+
+ send_cmd_with_mid : function(cmd, mid)
+ {
+ var buffer = new ArrayBuffer(4);
+ var i8V = new Int8Array(buffer);
+ i8V[0] = cmd;
+ i8V[1] = 2;
+ i8V[2] = mid%128;
+ i8V[3] = mid/128;
+ if(this.ws.readyState == 1){
+ this.ws.send(buffer);
+ }else{
+ this.queue(buffer);
+ }
+ },
+
+ unsubscribe : function(topic)
+ {
+ var rl = 2+2+topic.length;
+ var remaining_count = this.get_remaining_count(rl);
+ var buffer = new ArrayBuffer(1+remaining_count+rl);
+ var i8V = new Int8Array(buffer);
+
+ var i=0;
+ i8V[i++] = UNSUBSCRIBE | 0x02;
+ do{
+ digit = Math.floor(rl % 128);
+ rl = Math.floor(rl / 128);
+ if(rl > 0){
+ digit = digit | 0x80;
+ }
+ i8V[i++] = digit;
+ }while(rl > 0);
+ i8V[i++] = 0;
+ i8V[i++] = this.generate_mid();
+ i8V[i++] = 0;
+ i8V[i++] = topic.length;
+ for(var j=0; j<topic.length; j++){
+ i8V[i++] = topic.charCodeAt(j);
+ }
+
+ if(this.ws.readyState == 1){
+ this.ws.send(buffer);
+ }else{
+ this.queue(buffer);
+ }
+ },
+
+ subscribe : function(topic, qos)
+ {
+ if(qos != 0){
+ return 1;
+ }
+ var rl = 2+2+topic.length+1;
+ var remaining_count = this.get_remaining_count(rl);
+ var buffer = new ArrayBuffer(1+remaining_count+rl);
+ var i8V = new Int8Array(buffer);
+
+ var i=0;
+ i8V[i++] = SUBSCRIBE | 0x02;
+ do{
+ digit = Math.floor(rl % 128);
+ rl = Math.floor(rl / 128);
+ if(rl > 0){
+ digit = digit | 0x80;
+ }
+ i8V[i++] = digit;
+ }while(rl > 0);
+ i8V[i++] = 0;
+ i8V[i++] = this.generate_mid();
+ i8V[i++] = 0;
+ i8V[i++] = topic.length;
+ for(var j=0; j<topic.length; j++){
+ i8V[i++] = topic.charCodeAt(j);
+ }
+ i8V[i++] = qos;
+
+ if(this.ws.readyState == 1){
+ this.ws.send(buffer);
+ }else{
+ this.queue(buffer);
+ }
+ },
+
+ publish : function(topic, payload, qos, retain){
+ if(qos != 0) return 1;
+ var rl = 2+topic.length+payload.length;
+ var remaining_count = this.get_remaining_count(rl);
+ var buffer = new ArrayBuffer(1+remaining_count+rl);
+ var i8V = new Int8Array(buffer);
+
+ var i=0;
+ retain = retain?1:0;
+ i8V[i++] = PUBLISH | (qos<<1) | retain;
+ do{
+ digit = Math.floor(rl % 128);
+ rl = Math.floor(rl / 128);
+ if(rl > 0){
+ digit = digit | 0x80;
+ }
+ i8V[i++] = digit;
+ }while(rl > 0);
+ i8V[i++] = 0;
+ i8V[i++] = topic.length;
+ for(var j=0; j<topic.length; j++){
+ i8V[i++] = topic.charCodeAt(j);
+ }
+ for(var j=0; j<payload.length; j++){
+ i8V[i++] = payload.charCodeAt(j);
+ }
+
+ if(this.ws.readyState == 1){
+ this.ws.send(buffer);
+ }else{
+ this.queue(buffer);
+ }
+ }
+}
+
--- /dev/null
+/* Linker version script - currently used here primarily to control which
+ * symbols are exported.
+ */
+
+MOSQ_1.0 {
+ global:
+ mosquitto_lib_version;
+ mosquitto_lib_init;
+ mosquitto_lib_cleanup;
+ mosquitto_new;
+ mosquitto_destroy;
+ mosquitto_reinitialise;
+ mosquitto_will_set;
+ mosquitto_will_clear;
+ mosquitto_username_pw_set;
+ mosquitto_connect;
+ mosquitto_connect_async;
+ mosquitto_reconnect;
+ mosquitto_disconnect;
+ mosquitto_publish;
+ mosquitto_subscribe;
+ mosquitto_unsubscribe;
+ mosquitto_message_copy;
+ mosquitto_message_free;
+ mosquitto_loop;
+ mosquitto_socket;
+ mosquitto_loop_start;
+ mosquitto_loop_stop;
+ mosquitto_loop_read;
+ mosquitto_loop_write;
+ mosquitto_loop_misc;
+ mosquitto_connect_callback_set;
+ mosquitto_disconnect_callback_set;
+ mosquitto_publish_callback_set;
+ mosquitto_message_callback_set;
+ mosquitto_subscribe_callback_set;
+ mosquitto_unsubscribe_callback_set;
+ mosquitto_log_callback_set;
+ mosquitto_message_retry_set;
+ mosquitto_want_write;
+ mosquitto_user_data_set;
+ mosquitto_strerror;
+ mosquitto_connack_string;
+ mosquitto_tls_set;
+ mosquitto_tls_opts_set;
+ mosquitto_tls_psk_set;
+ mosquitto_sub_topic_tokenise;
+ mosquitto_sub_topic_tokens_free;
+ mosquitto_topic_matches_sub;
+ local: *;
+};
+
+MOSQ_1.1 {
+ global:
+ mosquitto_loop_forever;
+} MOSQ_1.0;
+
+MOSQ_1.2 {
+ global:
+ mosquitto_connect_bind;
+ mosquitto_connect_bind_async;
+ mosquitto_max_inflight_messages_set;
+ mosquitto_reconnect_delay_set;
+ mosquitto_reconnect_async;
+ mosquitto_tls_insecure_set;
+} MOSQ_1.1;
+
+MOSQ_1.3 {
+ global:
+ mosquitto_connect_srv;
+} MOSQ_1.2;
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mosquitto_internal.h"
+#include "mosquitto.h"
+#include "memory_mosq.h"
+
+int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...)
+{
+ va_list va;
+ char *s;
+ int len;
+
+ assert(mosq);
+ assert(fmt);
+
+ pthread_mutex_lock(&mosq->log_callback_mutex);
+ if(mosq->on_log){
+ len = strlen(fmt) + 500;
+ s = _mosquitto_malloc(len*sizeof(char));
+ if(!s){
+ pthread_mutex_unlock(&mosq->log_callback_mutex);
+ return MOSQ_ERR_NOMEM;
+ }
+
+ va_start(va, fmt);
+ vsnprintf(s, len, fmt, va);
+ va_end(va);
+ s[len-1] = '\0'; /* Ensure string is null terminated. */
+
+ mosq->on_log(mosq, mosq->userdata, priority, s);
+
+ _mosquitto_free(s);
+ }
+ pthread_mutex_unlock(&mosq->log_callback_mutex);
+
+ return MOSQ_ERR_SUCCESS;
+}
+
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _LOGGING_MOSQ_H_
+#define _LOGGING_MOSQ_H_
+
+#include "mosquitto.h"
+
+int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...);
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "memory_mosq.h"
+
+#ifdef REAL_WITH_MEMORY_TRACKING
+# if defined(__APPLE__)
+# include <malloc/malloc.h>
+# define malloc_usable_size malloc_size
+# elif defined(__FreeBSD__)
+# include <malloc_np.h>
+# else
+# include <malloc.h>
+# endif
+#endif
+
+#ifdef REAL_WITH_MEMORY_TRACKING
+static unsigned long memcount = 0;
+static unsigned long max_memcount = 0;
+#endif
+
+void *_mosquitto_calloc(size_t nmemb, size_t size)
+{
+ void *mem = calloc(nmemb, size);
+
+#ifdef REAL_WITH_MEMORY_TRACKING
+ memcount += malloc_usable_size(mem);
+ if(memcount > max_memcount){
+ max_memcount = memcount;
+ }
+#endif
+
+ return mem;
+}
+
+void _mosquitto_free(void *mem)
+{
+#ifdef REAL_WITH_MEMORY_TRACKING
+ memcount -= malloc_usable_size(mem);
+#endif
+ free(mem);
+}
+
+void *_mosquitto_malloc(size_t size)
+{
+ void *mem = malloc(size);
+
+#ifdef REAL_WITH_MEMORY_TRACKING
+ memcount += malloc_usable_size(mem);
+ if(memcount > max_memcount){
+ max_memcount = memcount;
+ }
+#endif
+
+ return mem;
+}
+
+#ifdef REAL_WITH_MEMORY_TRACKING
+unsigned long _mosquitto_memory_used(void)
+{
+ return memcount;
+}
+
+unsigned long _mosquitto_max_memory_used(void)
+{
+ return max_memcount;
+}
+#endif
+
+void *_mosquitto_realloc(void *ptr, size_t size)
+{
+ void *mem;
+#ifdef REAL_WITH_MEMORY_TRACKING
+ if(ptr){
+ memcount -= malloc_usable_size(ptr);
+ }
+#endif
+ mem = realloc(ptr, size);
+
+#ifdef REAL_WITH_MEMORY_TRACKING
+ memcount += malloc_usable_size(mem);
+ if(memcount > max_memcount){
+ max_memcount = memcount;
+ }
+#endif
+
+ return mem;
+}
+
+char *_mosquitto_strdup(const char *s)
+{
+ char *str = strdup(s);
+
+#ifdef REAL_WITH_MEMORY_TRACKING
+ memcount += malloc_usable_size(str);
+ if(memcount > max_memcount){
+ max_memcount = memcount;
+ }
+#endif
+
+ return str;
+}
+
--- /dev/null
+/*
+Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _MEMORY_MOSQ_H_
+#define _MEMORY_MOSQ_H_
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#if defined(WITH_MEMORY_TRACKING) && defined(WITH_BROKER) && !defined(WIN32) && !defined(__SYMBIAN32__) && !defined(__ANDROID__)
+#define REAL_WITH_MEMORY_TRACKING
+#endif
+
+void *_mosquitto_calloc(size_t nmemb, size_t size);
+void _mosquitto_free(void *mem);
+void *_mosquitto_malloc(size_t size);
+#ifdef REAL_WITH_MEMORY_TRACKING
+unsigned long _mosquitto_memory_used(void);
+unsigned long _mosquitto_max_memory_used(void);
+#endif
+void *_mosquitto_realloc(void *ptr, size_t size);
+char *_mosquitto_strdup(const char *s);
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mosquitto_internal.h"
+#include "mosquitto.h"
+#include "memory_mosq.h"
+#include "messages_mosq.h"
+#include "send_mosq.h"
+#include "time_mosq.h"
+
+void _mosquitto_message_cleanup(struct mosquitto_message_all **message)
+{
+ struct mosquitto_message_all *msg;
+
+ if(!message || !*message) return;
+
+ msg = *message;
+
+ if(msg->msg.topic) _mosquitto_free(msg->msg.topic);
+ if(msg->msg.payload) _mosquitto_free(msg->msg.payload);
+ _mosquitto_free(msg);
+}
+
+void _mosquitto_message_cleanup_all(struct mosquitto *mosq)
+{
+ struct mosquitto_message_all *tmp;
+
+ assert(mosq);
+
+ while(mosq->in_messages){
+ tmp = mosq->in_messages->next;
+ _mosquitto_message_cleanup(&mosq->in_messages);
+ mosq->in_messages = tmp;
+ }
+ while(mosq->out_messages){
+ tmp = mosq->out_messages->next;
+ _mosquitto_message_cleanup(&mosq->out_messages);
+ mosq->out_messages = tmp;
+ }
+}
+
+int mosquitto_message_copy(struct mosquitto_message *dst, const struct mosquitto_message *src)
+{
+ if(!dst || !src) return MOSQ_ERR_INVAL;
+
+ dst->mid = src->mid;
+ dst->topic = _mosquitto_strdup(src->topic);
+ if(!dst->topic) return MOSQ_ERR_NOMEM;
+ dst->qos = src->qos;
+ dst->retain = src->retain;
+ if(src->payloadlen){
+ dst->payload = _mosquitto_malloc(src->payloadlen);
+ if(!dst->payload){
+ _mosquitto_free(dst->topic);
+ return MOSQ_ERR_NOMEM;
+ }
+ memcpy(dst->payload, src->payload, src->payloadlen);
+ dst->payloadlen = src->payloadlen;
+ }else{
+ dst->payloadlen = 0;
+ dst->payload = NULL;
+ }
+ return MOSQ_ERR_SUCCESS;
+}
+
+int _mosquitto_message_delete(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir)
+{
+ struct mosquitto_message_all *message;
+ int rc;
+ assert(mosq);
+
+ rc = _mosquitto_message_remove(mosq, mid, dir, &message);
+ if(rc == MOSQ_ERR_SUCCESS){
+ _mosquitto_message_cleanup(&message);
+ }
+ return rc;
+}
+
+void mosquitto_message_free(struct mosquitto_message **message)
+{
+ struct mosquitto_message *msg;
+
+ if(!message || !*message) return;
+
+ msg = *message;
+
+ if(msg->topic) _mosquitto_free(msg->topic);
+ if(msg->payload) _mosquitto_free(msg->payload);
+ _mosquitto_free(msg);
+}
+
+void _mosquitto_message_queue(struct mosquitto *mosq, struct mosquitto_message_all *message, enum mosquitto_msg_direction dir)
+{
+ /* mosq->*_message_mutex should be locked before entering this function */
+ assert(mosq);
+ assert(message);
+
+ if(dir == mosq_md_out){
+ mosq->out_queue_len++;
+ message->next = NULL;
+ if(mosq->out_messages_last){
+ mosq->out_messages_last->next = message;
+ }else{
+ mosq->out_messages = message;
+ }
+ mosq->out_messages_last = message;
+ }else{
+ mosq->in_queue_len++;
+ if(message->msg.qos > 0 && (mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages)){
+ mosq->inflight_messages++;
+ }
+ message->next = NULL;
+ if(mosq->in_messages_last){
+ mosq->in_messages_last->next = message;
+ }else{
+ mosq->in_messages = message;
+ }
+ mosq->in_messages_last = message;
+ }
+}
+
+void _mosquitto_messages_reconnect_reset(struct mosquitto *mosq)
+{
+ struct mosquitto_message_all *message;
+ struct mosquitto_message_all *prev = NULL;
+ assert(mosq);
+
+ pthread_mutex_lock(&mosq->in_message_mutex);
+ message = mosq->in_messages;
+ mosq->in_queue_len = 0;
+ while(message){
+ mosq->in_queue_len++;
+ message->timestamp = 0;
+ if(message->msg.qos != 2){
+ if(prev){
+ prev->next = message->next;
+ _mosquitto_message_cleanup(&message);
+ message = prev;
+ }else{
+ mosq->in_messages = message->next;
+ _mosquitto_message_cleanup(&message);
+ message = mosq->in_messages;
+ }
+ }else{
+ /* Message state can be preserved here because it should match
+ * whatever the client has got. */
+ }
+ prev = message;
+ message = message->next;
+ }
+ mosq->in_messages_last = prev;
+ pthread_mutex_unlock(&mosq->in_message_mutex);
+
+
+ pthread_mutex_lock(&mosq->out_message_mutex);
+ mosq->inflight_messages = 0;
+ message = mosq->out_messages;
+ mosq->out_queue_len = 0;
+ while(message){
+ mosq->out_queue_len++;
+ message->timestamp = 0;
+
+ if(message->msg.qos > 0){
+ mosq->inflight_messages++;
+ }
+ if(mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages){
+ if(message->msg.qos == 1){
+ message->state = mosq_ms_wait_for_puback;
+ }else if(message->msg.qos == 2){
+ /* Should be able to preserve state. */
+ }
+ }else{
+ message->state = mosq_ms_invalid;
+ }
+ prev = message;
+ message = message->next;
+ }
+ mosq->out_messages_last = prev;
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+}
+
+int _mosquitto_message_remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, struct mosquitto_message_all **message)
+{
+ struct mosquitto_message_all *cur, *prev = NULL;
+ bool found = false;
+ int rc;
+ assert(mosq);
+ assert(message);
+
+ if(dir == mosq_md_out){
+ pthread_mutex_lock(&mosq->out_message_mutex);
+ cur = mosq->out_messages;
+ while(cur){
+ if(cur->msg.mid == mid){
+ if(prev){
+ prev->next = cur->next;
+ }else{
+ mosq->out_messages = cur->next;
+ }
+ *message = cur;
+ mosq->out_queue_len--;
+ if(cur->next == NULL){
+ mosq->out_messages_last = prev;
+ }else if(!mosq->out_messages){
+ mosq->out_messages_last = NULL;
+ }
+ if(cur->msg.qos > 0){
+ mosq->inflight_messages--;
+ }
+ found = true;
+ break;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+ if(found){
+ cur = mosq->out_messages;
+ while(cur){
+ if(mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages){
+ if(cur->msg.qos > 0 && cur->state == mosq_ms_invalid){
+ mosq->inflight_messages++;
+ if(cur->msg.qos == 1){
+ cur->state = mosq_ms_wait_for_puback;
+ }else if(cur->msg.qos == 2){
+ cur->state = mosq_ms_wait_for_pubrec;
+ }
+ rc = _mosquitto_send_publish(mosq, cur->msg.mid, cur->msg.topic, cur->msg.payloadlen, cur->msg.payload, cur->msg.qos, cur->msg.retain, cur->dup);
+ if(rc){
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+ return rc;
+ }
+ }
+ }else{
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+ return MOSQ_ERR_SUCCESS;
+ }
+ cur = cur->next;
+ }
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+ return MOSQ_ERR_SUCCESS;
+ }else{
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+ return MOSQ_ERR_NOT_FOUND;
+ }
+ }else{
+ pthread_mutex_lock(&mosq->in_message_mutex);
+ cur = mosq->in_messages;
+ while(cur){
+ if(cur->msg.mid == mid){
+ if(prev){
+ prev->next = cur->next;
+ }else{
+ mosq->in_messages = cur->next;
+ }
+ *message = cur;
+ mosq->in_queue_len--;
+ if(cur->next == NULL){
+ mosq->in_messages_last = prev;
+ }else if(!mosq->in_messages){
+ mosq->in_messages_last = NULL;
+ }
+ if(cur->msg.qos == 2){
+ mosq->inflight_messages--;
+ }
+ found = true;
+ break;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+ pthread_mutex_unlock(&mosq->in_message_mutex);
+ if(found){
+ return MOSQ_ERR_SUCCESS;
+ }else{
+ return MOSQ_ERR_NOT_FOUND;
+ }
+ }
+}
+
+#ifdef WITH_THREADING
+void _mosquitto_message_retry_check_actual(struct mosquitto *mosq, struct mosquitto_message_all *messages, pthread_mutex_t mutex)
+#else
+void _mosquitto_message_retry_check_actual(struct mosquitto *mosq, struct mosquitto_message_all *messages)
+#endif
+{
+ time_t now = mosquitto_time();
+ assert(mosq);
+
+#ifdef WITH_THREADING
+ pthread_mutex_lock(&mutex);
+#endif
+
+ while(messages){
+ if(messages->timestamp + mosq->message_retry < now){
+ switch(messages->state){
+ case mosq_ms_wait_for_puback:
+ case mosq_ms_wait_for_pubrec:
+ messages->timestamp = now;
+ messages->dup = true;
+ _mosquitto_send_publish(mosq, messages->msg.mid, messages->msg.topic, messages->msg.payloadlen, messages->msg.payload, messages->msg.qos, messages->msg.retain, messages->dup);
+ break;
+ case mosq_ms_wait_for_pubrel:
+ messages->timestamp = now;
+ messages->dup = true;
+ _mosquitto_send_pubrec(mosq, messages->msg.mid);
+ break;
+ case mosq_ms_wait_for_pubcomp:
+ messages->timestamp = now;
+ messages->dup = true;
+ _mosquitto_send_pubrel(mosq, messages->msg.mid, true);
+ break;
+ default:
+ break;
+ }
+ }
+ messages = messages->next;
+ }
+#ifdef WITH_THREADING
+ pthread_mutex_unlock(&mutex);
+#endif
+}
+
+void _mosquitto_message_retry_check(struct mosquitto *mosq)
+{
+#ifdef WITH_THREADING
+ _mosquitto_message_retry_check_actual(mosq, mosq->out_messages, mosq->out_message_mutex);
+ _mosquitto_message_retry_check_actual(mosq, mosq->in_messages, mosq->in_message_mutex);
+#else
+ _mosquitto_message_retry_check_actual(mosq, mosq->out_messages);
+ _mosquitto_message_retry_check_actual(mosq, mosq->in_messages);
+#endif
+}
+
+void mosquitto_message_retry_set(struct mosquitto *mosq, unsigned int message_retry)
+{
+ assert(mosq);
+ if(mosq) mosq->message_retry = message_retry;
+}
+
+int _mosquitto_message_out_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_state state)
+{
+ struct mosquitto_message_all *message;
+ assert(mosq);
+
+ pthread_mutex_lock(&mosq->out_message_mutex);
+ message = mosq->out_messages;
+ while(message){
+ if(message->msg.mid == mid){
+ message->state = state;
+ message->timestamp = mosquitto_time();
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+ return MOSQ_ERR_SUCCESS;
+ }
+ message = message->next;
+ }
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+ return MOSQ_ERR_NOT_FOUND;
+}
+
+int mosquitto_max_inflight_messages_set(struct mosquitto *mosq, unsigned int max_inflight_messages)
+{
+ if(!mosq) return MOSQ_ERR_INVAL;
+
+ mosq->max_inflight_messages = max_inflight_messages;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
--- /dev/null
+/*
+Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _MESSAGES_MOSQ_H_
+#define _MESSAGES_MOSQ_H_
+
+#include "mosquitto_internal.h"
+#include "mosquitto.h"
+
+void _mosquitto_message_cleanup_all(struct mosquitto *mosq);
+void _mosquitto_message_cleanup(struct mosquitto_message_all **message);
+int _mosquitto_message_delete(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir);
+void _mosquitto_message_queue(struct mosquitto *mosq, struct mosquitto_message_all *message, enum mosquitto_msg_direction dir);
+void _mosquitto_messages_reconnect_reset(struct mosquitto *mosq);
+int _mosquitto_message_remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, struct mosquitto_message_all **message);
+void _mosquitto_message_retry_check(struct mosquitto *mosq);
+int _mosquitto_message_out_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_state state);
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef WIN32
+#include <sys/select.h>
+#include <sys/time.h>
+#include <unistd.h>
+#else
+#include <winsock2.h>
+#include <windows.h>
+typedef int ssize_t;
+#endif
+
+#include "mosquitto.h"
+#include "mosquitto_internal.h"
+#include "logging_mosq.h"
+#include "messages_mosq.h"
+#include "memory_mosq.h"
+#include "mqtt3_protocol.h"
+#include "net_mosq.h"
+#include "read_handle.h"
+#include "send_mosq.h"
+#include "time_mosq.h"
+#include "tls_mosq.h"
+#include "util_mosq.h"
+#include "will_mosq.h"
+
+#if !defined(WIN32) && !defined(__SYMBIAN32__)
+#define HAVE_PSELECT
+#endif
+
+void _mosquitto_destroy(struct mosquitto *mosq);
+static int _mosquitto_reconnect(struct mosquitto *mosq, bool blocking);
+static int _mosquitto_connect_init(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address);
+
+int mosquitto_lib_version(int *major, int *minor, int *revision)
+{
+ if(major) *major = LIBMOSQUITTO_MAJOR;
+ if(minor) *minor = LIBMOSQUITTO_MINOR;
+ if(revision) *revision = LIBMOSQUITTO_REVISION;
+ return LIBMOSQUITTO_VERSION_NUMBER;
+}
+
+int mosquitto_lib_init(void)
+{
+#ifdef WIN32
+ srand(GetTickCount());
+#else
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ srand(tv.tv_sec*1000 + tv.tv_usec/1000);
+#endif
+
+ _mosquitto_net_init();
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+int mosquitto_lib_cleanup(void)
+{
+ _mosquitto_net_cleanup();
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+struct mosquitto *mosquitto_new(const char *id, bool clean_session, void *userdata)
+{
+ struct mosquitto *mosq = NULL;
+ int rc;
+
+ if(clean_session == false && id == NULL){
+ errno = EINVAL;
+ return NULL;
+ }
+
+#ifndef WIN32
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ mosq = (struct mosquitto *)_mosquitto_calloc(1, sizeof(struct mosquitto));
+ if(mosq){
+ mosq->sock = INVALID_SOCKET;
+ mosq->sockpairR = INVALID_SOCKET;
+ mosq->sockpairW = INVALID_SOCKET;
+#ifdef WITH_THREADING
+ mosq->thread_id = pthread_self();
+#endif
+ rc = mosquitto_reinitialise(mosq, id, clean_session, userdata);
+ if(rc){
+ mosquitto_destroy(mosq);
+ if(rc == MOSQ_ERR_INVAL){
+ errno = EINVAL;
+ }else if(rc == MOSQ_ERR_NOMEM){
+ errno = ENOMEM;
+ }
+ return NULL;
+ }
+ }else{
+ errno = ENOMEM;
+ }
+ return mosq;
+}
+
+int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_session, void *userdata)
+{
+ int i;
+
+ if(!mosq) return MOSQ_ERR_INVAL;
+
+ if(clean_session == false && id == NULL){
+ return MOSQ_ERR_INVAL;
+ }
+
+ _mosquitto_destroy(mosq);
+ memset(mosq, 0, sizeof(struct mosquitto));
+
+ if(userdata){
+ mosq->userdata = userdata;
+ }else{
+ mosq->userdata = mosq;
+ }
+ mosq->sock = INVALID_SOCKET;
+ mosq->sockpairR = INVALID_SOCKET;
+ mosq->sockpairW = INVALID_SOCKET;
+ mosq->keepalive = 60;
+ mosq->message_retry = 20;
+ mosq->last_retry_check = 0;
+ mosq->clean_session = clean_session;
+ if(id){
+ if(strlen(id) == 0){
+ return MOSQ_ERR_INVAL;
+ }
+ mosq->id = _mosquitto_strdup(id);
+ }else{
+ mosq->id = (char *)_mosquitto_calloc(24, sizeof(char));
+ if(!mosq->id){
+ return MOSQ_ERR_NOMEM;
+ }
+ mosq->id[0] = 'm';
+ mosq->id[1] = 'o';
+ mosq->id[2] = 's';
+ mosq->id[3] = 'q';
+ mosq->id[4] = '/';
+
+ for(i=5; i<23; i++){
+ mosq->id[i] = (rand()%73)+48;
+ }
+ }
+ mosq->in_packet.payload = NULL;
+ _mosquitto_packet_cleanup(&mosq->in_packet);
+ mosq->out_packet = NULL;
+ mosq->current_out_packet = NULL;
+ mosq->last_msg_in = mosquitto_time();
+ mosq->last_msg_out = mosquitto_time();
+ mosq->ping_t = 0;
+ mosq->last_mid = 0;
+ mosq->state = mosq_cs_new;
+ mosq->in_messages = NULL;
+ mosq->in_messages_last = NULL;
+ mosq->out_messages = NULL;
+ mosq->out_messages_last = NULL;
+ mosq->max_inflight_messages = 20;
+ mosq->will = NULL;
+ mosq->on_connect = NULL;
+ mosq->on_publish = NULL;
+ mosq->on_message = NULL;
+ mosq->on_subscribe = NULL;
+ mosq->on_unsubscribe = NULL;
+ mosq->host = NULL;
+ mosq->port = 1883;
+ mosq->in_callback = false;
+ mosq->in_queue_len = 0;
+ mosq->out_queue_len = 0;
+ mosq->reconnect_delay = 1;
+ mosq->reconnect_delay_max = 1;
+ mosq->reconnect_exponential_backoff = false;
+ mosq->threaded = false;
+#ifdef WITH_TLS
+ mosq->ssl = NULL;
+ mosq->tls_cert_reqs = SSL_VERIFY_PEER;
+ mosq->tls_insecure = false;
+#endif
+#ifdef WITH_THREADING
+ pthread_mutex_init(&mosq->callback_mutex, NULL);
+ pthread_mutex_init(&mosq->log_callback_mutex, NULL);
+ pthread_mutex_init(&mosq->state_mutex, NULL);
+ pthread_mutex_init(&mosq->out_packet_mutex, NULL);
+ pthread_mutex_init(&mosq->current_out_packet_mutex, NULL);
+ pthread_mutex_init(&mosq->msgtime_mutex, NULL);
+ pthread_mutex_init(&mosq->in_message_mutex, NULL);
+ pthread_mutex_init(&mosq->out_message_mutex, NULL);
+ mosq->thread_id = pthread_self();
+#endif
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+int mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain)
+{
+ if(!mosq) return MOSQ_ERR_INVAL;
+ return _mosquitto_will_set(mosq, topic, payloadlen, payload, qos, retain);
+}
+
+int mosquitto_will_clear(struct mosquitto *mosq)
+{
+ if(!mosq) return MOSQ_ERR_INVAL;
+ return _mosquitto_will_clear(mosq);
+}
+
+int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password)
+{
+ if(!mosq) return MOSQ_ERR_INVAL;
+
+ if(mosq->username){
+ _mosquitto_free(mosq->username);
+ mosq->username = NULL;
+ }
+ if(mosq->password){
+ _mosquitto_free(mosq->password);
+ mosq->password = NULL;
+ }
+
+ if(username){
+ mosq->username = _mosquitto_strdup(username);
+ if(!mosq->username) return MOSQ_ERR_NOMEM;
+ if(password){
+ mosq->password = _mosquitto_strdup(password);
+ if(!mosq->password){
+ _mosquitto_free(mosq->username);
+ mosq->username = NULL;
+ return MOSQ_ERR_NOMEM;
+ }
+ }
+ }
+ return MOSQ_ERR_SUCCESS;
+}
+
+int mosquitto_reconnect_delay_set(struct mosquitto *mosq, unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff)
+{
+ if(!mosq) return MOSQ_ERR_INVAL;
+
+ mosq->reconnect_delay = reconnect_delay;
+ mosq->reconnect_delay_max = reconnect_delay_max;
+ mosq->reconnect_exponential_backoff = reconnect_exponential_backoff;
+
+ return MOSQ_ERR_SUCCESS;
+
+}
+
+void _mosquitto_destroy(struct mosquitto *mosq)
+{
+ struct _mosquitto_packet *packet;
+ if(!mosq) return;
+
+#ifdef WITH_THREADING
+ if(mosq->threaded && !pthread_equal(mosq->thread_id, pthread_self())){
+ pthread_cancel(mosq->thread_id);
+ pthread_join(mosq->thread_id, NULL);
+ mosq->threaded = false;
+ }
+
+ if(mosq->id){
+ /* If mosq->id is not NULL then the client has already been initialised
+ * and so the mutexes need destroying. If mosq->id is NULL, the mutexes
+ * haven't been initialised. */
+ pthread_mutex_destroy(&mosq->callback_mutex);
+ pthread_mutex_destroy(&mosq->log_callback_mutex);
+ pthread_mutex_destroy(&mosq->state_mutex);
+ pthread_mutex_destroy(&mosq->out_packet_mutex);
+ pthread_mutex_destroy(&mosq->current_out_packet_mutex);
+ pthread_mutex_destroy(&mosq->msgtime_mutex);
+ pthread_mutex_destroy(&mosq->in_message_mutex);
+ pthread_mutex_destroy(&mosq->out_message_mutex);
+ }
+#endif
+ if(mosq->sock != INVALID_SOCKET){
+ _mosquitto_socket_close(mosq);
+ }
+ _mosquitto_message_cleanup_all(mosq);
+ _mosquitto_will_clear(mosq);
+#ifdef WITH_TLS
+ if(mosq->ssl){
+ SSL_free(mosq->ssl);
+ }
+ if(mosq->ssl_ctx){
+ SSL_CTX_free(mosq->ssl_ctx);
+ }
+ if(mosq->tls_cafile) _mosquitto_free(mosq->tls_cafile);
+ if(mosq->tls_capath) _mosquitto_free(mosq->tls_capath);
+ if(mosq->tls_certfile) _mosquitto_free(mosq->tls_certfile);
+ if(mosq->tls_keyfile) _mosquitto_free(mosq->tls_keyfile);
+ if(mosq->tls_pw_callback) mosq->tls_pw_callback = NULL;
+ if(mosq->tls_version) _mosquitto_free(mosq->tls_version);
+ if(mosq->tls_ciphers) _mosquitto_free(mosq->tls_ciphers);
+ if(mosq->tls_psk) _mosquitto_free(mosq->tls_psk);
+ if(mosq->tls_psk_identity) _mosquitto_free(mosq->tls_psk_identity);
+#endif
+
+ if(mosq->address){
+ _mosquitto_free(mosq->address);
+ mosq->address = NULL;
+ }
+ if(mosq->id){
+ _mosquitto_free(mosq->id);
+ mosq->id = NULL;
+ }
+ if(mosq->username){
+ _mosquitto_free(mosq->username);
+ mosq->username = NULL;
+ }
+ if(mosq->password){
+ _mosquitto_free(mosq->password);
+ mosq->password = NULL;
+ }
+ if(mosq->host){
+ _mosquitto_free(mosq->host);
+ mosq->host = NULL;
+ }
+ if(mosq->bind_address){
+ _mosquitto_free(mosq->bind_address);
+ mosq->bind_address = NULL;
+ }
+
+ /* Out packet cleanup */
+ if(mosq->out_packet && !mosq->current_out_packet){
+ mosq->current_out_packet = mosq->out_packet;
+ mosq->out_packet = mosq->out_packet->next;
+ }
+ while(mosq->current_out_packet){
+ packet = mosq->current_out_packet;
+ /* Free data and reset values */
+ mosq->current_out_packet = mosq->out_packet;
+ if(mosq->out_packet){
+ mosq->out_packet = mosq->out_packet->next;
+ }
+
+ _mosquitto_packet_cleanup(packet);
+ _mosquitto_free(packet);
+ }
+
+ _mosquitto_packet_cleanup(&mosq->in_packet);
+ if(mosq->sockpairR != INVALID_SOCKET){
+ COMPAT_CLOSE(mosq->sockpairR);
+ mosq->sockpairR = INVALID_SOCKET;
+ }
+ if(mosq->sockpairW != INVALID_SOCKET){
+ COMPAT_CLOSE(mosq->sockpairW);
+ mosq->sockpairW = INVALID_SOCKET;
+ }
+}
+
+void mosquitto_destroy(struct mosquitto *mosq)
+{
+ if(!mosq) return;
+
+ _mosquitto_destroy(mosq);
+ _mosquitto_free(mosq);
+}
+
+int mosquitto_socket(struct mosquitto *mosq)
+{
+ if(!mosq) return MOSQ_ERR_INVAL;
+ return mosq->sock;
+}
+
+static int _mosquitto_connect_init(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address)
+{
+ if(!mosq) return MOSQ_ERR_INVAL;
+ if(!host || port <= 0) return MOSQ_ERR_INVAL;
+
+ if(mosq->host) _mosquitto_free(mosq->host);
+ mosq->host = _mosquitto_strdup(host);
+ if(!mosq->host) return MOSQ_ERR_NOMEM;
+ mosq->port = port;
+
+ if(mosq->bind_address) _mosquitto_free(mosq->bind_address);
+ if(bind_address){
+ mosq->bind_address = _mosquitto_strdup(bind_address);
+ if(!mosq->bind_address) return MOSQ_ERR_NOMEM;
+ }
+
+ mosq->keepalive = keepalive;
+
+ if(_mosquitto_socketpair(&mosq->sockpairR, &mosq->sockpairW)){
+ _mosquitto_log_printf(mosq, MOSQ_LOG_WARNING,
+ "Warning: Unable to open socket pair, outgoing publish commands may be delayed.");
+ }
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+int mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive)
+{
+ return mosquitto_connect_bind(mosq, host, port, keepalive, NULL);
+}
+
+int mosquitto_connect_bind(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address)
+{
+ int rc;
+ rc = _mosquitto_connect_init(mosq, host, port, keepalive, bind_address);
+ if(rc) return rc;
+
+ pthread_mutex_lock(&mosq->state_mutex);
+ mosq->state = mosq_cs_new;
+ pthread_mutex_unlock(&mosq->state_mutex);
+
+ return _mosquitto_reconnect(mosq, true);
+}
+
+int mosquitto_connect_async(struct mosquitto *mosq, const char *host, int port, int keepalive)
+{
+ return mosquitto_connect_bind_async(mosq, host, port, keepalive, NULL);
+}
+
+int mosquitto_connect_bind_async(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address)
+{
+ int rc = _mosquitto_connect_init(mosq, host, port, keepalive, bind_address);
+ if(rc) return rc;
+
+ pthread_mutex_lock(&mosq->state_mutex);
+ mosq->state = mosq_cs_connect_async;
+ pthread_mutex_unlock(&mosq->state_mutex);
+
+ return _mosquitto_reconnect(mosq, false);
+}
+
+int mosquitto_reconnect_async(struct mosquitto *mosq)
+{
+ return _mosquitto_reconnect(mosq, false);
+}
+
+int mosquitto_reconnect(struct mosquitto *mosq)
+{
+ return _mosquitto_reconnect(mosq, true);
+}
+
+static int _mosquitto_reconnect(struct mosquitto *mosq, bool blocking)
+{
+ int rc;
+ struct _mosquitto_packet *packet;
+ if(!mosq) return MOSQ_ERR_INVAL;
+ if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL;
+
+ pthread_mutex_lock(&mosq->state_mutex);
+ mosq->state = mosq_cs_new;
+ pthread_mutex_unlock(&mosq->state_mutex);
+
+ pthread_mutex_lock(&mosq->msgtime_mutex);
+ mosq->last_msg_in = mosquitto_time();
+ mosq->last_msg_out = mosquitto_time();
+ pthread_mutex_unlock(&mosq->msgtime_mutex);
+
+ mosq->ping_t = 0;
+
+ _mosquitto_packet_cleanup(&mosq->in_packet);
+
+ pthread_mutex_lock(&mosq->current_out_packet_mutex);
+ pthread_mutex_lock(&mosq->out_packet_mutex);
+
+ if(mosq->out_packet && !mosq->current_out_packet){
+ mosq->current_out_packet = mosq->out_packet;
+ mosq->out_packet = mosq->out_packet->next;
+ }
+
+ while(mosq->current_out_packet){
+ packet = mosq->current_out_packet;
+ /* Free data and reset values */
+ mosq->current_out_packet = mosq->out_packet;
+ if(mosq->out_packet){
+ mosq->out_packet = mosq->out_packet->next;
+ }
+
+ _mosquitto_packet_cleanup(packet);
+ _mosquitto_free(packet);
+ }
+ pthread_mutex_unlock(&mosq->out_packet_mutex);
+ pthread_mutex_unlock(&mosq->current_out_packet_mutex);
+
+ _mosquitto_messages_reconnect_reset(mosq);
+
+ rc = _mosquitto_socket_connect(mosq, mosq->host, mosq->port, mosq->bind_address, blocking);
+ if(rc){
+ return rc;
+ }
+
+ return _mosquitto_send_connect(mosq, mosq->keepalive, mosq->clean_session);
+}
+
+int mosquitto_disconnect(struct mosquitto *mosq)
+{
+ if(!mosq) return MOSQ_ERR_INVAL;
+
+ pthread_mutex_lock(&mosq->state_mutex);
+ mosq->state = mosq_cs_disconnecting;
+ pthread_mutex_unlock(&mosq->state_mutex);
+
+ if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
+ return _mosquitto_send_disconnect(mosq);
+}
+
+int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain)
+{
+ struct mosquitto_message_all *message;
+ uint16_t local_mid;
+
+ if(!mosq || !topic || qos<0 || qos>2) return MOSQ_ERR_INVAL;
+ if(strlen(topic) == 0) return MOSQ_ERR_INVAL;
+ if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE;
+
+ if(_mosquitto_topic_wildcard_len_check(topic) != MOSQ_ERR_SUCCESS){
+ return MOSQ_ERR_INVAL;
+ }
+
+ local_mid = _mosquitto_mid_generate(mosq);
+ if(mid){
+ *mid = local_mid;
+ }
+
+ if(qos == 0){
+ return _mosquitto_send_publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false);
+ }else{
+ message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all));
+ if(!message) return MOSQ_ERR_NOMEM;
+
+ message->next = NULL;
+ message->timestamp = mosquitto_time();
+ message->msg.mid = local_mid;
+ message->msg.topic = _mosquitto_strdup(topic);
+ if(!message->msg.topic){
+ _mosquitto_message_cleanup(&message);
+ return MOSQ_ERR_NOMEM;
+ }
+ if(payloadlen){
+ message->msg.payloadlen = payloadlen;
+ message->msg.payload = _mosquitto_malloc(payloadlen*sizeof(uint8_t));
+ if(!message->msg.payload){
+ _mosquitto_message_cleanup(&message);
+ return MOSQ_ERR_NOMEM;
+ }
+ memcpy(message->msg.payload, payload, payloadlen*sizeof(uint8_t));
+ }else{
+ message->msg.payloadlen = 0;
+ message->msg.payload = NULL;
+ }
+ message->msg.qos = qos;
+ message->msg.retain = retain;
+ message->dup = false;
+
+ pthread_mutex_lock(&mosq->out_message_mutex);
+ _mosquitto_message_queue(mosq, message, mosq_md_out);
+ if(mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages){
+ mosq->inflight_messages++;
+ if(qos == 1){
+ message->state = mosq_ms_wait_for_puback;
+ }else if(qos == 2){
+ message->state = mosq_ms_wait_for_pubrec;
+ }
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+ 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);
+ }else{
+ message->state = mosq_ms_invalid;
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+ return MOSQ_ERR_SUCCESS;
+ }
+ }
+}
+
+int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int qos)
+{
+ if(!mosq) return MOSQ_ERR_INVAL;
+ if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
+
+ if(_mosquitto_topic_wildcard_pos_check(sub)) return MOSQ_ERR_INVAL;
+
+ return _mosquitto_send_subscribe(mosq, mid, false, sub, qos);
+}
+
+int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const char *sub)
+{
+ if(!mosq) return MOSQ_ERR_INVAL;
+ if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
+
+ if(_mosquitto_topic_wildcard_pos_check(sub)) return MOSQ_ERR_INVAL;
+
+ return _mosquitto_send_unsubscribe(mosq, mid, false, sub);
+}
+
+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))
+{
+#ifdef WITH_TLS
+ FILE *fptr;
+
+ if(!mosq || (!cafile && !capath) || (certfile && !keyfile) || (!certfile && keyfile)) return MOSQ_ERR_INVAL;
+
+ if(cafile){
+ fptr = _mosquitto_fopen(cafile, "rt");
+ if(fptr){
+ fclose(fptr);
+ }else{
+ return MOSQ_ERR_INVAL;
+ }
+ mosq->tls_cafile = _mosquitto_strdup(cafile);
+
+ if(!mosq->tls_cafile){
+ return MOSQ_ERR_NOMEM;
+ }
+ }else if(mosq->tls_cafile){
+ _mosquitto_free(mosq->tls_cafile);
+ mosq->tls_cafile = NULL;
+ }
+
+ if(capath){
+ mosq->tls_capath = _mosquitto_strdup(capath);
+ if(!mosq->tls_capath){
+ return MOSQ_ERR_NOMEM;
+ }
+ }else if(mosq->tls_capath){
+ _mosquitto_free(mosq->tls_capath);
+ mosq->tls_capath = NULL;
+ }
+
+ if(certfile){
+ fptr = _mosquitto_fopen(certfile, "rt");
+ if(fptr){
+ fclose(fptr);
+ }else{
+ if(mosq->tls_cafile){
+ _mosquitto_free(mosq->tls_cafile);
+ mosq->tls_cafile = NULL;
+ }
+ if(mosq->tls_capath){
+ _mosquitto_free(mosq->tls_capath);
+ mosq->tls_capath = NULL;
+ }
+ return MOSQ_ERR_INVAL;
+ }
+ mosq->tls_certfile = _mosquitto_strdup(certfile);
+ if(!mosq->tls_certfile){
+ return MOSQ_ERR_NOMEM;
+ }
+ }else{
+ if(mosq->tls_certfile) _mosquitto_free(mosq->tls_certfile);
+ mosq->tls_certfile = NULL;
+ }
+
+ if(keyfile){
+ fptr = _mosquitto_fopen(keyfile, "rt");
+ if(fptr){
+ fclose(fptr);
+ }else{
+ if(mosq->tls_cafile){
+ _mosquitto_free(mosq->tls_cafile);
+ mosq->tls_cafile = NULL;
+ }
+ if(mosq->tls_capath){
+ _mosquitto_free(mosq->tls_capath);
+ mosq->tls_capath = NULL;
+ }
+ if(mosq->tls_certfile){
+ _mosquitto_free(mosq->tls_certfile);
+ mosq->tls_certfile = NULL;
+ }
+ return MOSQ_ERR_INVAL;
+ }
+ mosq->tls_keyfile = _mosquitto_strdup(keyfile);
+ if(!mosq->tls_keyfile){
+ return MOSQ_ERR_NOMEM;
+ }
+ }else{
+ if(mosq->tls_keyfile) _mosquitto_free(mosq->tls_keyfile);
+ mosq->tls_keyfile = NULL;
+ }
+
+ mosq->tls_pw_callback = pw_callback;
+
+
+ return MOSQ_ERR_SUCCESS;
+#else
+ return MOSQ_ERR_NOT_SUPPORTED;
+
+#endif
+}
+
+int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers)
+{
+#ifdef WITH_TLS
+ if(!mosq) return MOSQ_ERR_INVAL;
+
+ mosq->tls_cert_reqs = cert_reqs;
+ if(tls_version){
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ if(!strcasecmp(tls_version, "tlsv1.2")
+ || !strcasecmp(tls_version, "tlsv1.1")
+ || !strcasecmp(tls_version, "tlsv1")){
+
+ mosq->tls_version = _mosquitto_strdup(tls_version);
+ if(!mosq->tls_version) return MOSQ_ERR_NOMEM;
+ }else{
+ return MOSQ_ERR_INVAL;
+ }
+#else
+ if(!strcasecmp(tls_version, "tlsv1")){
+ mosq->tls_version = _mosquitto_strdup(tls_version);
+ if(!mosq->tls_version) return MOSQ_ERR_NOMEM;
+ }else{
+ return MOSQ_ERR_INVAL;
+ }
+#endif
+ }else{
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ mosq->tls_version = _mosquitto_strdup("tlsv1.2");
+#else
+ mosq->tls_version = _mosquitto_strdup("tlsv1");
+#endif
+ if(!mosq->tls_version) return MOSQ_ERR_NOMEM;
+ }
+ if(ciphers){
+ mosq->tls_ciphers = _mosquitto_strdup(ciphers);
+ if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM;
+ }else{
+ mosq->tls_ciphers = NULL;
+ }
+
+
+ return MOSQ_ERR_SUCCESS;
+#else
+ return MOSQ_ERR_NOT_SUPPORTED;
+
+#endif
+}
+
+
+int mosquitto_tls_insecure_set(struct mosquitto *mosq, bool value)
+{
+#ifdef WITH_TLS
+ if(!mosq) return MOSQ_ERR_INVAL;
+ mosq->tls_insecure = value;
+ return MOSQ_ERR_SUCCESS;
+#else
+ return MOSQ_ERR_NOT_SUPPORTED;
+#endif
+}
+
+
+int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers)
+{
+#ifdef REAL_WITH_TLS_PSK
+ if(!mosq || !psk || !identity) return MOSQ_ERR_INVAL;
+
+ /* Check for hex only digits */
+ if(strspn(psk, "0123456789abcdefABCDEF") < strlen(psk)){
+ return MOSQ_ERR_INVAL;
+ }
+ mosq->tls_psk = _mosquitto_strdup(psk);
+ if(!mosq->tls_psk) return MOSQ_ERR_NOMEM;
+
+ mosq->tls_psk_identity = _mosquitto_strdup(identity);
+ if(!mosq->tls_psk_identity){
+ _mosquitto_free(mosq->tls_psk);
+ return MOSQ_ERR_NOMEM;
+ }
+ if(ciphers){
+ mosq->tls_ciphers = _mosquitto_strdup(ciphers);
+ if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM;
+ }else{
+ mosq->tls_ciphers = NULL;
+ }
+
+ return MOSQ_ERR_SUCCESS;
+#else
+ return MOSQ_ERR_NOT_SUPPORTED;
+#endif
+}
+
+
+int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets)
+{
+#ifdef HAVE_PSELECT
+ struct timespec local_timeout;
+#else
+ struct timeval local_timeout;
+#endif
+ fd_set readfds, writefds;
+ int fdcount;
+ int rc;
+ char pairbuf;
+ int maxfd = 0;
+
+ if(!mosq || max_packets < 1) return MOSQ_ERR_INVAL;
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ if(mosq->sock != INVALID_SOCKET){
+ maxfd = mosq->sock;
+ FD_SET(mosq->sock, &readfds);
+ pthread_mutex_lock(&mosq->current_out_packet_mutex);
+ pthread_mutex_lock(&mosq->out_packet_mutex);
+ if(mosq->out_packet || mosq->current_out_packet){
+ FD_SET(mosq->sock, &writefds);
+#ifdef WITH_TLS
+ }else if(mosq->ssl && mosq->want_write){
+ FD_SET(mosq->sock, &writefds);
+#endif
+ }
+ pthread_mutex_unlock(&mosq->out_packet_mutex);
+ pthread_mutex_unlock(&mosq->current_out_packet_mutex);
+ }else{
+#ifdef WITH_SRV
+ if(mosq->achan){
+ pthread_mutex_lock(&mosq->state_mutex);
+ if(mosq->state == mosq_cs_connect_srv){
+ rc = ares_fds(mosq->achan, &readfds, &writefds);
+ if(rc > maxfd){
+ maxfd = rc;
+ }
+ }else{
+ return MOSQ_ERR_NO_CONN;
+ }
+ pthread_mutex_unlock(&mosq->state_mutex);
+ }
+#else
+ return MOSQ_ERR_NO_CONN;
+#endif
+ }
+ if(mosq->sockpairR != INVALID_SOCKET){
+ /* sockpairR is used to break out of select() before the timeout, on a
+ * call to publish() etc. */
+ FD_SET(mosq->sockpairR, &readfds);
+ if(mosq->sockpairR > maxfd){
+ maxfd = mosq->sockpairR;
+ }
+ }
+
+ if(timeout >= 0){
+ local_timeout.tv_sec = timeout/1000;
+#ifdef HAVE_PSELECT
+ local_timeout.tv_nsec = (timeout-local_timeout.tv_sec*1000)*1e6;
+#else
+ local_timeout.tv_usec = (timeout-local_timeout.tv_sec*1000)*1000;
+#endif
+ }else{
+ local_timeout.tv_sec = 1;
+#ifdef HAVE_PSELECT
+ local_timeout.tv_nsec = 0;
+#else
+ local_timeout.tv_usec = 0;
+#endif
+ }
+
+#ifdef HAVE_PSELECT
+ fdcount = pselect(maxfd+1, &readfds, &writefds, NULL, &local_timeout, NULL);
+#else
+ fdcount = select(maxfd+1, &readfds, &writefds, NULL, &local_timeout);
+#endif
+ if(fdcount == -1){
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if(errno == EINTR){
+ return MOSQ_ERR_SUCCESS;
+ }else{
+ return MOSQ_ERR_ERRNO;
+ }
+ }else{
+ if(mosq->sock != INVALID_SOCKET){
+ if(FD_ISSET(mosq->sock, &readfds)){
+ rc = mosquitto_loop_read(mosq, max_packets);
+ if(rc || mosq->sock == INVALID_SOCKET){
+ return rc;
+ }
+ }
+ if(mosq->sockpairR >= 0 && FD_ISSET(mosq->sockpairR, &readfds)){
+#ifndef WIN32
+ if(read(mosq->sockpairR, &pairbuf, 1) == 0){
+ }
+#else
+ recv(mosq->sockpairR, &pairbuf, 1, 0);
+#endif
+ /* Fake write possible, to stimulate output write even though
+ * we didn't ask for it, because at that point the publish or
+ * other command wasn't present. */
+ FD_SET(mosq->sock, &writefds);
+ }
+ if(FD_ISSET(mosq->sock, &writefds)){
+ rc = mosquitto_loop_write(mosq, max_packets);
+ if(rc || mosq->sock == INVALID_SOCKET){
+ return rc;
+ }
+ }
+ }
+#ifdef WITH_SRV
+ if(mosq->achan){
+ ares_process(mosq->achan, &readfds, &writefds);
+ }
+#endif
+ }
+ return mosquitto_loop_misc(mosq);
+}
+
+int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets)
+{
+ int run = 1;
+ int rc;
+ unsigned int reconnects = 0;
+ unsigned long reconnect_delay;
+
+ if(!mosq) return MOSQ_ERR_INVAL;
+
+ if(mosq->state == mosq_cs_connect_async){
+ mosquitto_reconnect(mosq);
+ }
+
+ while(run){
+ do{
+ rc = mosquitto_loop(mosq, timeout, max_packets);
+ if (reconnects !=0 && rc == MOSQ_ERR_SUCCESS){
+ reconnects = 0;
+ }
+ }while(rc == MOSQ_ERR_SUCCESS);
+ if(errno == EPROTO){
+ return rc;
+ }
+ pthread_mutex_lock(&mosq->state_mutex);
+ if(mosq->state == mosq_cs_disconnecting){
+ run = 0;
+ pthread_mutex_unlock(&mosq->state_mutex);
+ }else{
+ pthread_mutex_unlock(&mosq->state_mutex);
+
+ if(mosq->reconnect_delay > 0 && mosq->reconnect_exponential_backoff){
+ reconnect_delay = mosq->reconnect_delay*reconnects*reconnects;
+ }else{
+ reconnect_delay = mosq->reconnect_delay;
+ }
+
+ if(reconnect_delay > mosq->reconnect_delay_max){
+ reconnect_delay = mosq->reconnect_delay_max;
+ }else{
+ reconnects++;
+ }
+
+#ifdef WIN32
+ Sleep(reconnect_delay*1000);
+#else
+ sleep(reconnect_delay);
+#endif
+
+ pthread_mutex_lock(&mosq->state_mutex);
+ if(mosq->state == mosq_cs_disconnecting){
+ run = 0;
+ pthread_mutex_unlock(&mosq->state_mutex);
+ }else{
+ pthread_mutex_unlock(&mosq->state_mutex);
+ mosquitto_reconnect(mosq);
+ }
+ }
+ }
+ return rc;
+}
+
+int mosquitto_loop_misc(struct mosquitto *mosq)
+{
+ time_t now;
+ int rc;
+
+ if(!mosq) return MOSQ_ERR_INVAL;
+ if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
+
+ now = mosquitto_time();
+
+ _mosquitto_check_keepalive(mosq);
+ if(mosq->last_retry_check+1 < now){
+ _mosquitto_message_retry_check(mosq);
+ mosq->last_retry_check = now;
+ }
+ if(mosq->ping_t && now - mosq->ping_t >= mosq->keepalive){
+ /* mosq->ping_t != 0 means we are waiting for a pingresp.
+ * This hasn't happened in the keepalive time so we should disconnect.
+ */
+ _mosquitto_socket_close(mosq);
+ pthread_mutex_lock(&mosq->state_mutex);
+ if(mosq->state == mosq_cs_disconnecting){
+ rc = MOSQ_ERR_SUCCESS;
+ }else{
+ rc = 1;
+ }
+ pthread_mutex_unlock(&mosq->state_mutex);
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_disconnect){
+ mosq->in_callback = true;
+ mosq->on_disconnect(mosq, mosq->userdata, rc);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+ return MOSQ_ERR_CONN_LOST;
+ }
+ return MOSQ_ERR_SUCCESS;
+}
+
+static int _mosquitto_loop_rc_handle(struct mosquitto *mosq, int rc)
+{
+ if(rc){
+ _mosquitto_socket_close(mosq);
+ pthread_mutex_lock(&mosq->state_mutex);
+ if(mosq->state == mosq_cs_disconnecting){
+ rc = MOSQ_ERR_SUCCESS;
+ }
+ pthread_mutex_unlock(&mosq->state_mutex);
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_disconnect){
+ mosq->in_callback = true;
+ mosq->on_disconnect(mosq, mosq->userdata, rc);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+ return rc;
+ }
+ return rc;
+}
+
+int mosquitto_loop_read(struct mosquitto *mosq, int max_packets)
+{
+ int rc;
+ int i;
+ if(max_packets < 1) return MOSQ_ERR_INVAL;
+
+ pthread_mutex_lock(&mosq->out_message_mutex);
+ max_packets = mosq->out_queue_len;
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+
+ pthread_mutex_lock(&mosq->in_message_mutex);
+ max_packets += mosq->in_queue_len;
+ pthread_mutex_unlock(&mosq->in_message_mutex);
+
+ if(max_packets < 1) max_packets = 1;
+ /* Queue len here tells us how many messages are awaiting processing and
+ * have QoS > 0. We should try to deal with that many in this loop in order
+ * to keep up. */
+ for(i=0; i<max_packets; i++){
+ rc = _mosquitto_packet_read(mosq);
+ if(rc || errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){
+ return _mosquitto_loop_rc_handle(mosq, rc);
+ }
+ }
+ return rc;
+}
+
+int mosquitto_loop_write(struct mosquitto *mosq, int max_packets)
+{
+ int rc;
+ int i;
+ if(max_packets < 1) return MOSQ_ERR_INVAL;
+
+ pthread_mutex_lock(&mosq->out_message_mutex);
+ max_packets = mosq->out_queue_len;
+ pthread_mutex_unlock(&mosq->out_message_mutex);
+
+ pthread_mutex_lock(&mosq->in_message_mutex);
+ max_packets += mosq->in_queue_len;
+ pthread_mutex_unlock(&mosq->in_message_mutex);
+
+ if(max_packets < 1) max_packets = 1;
+ /* Queue len here tells us how many messages are awaiting processing and
+ * have QoS > 0. We should try to deal with that many in this loop in order
+ * to keep up. */
+ for(i=0; i<max_packets; i++){
+ rc = _mosquitto_packet_write(mosq);
+ if(rc || errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){
+ return _mosquitto_loop_rc_handle(mosq, rc);
+ }
+ }
+ return rc;
+}
+
+bool mosquitto_want_write(struct mosquitto *mosq)
+{
+ if(mosq->out_packet || mosq->current_out_packet){
+ return true;
+#ifdef WITH_TLS
+ }else if(mosq->ssl && mosq->want_write){
+ return true;
+#endif
+ }else{
+ return false;
+ }
+}
+
+void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int))
+{
+ pthread_mutex_lock(&mosq->callback_mutex);
+ mosq->on_connect = on_connect;
+ pthread_mutex_unlock(&mosq->callback_mutex);
+}
+
+void mosquitto_disconnect_callback_set(struct mosquitto *mosq, void (*on_disconnect)(struct mosquitto *, void *, int))
+{
+ pthread_mutex_lock(&mosq->callback_mutex);
+ mosq->on_disconnect = on_disconnect;
+ pthread_mutex_unlock(&mosq->callback_mutex);
+}
+
+void mosquitto_publish_callback_set(struct mosquitto *mosq, void (*on_publish)(struct mosquitto *, void *, int))
+{
+ pthread_mutex_lock(&mosq->callback_mutex);
+ mosq->on_publish = on_publish;
+ pthread_mutex_unlock(&mosq->callback_mutex);
+}
+
+void mosquitto_message_callback_set(struct mosquitto *mosq, void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *))
+{
+ pthread_mutex_lock(&mosq->callback_mutex);
+ mosq->on_message = on_message;
+ pthread_mutex_unlock(&mosq->callback_mutex);
+}
+
+void mosquitto_subscribe_callback_set(struct mosquitto *mosq, void (*on_subscribe)(struct mosquitto *, void *, int, int, const int *))
+{
+ pthread_mutex_lock(&mosq->callback_mutex);
+ mosq->on_subscribe = on_subscribe;
+ pthread_mutex_unlock(&mosq->callback_mutex);
+}
+
+void mosquitto_unsubscribe_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(struct mosquitto *, void *, int))
+{
+ pthread_mutex_lock(&mosq->callback_mutex);
+ mosq->on_unsubscribe = on_unsubscribe;
+ pthread_mutex_unlock(&mosq->callback_mutex);
+}
+
+void mosquitto_log_callback_set(struct mosquitto *mosq, void (*on_log)(struct mosquitto *, void *, int, const char *))
+{
+ pthread_mutex_lock(&mosq->log_callback_mutex);
+ mosq->on_log = on_log;
+ pthread_mutex_unlock(&mosq->log_callback_mutex);
+}
+
+void mosquitto_user_data_set(struct mosquitto *mosq, void *userdata)
+{
+ if(mosq){
+ mosq->userdata = userdata;
+ }
+}
+
+const char *mosquitto_strerror(int mosq_errno)
+{
+ switch(mosq_errno){
+ case MOSQ_ERR_SUCCESS:
+ return "No error.";
+ case MOSQ_ERR_NOMEM:
+ return "Out of memory.";
+ case MOSQ_ERR_PROTOCOL:
+ return "A network protocol error occurred when communicating with the broker.";
+ case MOSQ_ERR_INVAL:
+ return "Invalid function arguments provided.";
+ case MOSQ_ERR_NO_CONN:
+ return "The client is not currently connected.";
+ case MOSQ_ERR_CONN_REFUSED:
+ return "The connection was refused.";
+ case MOSQ_ERR_NOT_FOUND:
+ return "Message not found (internal error).";
+ case MOSQ_ERR_CONN_LOST:
+ return "The connection was lost.";
+ case MOSQ_ERR_TLS:
+ return "A TLS error occurred.";
+ case MOSQ_ERR_PAYLOAD_SIZE:
+ return "Payload too large.";
+ case MOSQ_ERR_NOT_SUPPORTED:
+ return "This feature is not supported.";
+ case MOSQ_ERR_AUTH:
+ return "Authorisation failed.";
+ case MOSQ_ERR_ACL_DENIED:
+ return "Access denied by ACL.";
+ case MOSQ_ERR_UNKNOWN:
+ return "Unknown error.";
+ case MOSQ_ERR_ERRNO:
+ return strerror(errno);
+ default:
+ return "Unknown error.";
+ }
+}
+
+const char *mosquitto_connack_string(int connack_code)
+{
+ switch(connack_code){
+ case 0:
+ return "Connection Accepted.";
+ case 1:
+ return "Connection Refused: unacceptable protocol version.";
+ case 2:
+ return "Connection Refused: identifier rejected.";
+ case 3:
+ return "Connection Refused: broker unavailable.";
+ case 4:
+ return "Connection Refused: bad user name or password.";
+ case 5:
+ return "Connection Refused: not authorised.";
+ default:
+ return "Connection Refused: unknown reason.";
+ }
+}
+
+int mosquitto_sub_topic_tokenise(const char *subtopic, char ***topics, int *count)
+{
+ int len;
+ int hier_count = 1;
+ int start, stop;
+ int hier;
+ int tlen;
+ int i, j;
+
+ if(!subtopic || !topics || !count) return MOSQ_ERR_INVAL;
+
+ len = strlen(subtopic);
+
+ for(i=0; i<len; i++){
+ if(subtopic[i] == '/'){
+ if(i > len-1){
+ /* Separator at end of line */
+ }else{
+ hier_count++;
+ }
+ }
+ }
+
+ (*topics) = _mosquitto_calloc(hier_count, sizeof(char *));
+ if(!(*topics)) return MOSQ_ERR_NOMEM;
+
+ start = 0;
+ stop = 0;
+ hier = 0;
+
+ for(i=0; i<len+1; i++){
+ if(subtopic[i] == '/' || subtopic[i] == '\0'){
+ stop = i;
+ if(start != stop){
+ tlen = stop-start + 1;
+ (*topics)[hier] = _mosquitto_calloc(tlen, sizeof(char));
+ if(!(*topics)[hier]){
+ for(i=0; i<hier_count; i++){
+ if((*topics)[hier]){
+ _mosquitto_free((*topics)[hier]);
+ }
+ }
+ _mosquitto_free((*topics));
+ return MOSQ_ERR_NOMEM;
+ }
+ for(j=start; j<stop; j++){
+ (*topics)[hier][j-start] = subtopic[j];
+ }
+ }
+ start = i+1;
+ hier++;
+ }
+ }
+
+ *count = hier_count;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+int mosquitto_sub_topic_tokens_free(char ***topics, int count)
+{
+ int i;
+
+ if(!topics || !(*topics) || count<1) return MOSQ_ERR_INVAL;
+
+ for(i=0; i<count; i++){
+ if((*topics)[i]) _mosquitto_free((*topics)[i]);
+ }
+ _mosquitto_free(*topics);
+
+ return MOSQ_ERR_SUCCESS;
+}
+
--- /dev/null
+/*
+Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+This product includes software developed by the OpenSSL Project for use in the
+OpenSSL Toolkit. (http://www.openssl.org/)
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com)
+This product includes software written by Tim Hudson (tjh@cryptsoft.com)
+*/
+
+#ifndef _MOSQUITTO_H_
+#define _MOSQUITTO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(WIN32) && !defined(WITH_BROKER)
+# ifdef libmosquitto_EXPORTS
+# define libmosq_EXPORT __declspec(dllexport)
+# else
+# define libmosq_EXPORT __declspec(dllimport)
+# endif
+#else
+# define libmosq_EXPORT
+#endif
+
+#ifdef WIN32
+# ifndef __cplusplus
+# define bool char
+# define true 1
+# define false 0
+# endif
+#else
+# ifndef __cplusplus
+# include <stdbool.h>
+# endif
+#endif
+
+#define LIBMOSQUITTO_MAJOR 1
+#define LIBMOSQUITTO_MINOR 3
+#define LIBMOSQUITTO_REVISION 1
+/* LIBMOSQUITTO_VERSION_NUMBER looks like 1002001 for e.g. version 1.2.1. */
+#define LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION)
+
+/* Log types */
+#define MOSQ_LOG_NONE 0x00
+#define MOSQ_LOG_INFO 0x01
+#define MOSQ_LOG_NOTICE 0x02
+#define MOSQ_LOG_WARNING 0x04
+#define MOSQ_LOG_ERR 0x08
+#define MOSQ_LOG_DEBUG 0x10
+#define MOSQ_LOG_SUBSCRIBE 0x20
+#define MOSQ_LOG_UNSUBSCRIBE 0x40
+#define MOSQ_LOG_ALL 0xFFFF
+
+/* Error values */
+enum mosq_err_t {
+ MOSQ_ERR_CONN_PENDING = -1,
+ MOSQ_ERR_SUCCESS = 0,
+ MOSQ_ERR_NOMEM = 1,
+ MOSQ_ERR_PROTOCOL = 2,
+ MOSQ_ERR_INVAL = 3,
+ MOSQ_ERR_NO_CONN = 4,
+ MOSQ_ERR_CONN_REFUSED = 5,
+ MOSQ_ERR_NOT_FOUND = 6,
+ MOSQ_ERR_CONN_LOST = 7,
+ MOSQ_ERR_TLS = 8,
+ MOSQ_ERR_PAYLOAD_SIZE = 9,
+ MOSQ_ERR_NOT_SUPPORTED = 10,
+ MOSQ_ERR_AUTH = 11,
+ MOSQ_ERR_ACL_DENIED = 12,
+ MOSQ_ERR_UNKNOWN = 13,
+ MOSQ_ERR_ERRNO = 14,
+ MOSQ_ERR_EAI = 15
+};
+
+/* MQTT specification restricts client ids to a maximum of 23 characters */
+#define MOSQ_MQTT_ID_MAX_LENGTH 23
+
+struct mosquitto_message{
+ int mid;
+ char *topic;
+ void *payload;
+ int payloadlen;
+ int qos;
+ bool retain;
+};
+
+struct mosquitto;
+
+/*
+ * Topic: Threads
+ * libmosquitto provides thread safe operation, with the exception of
+ * <mosquitto_lib_init> which is not thread safe.
+ */
+/***************************************************
+ * Important note
+ *
+ * The following functions that deal with network operations will return
+ * MOSQ_ERR_SUCCESS on success, but this does not mean that the operation has
+ * taken place. An attempt will be made to write the network data, but if the
+ * socket is not available for writing at that time then the packet will not be
+ * sent. To ensure the packet is sent, call mosquitto_loop() (which must also
+ * be called to process incoming network data).
+ * This is especially important when disconnecting a client that has a will. If
+ * the broker does not receive the DISCONNECT command, it will assume that the
+ * client has disconnected unexpectedly and send the will.
+ *
+ * mosquitto_connect()
+ * mosquitto_disconnect()
+ * mosquitto_subscribe()
+ * mosquitto_unsubscribe()
+ * mosquitto_publish()
+ ***************************************************/
+
+/*
+ * Function: mosquitto_lib_version
+ *
+ * Can be used to obtain version information for the mosquitto library.
+ * This allows the application to compare the library version against the
+ * version it was compiled against by using the LIBMOSQUITTO_MAJOR,
+ * LIBMOSQUITTO_MINOR and LIBMOSQUITTO_REVISION defines.
+ *
+ * Parameters:
+ * major - an integer pointer. If not NULL, the major version of the
+ * library will be returned in this variable.
+ * minor - an integer pointer. If not NULL, the minor version of the
+ * library will be returned in this variable.
+ * revision - an integer pointer. If not NULL, the revision of the library will
+ * be returned in this variable.
+ *
+ * Returns:
+ * LIBMOSQUITTO_VERSION_NUMBER, which is a unique number based on the major,
+ * minor and revision values.
+ * See Also:
+ * <mosquitto_lib_cleanup>, <mosquitto_lib_init>
+ */
+libmosq_EXPORT int mosquitto_lib_version(int *major, int *minor, int *revision);
+
+/*
+ * Function: mosquitto_lib_init
+ *
+ * Must be called before any other mosquitto functions.
+ *
+ * This function is *not* thread safe.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - always
+ *
+ * See Also:
+ * <mosquitto_lib_cleanup>, <mosquitto_lib_version>
+ */
+libmosq_EXPORT int mosquitto_lib_init(void);
+
+/*
+ * Function: mosquitto_lib_cleanup
+ *
+ * Call to free resources associated with the library.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - always
+ *
+ * See Also:
+ * <mosquitto_lib_init>, <mosquitto_lib_version>
+ */
+libmosq_EXPORT int mosquitto_lib_cleanup(void);
+
+/*
+ * Function: mosquitto_new
+ *
+ * Create a new mosquitto client instance.
+ *
+ * Parameters:
+ * id - String to use as the client id. If NULL, a random client id
+ * will be generated. If id is NULL, clean_session must be true.
+ * clean_session - set to true to instruct the broker to clean all messages
+ * and subscriptions on disconnect, false to instruct it to
+ * keep them. See the man page mqtt(7) for more details.
+ * Note that a client will never discard its own outgoing
+ * messages on disconnect. Calling <mosquitto_connect> or
+ * <mosquitto_reconnect> will cause the messages to be resent.
+ * Use <mosquitto_reinitialise> to reset a client to its
+ * original state.
+ * Must be set to true if the id parameter is NULL.
+ * obj - A user pointer that will be passed as an argument to any
+ * callbacks that are specified.
+ *
+ * Returns:
+ * Pointer to a struct mosquitto on success.
+ * NULL on failure. Interrogate errno to determine the cause for the failure:
+ * - ENOMEM on out of memory.
+ * - EINVAL on invalid input parameters.
+ *
+ * See Also:
+ * <mosquitto_reinitialise>, <mosquitto_destroy>, <mosquitto_user_data_set>
+ */
+libmosq_EXPORT struct mosquitto *mosquitto_new(const char *id, bool clean_session, void *obj);
+
+/*
+ * Function: mosquitto_destroy
+ *
+ * Use to free memory associated with a mosquitto client instance.
+ *
+ * Parameters:
+ * mosq - a struct mosquitto pointer to free.
+ *
+ * See Also:
+ * <mosquitto_new>, <mosquitto_reinitialise>
+ */
+libmosq_EXPORT void mosquitto_destroy(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_reinitialise
+ *
+ * This function allows an existing mosquitto client to be reused. Call on a
+ * mosquitto instance to close any open network connections, free memory
+ * and reinitialise the client with the new parameters. The end result is the
+ * same as the output of <mosquitto_new>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * id - string to use as the client id. If NULL, a random client id
+ * will be generated. If id is NULL, clean_session must be true.
+ * clean_session - set to true to instruct the broker to clean all messages
+ * and subscriptions on disconnect, false to instruct it to
+ * keep them. See the man page mqtt(7) for more details.
+ * Must be set to true if the id parameter is NULL.
+ * obj - A user pointer that will be passed as an argument to any
+ * callbacks that are specified.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ *
+ * See Also:
+ * <mosquitto_new>, <mosquitto_destroy>
+ */
+libmosq_EXPORT int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_session, void *obj);
+
+/*
+ * Function: mosquitto_will_set
+ *
+ * Configure will information for a mosquitto instance. By default, clients do
+ * not have a will. This must be called before calling <mosquitto_connect>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * topic - the topic on which to publish the will.
+ * payloadlen - the size of the payload (bytes). Valid values are between 0 and
+ * 268,435,455.
+ * payload - pointer to the data to send. If payloadlen > 0 this must be a
+ * valid memory location.
+ * qos - integer value 0, 1 or 2 indicating the Quality of Service to be
+ * used for the will.
+ * retain - set to true to make the will a retained message.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ * MOSQ_ERR_PAYLOAD_SIZE - if payloadlen is too large.
+ */
+libmosq_EXPORT int mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain);
+
+/*
+ * Function: mosquitto_will_clear
+ *
+ * Remove a previously configured will. This must be called before calling
+ * <mosquitto_connect>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ */
+libmosq_EXPORT int mosquitto_will_clear(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_username_pw_set
+ *
+ * Configure username and password for a mosquitton instance. This is only
+ * supported by brokers that implement the MQTT spec v3.1. By default, no
+ * username or password will be sent.
+ * If username is NULL, the password argument is ignored.
+ * This must be called before calling mosquitto_connect().
+ *
+ * This is must be called before calling <mosquitto_connect>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * username - the username to send as a string, or NULL to disable
+ * authentication.
+ * password - the password to send as a string. Set to NULL when username is
+ * valid in order to send just a username.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ */
+libmosq_EXPORT int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password);
+
+/*
+ * Function: mosquitto_connect
+ *
+ * Connect to an MQTT broker.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * host - the hostname or ip address of the broker to connect to.
+ * port - the network port to connect to. Usually 1883.
+ * keepalive - the number of seconds after which the broker should send a PING
+ * message to the client if no other messages have been exchanged
+ * in that time.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ *
+ * See Also:
+ * <mosquitto_connect_bind>, <mosquitto_connect_async>, <mosquitto_reconnect>, <mosquitto_disconnect>, <mosquitto_tls_set>
+ */
+libmosq_EXPORT int mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive);
+
+/*
+ * Function: mosquitto_connect_bind
+ *
+ * Connect to an MQTT broker. This extends the functionality of
+ * <mosquitto_connect> by adding the bind_address parameter. Use this function
+ * if you need to restrict network communication over a particular interface.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * host - the hostname or ip address of the broker to connect to.
+ * port - the network port to connect to. Usually 1883.
+ * keepalive - the number of seconds after which the broker should send a PING
+ * message to the client if no other messages have been exchanged
+ * in that time.
+ * bind_address - the hostname or ip address of the local network interface to
+ * bind to.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ *
+ * See Also:
+ * <mosquitto_connect>, <mosquitto_connect_async>, <mosquitto_connect_bind_async>
+ */
+libmosq_EXPORT int mosquitto_connect_bind(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address);
+
+/*
+ * Function: mosquitto_connect_async
+ *
+ * Connect to an MQTT broker. This is a non-blocking call. If you use
+ * <mosquitto_connect_async> your client must use the threaded interface
+ * <mosquitto_loop_start>. If you need to use <mosquitto_loop>, you must use
+ * <mosquitto_connect> to connect the client.
+ *
+ * May be called before or after <mosquitto_loop_start>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * host - the hostname or ip address of the broker to connect to.
+ * port - the network port to connect to. Usually 1883.
+ * keepalive - the number of seconds after which the broker should send a PING
+ * message to the client if no other messages have been exchanged
+ * in that time.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ *
+ * See Also:
+ * <mosquitto_connect_bind_async>, <mosquitto_connect>, <mosquitto_reconnect>, <mosquitto_disconnect>, <mosquitto_tls_set>
+ */
+libmosq_EXPORT int mosquitto_connect_async(struct mosquitto *mosq, const char *host, int port, int keepalive);
+
+/*
+ * Function: mosquitto_connect_async
+ *
+ * Connect to an MQTT broker. This is a non-blocking call. If you use
+ * <mosquitto_connect_async> your client must use the threaded interface
+ * <mosquitto_loop_start>. If you need to use <mosquitto_loop>, you must use
+ * <mosquitto_connect> to connect the client.
+ *
+ * This extends the functionality of <mosquitto_connect_async> by adding the
+ * bind_address parameter. Use this function if you need to restrict network
+ * communication over a particular interface.
+ *
+ * May be called before or after <mosquitto_loop_start>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * host - the hostname or ip address of the broker to connect to.
+ * port - the network port to connect to. Usually 1883.
+ * keepalive - the number of seconds after which the broker should send a PING
+ * message to the client if no other messages have been exchanged
+ * in that time.
+ * bind_address - the hostname or ip address of the local network interface to
+ * bind to.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ *
+ * See Also:
+ * <mosquitto_connect_async>, <mosquitto_connect>, <mosquitto_connect_bind>
+ */
+libmosq_EXPORT int mosquitto_connect_bind_async(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address);
+
+/*
+ * Function: mosquitto_connect_srv
+ *
+ * Connect to an MQTT broker. This is a non-blocking call. If you use
+ * <mosquitto_connect_async> your client must use the threaded interface
+ * <mosquitto_loop_start>. If you need to use <mosquitto_loop>, you must use
+ * <mosquitto_connect> to connect the client.
+ *
+ * This extends the functionality of <mosquitto_connect_async> by adding the
+ * bind_address parameter. Use this function if you need to restrict network
+ * communication over a particular interface.
+ *
+ * May be called before or after <mosquitto_loop_start>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * host - the hostname or ip address of the broker to connect to.
+ * keepalive - the number of seconds after which the broker should send a PING
+ * message to the client if no other messages have been exchanged
+ * in that time.
+ * bind_address - the hostname or ip address of the local network interface to
+ * bind to.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ *
+ * See Also:
+ * <mosquitto_connect_async>, <mosquitto_connect>, <mosquitto_connect_bind>
+ */
+libmosq_EXPORT int mosquitto_connect_srv(struct mosquitto *mosq, const char *host, int keepalive, const char *bind_address);
+
+/*
+ * Function: mosquitto_reconnect
+ *
+ * Reconnect to a broker.
+ *
+ * This function provides an easy way of reconnecting to a broker after a
+ * connection has been lost. It uses the values that were provided in the
+ * <mosquitto_connect> call. It must not be called before
+ * <mosquitto_connect>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ *
+ * See Also:
+ * <mosquitto_connect>, <mosquitto_disconnect>, <mosquitto_reconnect_async>
+ */
+libmosq_EXPORT int mosquitto_reconnect(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_reconnect_async
+ *
+ * Reconnect to a broker. Non blocking version of <mosquitto_reconnect>.
+ *
+ * This function provides an easy way of reconnecting to a broker after a
+ * connection has been lost. It uses the values that were provided in the
+ * <mosquitto_connect> or <mosquitto_connect_async> calls. It must not be
+ * called before <mosquitto_connect>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ *
+ * See Also:
+ * <mosquitto_connect>, <mosquitto_disconnect>
+ */
+libmosq_EXPORT int mosquitto_reconnect_async(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_disconnect
+ *
+ * Disconnect from the broker.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
+ */
+libmosq_EXPORT int mosquitto_disconnect(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_publish
+ *
+ * Publish a message on a given topic.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * mid - pointer to an int. If not NULL, the function will set this
+ * to the message id of this particular message. This can be then
+ * used with the publish callback to determine when the message
+ * has been sent.
+ * Note that although the MQTT protocol doesn't use message ids
+ * for messages with QoS=0, libmosquitto assigns them message ids
+ * so they can be tracked with this parameter.
+ * payloadlen - the size of the payload (bytes). Valid values are between 0 and
+ * 268,435,455.
+ * payload - pointer to the data to send. If payloadlen > 0 this must be a
+ * valid memory location.
+ * qos - integer value 0, 1 or 2 indicating the Quality of Service to be
+ * used for the message.
+ * retain - set to true to make the message retained.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
+ * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the
+ * broker.
+ * MOSQ_ERR_PAYLOAD_SIZE - if payloadlen is too large.
+ *
+ * See Also:
+ * <mosquitto_max_inflight_messages_set>
+ */
+libmosq_EXPORT int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain);
+
+/*
+ * Function: mosquitto_subscribe
+ *
+ * Subscribe to a topic.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * mid - a pointer to an int. If not NULL, the function will set this to
+ * the message id of this particular message. This can be then used
+ * with the subscribe callback to determine when the message has been
+ * sent.
+ * sub - the subscription pattern.
+ * qos - the requested Quality of Service for this subscription.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
+ */
+libmosq_EXPORT int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int qos);
+
+/*
+ * Function: mosquitto_unsubscribe
+ *
+ * Unsubscribe from a topic.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * mid - a pointer to an int. If not NULL, the function will set this to
+ * the message id of this particular message. This can be then used
+ * with the unsubscribe callback to determine when the message has been
+ * sent.
+ * sub - the unsubscription pattern.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
+ */
+libmosq_EXPORT int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const char *sub);
+
+/*
+ * Function: mosquitto_message_copy
+ *
+ * Copy the contents of a mosquitto message to another message.
+ * Useful for preserving a message received in the on_message() callback.
+ *
+ * Parameters:
+ * dst - a pointer to a valid mosquitto_message struct to copy to.
+ * src - a pointer to a valid mosquitto_message struct to copy from.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ *
+ * See Also:
+ * <mosquitto_message_free>
+ */
+libmosq_EXPORT int mosquitto_message_copy(struct mosquitto_message *dst, const struct mosquitto_message *src);
+
+/*
+ * Function: mosquitto_message_free
+ *
+ * Completely free a mosquitto_message struct.
+ *
+ * Parameters:
+ * message - pointer to a mosquitto_message pointer to free.
+ *
+ * See Also:
+ * <mosquitto_message_copy>
+ */
+libmosq_EXPORT void mosquitto_message_free(struct mosquitto_message **message);
+
+/*
+ * Function: mosquitto_loop
+ *
+ * The main network loop for the client. You must call this frequently in order
+ * to keep communications between the client and broker working. If incoming
+ * data is present it will then be processed. Outgoing commands, from e.g.
+ * <mosquitto_publish>, are normally sent immediately that their function is
+ * called, but this is not always possible. <mosquitto_loop> will also attempt
+ * to send any remaining outgoing messages, which also includes commands that
+ * are part of the flow for messages with QoS>0.
+ *
+ * An alternative approach is to use <mosquitto_loop_start> to run the client
+ * loop in its own thread.
+ *
+ * This calls select() to monitor the client network socket. If you want to
+ * integrate mosquitto client operation with your own select() call, use
+ * <mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_write> and
+ * <mosquitto_loop_misc>.
+ *
+ * Threads:
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * timeout - Maximum number of milliseconds to wait for network activity
+ * in the select() call before timing out. Set to 0 for instant
+ * return. Set negative to use the default of 1000ms.
+ * max_packets - this parameter is currently unused and should be set to 1 for
+ * future compatibility.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
+ * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost.
+ * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the
+ * broker.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ * See Also:
+ * <mosquitto_loop_forever>, <mosquitto_loop_start>, <mosquitto_loop_stop>
+ */
+libmosq_EXPORT int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets);
+
+/*
+ * Function: mosquitto_loop_forever
+ *
+ * This function call loop() for you in an infinite blocking loop. It is useful
+ * for the case where you only want to run the MQTT client loop in your
+ * program.
+ *
+ * It handles reconnecting in case server connection is lost. If you call
+ * mosquitto_disconnect() in a callback it will return.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * timeout - Maximum number of milliseconds to wait for network activity
+ * in the select() call before timing out. Set to 0 for instant
+ * return. Set negative to use the default of 1000ms.
+ * max_packets - this parameter is currently unused and should be set to 1 for
+ * future compatibility.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
+ * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost.
+ * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the
+ * broker.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ *
+ * See Also:
+ * <mosquitto_loop>, <mosquitto_loop_start>
+ */
+libmosq_EXPORT int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets);
+
+/*
+ * Function: mosquitto_loop_start
+ *
+ * This is part of the threaded client interface. Call this once to start a new
+ * thread to process network traffic. This provides an alternative to
+ * repeatedly calling <mosquitto_loop> yourself.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOT_SUPPORTED - if thread support is not available.
+ *
+ * See Also:
+ * <mosquitto_connect_async>, <mosquitto_loop>, <mosquitto_loop_forever>, <mosquitto_loop_stop>
+ */
+libmosq_EXPORT int mosquitto_loop_start(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_loop_stop
+ *
+ * This is part of the threaded client interface. Call this once to stop the
+ * network thread previously created with <mosquitto_loop_start>. This call
+ * will block until the network thread finishes. For the network thread to end,
+ * you must have previously called <mosquitto_disconnect> or have set the force
+ * parameter to true.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * force - set to true to force thread cancellation. If false,
+ * <mosquitto_disconnect> must have already been called.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOT_SUPPORTED - if thread support is not available.
+ *
+ * See Also:
+ * <mosquitto_loop>, <mosquitto_loop_start>
+ */
+libmosq_EXPORT int mosquitto_loop_stop(struct mosquitto *mosq, bool force);
+
+/*
+ * Function: mosquitto_socket
+ *
+ * Return the socket handle for a mosquitto instance. Useful if you want to
+ * include a mosquitto client in your own select() calls.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ * The socket for the mosquitto client or -1 on failure.
+ */
+libmosq_EXPORT int mosquitto_socket(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_loop_read
+ *
+ * Carry out network read operations.
+ * This should only be used if you are not using mosquitto_loop() and are
+ * monitoring the client network socket for activity yourself.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * max_packets - this parameter is currently unused and should be set to 1 for
+ * future compatibility.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
+ * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost.
+ * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the
+ * broker.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ *
+ * See Also:
+ * <mosquitto_socket>, <mosquitto_loop_write>, <mosquitto_loop_misc>
+ */
+libmosq_EXPORT int mosquitto_loop_read(struct mosquitto *mosq, int max_packets);
+
+/*
+ * Function: mosquitto_loop_write
+ *
+ * Carry out network write operations.
+ * This should only be used if you are not using mosquitto_loop() and are
+ * monitoring the client network socket for activity yourself.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * max_packets - this parameter is currently unused and should be set to 1 for
+ * future compatibility.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
+ * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost.
+ * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the
+ * broker.
+ * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno
+ * contains the error code, even on Windows.
+ * Use strerror_r() where available or FormatMessage() on
+ * Windows.
+ *
+ * See Also:
+ * <mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_misc>, <mosquitto_want_write>
+ */
+libmosq_EXPORT int mosquitto_loop_write(struct mosquitto *mosq, int max_packets);
+
+/*
+ * Function: mosquitto_loop_misc
+ *
+ * Carry out miscellaneous operations required as part of the network loop.
+ * This should only be used if you are not using mosquitto_loop() and are
+ * monitoring the client network socket for activity yourself.
+ *
+ * This function deals with handling PINGs and checking whether messages need
+ * to be retried, so should be called fairly frequently.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker.
+ *
+ * See Also:
+ * <mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_write>
+ */
+libmosq_EXPORT int mosquitto_loop_misc(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_want_write
+ *
+ * Returns true if there is data ready to be written on the socket.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ *
+ * See Also:
+ * <mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_write>
+ */
+libmosq_EXPORT bool mosquitto_want_write(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_tls_set
+ *
+ * Configure the client for certificate based SSL/TLS support. Must be called
+ * before <mosquitto_connect>.
+ *
+ * Cannot be used in conjunction with <mosquitto_tls_psk_set>.
+ *
+ * Define the Certificate Authority certificates to be trusted (ie. the server
+ * certificate must be signed with one of these certificates) using cafile.
+ *
+ * If the server you are connecting to requires clients to provide a
+ * certificate, define certfile and keyfile with your client certificate and
+ * private key. If your private key is encrypted, provide a password callback
+ * function or you will have to enter the password at the command line.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * cafile - path to a file containing the PEM encoded trusted CA
+ * certificate files. Either cafile or capath must not be NULL.
+ * capath - path to a directory containing the PEM encoded trusted CA
+ * certificate files. See mosquitto.conf for more details on
+ * configuring this directory. Either cafile or capath must not
+ * be NULL.
+ * certfile - path to a file containing the PEM encoded certificate file
+ * for this client. If NULL, keyfile must also be NULL and no
+ * client certificate will be used.
+ * keyfile - path to a file containing the PEM encoded private key for
+ * this client. If NULL, certfile must also be NULL and no
+ * client certificate will be used.
+ * pw_callback - if keyfile is encrypted, set pw_callback to allow your client
+ * to pass the correct password for decryption. If set to NULL,
+ * the password must be entered on the command line.
+ * Your callback must write the password into "buf", which is
+ * "size" bytes long. The return value must be the length of the
+ * password. "userdata" will be set to the calling mosquitto
+ * instance.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ *
+ * See Also:
+ * <mosquitto_tls_opts_set>, <mosquitto_tls_psk_set>, <mosquitto_tls_insecure_set>
+ */
+libmosq_EXPORT 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));
+
+/*
+ * Function: mosquitto_tls_insecure_set
+ *
+ * Configure verification of the server hostname in the server certificate. If
+ * value is set to true, it is impossible to guarantee that the host you are
+ * connecting to is not impersonating your server. This can be useful in
+ * initial server testing, but makes it possible for a malicious third party to
+ * impersonate your server through DNS spoofing, for example.
+ * Do not use this function in a real system. Setting value to true makes the
+ * connection encryption pointless.
+ * Must be called before <mosquitto_connect>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * value - if set to false, the default, certificate hostname checking is
+ * performed. If set to true, no hostname checking is performed and
+ * the connection is insecure.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ *
+ * See Also:
+ * <mosquitto_tls_set>
+ */
+libmosq_EXPORT int mosquitto_tls_insecure_set(struct mosquitto *mosq, bool value);
+
+/*
+ * Function: mosquitto_tls_opts_set
+ *
+ * Set advanced SSL/TLS options. Must be called before <mosquitto_connect>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * cert_reqs - an integer defining the verification requirements the client
+ * will impose on the server. This can be one of:
+ * * SSL_VERIFY_NONE (0): the server will not be verified in any way.
+ * * SSL_VERIFY_PEER (1): the server certificate will be verified
+ * and the connection aborted if the verification fails.
+ * The default and recommended value is SSL_VERIFY_PEER. Using
+ * SSL_VERIFY_NONE provides no security.
+ * tls_version - the version of the SSL/TLS protocol to use as a string. If NULL,
+ * the default value is used. The default value and the
+ * available values depend on the version of openssl that the
+ * library was compiled against. For openssl >= 1.0.1, the
+ * available options are tlsv1.2, tlsv1.1 and tlsv1, with tlv1.2
+ * as the default. For openssl < 1.0.1, only tlsv1 is available.
+ * ciphers - a string describing the ciphers available for use. See the
+ * "openssl ciphers" tool for more information. If NULL, the
+ * default ciphers will be used.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ *
+ * See Also:
+ * <mosquitto_tls_set>
+ */
+libmosq_EXPORT int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers);
+
+/*
+ * Function: mosquitto_tls_psk_set
+ *
+ * Configure the client for pre-shared-key based TLS support. Must be called
+ * before <mosquitto_connect>.
+ *
+ * Cannot be used in conjunction with <mosquitto_tls_set>.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * psk - the pre-shared-key in hex format with no leading "0x".
+ * identity - the identity of this client. May be used as the username
+ * depending on the server settings.
+ * ciphers - a string describing the PSK ciphers available for use. See the
+ * "openssl ciphers" tool for more information. If NULL, the
+ * default ciphers will be used.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ *
+ * See Also:
+ * <mosquitto_tls_set>
+ */
+libmosq_EXPORT int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers);
+
+/*
+ * Function: mosquitto_connect_callback_set
+ *
+ * Set the connect callback. This is called when the broker sends a CONNACK
+ * message in response to a connection.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * on_connect - a callback function in the following form:
+ * void callback(struct mosquitto *mosq, void *obj, int rc)
+ *
+ * Callback Parameters:
+ * mosq - the mosquitto instance making the callback.
+ * obj - the user data provided in <mosquitto_new>
+ * rc - the return code of the connection response, one of:
+ *
+ * * 0 - success
+ * * 1 - connection refused (unacceptable protocol version)
+ * * 2 - connection refused (identifier rejected)
+ * * 3 - connection refused (broker unavailable)
+ * * 4-255 - reserved for future use
+ */
+libmosq_EXPORT void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int));
+
+/*
+ * Function: mosquitto_disconnect_callback_set
+ *
+ * Set the disconnect callback. This is called when the broker has received the
+ * DISCONNECT command and has disconnected the client.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * on_disconnect - a callback function in the following form:
+ * void callback(struct mosquitto *mosq, void *obj)
+ *
+ * Callback Parameters:
+ * mosq - the mosquitto instance making the callback.
+ * obj - the user data provided in <mosquitto_new>
+ * rc - integer value indicating the reason for the disconnect. A value of 0
+ * means the client has called <mosquitto_disconnect>. Any other value
+ * indicates that the disconnect is unexpected.
+ */
+libmosq_EXPORT void mosquitto_disconnect_callback_set(struct mosquitto *mosq, void (*on_disconnect)(struct mosquitto *, void *, int));
+
+/*
+ * Function: mosquitto_publish_callback_set
+ *
+ * Set the publish callback. This is called when a message initiated with
+ * <mosquitto_publish> has been sent to the broker successfully.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * on_publish - a callback function in the following form:
+ * void callback(struct mosquitto *mosq, void *obj, int mid)
+ *
+ * Callback Parameters:
+ * mosq - the mosquitto instance making the callback.
+ * obj - the user data provided in <mosquitto_new>
+ * mid - the message id of the sent message.
+ */
+libmosq_EXPORT void mosquitto_publish_callback_set(struct mosquitto *mosq, void (*on_publish)(struct mosquitto *, void *, int));
+
+/*
+ * Function: mosquitto_message_callback_set
+ *
+ * Set the message callback. This is called when a message is received from the
+ * broker.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * on_message - a callback function in the following form:
+ * void callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
+ *
+ * Callback Parameters:
+ * mosq - the mosquitto instance making the callback.
+ * obj - the user data provided in <mosquitto_new>
+ * message - the message data. This variable and associated memory will be
+ * freed by the library after the callback completes. The client
+ * should make copies of any of the data it requires.
+ *
+ * See Also:
+ * <mosquitto_message_copy>
+ */
+libmosq_EXPORT void mosquitto_message_callback_set(struct mosquitto *mosq, void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *));
+
+/*
+ * Function: mosquitto_subscribe_callback_set
+ *
+ * Set the subscribe callback. This is called when the broker responds to a
+ * subscription request.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * on_subscribe - a callback function in the following form:
+ * void callback(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
+ *
+ * Callback Parameters:
+ * mosq - the mosquitto instance making the callback.
+ * obj - the user data provided in <mosquitto_new>
+ * mid - the message id of the subscribe message.
+ * qos_count - the number of granted subscriptions (size of granted_qos).
+ * granted_qos - an array of integers indicating the granted QoS for each of
+ * the subscriptions.
+ */
+libmosq_EXPORT void mosquitto_subscribe_callback_set(struct mosquitto *mosq, void (*on_subscribe)(struct mosquitto *, void *, int, int, const int *));
+
+/*
+ * Function: mosquitto_unsubscribe_callback_set
+ *
+ * Set the unsubscribe callback. This is called when the broker responds to a
+ * unsubscription request.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * on_unsubscribe - a callback function in the following form:
+ * void callback(struct mosquitto *mosq, void *obj, int mid)
+ *
+ * Callback Parameters:
+ * mosq - the mosquitto instance making the callback.
+ * obj - the user data provided in <mosquitto_new>
+ * mid - the message id of the unsubscribe message.
+ */
+libmosq_EXPORT void mosquitto_unsubscribe_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(struct mosquitto *, void *, int));
+
+/*
+ * Function: mosquitto_log_callback_set
+ *
+ * Set the logging callback. This should be used if you want event logging
+ * information from the client library.
+ *
+ * mosq - a valid mosquitto instance.
+ * on_log - a callback function in the following form:
+ * void callback(struct mosquitto *mosq, void *obj, int level, const char *str)
+ *
+ * Callback Parameters:
+ * mosq - the mosquitto instance making the callback.
+ * obj - the user data provided in <mosquitto_new>
+ * level - the log message level from the values:
+ * MOSQ_LOG_INFO
+ * MOSQ_LOG_NOTICE
+ * MOSQ_LOG_WARNING
+ * MOSQ_LOG_ERR
+ * MOSQ_LOG_DEBUG
+ * str - the message string.
+ */
+libmosq_EXPORT void mosquitto_log_callback_set(struct mosquitto *mosq, void (*on_log)(struct mosquitto *, void *, int, const char *));
+
+/*
+ * Function: mosquitto_reconnect_delay_set
+ *
+ * Control the behaviour of the client when it has unexpectedly disconnected in
+ * <mosquitto_loop_forever> or after <mosquitto_loop_start>. The default
+ * behaviour if this function is not used is to repeatedly attempt to reconnect
+ * with a delay of 1 second until the connection succeeds.
+ *
+ * Use reconnect_delay parameter to change the delay between successive
+ * reconnection attempts. You may also enable exponential backoff of the time
+ * between reconnections by setting reconnect_exponential_backoff to true and
+ * set an upper bound on the delay with reconnect_delay_max.
+ *
+ * Example 1:
+ * delay=2, delay_max=10, exponential_backoff=False
+ * Delays would be: 2, 4, 6, 8, 10, 10, ...
+ *
+ * Example 2:
+ * delay=3, delay_max=30, exponential_backoff=True
+ * Delays would be: 3, 6, 12, 24, 30, 30, ...
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * reconnect_delay - the number of seconds to wait between
+ * reconnects.
+ * reconnect_delay_max - the maximum number of seconds to wait
+ * between reconnects.
+ * reconnect_exponential_backoff - use exponential backoff between
+ * reconnect attempts. Set to true to enable
+ * exponential backoff.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ */
+libmosq_EXPORT int mosquitto_reconnect_delay_set(struct mosquitto *mosq, unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff);
+
+/*
+ * Function: mosquitto_max_inflight_messages_set
+ *
+ * Set the number of QoS 1 and 2 messages that can be "in flight" at one time.
+ * An in flight message is part way through its delivery flow. Attempts to send
+ * further messages with <mosquitto_publish> will result in the messages being
+ * queued until the number of in flight messages reduces.
+ *
+ * A higher number here results in greater message throughput, but if set
+ * higher than the maximum in flight messages on the broker may lead to
+ * delays in the messages being acknowledged.
+ *
+ * Set to 0 for no maximum.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * max_inflight_messages - the maximum number of inflight messages. Defaults
+ * to 20.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success.
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ */
+libmosq_EXPORT int mosquitto_max_inflight_messages_set(struct mosquitto *mosq, unsigned int max_inflight_messages);
+
+/*
+ * Function: mosquitto_message_retry_set
+ *
+ * Set the number of seconds to wait before retrying messages. This applies to
+ * publish messages with QoS>0. May be called at any time.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * message_retry - the number of seconds to wait for a response before
+ * retrying. Defaults to 20.
+ */
+libmosq_EXPORT void mosquitto_message_retry_set(struct mosquitto *mosq, unsigned int message_retry);
+
+/*
+ * Function: mosquitto_user_data_set
+ *
+ * When <mosquitto_new> is called, the pointer given as the "obj" parameter
+ * will be passed to the callbacks as user data. The <mosquitto_user_data_set>
+ * function allows this obj parameter to be updated at any time. This function
+ * will not modify the memory pointed to by the current user data pointer. If
+ * it is dynamically allocated memory you must free it yourself.
+ *
+ * Parameters:
+ * mosq - a valid mosquitto instance.
+ * obj - A user pointer that will be passed as an argument to any callbacks
+ * that are specified.
+ */
+libmosq_EXPORT void mosquitto_user_data_set(struct mosquitto *mosq, void *obj);
+
+
+/* =============================================================================
+ *
+ * Section: Utility functions
+ *
+ * =============================================================================
+ */
+
+/*
+ * Function: mosquitto_strerror
+ *
+ * Call to obtain a const string description of a mosquitto error number.
+ *
+ * Parameters:
+ * mosq_errno - a mosquitto error number.
+ *
+ * Returns:
+ * A constant string describing the error.
+ */
+libmosq_EXPORT const char *mosquitto_strerror(int mosq_errno);
+
+/*
+ * Function: mosquitto_connack_string
+ *
+ * Call to obtain a const string description of an MQTT connection result.
+ *
+ * Parameters:
+ * connack_code - an MQTT connection result.
+ *
+ * Returns:
+ * A constant string describing the result.
+ */
+libmosq_EXPORT const char *mosquitto_connack_string(int connack_code);
+
+/*
+ * Function: mosquitto_sub_topic_tokenise
+ *
+ * Tokenise a topic or subscription string into an array of strings
+ * representing the topic hierarchy.
+ *
+ * For example:
+ *
+ * subtopic: "a/deep/topic/hierarchy"
+ *
+ * Would result in:
+ *
+ * topics[0] = "a"
+ * topics[1] = "deep"
+ * topics[2] = "topic"
+ * topics[3] = "hierarchy"
+ *
+ * and:
+ *
+ * subtopic: "/a/deep/topic/hierarchy/"
+ *
+ * Would result in:
+ *
+ * topics[0] = NULL
+ * topics[1] = "a"
+ * topics[2] = "deep"
+ * topics[3] = "topic"
+ * topics[4] = "hierarchy"
+ *
+ * Parameters:
+ * subtopic - the subscription/topic to tokenise
+ * topics - a pointer to store the array of strings
+ * count - an int pointer to store the number of items in the topics array.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ *
+ * Example:
+ *
+ * > char **topics;
+ * > int topic_count;
+ * > int i;
+ * >
+ * > mosquitto_sub_topic_tokenise("$SYS/broker/uptime", &topics, &topic_count);
+ * >
+ * > for(i=0; i<token_count; i++){
+ * > printf("%d: %s\n", i, topics[i]);
+ * > }
+ *
+ * See Also:
+ * <mosquitto_sub_topic_tokens_free>
+ */
+libmosq_EXPORT int mosquitto_sub_topic_tokenise(const char *subtopic, char ***topics, int *count);
+
+/*
+ * Function: mosquitto_sub_topic_tokens_free
+ *
+ * Free memory that was allocated in <mosquitto_sub_topic_tokenise>.
+ *
+ * Parameters:
+ * topics - pointer to string array.
+ * count - count of items in string array.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ *
+ * See Also:
+ * <mosquitto_sub_topic_tokenise>
+ */
+libmosq_EXPORT int mosquitto_sub_topic_tokens_free(char ***topics, int count);
+
+/*
+ * Function: mosquitto_topic_matches_sub
+ *
+ * Check whether a topic matches a subscription.
+ *
+ * For example:
+ *
+ * foo/bar would match the subscription foo/# or +/bar
+ * non/matching would not match the subscription non/+/+
+ *
+ * Parameters:
+ * sub - subscription string to check topic against.
+ * topic - topic to check.
+ * result - bool pointer to hold result. Will be set to true if the topic
+ * matches the subscription.
+ *
+ * Returns:
+ * MOSQ_ERR_SUCCESS - on success
+ * MOSQ_ERR_INVAL - if the input parameters were invalid.
+ * MOSQ_ERR_NOMEM - if an out of memory condition occurred.
+ */
+libmosq_EXPORT int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2010,2011,2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _MOSQUITTO_INTERNAL_H_
+#define _MOSQUITTO_INTERNAL_H_
+
+#include "config.h"
+
+#ifdef WIN32
+# include <winsock2.h>
+#endif
+
+#ifdef WITH_TLS
+#include <openssl/ssl.h>
+#endif
+#include <stdlib.h>
+
+#if defined(WITH_THREADING) && !defined(WITH_BROKER)
+# include <pthread.h>
+#else
+# include <dummypthread.h>
+#endif
+
+#ifdef WITH_SRV
+# include <ares.h>
+#endif
+
+#ifdef WIN32
+# if _MSC_VER < 1600
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+ typedef unsigned long long uint64_t;
+# else
+# include <stdint.h>
+# endif
+#else
+# include <stdint.h>
+#endif
+
+#include "mosquitto.h"
+#include "time_mosq.h"
+#ifdef WITH_BROKER
+struct mosquitto_client_msg;
+#endif
+
+enum mosquitto_msg_direction {
+ mosq_md_in = 0,
+ mosq_md_out = 1
+};
+
+enum mosquitto_msg_state {
+ mosq_ms_invalid = 0,
+ mosq_ms_publish_qos0 = 1,
+ mosq_ms_publish_qos1 = 2,
+ mosq_ms_wait_for_puback = 3,
+ mosq_ms_publish_qos2 = 4,
+ mosq_ms_wait_for_pubrec = 5,
+ mosq_ms_resend_pubrel = 6,
+ mosq_ms_wait_for_pubrel = 7,
+ mosq_ms_resend_pubcomp = 8,
+ mosq_ms_wait_for_pubcomp = 9,
+ mosq_ms_send_pubrec = 10,
+ mosq_ms_queued = 11
+};
+
+enum mosquitto_client_state {
+ mosq_cs_new = 0,
+ mosq_cs_connected = 1,
+ mosq_cs_disconnecting = 2,
+ mosq_cs_connect_async = 3,
+ mosq_cs_connect_pending = 4,
+ mosq_cs_connect_srv = 5
+};
+
+enum _mosquitto_protocol {
+ mosq_p_invalid = 0,
+ mosq_p_mqtt31 = 1,
+ mosq_p_mqtt311 = 2,
+ mosq_p_mqtts = 3
+};
+
+enum _mosquitto_transport {
+ mosq_t_invalid = 0,
+ mosq_t_tcp = 1,
+ mosq_t_ws = 2,
+ mosq_t_sctp = 3
+};
+
+struct _mosquitto_packet{
+ uint8_t command;
+ uint8_t have_remaining;
+ uint8_t remaining_count;
+ uint16_t mid;
+ uint32_t remaining_mult;
+ uint32_t remaining_length;
+ uint32_t packet_length;
+ uint32_t to_process;
+ uint32_t pos;
+ uint8_t *payload;
+ struct _mosquitto_packet *next;
+};
+
+struct mosquitto_message_all{
+ struct mosquitto_message_all *next;
+ time_t timestamp;
+ //enum mosquitto_msg_direction direction;
+ enum mosquitto_msg_state state;
+ bool dup;
+ struct mosquitto_message msg;
+};
+
+struct mosquitto {
+#ifndef WIN32
+ int sock;
+# ifndef WITH_BROKER
+ int sockpairR, sockpairW;
+# endif
+#else
+ SOCKET sock;
+# ifndef WITH_BROKER
+ SOCKET sockpairR, sockpairW;
+# endif
+#endif
+ enum _mosquitto_protocol protocol;
+ char *address;
+ char *id;
+ char *username;
+ char *password;
+ uint16_t keepalive;
+ bool clean_session;
+ enum mosquitto_client_state state;
+ time_t last_msg_in;
+ time_t last_msg_out;
+ time_t ping_t;
+ uint16_t last_mid;
+ struct _mosquitto_packet in_packet;
+ struct _mosquitto_packet *current_out_packet;
+ struct _mosquitto_packet *out_packet;
+ struct mosquitto_message *will;
+#ifdef WITH_TLS
+ SSL *ssl;
+ SSL_CTX *ssl_ctx;
+ char *tls_cafile;
+ char *tls_capath;
+ char *tls_certfile;
+ char *tls_keyfile;
+ int (*tls_pw_callback)(char *buf, int size, int rwflag, void *userdata);
+ int tls_cert_reqs;
+ char *tls_version;
+ char *tls_ciphers;
+ char *tls_psk;
+ char *tls_psk_identity;
+ bool tls_insecure;
+#endif
+ bool want_write;
+#if defined(WITH_THREADING) && !defined(WITH_BROKER)
+ pthread_mutex_t callback_mutex;
+ pthread_mutex_t log_callback_mutex;
+ pthread_mutex_t msgtime_mutex;
+ pthread_mutex_t out_packet_mutex;
+ pthread_mutex_t current_out_packet_mutex;
+ pthread_mutex_t state_mutex;
+ pthread_mutex_t in_message_mutex;
+ pthread_mutex_t out_message_mutex;
+ pthread_t thread_id;
+#endif
+#ifdef WITH_BROKER
+ bool is_bridge;
+ struct _mqtt3_bridge *bridge;
+ struct mosquitto_client_msg *msgs;
+ struct mosquitto_client_msg *last_msg;
+ int msg_count;
+ int msg_count12;
+ struct _mosquitto_acl_user *acl_list;
+ struct _mqtt3_listener *listener;
+ time_t disconnect_t;
+ int pollfd_index;
+ int db_index;
+ struct _mosquitto_packet *out_packet_last;
+ bool is_dropping;
+#else
+ void *userdata;
+ bool in_callback;
+ unsigned int message_retry;
+ time_t last_retry_check;
+ struct mosquitto_message_all *in_messages;
+ struct mosquitto_message_all *in_messages_last;
+ struct mosquitto_message_all *out_messages;
+ struct mosquitto_message_all *out_messages_last;
+ void (*on_connect)(struct mosquitto *, void *userdata, int rc);
+ void (*on_disconnect)(struct mosquitto *, void *userdata, int rc);
+ void (*on_publish)(struct mosquitto *, void *userdata, int mid);
+ void (*on_message)(struct mosquitto *, void *userdata, const struct mosquitto_message *message);
+ void (*on_subscribe)(struct mosquitto *, void *userdata, int mid, int qos_count, const int *granted_qos);
+ void (*on_unsubscribe)(struct mosquitto *, void *userdata, int mid);
+ void (*on_log)(struct mosquitto *, void *userdata, int level, const char *str);
+ //void (*on_error)();
+ char *host;
+ int port;
+ int in_queue_len;
+ int out_queue_len;
+ char *bind_address;
+ unsigned int reconnect_delay;
+ unsigned int reconnect_delay_max;
+ bool reconnect_exponential_backoff;
+ bool threaded;
+ struct _mosquitto_packet *out_packet_last;
+ int inflight_messages;
+ int max_inflight_messages;
+# ifdef WITH_SRV
+ ares_channel achan;
+# endif
+#endif
+};
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _MQTT3_PROTOCOL_H_
+#define _MQTT3_PROTOCOL_H_
+
+/* For version 3 of the MQTT protocol */
+
+#define PROTOCOL_NAME_v31 "MQIsdp"
+#define PROTOCOL_VERSION_v31 3
+
+#define PROTOCOL_NAME_v311 "MQTT"
+#define PROTOCOL_VERSION_v311 4
+
+/* Message types */
+#define CONNECT 0x10
+#define CONNACK 0x20
+#define PUBLISH 0x30
+#define PUBACK 0x40
+#define PUBREC 0x50
+#define PUBREL 0x60
+#define PUBCOMP 0x70
+#define SUBSCRIBE 0x80
+#define SUBACK 0x90
+#define UNSUBSCRIBE 0xA0
+#define UNSUBACK 0xB0
+#define PINGREQ 0xC0
+#define PINGRESP 0xD0
+#define DISCONNECT 0xE0
+
+#define CONNACK_ACCEPTED 0
+#define CONNACK_REFUSED_PROTOCOL_VERSION 1
+#define CONNACK_REFUSED_IDENTIFIER_REJECTED 2
+#define CONNACK_REFUSED_SERVER_UNAVAILABLE 3
+#define CONNACK_REFUSED_BAD_USERNAME_PASSWORD 4
+#define CONNACK_REFUSED_NOT_AUTHORIZED 5
+
+#define MQTT_MAX_PAYLOAD 268435455
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef WIN32
+#include <netdb.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+
+#ifdef __ANDROID__
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <sys/endian.h>
+#endif
+
+#ifdef __FreeBSD__
+# include <netinet/in.h>
+#endif
+
+#ifdef __SYMBIAN32__
+#include <netinet/in.h>
+#endif
+
+#ifdef __QNX__
+#ifndef AI_ADDRCONFIG
+#define AI_ADDRCONFIG 0
+#endif
+#include <net/netbyte.h>
+#include <netinet/in.h>
+#endif
+
+#ifdef WITH_TLS
+#include <openssl/err.h>
+#include <tls_mosq.h>
+#endif
+
+#ifdef WITH_BROKER
+# include <mosquitto_broker.h>
+# ifdef WITH_SYS_TREE
+ extern uint64_t g_bytes_received;
+ extern uint64_t g_bytes_sent;
+ extern unsigned long g_msgs_received;
+ extern unsigned long g_msgs_sent;
+ extern unsigned long g_pub_msgs_received;
+ extern unsigned long g_pub_msgs_sent;
+# endif
+#else
+# include <read_handle.h>
+#endif
+
+#include "logging_mosq.h"
+#include "memory_mosq.h"
+#include "mqtt3_protocol.h"
+#include "net_mosq.h"
+#include "time_mosq.h"
+#include "util_mosq.h"
+
+#ifdef WITH_TLS
+int tls_ex_index_mosq = -1;
+#endif
+
+void _mosquitto_net_init(void)
+{
+#ifdef WIN32
+ WSADATA wsaData;
+ WSAStartup(MAKEWORD(2,2), &wsaData);
+#endif
+
+#ifdef WITH_SRV
+ ares_library_init(ARES_LIB_INIT_ALL);
+#endif
+
+#ifdef WITH_TLS
+ SSL_load_error_strings();
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+ if(tls_ex_index_mosq == -1){
+ tls_ex_index_mosq = SSL_get_ex_new_index(0, "client context", NULL, NULL, NULL);
+ }
+#endif
+}
+
+void _mosquitto_net_cleanup(void)
+{
+#ifdef WITH_TLS
+ ERR_free_strings();
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+#endif
+
+#ifdef WITH_SRV
+ ares_library_cleanup();
+#endif
+
+#ifdef WIN32
+ WSACleanup();
+#endif
+}
+
+void _mosquitto_packet_cleanup(struct _mosquitto_packet *packet)
+{
+ if(!packet) return;
+
+ /* Free data and reset values */
+ packet->command = 0;
+ packet->have_remaining = 0;
+ packet->remaining_count = 0;
+ packet->remaining_mult = 1;
+ packet->remaining_length = 0;
+ if(packet->payload) _mosquitto_free(packet->payload);
+ packet->payload = NULL;
+ packet->to_process = 0;
+ packet->pos = 0;
+}
+
+int _mosquitto_packet_queue(struct mosquitto *mosq, struct _mosquitto_packet *packet)
+{
+#ifndef WITH_BROKER
+ char sockpair_data = 0;
+#endif
+ assert(mosq);
+ assert(packet);
+
+ packet->pos = 0;
+ packet->to_process = packet->packet_length;
+
+ packet->next = NULL;
+ pthread_mutex_lock(&mosq->out_packet_mutex);
+ if(mosq->out_packet){
+ mosq->out_packet_last->next = packet;
+ }else{
+ mosq->out_packet = packet;
+ }
+ mosq->out_packet_last = packet;
+ pthread_mutex_unlock(&mosq->out_packet_mutex);
+#ifdef WITH_BROKER
+ return _mosquitto_packet_write(mosq);
+#else
+
+ /* Write a single byte to sockpairW (connected to sockpairR) to break out
+ * of select() if in threaded mode. */
+ if(mosq->sockpairW != INVALID_SOCKET){
+#ifndef WIN32
+ if(write(mosq->sockpairW, &sockpair_data, 1)){
+ }
+#else
+ send(mosq->sockpairW, &sockpair_data, 1, 0);
+#endif
+ }
+
+ if(mosq->in_callback == false && mosq->threaded == false){
+ return _mosquitto_packet_write(mosq);
+ }else{
+ return MOSQ_ERR_SUCCESS;
+ }
+#endif
+}
+
+/* Close a socket associated with a context and set it to -1.
+ * Returns 1 on failure (context is NULL)
+ * Returns 0 on success.
+ */
+int _mosquitto_socket_close(struct mosquitto *mosq)
+{
+ int rc = 0;
+
+ assert(mosq);
+#ifdef WITH_TLS
+ if(mosq->ssl){
+ SSL_shutdown(mosq->ssl);
+ SSL_free(mosq->ssl);
+ mosq->ssl = NULL;
+ }
+ if(mosq->ssl_ctx){
+ SSL_CTX_free(mosq->ssl_ctx);
+ mosq->ssl_ctx = NULL;
+ }
+#endif
+
+ if(mosq->sock != INVALID_SOCKET){
+ rc = COMPAT_CLOSE(mosq->sock);
+ mosq->sock = INVALID_SOCKET;
+ }
+
+ return rc;
+}
+
+#ifdef REAL_WITH_TLS_PSK
+static unsigned int psk_client_callback(SSL *ssl, const char *hint,
+ char *identity, unsigned int max_identity_len,
+ unsigned char *psk, unsigned int max_psk_len)
+{
+ struct mosquitto *mosq;
+ int len;
+
+ mosq = SSL_get_ex_data(ssl, tls_ex_index_mosq);
+ if(!mosq) return 0;
+
+ snprintf(identity, max_identity_len, "%s", mosq->tls_psk_identity);
+
+ len = _mosquitto_hex2bin(mosq->tls_psk, psk, max_psk_len);
+ if (len < 0) return 0;
+ return len;
+}
+#endif
+
+int _mosquitto_try_connect(const char *host, uint16_t port, int *sock, const char *bind_address, bool blocking)
+{
+ struct addrinfo hints;
+ struct addrinfo *ainfo, *rp;
+ struct addrinfo *ainfo_bind, *rp_bind;
+ int s;
+ int rc;
+#ifdef WIN32
+ uint32_t val = 1;
+#endif
+
+ *sock = INVALID_SOCKET;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_ADDRCONFIG;
+ hints.ai_socktype = SOCK_STREAM;
+
+ s = getaddrinfo(host, NULL, &hints, &ainfo);
+ if(s){
+ errno = s;
+ return MOSQ_ERR_EAI;
+ }
+
+ if(bind_address){
+ s = getaddrinfo(bind_address, NULL, &hints, &ainfo_bind);
+ if(s){
+ freeaddrinfo(ainfo);
+ errno = s;
+ return MOSQ_ERR_EAI;
+ }
+ }
+
+ for(rp = ainfo; rp != NULL; rp = rp->ai_next){
+ *sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if(*sock == INVALID_SOCKET) continue;
+
+ if(rp->ai_family == PF_INET){
+ ((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port);
+ }else if(rp->ai_family == PF_INET6){
+ ((struct sockaddr_in6 *)rp->ai_addr)->sin6_port = htons(port);
+ }else{
+ continue;
+ }
+
+ if(bind_address){
+ for(rp_bind = ainfo_bind; rp_bind != NULL; rp_bind = rp_bind->ai_next){
+ if(bind(*sock, rp_bind->ai_addr, rp_bind->ai_addrlen) == 0){
+ break;
+ }
+ }
+ if(!rp_bind){
+ COMPAT_CLOSE(*sock);
+ continue;
+ }
+ }
+
+ if(!blocking){
+ /* Set non-blocking */
+ if(_mosquitto_socket_nonblock(*sock)){
+ COMPAT_CLOSE(*sock);
+ continue;
+ }
+ }
+
+ rc = connect(*sock, rp->ai_addr, rp->ai_addrlen);
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if(rc == 0 || errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK){
+ if(blocking){
+ /* Set non-blocking */
+ if(_mosquitto_socket_nonblock(*sock)){
+ COMPAT_CLOSE(*sock);
+ continue;
+ }
+ }
+ break;
+ }
+
+ COMPAT_CLOSE(*sock);
+ *sock = INVALID_SOCKET;
+ }
+ freeaddrinfo(ainfo);
+ if(bind_address){
+ freeaddrinfo(ainfo_bind);
+ }
+ if(!rp){
+ return MOSQ_ERR_ERRNO;
+ }
+ return MOSQ_ERR_SUCCESS;
+}
+
+/* Create a socket and connect it to 'ip' on port 'port'.
+ * Returns -1 on failure (ip is NULL, socket creation/connection error)
+ * Returns sock number on success.
+ */
+int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking)
+{
+ int sock = INVALID_SOCKET;
+ int rc;
+#ifdef WITH_TLS
+ int ret;
+ BIO *bio;
+#endif
+
+ if(!mosq || !host || !port) return MOSQ_ERR_INVAL;
+
+#ifdef WITH_TLS
+ if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
+ blocking = true;
+ }
+#endif
+
+ rc = _mosquitto_try_connect(host, port, &sock, bind_address, blocking);
+ if(rc != MOSQ_ERR_SUCCESS) return rc;
+
+#ifdef WITH_TLS
+ if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1.2")){
+ mosq->ssl_ctx = SSL_CTX_new(TLSv1_2_client_method());
+ }else if(!strcmp(mosq->tls_version, "tlsv1.1")){
+ mosq->ssl_ctx = SSL_CTX_new(TLSv1_1_client_method());
+ }else if(!strcmp(mosq->tls_version, "tlsv1")){
+ mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
+ }else{
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version);
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_INVAL;
+ }
+#else
+ if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1")){
+ mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
+ }else{
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version);
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_INVAL;
+ }
+#endif
+ if(!mosq->ssl_ctx){
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context.");
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_TLS;
+ }
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000
+ /* Disable compression */
+ SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_COMPRESSION);
+#endif
+#ifdef SSL_MODE_RELEASE_BUFFERS
+ /* Use even less memory per SSL connection. */
+ SSL_CTX_set_mode(mosq->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
+#endif
+
+ if(mosq->tls_ciphers){
+ ret = SSL_CTX_set_cipher_list(mosq->ssl_ctx, mosq->tls_ciphers);
+ if(ret == 0){
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", mosq->tls_ciphers);
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_TLS;
+ }
+ }
+ if(mosq->tls_cafile || mosq->tls_capath){
+ ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath);
+ if(ret == 0){
+#ifdef WITH_BROKER
+ if(mosq->tls_cafile && mosq->tls_capath){
+ _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);
+ }else if(mosq->tls_cafile){
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile);
+ }else{
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath);
+ }
+#else
+ if(mosq->tls_cafile && mosq->tls_capath){
+ _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);
+ }else if(mosq->tls_cafile){
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile);
+ }else{
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath);
+ }
+#endif
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_TLS;
+ }
+ if(mosq->tls_cert_reqs == 0){
+ SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_NONE, NULL);
+ }else{
+ SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_PEER, _mosquitto_server_certificate_verify);
+ }
+
+ if(mosq->tls_pw_callback){
+ SSL_CTX_set_default_passwd_cb(mosq->ssl_ctx, mosq->tls_pw_callback);
+ SSL_CTX_set_default_passwd_cb_userdata(mosq->ssl_ctx, mosq);
+ }
+
+ if(mosq->tls_certfile){
+ ret = SSL_CTX_use_certificate_chain_file(mosq->ssl_ctx, mosq->tls_certfile);
+ if(ret != 1){
+#ifdef WITH_BROKER
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate, check bridge_certfile \"%s\".", mosq->tls_certfile);
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate \"%s\".", mosq->tls_certfile);
+#endif
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_TLS;
+ }
+ }
+ if(mosq->tls_keyfile){
+ ret = SSL_CTX_use_PrivateKey_file(mosq->ssl_ctx, mosq->tls_keyfile, SSL_FILETYPE_PEM);
+ if(ret != 1){
+#ifdef WITH_BROKER
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file, check bridge_keyfile \"%s\".", mosq->tls_keyfile);
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file \"%s\".", mosq->tls_keyfile);
+#endif
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_TLS;
+ }
+ ret = SSL_CTX_check_private_key(mosq->ssl_ctx);
+ if(ret != 1){
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Client certificate/key are inconsistent.");
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_TLS;
+ }
+ }
+#ifdef REAL_WITH_TLS_PSK
+ }else if(mosq->tls_psk){
+ SSL_CTX_set_psk_client_callback(mosq->ssl_ctx, psk_client_callback);
+#endif
+ }
+
+ mosq->ssl = SSL_new(mosq->ssl_ctx);
+ if(!mosq->ssl){
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_TLS;
+ }
+ SSL_set_ex_data(mosq->ssl, tls_ex_index_mosq, mosq);
+ bio = BIO_new_socket(sock, BIO_NOCLOSE);
+ if(!bio){
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_TLS;
+ }
+ SSL_set_bio(mosq->ssl, bio, bio);
+
+ ret = SSL_connect(mosq->ssl);
+ if(ret != 1){
+ ret = SSL_get_error(mosq->ssl, ret);
+ if(ret == SSL_ERROR_WANT_READ){
+ /* We always try to read anyway */
+ }else if(ret == SSL_ERROR_WANT_WRITE){
+ mosq->want_write = true;
+ }else{
+ COMPAT_CLOSE(sock);
+ return MOSQ_ERR_TLS;
+ }
+ }
+ }
+#endif
+
+ mosq->sock = sock;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+int _mosquitto_read_byte(struct _mosquitto_packet *packet, uint8_t *byte)
+{
+ assert(packet);
+ if(packet->pos+1 > packet->remaining_length) return MOSQ_ERR_PROTOCOL;
+
+ *byte = packet->payload[packet->pos];
+ packet->pos++;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+void _mosquitto_write_byte(struct _mosquitto_packet *packet, uint8_t byte)
+{
+ assert(packet);
+ assert(packet->pos+1 <= packet->packet_length);
+
+ packet->payload[packet->pos] = byte;
+ packet->pos++;
+}
+
+int _mosquitto_read_bytes(struct _mosquitto_packet *packet, void *bytes, uint32_t count)
+{
+ assert(packet);
+ if(packet->pos+count > packet->remaining_length) return MOSQ_ERR_PROTOCOL;
+
+ memcpy(bytes, &(packet->payload[packet->pos]), count);
+ packet->pos += count;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+void _mosquitto_write_bytes(struct _mosquitto_packet *packet, const void *bytes, uint32_t count)
+{
+ assert(packet);
+ assert(packet->pos+count <= packet->packet_length);
+
+ memcpy(&(packet->payload[packet->pos]), bytes, count);
+ packet->pos += count;
+}
+
+int _mosquitto_read_string(struct _mosquitto_packet *packet, char **str)
+{
+ uint16_t len;
+ int rc;
+
+ assert(packet);
+ rc = _mosquitto_read_uint16(packet, &len);
+ if(rc) return rc;
+
+ if(packet->pos+len > packet->remaining_length) return MOSQ_ERR_PROTOCOL;
+
+ *str = _mosquitto_calloc(len+1, sizeof(char));
+ if(*str){
+ memcpy(*str, &(packet->payload[packet->pos]), len);
+ packet->pos += len;
+ }else{
+ return MOSQ_ERR_NOMEM;
+ }
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+void _mosquitto_write_string(struct _mosquitto_packet *packet, const char *str, uint16_t length)
+{
+ assert(packet);
+ _mosquitto_write_uint16(packet, length);
+ _mosquitto_write_bytes(packet, str, length);
+}
+
+int _mosquitto_read_uint16(struct _mosquitto_packet *packet, uint16_t *word)
+{
+ uint8_t msb, lsb;
+
+ assert(packet);
+ if(packet->pos+2 > packet->remaining_length) return MOSQ_ERR_PROTOCOL;
+
+ msb = packet->payload[packet->pos];
+ packet->pos++;
+ lsb = packet->payload[packet->pos];
+ packet->pos++;
+
+ *word = (msb<<8) + lsb;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+void _mosquitto_write_uint16(struct _mosquitto_packet *packet, uint16_t word)
+{
+ _mosquitto_write_byte(packet, MOSQ_MSB(word));
+ _mosquitto_write_byte(packet, MOSQ_LSB(word));
+}
+
+ssize_t _mosquitto_net_read(struct mosquitto *mosq, void *buf, size_t count)
+{
+#ifdef WITH_TLS
+ int ret;
+ int err;
+ char ebuf[256];
+ unsigned long e;
+#endif
+ assert(mosq);
+ errno = 0;
+#ifdef WITH_TLS
+ if(mosq->ssl){
+ ret = SSL_read(mosq->ssl, buf, count);
+ if(ret <= 0){
+ err = SSL_get_error(mosq->ssl, ret);
+ if(err == SSL_ERROR_WANT_READ){
+ ret = -1;
+ errno = EAGAIN;
+ }else if(err == SSL_ERROR_WANT_WRITE){
+ ret = -1;
+ mosq->want_write = true;
+ errno = EAGAIN;
+ }else{
+ e = ERR_get_error();
+ while(e){
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "OpenSSL Error: %s", ERR_error_string(e, ebuf));
+ e = ERR_get_error();
+ }
+ errno = EPROTO;
+ }
+ }
+ return (ssize_t )ret;
+ }else{
+ /* Call normal read/recv */
+
+#endif
+
+#ifndef WIN32
+ return read(mosq->sock, buf, count);
+#else
+ return recv(mosq->sock, buf, count, 0);
+#endif
+
+#ifdef WITH_TLS
+ }
+#endif
+}
+
+ssize_t _mosquitto_net_write(struct mosquitto *mosq, void *buf, size_t count)
+{
+#ifdef WITH_TLS
+ int ret;
+ int err;
+ char ebuf[256];
+ unsigned long e;
+#endif
+ assert(mosq);
+
+ errno = 0;
+#ifdef WITH_TLS
+ if(mosq->ssl){
+ ret = SSL_write(mosq->ssl, buf, count);
+ if(ret < 0){
+ err = SSL_get_error(mosq->ssl, ret);
+ if(err == SSL_ERROR_WANT_READ){
+ ret = -1;
+ errno = EAGAIN;
+ }else if(err == SSL_ERROR_WANT_WRITE){
+ ret = -1;
+ mosq->want_write = true;
+ errno = EAGAIN;
+ }else{
+ e = ERR_get_error();
+ while(e){
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "OpenSSL Error: %s", ERR_error_string(e, ebuf));
+ e = ERR_get_error();
+ }
+ errno = EPROTO;
+ }
+ }
+ return (ssize_t )ret;
+ }else{
+ /* Call normal write/send */
+#endif
+
+#ifndef WIN32
+ return write(mosq->sock, buf, count);
+#else
+ return send(mosq->sock, buf, count, 0);
+#endif
+
+#ifdef WITH_TLS
+ }
+#endif
+}
+
+int _mosquitto_packet_write(struct mosquitto *mosq)
+{
+ ssize_t write_length;
+ struct _mosquitto_packet *packet;
+
+ if(!mosq) return MOSQ_ERR_INVAL;
+ if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
+
+ pthread_mutex_lock(&mosq->current_out_packet_mutex);
+ pthread_mutex_lock(&mosq->out_packet_mutex);
+ if(mosq->out_packet && !mosq->current_out_packet){
+ mosq->current_out_packet = mosq->out_packet;
+ mosq->out_packet = mosq->out_packet->next;
+ if(!mosq->out_packet){
+ mosq->out_packet_last = NULL;
+ }
+ }
+ pthread_mutex_unlock(&mosq->out_packet_mutex);
+
+ while(mosq->current_out_packet){
+ packet = mosq->current_out_packet;
+
+ while(packet->to_process > 0){
+ write_length = _mosquitto_net_write(mosq, &(packet->payload[packet->pos]), packet->to_process);
+ if(write_length > 0){
+#if defined(WITH_BROKER) && defined(WITH_SYS_TREE)
+ g_bytes_sent += write_length;
+#endif
+ packet->to_process -= write_length;
+ packet->pos += write_length;
+ }else{
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){
+ pthread_mutex_unlock(&mosq->current_out_packet_mutex);
+ return MOSQ_ERR_SUCCESS;
+ }else{
+ pthread_mutex_unlock(&mosq->current_out_packet_mutex);
+ switch(errno){
+ case COMPAT_ECONNRESET:
+ return MOSQ_ERR_CONN_LOST;
+ default:
+ return MOSQ_ERR_ERRNO;
+ }
+ }
+ }
+ }
+
+#ifdef WITH_BROKER
+# ifdef WITH_SYS_TREE
+ g_msgs_sent++;
+ if(((packet->command)&0xF6) == PUBLISH){
+ g_pub_msgs_sent++;
+ }
+# endif
+#else
+ if(((packet->command)&0xF6) == PUBLISH){
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_publish){
+ /* This is a QoS=0 message */
+ mosq->in_callback = true;
+ mosq->on_publish(mosq, mosq->userdata, packet->mid);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+ }else if(((packet->command)&0xF0) == DISCONNECT){
+ /* FIXME what cleanup needs doing here?
+ * incoming/outgoing messages? */
+ _mosquitto_socket_close(mosq);
+
+ /* Start of duplicate, possibly unnecessary code.
+ * This does leave things in a consistent state at least. */
+ /* Free data and reset values */
+ pthread_mutex_lock(&mosq->out_packet_mutex);
+ mosq->current_out_packet = mosq->out_packet;
+ if(mosq->out_packet){
+ mosq->out_packet = mosq->out_packet->next;
+ if(!mosq->out_packet){
+ mosq->out_packet_last = NULL;
+ }
+ }
+ pthread_mutex_unlock(&mosq->out_packet_mutex);
+
+ _mosquitto_packet_cleanup(packet);
+ _mosquitto_free(packet);
+
+ pthread_mutex_lock(&mosq->msgtime_mutex);
+ mosq->last_msg_out = mosquitto_time();
+ pthread_mutex_unlock(&mosq->msgtime_mutex);
+ /* End of duplicate, possibly unnecessary code */
+
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_disconnect){
+ mosq->in_callback = true;
+ mosq->on_disconnect(mosq, mosq->userdata, 0);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->current_out_packet_mutex);
+ return MOSQ_ERR_SUCCESS;
+ }
+#endif
+
+ /* Free data and reset values */
+ pthread_mutex_lock(&mosq->out_packet_mutex);
+ mosq->current_out_packet = mosq->out_packet;
+ if(mosq->out_packet){
+ mosq->out_packet = mosq->out_packet->next;
+ if(!mosq->out_packet){
+ mosq->out_packet_last = NULL;
+ }
+ }
+ pthread_mutex_unlock(&mosq->out_packet_mutex);
+
+ _mosquitto_packet_cleanup(packet);
+ _mosquitto_free(packet);
+
+ pthread_mutex_lock(&mosq->msgtime_mutex);
+ mosq->last_msg_out = mosquitto_time();
+ pthread_mutex_unlock(&mosq->msgtime_mutex);
+ }
+ pthread_mutex_unlock(&mosq->current_out_packet_mutex);
+ return MOSQ_ERR_SUCCESS;
+}
+
+#ifdef WITH_BROKER
+int _mosquitto_packet_read(struct mosquitto_db *db, struct mosquitto *mosq)
+#else
+int _mosquitto_packet_read(struct mosquitto *mosq)
+#endif
+{
+ uint8_t byte;
+ ssize_t read_length;
+ int rc = 0;
+
+ if(!mosq) return MOSQ_ERR_INVAL;
+ if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
+ /* This gets called if pselect() indicates that there is network data
+ * available - ie. at least one byte. What we do depends on what data we
+ * already have.
+ * If we've not got a command, attempt to read one and save it. This should
+ * always work because it's only a single byte.
+ * Then try to read the remaining length. This may fail because it is may
+ * be more than one byte - will need to save data pending next read if it
+ * does fail.
+ * Then try to read the remaining payload, where 'payload' here means the
+ * combined variable header and actual payload. This is the most likely to
+ * fail due to longer length, so save current data and current position.
+ * After all data is read, send to _mosquitto_handle_packet() to deal with.
+ * Finally, free the memory and reset everything to starting conditions.
+ */
+ if(!mosq->in_packet.command){
+ read_length = _mosquitto_net_read(mosq, &byte, 1);
+ if(read_length == 1){
+ mosq->in_packet.command = byte;
+#ifdef WITH_BROKER
+# ifdef WITH_SYS_TREE
+ g_bytes_received++;
+# endif
+ /* Clients must send CONNECT as their first command. */
+ if(!(mosq->bridge) && mosq->state == mosq_cs_new && (byte&0xF0) != CONNECT) return MOSQ_ERR_PROTOCOL;
+#endif
+ }else{
+ if(read_length == 0) return MOSQ_ERR_CONN_LOST; /* EOF */
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){
+ return MOSQ_ERR_SUCCESS;
+ }else{
+ switch(errno){
+ case COMPAT_ECONNRESET:
+ return MOSQ_ERR_CONN_LOST;
+ default:
+ return MOSQ_ERR_ERRNO;
+ }
+ }
+ }
+ }
+ if(!mosq->in_packet.have_remaining){
+ do{
+ read_length = _mosquitto_net_read(mosq, &byte, 1);
+ if(read_length == 1){
+ mosq->in_packet.remaining_count++;
+ /* Max 4 bytes length for remaining length as defined by protocol.
+ * Anything more likely means a broken/malicious client.
+ */
+ if(mosq->in_packet.remaining_count > 4) return MOSQ_ERR_PROTOCOL;
+
+#if defined(WITH_BROKER) && defined(WITH_SYS_TREE)
+ g_bytes_received++;
+#endif
+ mosq->in_packet.remaining_length += (byte & 127) * mosq->in_packet.remaining_mult;
+ mosq->in_packet.remaining_mult *= 128;
+ }else{
+ if(read_length == 0) return MOSQ_ERR_CONN_LOST; /* EOF */
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){
+ return MOSQ_ERR_SUCCESS;
+ }else{
+ switch(errno){
+ case COMPAT_ECONNRESET:
+ return MOSQ_ERR_CONN_LOST;
+ default:
+ return MOSQ_ERR_ERRNO;
+ }
+ }
+ }
+ }while((byte & 128) != 0);
+
+ if(mosq->in_packet.remaining_length > 0){
+ mosq->in_packet.payload = _mosquitto_malloc(mosq->in_packet.remaining_length*sizeof(uint8_t));
+ if(!mosq->in_packet.payload) return MOSQ_ERR_NOMEM;
+ mosq->in_packet.to_process = mosq->in_packet.remaining_length;
+ }
+ mosq->in_packet.have_remaining = 1;
+ }
+ while(mosq->in_packet.to_process>0){
+ read_length = _mosquitto_net_read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process);
+ if(read_length > 0){
+#if defined(WITH_BROKER) && defined(WITH_SYS_TREE)
+ g_bytes_received += read_length;
+#endif
+ mosq->in_packet.to_process -= read_length;
+ mosq->in_packet.pos += read_length;
+ }else{
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){
+ if(mosq->in_packet.to_process > 1000){
+ /* Update last_msg_in time if more than 1000 bytes left to
+ * receive. Helps when receiving large messages.
+ * This is an arbitrary limit, but with some consideration.
+ * If a client can't send 1000 bytes in a second it
+ * probably shouldn't be using a 1 second keep alive. */
+ pthread_mutex_lock(&mosq->msgtime_mutex);
+ mosq->last_msg_in = mosquitto_time();
+ pthread_mutex_unlock(&mosq->msgtime_mutex);
+ }
+ return MOSQ_ERR_SUCCESS;
+ }else{
+ switch(errno){
+ case COMPAT_ECONNRESET:
+ return MOSQ_ERR_CONN_LOST;
+ default:
+ return MOSQ_ERR_ERRNO;
+ }
+ }
+ }
+ }
+
+ /* All data for this packet is read. */
+ mosq->in_packet.pos = 0;
+#ifdef WITH_BROKER
+# ifdef WITH_SYS_TREE
+ g_msgs_received++;
+ if(((mosq->in_packet.command)&0xF5) == PUBLISH){
+ g_pub_msgs_received++;
+ }
+# endif
+ rc = mqtt3_packet_handle(db, mosq);
+#else
+ rc = _mosquitto_packet_handle(mosq);
+#endif
+
+ /* Free data and reset values */
+ _mosquitto_packet_cleanup(&mosq->in_packet);
+
+ pthread_mutex_lock(&mosq->msgtime_mutex);
+ mosq->last_msg_in = mosquitto_time();
+ pthread_mutex_unlock(&mosq->msgtime_mutex);
+ return rc;
+}
+
+int _mosquitto_socket_nonblock(int sock)
+{
+#ifndef WIN32
+ int opt;
+ /* Set non-blocking */
+ opt = fcntl(sock, F_GETFL, 0);
+ if(opt == -1){
+ COMPAT_CLOSE(sock);
+ return 1;
+ }
+ if(fcntl(sock, F_SETFL, opt | O_NONBLOCK) == -1){
+ /* If either fcntl fails, don't want to allow this client to connect. */
+ COMPAT_CLOSE(sock);
+ return 1;
+ }
+#else
+ opt = 1;
+ if(ioctlsocket(sock, FIONBIO, &opt)){
+ COMPAT_CLOSE(sock);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+
+#ifndef WITH_BROKER
+int _mosquitto_socketpair(int *pairR, int *pairW)
+{
+#ifdef WIN32
+ int family[2] = {AF_INET, AF_INET6};
+ int i;
+ struct sockaddr_storage ss;
+ struct sockaddr_in *sa = (struct sockaddr_in *)&ss;
+ struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&ss;
+ socklen_t ss_len;
+ int spR, spW;
+
+ int listensock;
+
+ *pairR = -1;
+ *pairW = -1;
+
+ for(i=0; i<2; i++){
+ memset(&ss, 0, sizeof(ss));
+ if(family[i] == AF_INET){
+ sa->sin_family = family[i];
+ sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ sa->sin_port = 0;
+ ss_len = sizeof(struct sockaddr_in);
+ }else if(family[i] == AF_INET6){
+ sa6->sin6_family = family[i];
+ sa6->sin6_addr = in6addr_loopback;
+ sa6->sin6_port = 0;
+ ss_len = sizeof(struct sockaddr_in6);
+ }else{
+ return MOSQ_ERR_INVAL;
+ }
+
+ listensock = socket(family[i], SOCK_STREAM, IPPROTO_TCP);
+ if(listensock == -1){
+ continue;
+ }
+
+ if(bind(listensock, (struct sockaddr *)&ss, ss_len) == -1){
+ COMPAT_CLOSE(listensock);
+ continue;
+ }
+
+ if(listen(listensock, 1) == -1){
+ COMPAT_CLOSE(listensock);
+ continue;
+ }
+ memset(&ss, 0, sizeof(ss));
+ ss_len = sizeof(ss);
+ if(getsockname(listensock, (struct sockaddr *)&ss, &ss_len) < 0){
+ COMPAT_CLOSE(listensock);
+ continue;
+ }
+
+ if(_mosquitto_socket_nonblock(listensock)){
+ continue;
+ }
+
+ if(family[i] == AF_INET){
+ sa->sin_family = family[i];
+ sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ ss_len = sizeof(struct sockaddr_in);
+ }else if(family[i] == AF_INET6){
+ sa6->sin6_family = family[i];
+ sa6->sin6_addr = in6addr_loopback;
+ ss_len = sizeof(struct sockaddr_in6);
+ }
+
+ spR = socket(family[i], SOCK_STREAM, IPPROTO_TCP);
+ if(spR == -1){
+ COMPAT_CLOSE(listensock);
+ continue;
+ }
+ if(_mosquitto_socket_nonblock(spR)){
+ COMPAT_CLOSE(listensock);
+ continue;
+ }
+ if(connect(spR, (struct sockaddr *)&ss, ss_len) < 0){
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if(errno != EINPROGRESS && errno != COMPAT_EWOULDBLOCK){
+ COMPAT_CLOSE(spR);
+ COMPAT_CLOSE(listensock);
+ continue;
+ }
+ }
+ spW = accept(listensock, NULL, 0);
+ if(spW == -1){
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if(errno != EINPROGRESS && errno != COMPAT_EWOULDBLOCK){
+ COMPAT_CLOSE(spR);
+ COMPAT_CLOSE(listensock);
+ continue;
+ }
+ }
+
+ if(_mosquitto_socket_nonblock(spW)){
+ COMPAT_CLOSE(spR);
+ COMPAT_CLOSE(listensock);
+ continue;
+ }
+ COMPAT_CLOSE(listensock);
+
+ *pairR = spR;
+ *pairW = spW;
+ return MOSQ_ERR_SUCCESS;
+ }
+ return MOSQ_ERR_UNKNOWN;
+#else
+ int sv[2];
+
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1){
+ return MOSQ_ERR_ERRNO;
+ }
+ if(_mosquitto_socket_nonblock(sv[0])){
+ COMPAT_CLOSE(sv[0]);
+ COMPAT_CLOSE(sv[1]);
+ return MOSQ_ERR_ERRNO;
+ }
+ if(_mosquitto_socket_nonblock(sv[1])){
+ COMPAT_CLOSE(sv[0]);
+ COMPAT_CLOSE(sv[1]);
+ return MOSQ_ERR_ERRNO;
+ }
+ *pairR = sv[0];
+ *pairW = sv[1];
+ return MOSQ_ERR_SUCCESS;
+#endif
+}
+#endif
--- /dev/null
+/*
+Copyright (c) 2010,2011,2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _NET_MOSQ_H_
+#define _NET_MOSQ_H_
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <winsock2.h>
+typedef int ssize_t;
+#endif
+
+#include "mosquitto_internal.h"
+#include "mosquitto.h"
+
+#ifdef WITH_BROKER
+struct mosquitto_db;
+#endif
+
+#ifdef WIN32
+# define COMPAT_CLOSE(a) closesocket(a)
+# define COMPAT_ECONNRESET WSAECONNRESET
+# define COMPAT_EWOULDBLOCK WSAEWOULDBLOCK
+#else
+# define COMPAT_CLOSE(a) close(a)
+# define COMPAT_ECONNRESET ECONNRESET
+# define COMPAT_EWOULDBLOCK EWOULDBLOCK
+#endif
+
+#ifndef WIN32
+#else
+#endif
+
+/* For when not using winsock libraries. */
+#ifndef INVALID_SOCKET
+#define INVALID_SOCKET -1
+#endif
+
+/* Macros for accessing the MSB and LSB of a uint16_t */
+#define MOSQ_MSB(A) (uint8_t)((A & 0xFF00) >> 8)
+#define MOSQ_LSB(A) (uint8_t)(A & 0x00FF)
+
+void _mosquitto_net_init(void);
+void _mosquitto_net_cleanup(void);
+
+void _mosquitto_packet_cleanup(struct _mosquitto_packet *packet);
+int _mosquitto_packet_queue(struct mosquitto *mosq, struct _mosquitto_packet *packet);
+int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking);
+int _mosquitto_socket_close(struct mosquitto *mosq);
+int _mosquitto_try_connect(const char *host, uint16_t port, int *sock, const char *bind_address, bool blocking);
+int _mosquitto_socket_nonblock(int sock);
+int _mosquitto_socketpair(int *sp1, int *sp2);
+
+int _mosquitto_read_byte(struct _mosquitto_packet *packet, uint8_t *byte);
+int _mosquitto_read_bytes(struct _mosquitto_packet *packet, void *bytes, uint32_t count);
+int _mosquitto_read_string(struct _mosquitto_packet *packet, char **str);
+int _mosquitto_read_uint16(struct _mosquitto_packet *packet, uint16_t *word);
+
+void _mosquitto_write_byte(struct _mosquitto_packet *packet, uint8_t byte);
+void _mosquitto_write_bytes(struct _mosquitto_packet *packet, const void *bytes, uint32_t count);
+void _mosquitto_write_string(struct _mosquitto_packet *packet, const char *str, uint16_t length);
+void _mosquitto_write_uint16(struct _mosquitto_packet *packet, uint16_t word);
+
+ssize_t _mosquitto_net_read(struct mosquitto *mosq, void *buf, size_t count);
+ssize_t _mosquitto_net_write(struct mosquitto *mosq, void *buf, size_t count);
+
+int _mosquitto_packet_write(struct mosquitto *mosq);
+#ifdef WITH_BROKER
+int _mosquitto_packet_read(struct mosquitto_db *db, struct mosquitto *mosq);
+#else
+int _mosquitto_packet_read(struct mosquitto *mosq);
+#endif
+
+#ifdef WITH_TLS
+int _mosquitto_socket_apply_tls(struct mosquitto *mosq);
+#endif
+
+#endif
--- /dev/null
+include ../config.mk
+
+# Set DESTDIR if it isn't given
+DESTDIR?=/
+
+.PHONY : all clean install
+
+ifeq ($(WITH_PYTHON),yes)
+all : mosquitto.pyc
+else
+all :
+endif
+
+ifeq ($(WITH_PYTHON),yes)
+install : all
+ python ./setup.py install --prefix=${prefix} --root=${DESTDIR}
+else
+install :
+endif
+
+mosquitto.pyc : mosquitto.py
+ python ./setup.py build
+
+clean :
+ -rm -rf build mosquitto.pyc __pycache__
--- /dev/null
+from sys import version
+
+from distutils.core import setup
+setup(name='mosquitto',
+ version='1.3.1',
+ description='MQTT version 3.1 client class',
+ author='Roger Light',
+ author_email='roger@atchoo.org',
+ url='http://mosquitto.org/',
+ download_url='http://mosquitto.org/files/',
+ license='BSD License',
+ py_modules=['mosquitto'],
+
+ classifiers=[
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Operating System :: Microsoft :: Windows',
+ 'Operating System :: POSIX',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Topic :: Communications',
+ 'Topic :: Internet',
+ ]
+ )
--- /dev/null
+#!/usr/bin/python
+
+# Copyright (c) 2010,2011 Roger Light <roger@atchoo.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of mosquitto nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import mosquitto
+
+def on_connect(mosq, obj, rc):
+ mosq.subscribe("$SYS/#", 0)
+ print("rc: "+str(rc))
+
+def on_message(mosq, obj, msg):
+ print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))
+
+def on_publish(mosq, obj, mid):
+ print("mid: "+str(mid))
+
+def on_subscribe(mosq, obj, mid, granted_qos):
+ print("Subscribed: "+str(mid)+" "+str(granted_qos))
+
+def on_log(mosq, obj, level, string):
+ print(string)
+
+# If you want to use a specific client id, use
+# mqttc = mosquitto.Mosquitto("client-id")
+# but note that the client id must be unique on the broker. Leaving the client
+# id parameter empty will generate a random id for you.
+mqttc = mosquitto.Mosquitto()
+mqttc.on_message = on_message
+mqttc.on_connect = on_connect
+mqttc.on_publish = on_publish
+mqttc.on_subscribe = on_subscribe
+# Uncomment to enable debug messages
+#mqttc.on_log = on_log
+mqttc.connect("test.mosquitto.org", 1883, 60)
+
+#mqttc.subscribe("string", 0)
+#mqttc.subscribe(("tuple", 1))
+#mqttc.subscribe([("list0", 0), ("list1", 1)])
+
+mqttc.loop_forever()
+
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mosquitto.h"
+#include "logging_mosq.h"
+#include "memory_mosq.h"
+#include "messages_mosq.h"
+#include "mqtt3_protocol.h"
+#include "net_mosq.h"
+#include "read_handle.h"
+#include "send_mosq.h"
+#include "time_mosq.h"
+#include "util_mosq.h"
+
+int _mosquitto_packet_handle(struct mosquitto *mosq)
+{
+ assert(mosq);
+
+ switch((mosq->in_packet.command)&0xF0){
+ case PINGREQ:
+ return _mosquitto_handle_pingreq(mosq);
+ case PINGRESP:
+ return _mosquitto_handle_pingresp(mosq);
+ case PUBACK:
+ return _mosquitto_handle_pubackcomp(mosq, "PUBACK");
+ case PUBCOMP:
+ return _mosquitto_handle_pubackcomp(mosq, "PUBCOMP");
+ case PUBLISH:
+ return _mosquitto_handle_publish(mosq);
+ case PUBREC:
+ return _mosquitto_handle_pubrec(mosq);
+ case PUBREL:
+ return _mosquitto_handle_pubrel(NULL, mosq);
+ case CONNACK:
+ return _mosquitto_handle_connack(mosq);
+ case SUBACK:
+ return _mosquitto_handle_suback(mosq);
+ case UNSUBACK:
+ return _mosquitto_handle_unsuback(mosq);
+ default:
+ /* If we don't recognise the command, return an error straight away. */
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unrecognised command %d\n", (mosq->in_packet.command)&0xF0);
+ return MOSQ_ERR_PROTOCOL;
+ }
+}
+
+int _mosquitto_handle_publish(struct mosquitto *mosq)
+{
+ uint8_t header;
+ struct mosquitto_message_all *message;
+ int rc = 0;
+ uint16_t mid;
+
+ assert(mosq);
+
+ message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all));
+ if(!message) return MOSQ_ERR_NOMEM;
+
+ header = mosq->in_packet.command;
+
+ message->dup = (header & 0x08)>>3;
+ message->msg.qos = (header & 0x06)>>1;
+ message->msg.retain = (header & 0x01);
+
+ rc = _mosquitto_read_string(&mosq->in_packet, &message->msg.topic);
+ if(rc){
+ _mosquitto_message_cleanup(&message);
+ return rc;
+ }
+ if(!strlen(message->msg.topic)){
+ _mosquitto_message_cleanup(&message);
+ return MOSQ_ERR_PROTOCOL;
+ }
+
+ if(message->msg.qos > 0){
+ rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
+ if(rc){
+ _mosquitto_message_cleanup(&message);
+ return rc;
+ }
+ message->msg.mid = (int)mid;
+ }
+
+ message->msg.payloadlen = mosq->in_packet.remaining_length - mosq->in_packet.pos;
+ if(message->msg.payloadlen){
+ message->msg.payload = _mosquitto_calloc(message->msg.payloadlen+1, sizeof(uint8_t));
+ if(!message->msg.payload){
+ _mosquitto_message_cleanup(&message);
+ return MOSQ_ERR_NOMEM;
+ }
+ rc = _mosquitto_read_bytes(&mosq->in_packet, message->msg.payload, message->msg.payloadlen);
+ if(rc){
+ _mosquitto_message_cleanup(&message);
+ return rc;
+ }
+ }
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG,
+ "Client %s received PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))",
+ mosq->id, message->dup, message->msg.qos, message->msg.retain,
+ message->msg.mid, message->msg.topic,
+ (long)message->msg.payloadlen);
+
+ message->timestamp = mosquitto_time();
+ switch(message->msg.qos){
+ case 0:
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_message){
+ mosq->in_callback = true;
+ mosq->on_message(mosq, mosq->userdata, &message->msg);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+ _mosquitto_message_cleanup(&message);
+ return MOSQ_ERR_SUCCESS;
+ case 1:
+ rc = _mosquitto_send_puback(mosq, message->msg.mid);
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_message){
+ mosq->in_callback = true;
+ mosq->on_message(mosq, mosq->userdata, &message->msg);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+ _mosquitto_message_cleanup(&message);
+ return rc;
+ case 2:
+ rc = _mosquitto_send_pubrec(mosq, message->msg.mid);
+ pthread_mutex_lock(&mosq->in_message_mutex);
+ message->state = mosq_ms_wait_for_pubrel;
+ _mosquitto_message_queue(mosq, message, mosq_md_in);
+ pthread_mutex_unlock(&mosq->in_message_mutex);
+ return rc;
+ default:
+ _mosquitto_message_cleanup(&message);
+ return MOSQ_ERR_PROTOCOL;
+ }
+}
+
--- /dev/null
+/*
+Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _READ_HANDLE_H_
+#define _READ_HANDLE_H_
+
+#include "mosquitto.h"
+struct mosquitto_db;
+
+int _mosquitto_packet_handle(struct mosquitto *mosq);
+int _mosquitto_handle_connack(struct mosquitto *mosq);
+int _mosquitto_handle_pingreq(struct mosquitto *mosq);
+int _mosquitto_handle_pingresp(struct mosquitto *mosq);
+int _mosquitto_handle_pubackcomp(struct mosquitto *mosq, const char *type);
+int _mosquitto_handle_publish(struct mosquitto *mosq);
+int _mosquitto_handle_pubrec(struct mosquitto *mosq);
+int _mosquitto_handle_pubrel(struct mosquitto_db *db, struct mosquitto *mosq);
+int _mosquitto_handle_suback(struct mosquitto *mosq);
+int _mosquitto_handle_unsuback(struct mosquitto *mosq);
+
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+
+#include "mosquitto.h"
+#include "logging_mosq.h"
+#include "memory_mosq.h"
+#include "net_mosq.h"
+#include "read_handle.h"
+
+int _mosquitto_handle_connack(struct mosquitto *mosq)
+{
+ uint8_t byte;
+ uint8_t result;
+ int rc;
+
+ assert(mosq);
+#ifdef WITH_STRICT_PROTOCOL
+ if(mosq->in_packet.remaining_length != 2){
+ return MOSQ_ERR_PROTOCOL;
+ }
+#endif
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK", mosq->id);
+ rc = _mosquitto_read_byte(&mosq->in_packet, &byte); // Reserved byte, not used
+ if(rc) return rc;
+ rc = _mosquitto_read_byte(&mosq->in_packet, &result);
+ if(rc) return rc;
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_connect){
+ mosq->in_callback = true;
+ mosq->on_connect(mosq, mosq->userdata, result);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+ switch(result){
+ case 0:
+ mosq->state = mosq_cs_connected;
+ return MOSQ_ERR_SUCCESS;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ return MOSQ_ERR_CONN_REFUSED;
+ default:
+ return MOSQ_ERR_PROTOCOL;
+ }
+}
+
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mosquitto.h"
+#include "logging_mosq.h"
+#include "memory_mosq.h"
+#include "messages_mosq.h"
+#include "mqtt3_protocol.h"
+#include "net_mosq.h"
+#include "read_handle.h"
+#include "send_mosq.h"
+#include "util_mosq.h"
+#ifdef WITH_BROKER
+#include "mosquitto_broker.h"
+#endif
+
+int _mosquitto_handle_pingreq(struct mosquitto *mosq)
+{
+ assert(mosq);
+#ifdef WITH_STRICT_PROTOCOL
+ if(mosq->in_packet.remaining_length != 0){
+ return MOSQ_ERR_PROTOCOL;
+ }
+#endif
+#ifdef WITH_BROKER
+ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PINGREQ from %s", mosq->id);
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PINGREQ", mosq->id);
+#endif
+ return _mosquitto_send_pingresp(mosq);
+}
+
+int _mosquitto_handle_pingresp(struct mosquitto *mosq)
+{
+ assert(mosq);
+#ifdef WITH_STRICT_PROTOCOL
+ if(mosq->in_packet.remaining_length != 0){
+ return MOSQ_ERR_PROTOCOL;
+ }
+#endif
+ mosq->ping_t = 0; /* No longer waiting for a PINGRESP. */
+#ifdef WITH_BROKER
+ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PINGRESP from %s", mosq->id);
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PINGRESP", mosq->id);
+#endif
+ return MOSQ_ERR_SUCCESS;
+}
+
+int _mosquitto_handle_pubackcomp(struct mosquitto *mosq, const char *type)
+{
+ uint16_t mid;
+ int rc;
+
+ assert(mosq);
+#ifdef WITH_STRICT_PROTOCOL
+ if(mosq->in_packet.remaining_length != 2){
+ return MOSQ_ERR_PROTOCOL;
+ }
+#endif
+ rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
+ if(rc) return rc;
+#ifdef WITH_BROKER
+ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received %s from %s (Mid: %d)", type, mosq->id, mid);
+
+ if(mid){
+ rc = mqtt3_db_message_delete(mosq, mid, mosq_md_out);
+ if(rc) return rc;
+ }
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received %s (Mid: %d)", mosq->id, type, mid);
+
+ if(!_mosquitto_message_delete(mosq, mid, mosq_md_out)){
+ /* Only inform the client the message has been sent once. */
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_publish){
+ mosq->in_callback = true;
+ mosq->on_publish(mosq, mosq->userdata, mid);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+ }
+#endif
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+int _mosquitto_handle_pubrec(struct mosquitto *mosq)
+{
+ uint16_t mid;
+ int rc;
+
+ assert(mosq);
+#ifdef WITH_STRICT_PROTOCOL
+ if(mosq->in_packet.remaining_length != 2){
+ return MOSQ_ERR_PROTOCOL;
+ }
+#endif
+ rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
+ if(rc) return rc;
+#ifdef WITH_BROKER
+ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREC from %s (Mid: %d)", mosq->id, mid);
+
+ rc = mqtt3_db_message_update(mosq, mid, mosq_md_out, mosq_ms_wait_for_pubcomp);
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREC (Mid: %d)", mosq->id, mid);
+
+ rc = _mosquitto_message_out_update(mosq, mid, mosq_ms_wait_for_pubcomp);
+#endif
+ if(rc) return rc;
+ rc = _mosquitto_send_pubrel(mosq, mid, false);
+ if(rc) return rc;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+int _mosquitto_handle_pubrel(struct mosquitto_db *db, struct mosquitto *mosq)
+{
+ uint16_t mid;
+#ifndef WITH_BROKER
+ struct mosquitto_message_all *message = NULL;
+#endif
+ int rc;
+
+ assert(mosq);
+#ifdef WITH_STRICT_PROTOCOL
+ if(mosq->in_packet.remaining_length != 2){
+ return MOSQ_ERR_PROTOCOL;
+ }
+#endif
+ if(mosq->protocol == mosq_p_mqtt311){
+ if((mosq->in_packet.command&0x0F) != 0x02){
+ return MOSQ_ERR_PROTOCOL;
+ }
+ }
+ rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
+ if(rc) return rc;
+#ifdef WITH_BROKER
+ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREL from %s (Mid: %d)", mosq->id, mid);
+
+ if(mqtt3_db_message_release(db, mosq, mid, mosq_md_in)){
+ /* Message not found. Still send a PUBCOMP anyway because this could be
+ * due to a repeated PUBREL after a client has reconnected. */
+ }
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREL (Mid: %d)", mosq->id, mid);
+
+ if(!_mosquitto_message_remove(mosq, mid, mosq_md_in, &message)){
+ /* Only pass the message on if we have removed it from the queue - this
+ * prevents multiple callbacks for the same message. */
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_message){
+ mosq->in_callback = true;
+ mosq->on_message(mosq, mosq->userdata, &message->msg);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+ _mosquitto_message_cleanup(&message);
+ }
+#endif
+ rc = _mosquitto_send_pubcomp(mosq, mid);
+ if(rc) return rc;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+int _mosquitto_handle_suback(struct mosquitto *mosq)
+{
+ uint16_t mid;
+ uint8_t qos;
+ int *granted_qos;
+ int qos_count;
+ int i = 0;
+ int rc;
+
+ assert(mosq);
+#ifdef WITH_BROKER
+ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received SUBACK from %s", mosq->id);
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received SUBACK", mosq->id);
+#endif
+ rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
+ if(rc) return rc;
+
+ qos_count = mosq->in_packet.remaining_length - mosq->in_packet.pos;
+ granted_qos = _mosquitto_malloc(qos_count*sizeof(int));
+ if(!granted_qos) return MOSQ_ERR_NOMEM;
+ while(mosq->in_packet.pos < mosq->in_packet.remaining_length){
+ rc = _mosquitto_read_byte(&mosq->in_packet, &qos);
+ if(rc){
+ _mosquitto_free(granted_qos);
+ return rc;
+ }
+ granted_qos[i] = (int)qos;
+ i++;
+ }
+#ifndef WITH_BROKER
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_subscribe){
+ mosq->in_callback = true;
+ mosq->on_subscribe(mosq, mosq->userdata, mid, qos_count, granted_qos);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+#endif
+ _mosquitto_free(granted_qos);
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+int _mosquitto_handle_unsuback(struct mosquitto *mosq)
+{
+ uint16_t mid;
+ int rc;
+
+ assert(mosq);
+#ifdef WITH_STRICT_PROTOCOL
+ if(mosq->in_packet.remaining_length != 2){
+ return MOSQ_ERR_PROTOCOL;
+ }
+#endif
+#ifdef WITH_BROKER
+ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received UNSUBACK from %s", mosq->id);
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received UNSUBACK", mosq->id);
+#endif
+ rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
+ if(rc) return rc;
+#ifndef WITH_BROKER
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_unsubscribe){
+ mosq->in_callback = true;
+ mosq->on_unsubscribe(mosq, mosq->userdata, mid);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+#endif
+
+ return MOSQ_ERR_SUCCESS;
+}
+
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+#include <string.h>
+
+#include "mosquitto.h"
+#include "logging_mosq.h"
+#include "memory_mosq.h"
+#include "mqtt3_protocol.h"
+#include "net_mosq.h"
+#include "send_mosq.h"
+#include "util_mosq.h"
+
+#ifdef WITH_BROKER
+#include "mosquitto_broker.h"
+#endif
+
+int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session)
+{
+ struct _mosquitto_packet *packet = NULL;
+ int payloadlen;
+ uint8_t will = 0;
+ uint8_t byte;
+ int rc;
+ uint8_t version = PROTOCOL_VERSION_v31;
+
+ assert(mosq);
+ assert(mosq->id);
+
+ packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
+ if(!packet) return MOSQ_ERR_NOMEM;
+
+ payloadlen = 2+strlen(mosq->id);
+ if(mosq->will){
+ will = 1;
+ assert(mosq->will->topic);
+
+ payloadlen += 2+strlen(mosq->will->topic) + 2+mosq->will->payloadlen;
+ }
+ if(mosq->username){
+ payloadlen += 2+strlen(mosq->username);
+ if(mosq->password){
+ payloadlen += 2+strlen(mosq->password);
+ }
+ }
+
+ packet->command = CONNECT;
+ packet->remaining_length = 12+payloadlen;
+ rc = _mosquitto_packet_alloc(packet);
+ if(rc){
+ _mosquitto_free(packet);
+ return rc;
+ }
+
+ /* Variable header */
+ _mosquitto_write_string(packet, PROTOCOL_NAME_v31, strlen(PROTOCOL_NAME_v31));
+#if defined(WITH_BROKER) && defined(WITH_BRIDGE)
+ if(mosq->bridge && mosq->bridge->try_private && mosq->bridge->try_private_accepted){
+ version |= 0x80;
+ }else{
+ }
+#endif
+ _mosquitto_write_byte(packet, version);
+ byte = (clean_session&0x1)<<1;
+ if(will){
+ byte = byte | ((mosq->will->retain&0x1)<<5) | ((mosq->will->qos&0x3)<<3) | ((will&0x1)<<2);
+ }
+ if(mosq->username){
+ byte = byte | 0x1<<7;
+ if(mosq->password){
+ byte = byte | 0x1<<6;
+ }
+ }
+ _mosquitto_write_byte(packet, byte);
+ _mosquitto_write_uint16(packet, keepalive);
+
+ /* Payload */
+ _mosquitto_write_string(packet, mosq->id, strlen(mosq->id));
+ if(will){
+ _mosquitto_write_string(packet, mosq->will->topic, strlen(mosq->will->topic));
+ _mosquitto_write_string(packet, (const char *)mosq->will->payload, mosq->will->payloadlen);
+ }
+ if(mosq->username){
+ _mosquitto_write_string(packet, mosq->username, strlen(mosq->username));
+ if(mosq->password){
+ _mosquitto_write_string(packet, mosq->password, strlen(mosq->password));
+ }
+ }
+
+ mosq->keepalive = keepalive;
+#ifdef WITH_BROKER
+# ifdef WITH_BRIDGE
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending CONNECT", mosq->id);
+# endif
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending CONNECT", mosq->id);
+#endif
+ return _mosquitto_packet_queue(mosq, packet);
+}
+
+int _mosquitto_send_disconnect(struct mosquitto *mosq)
+{
+ assert(mosq);
+#ifdef WITH_BROKER
+# ifdef WITH_BRIDGE
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending DISCONNECT", mosq->id);
+# endif
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending DISCONNECT", mosq->id);
+#endif
+ return _mosquitto_send_simple_command(mosq, DISCONNECT);
+}
+
+int _mosquitto_send_subscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic, uint8_t topic_qos)
+{
+ /* FIXME - only deals with a single topic */
+ struct _mosquitto_packet *packet = NULL;
+ uint32_t packetlen;
+ uint16_t local_mid;
+ int rc;
+
+ assert(mosq);
+ assert(topic);
+
+ packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
+ if(!packet) return MOSQ_ERR_NOMEM;
+
+ packetlen = 2 + 2+strlen(topic) + 1;
+
+ packet->command = SUBSCRIBE | (dup<<3) | (1<<1);
+ packet->remaining_length = packetlen;
+ rc = _mosquitto_packet_alloc(packet);
+ if(rc){
+ _mosquitto_free(packet);
+ return rc;
+ }
+
+ /* Variable header */
+ local_mid = _mosquitto_mid_generate(mosq);
+ if(mid) *mid = (int)local_mid;
+ _mosquitto_write_uint16(packet, local_mid);
+
+ /* Payload */
+ _mosquitto_write_string(packet, topic, strlen(topic));
+ _mosquitto_write_byte(packet, topic_qos);
+
+#ifdef WITH_BROKER
+# ifdef WITH_BRIDGE
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d)", mosq->id, local_mid, topic, topic_qos);
+# endif
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d)", mosq->id, local_mid, topic, topic_qos);
+#endif
+
+ return _mosquitto_packet_queue(mosq, packet);
+}
+
+
+int _mosquitto_send_unsubscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic)
+{
+ /* FIXME - only deals with a single topic */
+ struct _mosquitto_packet *packet = NULL;
+ uint32_t packetlen;
+ uint16_t local_mid;
+ int rc;
+
+ assert(mosq);
+ assert(topic);
+
+ packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
+ if(!packet) return MOSQ_ERR_NOMEM;
+
+ packetlen = 2 + 2+strlen(topic);
+
+ packet->command = UNSUBSCRIBE | (dup<<3) | (1<<1);
+ packet->remaining_length = packetlen;
+ rc = _mosquitto_packet_alloc(packet);
+ if(rc){
+ _mosquitto_free(packet);
+ return rc;
+ }
+
+ /* Variable header */
+ local_mid = _mosquitto_mid_generate(mosq);
+ if(mid) *mid = (int)local_mid;
+ _mosquitto_write_uint16(packet, local_mid);
+
+ /* Payload */
+ _mosquitto_write_string(packet, topic, strlen(topic));
+
+#ifdef WITH_BROKER
+# ifdef WITH_BRIDGE
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending UNSUBSCRIBE (Mid: %d, Topic: %s)", mosq->id, local_mid, topic);
+# endif
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending UNSUBSCRIBE (Mid: %d, Topic: %s)", mosq->id, local_mid, topic);
+#endif
+ return _mosquitto_packet_queue(mosq, packet);
+}
+
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mosquitto.h"
+#include "mosquitto_internal.h"
+#include "logging_mosq.h"
+#include "mqtt3_protocol.h"
+#include "memory_mosq.h"
+#include "net_mosq.h"
+#include "send_mosq.h"
+#include "time_mosq.h"
+#include "util_mosq.h"
+
+#ifdef WITH_BROKER
+#include "mosquitto_broker.h"
+# ifdef WITH_SYS_TREE
+extern uint64_t g_pub_bytes_sent;
+# endif
+#endif
+
+int _mosquitto_send_pingreq(struct mosquitto *mosq)
+{
+ int rc;
+ assert(mosq);
+#ifdef WITH_BROKER
+ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGREQ to %s", mosq->id);
+#else
+ _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGREQ", mosq->id);
+#endif
+ rc = _mosquitto_send_simple_command(mosq, PINGREQ);
+ if(rc == MOSQ_ERR_SUCCESS){
+ mosq->ping_t = mosquitto_time();
+ }
+ return rc;
+}
+
+int _mosquitto_send_pingresp(struct mosquitto *mosq)
+{
+#ifdef WITH_BROKER
+ if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGRESP to %s", mosq->id);
+#else
+ if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGRESP", mosq->id);
+#endif
+ return _mosquitto_send_simple_command(mosq, PINGRESP);
+}
+
+int _mosquitto_send_puback(struct mosquitto *mosq, uint16_t mid)
+{
+#ifdef WITH_BROKER
+ if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBACK to %s (Mid: %d)", mosq->id, mid);
+#else
+ if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBACK (Mid: %d)", mosq->id, mid);
+#endif
+ return _mosquitto_send_command_with_mid(mosq, PUBACK, mid, false);
+}
+
+int _mosquitto_send_pubcomp(struct mosquitto *mosq, uint16_t mid)
+{
+#ifdef WITH_BROKER
+ if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBCOMP to %s (Mid: %d)", mosq->id, mid);
+#else
+ if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBCOMP (Mid: %d)", mosq->id, mid);
+#endif
+ return _mosquitto_send_command_with_mid(mosq, PUBCOMP, mid, false);
+}
+
+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)
+{
+#ifdef WITH_BROKER
+ size_t len;
+#ifdef WITH_BRIDGE
+ int i;
+ struct _mqtt3_bridge_topic *cur_topic;
+ bool match;
+ int rc;
+ char *mapped_topic = NULL;
+ char *topic_temp = NULL;
+#endif
+#endif
+ assert(mosq);
+ assert(topic);
+
+ if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
+#ifdef WITH_BROKER
+ if(mosq->listener && mosq->listener->mount_point){
+ len = strlen(mosq->listener->mount_point);
+ if(len < strlen(topic)){
+ topic += len;
+ }else{
+ /* Invalid topic string. Should never happen, but silently swallow the message anyway. */
+ return MOSQ_ERR_SUCCESS;
+ }
+ }
+#ifdef WITH_BRIDGE
+ if(mosq->bridge && mosq->bridge->topics && mosq->bridge->topic_remapping){
+ for(i=0; i<mosq->bridge->topic_count; i++){
+ cur_topic = &mosq->bridge->topics[i];
+ if((cur_topic->direction == bd_both || cur_topic->direction == bd_out)
+ && (cur_topic->remote_prefix || cur_topic->local_prefix)){
+ /* Topic mapping required on this topic if the message matches */
+
+ rc = mosquitto_topic_matches_sub(cur_topic->local_topic, topic, &match);
+ if(rc){
+ return rc;
+ }
+ if(match){
+ mapped_topic = _mosquitto_strdup(topic);
+ if(!mapped_topic) return MOSQ_ERR_NOMEM;
+ if(cur_topic->local_prefix){
+ /* This prefix needs removing. */
+ if(!strncmp(cur_topic->local_prefix, mapped_topic, strlen(cur_topic->local_prefix))){
+ topic_temp = _mosquitto_strdup(mapped_topic+strlen(cur_topic->local_prefix));
+ _mosquitto_free(mapped_topic);
+ if(!topic_temp){
+ return MOSQ_ERR_NOMEM;
+ }
+ mapped_topic = topic_temp;
+ }
+ }
+
+ if(cur_topic->remote_prefix){
+ /* This prefix needs adding. */
+ len = strlen(mapped_topic) + strlen(cur_topic->remote_prefix)+1;
+ topic_temp = _mosquitto_calloc(len+1, sizeof(char));
+ if(!topic_temp){
+ _mosquitto_free(mapped_topic);
+ return MOSQ_ERR_NOMEM;
+ }
+ snprintf(topic_temp, len, "%s%s", cur_topic->remote_prefix, mapped_topic);
+ _mosquitto_free(mapped_topic);
+ mapped_topic = topic_temp;
+ }
+ _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);
+#ifdef WITH_SYS_TREE
+ g_pub_bytes_sent += payloadlen;
+#endif
+ rc = _mosquitto_send_real_publish(mosq, mid, mapped_topic, payloadlen, payload, qos, retain, dup);
+ _mosquitto_free(mapped_topic);
+ return rc;
+ }
+ }
+ }
+ }
+#endif
+ _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);
+# ifdef WITH_SYS_TREE
+ g_pub_bytes_sent += payloadlen;
+# endif
+#else
+ _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);
+#endif
+
+ return _mosquitto_send_real_publish(mosq, mid, topic, payloadlen, payload, qos, retain, dup);
+}
+
+int _mosquitto_send_pubrec(struct mosquitto *mosq, uint16_t mid)
+{
+#ifdef WITH_BROKER
+ if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREC to %s (Mid: %d)", mosq->id, mid);
+#else
+ if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREC (Mid: %d)", mosq->id, mid);
+#endif
+ return _mosquitto_send_command_with_mid(mosq, PUBREC, mid, false);
+}
+
+int _mosquitto_send_pubrel(struct mosquitto *mosq, uint16_t mid, bool dup)
+{
+#ifdef WITH_BROKER
+ if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREL to %s (Mid: %d)", mosq->id, mid);
+#else
+ if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREL (Mid: %d)", mosq->id, mid);
+#endif
+ return _mosquitto_send_command_with_mid(mosq, PUBREL|2, mid, dup);
+}
+
+/* For PUBACK, PUBCOMP, PUBREC, and PUBREL */
+int _mosquitto_send_command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup)
+{
+ struct _mosquitto_packet *packet = NULL;
+ int rc;
+
+ assert(mosq);
+ packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
+ if(!packet) return MOSQ_ERR_NOMEM;
+
+ packet->command = command;
+ if(dup){
+ packet->command |= 8;
+ }
+ packet->remaining_length = 2;
+ rc = _mosquitto_packet_alloc(packet);
+ if(rc){
+ _mosquitto_free(packet);
+ return rc;
+ }
+
+ packet->payload[packet->pos+0] = MOSQ_MSB(mid);
+ packet->payload[packet->pos+1] = MOSQ_LSB(mid);
+
+ return _mosquitto_packet_queue(mosq, packet);
+}
+
+/* For DISCONNECT, PINGREQ and PINGRESP */
+int _mosquitto_send_simple_command(struct mosquitto *mosq, uint8_t command)
+{
+ struct _mosquitto_packet *packet = NULL;
+ int rc;
+
+ assert(mosq);
+ packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
+ if(!packet) return MOSQ_ERR_NOMEM;
+
+ packet->command = command;
+ packet->remaining_length = 0;
+
+ rc = _mosquitto_packet_alloc(packet);
+ if(rc){
+ _mosquitto_free(packet);
+ return rc;
+ }
+
+ return _mosquitto_packet_queue(mosq, packet);
+}
+
+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)
+{
+ struct _mosquitto_packet *packet = NULL;
+ int packetlen;
+ int rc;
+
+ assert(mosq);
+ assert(topic);
+
+ packetlen = 2+strlen(topic) + payloadlen;
+ if(qos > 0) packetlen += 2; /* For message id */
+ packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
+ if(!packet) return MOSQ_ERR_NOMEM;
+
+ packet->mid = mid;
+ packet->command = PUBLISH | ((dup&0x1)<<3) | (qos<<1) | retain;
+ packet->remaining_length = packetlen;
+ rc = _mosquitto_packet_alloc(packet);
+ if(rc){
+ _mosquitto_free(packet);
+ return rc;
+ }
+ /* Variable header (topic string) */
+ _mosquitto_write_string(packet, topic, strlen(topic));
+ if(qos > 0){
+ _mosquitto_write_uint16(packet, mid);
+ }
+
+ /* Payload */
+ if(payloadlen){
+ _mosquitto_write_bytes(packet, payload, payloadlen);
+ }
+
+ return _mosquitto_packet_queue(mosq, packet);
+}
--- /dev/null
+/*
+Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _SEND_MOSQ_H_
+#define _SEND_MOSQ_H_
+
+#include "mosquitto.h"
+
+int _mosquitto_send_simple_command(struct mosquitto *mosq, uint8_t command);
+int _mosquitto_send_command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup);
+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);
+
+int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session);
+int _mosquitto_send_disconnect(struct mosquitto *mosq);
+int _mosquitto_send_pingreq(struct mosquitto *mosq);
+int _mosquitto_send_pingresp(struct mosquitto *mosq);
+int _mosquitto_send_puback(struct mosquitto *mosq, uint16_t mid);
+int _mosquitto_send_pubcomp(struct mosquitto *mosq, uint16_t mid);
+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);
+int _mosquitto_send_pubrec(struct mosquitto *mosq, uint16_t mid);
+int _mosquitto_send_pubrel(struct mosquitto *mosq, uint16_t mid, bool dup);
+int _mosquitto_send_subscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic, uint8_t topic_qos);
+int _mosquitto_send_unsubscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic);
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef WITH_SRV
+# include <ares.h>
+
+# include <arpa/nameser.h>
+# include <stdio.h>
+# include <string.h>
+#endif
+
+#include "logging_mosq.h"
+#include "memory_mosq.h"
+#include "mosquitto_internal.h"
+#include "mosquitto.h"
+
+#ifdef WITH_SRV
+static void srv_callback(void *arg, int status, int timeouts, unsigned char *abuf, int alen)
+{
+ struct mosquitto *mosq = arg;
+ struct ares_srv_reply *reply = NULL;
+ if(status == ARES_SUCCESS){
+ status = ares_parse_srv_reply(abuf, alen, &reply);
+ if(status == ARES_SUCCESS){
+ // FIXME - choose which answer to use based on rfc2782 page 3. */
+ mosquitto_connect(mosq, reply->host, reply->port, mosq->keepalive);
+ }
+ }else{
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: SRV lookup failed (%d).", status);
+ exit(1);
+ }
+}
+#endif
+
+int mosquitto_connect_srv(struct mosquitto *mosq, const char *host, int keepalive, const char *bind_address)
+{
+#ifdef WITH_SRV
+ char *h;
+ int rc;
+ if(!mosq) return MOSQ_ERR_INVAL;
+
+ rc = ares_init(&mosq->achan);
+ if(rc != ARES_SUCCESS){
+ return MOSQ_ERR_UNKNOWN;
+ }
+
+ if(!host){
+ // get local domain
+ }else{
+#ifdef WITH_TLS
+ if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
+ h = _mosquitto_malloc(strlen(host) + strlen("_secure-mqtt._tcp.") + 1);
+ if(!h) return MOSQ_ERR_NOMEM;
+ sprintf(h, "_secure-mqtt._tcp.%s", host);
+ }else{
+#endif
+ h = _mosquitto_malloc(strlen(host) + strlen("_mqtt._tcp.") + 1);
+ if(!h) return MOSQ_ERR_NOMEM;
+ sprintf(h, "_mqtt._tcp.%s", host);
+#ifdef WITH_TLS
+ }
+#endif
+ ares_search(mosq->achan, h, ns_c_in, ns_t_srv, srv_callback, mosq);
+ _mosquitto_free(h);
+ }
+
+ pthread_mutex_lock(&mosq->state_mutex);
+ mosq->state = mosq_cs_connect_srv;
+ pthread_mutex_unlock(&mosq->state_mutex);
+
+ mosq->keepalive = keepalive;
+
+ return MOSQ_ERR_SUCCESS;
+
+#else
+ return MOSQ_ERR_NOT_SUPPORTED;
+#endif
+}
+
+
--- /dev/null
+/*
+Copyright (c) 2011-2014 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "config.h"
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include "mosquitto_internal.h"
+#include "net_mosq.h"
+
+void *_mosquitto_thread_main(void *obj);
+
+int mosquitto_loop_start(struct mosquitto *mosq)
+{
+#ifdef WITH_THREADING
+ if(!mosq || mosq->threaded) return MOSQ_ERR_INVAL;
+
+ mosq->threaded = true;
+ pthread_create(&mosq->thread_id, NULL, _mosquitto_thread_main, mosq);
+ return MOSQ_ERR_SUCCESS;
+#else
+ return MOSQ_ERR_NOT_SUPPORTED;
+#endif
+}
+
+int mosquitto_loop_stop(struct mosquitto *mosq, bool force)
+{
+#ifdef WITH_THREADING
+# ifndef WITH_BROKER
+ char sockpair_data = 0;
+# endif
+
+ if(!mosq || !mosq->threaded) return MOSQ_ERR_INVAL;
+
+
+ /* Write a single byte to sockpairW (connected to sockpairR) to break out
+ * of select() if in threaded mode. */
+ if(mosq->sockpairW != INVALID_SOCKET){
+#ifndef WIN32
+ if(write(mosq->sockpairW, &sockpair_data, 1)){
+ }
+#else
+ send(mosq->sockpairW, &sockpair_data, 1, 0);
+#endif
+ }
+
+ if(force){
+ pthread_cancel(mosq->thread_id);
+ }
+ pthread_join(mosq->thread_id, NULL);
+ mosq->thread_id = pthread_self();
+ mosq->threaded = false;
+
+ return MOSQ_ERR_SUCCESS;
+#else
+ return MOSQ_ERR_NOT_SUPPORTED;
+#endif
+}
+
+#ifdef WITH_THREADING
+void *_mosquitto_thread_main(void *obj)
+{
+ struct mosquitto *mosq = obj;
+
+ if(!mosq) return NULL;
+
+ pthread_mutex_lock(&mosq->state_mutex);
+ if(mosq->state == mosq_cs_connect_async){
+ pthread_mutex_unlock(&mosq->state_mutex);
+ mosquitto_reconnect(mosq);
+ }else{
+ pthread_mutex_unlock(&mosq->state_mutex);
+ }
+
+ if(!mosq->keepalive){
+ /* Sleep for a day if keepalive disabled. */
+ mosquitto_loop_forever(mosq, mosq->keepalive*1000*86400, 1);
+ }else{
+ /* Sleep for our keepalive value. publish() etc. will wake us up. */
+ mosquitto_loop_forever(mosq, mosq->keepalive*1000, 1);
+ }
+
+ return obj;
+}
+#endif
+
--- /dev/null
+/*
+Copyright (c) 2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef __APPLE__
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#endif
+
+#ifdef WIN32
+# define _WIN32_WINNT _WIN32_WINNT_VISTA
+# include <windows.h>
+#else
+# include <unistd.h>
+#endif
+#include <time.h>
+
+#include "mosquitto.h"
+#include "time_mosq.h"
+
+#ifdef WIN32
+static bool tick64 = false;
+
+void _windows_time_version_check(void)
+{
+ OSVERSIONINFO vi;
+
+ tick64 = false;
+
+ memset(&vi, 0, sizeof(OSVERSIONINFO));
+ vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if(GetVersionEx(&vi)){
+ if(vi.dwMajorVersion > 5){
+ tick64 = true;
+ }
+ }
+}
+#endif
+
+time_t mosquitto_time(void)
+{
+#ifdef WIN32
+ if(tick64){
+ return GetTickCount64()/1000;
+ }else{
+ return GetTickCount()/1000; /* FIXME - need to deal with overflow. */
+ }
+#elif _POSIX_TIMERS>0 && defined(_POSIX_MONOTONIC_CLOCK)
+ struct timespec tp;
+
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ return tp.tv_sec;
+#elif defined(__APPLE__)
+ static mach_timebase_info_data_t tb;
+ uint64_t ticks;
+ uint64_t sec;
+
+ ticks = mach_absolute_time();
+
+ if(tb.denom == 0){
+ mach_timebase_info(&tb);
+ }
+ sec = ticks*tb.numer/tb.denom/1000000000;
+
+ return (time_t)sec;
+#else
+ return time(NULL);
+#endif
+}
+
--- /dev/null
+/*
+Copyright (c) 2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _TIME_MOSQ_H_
+#define _TIME_MOSQ_H_
+
+time_t mosquitto_time(void);
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef WITH_TLS
+
+#ifdef WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#else
+# include <arpa/inet.h>
+#endif
+
+#include <string.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+
+#ifdef WITH_BROKER
+# include "mosquitto_broker.h"
+#endif
+#include "mosquitto_internal.h"
+#include "tls_mosq.h"
+
+extern int tls_ex_index_mosq;
+
+int _mosquitto_server_certificate_verify(int preverify_ok, X509_STORE_CTX *ctx)
+{
+ /* Preverify should have already checked expiry, revocation.
+ * We need to verify the hostname. */
+ struct mosquitto *mosq;
+ SSL *ssl;
+ X509 *cert;
+
+ /* Always reject if preverify_ok has failed. */
+ if(!preverify_ok) return 0;
+
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+ mosq = SSL_get_ex_data(ssl, tls_ex_index_mosq);
+ if(!mosq) return 0;
+
+ if(mosq->tls_insecure == false){
+ if(X509_STORE_CTX_get_error_depth(ctx) == 0){
+ /* FIXME - use X509_check_host() etc. for sufficiently new openssl (>=1.1.x) */
+ cert = X509_STORE_CTX_get_current_cert(ctx);
+ /* This is the peer certificate, all others are upwards in the chain. */
+#if defined(WITH_BROKER)
+ return _mosquitto_verify_certificate_hostname(cert, mosq->bridge->addresses[mosq->bridge->cur_address].address);
+#else
+ return _mosquitto_verify_certificate_hostname(cert, mosq->host);
+#endif
+ }else{
+ return preverify_ok;
+ }
+ }else{
+ return preverify_ok;
+ }
+}
+
+/* This code is based heavily on the example provided in "Secure Programming
+ * Cookbook for C and C++".
+ */
+int _mosquitto_verify_certificate_hostname(X509 *cert, const char *hostname)
+{
+ int i;
+ char name[256];
+ X509_NAME *subj;
+ bool have_san_dns = false;
+ STACK_OF(GENERAL_NAME) *san;
+ const GENERAL_NAME *nval;
+ const unsigned char *data;
+ unsigned char ipv6_addr[16];
+ unsigned char ipv4_addr[4];
+ int ipv6_ok;
+ int ipv4_ok;
+
+#ifdef WIN32
+ ipv6_ok = InetPton(AF_INET6, hostname, &ipv6_addr);
+ ipv4_ok = InetPton(AF_INET, hostname, &ipv4_addr);
+#else
+ ipv6_ok = inet_pton(AF_INET6, hostname, &ipv6_addr);
+ ipv4_ok = inet_pton(AF_INET, hostname, &ipv4_addr);
+#endif
+
+ san = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
+ if(san){
+ for(i=0; i<sk_GENERAL_NAME_num(san); i++){
+ nval = sk_GENERAL_NAME_value(san, i);
+ if(nval->type == GEN_DNS){
+ data = ASN1_STRING_data(nval->d.dNSName);
+ if(data && !strcasecmp((char *)data, hostname)){
+ return 1;
+ }
+ have_san_dns = true;
+ }else if(nval->type == GEN_IPADD){
+ data = ASN1_STRING_data(nval->d.iPAddress);
+ if(nval->d.iPAddress->length == 4 && ipv4_ok){
+ if(!memcmp(ipv4_addr, data, 4)){
+ return 1;
+ }
+ }else if(nval->d.iPAddress->length == 16 && ipv6_ok){
+ if(!memcmp(ipv6_addr, data, 16)){
+ return 1;
+ }
+ }
+ }
+ }
+ if(have_san_dns){
+ /* Only check CN if subjectAltName DNS entry does not exist. */
+ return 0;
+ }
+ }
+ subj = X509_get_subject_name(cert);
+ if(X509_NAME_get_text_by_NID(subj, NID_commonName, name, sizeof(name)) > 0){
+ name[sizeof(name) - 1] = '\0';
+ if (!strcasecmp(name, hostname)) return 1;
+ }
+ return 0;
+}
+
+#endif
+
--- /dev/null
+/*
+Copyright (c) 2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _TLS_MOSQ_H_
+#define _TLS_MOSQ_H_
+
+#ifdef WITH_TLS
+
+#include <openssl/ssl.h>
+#ifdef WITH_TLS_PSK
+# if OPENSSL_VERSION_NUMBER >= 0x10000000
+# define REAL_WITH_TLS_PSK
+# else
+# warning "TLS-PSK not supported, openssl too old."
+# endif
+#endif
+
+int _mosquitto_server_certificate_verify(int preverify_ok, X509_STORE_CTX *ctx);
+int _mosquitto_verify_certificate_hostname(X509 *cert, const char *hostname);
+
+#endif /* WITH_TLS */
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+#include <string.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#endif
+
+
+#include "mosquitto.h"
+#include "memory_mosq.h"
+#include "net_mosq.h"
+#include "send_mosq.h"
+#include "time_mosq.h"
+#include "tls_mosq.h"
+#include "util_mosq.h"
+
+#ifdef WITH_BROKER
+#include "mosquitto_broker.h"
+#endif
+
+int _mosquitto_packet_alloc(struct _mosquitto_packet *packet)
+{
+ uint8_t remaining_bytes[5], byte;
+ uint32_t remaining_length;
+ int i;
+
+ assert(packet);
+
+ remaining_length = packet->remaining_length;
+ packet->payload = NULL;
+ packet->remaining_count = 0;
+ do{
+ byte = remaining_length % 128;
+ remaining_length = remaining_length / 128;
+ /* If there are more digits to encode, set the top bit of this digit */
+ if(remaining_length > 0){
+ byte = byte | 0x80;
+ }
+ remaining_bytes[packet->remaining_count] = byte;
+ packet->remaining_count++;
+ }while(remaining_length > 0 && packet->remaining_count < 5);
+ if(packet->remaining_count == 5) return MOSQ_ERR_PAYLOAD_SIZE;
+ packet->packet_length = packet->remaining_length + 1 + packet->remaining_count;
+ packet->payload = _mosquitto_malloc(sizeof(uint8_t)*packet->packet_length);
+ if(!packet->payload) return MOSQ_ERR_NOMEM;
+
+ packet->payload[0] = packet->command;
+ for(i=0; i<packet->remaining_count; i++){
+ packet->payload[i+1] = remaining_bytes[i];
+ }
+ packet->pos = 1 + packet->remaining_count;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+void _mosquitto_check_keepalive(struct mosquitto *mosq)
+{
+ time_t last_msg_out;
+ time_t last_msg_in;
+ time_t now = mosquitto_time();
+#ifndef WITH_BROKER
+ int rc;
+#endif
+
+ assert(mosq);
+#if defined(WITH_BROKER) && defined(WITH_BRIDGE)
+ /* Check if a lazy bridge should be timed out due to idle. */
+ if(mosq->bridge && mosq->bridge->start_type == bst_lazy
+ && mosq->sock != INVALID_SOCKET
+ && now - mosq->last_msg_out >= mosq->bridge->idle_timeout){
+
+ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Bridge connection %s has exceeded idle timeout, disconnecting.", mosq->id);
+ _mosquitto_socket_close(mosq);
+ return;
+ }
+#endif
+ pthread_mutex_lock(&mosq->msgtime_mutex);
+ last_msg_out = mosq->last_msg_out;
+ last_msg_in = mosq->last_msg_in;
+ pthread_mutex_unlock(&mosq->msgtime_mutex);
+ if(mosq->keepalive && mosq->sock != INVALID_SOCKET &&
+ (now - last_msg_out >= mosq->keepalive || now - last_msg_in >= mosq->keepalive)){
+
+ if(mosq->state == mosq_cs_connected && mosq->ping_t == 0){
+ _mosquitto_send_pingreq(mosq);
+ /* Reset last msg times to give the server time to send a pingresp */
+ pthread_mutex_lock(&mosq->msgtime_mutex);
+ mosq->last_msg_in = now;
+ mosq->last_msg_out = now;
+ pthread_mutex_unlock(&mosq->msgtime_mutex);
+ }else{
+#ifdef WITH_BROKER
+ if(mosq->listener){
+ mosq->listener->client_count--;
+ assert(mosq->listener->client_count >= 0);
+ }
+ mosq->listener = NULL;
+#endif
+ _mosquitto_socket_close(mosq);
+#ifndef WITH_BROKER
+ pthread_mutex_lock(&mosq->state_mutex);
+ if(mosq->state == mosq_cs_disconnecting){
+ rc = MOSQ_ERR_SUCCESS;
+ }else{
+ rc = 1;
+ }
+ pthread_mutex_unlock(&mosq->state_mutex);
+ pthread_mutex_lock(&mosq->callback_mutex);
+ if(mosq->on_disconnect){
+ mosq->in_callback = true;
+ mosq->on_disconnect(mosq, mosq->userdata, rc);
+ mosq->in_callback = false;
+ }
+ pthread_mutex_unlock(&mosq->callback_mutex);
+#endif
+ }
+ }
+}
+
+uint16_t _mosquitto_mid_generate(struct mosquitto *mosq)
+{
+ assert(mosq);
+
+ mosq->last_mid++;
+ if(mosq->last_mid == 0) mosq->last_mid++;
+
+ return mosq->last_mid;
+}
+
+/* Search for + or # in a topic. Return MOSQ_ERR_INVAL if found.
+ * Also returns MOSQ_ERR_INVAL if the topic string is too long.
+ * Returns MOSQ_ERR_SUCCESS if everything is fine.
+ */
+int _mosquitto_topic_wildcard_len_check(const char *str)
+{
+ int len = 0;
+ while(str && str[0]){
+ if(str[0] == '+' || str[0] == '#'){
+ return MOSQ_ERR_INVAL;
+ }
+ len++;
+ str = &str[1];
+ }
+ if(len > 65535) return MOSQ_ERR_INVAL;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+/* Search for + or # in a topic, check they aren't in invalid positions such as foo/#/bar, foo/+bar or foo/bar#.
+ * Return MOSQ_ERR_INVAL if invalid position found.
+ * Also returns MOSQ_ERR_INVAL if the topic string is too long.
+ * Returns MOSQ_ERR_SUCCESS if everything is fine.
+ */
+int _mosquitto_topic_wildcard_pos_check(const char *str)
+{
+ char c = '\0';
+ int len = 0;
+ while(str && str[0]){
+ if(str[0] == '+'){
+ if((c != '\0' && c != '/') || (str[1] != '\0' && str[1] != '/')){
+ return MOSQ_ERR_INVAL;
+ }
+ }else if(str[0] == '#'){
+ if((c != '\0' && c != '/') || str[1] != '\0'){
+ return MOSQ_ERR_INVAL;
+ }
+ }
+ len++;
+ c = str[0];
+ str = &str[1];
+ }
+ if(len > 65535) return MOSQ_ERR_INVAL;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+/* Does a topic match a subscription? */
+int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)
+{
+ int slen, tlen;
+ int spos, tpos;
+ bool multilevel_wildcard = false;
+
+ if(!sub || !topic || !result) return MOSQ_ERR_INVAL;
+
+ slen = strlen(sub);
+ tlen = strlen(topic);
+
+ if(slen && tlen){
+ if((sub[0] == '$' && topic[0] != '$')
+ || (topic[0] == '$' && sub[0] != '$')){
+
+ *result = false;
+ return MOSQ_ERR_SUCCESS;
+ }
+ }
+
+ spos = 0;
+ tpos = 0;
+
+ while(spos < slen && tpos < tlen){
+ if(sub[spos] == topic[tpos]){
+ spos++;
+ tpos++;
+ if(spos == slen && tpos == tlen){
+ *result = true;
+ return MOSQ_ERR_SUCCESS;
+ }else if(tpos == tlen && spos == slen-1 && sub[spos] == '+'){
+ spos++;
+ *result = true;
+ return MOSQ_ERR_SUCCESS;
+ }
+ }else{
+ if(sub[spos] == '+'){
+ spos++;
+ while(tpos < tlen && topic[tpos] != '/'){
+ tpos++;
+ }
+ if(tpos == tlen && spos == slen){
+ *result = true;
+ return MOSQ_ERR_SUCCESS;
+ }
+ }else if(sub[spos] == '#'){
+ multilevel_wildcard = true;
+ if(spos+1 != slen){
+ *result = false;
+ return MOSQ_ERR_SUCCESS;
+ }else{
+ *result = true;
+ return MOSQ_ERR_SUCCESS;
+ }
+ }else{
+ *result = false;
+ return MOSQ_ERR_SUCCESS;
+ }
+ }
+ if(tpos == tlen-1){
+ /* Check for e.g. foo matching foo/# */
+ if(spos == slen-3
+ && sub[spos+1] == '/'
+ && sub[spos+2] == '#'){
+ *result = true;
+ multilevel_wildcard = true;
+ return MOSQ_ERR_SUCCESS;
+ }
+ }
+ }
+ if(multilevel_wildcard == false && (tpos < tlen || spos < slen)){
+ *result = false;
+ }
+
+ return MOSQ_ERR_SUCCESS;
+}
+
+#ifdef REAL_WITH_TLS_PSK
+int _mosquitto_hex2bin(const char *hex, unsigned char *bin, int bin_max_len)
+{
+ BIGNUM *bn = NULL;
+ int len;
+
+ if(BN_hex2bn(&bn, hex) == 0){
+ if(bn) BN_free(bn);
+ return 0;
+ }
+ if(BN_num_bytes(bn) > bin_max_len){
+ BN_free(bn);
+ return 0;
+ }
+
+ len = BN_bn2bin(bn, bin);
+ BN_free(bn);
+ return len;
+}
+#endif
+
+FILE *_mosquitto_fopen(const char *path, const char *mode)
+{
+#ifdef WIN32
+ char buf[MAX_PATH];
+ int rc;
+ rc = ExpandEnvironmentStrings(path, buf, MAX_PATH);
+ if(rc == 0 || rc == MAX_PATH){
+ return NULL;
+ }else{
+ return fopen(buf, mode);
+ }
+#else
+ return fopen(path, mode);
+#endif
+}
+
--- /dev/null
+/*
+Copyright (c) 2009-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _UTIL_MOSQ_H_
+#define _UTIL_MOSQ_H_
+
+#include <stdio.h>
+
+#include "tls_mosq.h"
+#include "mosquitto.h"
+
+int _mosquitto_packet_alloc(struct _mosquitto_packet *packet);
+void _mosquitto_check_keepalive(struct mosquitto *mosq);
+uint16_t _mosquitto_mid_generate(struct mosquitto *mosq);
+int _mosquitto_topic_wildcard_len_check(const char *str);
+int _mosquitto_topic_wildcard_pos_check(const char *str);
+FILE *_mosquitto_fopen(const char *path, const char *mode);
+
+#ifdef REAL_WITH_TLS_PSK
+int _mosquitto_hex2bin(const char *hex, unsigned char *bin, int bin_max_len);
+#endif
+
+#endif
--- /dev/null
+/*
+Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef WIN32
+#include <sys/select.h>
+#include <unistd.h>
+#else
+#include <winsock2.h>
+typedef int ssize_t;
+#endif
+
+#include "mosquitto.h"
+#include "mosquitto_internal.h"
+#include "logging_mosq.h"
+#include "messages_mosq.h"
+#include "memory_mosq.h"
+#include "mqtt3_protocol.h"
+#include "net_mosq.h"
+#include "read_handle.h"
+#include "send_mosq.h"
+#include "util_mosq.h"
+
+int _mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain)
+{
+ int rc = MOSQ_ERR_SUCCESS;
+
+ if(!mosq || !topic) return MOSQ_ERR_INVAL;
+ if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE;
+ if(payloadlen > 0 && !payload) return MOSQ_ERR_INVAL;
+
+ if(_mosquitto_topic_wildcard_pos_check(topic)) return MOSQ_ERR_INVAL;
+
+ if(mosq->will){
+ if(mosq->will->topic){
+ _mosquitto_free(mosq->will->topic);
+ mosq->will->topic = NULL;
+ }
+ if(mosq->will->payload){
+ _mosquitto_free(mosq->will->payload);
+ mosq->will->payload = NULL;
+ }
+ _mosquitto_free(mosq->will);
+ mosq->will = NULL;
+ }
+
+ mosq->will = _mosquitto_calloc(1, sizeof(struct mosquitto_message));
+ if(!mosq->will) return MOSQ_ERR_NOMEM;
+ mosq->will->topic = _mosquitto_strdup(topic);
+ if(!mosq->will->topic){
+ rc = MOSQ_ERR_NOMEM;
+ goto cleanup;
+ }
+ mosq->will->payloadlen = payloadlen;
+ if(mosq->will->payloadlen > 0){
+ if(!payload){
+ rc = MOSQ_ERR_INVAL;
+ goto cleanup;
+ }
+ mosq->will->payload = _mosquitto_malloc(sizeof(char)*mosq->will->payloadlen);
+ if(!mosq->will->payload){
+ rc = MOSQ_ERR_NOMEM;
+ goto cleanup;
+ }
+
+ memcpy(mosq->will->payload, payload, payloadlen);
+ }
+ mosq->will->qos = qos;
+ mosq->will->retain = retain;
+
+ return MOSQ_ERR_SUCCESS;
+
+cleanup:
+ if(mosq->will){
+ if(mosq->will->topic) _mosquitto_free(mosq->will->topic);
+ if(mosq->will->payload) _mosquitto_free(mosq->will->payload);
+ }
+ _mosquitto_free(mosq->will);
+ mosq->will = NULL;
+
+ return rc;
+}
+
+int _mosquitto_will_clear(struct mosquitto *mosq)
+{
+ if(!mosq->will) return MOSQ_ERR_SUCCESS;
+
+ if(mosq->will->topic){
+ _mosquitto_free(mosq->will->topic);
+ mosq->will->topic = NULL;
+ }
+ if(mosq->will->payload){
+ _mosquitto_free(mosq->will->payload);
+ mosq->will->payload = NULL;
+ }
+ _mosquitto_free(mosq->will);
+ mosq->will = NULL;
+
+ return MOSQ_ERR_SUCCESS;
+}
+
--- /dev/null
+/*
+Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of mosquitto nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _WILL_MOSQ_H_
+#define _WILL_MOSQ_H_
+
+#include "mosquitto.h"
+#include "mosquitto_internal.h"
+
+int _mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain);
+int _mosquitto_will_clear(struct mosquitto *mosq);
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+///
+/// This sample provides steps to define an interface for a resource
+/// (properties and methods) and host this resource on the server.
+///
+
+#include <functional>
+#include <pthread.h>
+#include <cpluff.h>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "../lib/mosquitto.h"
+#include "lightserver.h"
+
+#include <time.h>
+
+using namespace OC;
+using namespace std;
+namespace PH = std::placeholders;
+
+time_t timer; // Define the timer
+struct tm *tblock; // Define a structure for time block
+
+int gObservation = 0;
+void *ChangeLightRepresentation (void *param);
+
+// Specifies where to notify all observers or list of observers
+// 0 - notifies all observers
+// 1 - notifies list of observers
+int isListOfObservers = 0;
+
+// Forward declaring the entityHandler
+
+/// This class represents a single resource named 'lightResource'. This resource has
+/// two simple properties named 'state' and 'power'
+
+
+
+// Forward declaring the entityHandler
+// void entityHandler(std::shared_ptr<OCResourceRequest> request,
+// std::shared_ptr<OCResourceResponse> response);
+
+/// This class represents a single resource named 'lightResource'. This resource has
+/// two simple properties named 'state' and 'power'
+typedef struct plugin_data_t plugin_data_t;
+
+struct plugin_data_t
+{
+ cp_context_t *ctx;
+ pthread_t m_thread; // 2
+ void *str;
+ bool flag;
+};
+
+
+class LightResource
+{
+ public:
+ /// Access this property from a TB client
+ std::string m_name;
+ bool m_state;
+ int m_power;
+ int m_health;
+ std::string m_lightUri;
+ OCResourceHandle m_resourceHandle;
+ OCRepresentation m_lightRep;
+ ObservationIds m_interestedObservers;
+
+ public:
+ /// Constructor
+ LightResource(): m_name("John's light"), m_state(false), m_power(0), m_lightUri("/a/light")
+ {
+ // Initialize representation
+ m_lightRep.setUri(m_lightUri);
+
+ m_lightRep.setValue("state", m_state);
+ m_lightRep.setValue("power", m_power);
+ m_lightRep.setValue("name", m_name);
+ }
+
+
+ /* Note that this does not need to be a member function: for classes you do not have
+ access to, you can accomplish this with a free function: */
+
+ /// This function internally calls registerResource API.
+ void createResource()
+ {
+ std::string resourceURI = m_lightUri; // URI of the resource
+ std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
+ std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
+
+ // OCResourceProperty is defined ocstack.h
+ uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
+
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+
+ // This will internally create and register the resource.
+ OCStackResult result = OCPlatform::registerResource(
+ m_resourceHandle, resourceURI, resourceTypeName,
+ resourceInterface, cb, resourceProperty);
+
+ if (OC_STACK_OK != result)
+ {
+ cout << "Resource creation was unsuccessful\n";
+ }
+ }
+
+ OCStackResult createResource1()
+ {
+ std::string resourceURI = "/a/light1"; // URI of the resource
+ std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
+ std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
+
+ // OCResourceProperty is defined ocstack.h
+ uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
+
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+
+ OCResourceHandle resHandle;
+
+ // This will internally create and register the resource.
+ OCStackResult result = OCPlatform::registerResource(
+ resHandle, resourceURI, resourceTypeName,
+ resourceInterface, cb, resourceProperty);
+
+ if (OC_STACK_OK != result)
+ {
+ cout << "Resource creation was unsuccessful\n";
+ }
+
+ return result;
+ }
+
+ OCResourceHandle getHandle()
+ {
+ return m_resourceHandle;
+ }
+
+ // Puts representation.
+ // Gets values from the representation and
+ // updates the internal state
+ void put(OCRepresentation &rep)
+ {
+ try
+ {
+ if (rep.getValue("state", m_state))
+ {
+ cout << "\t\t\t\t" << "state: " << m_state << endl;
+ }
+ else
+ {
+ cout << "\t\t\t\t" << "state not found in the representation" << endl;
+ }
+
+ if (rep.getValue("power", m_power))
+ {
+ cout << "\t\t\t\t" << "power: " << m_power << endl;
+ }
+ else
+ {
+ cout << "\t\t\t\t" << "power not found in the representation" << endl;
+ }
+ }
+ catch (exception &e)
+ {
+ cout << e.what() << endl;
+ }
+
+ }
+
+ // Post representation.
+ // Post can create new resource or simply act like put.
+ // Gets values from the representation and
+ // updates the internal state
+ OCRepresentation post(OCRepresentation &rep)
+ {
+ static int first = 1;
+
+ // for the first time it tries to create a resource
+ if (first)
+ {
+ first = 0;
+
+ if (OC_STACK_OK == createResource1())
+ {
+ OCRepresentation rep1;
+ rep1.setValue("createduri", std::string("/a/light1"));
+
+ return rep1;
+ }
+ }
+
+ // from second time onwards it just puts
+ put(rep);
+ return get();
+ }
+
+
+ // gets the updated representation.
+ // Updates the representation with latest internal state before
+ // sending out.
+ OCRepresentation get()
+ {
+ m_lightRep.setValue("state", m_state);
+ m_lightRep.setValue("power", m_power);
+
+ return m_lightRep;
+ }
+
+
+ void addType(const std::string &type) const
+ {
+ OCStackResult result = OCPlatform::bindTypeToResource(m_resourceHandle, type);
+ if (OC_STACK_OK != result)
+ {
+ cout << "Binding TypeName to Resource was unsuccessful\n";
+ }
+ }
+
+ void addInterface(const std::string &interface) const
+ {
+ OCStackResult result = OCPlatform::bindInterfaceToResource(m_resourceHandle, interface);
+ if (OC_STACK_OK != result)
+ {
+ cout << "Binding TypeName to Resource was unsuccessful\n";
+ }
+ }
+
+ private:
+ // This is just a sample implementation of entity handler.
+ // Entity handler can be implemented in several ways by the manufacturer
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
+ std::shared_ptr<OCResourceResponse> response)
+ {
+ OCEntityHandlerResult result = OC_EH_OK;
+
+ cout << "\tIn Server CPP entity handler:\n";
+
+ if (request)
+ {
+ // Get the request type and request flag
+ std::string requestType = request->getRequestType();
+ int requestFlag = request->getRequestHandlerFlag();
+
+ if (requestFlag & RequestHandlerFlag::InitFlag)
+ {
+ cout << "\t\trequestFlag : Init\n";
+
+ // entity handler to perform resource initialization operations
+ }
+ if (requestFlag & RequestHandlerFlag::RequestFlag)
+ {
+ cout << "\t\trequestFlag : Request === Handle by LightServer\n";
+
+ // If the request type is GET
+ if (requestType == "GET")
+ {
+ cout << "\t\t\trequestType : GET\n";
+
+ if (response)
+ {
+ // TODO Error Code
+ response->setErrorCode(200);
+
+ response->setResourceRepresentation(get());
+ }
+ }
+ else if (requestType == "PUT")
+ {
+ cout << "\t\t\trequestType : PUT\n";
+
+ OCRepresentation rep = request->getResourceRepresentation();
+
+ // Do related operations related to PUT request
+
+ // Update the lightResource
+ put(rep);
+
+ if (response)
+ {
+ // TODO Error Code
+ response->setErrorCode(200);
+
+ response->setResourceRepresentation(get());
+ }
+
+ }
+ else if (requestType == "POST")
+ {
+ cout << "\t\t\trequestType : POST\n";
+
+ OCRepresentation rep = request->getResourceRepresentation();
+
+ // Do related operations related to POST request
+
+ OCRepresentation rep_post = post(rep);
+
+ if (response)
+ {
+ // TODO Error Code
+ response->setErrorCode(200);
+
+ response->setResourceRepresentation(rep_post);
+
+ if (rep_post.hasAttribute("createduri"))
+ {
+ result = OC_EH_RESOURCE_CREATED;
+
+ response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
+ }
+
+ }
+
+ // POST request operations
+ }
+ else if (requestType == "DELETE")
+ {
+ // DELETE request operations
+ }
+ }
+
+ if (requestFlag & RequestHandlerFlag::ObserverFlag)
+ {
+ ObservationInfo observationInfo = request->getObservationInfo();
+ if (ObserveAction::ObserveRegister == observationInfo.action)
+ {
+ m_interestedObservers.push_back(observationInfo.obsId);
+ }
+ else if (ObserveAction::ObserveUnregister == observationInfo.action)
+ {
+ m_interestedObservers.erase(std::remove(
+ m_interestedObservers.begin(),
+ m_interestedObservers.end(),
+ observationInfo.obsId),
+ m_interestedObservers.end());
+ }
+
+ pthread_t threadId;
+
+ cout << "\t\trequestFlag : Observer\n";
+ gObservation = 1;
+ static int startedThread = 0;
+
+ // Observation happens on a different thread in ChangeLightRepresentation function.
+ // If we have not created the thread already, we will create one here.
+ if (!startedThread)
+ {
+ pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
+ startedThread = 1;
+ }
+ }
+ }
+ else
+ {
+ std::cout << "Request invalid" << std::endl;
+ }
+
+ return result;
+ }
+};
+
+// Create the instance of the resource class (in this case instance of class 'LightResource').
+struct mosquitto *myMosquitto;
+
+// ChangeLightRepresentaion is an observation function,
+// which notifies any changes to the resource to stack
+// via notifyObservers
+void *ChangeLightRepresentation (void *param)
+{
+ LightResource *lightPtr = (LightResource *) param;
+
+ // This function continuously monitors for the changes
+ while (1)
+ {
+ sleep (5);
+
+ if (gObservation)
+ {
+ // If under observation if there are any changes to the light resource
+ // we call notifyObservors
+ //
+ // For demostration we are changing the power value and notifying.
+ lightPtr->m_power += 10;
+
+ cout << "\nPower updated to : " << lightPtr->m_power << endl;
+ cout << "Notifying observers with resource handle: " << lightPtr->getHandle() << endl;
+
+ OCStackResult result = OC_STACK_OK;
+
+ if (isListOfObservers)
+ {
+ std::shared_ptr<OCResourceResponse> resourceResponse(new OCResourceResponse());
+
+ resourceResponse->setErrorCode(200);
+ resourceResponse->setResourceRepresentation(lightPtr->get(), DEFAULT_INTERFACE);
+
+ result = OCPlatform::notifyListOfObservers( lightPtr->getHandle(),
+ lightPtr->m_interestedObservers,
+ resourceResponse);
+ }
+ else
+ {
+ result = OCPlatform::notifyAllObservers(lightPtr->getHandle());
+ }
+
+ if (OC_STACK_NO_OBSERVERS == result)
+ {
+ cout << "No More observers, stopping notifications" << endl;
+ gObservation = 0;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+
+
+//int start_lightserver(void*) // 1
+void *start_lightserver(void *d) // 2
+{
+ /*PlatformConfig cfg;
+ cfg.ipAddress = "192.168.2.5";
+ cfg.port = 56832;
+ cfg.mode = ModeType::Server;
+ cfg.serviceType = ServiceType::InProc;*/
+ // PlatformConfig cfg
+ // {
+ // OC::ServiceType::InProc,
+ // OC::ModeType::Server,
+ // "192.168.2.5",
+ // 56832,
+ // OC::QualityOfService::NonConfirmable
+ // };
+
+ // Create PlatformConfig object
+
+ // Create a OCPlatform instance.
+ // Note: Platform creation is synchronous call.
+
+ // Create PlatformConfig object
+ PlatformConfig cfg
+ {
+ OC::ServiceType::InProc,
+ OC::ModeType::Server,
+ "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
+ 0, // Uses randomly available port
+ OC::QualityOfService::LowQos
+ };
+
+ OCPlatform::Configure(cfg);
+
+ printf("start_fanserver [mosquitto] Null\n");
+ try
+ {
+ LightResource myLightResource;
+ mosquitto_lib_init();
+ myMosquitto = mosquitto_new("MQTT plug-in", true, NULL);
+ if (!myMosquitto)
+ {
+ printf("[mosquitto] Null\n");
+ printf("You need to install mqtt broker\n");
+ }
+ else
+ {
+ printf("Mosquitto is working\n");
+ }
+
+ //plugin_data_t *data = (plugin_data_t *)d;
+ //OCPlatform *platform = (OCPlatform*)data->str;
+ //myLightResource.m_platform = (OCPlatform*)data->str;
+ //OCPlatform platform(cfg);
+ // Invoke createResource function of class light.
+
+ //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
+ mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
+ printf("Mosquitto Connection is done\n");
+ myLightResource.createResource();
+ //myLightResource.addType(std::string("core.light"));
+ //myLightResource.addInterface(std::string("oc.mi.ll"));
+ // Get time of day
+ timer = time(NULL);
+ // Converts date/time to a structure
+ tblock = localtime(&timer);
+ // Output ASCII data/time
+ printf("LightReousrce reigishter time is: %s", asctime(tblock));
+ // Perform app tasks
+ while (true)
+ {
+ // some tasks
+ }
+ }
+ catch (OCException e)
+ {
+ //log(e.what());
+ }
+ // No explicit call to stop the platform.
+ // When OCPlatform destructor is invoked, internally we do platform cleanup
+ mosquitto_destroy(myMosquitto);
+
+ mosquitto_lib_cleanup();
+ printf("start_lightserver finish\n");
+ pthread_exit((void *)0);
+}
--- /dev/null
+//int start_fanserver(void*); // 1
+void *start_lightserver(void *ocplatform); // 2
--- /dev/null
+#include "lightserver_mqtt_plugin.h"
+#include "lightserver.h"
+#include <cstdlib>
+#include <pthread.h> // 2
+
+//int start_fanserver(void*); // 1
+void *start_lightserver(void *d); // 2
+
+typedef struct plugin_data_t plugin_data_t;
+
+struct plugin_data_t
+{
+ cp_context_t *ctx;
+ pthread_t m_thread; // 2
+ void *str;
+ bool flag;
+};
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+static void *create(cp_context_t *ctx)
+{
+ plugin_data_t *data = (plugin_data_t *)malloc(sizeof(plugin_data_t));
+
+ if (data != NULL)
+ {
+ data->ctx = ctx;
+ data->flag = true;
+ }
+ else
+ {
+ printf("[MQTT] ERROR: Plug-in Data - NULL\n");
+ }
+
+ return data;
+}
+
+static int start(void *d)
+{
+ plugin_data_t *data = (plugin_data_t *)d;
+
+ data->str = (void *)cp_resolve_symbol(data->ctx, "lightserver_mqtt_plugin", "START_ARGUMENT", NULL);
+
+ //cp_run_function(data->ctx, (cp_run_func_t)start_fanserver); // 1
+ pthread_create(&(data->m_thread), NULL, start_lightserver, data); // 2
+ return 0;
+}
+
+static void stop(void *d)
+{
+ printf("function_stop\n");
+ plugin_data_t *data = (plugin_data_t *)d;
+
+ data->flag = false;
+ cp_release_symbol(data->ctx, data->str);
+ pthread_join(data->m_thread, (void **)NULL);
+}
+
+static void destroy(void *d)
+{
+ printf("function_destroy\n");
+ plugin_data_t *data = (plugin_data_t *)d;
+ free(data);
+}
+
+CP_EXPORT cp_plugin_runtime_t mqtt_plugin_lightserver_funcs =
+{
+ create,
+ start,
+ stop,
+ destroy
+};
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+#ifndef PLUGIN_1_HEADER_INCLUDED
+#define PLUGIN_1_HEADER_INCLUDED
+
+#include <stdio.h>
+#include <cpluff.h>
+#endif
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Intel Corporation All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-///
-/// This sample provides steps to define an interface for a resource
-/// (properties and methods) and host this resource on the server.
-///
-
-#include <functional>
-#include <pthread.h>
-#include <cpluff.h>
-
-#include "OCPlatform.h"
-#include "OCApi.h"
-#include "../lib/mosquitto.h"
-
-
-using namespace OC;
-using namespace std;
-
-int gObservation = 0;
-
-// Forward declaring the entityHandler
-void entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response);
-
-/// This class represents a single resource named 'fanResource'. This resource has
-/// two simple properties named 'state' and 'power'
-typedef struct plugin_data_t plugin_data_t;
-
-struct plugin_data_t
-{
- cp_context_t *ctx;
- pthread_t m_thread; // 2
- void *str;
- bool flag;
-};
-
-
-class FanResource
-{
- public:
- /// Access this property from a TB client
- bool m_state;
- int m_power;
- int m_health;
- std::string m_fanUri;
- OCResourceHandle m_resourceHandle;
-
- public:
- /// Constructor
- FanResource(): m_state(false), m_power(0), m_health(0), m_fanUri {"/a/fan"} { }
-
- /* Note that this does not need to be a member function: for classes you do not have
- access to, you can accomplish this with a free function: */
-
- /// This function internally calls registerResource API.
- void createResource(OC::OCPlatform &platform)
- {
- std::string resourceURI = m_fanUri; // URI of the resource
- std::string resourceTypeName = "core.fan"; // resource type name. In this case, it is fan
- std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
-
- // OCResourceProperty is defined ocstack.h
- uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
-
- // This will internally create and register the resource.
- OCStackResult result = platform.registerResource(
- m_resourceHandle, resourceURI, resourceTypeName,
- resourceInterface, &entityHandler, resourceProperty);
-
- if (OC_STACK_OK != result)
- {
- cout << "Resource creation was unsuccessful\n";
- }
- }
-
- OCResourceHandle getHandle()
- {
- return m_resourceHandle;
- }
-
- void setRepresentation(OCRepresentation &fan)
- {
- AttributeMap attributeMap = fan.getAttributeMap();
-
- if (attributeMap.find("state") != attributeMap.end()
- && attributeMap.find("power") != attributeMap.end()
- && attributeMap.find("health") != attributeMap.end())
- {
- cout << "\t\t\t" << "Received representation: " << endl;
- cout << "\t\t\t\t" << "power: " << attributeMap["power"][0] << endl;
- cout << "\t\t\t\t" << "state: " << attributeMap["state"][0] << endl;
- cout << "\t\t\t\t" << "health: " << attributeMap["health"][0] << endl;
-
- m_state = attributeMap["state"][0].compare("true") == 0;
- m_power = std::stoi(attributeMap["power"][0]);
- m_health = std::stoi(attributeMap["health"][0]);
- }
-
- }
-
- OCRepresentation getRepresentation()
- {
- OCRepresentation fan;
-
- fan.setUri(m_fanUri);
-
- std::vector<std::string> interfaces;
- fan.setResourceInterfaces(interfaces);
-
- std::vector<std::string> types;
- fan.setResourceTypes(types);
-
- AttributeMap attributeMap;
- AttributeValues stateVal;
-
- if (m_state)
- {
- stateVal.push_back("true");
- }
- else
- {
- stateVal.push_back("false");
- }
-
- AttributeValues powerVal;
- powerVal.push_back(to_string(m_power));
-
- AttributeValues healthVal;
- healthVal.push_back(to_string(m_health));
-
- attributeMap["state"] = stateVal;
- attributeMap["power"] = powerVal;
- attributeMap["health"] = healthVal;
-
- fan.setAttributeMap(attributeMap);
-
- return fan;
- }
-
- void addType(const OC::OCPlatform &platform, const std::string &type) const
- {
- OCStackResult result = platform.bindTypeToResource(m_resourceHandle, type);
- if (OC_STACK_OK != result)
- {
- cout << "Binding TypeName to Resource was unsuccessful\n";
- }
- }
-
- void addInterface(const OC::OCPlatform &platform, const std::string &interface) const
- {
- OCStackResult result = platform.bindInterfaceToResource(m_resourceHandle, interface);
- if (OC_STACK_OK != result)
- {
- cout << "Binding TypeName to Resource was unsuccessful\n";
- }
- }
-};
-
-// Create the instance of the resource class (in this case instance of class 'FanResource').
-FanResource myFanResource;
-struct mosquitto *myMosquitto;
-
-// ChangeFanRepresentaion is an observation function,
-// which notifies any changes to the resource to stack
-// via notifyObservers
-void *ChangeFanRepresentation (void *param)
-{
- // This function continuously monitors for the changes
- while (1)
- {
- sleep (5);
-
- if (gObservation)
- {
- // If under observation if there are any changes to the fan resource
- // we call notifyObservors
- //
- // For demostration we are changing the power value and notifying.
- if (myFanResource.m_health != 0)
- myFanResource.m_health += 1;
-
- cout << "\nPower updated to : " << myFanResource.m_health << endl;
- cout << "Notifying observers with resource handle: " << myFanResource.getHandle() << endl;
-
- OCStackResult result = OCPlatform::notifyObservers(myFanResource.getHandle());
-
- if (OC_STACK_NO_OBSERVERS == result)
- {
- cout << "No More observers, stopping notifications" << endl;
- gObservation = 0;
- }
- }
- }
-
- return NULL;
-}
-
-
-// This is just a sample implementation of entity handler.
-// Entity handler can be implemented in several ways by the manufacturer
-void entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
-{
- cout << "\tIn Server CPP entity handler:\n";
-
- if (request)
- {
- // Get the request type and request flag
- std::string requestType = request->getRequestType();
- RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
-
- if (requestFlag == RequestHandlerFlag::InitFlag)
- {
- cout << "\t\trequestFlag : Init\n";
-
- // entity handler to perform resource initialization operations
- }
- else if (requestFlag == RequestHandlerFlag::RequestFlag)
- {
- cout << "\t\trequestFlag : Request\n";
-
- // If the request type is GET
- if (requestType == "GET")
- {
- cout << "\t\t\trequestType : GET\n";
-
- // Check for query params (if any)
- QueryParamsMap queryParamsMap = request->getQueryParameters();
-
- cout << "\t\t\tquery params: \n";
- for (QueryParamsMap::iterator it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
- {
- cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
- }
-
- // Process query params and do required operations ..
-
- // Get the representation of this resource at this point and send it as response
- //AttributeMap attributeMap;
- OCRepresentation rep;
- rep = myFanResource.getRepresentation();
-
- if (response)
- {
- // TODO Error Code
- response->setErrorCode(200);
- auto findRes = queryParamsMap.find("if");
-
- if (findRes != queryParamsMap.end())
- {
- response->setResourceRepresentation(rep, findRes->second);
- }
- else
- {
- response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
- }
- }
- }
- else if (requestType == "PUT")
- {
- cout << "\t\t\trequestType : PUT\n";
-
- // Check for query params (if any)
- QueryParamsMap queryParamsMap = request->getQueryParameters();
-
- cout << "\t\t\tquery params: \n";
- for (auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
- {
- cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
- }
-
- // Get the representation from the request
- OCRepresentation rep = request->getResourceRepresentation();
- AttributeMap attributeMap = rep.getAttributeMap();
-
- myFanResource.setRepresentation(rep);
- // Do related operations related to PUT request
- rep = myFanResource.getRepresentation();
-
- int power = std::stoi(attributeMap["power"][0]);
-
- if (power == 1)
- {
- mosquitto_publish(myMosquitto, NULL, "actuators/fan", 32, "onfan", 0, true);
- }
- else
- {
- mosquitto_publish(myMosquitto, NULL, "actuators/fan", 32, "offfan", 0, true);
- }
-
- if (response)
- {
- response->setErrorCode(200);
- auto findRes = queryParamsMap.find("if");
-
- if (findRes != queryParamsMap.end())
- {
- response->setResourceRepresentation(rep, findRes->second);
- }
- else
- {
- response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
- }
- }
- }
- else if (requestType == "POST")
- {
- // POST request operations
- }
- else if (requestType == "DELETE")
- {
- // DELETE request operations
- }
- }
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
- {
- pthread_t threadId;
-
- cout << "\t\trequestFlag : Observer\n";
- gObservation = 1;
-
- static int startedThread = 0;
-
- // Observation happens on a different thread in ChangeFanRepresentation function.
- // If we have not created the thread already, we will create one here.
- if (!startedThread)
- {
- pthread_create (&threadId, NULL, ChangeFanRepresentation, (void *)NULL);
- startedThread = 1;
- }
-
- }
- }
- else
- {
- std::cout << "Request invalid" << std::endl;
- }
-}
-
-//int start_fanserver(void*) // 1
-void *start_fanserver(void *d) // 2
-{
- /*PlatformConfig cfg;
- cfg.ipAddress = "192.168.2.5";
- cfg.port = 56832;
- cfg.mode = ModeType::Server;
- cfg.serviceType = ServiceType::InProc;*/
- PlatformConfig cfg
- {
- OC::ServiceType::InProc,
- OC::ModeType::Server,
- "192.168.2.5",
- 56832,
- OC::QualityOfService::NonConfirmable
- };
-
- // Create PlatformConfig object
-
- // Create a OCPlatform instance.
- // Note: Platform creation is synchronous call.
- try
- {
- mosquitto_lib_init();
- myMosquitto = mosquitto_new("MQTT plug-in", true, NULL);
- if (!myMosquitto)
- {
- printf("[mosquitto] Null\n");
- //return 1; // 1
- }
-
- plugin_data_t *data = (plugin_data_t *)d;
- //OCPlatform *platform = (OCPlatform*)data->str;
- OCPlatform platform(cfg);
- // Invoke createResource function of class fan.
-
- mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
- myFanResource.createResource(platform);
- myFanResource.addType(platform, std::string("core.fan"));
- myFanResource.addInterface(platform, std::string("oc.mi.ll"));
- // Perform app tasks
- while (data->flag)
- {
- // some tasks
- }
- }
- catch (OCException e)
- {
- //log(e.what());
- }
-
- // No explicit call to stop the platform.
- // When OCPlatform destructor is invoked, internally we do platform cleanup
-
- gObservation = 0;
- mosquitto_destroy(myMosquitto);
-
- mosquitto_lib_cleanup();
- printf("start_fanserver finish\n");
- pthread_exit((void *)0);
-}
-include ../../../config.mk
-
CXX = g++
CXX_FLAGS = -std=c++0x -Wall -pthread
LIB_DIR = ../../../../../resource
CXX_INC := -I$(LIB_DIR)/include/
+CXX_INC += -I$(LIB_DIR)/oc_logger/include/
CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
CXX_INC += -I$(LIB_DIR)/csdk/ocsocket/include/
CXX_INC += -I$(LIB_DIR)/csdk/ocrandom/include/
-CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
+CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
CXX_INC += -I$(BOOST_DIR)
-CXX_INC += -I./lib
+CXX_INC += -I../../lib
+CXX_INC += -I../../../lib/cpluff/libcpluff
+CXX_INC += -I../../../plugin-manager/src
+LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
+CXX_LIBS := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../build/linux/release/libppm.a ../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread
.PHONY: fanclient
all: .PHONY
-fanclient: $(LIB_DIR)/build/linux/release/obj/liboc.a fanclient.o
- $(CXX) $(CXX_FLAGS) -o fanclient fanclient.o $(LIB_DIR)/build/linux/release/obj/liboc.a $(LIB_DIR)/csdk/build/linux/release/liboctbstack.a
+fanclient: fanclient.o
+ $(CXX) $(CXX_FLAGS) -o fanclient fanclient.o $(CXX_LIBS) $(LINK_LIB)
fanclient.o: fanclient.cpp
$(CXX) $(CXX_FLAGS) -c fanclient.cpp $(CXX_INC)
+
clean:
rm -f *.o
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-* : Initialization Part has been referenced from OCClient.cpp file of Intel copyright.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-*******************************************************************/
-
-// FanClient.cpp : Defines the entry point for the console application for controlling fan.
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+// OCClient.cpp : Defines the entry point for the console application.
//
#include <string>
#include <cstdlib>
#include <pthread.h>
#include "OCPlatform.h"
+#include "PluginManager.h"
#include "OCApi.h"
+#include <time.h>
using namespace OC;
+using namespace OIC;
-const int SUCCESS_RESPONSE = 0;
std::shared_ptr<OCResource> curResource;
static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
+time_t timer; // Define the timer
+struct tm *tblock; // Define a structure for time block
+
+class Fan
+{
+ public:
+
+ bool m_state;
+ int m_power;
+ std::string m_name;
+
+ Fan() : m_state(false), m_power(0), m_name("")
+ {
+ }
+};
+
+Fan myfan;
+
int observe_count()
{
static int oc = 0;
return ++oc;
}
-void onObserve(const OCRepresentation &rep, const int &eCode, const int &sequenceNumber)
+void onObserve(const HeaderOptions headerOptions, const OCRepresentation &rep,
+ const int &eCode, const int &sequenceNumber)
{
- if (eCode == SUCCESS_RESPONSE)
+ if (eCode == OC_STACK_OK)
{
- AttributeMap attributeMap = rep.getAttributeMap();
-
std::cout << "OBSERVE RESULT:" << std::endl;
std::cout << "\tSequenceNumber: " << sequenceNumber << endl;
- for (auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
+
+ rep.getValue("state", myfan.m_state);
+ rep.getValue("power", myfan.m_power);
+ rep.getValue("name", myfan.m_name);
+
+ std::cout << "\tstate: " << myfan.m_state << std::endl;
+ std::cout << "\tpower: " << myfan.m_power << std::endl;
+ std::cout << "\tname: " << myfan.m_name << std::endl;
+
+ if (observe_count() > 30)
{
- std::cout << "\tAttribute name: " << it->first << " value: ";
- for (auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
- {
- std::cout << "\t" << *valueItr << " ";
- }
- std::cout << std::endl;
+ std::cout << "Cancelling Observe..." << std::endl;
+ OCStackResult result = curResource->cancelObserve();
+
+ std::cout << "Cancel result: " << result << std::endl;
+ sleep(10);
+ std::cout << "DONE" << std::endl;
+ std::exit(0);
}
}
else
}
}
-// callback handler on PUT request
-void onPut(const OCRepresentation &rep, const int eCode)
+void onPost2(const HeaderOptions &headerOptions, const OCRepresentation &rep, const int eCode)
{
- if (eCode == SUCCESS_RESPONSE)
+ if (eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED)
{
- std::cout << "PUT request was successful" << std::endl;
+ std::cout << "POST request was successful" << std::endl;
- AttributeMap attributeMap = rep.getAttributeMap();
-
- for (auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
+ if (rep.hasAttribute("createduri"))
{
- std::cout << "\tAttribute name: " << it->first << " value: ";
- for (auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
- {
- std::cout << "\t" << *valueItr << " ";
- }
-
- std::cout << std::endl;
+ std::cout << "\tUri of the created resource: "
+ << rep.getValue<std::string>("createduri") << std::endl;
}
-
- std::vector<OCRepresentation> children = rep.getChildren();
-
- for (auto oit = children.begin(); oit != children.end(); ++oit)
+ else
{
- attributeMap = oit->getAttributeMap();
-
- for (auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
- {
- std::cout << "\tAttribute name: " << it->first << " value: ";
- for (auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
- {
- std::cout << "\t" << *valueItr << " ";
- }
+ rep.getValue("state", myfan.m_state);
+ rep.getValue("power", myfan.m_power);
+ rep.getValue("name", myfan.m_name);
- std::cout << std::endl;
- }
+ std::cout << "\tstate: " << myfan.m_state << std::endl;
+ std::cout << "\tpower: " << myfan.m_power << std::endl;
+ std::cout << "\tname: " << myfan.m_name << std::endl;
}
if (OBSERVE_TYPE_TO_USE == ObserveType::Observe)
else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
std::cout << endl << "ObserveAll is used." << endl << endl;
- QueryParamsMap test;
-
- curResource->observe(OBSERVE_TYPE_TO_USE, test, &onObserve);
+ curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
}
else
{
- std::cout << "onPut Response error: " << eCode << std::endl;
+ std::cout << "onPost Response error: " << eCode << std::endl;
std::exit(-1);
}
}
-// Local function to put a different state for this resource
-void putFanRepresentation(std::shared_ptr<OCResource> resource)
+void onPost(const HeaderOptions &headerOptions, const OCRepresentation &rep, const int eCode)
{
- if (resource)
+ if (eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED)
{
- OCRepresentation rep;
-
- std::cout << "Putting light representation..." << std::endl;
- // Create AttributeMap
- AttributeMap attributeMap;
- // Add the attribute name and values in the attribute map
- AttributeValues stateVal;
- stateVal.push_back("true");
+ std::cout << "POST request was successful" << std::endl;
- AttributeValues powerVal;
- powerVal.push_back("1");
+ if (rep.hasAttribute("createduri"))
+ {
+ std::cout << "\tUri of the created resource: "
+ << rep.getValue<std::string>("createduri") << std::endl;
+ }
+ else
+ {
+ rep.getValue("state", myfan.m_state);
+ rep.getValue("power", myfan.m_power);
+ rep.getValue("name", myfan.m_name);
- AttributeValues healthVal;
- healthVal.push_back("1");
+ std::cout << "\tstate: " << myfan.m_state << std::endl;
+ std::cout << "\tpower: " << myfan.m_power << std::endl;
+ std::cout << "\tname: " << myfan.m_name << std::endl;
+ }
+ OCRepresentation rep2;
- attributeMap["state"] = stateVal;
- attributeMap["power"] = powerVal;
- attributeMap["health"] = healthVal;
+ std::cout << "Posting fan representation..." << std::endl;
- // Create QueryParameters Map and add query params (if any)
- QueryParamsMap queryParamsMap;
+ myfan.m_state = true;
+ myfan.m_power = 55;
- rep.setAttributeMap(attributeMap);
+ rep2.setValue("state", myfan.m_state);
+ rep2.setValue("power", myfan.m_power);
- // Invoke resource's pit API with attribute map, query map and the callback parameter
- resource->put(rep, queryParamsMap, &onPut);
+ curResource->post(rep2, QueryParamsMap(), &onPost2);
+ }
+ else
+ {
+ std::cout << "onPost Response error: " << eCode << std::endl;
+ std::exit(-1);
}
}
-
-void putFanRepresentationON(std::shared_ptr<OCResource> resource)
+// Local function to put a different state for this resource
+void postFanRepresentation(std::shared_ptr<OCResource> resource)
{
if (resource)
{
OCRepresentation rep;
- std::cout << "Putting Fan representation..." << std::endl;
- // Create AttributeMap
- AttributeMap attributeMap;
- // Add the attribute name and values in the attribute map
- AttributeValues stateVal;
- stateVal.push_back("true");
+ std::cout << "Posting fan representation..." << std::endl;
- AttributeValues powerVal;
- powerVal.push_back("1");
+ myfan.m_state = false;
+ myfan.m_power = 105;
- AttributeValues healthVal;
- healthVal.push_back("1");
+ rep.setValue("state", myfan.m_state);
+ rep.setValue("power", myfan.m_power);
+ // Invoke resource's post API with rep, query map and the callback parameter
+ resource->post(rep, QueryParamsMap(), &onPost);
+ }
+}
- attributeMap["state"] = stateVal;
- attributeMap["power"] = powerVal;
- attributeMap["health"] = healthVal;
+// callback handler on PUT request
+void onPut(const HeaderOptions &headerOptions, const OCRepresentation &rep, const int eCode)
+{
+ if (eCode == OC_STACK_OK)
+ {
+ std::cout << "PUT request was successful" << std::endl;
- // Create QueryParameters Map and add query params (if any)
- QueryParamsMap queryParamsMap;
+ rep.getValue("state", myfan.m_state);
+ rep.getValue("power", myfan.m_power);
+ rep.getValue("name", myfan.m_name);
- rep.setAttributeMap(attributeMap);
+ std::cout << "\tstate: " << myfan.m_state << std::endl;
+ std::cout << "\tpower: " << myfan.m_power << std::endl;
+ std::cout << "\tname: " << myfan.m_name << std::endl;
- // Invoke resource's pit API with attribute map, query map and the callback parameter
- resource->put(rep, queryParamsMap, &onPut);
+ postFanRepresentation(curResource);
+ }
+ else
+ {
+ std::cout << "onPut Response error: " << eCode << std::endl;
+ std::exit(-1);
}
}
-void putFanRepresentationOFF(std::shared_ptr<OCResource> resource)
+// Local function to put a different state for this resource
+void putFanRepresentation(std::shared_ptr<OCResource> resource)
{
if (resource)
{
OCRepresentation rep;
std::cout << "Putting fan representation..." << std::endl;
- // Create AttributeMap
- AttributeMap attributeMap;
- // Add the attribute name and values in the attribute map
- AttributeValues stateVal;
- stateVal.push_back("false");
-
- AttributeValues powerVal;
- powerVal.push_back("0");
- AttributeValues healthVal;
- healthVal.push_back("0");
+ myfan.m_state = true;
+ myfan.m_power = 15;
+ rep.setValue("state", myfan.m_state);
+ rep.setValue("power", myfan.m_power);
- attributeMap["state"] = stateVal;
- attributeMap["power"] = powerVal;
- attributeMap["health"] = healthVal;
-
- // Create QueryParameters Map and add query params (if any)
- QueryParamsMap queryParamsMap;
-
- // Invoke resource's pit API with attribute map, query map and the callback parameter
- rep.setAttributeMap(attributeMap);
-
- // Invoke resource's pit API with attribute map, query map and the callback parameter
- resource->put(rep, queryParamsMap, &onPut);
+ // Invoke resource's put API with rep, query map and the callback parameter
+ resource->put(rep, QueryParamsMap(), &onPut);
}
}
-
-// callback handler on GET request
-void onGet(const OCRepresentation &rep, const int eCode)
+// Callback handler on GET request
+void onGet(const HeaderOptions &headerOptions, const OCRepresentation &rep, const int eCode)
{
- if (eCode == SUCCESS_RESPONSE)
+ if (eCode == OC_STACK_OK)
{
- std::cout << "GET Succeeded:" << std::endl;
-
- AttributeMap attributeMap = rep.getAttributeMap();
+ std::cout << "GET request was successful" << std::endl;
std::cout << "Resource URI: " << rep.getUri() << std::endl;
- for (auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
- {
- std::cout << "\tAttribute name: " << it->first << " value: ";
- for (auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
- {
- std::cout << "\t" << *valueItr << " ";
- }
-
- std::cout << std::endl;
- }
-
- std::vector<OCRepresentation> children = rep.getChildren();
-
- for (auto oit = children.begin(); oit != children.end(); ++oit)
- {
- std::cout << "Child Resource URI: " << oit->getUri() << std::endl;
-
- attributeMap = oit->getAttributeMap();
+ rep.getValue("state", myfan.m_state);
+ rep.getValue("power", myfan.m_power);
+ rep.getValue("name", myfan.m_name);
- for (auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
- {
- std::cout << "\tAttribute name: " << it->first << " value: ";
- for (auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
- {
- std::cout << "\t" << *valueItr << " ";
- }
+ std::cout << "\tstate: " << myfan.m_state << std::endl;
+ std::cout << "\tpower: " << myfan.m_power << std::endl;
+ std::cout << "\tname: " << myfan.m_name << std::endl;
- std::cout << std::endl;
- }
- }
putFanRepresentation(curResource);
}
else
{
- std::cout << "onGet Response error: " << eCode << std::endl;
+ std::cout << "onGET Response error: " << eCode << std::endl;
std::exit(-1);
}
}
+
// Local function to get representation of fan resource
void getFanRepresentation(std::shared_ptr<OCResource> resource)
{
if (resource)
{
+ std::cout << "Getting Fan Representation..." << std::endl;
+ // Invoke resource's get API with the callback parameter
+
+ QueryParamsMap test;
+ resource->get(test, &onGet);
+ }
+}
+
+void getLightRepresentation(std::shared_ptr<OCResource> resource)
+{
+ if (resource)
+ {
std::cout << "Getting Light Representation..." << std::endl;
// Invoke resource's get API with the callback parameter
}
// Callback to found resources
-void foundResource(std::shared_ptr<OCResource> resource)
+void foundResourceFan(std::shared_ptr<OCResource> resource)
{
-
if (curResource)
{
std::cout << "Found another resource, ignoring" << std::endl;
// Get the resource host address
hostAddress = resource->host();
std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
+
// Get the resource types
std::cout << "\tList of resource types: " << std::endl;
for (auto &resourceTypes : resource->getResourceTypes())
}
}
+// Callback to found resources
+void foundResourceLight(std::shared_ptr<OCResource> resource)
+{
+ if (curResource)
+ {
+ std::cout << "Found another resource, ignoring" << std::endl;
+ }
+
+ std::string resourceURI;
+ std::string hostAddress;
+ try
+ {
+ // Do some operations with resource object.
+ if (resource)
+ {
+ std::cout << "DISCOVERED Resource:" << std::endl;
+ // Get the resource URI
+ resourceURI = resource->uri();
+ std::cout << "\tURI of the resource: " << resourceURI << std::endl;
+
+ // Get the resource host address
+ hostAddress = resource->host();
+ std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
+
+ // Get the resource types
+ std::cout << "\tList of resource types: " << std::endl;
+ for (auto &resourceTypes : resource->getResourceTypes())
+ {
+ std::cout << "\t\t" << resourceTypes << std::endl;
+ }
+
+ // Get the resource interfaces
+ std::cout << "\tList of resource interfaces: " << std::endl;
+ for (auto &resourceInterfaces : resource->getResourceInterfaces())
+ {
+ std::cout << "\t\t" << resourceInterfaces << std::endl;
+ }
+
+ if (resourceURI == "/a/light")
+ {
+ curResource = resource;
+ // Call a local function which will internally invoke get API on the resource pointer
+ getLightRepresentation(resource);
+ }
+ }
+ else
+ {
+ // Resource is invalid
+ std::cout << "Resource is invalid" << std::endl;
+ }
+
+ }
+ catch (std::exception &e)
+ {
+ //log(e.what());
+ }
+}
+
+void PrintUsage()
+{
+ std::cout << std::endl;
+ std::cout << "Usage : simpleclient <ObserveType>" << std::endl;
+ std::cout << " ObserveType : 1 - Observe" << std::endl;
+ std::cout << " ObserveType : 2 - ObserveAll" << std::endl;
+}
+
+void client1()
+{
+ std::cout << "in client1\n";
+
+ // OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.foo",
+ // foundResource1);
+ std::cout << "starting findResource = core.fan" << std::endl;
+ // Find all resources
+ OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.fan", &foundResourceFan);
+ // Get time of day
+ timer = time(NULL);
+ // Converts date/time to a structure
+ tblock = localtime(&timer);
+ std::cout << "Finding Fan Resource... time : " << asctime(tblock) << std::endl;
+ while (1)
+ {
+ // client1 related operations
+ }
+}
+
+void client2()
+{
+ std::cout << "in client2\n";
+
+ // OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.foo",
+ // foundResource2);
+
+ std::cout << "starting findResource = core.light" << std::endl;
+ // Find all resources
+ OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResourceLight);
+ // Get time of day
+ timer = time(NULL);
+ // Converts date/time to a structure
+ tblock = localtime(&timer);
+ std::cout << "Finding Light Resource... time : " << asctime(tblock) << std::endl;
+
+
+
+ while (1)
+ {
+ // client2 related operations
+ }
+}
+
+
+
int main(int argc, char *argv[])
{
+ if (argc == 1)
+ {
+ OBSERVE_TYPE_TO_USE = ObserveType::Observe;
+ }
+ else if (argc == 2)
+ {
+ int value = atoi(argv[1]);
+ if (value == 1)
+ OBSERVE_TYPE_TO_USE = ObserveType::Observe;
+ else if (value == 2)
+ OBSERVE_TYPE_TO_USE = ObserveType::ObserveAll;
+ else
+ OBSERVE_TYPE_TO_USE = ObserveType::Observe;
+ }
+ else
+ {
+ PrintUsage();
+ return -1;
+ }
+
+ // Create PlatformConfig object
PlatformConfig cfg
{
OC::ServiceType::InProc,
- OC::ModeType::Client,
- "192.168.2.5",
- 5683,
- OC::QualityOfService::NonConfirmable
+ OC::ModeType::Both,
+ "0.0.0.0",
+ 0,
+ OC::QualityOfService::LowQos
};
- // Create a OCPlatform instance.
- // Note: Platform creation is synchronous call.
+ OCPlatform::Configure(cfg);
try
{
- OCPlatform platform(cfg);
+
std::cout << "Created Platform..." << std::endl;
- // Find all resources
- platform.findResource("", "coap://224.0.1.187/oc/core?rt=core.fan", &foundResource);
- std::cout << "Finding Resource... " << std::endl;
- sleep(20);
+
+
+ PluginManager *m_pm = new PluginManager();
+
+ std::cout << "======================" << std::endl;
+
+ std::cout << "start light Plugin by Resource Type" << std::endl;
+ m_pm->startPlugins("ResourceType", "oic.light");
+
+ sleep(2);
+
+ std::cout << "======================" << std::endl;
+ std::cout << "get Plugin List" << std::endl;
+ std::vector<Plugin> user_plugin;
+ user_plugin = m_pm->getPlugins();
+ for (unsigned int i = 0; i < user_plugin.size(); i++)
+ {
+ printf("value Name = %s\n", user_plugin[i].getName().c_str());
+ printf("value ID = %s\n", user_plugin[i].getID().c_str());
+ }
+
+ std::cout << "======================" << std::endl;
+ std::cout << "start Fan Plugin by Name" << std::endl;
+ m_pm->startPlugins("Name", "mqtt-fan");
+
+
+ // Start each client in a seperate thread
+// std::thread t1(client1);
+// t1.detach();
+
+///*
+// sleep(5);
+ // Start each client in a seperate thread
+// std::thread t2(client2);
+// t2.detach();
+//*/
while (true)
{
- //Test Simple Scenario
- std::cout << "Turn off the Fan" << std::endl;
- putFanRepresentationOFF(curResource);
- sleep(15);
- std::cout << "Turn on the Fan" << std::endl;
- putFanRepresentationON(curResource);
- sleep(30);
// some operations
}
+
}
- catch (OCException e)
+ catch (OCException &e)
{
//log(e.what());
}