Commit 84f4eea9 authored by whmaizmy's avatar whmaizmy

【修改内容】调整目录结构

【陈伟灿】
parent f9a164bf
//=========kk=============
#include "com_api.h"
#define APP2MID "ipc:///tmp/app2mid.ipc"
#define PLAT2MID "ipc:///tmp/plat2mid.ipc"
typedef struct {
int n; //nanomsg socket
int s; //nanomsg recieve fd
}nanomsg_info_t;
typedef struct {
nanomsg_info_t ba;
}Bloop_ctrl_t;
Bloop_ctrl_t Bloop_ctrl;
static struct ev_io g_watcher;
ipc_cb* g_cb = NULL;
static void watcher_cb (struct ev_loop *loop ,struct ev_io *w, int revents)
{
void *user_data = ev_userdata(loop);
Bloop_ctrl_t *Bloop_ctrl = (Bloop_ctrl_t *)user_data;
uint8_t *dat = NULL;
uint32_t bytes = nn_recv(Bloop_ctrl->ba.n, &dat, NN_MSG, NN_DONTWAIT);
if (bytes <= 0) {
return;
}
printf("watcher_cb:%s recived\r\n\r\n", (char *)dat);
if (g_cb != NULL){
g_cb((void *)dat);
}
nn_freemsg(dat);
}
struct ev_loop* __loop_init(Bloop_ctrl_t *loop_ctrl)
{
struct ev_loop *loop = ev_loop_new(EVBACKEND_EPOLL);
if (NULL == loop) {
printf("create loop failed\r\n");
return NULL;
}
ev_io_init (&g_watcher, watcher_cb, loop_ctrl->ba.s, EV_READ);
ev_io_start (loop, &g_watcher);
return loop;
}
int __nanomsg_init(Bloop_ctrl_t *Bloop_ctrl, ipc_type type)
{
Bloop_ctrl->ba.n = nn_socket(AF_SP, NN_PAIR);
printf("__nanomsg_initBloop_ctrl->ba.n=%d \r\n",Bloop_ctrl->ba.n);
if (Bloop_ctrl->ba.n < 0) {
return -1;
}
switch (type) {
case IPC_APP2MID:{
if (nn_connect(Bloop_ctrl->ba.n, APP2MID) < 0) {
return -1;
}
}
break;
case IPC_PLAT2MID: {
if (nn_connect(Bloop_ctrl->ba.n, PLAT2MID) < 0) {
return -1;
}
}
break;
case IPC_MID2APP: {
if (nn_bind(Bloop_ctrl->ba.n, APP2MID) < 0) {
return -1;
}
}
break;
case IPC_MID2PLAT: {
if (nn_bind(Bloop_ctrl->ba.n, PLAT2MID) < 0) {
return -1;
}
}
break;
default: {
}
break;
}
size_t size = sizeof(size_t);
if (nn_getsockopt(Bloop_ctrl->ba.n, NN_SOL_SOCKET, NN_RCVFD, (char *)&Bloop_ctrl->ba.s, &size) < 0) {
return -1;
}
return 0;
}
/*=================================
* TODO: only one methd pair
*
*
==================================*/
void loop_thread(void *arg){
struct ev_loop* loop = __loop_init(&Bloop_ctrl);
if (NULL == loop) {
printf("loop init failed\r\n");
return ;
}
ev_set_userdata(loop, &Bloop_ctrl);
ev_run (loop, 0);
}
void kk_ipc_init(ipc_type type, ipc_cb cb)
{
pthread_t pb;
if (g_cb == NULL){
printf("ipc has been inited!\r\n");
return;
}
if (__nanomsg_init(&Bloop_ctrl, type) < 0) {
printf("nanomsg init failed\r\n");
return ;
}
if (0 != pthread_create(&pb, NULL, loop_thread, NULL)) {
printf("create pthread B failed\r\n");
return -1;
}
g_cb = cb;
return ;
}
int kk_ipc_dinit()
{
#if 0
if (Bloop_ctrl.ba.n > -1){
nn_shutdown(Bloop_ctrl.ba.n, 0);
}
ev_io_stop(g_watcher);
ev_break(EV_A_ EVBREAK_ALL);
g_cb = NULL;
#endif
}
int kk_ipc_send(void* data)
{
//printf("kk_ipc_send 11111111\r\n");
if (data != NULL){
printf("kk_ipc_send data= %s\r\n", data);
char* buf = nn_allocmsg(strlen(data)+1, 0);
memcpy(buf, data,strlen(data)+1);
nn_send(Bloop_ctrl.ba.n, &buf, NN_MSG, NN_DONTWAIT);
//printf("kk_ipc_send: RECEIVED \"%s\"\n", data);
}
}
/*
* Copyright (C) 2020-2020 ikonke
*/
#ifndef _KK_COM_API_H_
#define _KK_COM_API_H_
#if defined(__cplusplus)
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "ev.h"
#include "nn.h"
#include "pair.h"
//=====kk======================
typedef enum {
IPC_APP2MID = 0,
IPC_MID2APP,
IPC_MID2PLAT,
IPC_PLAT2MID
} ipc_type;
typedef void ipc_cb(void* data);
void kk_ipc_init(ipc_type type, ipc_cb cb);
int kk_ipc_dinit();
int kk_ipc_send(void* data);
#if defined(__cplusplus)
}
#endif
#endif
LIBA_TARGET := libapi_com.a
#
CFLAGS += -I$(TOP_DIR)/common/nanomsg/include
CFLAGS += -I$(TOP_DIR)/common/ev/include
LDFLAGS += -L$(TOP_DIR)/common/nanomsg -static -lnanomsg
LDFLAGS += -L$(TOP_DIR)/common/ev -static -lev
LDFLAGS += -ldl
\ No newline at end of file
/*
* libev native API header
*
* Copyright (c) 2007-2020 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifndef EV_H_
#define EV_H_
#ifdef __cplusplus
# define EV_CPP(x) x
# if __cplusplus >= 201103L
# define EV_NOEXCEPT noexcept
# else
# define EV_NOEXCEPT
# endif
#else
# define EV_CPP(x)
# define EV_NOEXCEPT
#endif
#define EV_THROW EV_NOEXCEPT /* pre-4.25, do not use in new code */
EV_CPP(extern "C" {)
/*****************************************************************************/
/* pre-4.0 compatibility */
#ifndef EV_COMPAT3
# define EV_COMPAT3 1
#endif
#ifndef EV_FEATURES
# if defined __OPTIMIZE_SIZE__
# define EV_FEATURES 0x7c
# else
# define EV_FEATURES 0x7f
# endif
#endif
#define EV_FEATURE_CODE ((EV_FEATURES) & 1)
#define EV_FEATURE_DATA ((EV_FEATURES) & 2)
#define EV_FEATURE_CONFIG ((EV_FEATURES) & 4)
#define EV_FEATURE_API ((EV_FEATURES) & 8)
#define EV_FEATURE_WATCHERS ((EV_FEATURES) & 16)
#define EV_FEATURE_BACKENDS ((EV_FEATURES) & 32)
#define EV_FEATURE_OS ((EV_FEATURES) & 64)
/* these priorities are inclusive, higher priorities will be invoked earlier */
#ifndef EV_MINPRI
# define EV_MINPRI (EV_FEATURE_CONFIG ? -2 : 0)
#endif
#ifndef EV_MAXPRI
# define EV_MAXPRI (EV_FEATURE_CONFIG ? +2 : 0)
#endif
#ifndef EV_MULTIPLICITY
# define EV_MULTIPLICITY EV_FEATURE_CONFIG
#endif
#ifndef EV_PERIODIC_ENABLE
# define EV_PERIODIC_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_STAT_ENABLE
# define EV_STAT_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_PREPARE_ENABLE
# define EV_PREPARE_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CHECK_ENABLE
# define EV_CHECK_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_IDLE_ENABLE
# define EV_IDLE_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_FORK_ENABLE
# define EV_FORK_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CLEANUP_ENABLE
# define EV_CLEANUP_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_SIGNAL_ENABLE
# define EV_SIGNAL_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CHILD_ENABLE
# ifdef _WIN32
# define EV_CHILD_ENABLE 0
# else
# define EV_CHILD_ENABLE EV_FEATURE_WATCHERS
#endif
#endif
#ifndef EV_ASYNC_ENABLE
# define EV_ASYNC_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_EMBED_ENABLE
# define EV_EMBED_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_WALK_ENABLE
# define EV_WALK_ENABLE 0 /* not yet */
#endif
/*****************************************************************************/
#if EV_CHILD_ENABLE && !EV_SIGNAL_ENABLE
# undef EV_SIGNAL_ENABLE
# define EV_SIGNAL_ENABLE 1
#endif
/*****************************************************************************/
#ifndef EV_TSTAMP_T
# define EV_TSTAMP_T double
#endif
typedef EV_TSTAMP_T ev_tstamp;
#include <string.h> /* for memmove */
#ifndef EV_ATOMIC_T
# include <signal.h>
# define EV_ATOMIC_T sig_atomic_t volatile
#endif
#if EV_STAT_ENABLE
# ifdef _WIN32
# include <time.h>
# include <sys/types.h>
# endif
# include <sys/stat.h>
#endif
/* support multiple event loops? */
#if EV_MULTIPLICITY
struct ev_loop;
# define EV_P struct ev_loop *loop /* a loop as sole parameter in a declaration */
# define EV_P_ EV_P, /* a loop as first of multiple parameters */
# define EV_A loop /* a loop as sole argument to a function call */
# define EV_A_ EV_A, /* a loop as first of multiple arguments */
# define EV_DEFAULT_UC ev_default_loop_uc_ () /* the default loop, if initialised, as sole arg */
# define EV_DEFAULT_UC_ EV_DEFAULT_UC, /* the default loop as first of multiple arguments */
# define EV_DEFAULT ev_default_loop (0) /* the default loop as sole arg */
# define EV_DEFAULT_ EV_DEFAULT, /* the default loop as first of multiple arguments */
#else
# define EV_P void
# define EV_P_
# define EV_A
# define EV_A_
# define EV_DEFAULT
# define EV_DEFAULT_
# define EV_DEFAULT_UC
# define EV_DEFAULT_UC_
# undef EV_EMBED_ENABLE
#endif
/* EV_INLINE is used for functions in header files */
#if __STDC_VERSION__ >= 199901L || __GNUC__ >= 3
# define EV_INLINE static inline
#else
# define EV_INLINE static
#endif
#ifdef EV_API_STATIC
# define EV_API_DECL static
#else
# define EV_API_DECL extern
#endif
/* EV_PROTOTYPES can be used to switch of prototype declarations */
#ifndef EV_PROTOTYPES
# define EV_PROTOTYPES 1
#endif
/*****************************************************************************/
#define EV_VERSION_MAJOR 4
#define EV_VERSION_MINOR 33
/* eventmask, revents, events... */
enum {
EV_UNDEF = (int)0xFFFFFFFF, /* guaranteed to be invalid */
EV_NONE = 0x00, /* no events */
EV_READ = 0x01, /* ev_io detected read will not block */
EV_WRITE = 0x02, /* ev_io detected write will not block */
EV__IOFDSET = 0x80, /* internal use only */
EV_IO = EV_READ, /* alias for type-detection */
EV_TIMER = 0x00000100, /* timer timed out */
#if EV_COMPAT3
EV_TIMEOUT = EV_TIMER, /* pre 4.0 API compatibility */
#endif
EV_PERIODIC = 0x00000200, /* periodic timer timed out */
EV_SIGNAL = 0x00000400, /* signal was received */
EV_CHILD = 0x00000800, /* child/pid had status change */
EV_STAT = 0x00001000, /* stat data changed */
EV_IDLE = 0x00002000, /* event loop is idling */
EV_PREPARE = 0x00004000, /* event loop about to poll */
EV_CHECK = 0x00008000, /* event loop finished poll */
EV_EMBED = 0x00010000, /* embedded event loop needs sweep */
EV_FORK = 0x00020000, /* event loop resumed in child */
EV_CLEANUP = 0x00040000, /* event loop resumed in child */
EV_ASYNC = 0x00080000, /* async intra-loop signal */
EV_CUSTOM = 0x01000000, /* for use by user code */
EV_ERROR = (int)0x80000000 /* sent when an error occurs */
};
/* can be used to add custom fields to all watchers, while losing binary compatibility */
#ifndef EV_COMMON
# define EV_COMMON void *data;
#endif
#ifndef EV_CB_DECLARE
# define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents);
#endif
#ifndef EV_CB_INVOKE
# define EV_CB_INVOKE(watcher,revents) (watcher)->cb (EV_A_ (watcher), (revents))
#endif
/* not official, do not use */
#define EV_CB(type,name) void name (EV_P_ struct ev_ ## type *w, int revents)
/*
* struct member types:
* private: you may look at them, but not change them,
* and they might not mean anything to you.
* ro: can be read anytime, but only changed when the watcher isn't active.
* rw: can be read and modified anytime, even when the watcher is active.
*
* some internal details that might be helpful for debugging:
*
* active is either 0, which means the watcher is not active,
* or the array index of the watcher (periodics, timers)
* or the array index + 1 (most other watchers)
* or simply 1 for watchers that aren't in some array.
* pending is either 0, in which case the watcher isn't,
* or the array index + 1 in the pendings array.
*/
#if EV_MINPRI == EV_MAXPRI
# define EV_DECL_PRIORITY
#elif !defined (EV_DECL_PRIORITY)
# define EV_DECL_PRIORITY int priority;
#endif
/* shared by all watchers */
#define EV_WATCHER(type) \
int active; /* private */ \
int pending; /* private */ \
EV_DECL_PRIORITY /* private */ \
EV_COMMON /* rw */ \
EV_CB_DECLARE (type) /* private */
#define EV_WATCHER_LIST(type) \
EV_WATCHER (type) \
struct ev_watcher_list *next; /* private */
#define EV_WATCHER_TIME(type) \
EV_WATCHER (type) \
ev_tstamp at; /* private */
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher
{
EV_WATCHER (ev_watcher)
} ev_watcher;
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_list
{
EV_WATCHER_LIST (ev_watcher_list)
} ev_watcher_list;
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_time
{
EV_WATCHER_TIME (ev_watcher_time)
} ev_watcher_time;
/* invoked when fd is either EV_READable or EV_WRITEable */
/* revent EV_READ, EV_WRITE */
typedef struct ev_io
{
EV_WATCHER_LIST (ev_io)
int fd; /* ro */
int events; /* ro */
} ev_io;
/* invoked after a specific time, repeatable (based on monotonic clock) */
/* revent EV_TIMEOUT */
typedef struct ev_timer
{
EV_WATCHER_TIME (ev_timer)
ev_tstamp repeat; /* rw */
} ev_timer;
/* invoked at some specific time, possibly repeating at regular intervals (based on UTC) */
/* revent EV_PERIODIC */
typedef struct ev_periodic
{
EV_WATCHER_TIME (ev_periodic)
ev_tstamp offset; /* rw */
ev_tstamp interval; /* rw */
ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now) EV_NOEXCEPT; /* rw */
} ev_periodic;
/* invoked when the given signal has been received */
/* revent EV_SIGNAL */
typedef struct ev_signal
{
EV_WATCHER_LIST (ev_signal)
int signum; /* ro */
} ev_signal;
/* invoked when sigchld is received and waitpid indicates the given pid */
/* revent EV_CHILD */
/* does not support priorities */
typedef struct ev_child
{
EV_WATCHER_LIST (ev_child)
int flags; /* private */
int pid; /* ro */
int rpid; /* rw, holds the received pid */
int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */
} ev_child;
#if EV_STAT_ENABLE
/* st_nlink = 0 means missing file or other error */
# ifdef _WIN32
typedef struct _stati64 ev_statdata;
# else
typedef struct stat ev_statdata;
# endif
/* invoked each time the stat data changes for a given path */
/* revent EV_STAT */
typedef struct ev_stat
{
EV_WATCHER_LIST (ev_stat)
ev_timer timer; /* private */
ev_tstamp interval; /* ro */
const char *path; /* ro */
ev_statdata prev; /* ro */
ev_statdata attr; /* ro */
int wd; /* wd for inotify, fd for kqueue */
} ev_stat;
#endif
/* invoked when the nothing else needs to be done, keeps the process from blocking */
/* revent EV_IDLE */
typedef struct ev_idle
{
EV_WATCHER (ev_idle)
} ev_idle;
/* invoked for each run of the mainloop, just before the blocking call */
/* you can still change events in any way you like */
/* revent EV_PREPARE */
typedef struct ev_prepare
{
EV_WATCHER (ev_prepare)
} ev_prepare;
/* invoked for each run of the mainloop, just after the blocking call */
/* revent EV_CHECK */
typedef struct ev_check
{
EV_WATCHER (ev_check)
} ev_check;
/* the callback gets invoked before check in the child process when a fork was detected */
/* revent EV_FORK */
typedef struct ev_fork
{
EV_WATCHER (ev_fork)
} ev_fork;
/* is invoked just before the loop gets destroyed */
/* revent EV_CLEANUP */
typedef struct ev_cleanup
{
EV_WATCHER (ev_cleanup)
} ev_cleanup;
#if EV_EMBED_ENABLE
/* used to embed an event loop inside another */
/* the callback gets invoked when the event loop has handled events, and can be 0 */
typedef struct ev_embed
{
EV_WATCHER (ev_embed)
struct ev_loop *other; /* ro */
#undef EV_IO_ENABLE
#define EV_IO_ENABLE 1
ev_io io; /* private */
#undef EV_PREPARE_ENABLE
#define EV_PREPARE_ENABLE 1
ev_prepare prepare; /* private */
ev_check check; /* unused */
ev_timer timer; /* unused */
ev_periodic periodic; /* unused */
ev_idle idle; /* unused */
ev_fork fork; /* private */
ev_cleanup cleanup; /* unused */
} ev_embed;
#endif
#if EV_ASYNC_ENABLE
/* invoked when somebody calls ev_async_send on the watcher */
/* revent EV_ASYNC */
typedef struct ev_async
{
EV_WATCHER (ev_async)
EV_ATOMIC_T sent; /* private */
} ev_async;
# define ev_async_pending(w) (+(w)->sent)
#endif
/* the presence of this union forces similar struct layout */
union ev_any_watcher
{
struct ev_watcher w;
struct ev_watcher_list wl;
struct ev_io io;
struct ev_timer timer;
struct ev_periodic periodic;
struct ev_signal signal;
struct ev_child child;
#if EV_STAT_ENABLE
struct ev_stat stat;
#endif
#if EV_IDLE_ENABLE
struct ev_idle idle;
#endif
struct ev_prepare prepare;
struct ev_check check;
#if EV_FORK_ENABLE
struct ev_fork fork;
#endif
#if EV_CLEANUP_ENABLE
struct ev_cleanup cleanup;
#endif
#if EV_EMBED_ENABLE
struct ev_embed embed;
#endif
#if EV_ASYNC_ENABLE
struct ev_async async;
#endif
};
/* flag bits for ev_default_loop and ev_loop_new */
enum {
/* the default */
EVFLAG_AUTO = 0x00000000U, /* not quite a mask */
/* flag bits */
EVFLAG_NOENV = 0x01000000U, /* do NOT consult environment */
EVFLAG_FORKCHECK = 0x02000000U, /* check for a fork in each iteration */
/* debugging/feature disable */
EVFLAG_NOINOTIFY = 0x00100000U, /* do not attempt to use inotify */
#if EV_COMPAT3
EVFLAG_NOSIGFD = 0, /* compatibility to pre-3.9 */
#endif
EVFLAG_SIGNALFD = 0x00200000U, /* attempt to use signalfd */
EVFLAG_NOSIGMASK = 0x00400000U, /* avoid modifying the signal mask */
EVFLAG_NOTIMERFD = 0x00800000U /* avoid creating a timerfd */
};
/* method bits to be ored together */
enum {
EVBACKEND_SELECT = 0x00000001U, /* available just about anywhere */
EVBACKEND_POLL = 0x00000002U, /* !win, !aix, broken on osx */
EVBACKEND_EPOLL = 0x00000004U, /* linux */
EVBACKEND_KQUEUE = 0x00000008U, /* bsd, broken on osx */
EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */
EVBACKEND_PORT = 0x00000020U, /* solaris 10 */
EVBACKEND_LINUXAIO = 0x00000040U, /* linux AIO, 4.19+ */
EVBACKEND_IOURING = 0x00000080U, /* linux io_uring, 5.1+ */
EVBACKEND_ALL = 0x000000FFU, /* all known backends */
EVBACKEND_MASK = 0x0000FFFFU /* all future backends */
};
#if EV_PROTOTYPES
EV_API_DECL int ev_version_major (void) EV_NOEXCEPT;
EV_API_DECL int ev_version_minor (void) EV_NOEXCEPT;
EV_API_DECL unsigned int ev_supported_backends (void) EV_NOEXCEPT;
EV_API_DECL unsigned int ev_recommended_backends (void) EV_NOEXCEPT;
EV_API_DECL unsigned int ev_embeddable_backends (void) EV_NOEXCEPT;
EV_API_DECL ev_tstamp ev_time (void) EV_NOEXCEPT;
EV_API_DECL void ev_sleep (ev_tstamp delay) EV_NOEXCEPT; /* sleep for a while */
/* Sets the allocation function to use, works like realloc.
* It is used to allocate and free memory.
* If it returns zero when memory needs to be allocated, the library might abort
* or take some potentially destructive action.
* The default is your system realloc function.
*/
EV_API_DECL void ev_set_allocator (void *(*cb)(void *ptr, long size) EV_NOEXCEPT) EV_NOEXCEPT;
/* set the callback function to call on a
* retryable syscall error
* (such as failed select, poll, epoll_wait)
*/
EV_API_DECL void ev_set_syserr_cb (void (*cb)(const char *msg) EV_NOEXCEPT) EV_NOEXCEPT;
#if EV_MULTIPLICITY
/* the default loop is the only one that handles signals and child watchers */
/* you can call this as often as you like */
EV_API_DECL struct ev_loop *ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_NOEXCEPT;
#ifdef EV_API_STATIC
EV_API_DECL struct ev_loop *ev_default_loop_ptr;
#endif
EV_INLINE struct ev_loop *
ev_default_loop_uc_ (void) EV_NOEXCEPT
{
extern struct ev_loop *ev_default_loop_ptr;
return ev_default_loop_ptr;
}
EV_INLINE int
ev_is_default_loop (EV_P) EV_NOEXCEPT
{
return EV_A == EV_DEFAULT_UC;
}
/* create and destroy alternative loops that don't handle signals */
EV_API_DECL struct ev_loop *ev_loop_new (unsigned int flags EV_CPP (= 0)) EV_NOEXCEPT;
EV_API_DECL ev_tstamp ev_now (EV_P) EV_NOEXCEPT; /* time w.r.t. timers and the eventloop, updated after each poll */
#else
EV_API_DECL int ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_NOEXCEPT; /* returns true when successful */
EV_API_DECL ev_tstamp ev_rt_now;
EV_INLINE ev_tstamp
ev_now (void) EV_NOEXCEPT
{
return ev_rt_now;
}
/* looks weird, but ev_is_default_loop (EV_A) still works if this exists */
EV_INLINE int
ev_is_default_loop (void) EV_NOEXCEPT
{
return 1;
}
#endif /* multiplicity */
/* destroy event loops, also works for the default loop */
EV_API_DECL void ev_loop_destroy (EV_P);
/* this needs to be called after fork, to duplicate the loop */
/* when you want to re-use it in the child */
/* you can call it in either the parent or the child */
/* you can actually call it at any time, anywhere :) */
EV_API_DECL void ev_loop_fork (EV_P) EV_NOEXCEPT;
EV_API_DECL unsigned int ev_backend (EV_P) EV_NOEXCEPT; /* backend in use by loop */
EV_API_DECL void ev_now_update (EV_P) EV_NOEXCEPT; /* update event loop time */
#if EV_WALK_ENABLE
/* walk (almost) all watchers in the loop of a given type, invoking the */
/* callback on every such watcher. The callback might stop the watcher, */
/* but do nothing else with the loop */
EV_API_DECL void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_NOEXCEPT;
#endif
#endif /* prototypes */
/* ev_run flags values */
enum {
EVRUN_NOWAIT = 1, /* do not block/wait */
EVRUN_ONCE = 2 /* block *once* only */
};
/* ev_break how values */
enum {
EVBREAK_CANCEL = 0, /* undo unloop */
EVBREAK_ONE = 1, /* unloop once */
EVBREAK_ALL = 2 /* unloop all loops */
};
#if EV_PROTOTYPES
EV_API_DECL int ev_run (EV_P_ int flags EV_CPP (= 0));
EV_API_DECL void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)) EV_NOEXCEPT; /* break out of the loop */
/*
* ref/unref can be used to add or remove a refcount on the mainloop. every watcher
* keeps one reference. if you have a long-running watcher you never unregister that
* should not keep ev_loop from running, unref() after starting, and ref() before stopping.
*/
EV_API_DECL void ev_ref (EV_P) EV_NOEXCEPT;
EV_API_DECL void ev_unref (EV_P) EV_NOEXCEPT;
/*
* convenience function, wait for a single event, without registering an event watcher
* if timeout is < 0, do wait indefinitely
*/
EV_API_DECL void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_NOEXCEPT;
EV_API_DECL void ev_invoke_pending (EV_P); /* invoke all pending watchers */
# if EV_FEATURE_API
EV_API_DECL unsigned int ev_iteration (EV_P) EV_NOEXCEPT; /* number of loop iterations */
EV_API_DECL unsigned int ev_depth (EV_P) EV_NOEXCEPT; /* #ev_loop enters - #ev_loop leaves */
EV_API_DECL void ev_verify (EV_P) EV_NOEXCEPT; /* abort if loop data corrupted */
EV_API_DECL void ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_NOEXCEPT; /* sleep at least this time, default 0 */
EV_API_DECL void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_NOEXCEPT; /* sleep at least this time, default 0 */
/* advanced stuff for threading etc. support, see docs */
EV_API_DECL void ev_set_userdata (EV_P_ void *data) EV_NOEXCEPT;
EV_API_DECL void *ev_userdata (EV_P) EV_NOEXCEPT;
typedef void (*ev_loop_callback)(EV_P);
EV_API_DECL void ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_NOEXCEPT;
/* C++ doesn't allow the use of the ev_loop_callback typedef here, so we need to spell it out */
EV_API_DECL void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_NOEXCEPT, void (*acquire)(EV_P) EV_NOEXCEPT) EV_NOEXCEPT;
EV_API_DECL unsigned int ev_pending_count (EV_P) EV_NOEXCEPT; /* number of pending events, if any */
/*
* stop/start the timer handling.
*/
EV_API_DECL void ev_suspend (EV_P) EV_NOEXCEPT;
EV_API_DECL void ev_resume (EV_P) EV_NOEXCEPT;
#endif
#endif
/* these may evaluate ev multiple times, and the other arguments at most once */
/* either use ev_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */
#define ev_init(ev,cb_) do { \
((ev_watcher *)(void *)(ev))->active = \
((ev_watcher *)(void *)(ev))->pending = 0; \
ev_set_priority ((ev), 0); \
ev_set_cb ((ev), cb_); \
} while (0)
#define ev_io_modify(ev,events_) do { (ev)->events = (ev)->events & EV__IOFDSET | (events_); } while (0)
#define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_) | EV__IOFDSET; } while (0)
#define ev_timer_set(ev,after_,repeat_) do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0)
#define ev_periodic_set(ev,ofs_,ival_,rcb_) do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb = (rcb_); } while (0)
#define ev_signal_set(ev,signum_) do { (ev)->signum = (signum_); } while (0)
#define ev_child_set(ev,pid_,trace_) do { (ev)->pid = (pid_); (ev)->flags = !!(trace_); } while (0)
#define ev_stat_set(ev,path_,interval_) do { (ev)->path = (path_); (ev)->interval = (interval_); (ev)->wd = -2; } while (0)
#define ev_idle_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_prepare_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_check_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_embed_set(ev,other_) do { (ev)->other = (other_); } while (0)
#define ev_fork_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_cleanup_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_async_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)
#define ev_timer_init(ev,cb,after,repeat) do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0)
#define ev_periodic_init(ev,cb,ofs,ival,rcb) do { ev_init ((ev), (cb)); ev_periodic_set ((ev),(ofs),(ival),(rcb)); } while (0)
#define ev_signal_init(ev,cb,signum) do { ev_init ((ev), (cb)); ev_signal_set ((ev), (signum)); } while (0)
#define ev_child_init(ev,cb,pid,trace) do { ev_init ((ev), (cb)); ev_child_set ((ev),(pid),(trace)); } while (0)
#define ev_stat_init(ev,cb,path,interval) do { ev_init ((ev), (cb)); ev_stat_set ((ev),(path),(interval)); } while (0)
#define ev_idle_init(ev,cb) do { ev_init ((ev), (cb)); ev_idle_set ((ev)); } while (0)
#define ev_prepare_init(ev,cb) do { ev_init ((ev), (cb)); ev_prepare_set ((ev)); } while (0)
#define ev_check_init(ev,cb) do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0)
#define ev_embed_init(ev,cb,other) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0)
#define ev_fork_init(ev,cb) do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0)
#define ev_cleanup_init(ev,cb) do { ev_init ((ev), (cb)); ev_cleanup_set ((ev)); } while (0)
#define ev_async_init(ev,cb) do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0)
#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */
#define ev_cb_(ev) (ev)->cb /* rw */
#define ev_cb(ev) (memmove (&ev_cb_ (ev), &((ev_watcher *)(ev))->cb, sizeof (ev_cb_ (ev))), (ev)->cb)
#if EV_MINPRI == EV_MAXPRI
# define ev_priority(ev) ((ev), EV_MINPRI)
# define ev_set_priority(ev,pri) ((ev), (pri))
#else
# define ev_priority(ev) (+(((ev_watcher *)(void *)(ev))->priority))
# define ev_set_priority(ev,pri) ( (ev_watcher *)(void *)(ev))->priority = (pri)
#endif
#define ev_periodic_at(ev) (+((ev_watcher_time *)(ev))->at)
#ifndef ev_set_cb
/* memmove is used here to avoid strict aliasing violations, and hopefully is optimized out by any reasonable compiler */
# define ev_set_cb(ev,cb_) (ev_cb_ (ev) = (cb_), memmove (&((ev_watcher *)(ev))->cb, &ev_cb_ (ev), sizeof (ev_cb_ (ev))))
#endif
/* stopping (enabling, adding) a watcher does nothing if it is already running */
/* stopping (disabling, deleting) a watcher does nothing unless it's already running */
#if EV_PROTOTYPES
/* feeds an event into a watcher as if the event actually occurred */
/* accepts any ev_watcher type */
EV_API_DECL void ev_feed_event (EV_P_ void *w, int revents) EV_NOEXCEPT;
EV_API_DECL void ev_feed_fd_event (EV_P_ int fd, int revents) EV_NOEXCEPT;
#if EV_SIGNAL_ENABLE
EV_API_DECL void ev_feed_signal (int signum) EV_NOEXCEPT;
EV_API_DECL void ev_feed_signal_event (EV_P_ int signum) EV_NOEXCEPT;
#endif
EV_API_DECL void ev_invoke (EV_P_ void *w, int revents);
EV_API_DECL int ev_clear_pending (EV_P_ void *w) EV_NOEXCEPT;
EV_API_DECL void ev_io_start (EV_P_ ev_io *w) EV_NOEXCEPT;
EV_API_DECL void ev_io_stop (EV_P_ ev_io *w) EV_NOEXCEPT;
EV_API_DECL void ev_timer_start (EV_P_ ev_timer *w) EV_NOEXCEPT;
EV_API_DECL void ev_timer_stop (EV_P_ ev_timer *w) EV_NOEXCEPT;
/* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */
EV_API_DECL void ev_timer_again (EV_P_ ev_timer *w) EV_NOEXCEPT;
/* return remaining time */
EV_API_DECL ev_tstamp ev_timer_remaining (EV_P_ ev_timer *w) EV_NOEXCEPT;
#if EV_PERIODIC_ENABLE
EV_API_DECL void ev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT;
EV_API_DECL void ev_periodic_stop (EV_P_ ev_periodic *w) EV_NOEXCEPT;
EV_API_DECL void ev_periodic_again (EV_P_ ev_periodic *w) EV_NOEXCEPT;
#endif
/* only supported in the default loop */
#if EV_SIGNAL_ENABLE
EV_API_DECL void ev_signal_start (EV_P_ ev_signal *w) EV_NOEXCEPT;
EV_API_DECL void ev_signal_stop (EV_P_ ev_signal *w) EV_NOEXCEPT;
#endif
/* only supported in the default loop */
# if EV_CHILD_ENABLE
EV_API_DECL void ev_child_start (EV_P_ ev_child *w) EV_NOEXCEPT;
EV_API_DECL void ev_child_stop (EV_P_ ev_child *w) EV_NOEXCEPT;
# endif
# if EV_STAT_ENABLE
EV_API_DECL void ev_stat_start (EV_P_ ev_stat *w) EV_NOEXCEPT;
EV_API_DECL void ev_stat_stop (EV_P_ ev_stat *w) EV_NOEXCEPT;
EV_API_DECL void ev_stat_stat (EV_P_ ev_stat *w) EV_NOEXCEPT;
# endif
# if EV_IDLE_ENABLE
EV_API_DECL void ev_idle_start (EV_P_ ev_idle *w) EV_NOEXCEPT;
EV_API_DECL void ev_idle_stop (EV_P_ ev_idle *w) EV_NOEXCEPT;
# endif
#if EV_PREPARE_ENABLE
EV_API_DECL void ev_prepare_start (EV_P_ ev_prepare *w) EV_NOEXCEPT;
EV_API_DECL void ev_prepare_stop (EV_P_ ev_prepare *w) EV_NOEXCEPT;
#endif
#if EV_CHECK_ENABLE
EV_API_DECL void ev_check_start (EV_P_ ev_check *w) EV_NOEXCEPT;
EV_API_DECL void ev_check_stop (EV_P_ ev_check *w) EV_NOEXCEPT;
#endif
# if EV_FORK_ENABLE
EV_API_DECL void ev_fork_start (EV_P_ ev_fork *w) EV_NOEXCEPT;
EV_API_DECL void ev_fork_stop (EV_P_ ev_fork *w) EV_NOEXCEPT;
# endif
# if EV_CLEANUP_ENABLE
EV_API_DECL void ev_cleanup_start (EV_P_ ev_cleanup *w) EV_NOEXCEPT;
EV_API_DECL void ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_NOEXCEPT;
# endif
# if EV_EMBED_ENABLE
/* only supported when loop to be embedded is in fact embeddable */
EV_API_DECL void ev_embed_start (EV_P_ ev_embed *w) EV_NOEXCEPT;
EV_API_DECL void ev_embed_stop (EV_P_ ev_embed *w) EV_NOEXCEPT;
EV_API_DECL void ev_embed_sweep (EV_P_ ev_embed *w) EV_NOEXCEPT;
# endif
# if EV_ASYNC_ENABLE
EV_API_DECL void ev_async_start (EV_P_ ev_async *w) EV_NOEXCEPT;
EV_API_DECL void ev_async_stop (EV_P_ ev_async *w) EV_NOEXCEPT;
EV_API_DECL void ev_async_send (EV_P_ ev_async *w) EV_NOEXCEPT;
# endif
#if EV_COMPAT3
#define EVLOOP_NONBLOCK EVRUN_NOWAIT
#define EVLOOP_ONESHOT EVRUN_ONCE
#define EVUNLOOP_CANCEL EVBREAK_CANCEL
#define EVUNLOOP_ONE EVBREAK_ONE
#define EVUNLOOP_ALL EVBREAK_ALL
#if EV_PROTOTYPES
EV_INLINE void ev_loop (EV_P_ int flags) { ev_run (EV_A_ flags); }
EV_INLINE void ev_unloop (EV_P_ int how ) { ev_break (EV_A_ how ); }
EV_INLINE void ev_default_destroy (void) { ev_loop_destroy (EV_DEFAULT); }
EV_INLINE void ev_default_fork (void) { ev_loop_fork (EV_DEFAULT); }
#if EV_FEATURE_API
EV_INLINE unsigned int ev_loop_count (EV_P) { return ev_iteration (EV_A); }
EV_INLINE unsigned int ev_loop_depth (EV_P) { return ev_depth (EV_A); }
EV_INLINE void ev_loop_verify (EV_P) { ev_verify (EV_A); }
#endif
#endif
#else
typedef struct ev_loop ev_loop;
#endif
#endif
EV_CPP(})
#endif
LIBA_TARGET := libapi_ev.a
\ No newline at end of file
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* cJSON */
/* JSON parser in C. */
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "cJSON.h"
static int cJSON_strcasecmp(const char *s1,const char *s2)
{
if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}
static void *(*cJSON_malloc)(size_t sz) = malloc;
static void (*cJSON_free)(void *ptr) = free;
static char* cJSON_strdup(const char* str)
{
size_t len;
char* copy;
len = strlen(str) + 1;
if (!(copy = (char*)cJSON_malloc(len))) return 0;
memcpy(copy,str,len);
return copy;
}
void cJSON_InitHooks(cJSON_Hooks* hooks)
{
if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc;
cJSON_free = free;
return;
}
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
}
/* Internal constructor. */
static cJSON *cJSON_New_Item()
{
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
if (node) memset(node,0,sizeof(cJSON));
return node;
}
/* Delete a cJSON structure. */
void cJSON_Delete(cJSON *c)
{
cJSON *next;
while (c)
{
next=c->next;
if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
if (c->string) cJSON_free(c->string);
cJSON_free(c);
c=next;
}
}
/* Parse the input text to generate a number, and populate the result into item. */
static char **parse_number(cJSON *item, char **num)
{
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
if (**num=='-') { /* Has sign? */
sign = -1;
(*num)++;
}
if (**num=='0') /* is zero */
(*num)++;
if (**num>='1' && **num<='9') { /* Number? */
do {
n=(n*10.0)+(**num -'0');
(*num)++;
} while (**num>='0' && **num<='9');
}
if (**num=='.' && (*num)[1]>='0' && (*num)[1]<='9') { /* Fractional part? */
(*num)++;
do {
n=(n*10.0)+(**num -'0');
scale--;
(*num)++;
} while (**num>='0' && **num<='9');
}
if (**num=='e' || **num=='E') /* Exponent? */
{ (*num)++;
/* signed? */
if (**num=='+')
(*num)++;
else if (**num=='-')
signsubscale=-1,(*num)++;
while (**num>='0' && **num<='9') { /* Number? */
subscale=(subscale*10)+(**num - '0');
(*num)++;
}
}
n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
item->valuedouble=n;
item->valueint=(int)n;
item->type=cJSON_Number;
return num;
}
/* Render the number nicely from the given item into a string. */
static char *print_number(cJSON *item)
{
char *str;
double d=item->valuedouble;
if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
{
str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
if (str) sprintf(str,"%d",item->valueint);
}
else
{
str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
if (str)
{
if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
else sprintf(str,"%f",d);
}
}
return str;
}
/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static char **parse_string(cJSON *item, char **str)
{
char *ptr=*str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (**str!='\"') return NULL; /* not a string! */
while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
if (!out) return 0;
ptr=*str+1;ptr2=out;
while (*ptr!='\"' && *ptr)
{
if (*ptr!='\\') *ptr2++=*ptr++;
else
{
ptr++;
switch (*ptr)
{
case 'b': *ptr2++='\b'; break;
case 'f': *ptr2++='\f'; break;
case 'n': *ptr2++='\n'; break;
case 'r': *ptr2++='\r'; break;
case 't': *ptr2++='\t'; break;
case 'u': /* transcode utf16 to utf8. */
sscanf(ptr+1,"%4x",&uc);ptr+=4; /* get the unicode char. */
if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; // check for invalid.
if (uc>=0xD800 && uc<=0xDBFF) // UTF16 surrogate pairs.
{
if (ptr[1]!='\\' || ptr[2]!='u') break; // missing second-half of surrogate.
sscanf(ptr+3,"%4x",&uc2);ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) break; // invalid second-half of surrogate.
uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF);
}
len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
switch (len) {
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=len;
break;
default: *ptr2++=*ptr; break;
}
ptr++;
}
}
*ptr2=0;
if (*ptr=='\"') ptr++;
item->valuestring=out;
item->type=cJSON_String;
*str = ptr;
return str;
}
/* Render the cstring provided to an escaped version that can be printed. */
static char *print_string_ptr(const char *str)
{
const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
if (!str) return cJSON_strdup("");
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
out=(char*)cJSON_malloc(len+3);
if (!out) return 0;
ptr2=out;ptr=str;
*ptr2++='\"';
while (*ptr)
{
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
else
{
*ptr2++='\\';
switch (token=*ptr++)
{
case '\\': *ptr2++='\\'; break;
case '\"': *ptr2++='\"'; break;
case '\b': *ptr2++='b'; break;
case '\f': *ptr2++='f'; break;
case '\n': *ptr2++='n'; break;
case '\r': *ptr2++='r'; break;
case '\t': *ptr2++='t'; break;
default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
}
}
}
*ptr2++='\"';
*ptr2++=0;
return out;
}
/* Render the cstring provided to an escaped version that can be printed. */
static char *print_string_pure(const char *str)
{
const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
if (!str) return cJSON_strdup("");
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
out=(char*)cJSON_malloc(len+3);
if (!out) return 0;
ptr2=out;ptr=str;
//*ptr2++='\"';
while (*ptr)
{
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
else
{
*ptr2++='\\';
switch (token=*ptr++)
{
case '\\': *ptr2++='\\'; break;
case '\"': *ptr2++='\"'; break;
case '\b': *ptr2++='b'; break;
case '\f': *ptr2++='f'; break;
case '\n': *ptr2++='n'; break;
case '\r': *ptr2++='r'; break;
case '\t': *ptr2++='t'; break;
default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
}
}
}
//*ptr2++='\"';
*ptr2++=0;
return out;
}
/* Invote print_string_ptr (which is useful) on an item. */
static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
static char *print_string_clean(cJSON *item) {return print_string_pure(item->valuestring);}
/* Predeclare these prototypes. */
static char **parse_value(cJSON *item, char **value);
static char *print_value(cJSON *item,int depth,int fmt);
static char *print_value_pure(cJSON *item,int depth,int fmt);
static char **parse_array(cJSON *item, char **value);
static char *print_array(cJSON *item,int depth,int fmt);
static char **parse_object(cJSON *item, char **value);
static char *print_object(cJSON *item,int depth,int fmt);
/* Utility to jump whitespace and cr/lf */
static inline char **skip(char **in)
{
if (in && *in)
while (isspace(**in))
(*in)++;
return in;
}
/* Parse an object - create a new root, and populate. */
cJSON *cJSON_Parse(const char *value)
{
cJSON *c=cJSON_New_Item();
if (!c) return 0; /* memory fail */
char **end_ptr = (char **)&value;
if (!parse_value(c,skip(end_ptr))) {cJSON_Delete(c);return 0;}
return c;
}
/* Parse an object - create a new root, and populate
* Also indicates where in the stream the Object ends. */
cJSON *cJSON_Parse_Stream(const char *value, char **end_ptr)
{
if(!end_ptr)
return NULL;
cJSON *c=cJSON_New_Item();
if (!c) return 0; /* memory fail */
*end_ptr = (char *)value;
if (!parse_value(c,skip(end_ptr))) {cJSON_Delete(c);return 0;}
return c;
}
/* Render a cJSON item/entity/structure to text. */
char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
char *cJSON_Print_pure(cJSON *item) {return print_value_pure(item,0,1);}
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
static int stream_cmp(char **stream, const char *str)
{
while (**stream == *str) {
(*stream)++;
str++;
}
if (*str == '\0')
return 0;
return **stream - *str;
}
/* Parser core - when encountering text, process appropriately. */
static char **parse_value(cJSON *item, char **value)
{
if (!stream_cmp(value,"null")) {
item->type=cJSON_NULL;
return value;
} else if (!stream_cmp(value,"false")) {
item->type=cJSON_False;
return value;
} else if (!stream_cmp(value,"true")) {
item->type=cJSON_True;
item->valueint = 1;
return value;
}
switch (**value) {
case '"': return parse_string(item,value);
case '-':
case '0'...'9': return parse_number(item,value);
case '[': return parse_array(item,value);
case '{': return parse_object(item,value);
}
return NULL; /* failure */
}
/* Render a value to text. */
static char *print_value(cJSON *item,int depth,int fmt)
{
char *out=0;
if (!item) return 0;
switch ((item->type)&255)
{
case cJSON_NULL: out=cJSON_strdup("null"); break;
case cJSON_False: out=cJSON_strdup("false");break;
case cJSON_True: out=cJSON_strdup("true"); break;
case cJSON_Number: out=print_number(item);break;
case cJSON_String: out=print_string(item);break;
case cJSON_Array: out=print_array(item,depth,fmt);break;
case cJSON_Object: out=print_object(item,depth,fmt);break;
}
return out;
}
static char *print_value_pure(cJSON *item,int depth,int fmt)
{
char *out=0;
if (!item) return 0;
switch ((item->type)&255)
{
case cJSON_NULL: out=cJSON_strdup("null"); break;
case cJSON_False: out=cJSON_strdup("false");break;
case cJSON_True: out=cJSON_strdup("true"); break;
case cJSON_Number: out=print_number(item);break;
case cJSON_String: out=print_string_clean(item);break;
case cJSON_Array: out=print_array(item,depth,fmt);break;
case cJSON_Object: out=print_object(item,depth,fmt);break;
}
return out;
}
/* Build an array from input text. */
static char **parse_array(cJSON *item, char **value)
{
cJSON *child;
if (**value!='[') /* not an array! */
return NULL;
item->type=cJSON_Array;
(*value)++;
skip(value);
if (**value==']') {
(*value)++;
return value; /* empty array. */
}
item->child=child=cJSON_New_Item();
if (!item->child) return 0; /* memory fail */
if (!skip(parse_value(child,value))) /* skip any spacing, get the value. */
return NULL;
while (**value==',')
{
(*value)++;
skip(value);
if (**value==']') {
(*value)++;
break;
}
cJSON *new_item;
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
if(!skip(parse_value(child,value)))
return 0; /* memory fail */
}
if (**value != ']')
return NULL;
(*value)++;
return value;
}
/* Render an array to text */
static char *print_array(cJSON *item,int depth,int fmt)
{
char **entries;
char *out=0,*ptr,*ret;int len=5;
cJSON *child=item->child;
int numentries=0,i=0,fail=0;
/* How many entries in the array? */
while (child) numentries++,child=child->next;
/* Allocate an array to hold the values for each */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
memset(entries,0,numentries*sizeof(char*));
/* Retrieve all the results: */
child=item->child;
while (child && !fail)
{
ret=print_value(child,depth+1,fmt);
entries[i++]=ret;
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
child=child->next;
}
/* If we didn't fail, try to malloc the output string */
if (!fail) out=(char*)cJSON_malloc(len);
/* If that fails, we fail. */
if (!out) fail=1;
/* Handle failure. */
if (fail)
{
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
cJSON_free(entries);
return 0;
}
/* Compose the output array. */
*out='[';
ptr=out+1;*ptr=0;
for (i=0;i<numentries;i++)
{
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
cJSON_free(entries[i]);
}
cJSON_free(entries);
*ptr++=']';*ptr++=0;
return out;
}
/* Build an object from the text. */
static char **parse_object(cJSON *item, char **value)
{
cJSON *child;
if (**value!='{') return NULL; /* not an object! */
item->type=cJSON_Object;
(*value)++;
skip(value);
if (**value=='}') {
(*value)++;
return value; /* empty object. */
}
item->child=child=cJSON_New_Item();
if (!item->child) return 0;
if (!skip(parse_string(child,value)))
return 0;
child->string=child->valuestring;child->valuestring=0;
if (**value!=':') return NULL; /* fail! */
(*value)++;
if (!skip(parse_value(child,skip(value)))) /* skip any spacing, get the value. */
return 0;
while (**value==',')
{
(*value)++;
skip(value);
if (**value == '}') {
(*value)++;
break;
}
cJSON *new_item;
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
if (!skip(parse_string(child,value)))
return 0;
child->string=child->valuestring;child->valuestring=0;
if (**value!=':') return NULL; /* fail! */
(*value)++;
if (!skip(parse_value(child,skip(value)))) /* skip any spacing, get the value. */
return 0;
}
if (**value != '}')
return NULL;
(*value)++;
return value;
}
/* Render an object to text. */
static char *print_object(cJSON *item,int depth,int fmt)
{
char **entries=0,**names=0;
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
cJSON *child=item->child;
int numentries=0,fail=0;
/* Count the number of entries. */
while (child) numentries++,child=child->next;
/* Allocate space for the names and the objects */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
names=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!names) {cJSON_free(entries);return 0;}
memset(entries,0,sizeof(char*)*numentries);
memset(names,0,sizeof(char*)*numentries);
/* Collect all the results into our arrays: */
child=item->child;depth++;if (fmt) len+=depth;
while (child)
{
names[i]=str=print_string_ptr(child->string);
entries[i++]=ret=print_value(child,depth,fmt);
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
child=child->next;
}
/* Try to allocate the output string */
if (!fail) out=(char*)cJSON_malloc(len);
if (!out) fail=1;
/* Handle failure */
if (fail)
{
for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
cJSON_free(names);cJSON_free(entries);
return 0;
}
/* Compose the output: */
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
for (i=0;i<numentries;i++)
{
if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
strcpy(ptr,names[i]);ptr+=strlen(names[i]);
*ptr++=':';if (fmt) *ptr++='\t';
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) *ptr++=',';
if (fmt) *ptr++='\n';*ptr=0;
cJSON_free(names[i]);cJSON_free(entries[i]);
}
cJSON_free(names);cJSON_free(entries);
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr++=0;
return out;
}
/* Get Array size/item / object item. */
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
/* Utility for array list handling. */
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
/* Utility for handling references. */
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
/* Add item to array/object. */
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
/* Replace array/object items with new ones. */
void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
/* Create basic types: */
cJSON *cJSON_CreateNull() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
cJSON *cJSON_CreateArray() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
/* Create Arrays: */
cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
#define cJSON_IsReference 256
/* The cJSON structure: */
typedef struct cJSON {
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;
typedef struct cJSON_Hooks {
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;
/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished.
* end_ptr will point to 1 past the end of the JSON object */
extern cJSON *cJSON_Parse_Stream(const char *value, char **end_ptr);
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char *cJSON_Print(cJSON *item);
extern char *cJSON_Print_pure(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item);
/* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c);
/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull();
extern cJSON *cJSON_CreateTrue();
extern cJSON *cJSON_CreateFalse();
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray();
extern cJSON *cJSON_CreateObject();
/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
/* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
/* Update array items. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
#ifdef __cplusplus
}
#endif
#endif
LIBA_TARGET := libiot_cjson.a
\ No newline at end of file
...@@ -2885,7 +2885,7 @@ static int MQTTAsync_cleanSession(Clients* client) ...@@ -2885,7 +2885,7 @@ static int MQTTAsync_cleanSession(Clients* client)
static int MQTTAsync_deliverMessage(MQTTAsyncs* m, char* topicName, size_t topicLen, MQTTAsync_message* mm) static int MQTTAsync_deliverMessage(MQTTAsyncs* m, char* topicName, size_t topicLen, MQTTAsync_message* mm)
{ {
int rc; int rc;
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
Log(TRACE_MIN, -1, "Calling messageArrived for client %s, queue depth %d", Log(TRACE_MIN, -1, "Calling messageArrived for client %s, queue depth %d",
m->c->clientID, m->c->messageQueue->count); m->c->clientID, m->c->messageQueue->count);
rc = (*(m->ma))(m->maContext, topicName, (int)topicLen, mm); rc = (*(m->ma))(m->maContext, topicName, (int)topicLen, mm);
...@@ -2902,6 +2902,7 @@ void Protocol_processPublication(Publish* publish, Clients* client, int allocate ...@@ -2902,6 +2902,7 @@ void Protocol_processPublication(Publish* publish, Clients* client, int allocate
MQTTAsync_message* mm = NULL; MQTTAsync_message* mm = NULL;
MQTTAsync_message initialized = MQTTAsync_message_initializer; MQTTAsync_message initialized = MQTTAsync_message_initializer;
int rc = 0; int rc = 0;
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
FUNC_ENTRY; FUNC_ENTRY;
if ((mm = malloc(sizeof(MQTTAsync_message))) == NULL) if ((mm = malloc(sizeof(MQTTAsync_message))) == NULL)
......
...@@ -304,6 +304,7 @@ int MQTTProtocol_handlePublishes(void* pack, int sock) ...@@ -304,6 +304,7 @@ int MQTTProtocol_handlePublishes(void* pack, int sock)
Clients* client = NULL; Clients* client = NULL;
char* clientid = NULL; char* clientid = NULL;
int rc = TCPSOCKET_COMPLETE; int rc = TCPSOCKET_COMPLETE;
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
FUNC_ENTRY; FUNC_ENTRY;
client = (Clients*)(ListFindItem(bstate->clients, &sock, clientSocketCompare)->content); client = (Clients*)(ListFindItem(bstate->clients, &sock, clientSocketCompare)->content);
...@@ -311,8 +312,10 @@ int MQTTProtocol_handlePublishes(void* pack, int sock) ...@@ -311,8 +312,10 @@ int MQTTProtocol_handlePublishes(void* pack, int sock)
Log(LOG_PROTOCOL, 11, NULL, sock, clientid, publish->msgId, publish->header.bits.qos, Log(LOG_PROTOCOL, 11, NULL, sock, clientid, publish->msgId, publish->header.bits.qos,
publish->header.bits.retain, publish->payloadlen, min(20, publish->payloadlen), publish->payload); publish->header.bits.retain, publish->payloadlen, min(20, publish->payloadlen), publish->payload);
if (publish->header.bits.qos == 0) if (publish->header.bits.qos == 0){
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
Protocol_processPublication(publish, client, 1); Protocol_processPublication(publish, client, 1);
}
else if (!Socket_noPendingWrites(sock)) else if (!Socket_noPendingWrites(sock))
rc = SOCKET_ERROR; /* queue acks? */ rc = SOCKET_ERROR; /* queue acks? */
else if (publish->header.bits.qos == 1) else if (publish->header.bits.qos == 1)
...@@ -321,6 +324,7 @@ int MQTTProtocol_handlePublishes(void* pack, int sock) ...@@ -321,6 +324,7 @@ int MQTTProtocol_handlePublishes(void* pack, int sock)
rc = MQTTPacket_send_puback(publish->MQTTVersion, publish->msgId, &client->net, client->clientID); rc = MQTTPacket_send_puback(publish->MQTTVersion, publish->msgId, &client->net, client->clientID);
/* if we get a socket error from sending the puback, should we ignore the publication? */ /* if we get a socket error from sending the puback, should we ignore the publication? */
Protocol_processPublication(publish, client, 1); Protocol_processPublication(publish, client, 1);
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
} }
else if (publish->header.bits.qos == 2) else if (publish->header.bits.qos == 2)
{ {
...@@ -370,6 +374,7 @@ int MQTTProtocol_handlePublishes(void* pack, int sock) ...@@ -370,6 +374,7 @@ int MQTTProtocol_handlePublishes(void* pack, int sock)
publish1.payloadlen = m->publish->payloadlen; publish1.payloadlen = m->publish->payloadlen;
publish1.MQTTVersion = m->MQTTVersion; publish1.MQTTVersion = m->MQTTVersion;
publish1.properties = m->properties; publish1.properties = m->properties;
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
Protocol_processPublication(&publish1, client, 1); Protocol_processPublication(&publish1, client, 1);
ListRemove(&(state.publications), m->publish); ListRemove(&(state.publications), m->publish);
...@@ -567,6 +572,7 @@ int MQTTProtocol_handlePubrels(void* pack, int sock) ...@@ -567,6 +572,7 @@ int MQTTProtocol_handlePubrels(void* pack, int sock)
publish.properties = m->properties; publish.properties = m->properties;
else else
Protocol_processPublication(&publish, client, 0); /* only for 3.1.1 and lower */ Protocol_processPublication(&publish, client, 0); /* only for 3.1.1 and lower */
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
#if !defined(NO_PERSISTENCE) #if !defined(NO_PERSISTENCE)
rc += MQTTPersistence_remove(client, rc += MQTTPersistence_remove(client,
(m->MQTTVersion >= MQTTVERSION_5) ? PERSISTENCE_V5_PUBLISH_RECEIVED : PERSISTENCE_PUBLISH_RECEIVED, (m->MQTTVersion >= MQTTVERSION_5) ? PERSISTENCE_V5_PUBLISH_RECEIVED : PERSISTENCE_PUBLISH_RECEIVED,
......
/*
Copyright (c) 2013 Martin Sustrik All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef BUS_H_INCLUDED
#define BUS_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#define NN_PROTO_BUS 7
#define NN_BUS (NN_PROTO_BUS * 16 + 0)
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012 Martin Sustrik All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef INPROC_H_INCLUDED
#define INPROC_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#define NN_INPROC -1
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012 Martin Sustrik All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef IPC_H_INCLUDED
#define IPC_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#define NN_IPC -2
/* The object set here must be valid as long as you are using the socket */
#define NN_IPC_SEC_ATTR 1
#define NN_IPC_OUTBUFSZ 2
#define NN_IPC_INBUFSZ 3
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012-2014 Martin Sustrik All rights reserved.
Copyright (c) 2013 GoPivotal, Inc. All rights reserved.
Copyright (c) 2015-2016 Jack R. Dunaway. All rights reserved.
Copyright 2017 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef NN_H_INCLUDED
#define NN_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
/* Handle DSO symbol visibility. */
#if !defined(NN_EXPORT)
# if defined(_WIN32) && !defined(NN_STATIC_LIB)
# if defined NN_SHARED_LIB
# define NN_EXPORT __declspec(dllexport)
# else
# define NN_EXPORT __declspec(dllimport)
# endif
# else
# define NN_EXPORT extern
# endif
#endif
/******************************************************************************/
/* ABI versioning support. */
/******************************************************************************/
/* Don't change this unless you know exactly what you're doing and have */
/* read and understand the following documents: */
/* www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html */
/* www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html */
/* The current interface version. */
#define NN_VERSION_CURRENT 5
/* The latest revision of the current interface. */
#define NN_VERSION_REVISION 1
/* How many past interface versions are still supported. */
#define NN_VERSION_AGE 0
/******************************************************************************/
/* Errors. */
/******************************************************************************/
/* A number random enough not to collide with different errno ranges on */
/* different OSes. The assumption is that error_t is at least 32-bit type. */
#define NN_HAUSNUMERO 156384712
/* On some platforms some standard POSIX errnos are not defined. */
#ifndef ENOTSUP
#define ENOTSUP (NN_HAUSNUMERO + 1)
#endif
#ifndef EPROTONOSUPPORT
#define EPROTONOSUPPORT (NN_HAUSNUMERO + 2)
#endif
#ifndef ENOBUFS
#define ENOBUFS (NN_HAUSNUMERO + 3)
#endif
#ifndef ENETDOWN
#define ENETDOWN (NN_HAUSNUMERO + 4)
#endif
#ifndef EADDRINUSE
#define EADDRINUSE (NN_HAUSNUMERO + 5)
#endif
#ifndef EADDRNOTAVAIL
#define EADDRNOTAVAIL (NN_HAUSNUMERO + 6)
#endif
#ifndef ECONNREFUSED
#define ECONNREFUSED (NN_HAUSNUMERO + 7)
#endif
#ifndef EINPROGRESS
#define EINPROGRESS (NN_HAUSNUMERO + 8)
#endif
#ifndef ENOTSOCK
#define ENOTSOCK (NN_HAUSNUMERO + 9)
#endif
#ifndef EAFNOSUPPORT
#define EAFNOSUPPORT (NN_HAUSNUMERO + 10)
#endif
#ifndef EPROTO
#define EPROTO (NN_HAUSNUMERO + 11)
#endif
#ifndef EAGAIN
#define EAGAIN (NN_HAUSNUMERO + 12)
#endif
#ifndef EBADF
#define EBADF (NN_HAUSNUMERO + 13)
#endif
#ifndef EINVAL
#define EINVAL (NN_HAUSNUMERO + 14)
#endif
#ifndef EMFILE
#define EMFILE (NN_HAUSNUMERO + 15)
#endif
#ifndef EFAULT
#define EFAULT (NN_HAUSNUMERO + 16)
#endif
#ifndef EACCES
#define EACCES (NN_HAUSNUMERO + 17)
#endif
#ifndef EACCESS
#define EACCESS (EACCES)
#endif
#ifndef ENETRESET
#define ENETRESET (NN_HAUSNUMERO + 18)
#endif
#ifndef ENETUNREACH
#define ENETUNREACH (NN_HAUSNUMERO + 19)
#endif
#ifndef EHOSTUNREACH
#define EHOSTUNREACH (NN_HAUSNUMERO + 20)
#endif
#ifndef ENOTCONN
#define ENOTCONN (NN_HAUSNUMERO + 21)
#endif
#ifndef EMSGSIZE
#define EMSGSIZE (NN_HAUSNUMERO + 22)
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT (NN_HAUSNUMERO + 23)
#endif
#ifndef ECONNABORTED
#define ECONNABORTED (NN_HAUSNUMERO + 24)
#endif
#ifndef ECONNRESET
#define ECONNRESET (NN_HAUSNUMERO + 25)
#endif
#ifndef ENOPROTOOPT
#define ENOPROTOOPT (NN_HAUSNUMERO + 26)
#endif
#ifndef EISCONN
#define EISCONN (NN_HAUSNUMERO + 27)
#define NN_EISCONN_DEFINED
#endif
#ifndef ESOCKTNOSUPPORT
#define ESOCKTNOSUPPORT (NN_HAUSNUMERO + 28)
#endif
/* Native nanomsg error codes. */
#ifndef ETERM
#define ETERM (NN_HAUSNUMERO + 53)
#endif
#ifndef EFSM
#define EFSM (NN_HAUSNUMERO + 54)
#endif
/* This function retrieves the errno as it is known to the library. */
/* The goal of this function is to make the code 100% portable, including */
/* where the library is compiled with certain CRT library (on Windows) and */
/* linked to an application that uses different CRT library. */
NN_EXPORT int nn_errno (void);
/* Resolves system errors and native errors to human-readable string. */
NN_EXPORT const char *nn_strerror (int errnum);
/* Returns the symbol name (e.g. "NN_REQ") and value at a specified index. */
/* If the index is out-of-range, returns NULL and sets errno to EINVAL */
/* General usage is to start at i=0 and iterate until NULL is returned. */
NN_EXPORT const char *nn_symbol (int i, int *value);
/* Constants that are returned in `ns` member of nn_symbol_properties */
#define NN_NS_NAMESPACE 0
#define NN_NS_VERSION 1
#define NN_NS_DOMAIN 2
#define NN_NS_TRANSPORT 3
#define NN_NS_PROTOCOL 4
#define NN_NS_OPTION_LEVEL 5
#define NN_NS_SOCKET_OPTION 6
#define NN_NS_TRANSPORT_OPTION 7
#define NN_NS_OPTION_TYPE 8
#define NN_NS_OPTION_UNIT 9
#define NN_NS_FLAG 10
#define NN_NS_ERROR 11
#define NN_NS_LIMIT 12
#define NN_NS_EVENT 13
#define NN_NS_STATISTIC 14
/* Constants that are returned in `type` member of nn_symbol_properties */
#define NN_TYPE_NONE 0
#define NN_TYPE_INT 1
#define NN_TYPE_STR 2
/* Constants that are returned in the `unit` member of nn_symbol_properties */
#define NN_UNIT_NONE 0
#define NN_UNIT_BYTES 1
#define NN_UNIT_MILLISECONDS 2
#define NN_UNIT_PRIORITY 3
#define NN_UNIT_BOOLEAN 4
#define NN_UNIT_MESSAGES 5
#define NN_UNIT_COUNTER 6
/* Structure that is returned from nn_symbol */
struct nn_symbol_properties {
/* The constant value */
int value;
/* The constant name */
const char* name;
/* The constant namespace, or zero for namespaces themselves */
int ns;
/* The option type for socket option constants */
int type;
/* The unit for the option value for socket option constants */
int unit;
};
/* Fills in nn_symbol_properties structure and returns it's length */
/* If the index is out-of-range, returns 0 */
/* General usage is to start at i=0 and iterate until zero is returned. */
NN_EXPORT int nn_symbol_info (int i,
struct nn_symbol_properties *buf, int buflen);
/******************************************************************************/
/* Helper function for shutting down multi-threaded applications. */
/******************************************************************************/
NN_EXPORT void nn_term (void);
/******************************************************************************/
/* Zero-copy support. */
/******************************************************************************/
#define NN_MSG ((size_t) -1)
NN_EXPORT void *nn_allocmsg (size_t size, int type);
NN_EXPORT void *nn_reallocmsg (void *msg, size_t size);
NN_EXPORT int nn_freemsg (void *msg);
/******************************************************************************/
/* Socket definition. */
/******************************************************************************/
struct nn_iovec {
void *iov_base;
size_t iov_len;
};
struct nn_msghdr {
struct nn_iovec *msg_iov;
int msg_iovlen;
void *msg_control;
size_t msg_controllen;
};
struct nn_cmsghdr {
size_t cmsg_len;
int cmsg_level;
int cmsg_type;
};
/* Internal stuff. Not to be used directly. */
NN_EXPORT struct nn_cmsghdr *nn_cmsg_nxthdr_ (
const struct nn_msghdr *mhdr,
const struct nn_cmsghdr *cmsg);
#define NN_CMSG_ALIGN_(len) \
(((len) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1))
/* POSIX-defined msghdr manipulation. */
#define NN_CMSG_FIRSTHDR(mhdr) \
nn_cmsg_nxthdr_ ((struct nn_msghdr*) (mhdr), NULL)
#define NN_CMSG_NXTHDR(mhdr, cmsg) \
nn_cmsg_nxthdr_ ((struct nn_msghdr*) (mhdr), (struct nn_cmsghdr*) (cmsg))
#define NN_CMSG_DATA(cmsg) \
((unsigned char*) (((struct nn_cmsghdr*) (cmsg)) + 1))
/* Extensions to POSIX defined by RFC 3542. */
#define NN_CMSG_SPACE(len) \
(NN_CMSG_ALIGN_ (len) + NN_CMSG_ALIGN_ (sizeof (struct nn_cmsghdr)))
#define NN_CMSG_LEN(len) \
(NN_CMSG_ALIGN_ (sizeof (struct nn_cmsghdr)) + (len))
/* SP address families. */
#define AF_SP 1
#define AF_SP_RAW 2
/* Max size of an SP address. */
#define NN_SOCKADDR_MAX 128
/* Socket option levels: Negative numbers are reserved for transports,
positive for socket types. */
#define NN_SOL_SOCKET 0
/* Generic socket options (NN_SOL_SOCKET level). */
#define NN_LINGER 1
#define NN_SNDBUF 2
#define NN_RCVBUF 3
#define NN_SNDTIMEO 4
#define NN_RCVTIMEO 5
#define NN_RECONNECT_IVL 6
#define NN_RECONNECT_IVL_MAX 7
#define NN_SNDPRIO 8
#define NN_RCVPRIO 9
#define NN_SNDFD 10
#define NN_RCVFD 11
#define NN_DOMAIN 12
#define NN_PROTOCOL 13
#define NN_IPV4ONLY 14
#define NN_SOCKET_NAME 15
#define NN_RCVMAXSIZE 16
#define NN_MAXTTL 17
/* Send/recv options. */
#define NN_DONTWAIT 1
/* Ancillary data. */
#define PROTO_SP 1
#define SP_HDR 1
NN_EXPORT int nn_socket (int domain, int protocol);
NN_EXPORT int nn_close (int s);
NN_EXPORT int nn_setsockopt (int s, int level, int option, const void *optval,
size_t optvallen);
NN_EXPORT int nn_getsockopt (int s, int level, int option, void *optval,
size_t *optvallen);
NN_EXPORT int nn_bind (int s, const char *addr);
NN_EXPORT int nn_connect (int s, const char *addr);
NN_EXPORT int nn_shutdown (int s, int how);
NN_EXPORT int nn_send (int s, const void *buf, size_t len, int flags);
NN_EXPORT int nn_recv (int s, void *buf, size_t len, int flags);
NN_EXPORT int nn_sendmsg (int s, const struct nn_msghdr *msghdr, int flags);
NN_EXPORT int nn_recvmsg (int s, struct nn_msghdr *msghdr, int flags);
/******************************************************************************/
/* Socket mutliplexing support. */
/******************************************************************************/
#define NN_POLLIN 1
#define NN_POLLOUT 2
struct nn_pollfd {
int fd;
short events;
short revents;
};
NN_EXPORT int nn_poll (struct nn_pollfd *fds, int nfds, int timeout);
/******************************************************************************/
/* Built-in support for devices. */
/******************************************************************************/
NN_EXPORT int nn_device (int s1, int s2);
/******************************************************************************/
/* Statistics. */
/******************************************************************************/
/* Transport statistics */
#define NN_STAT_ESTABLISHED_CONNECTIONS 101
#define NN_STAT_ACCEPTED_CONNECTIONS 102
#define NN_STAT_DROPPED_CONNECTIONS 103
#define NN_STAT_BROKEN_CONNECTIONS 104
#define NN_STAT_CONNECT_ERRORS 105
#define NN_STAT_BIND_ERRORS 106
#define NN_STAT_ACCEPT_ERRORS 107
#define NN_STAT_CURRENT_CONNECTIONS 201
#define NN_STAT_INPROGRESS_CONNECTIONS 202
#define NN_STAT_CURRENT_EP_ERRORS 203
/* The socket-internal statistics */
#define NN_STAT_MESSAGES_SENT 301
#define NN_STAT_MESSAGES_RECEIVED 302
#define NN_STAT_BYTES_SENT 303
#define NN_STAT_BYTES_RECEIVED 304
/* Protocol statistics */
#define NN_STAT_CURRENT_SND_PRIORITY 401
NN_EXPORT uint64_t nn_get_statistic (int s, int stat);
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012 Martin Sustrik All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef PAIR_H_INCLUDED
#define PAIR_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#define NN_PROTO_PAIR 1
#define NN_PAIR (NN_PROTO_PAIR * 16 + 0)
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012 Martin Sustrik All rights reserved.
Copyright (c) 2013 GoPivotal, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef PIPELINE_H_INCLUDED
#define PIPELINE_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#define NN_PROTO_PIPELINE 5
#define NN_PUSH (NN_PROTO_PIPELINE * 16 + 0)
#define NN_PULL (NN_PROTO_PIPELINE * 16 + 1)
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012-2013 Martin Sustrik All rights reserved.
Copyright 2016 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef NN_PROTOCOL_INCLUDED
#define NN_PROTOCOL_INCLUDED
#include "utils/msg.h"
#include "utils/list.h"
#include <stddef.h>
#include <stdint.h>
struct nn_ctx;
/******************************************************************************/
/* Pipe class. */
/******************************************************************************/
/* Any combination of following flags can be returned from successful call
to nn_pipe_send or nn_pipe_recv. */
/* This flag means that the pipe can't be used for receiving (when returned
from nn_pipe_recv()) or sending (when returned from nn_pipe_send()).
Protocol implementation should not send/recv messages from the pipe until
the pipe is revived by in()/out() function. */
#define NN_PIPE_RELEASE 1
/* Specifies that received message is already split into header and body.
This flag is used only by inproc transport to avoid merging and re-splitting
the messages passed with a single process. */
#define NN_PIPE_PARSED 2
/* Events generated by the pipe. */
#define NN_PIPE_IN 33987
#define NN_PIPE_OUT 33988
struct nn_pipe;
/* Associates opaque pointer to protocol-specific data with the pipe. */
void nn_pipe_setdata (struct nn_pipe *self, void *data);
/* Retrieves the opaque pointer associated with the pipe. */
void *nn_pipe_getdata (struct nn_pipe *self);
/* Send the message to the pipe. If successful, pipe takes ownership of the
messages. */
int nn_pipe_send (struct nn_pipe *self, struct nn_msg *msg);
/* Receive a message from a pipe. 'msg' should not be initialised prior to
the call. It will be initialised when the call succeeds. */
int nn_pipe_recv (struct nn_pipe *self, struct nn_msg *msg);
/* Get option for pipe. Mostly useful for endpoint-specific options */
void nn_pipe_getopt (struct nn_pipe *self, int level, int option,
void *optval, size_t *optvallen);
/******************************************************************************/
/* Base class for all socket types. */
/******************************************************************************/
struct nn_sockbase;
/* Any combination of these events can be returned from 'events' virtual
function. */
#define NN_SOCKBASE_EVENT_IN 1
#define NN_SOCKBASE_EVENT_OUT 2
/* To be implemented by individual socket types. */
struct nn_sockbase_vfptr {
/* Ask socket to stop. */
void (*stop) (struct nn_sockbase *self);
/* Deallocate the socket. */
void (*destroy) (struct nn_sockbase *self);
/* Management of pipes. 'add' registers a new pipe. The pipe cannot be used
to send to or to be received from at the moment. 'rm' unregisters the
pipe. The pipe should not be used after this call as it may already be
deallocated. 'in' informs the socket that pipe is readable. 'out'
informs it that it is writable. */
int (*add) (struct nn_sockbase *self, struct nn_pipe *pipe);
void (*rm) (struct nn_sockbase *self, struct nn_pipe *pipe);
void (*in) (struct nn_sockbase *self, struct nn_pipe *pipe);
void (*out) (struct nn_sockbase *self, struct nn_pipe *pipe);
/* Return any combination of event flags defined above, thus specifying
whether the socket should be readable, writable, both or none. */
int (*events) (struct nn_sockbase *self);
/* Send a message to the socket. Returns -EAGAIN if it cannot be done at
the moment or zero in case of success. */
int (*send) (struct nn_sockbase *self, struct nn_msg *msg);
/* Receive a message from the socket. Returns -EAGAIN if it cannot be done
at the moment or zero in case of success. */
int (*recv) (struct nn_sockbase *self, struct nn_msg *msg);
/* Set a protocol specific option. */
int (*setopt) (struct nn_sockbase *self, int level, int option,
const void *optval, size_t optvallen);
/* Retrieve a protocol specific option. */
int (*getopt) (struct nn_sockbase *self, int level, int option,
void *optval, size_t *optvallen);
};
struct nn_sockbase {
const struct nn_sockbase_vfptr *vfptr;
struct nn_sock *sock;
};
/* Initialise the socket base class. 'hint' is the opaque value passed to the
nn_transport's 'create' function. */
void nn_sockbase_init (struct nn_sockbase *self,
const struct nn_sockbase_vfptr *vfptr, void *hint);
/* Terminate the socket base class. */
void nn_sockbase_term (struct nn_sockbase *self);
/* Call this function when stopping is done. */
void nn_sockbase_stopped (struct nn_sockbase *self);
/* Returns the AIO context associated with the socket. This function is
useful when socket type implementation needs to create async objects,
such as timers. */
struct nn_ctx *nn_sockbase_getctx (struct nn_sockbase *self);
/* Retrieve a NN_SOL_SOCKET-level option. */
int nn_sockbase_getopt (struct nn_sockbase *self, int option,
void *optval, size_t *optvallen);
/* Add some statistics for socket */
void nn_sockbase_stat_increment (struct nn_sockbase *self, int name,
int increment);
/******************************************************************************/
/* The socktype class. */
/******************************************************************************/
/* This structure defines a class factory for individual socket types. */
/* Specifies that the socket type can be never used to receive messages. */
#define NN_SOCKTYPE_FLAG_NORECV 1
/* Specifies that the socket type can be never used to send messages. */
#define NN_SOCKTYPE_FLAG_NOSEND 2
struct nn_socktype {
/* Domain and protocol IDs as specified in nn_socket() function. */
int domain;
int protocol;
/* Any combination of the flags defined above. */
int flags;
/* Function to create specific socket type. 'sockbase' is the output
parameter to return reference to newly created socket. This function
is called under global lock, so it is not possible that two sockets are
being created in parallel. */
int (*create) (void *hint, struct nn_sockbase **sockbase);
/* Returns 1 if the supplied socket type is a valid peer for this socket,
0 otherwise. Note that the validation is done only within a single
SP protocol. Peers speaking other SP protocols are discarded by the
core and socket is not even asked to validate them. */
int (*ispeer) (int socktype);
};
#endif
/*
Copyright (c) 2012 Martin Sustrik All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef PUBSUB_H_INCLUDED
#define PUBSUB_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#define NN_PROTO_PUBSUB 2
#define NN_PUB (NN_PROTO_PUBSUB * 16 + 0)
#define NN_SUB (NN_PROTO_PUBSUB * 16 + 1)
#define NN_SUB_SUBSCRIBE 1
#define NN_SUB_UNSUBSCRIBE 2
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012 Martin Sustrik All rights reserved.
Copyright 2016 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef REQREP_H_INCLUDED
#define REQREP_H_INCLUDED
#include "nn.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NN_PROTO_REQREP 3
#define NN_REQ (NN_PROTO_REQREP * 16 + 0)
#define NN_REP (NN_PROTO_REQREP * 16 + 1)
#define NN_REQ_RESEND_IVL 1
typedef union nn_req_handle {
int i;
void *ptr;
} nn_req_handle;
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012 Martin Sustrik All rights reserved.
Copyright 2015 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef SURVEY_H_INCLUDED
#define SURVEY_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#define NN_PROTO_SURVEY 6
/* NB: Version 0 used 16 + 0/1. That version lacked backtraces, and so
is wire-incompatible with this version. */
#define NN_SURVEYOR (NN_PROTO_SURVEY * 16 + 2)
#define NN_RESPONDENT (NN_PROTO_SURVEY * 16 + 3)
#define NN_SURVEYOR_DEADLINE 1
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012 Martin Sustrik All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef TCP_H_INCLUDED
#define TCP_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#define NN_TCP -3
#define NN_TCP_NODELAY 1
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012-2014 Martin Sustrik All rights reserved.
Copyright (c) 2013 GoPivotal, Inc. All rights reserved.
Copyright 2016 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef NN_TRANSPORT_INCLUDED
#define NN_TRANSPORT_INCLUDED
#include "nn.h"
#include "aio/fsm.h"
#include "utils/list.h"
#include "utils/msg.h"
#include <stddef.h>
/* This is the API between the nanomsg core and individual transports. */
struct nn_sock;
/******************************************************************************/
/* Container for transport-specific socket options. */
/******************************************************************************/
struct nn_optset;
struct nn_optset_vfptr {
void (*destroy) (struct nn_optset *self);
int (*setopt) (struct nn_optset *self, int option, const void *optval,
size_t optvallen);
int (*getopt) (struct nn_optset *self, int option, void *optval,
size_t *optvallen);
};
struct nn_optset {
const struct nn_optset_vfptr *vfptr;
};
/******************************************************************************/
/* The base class for endpoints. */
/******************************************************************************/
/* The best way to think about endpoints is that endpoint is an object created
by each nn_bind() or nn_connect() call. Each endpoint is associated with
exactly one address string (e.g. "tcp://127.0.0.1:5555"). */
struct nn_ep;
struct nn_ep_ops {
/* Ask the endpoint to stop itself. The endpoint is allowed to linger
to send the pending outbound data. When done, it reports the fact by
invoking nn_ep_stopped() function. */
void (*stop) (void *);
/* Deallocate the endpoint object. It will already have been stopped. */
void (*destroy) (void *);
};
/* Set up an ep for use by a transport. The final opaque argument is passed
as the first argument to the ops entry points. */
void nn_ep_tran_setup (struct nn_ep *, const struct nn_ep_ops *, void *);
/* Notify the user that stopping is done. */
void nn_ep_stopped (struct nn_ep *);
/* Returns the AIO context associated with the endpoint. */
struct nn_ctx *nn_ep_getctx (struct nn_ep *);
/* Returns the address string associated with this endpoint. */
const char *nn_ep_getaddr (struct nn_ep *self);
/* Retrieve value of a socket option. */
void nn_ep_getopt (struct nn_ep *, int level, int option,
void *optval, size_t *optvallen);
/* Returns 1 if the specified socket type is a valid peer for this socket,
or 0 otherwise. */
int nn_ep_ispeer (struct nn_ep *, int socktype);
/* Returns 1 if the ep's are valid peers for each other, 0 otherwise. */
int nn_ep_ispeer_ep (struct nn_ep *, struct nn_ep *);
/* Notifies a monitoring system the error on this endpoint */
void nn_ep_set_error(struct nn_ep*, int errnum);
/* Notifies a monitoring system that error is gone */
void nn_ep_clear_error(struct nn_ep *);
/* Increments statistics counters in the socket structure */
void nn_ep_stat_increment(struct nn_ep *, int name, int increment);
/******************************************************************************/
/* The base class for pipes. */
/******************************************************************************/
/* Pipe represents one "connection", i.e. perfectly ordered uni- or
bi-directional stream of messages. One endpoint can create multiple pipes
(for example, bound TCP socket is an endpoint, individual accepted TCP
connections are represented by pipes. */
struct nn_pipebase;
/* This value is returned by pipe's send and recv functions to signalise that
more sends/recvs are not possible at the moment. From that moment on,
the core will stop invoking the function. To re-establish the message
flow nn_pipebase_received (respectively nn_pipebase_sent) should
be called. */
#define NN_PIPEBASE_RELEASE 1
/* Specifies that received message is already split into header and body.
This flag is used only by inproc transport to avoid merging and re-splitting
the messages passed with a single process. */
#define NN_PIPEBASE_PARSED 2
struct nn_pipebase_vfptr {
/* Send a message to the network. The function can return either error
(negative number) or any combination of the flags defined above. */
int (*send) (struct nn_pipebase *self, struct nn_msg *msg);
/* Receive a message from the network. The function can return either error
(negative number) or any combination of the flags defined above. */
int (*recv) (struct nn_pipebase *self, struct nn_msg *msg);
};
/* Endpoint specific options. Same restrictions as for nn_pipebase apply */
struct nn_ep_options
{
int sndprio;
int rcvprio;
int ipv4only;
};
/* The member of this structure are used internally by the core. Never use
or modify them directly from the transport. */
struct nn_pipebase {
struct nn_fsm fsm;
const struct nn_pipebase_vfptr *vfptr;
uint8_t state;
uint8_t instate;
uint8_t outstate;
struct nn_sock *sock;
void *data;
struct nn_fsm_event in;
struct nn_fsm_event out;
struct nn_ep_options options;
};
/* Initialise the pipe. */
void nn_pipebase_init (struct nn_pipebase *self,
const struct nn_pipebase_vfptr *vfptr, struct nn_ep *ep);
/* Terminate the pipe. */
void nn_pipebase_term (struct nn_pipebase *self);
/* Call this function once the connection is established. */
int nn_pipebase_start (struct nn_pipebase *self);
/* Call this function once the connection is broken. */
void nn_pipebase_stop (struct nn_pipebase *self);
/* Call this function when new message was fully received. */
void nn_pipebase_received (struct nn_pipebase *self);
/* Call this function when current outgoing message was fully sent. */
void nn_pipebase_sent (struct nn_pipebase *self);
/* Retrieve value of a socket option. */
void nn_pipebase_getopt (struct nn_pipebase *self, int level, int option,
void *optval, size_t *optvallen);
/* Returns 1 is the specified socket type is a valid peer for this socket,
or 0 otherwise. */
int nn_pipebase_ispeer (struct nn_pipebase *self, int socktype);
/******************************************************************************/
/* The transport class. */
/******************************************************************************/
struct nn_transport {
/* Name of the transport as it appears in the connection strings ("tcp",
"ipc", "inproc" etc. */
const char *name;
/* ID of the transport. */
int id;
/* Following methods are guarded by a global critical section. Two of these
function will never be invoked in parallel. The first is called when
the library is initialised, the second one when it is terminated, i.e.
when there are no more open sockets. Either of them can be set to NULL
if no specific initialisation/termination is needed. */
void (*init) (void);
void (*term) (void);
/* Each of these functions creates an endpoint and sets up the newly
established endpoint in 'ep' parameter using nn_ep_tran_setup ().
These functions are guarded by a socket-wide critical section.
Two of these function will never be invoked in parallel on the same
socket. */
int (*bind) (struct nn_ep *);
int (*connect) (struct nn_ep *);
/* Create an object to hold transport-specific socket options.
Set this member to NULL in case there are no transport-specific
socket options available. */
struct nn_optset *(*optset) (void);
};
#endif
/*
Copyright (c) 2012 250bpm s.r.o. All rights reserved.
Copyright (c) 2014 Wirebird Labs LLC. All rights reserved.
Copyright 2015 Garrett D'Amore <garrett@damore.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef WS_H_INCLUDED
#define WS_H_INCLUDED
#include "nn.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NN_WS -4
/* NN_WS level socket/cmsg options. Note that only NN_WSMG_TYPE_TEXT and
NN_WS_MSG_TYPE_BINARY messages are supported fully by this implementation.
Attempting to set other message types is undefined. */
#define NN_WS_MSG_TYPE 1
/* WebSocket opcode constants as per RFC 6455 5.2 */
#define NN_WS_MSG_TYPE_TEXT 0x01
#define NN_WS_MSG_TYPE_BINARY 0x02
#ifdef __cplusplus
}
#endif
#endif
LIBA_TARGET := libnanomsg.a LIBA_TARGET := libapi_nanomsg.a
\ No newline at end of file
LIBA_TARGET := libiot_mqtt_fnc.a
#SRCS_example := MQTTAsync_publish.c
$(call Append_Conditional, TARGET, MQTTAsync_publish)
#CFLAGS += -I../../work/ssl/include -lrt
#LDFLAGS += -L../../work/ssl/lib
#DEPENDS += common/mqtt
LDFLAGS += -liot_mqtt -ldl
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTAsync.h"
static const char* OPT_SEND = "MQTTAsync_sendMessage";
static const char* OPT_SUB = "MQTTAsync_subscribe";
static const char* OPT_UNSUB = "MQTTAsync_unsubscribe";
static void onOptSuccess(void* context, MQTTAsync_successData* response)
{
if(strcmp((char *)context,OPT_SEND)==0)
{
printf("MQTTAsync_sendMessage success,return token:%d,msg length:%d \n",
response->token,response->alt.pub.message.payloadlen);
}
else if(strcmp((char *)context,OPT_SUB)==0)
{
printf("MQTTAsync_subscribe success,return token:%d \n",response->token);
}
else if(strcmp((char *)context,OPT_UNSUB)==0)
{
printf("MQTTAsync_unsubscribe success,return token:%d \n",response->token);
}
}
static void onOptFail(void* context, MQTTAsync_failureData* response)
{
if(strcmp((char *)context,OPT_SEND)==0)
{
printf("MQTTAsync_sendMessage fail,token:%d,code:%d,msg:%s \n",
response->token,response->code,response->message);
}
else if(strcmp((char *)context,OPT_SUB)==0)
{
printf("MQTTAsync_subscribe fail,return token:%d \n",response->token);
}
else if(strcmp((char *)context,OPT_UNSUB)==0)
{
printf("MQTTAsync_unsubscribe fail,return token:%d \n",response->token);
}
}
int KK_MQTT_SubTopic(MQTTAsync handle,char *topicName,int qos,int waitTimeout)
{
printf("to subtopic:%s \n",topicName);
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
int rc;
opts.onSuccess = onOptSuccess;
opts.onFailure = onOptFail;
opts.context = (void*)OPT_SUB;
if ((rc = MQTTAsync_subscribe(handle,topicName, qos, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start subscribe, return code:%d.\n", rc);
return -1;
}
return 0;
}
int KK_MQTT_SendMsg(MQTTAsync handle,char *topicName,const char *payload,int qos)
{
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
int rc;
opts.onSuccess = onOptSuccess;
opts.onFailure = onOptFail;
opts.context = (void*)OPT_SEND;
pubmsg.payload = (void*)payload;
pubmsg.payloadlen = strlen(payload);
pubmsg.qos = qos;
pubmsg.retained = 0;
printf("mqtt send payload len:%d,qos:%d.\n",pubmsg.payloadlen,qos);
if ((rc = MQTTAsync_sendMessage(handle, topicName, &pubmsg, &opts)) != MQTTASYNC_SUCCESS){
printf("Failed to start sendMessage, return code:%d.\n", rc);
return -1;
}
return rc;
}
int KK_MQTT_RecvMsg(MQTTAsync handle,const char *topicName,const char *payload)
{
if(topicName == NULL)
{
return -1;
}
return 0;
}
int KK_MQTT_UnsubTopic(MQTTAsync handle,const char *topicName)
{
printf("to unsubtopic:%s \n",topicName);
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
int rc;
opts.onSuccess = onOptSuccess;
opts.onFailure = onOptFail;
opts.context = (void*)OPT_UNSUB;
if ((rc = MQTTAsync_unsubscribe(handle,topicName,&opts)) != MQTTASYNC_SUCCESS){
printf("Failed to start unubscribe, return code:%d.\n", rc);
return -1;
}
return rc;
}
...@@ -10,12 +10,14 @@ COMP_LIB := libiot_sdk.a ...@@ -10,12 +10,14 @@ COMP_LIB := libiot_sdk.a
COMP_LIB_COMPONENTS := \ COMP_LIB_COMPONENTS := \
src/test \ src/test \
SUBDIRS += src/kcloud
SUBDIRS += common/mqtt SUBDIRS += common/mqtt
#SUBDIRS += common/nanomsg SUBDIRS += common/json
SUBDIRS += example/mqtt SUBDIRS += common/api
#SUBDIRS += example/mqtt
SUBDIRS += example/nanomsg SUBDIRS += example/nanomsg
SUBDIRS += example/ev SUBDIRS += example/ev
SUBDIRS += example/ev_nanomsg #SUBDIRS += example/ev_nanomsg
$(call Append_Conditional, SUBDIRS) $(call Append_Conditional, SUBDIRS)
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#define ADDRESS "tcp://106.13.117.117:1883" #define ADDRESS "tcp://106.13.117.117:1883"
#define CLIENTID "1234" #define CLIENTID "1234"
#define TOPIC "cwctest" #define TOPIC "cwctest"
#define PAYLOAD "Hello cwc World!" #define PAYLOAD "Hello cwc World!"
#define QOS 2 #define QOS 2
#define TIMEOUT 10000L #define TIMEOUT 10000L
......
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pair.h"
#include "nn.h"
#include "ev.h"
#include "mqtt_api.h"
typedef struct
{
int n;
int s;
}kk_nanomsg_t;
typedef struct
{
kk_nanomsg_t handle;
}kk_nanomsg_handle_t;
static kk_nanomsg_handle_t s_msgHdl;
#define NANOMSG_ADDR "ipc://b2a_loop"
int KK_Sendto_DevData(const char *data, int len)
{
kk_nanomsg_handle_t *msgHdl = &s_msgHdl;
if(len <= 0||data == NULL)
{
return -1;
}
int length = len + 1;
unsigned char *udata = nn_allocmsg(length, 0);
if (NULL != udata)
{
memcpy(udata, data, length);
nn_send(msgHdl->handle.n, &udata, NN_MSG, NN_DONTWAIT);
INFO_PRINT("KK_data_send:%s \r\n\r\n", udata);
}
}
int KK_Sendto_CloudData(const char *data, int len)
{
if(len <= 0||data == NULL)
{
return -1;
}
return KK_MQTT_SendMsg(TOPIC,data,len);
}
static void kk_data_cb (struct ev_loop *loop ,struct ev_io *w, int revents)
{
unsigned char *dat = NULL;
void *user_data = ev_userdata(loop);
kk_nanomsg_handle_t *msgHdl = (kk_nanomsg_handle_t *)user_data;
unsigned int bytes = nn_recv(msgHdl->handle.n, &dat, NN_MSG, NN_DONTWAIT);
if (bytes <= 0)
{
return;
}
KK_Sendto_CloudData(dat,bytes);
INFO_PRINT("kk_data_cb:%s \r\n", (char *)dat);
nn_freemsg(dat);
}
static int kk_nanomsg_init(kk_nanomsg_handle_t *nanoMsgHdl)
{
if(nanoMsgHdl == NULL)
{
return -1;
}
nanoMsgHdl->handle.n = nn_socket(AF_SP, NN_PAIR);
if (nanoMsgHdl->handle.n < 0)
{
return -1;
}
if (nn_connect(nanoMsgHdl->handle.n,NANOMSG_ADDR) < 0)
{
return -1;
}
size_t size = sizeof(size_t);
if (nn_getsockopt(nanoMsgHdl->handle.n, NN_SOL_SOCKET, NN_RCVFD, (char *)&nanoMsgHdl->handle.s, &size) < 0)
{
return -1;
}
return 0;
}
struct ev_loop* kk_loop_init(kk_nanomsg_handle_t *nanoMsgHdl)
{
static struct ev_io watcher_b;
struct ev_loop *loop = ev_loop_new(EVBACKEND_EPOLL);
if (NULL == loop)
{
ERROR_PRINT("create loop failed\r\n");
return NULL;
}
ev_io_init (&watcher_b, kk_data_cb, nanoMsgHdl->handle.s, EV_READ);
ev_io_start (loop, &watcher_b);
return loop;
}
void KK_Data_Handle(void)
{
int rc = 0;
rc = kk_nanomsg_init(&s_msgHdl);
struct ev_loop* kloop = kk_loop_init(&s_msgHdl);
if (NULL == kloop)
{
ERROR_PRINT("Bloop init failed\r\n");
return ;
}
ev_set_userdata(kloop, &s_msgHdl);
ev_run (kloop, 0);
return ;
}
\ No newline at end of file
#ifndef _LOGDEF_H_
#define _LOGDEF_H_
enum
{
INFO,
WARNING,
ERROR,
ALL
};
#define DEBUG_LEVEL ERROR
#define INFO_PRINT(info,...) \
do{ \
if(DEBUG_LEVEL>=INFO){ \
printf("Info %s,%s,%d:"info"",__FILE__,__FUNCTION__,__LINE__,##__VA_ARGS__);}\
}while(0)
#define WARNING_PRINT(warning,...) \
do{ \
if(DEBUG_LEVEL>=WARNING){ \
printf("warning %s,%s,%d:"warning"",__FILE__,__FUNCTION__,__LINE__,##__VA_ARGS__);}\
}while(0)
#define ERROR_PRINT(error,...) \
do{ \
if(DEBUG_LEVEL>=ERROR){ \
printf("error %s,%s,%d:"error"",__FILE__,__FUNCTION__,__LINE__,##__VA_ARGS__);}\
}while(0)
#endif
/*******************************************************************************
* Copyright (c) 2012, 2020 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "MQTTAsync.h"
#include "mqtt_api.h"
#define THREAD_NUM 10
static int mqtt_start(void)
{
int count = 0;
MQTTAsync mqttClient;
int rc = 0;
mqttClient = KK_MQTT_Connect();
if(mqttClient == NULL)
{
WARNING_PRINT("KK_MQTT_Connect FAIL!!!\n");
}
else
{
INFO_PRINT("Waiting for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
PAYLOAD, TOPIC, CLIENTID);
}
while(1)
{
usleep(100000L);
count++;
if(count>50)
{
count = 0;
INFO_PRINT("i am send now\n");
KK_MQTT_SendMsg(TOPIC,"hello my world",2);
}
}
INFO_PRINT("MQTTAsync_destroy\n");
MQTTAsync_destroy(&mqttClient);
return rc;
}
int main(int argc, char* argv[])
{
int thread_count = 0;
pthread_t thread_num[THREAD_NUM];
memset(thread_num,0,sizeof(thread_num));
int rc = 0;
if(pthread_create(&thread_num[thread_count++],NULL,(void*)&KK_Data_Handle,NULL)!=0)
{
printf("pthread_create %d error!!!",(int)thread_num[thread_count-1]);
}
rc = mqtt_start();
return rc;
}
/*******************************************************************************
* Copyright (c) 2012, 2020 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
*******************************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "MQTTAsync.h" #include "mqtt_api.h"
#include "mqtt_config.h"
static const char* OPT_SEND = "MQTTAsync_sendMessage";
static const char* OPT_SUB = "MQTTAsync_subscribe";
static const char* OPT_UNSUB = "MQTTAsync_unsubscribe";
static MQTTAsync s_Client; static MQTTAsync s_Client;
int finished = 0; static int s_mqttStop = 0;
void connlost(void *context, char *cause) /*Connect lost callback*/
static void connlost(void *context, char *cause)
{ {
if(context == NULL || cause == NULL)
{
ERROR_PRINT("PARAM ERROR\n");
s_mqttStop = 1;
return;
}
MQTTAsync client = (MQTTAsync)context; MQTTAsync client = (MQTTAsync)context;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
int rc; int rc;
printf("\nConnection lost\n"); INFO_PRINT("\nConnection lost\n");
printf(" cause: %s\n", cause); INFO_PRINT("cause: %s\n", cause);
printf("Reconnecting\n");
conn_opts.keepAliveInterval = 20; conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1; conn_opts.cleansession = 1;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{ {
printf("Failed to start connect, return code %d\n", rc); ERROR_PRINT("Failed to start connect, return code %d\n", rc);
finished = 1; s_mqttStop = 1;
} }
} }
void onDisconnectFailure(void* context, MQTTAsync_failureData* response) void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
{ {
printf("Disconnect failed\n"); WARNING_PRINT("Disconnect failed\n");
finished = 1; s_mqttStop = 1;
} }
void onDisconnect(void* context, MQTTAsync_successData* response) void onDisconnect(void* context, MQTTAsync_successData* response)
{ {
printf("Successful disconnection\n"); WARNING_PRINT("Successful disconnection\n");
finished = 1; s_mqttStop = 1;
} }
void onSendFailure(void* context, MQTTAsync_failureData* response) void onSendFailure(void* context, MQTTAsync_failureData* response)
{ {
if(context == NULL || response == NULL)
{
ERROR_PRINT("PARAM ERROR\n");
return;
}
MQTTAsync client = (MQTTAsync)context; MQTTAsync client = (MQTTAsync)context;
MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer; MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
int rc; int rc;
printf("Message send failed token %d error code %d\n", response->token, response->code); WARNING_PRINT("Message send failed token %d error code %d\n", response->token, response->code);
opts.onSuccess = onDisconnect; opts.onSuccess = onDisconnect;
opts.onFailure = onDisconnectFailure; opts.onFailure = onDisconnectFailure;
opts.context = client; opts.context = client;
if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS) if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
{ {
printf("Failed to start disconnect, return code %d\n", rc); ERROR_PRINT("Failed to start disconnect, return code %d\n", rc);
} }
} }
void onSend(void* context, MQTTAsync_successData* response) void onSend(void* context, MQTTAsync_successData* response)
{ {
MQTTAsync client = (MQTTAsync)context; if(response == NULL)
MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer; {
int rc; ERROR_PRINT("PARAM ERROR\n");
return;
printf("Message with token value %d delivery confirmed\n", response->token); }
INFO_PRINT("Message with token value %d delivery confirmed\n", response->token);
} }
void onConnectFailure(void* context, MQTTAsync_failureData* response) void onConnectFailure(void* context, MQTTAsync_failureData* response)
{ {
printf("Connect failed, rc %d\n", response ? response->code : 0); s_mqttStop = 1;
finished = 1; if(response == NULL)
{
ERROR_PRINT("PARAM ERROR\n");
return;
}
WARNING_PRINT("Connect failed, rc %d\n", response ? response->code : 0);
} }
void onConnect(void* context, MQTTAsync_successData* response) void onConnect(void* context, MQTTAsync_successData* response)
{ {
MQTTAsync client = (MQTTAsync)context; INFO_PRINT("Successful connection\n");
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
int rc;
printf("Successful connection\n");
opts.onSuccess = onSend;
opts.onFailure = onSendFailure;
opts.context = client;
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = (int)strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start sendMessage, return code %d\n", rc);
}
} }
int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message) int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message)
{ {
/* not expecting any messages */ /* not expecting any messages */
printf("onMessageArrived topic:%s,message length:%d.\n",topicName,message->payloadlen); INFO_PRINT("onMessageArrived topic:%s,message length:%d.\n",topicName,message->payloadlen);
printf("payload:%s,\n",message->payload); INFO_PRINT("payload:%s,\n",message->payload);
KK_MQTT_RecvMsg((MQTTAsync)context,topicName,message->payload); KK_MQTT_RecvMsg((MQTTAsync)context,topicName,message->payload);
MQTTAsync_freeMessage(&message); MQTTAsync_freeMessage(&message);
MQTTAsync_free(topicName); MQTTAsync_free(topicName);
...@@ -126,18 +118,56 @@ static void mqttTraceCallback(enum MQTTASYNC_TRACE_LEVELS level, char *message) ...@@ -126,18 +118,56 @@ static void mqttTraceCallback(enum MQTTASYNC_TRACE_LEVELS level, char *message)
} }
static void onDeliveryComplete(void* context, MQTTAsync_token token) static void onDeliveryComplete(void* context, MQTTAsync_token token)
{ {
printf("onDeliveryComplete,token:%d \n",token); INFO_PRINT("onDeliveryComplete,token:%d \n",token);
} }
static void onConnectBuild(void *context, char *cause) static void onConnectBuild(void *context, char *cause)
{ {
printf("onConnectBuild:%s \n",cause); int rc = 0;
KK_MQTT_SubTopic(s_Client,TOPIC,0,2000); INFO_PRINT("onConnectBuild:%s \n",cause);
rc = KK_MQTT_SubTopic(s_Client,TOPIC,QOS,2000);
if(rc != 0)
{
ERROR_PRINT("KK_MQTT_SubTopic ERROR rc = %d\n",rc);
}
} }
static void onDisConnected(void *context, MQTTProperties* properties,enum MQTTReasonCodes reasonCode) static void onDisConnected(void *context, MQTTProperties* properties,enum MQTTReasonCodes reasonCode)
{ {
printf("onDisConnected,maybe kicked by broker.\n"); INFO_PRINT("onDisConnected,maybe kicked by broker.\n");
} }
static void onOptSuccess(void* context, MQTTAsync_successData* response)
{
if(strcmp((char *)context,OPT_SEND)==0)
{
INFO_PRINT("MQTTAsync_sendMessage success,return token:%d,msg length:%d \n",
response->token,response->alt.pub.message.payloadlen);
}
else if(strcmp((char *)context,OPT_SUB)==0)
{
INFO_PRINT("MQTTAsync_subscribe success,return token:%d \n",response->token);
}
else if(strcmp((char *)context,OPT_UNSUB)==0)
{
INFO_PRINT("MQTTAsync_unsubscribe success,return token:%d \n",response->token);
}
}
static void onOptFail(void* context, MQTTAsync_failureData* response)
{
if(strcmp((char *)context,OPT_SEND)==0)
{
WARNING_PRINT("MQTTAsync_sendMessage fail,token:%d,code:%d,msg:%s \n",
response->token,response->code,response->message);
}
else if(strcmp((char *)context,OPT_SUB)==0)
{
WARNING_PRINT("MQTTAsync_subscribe fail,return token:%d \n",response->token);
}
else if(strcmp((char *)context,OPT_UNSUB)==0)
{
WARNING_PRINT("MQTTAsync_unsubscribe fail,return token:%d \n",response->token);
}
}
static void mqtt_set_callbacks(void) static void mqtt_set_callbacks(void)
{ {
MQTTAsync_setConnectionLostCallback(s_Client,NULL,connlost); MQTTAsync_setConnectionLostCallback(s_Client,NULL,connlost);
...@@ -147,22 +177,29 @@ static void mqtt_set_callbacks(void) ...@@ -147,22 +177,29 @@ static void mqtt_set_callbacks(void)
MQTTAsync_setDisconnected(s_Client,NULL,onDisConnected); MQTTAsync_setDisconnected(s_Client,NULL,onDisConnected);
} }
static int mqtt_start(void) void KK_Get_MqttClient(MQTTAsync *pClient)
{
if(pClient != NULL)
{
*pClient = s_Client;
}
}
MQTTAsync KK_MQTT_Connect(void)
{ {
int count = 0;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
int rc = 0; int rc = 0;
MQTTAsync_createOptions opts = MQTTAsync_createOptions_initializer; MQTTAsync_createOptions opts = MQTTAsync_createOptions_initializer;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
MQTTAsync_setTraceCallback(mqttTraceCallback); MQTTAsync_setTraceCallback(mqttTraceCallback);
opts.MQTTVersion = MQTTVERSION_3_1_1;
if ((rc = MQTTAsync_createWithOptions(&s_Client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL,&opts)) != MQTTASYNC_SUCCESS) if ((rc = MQTTAsync_createWithOptions(&s_Client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL,&opts)) != MQTTASYNC_SUCCESS)
{ {
printf("Failed to create client object, return code %d\n", rc); ERROR_PRINT("Failed to create client object, return code %d\n", rc);
return -1; return NULL;
} }
/*Set the mqtt callback*/
mqtt_set_callbacks(); mqtt_set_callbacks();
opts.MQTTVersion = MQTTVERSION_3_1_1;
conn_opts.keepAliveInterval = 60; conn_opts.keepAliveInterval = 60;
conn_opts.connectTimeout = CONNECT_TIMEOUT; conn_opts.connectTimeout = CONNECT_TIMEOUT;
conn_opts.automaticReconnect = AUTO_CONN; conn_opts.automaticReconnect = AUTO_CONN;
...@@ -170,44 +207,90 @@ static int mqtt_start(void) ...@@ -170,44 +207,90 @@ static int mqtt_start(void)
conn_opts.maxRetryInterval = 32; conn_opts.maxRetryInterval = 32;
conn_opts.username = USRNAME; conn_opts.username = USRNAME;
conn_opts.password = PASSWORD; conn_opts.password = PASSWORD;
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1; conn_opts.cleansession = 1;
conn_opts.onSuccess = onConnect; conn_opts.onSuccess = onConnect;
conn_opts.onFailure = onConnectFailure; conn_opts.onFailure = onConnectFailure;
conn_opts.context = s_Client; conn_opts.context = s_Client;
if ((rc = MQTTAsync_connect(s_Client, &conn_opts)) != MQTTASYNC_SUCCESS) if ((rc = MQTTAsync_connect(s_Client, &conn_opts)) != MQTTASYNC_SUCCESS)
{ {
printf("Failed to start connect, return code %d\n", rc); ERROR_PRINT("Failed to start connect, return code %d\n", rc);
return -1; return NULL;
} }
printf("Waiting for publication of %s\n" return s_Client;
"on topic %s for client with ClientID: %s\n", }
PAYLOAD, TOPIC, CLIENTID);
while (!finished) int KK_MQTT_SubTopic(MQTTAsync handle,char *topicName,int qos,int waitTimeout)
{ {
usleep(100000L); INFO_PRINT("to subtopic:%s \n",topicName);
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
int rc;
count++; opts.onSuccess = onOptSuccess;
if(count>50) opts.onFailure = onOptFail;
opts.context = (void*)OPT_SUB;
if ((rc = MQTTAsync_subscribe(handle,topicName, qos, &opts)) != MQTTASYNC_SUCCESS)
{ {
count = 0; ERROR_PRINT("Failed to start subscribe, return code:%d.\n", rc);
printf("i am alive now\n"); return -1;
KK_MQTT_SendMsg(s_Client,TOPIC,"hello my world",2);
} }
return 0;
}
int KK_MQTT_SendMsg(char *topicName,const char *payload,int qos)
{
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
int rc;
opts.onSuccess = onOptSuccess;
opts.onFailure = onOptFail;
opts.context = (void*)OPT_SEND;
pubmsg.payload = (void*)payload;
pubmsg.payloadlen = strlen(payload);
pubmsg.qos = qos;
pubmsg.retained = 0;
INFO_PRINT("mqtt send payload len:%d,qos:%d.\n",pubmsg.payloadlen,qos);
if ((rc = MQTTAsync_sendMessage(s_Client, topicName, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
{
ERROR_PRINT("Failed to start sendMessage, return code:%d.\n", rc);
return -1;
} }
printf("MQTTAsync_destroy\n");
MQTTAsync_destroy(&s_Client);
return rc; return rc;
}
int KK_MQTT_RecvMsg(MQTTAsync handle,const char *topicName,const char *payload)
{
if(topicName == NULL || payload ==NULL)
{
ERROR_PRINT("PARAM ERROR\n");
return -1;
}
KK_Sendto_DevData(payload,strlen(payload));
return 0;
} }
int KK_MQTT_UnsubTopic(MQTTAsync handle,const char *topicName)
{
INFO_PRINT("to unsubtopic:%s \n",topicName);
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
int rc;
int main(int argc, char* argv[]) opts.onSuccess = onOptSuccess;
{ opts.onFailure = onOptFail;
int rc = 0; opts.context = (void*)OPT_UNSUB;
rc = mqtt_start();
if ((rc = MQTTAsync_unsubscribe(handle,topicName,&opts)) != MQTTASYNC_SUCCESS)
{
ERROR_PRINT("Failed to start unubscribe, return code:%d.\n", rc);
return -1;
}
return rc; return rc;
} }
#ifndef _MQTT_API_H_
#define _MQTT_API_H_
#include "MQTTAsync.h"
#include "kcloud_log.h"
#include "kcloud_config.h"
extern void KK_Data_Handle(void);
extern int KK_MQTT_SubTopic(MQTTAsync handle,char *topicName,int qos,int waitTimeout);
extern int KK_MQTT_SendMsg(char *topicName,const char *payload,int qos);
extern int KK_MQTT_RecvMsg(MQTTAsync handle,const char *topicName,const char *payload);
extern int KK_MQTT_UnsubTopic(MQTTAsync handle,const char *topicName);
extern MQTTAsync KK_MQTT_Connect(void);
#endif
LIBA_TARGET := libiot_test.a LIBA_TARGET := libiot_test.a
/******************************************************************************* #include<stdio.h>
* Copyright (c) 2012, 2020 IBM Corp. int test(void)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
*******************************************************************************/
#include <stdio.h>
int test()
{ {
return 0; return 1;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment