mirror of
https://github.com/JamesonHuang/OpenWrt_Luci_Lua.git
synced 2024-11-23 22:00:11 +00:00
rm sth sdk
This commit is contained in:
parent
1102dc1956
commit
a955789014
Binary file not shown.
@ -1,5 +0,0 @@
|
|||||||
libprotobuf-c0-dev
|
|
||||||
libsnappy-dev
|
|
||||||
protobuf-c-compiler
|
|
||||||
libtcmalloc-minimal4
|
|
||||||
libtcmalloc-minimal4-dbg
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,28 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include "nebula_sdk.h"
|
|
||||||
|
|
||||||
void msg_cb(const char* data, int len)
|
|
||||||
{
|
|
||||||
printf("karldbg %s %s\n", __func__, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
|
||||||
{
|
|
||||||
|
|
||||||
const char* app_name[] = {"com.meizu.router",};
|
|
||||||
NebulaMsgCallback cb = msg_cb;
|
|
||||||
|
|
||||||
NebulaInit("R10WZOANC5400EE", "https://p.meizu.com", "/tmp");
|
|
||||||
|
|
||||||
NebulaSubScribe(1, app_name);
|
|
||||||
|
|
||||||
NebulaRegister(eNebulaMsg_Push, cb);
|
|
||||||
|
|
||||||
NebulaStart();
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
[2015-05-07 15:02:59.365817]|WARN|nebula_sdk.c:55:(NebulaInit):load archive file failed...
|
|
||||||
[2015-05-07 15:02:59.365960]|INFO|nebula_sdk.c:95:(__NebulaStart):set status to eStatus_Redirect
|
|
||||||
[2015-05-07 15:02:59.387127]|INFO|redirect.c:119:(NebulaRedirect):HTTPS POST. url=https://p.meizu.com/push/redirect, params=uid=R10WZOANC5400EE&nonce=y9757acx1eve7nmoigsz8fxqqqvjj&ts=1430982179&sign=915a7e6c46cb4894f43e0626835ca183
|
|
||||||
[2015-05-07 15:03:00.110994]|INFO|redirect.c:126:(NebulaRedirect):curl_easy_perform success. response={"code":200,"hostlist":[{"ip":"121.14.58.42","port":8080},{"ip":"122.13.148.217","port":8080}],"md5_daa":{"rule":"hhs","salt":"fdsafdsafewqfewq"}}
|
|
||||||
|
|
||||||
[2015-05-07 15:03:00.111336]|INFO|nebula_sdk.c:100:(__NebulaStart):set status to eStatus_LoopTest
|
|
||||||
[2015-05-07 15:03:00.131505]|INFO|nebula_sdk.c:108:(__NebulaStart):set status to eStatus_Connect
|
|
||||||
[2015-05-07 15:03:00.151805]|INFO|connect.c:159:(NebulaConnect):connect to server:121.14.58.42:8080
|
|
||||||
[2015-05-07 15:03:00.151889]|INFO|nebula_sdk.c:113:(__NebulaStart):set status to eStatus_Connecting
|
|
||||||
[2015-05-07 15:03:00.157523]|INFO|connect.c:31:(__on_connect):connect success, server_addr:121.14.58.42:8080
|
|
||||||
[2015-05-07 15:03:00.157623]|INFO|connect.c:34:(__on_connect):set status to eStatus_Auth1
|
|
||||||
[2015-05-07 15:03:00.157811]|DEBUG|net.c:143:(NebulaConnSend):NEBULA TX REQ AUTH|62
|
|
||||||
[2015-05-07 15:03:00.157851]|INFO|nebula_sdk.c:125:(__NebulaStart):set status to eStatus_Auth1_Waiting
|
|
||||||
[2015-05-07 15:03:00.168268]|DEBUG|connect.c:46:(__handle_message):NEBULA RX RSP AUTH|112
|
|
||||||
[2015-05-07 15:03:00.180330]|DEBUG|net.c:143:(NebulaConnSend):NEBULA TX REQ AUTH|140
|
|
||||||
[2015-05-07 15:03:00.180446]|INFO|auth.c:107:(NebulaOnAuth):set status to eStatus_Auth2
|
|
||||||
[2015-05-07 15:03:00.187501]|DEBUG|connect.c:46:(__handle_message):NEBULA RX RSP AUTH|47
|
|
||||||
[2015-05-07 15:03:00.187558]|INFO|auth.c:44:(NebulaOnAuth):set status to eStatus_Sub
|
|
||||||
[2015-05-07 15:03:00.187600]|DEBUG|net.c:143:(NebulaConnSend):NEBULA TX REQ SUB|46
|
|
||||||
[2015-05-07 15:03:00.196984]|DEBUG|connect.c:46:(__handle_message):NEBULA RX RSP SUB|96
|
|
||||||
[2015-05-07 15:03:00.197133]|INFO|subscribe.c:45:(NebulaOnSubSuccess):sub com.meizu.router success.
|
|
||||||
[2015-05-07 15:03:00.197194]|INFO|nebula_sdk.c:139:(__NebulaStart):set status to eStatus_Estab
|
|
||||||
[2015-05-07 15:03:00.337788]|DEBUG|net.c:143:(NebulaConnSend):NEBULA TX REQ PING|0
|
|
||||||
[2015-05-07 15:03:00.352052]|DEBUG|connect.c:46:(__handle_message):NEBULA RX RSP PING|0
|
|
||||||
[2015-05-07 15:03:00.352100]|DEBUG|connect.c:49:(__handle_message):pong.
|
|
@ -1,56 +0,0 @@
|
|||||||
#ifndef NEBULA_SDK_H
|
|
||||||
#define NEBULA_SDK_H
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
eNebulaMsg_Push, /// 推送 (路由器只需关心这一类消息)
|
|
||||||
eNebulaMsg_Presence, /// Presence
|
|
||||||
eNebulaMsg_Sms, /// 网络短信
|
|
||||||
eNebulaMsg_Mms, /// 网络彩信
|
|
||||||
eNebulaMsg_Max,
|
|
||||||
} NebulaMsgType;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** 初始化网络连接
|
|
||||||
* @device_tag: 硬件信息 (手机端为IMEI)
|
|
||||||
* @verify_pwd: 鉴权密码 (手机端为SN)
|
|
||||||
* @host: 服务端域名, 例如: https://p.meizu.com (结尾不要带"/", 前面要加上https)
|
|
||||||
* @file: 用于读取/存储持久化数据的文件名, 要求目录存在, 且有创建文件权限。
|
|
||||||
* @return: 如果文件打开成功, 返回0; 否则返回-1, 文件打开失败原因记录在错误码errno中.
|
|
||||||
* @只能调用一次, 重复调用无效并返回-1.
|
|
||||||
*/
|
|
||||||
int NebulaInit(const char* device_tag, const char* host, const char* file);
|
|
||||||
|
|
||||||
/** 设置订阅列表
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void NebulaSubScribe(int count, const char** app_name);
|
|
||||||
|
|
||||||
/** 消息处理回调函数
|
|
||||||
* @app: App名
|
|
||||||
* @msg: 消息内容
|
|
||||||
*/
|
|
||||||
typedef void (*NebulaMsgCallback)(const char* app, const char* msg);
|
|
||||||
|
|
||||||
/** 注册消息处理回调函数
|
|
||||||
* @type: 消息类型
|
|
||||||
* @cb: 回调函数
|
|
||||||
* @return: 旧的回调函数
|
|
||||||
* @一次只能注册一个回调函数, 重复注册会覆盖.
|
|
||||||
*/
|
|
||||||
NebulaMsgCallback NebulaRegister(NebulaMsgType type, NebulaMsgCallback cb);
|
|
||||||
|
|
||||||
/** 启动
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int NebulaStart();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //NEBULA_SDK_H
|
|
||||||
|
|
Binary file not shown.
@ -1,31 +0,0 @@
|
|||||||
CC=gcc
|
|
||||||
CFLAGS=-g -fPIC -Wall -Werror
|
|
||||||
INCLUDES=-Iproto -Icrypto
|
|
||||||
LINK=-lpthread -lcurl -lssl -lcrypto
|
|
||||||
LINK+=-Lproto -lnebula_proto
|
|
||||||
LINK+=-Lcrypto
|
|
||||||
LINK+=-Llibs -ljson-c -lsnappy -lprotobuf-c -luuid -lcrypto_framwork -L/usr/lib
|
|
||||||
LINK+=-ltcmalloc_minimal
|
|
||||||
TARGET=libnebula_sdk.so
|
|
||||||
OBJS=$(patsubst %.c,%.o,$(wildcard *.c))
|
|
||||||
|
|
||||||
all:$(TARGET)
|
|
||||||
|
|
||||||
$(TARGET):$(OBJS)
|
|
||||||
cd proto && make
|
|
||||||
@echo LD $(TARGET)
|
|
||||||
@$(CC) $(CFLAGS) $(OBJS) -o $(TARGET) -shared $(LINK)
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(CC) $(CFLAGS) -c $< -o $@ $(INCLUDES)
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm $(TARGET) $(OBJS) -rf
|
|
||||||
cd proto && make clean
|
|
||||||
|
|
||||||
install:
|
|
||||||
install $(TARGET) /usr/lib
|
|
||||||
mkdir -p /usr/include/nebula_sdk
|
|
||||||
install nebula_sdk.h /usr/include/nebula_sdk
|
|
@ -1,15 +0,0 @@
|
|||||||
Interface:
|
|
||||||
|
|
||||||
Sample:
|
|
||||||
|
|
||||||
Depend dynamic libraries:
|
|
||||||
libcurl.so
|
|
||||||
libprotobuf-c.so
|
|
||||||
libssl.so
|
|
||||||
libcrypto.so
|
|
||||||
libtcmalloc_minimal.so
|
|
||||||
|
|
||||||
Build:
|
|
||||||
Run `make` command in this directory.
|
|
||||||
|
|
||||||
|
|
@ -1,198 +0,0 @@
|
|||||||
#include "archive.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include <sys/file.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "timer.h"
|
|
||||||
|
|
||||||
extern dict* g_seq_dict;
|
|
||||||
extern char* g_storage_file;
|
|
||||||
Archive g_archive = {0, NULL, &g_seq_dict};
|
|
||||||
|
|
||||||
int NebulaIsSubscribed(const char* appname)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < g_archive.n_sub_apps; ++i) {
|
|
||||||
if (strcmp(appname, g_archive.sub_apps[i]) == 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaAddSubApp(const char* appname)
|
|
||||||
{
|
|
||||||
if (!g_archive.sub_apps) {
|
|
||||||
g_archive.sub_apps = (char**)malloc(sizeof(char*));
|
|
||||||
if (!g_archive.sub_apps) {
|
|
||||||
log_error("malloc error.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_archive.sub_apps[0] = strdup(appname);
|
|
||||||
if (!g_archive.sub_apps[0]) {
|
|
||||||
log_error("malloc error.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
g_archive.n_sub_apps = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_archive.sub_apps =
|
|
||||||
(char**)realloc(g_archive.sub_apps, sizeof(char*) * (g_archive.n_sub_apps + 1));
|
|
||||||
if (!g_archive.sub_apps) {
|
|
||||||
log_error("malloc error.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
g_archive.sub_apps[g_archive.n_sub_apps] = strdup(appname);
|
|
||||||
if (!g_archive.sub_apps[g_archive.n_sub_apps]) {
|
|
||||||
log_error("malloc error.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
g_archive.n_sub_apps++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReleaseArchive()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < g_archive.n_sub_apps; ++i) {
|
|
||||||
free(g_archive.sub_apps[i]);
|
|
||||||
}
|
|
||||||
free(g_archive.sub_apps);
|
|
||||||
g_archive.n_sub_apps = 0;
|
|
||||||
g_archive.sub_apps = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaLoadFromFile(const char* file)
|
|
||||||
{
|
|
||||||
char *key = NULL;
|
|
||||||
FILE *f = fopen(file, "r");
|
|
||||||
if (!f) {
|
|
||||||
log_warn("not found archive file:%s, please confirm SDK is first startup.", file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseArchive();
|
|
||||||
|
|
||||||
char *line = NULL;
|
|
||||||
size_t len = 0;
|
|
||||||
ssize_t n = getline(&line, &len, f);
|
|
||||||
if (n <= 0) {
|
|
||||||
fclose(f);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
key = strndup(line, strlen(line) - 1);
|
|
||||||
g_archive.n_sub_apps = atoi(key);
|
|
||||||
free(key);
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < g_archive.n_sub_apps; ++i) {
|
|
||||||
n = getline(&line, &len, f);
|
|
||||||
if (n <= 0) {
|
|
||||||
ReleaseArchive();
|
|
||||||
fclose(f);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
key = strndup(line, strlen(line) - 1);
|
|
||||||
NebulaAddSubApp(key);
|
|
||||||
free(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
n = getline(&line, &len, f);
|
|
||||||
if (n <= 0) {
|
|
||||||
ReleaseArchive();
|
|
||||||
fclose(f);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
key = strndup(line, strlen(line) - 1);
|
|
||||||
int dict_size = atoi(key);
|
|
||||||
free(key);
|
|
||||||
for (i = 0; i < dict_size; ++i) {
|
|
||||||
n = getline(&line, &len, f);
|
|
||||||
if (n <= 0) {
|
|
||||||
ReleaseArchive();
|
|
||||||
fclose(f);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
key = strndup(line, strlen(line) - 1);
|
|
||||||
char* pSpace = strchr(key, ' ');
|
|
||||||
if (!pSpace) {
|
|
||||||
ReleaseArchive();
|
|
||||||
fclose(f);
|
|
||||||
free(key);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pSpace = '\0';
|
|
||||||
char* value = pSpace + 1;
|
|
||||||
int v = atoi(value);
|
|
||||||
dict *seqs = *g_archive.seqs;
|
|
||||||
dictEntry *entry = dictFind(seqs, key);
|
|
||||||
if (entry) {
|
|
||||||
entry->v.u64 = v;
|
|
||||||
} else {
|
|
||||||
dictAdd(seqs, key, (void*)(uint64_t)v);
|
|
||||||
}
|
|
||||||
free(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line)
|
|
||||||
free(line);
|
|
||||||
fclose(f);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaSaveToFile(const char* file)
|
|
||||||
{
|
|
||||||
FILE *f = fopen(file, "w");
|
|
||||||
if (!f) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[32];
|
|
||||||
snprintf(buf, sizeof(buf), "%d", g_archive.n_sub_apps);
|
|
||||||
fwrite(buf, 1, strlen(buf), f);
|
|
||||||
fwrite("\n", 1, 1, f);
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < g_archive.n_sub_apps; ++i) {
|
|
||||||
fwrite(g_archive.sub_apps[i], 1, strlen(g_archive.sub_apps[i]), f);
|
|
||||||
fwrite("\n", 1, 1, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
dict *seqs = *g_archive.seqs;
|
|
||||||
snprintf(buf, sizeof(buf), "%d", (int)dictSize(seqs));
|
|
||||||
fwrite(buf, 1, strlen(buf), f);
|
|
||||||
fwrite("\n", 1, 1, f);
|
|
||||||
dictIterator *it = dictGetIterator(seqs);
|
|
||||||
dictEntry *entry = dictNext(it);
|
|
||||||
while (entry) {
|
|
||||||
fwrite((const char*)entry->key, 1, strlen((const char*)entry->key), f);
|
|
||||||
fwrite(" ", 1, 1, f);
|
|
||||||
snprintf(buf, sizeof(buf), "%lu", entry->v.u64);
|
|
||||||
fwrite(buf, 1, strlen(buf), f);
|
|
||||||
fwrite("\n", 1, 1, f);
|
|
||||||
entry = dictNext(it);
|
|
||||||
}
|
|
||||||
int ret = fflush(f);
|
|
||||||
fclose(f);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct timer_entry g_save_entry;
|
|
||||||
void save_timer(timer_heap_t* ht, timer_entry* entry)
|
|
||||||
{
|
|
||||||
timer_update(ht, entry, 10000);
|
|
||||||
NebulaSaveToFile(g_storage_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaInitAutoSave()
|
|
||||||
{
|
|
||||||
timer_entry_init(&g_save_entry, 0, NULL, &save_timer);
|
|
||||||
timer_add(g_timer, &g_save_entry, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
|||||||
#ifndef ARCHIVE_H
|
|
||||||
#define ARCHIVE_H
|
|
||||||
|
|
||||||
#include "dict.h"
|
|
||||||
|
|
||||||
struct _Archive
|
|
||||||
{
|
|
||||||
int n_sub_apps;
|
|
||||||
char **sub_apps;
|
|
||||||
dict **seqs;
|
|
||||||
};
|
|
||||||
typedef struct _Archive Archive;
|
|
||||||
extern Archive g_archive;
|
|
||||||
|
|
||||||
void NebulaInitAutoSave();
|
|
||||||
|
|
||||||
int NebulaIsSubscribed(const char* appname);
|
|
||||||
|
|
||||||
int NebulaAddSubApp(const char* appname);
|
|
||||||
|
|
||||||
int NebulaLoadFromFile(const char* file);
|
|
||||||
|
|
||||||
int NebulaSaveToFile(const char* file);
|
|
||||||
|
|
||||||
#endif //ARCHIVE_H
|
|
Binary file not shown.
@ -1,112 +0,0 @@
|
|||||||
#include "auth.h"
|
|
||||||
#include "connect.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include <openssl/md5.h>
|
|
||||||
#include "str.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "connect.h"
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
char* g_token = "";
|
|
||||||
|
|
||||||
int NebulaAuth1()
|
|
||||||
{
|
|
||||||
Nebula__AuthRequest request;
|
|
||||||
nebula__auth_request__init(&request);
|
|
||||||
request.uid = g_device_tag;
|
|
||||||
request.username = g_device_tag;
|
|
||||||
return NebulaSend(MSG_SET_REQUEST(NEBULA_MSG_AUTH), (ProtobufCMessage*)&request);
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaAuth2(char* token, char* nonce)
|
|
||||||
{
|
|
||||||
Nebula__AuthRequest request;
|
|
||||||
nebula__auth_request__init(&request);
|
|
||||||
request.uid = g_device_tag;
|
|
||||||
request.username = g_device_tag;
|
|
||||||
request.token = token;
|
|
||||||
request.nonce = nonce;
|
|
||||||
request.has_algorithm = 1;
|
|
||||||
request.algorithm = NEBULA__AUTH_REQUEST__ALGORITHM__MD5_DAA;
|
|
||||||
return NebulaSend(MSG_SET_REQUEST(NEBULA_MSG_AUTH), (ProtobufCMessage*)&request);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaOnAuth(NebulaHeader *head, const char* data, int len)
|
|
||||||
{
|
|
||||||
Nebula__AuthResponse *response = nebula__auth_response__unpack(NULL, len, (const uint8_t*)data);
|
|
||||||
if (!response) {
|
|
||||||
log_error("parse auth response error. data_len=%d", len);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response->status == 200) {
|
|
||||||
// auth success.
|
|
||||||
next_status();
|
|
||||||
} else {
|
|
||||||
if (Nebulaget_status() == eStatus_Auth2) {
|
|
||||||
// auth failed, retry redirect.
|
|
||||||
log_error("auth failed, rsp.status() == %d. sleep 1 and retry redirect.", response->status);
|
|
||||||
nebula__auth_response__free_unpacked(response, NULL);
|
|
||||||
sleep(1);
|
|
||||||
PopFront(g_server_list);
|
|
||||||
jump_status(eStatus_Connect);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char hex[] = "0123456789abcdef";
|
|
||||||
int i;
|
|
||||||
unsigned char ha1_b[16], ha1[32], token_b[16], token[33];
|
|
||||||
struct str buf;
|
|
||||||
string_init(&buf);
|
|
||||||
string_append_fast(&buf, g_salt, strlen(g_salt));
|
|
||||||
string_append_fast(&buf, ":", 1);
|
|
||||||
string_append_fast(&buf, g_device_tag, strlen(g_device_tag));
|
|
||||||
string_append_fast(&buf, ":", 1);
|
|
||||||
string_append_fast(&buf, response->nonce, strlen(response->nonce));
|
|
||||||
MD5((unsigned char*)buf.ptr, buf.len, ha1_b);
|
|
||||||
for (i = 0; i < MD5_DIGEST_LENGTH; i++)
|
|
||||||
{
|
|
||||||
ha1[i * 2] = hex[ha1_b[i] >> 4];
|
|
||||||
ha1[i * 2 + 1] = hex[ha1_b[i] & 0xf];
|
|
||||||
}
|
|
||||||
|
|
||||||
string_reset(&buf);
|
|
||||||
char *rule = g_rule;
|
|
||||||
while (*rule) {
|
|
||||||
if (!string_empty(&buf)) {
|
|
||||||
string_append_fast(&buf, ":", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*rule == 'h') {
|
|
||||||
string_append_fast(&buf, (char*)ha1, 32);
|
|
||||||
} else if (*rule == 's') {
|
|
||||||
string_append_fast(&buf, g_salt, strlen(g_salt));
|
|
||||||
} else {
|
|
||||||
log_error("unkown rule: %s", g_rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
rule++;
|
|
||||||
}
|
|
||||||
MD5((unsigned char*)buf.ptr, buf.len, token_b);
|
|
||||||
|
|
||||||
for (i = 0; i < MD5_DIGEST_LENGTH; i++)
|
|
||||||
{
|
|
||||||
token[i * 2] = hex[token_b[i] >> 4];
|
|
||||||
token[i * 2 + 1] = hex[token_b[i] & 0xf];
|
|
||||||
}
|
|
||||||
token[32] = '\0';
|
|
||||||
|
|
||||||
//log_debug("auth. md5buf:%s, token:%s", buf.ptr, token);
|
|
||||||
|
|
||||||
string_deinit(&buf);
|
|
||||||
if (-1 == NebulaAuth2((char*)token, response->nonce)) {
|
|
||||||
jump_status(eStatus_Redirect);
|
|
||||||
} else {
|
|
||||||
if (strlen(g_token)) free(g_token);
|
|
||||||
g_token = strdup((char*)token);
|
|
||||||
next_status();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nebula__auth_response__free_unpacked(response, NULL);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#ifndef AUTH_H
|
|
||||||
#define AUTH_H
|
|
||||||
|
|
||||||
#include "nebula_proto.h"
|
|
||||||
|
|
||||||
// auth 分为2步.
|
|
||||||
|
|
||||||
int NebulaAuth1();
|
|
||||||
|
|
||||||
void NebulaOnAuth(NebulaHeader *head, const char* data, int len);
|
|
||||||
|
|
||||||
#endif //AUTH_H
|
|
Binary file not shown.
@ -1,63 +0,0 @@
|
|||||||
#include "config.h"
|
|
||||||
|
|
||||||
eStatus g_status = eStatus_Init;
|
|
||||||
|
|
||||||
const char* Nebularand_string()
|
|
||||||
{
|
|
||||||
static char buf[32] = {};
|
|
||||||
int len = rand() % (sizeof(buf) - 1 - 16) + 16;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
int v = rand() % 36;
|
|
||||||
if (v < 10)
|
|
||||||
buf[i] = '0' + v;
|
|
||||||
else
|
|
||||||
buf[i] = 'a' + v - 10;
|
|
||||||
}
|
|
||||||
buf[i] = '\0';
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Nebulamsgtype_name(int type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case eNebulaMsg_Push: /// 推送 (路由器只需关心这一类消息)
|
|
||||||
return "eNebulaMsg_Push";
|
|
||||||
break;
|
|
||||||
case eNebulaMsg_Presence: /// Presence
|
|
||||||
return "eNebulaMsg_Presence";
|
|
||||||
break;
|
|
||||||
case eNebulaMsg_Sms: /// 网络短信
|
|
||||||
return "eNebulaMsg_Sms";
|
|
||||||
break;
|
|
||||||
case eNebulaMsg_Mms: /// 网络彩信
|
|
||||||
return "eNebulaMsg_Mms";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Nebulastatus_name(eStatus ss)
|
|
||||||
{
|
|
||||||
static const char* names[] = {
|
|
||||||
"eStatus_Init",
|
|
||||||
"eStatus_Redirect",
|
|
||||||
"eStatus_LoopTest",
|
|
||||||
"eStatus_Connect",
|
|
||||||
"eStatus_Connecting",
|
|
||||||
"eStatus_Auth1",
|
|
||||||
"eStatus_Auth1_Waiting",
|
|
||||||
"eStatus_Auth2",
|
|
||||||
"eStatus_Sub",
|
|
||||||
"eStatus_Estab",
|
|
||||||
};
|
|
||||||
|
|
||||||
return names[ss];
|
|
||||||
}
|
|
||||||
|
|
||||||
eStatus Nebulaget_status()
|
|
||||||
{
|
|
||||||
return g_status;
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
#ifndef CONFIG_H
|
|
||||||
#define CONFIG_H
|
|
||||||
|
|
||||||
#include "nebula_sdk.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "logger.h"
|
|
||||||
#include "list.h"
|
|
||||||
#include "message.pb-c.h"
|
|
||||||
#include "nebula.pb-c.h"
|
|
||||||
|
|
||||||
enum _eStatus {
|
|
||||||
eStatus_Init,
|
|
||||||
eStatus_Redirect,
|
|
||||||
eStatus_LoopTest,
|
|
||||||
eStatus_Connect,
|
|
||||||
eStatus_Connecting,
|
|
||||||
eStatus_Auth1,
|
|
||||||
eStatus_Auth1_Waiting,
|
|
||||||
eStatus_Auth2,
|
|
||||||
eStatus_Sub,
|
|
||||||
eStatus_Estab,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum _eStatus eStatus;
|
|
||||||
|
|
||||||
extern char* g_device_tag;
|
|
||||||
extern char* g_nebula_host;
|
|
||||||
extern NebulaMsgCallback g_nebula_cb[eNebulaMsg_Max];
|
|
||||||
extern int g_storage_fd;
|
|
||||||
extern timer_heap_t *g_timer;
|
|
||||||
extern List *g_server_list;
|
|
||||||
extern char* g_salt;
|
|
||||||
extern char* g_rule;
|
|
||||||
extern char* g_token;
|
|
||||||
extern int g_sub_app_count;
|
|
||||||
extern char** g_sub_apps;
|
|
||||||
extern eStatus g_status;
|
|
||||||
|
|
||||||
const char* Nebularand_string();
|
|
||||||
const char* Nebulamsgtype_name(int type);
|
|
||||||
|
|
||||||
const char* Nebulastatus_name(eStatus ss);
|
|
||||||
eStatus Nebulaget_status();
|
|
||||||
|
|
||||||
#define next_status() \
|
|
||||||
do \
|
|
||||||
{\
|
|
||||||
if (g_status < eStatus_Estab) {\
|
|
||||||
g_status ++;\
|
|
||||||
log_info("set status to %s", Nebulastatus_name(g_status));\
|
|
||||||
} else {\
|
|
||||||
g_status = eStatus_Init;\
|
|
||||||
log_info("set status to %s", Nebulastatus_name(g_status));\
|
|
||||||
}\
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
|
|
||||||
#define jump_status(ss) \
|
|
||||||
do \
|
|
||||||
{\
|
|
||||||
g_status = ss;\
|
|
||||||
log_info("set status to %s", Nebulastatus_name(g_status));\
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#endif //CONFIG_H
|
|
Binary file not shown.
@ -1,208 +0,0 @@
|
|||||||
#include "connect.h"
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "net.h"
|
|
||||||
#include "auth.h"
|
|
||||||
#include "subscribe.h"
|
|
||||||
#include "nebula.pb-c.h"
|
|
||||||
#include "nebula_proto.h"
|
|
||||||
#include "nebula_compress_uncompress_wrapper.h"
|
|
||||||
#include "nebula_encrypt_decrypt_wrapper.h"
|
|
||||||
#include "push.h"
|
|
||||||
#include "timer.h"
|
|
||||||
|
|
||||||
static Conn* g_conn = NULL;
|
|
||||||
timer_entry g_ping_entry;
|
|
||||||
|
|
||||||
void Ping(timer_heap_t* ht, timer_entry *entry);
|
|
||||||
|
|
||||||
static void __on_connect(Conn* conn, int err)
|
|
||||||
{
|
|
||||||
if (err) {
|
|
||||||
// connect failed.
|
|
||||||
log_error("connect server_addr:%s:%d error:%s", conn->host, conn->port, strerror(err));
|
|
||||||
PopFront(g_server_list);
|
|
||||||
jump_status(eStatus_Connect);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info("connect success, server_addr:%s:%d", conn->host, conn->port);
|
|
||||||
timer_entry_init(&g_ping_entry, 0, NULL, &Ping);
|
|
||||||
timer_add(g_timer, &g_ping_entry, 180);
|
|
||||||
next_status();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __handle_message(NebulaHeader* head)
|
|
||||||
{
|
|
||||||
static char *buf1 = NULL;
|
|
||||||
if (!buf1)
|
|
||||||
buf1 = (char*)malloc(MAX_BUF_SIZE);
|
|
||||||
static char *buf2 = NULL;
|
|
||||||
if (!buf2)
|
|
||||||
buf2 = (char*)malloc(MAX_BUF_SIZE);
|
|
||||||
|
|
||||||
log_debug("NEBULA RX %s|%d", MsgType2Str(head->type), (int)htons(head->len));
|
|
||||||
|
|
||||||
if ((head->type & 0x7f) == NEBULA_MSG_PING) {
|
|
||||||
log_debug("pong.");
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
Nebula__NebulaMsg *msg = nebula__nebula_msg__unpack(NULL, htons(head->len), (uint8_t*)(head + 1));
|
|
||||||
if (!msg) {
|
|
||||||
log_debug("NebulaMsg parser error.");
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *data = (char*)msg->body.data;
|
|
||||||
uint32_t len = msg->body.len;
|
|
||||||
|
|
||||||
int compress_type = head->flag >> 4;
|
|
||||||
int encrypt_type = head->flag & 0x0f;
|
|
||||||
if (compress_type) {
|
|
||||||
// uncompress
|
|
||||||
uint32_t dst_len = MAX_BUF_SIZE;
|
|
||||||
if (-1 == NebulaUnCompress(compress_type, data, len, buf1, &dst_len)) {
|
|
||||||
log_debug("uncompress error. head->type=%d", head->type);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = buf1;
|
|
||||||
len = dst_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (encrypt_type) {
|
|
||||||
// unencrypt
|
|
||||||
uint32_t dst_len = MAX_BUF_SIZE;
|
|
||||||
if (-1 == NebulaDecrypt(encrypt_type, g_token,
|
|
||||||
strlen(g_token), data, len, buf2, &dst_len)) {
|
|
||||||
log_debug("unencrypt error. head->type=%d", head->type);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = buf2;
|
|
||||||
len = dst_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dispatch
|
|
||||||
if (MSG_IS_REQUEST(head)) {
|
|
||||||
// request
|
|
||||||
switch (head->type & 0x7f) {
|
|
||||||
case NEBULA_MSG_PSH:
|
|
||||||
NebulaOnPush(head, data, len);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NEBULA_MSG_MSG:
|
|
||||||
NebulaOnMsg(head, data, len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// response
|
|
||||||
switch (head->type & 0x7f) {
|
|
||||||
case NEBULA_MSG_AUTH:
|
|
||||||
NebulaOnAuth(head, data, len);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NEBULA_MSG_SUB:
|
|
||||||
NebulaOnSub(head, data, len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __on_read(Conn* conn, NebulaHeader* head)
|
|
||||||
{
|
|
||||||
(void)conn;
|
|
||||||
__handle_message(head);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __on_disconnect(Conn* conn)
|
|
||||||
{
|
|
||||||
(void)conn;
|
|
||||||
log_warn("tcp net disconnected, retry connect...");
|
|
||||||
timer_del(g_timer, &g_ping_entry);
|
|
||||||
if (Nebulaget_status() > eStatus_Connect)
|
|
||||||
jump_status(eStatus_Connect);
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaConnect()
|
|
||||||
{
|
|
||||||
if (!g_conn) {
|
|
||||||
g_conn = NebulaConnCreate();
|
|
||||||
NebulaConnInit(g_conn, __on_connect, __on_read, __on_disconnect);
|
|
||||||
if (!g_conn) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_conn->state == eConnState_Estab) {
|
|
||||||
NebulaDisconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_server_list->size) {
|
|
||||||
// 没有ip列表, 重新redirect.
|
|
||||||
jump_status(eStatus_Redirect);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in *addr = (struct sockaddr_in *)Front(g_server_list);
|
|
||||||
uint16_t port = htons(addr->sin_port);
|
|
||||||
char ip[32] = {};
|
|
||||||
inet_ntop(AF_INET, &addr->sin_addr.s_addr, ip, sizeof(ip));
|
|
||||||
|
|
||||||
if (-1 == NebulaConnConnect(g_conn, ip, port)) {
|
|
||||||
log_error("connect error, server_addr:%s:%d", ip, port);
|
|
||||||
PopFront(g_server_list);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info("connect to server:%s:%d", ip, port);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaSend(uint8_t type, ProtobufCMessage *msg)
|
|
||||||
{
|
|
||||||
NebulaHeader head;
|
|
||||||
HEAD_INIT(&head, type);
|
|
||||||
|
|
||||||
Nebula__NebulaMsg nebula_msg;
|
|
||||||
nebula__nebula_msg__init(&nebula_msg);
|
|
||||||
char msgid_buf[24];
|
|
||||||
CreateMsgid(msgid_buf);
|
|
||||||
nebula_msg.msgid = msgid_buf;
|
|
||||||
if (msg) {
|
|
||||||
nebula_msg.has_body = 1;
|
|
||||||
nebula_msg.body.len = protobuf_c_message_get_packed_size(msg);
|
|
||||||
nebula_msg.body.data = (uint8_t*)malloc(nebula_msg.body.len);
|
|
||||||
if (!nebula_msg.body.data) {
|
|
||||||
log_error("malloc error.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
protobuf_c_message_pack(msg, nebula_msg.body.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret = NebulaConnSend(g_conn, &head, (ProtobufCMessage *)&nebula_msg);
|
|
||||||
if (nebula_msg.has_body) {
|
|
||||||
free(nebula_msg.body.data);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Ping(timer_heap_t* ht, timer_entry *entry)
|
|
||||||
{
|
|
||||||
NebulaHeader head;
|
|
||||||
HEAD_INIT(&head, MSG_SET_REQUEST(NEBULA_MSG_PING));
|
|
||||||
head.flag = 180;
|
|
||||||
//TODO: dynamic ping's time interval.
|
|
||||||
timer_update(ht, entry, head.flag * 1000);
|
|
||||||
if (-1 == NebulaConnSend(g_conn, &head, NULL)) {
|
|
||||||
log_error("Ping send error.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaDisconnect()
|
|
||||||
{
|
|
||||||
NebulaConnNebulaDisconnect(g_conn);
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
|||||||
#ifndef CONNECT_H
|
|
||||||
#define CONNECT_H
|
|
||||||
|
|
||||||
#include <google/protobuf-c/protobuf-c.h>
|
|
||||||
|
|
||||||
#define MAX_BUF_SIZE 4096
|
|
||||||
|
|
||||||
int NebulaConnect();
|
|
||||||
|
|
||||||
int NebulaSend(uint8_t type, ProtobufCMessage *msg);
|
|
||||||
|
|
||||||
void NebulaDisconnect();
|
|
||||||
|
|
||||||
#endif //CONNECT_H
|
|
Binary file not shown.
@ -1,60 +0,0 @@
|
|||||||
#ifndef CRYPTO_FRAMWROK_H
|
|
||||||
#define CRYPTO_FRAMWROK_H
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CRYPTO_OK 0
|
|
||||||
#define CRYPTO_UNDEF_MEMORY -1
|
|
||||||
#define CRYPTO_TOOSHORT_DST_LEN -2
|
|
||||||
#define CRYPTO_TOOSHORT_KEY_LEN -3
|
|
||||||
#define CRYPTO_SET_KEY_ERROR -4
|
|
||||||
#define CRYPTO_SRC_LEN_ZERO -5
|
|
||||||
|
|
||||||
#define CRYPTO1_BLOCK_SIZE 16
|
|
||||||
#define CRYPTO2_BLOCK_SIZE 16
|
|
||||||
#define CRYPTO3_BLOCK_SIZE 8
|
|
||||||
/*
|
|
||||||
* CRYPTO_UNDEF_MEMORY means key,src,dst is NULL
|
|
||||||
* CRYPTO_TOOSHORT_DST_LEN means dst_len too short
|
|
||||||
* if(*len < src_len)
|
|
||||||
return CRYPTO_TOOSHORT_DST_LEN;
|
|
||||||
if(*len < src_len + BLOCK_SIZE - src_len % BLOCK_SIZE)
|
|
||||||
if(src_len % BLOCK_SIZE != 0)
|
|
||||||
return CRYPTO_TOOSHORT_DST_LEN;
|
|
||||||
typically src_len = *len = BLOCK_SIZE * n (n = 1,2,3....) is recommend
|
|
||||||
* CRYPTO_TOOSHORT_KEY_LEN means key_len < 16
|
|
||||||
* CRYPTO_SET_KEY_ERROR means set key error(hardly occurs)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* fast : CRYPTO3 > CRYPTO2 > CRYPTO1
|
|
||||||
* secure : CRYPTO2 > CRYPTO1 > CRYPTO3
|
|
||||||
* 128 bits key is less secure than 256 bits,but run faster
|
|
||||||
*/
|
|
||||||
/* CRYPTO1 is fast */
|
|
||||||
int CRYPTO1_encrypt(const unsigned char *key,const uint32_t key_len,const unsigned char *src,const uint32_t src_len,unsigned char *dst,uint32_t *len);
|
|
||||||
|
|
||||||
int CRYPTO1_decrypt(const unsigned char *key,const uint32_t key_len,const unsigned char *src,const uint32_t src_len,unsigned char *dst,uint32_t *len);
|
|
||||||
|
|
||||||
/* CRYPTO2 is slightly slower but safer*/
|
|
||||||
int CRYPTO2_encrypt(const unsigned char *key,const uint32_t key_len,const unsigned char *src,const uint32_t src_len,unsigned char *dst,uint32_t *len);
|
|
||||||
|
|
||||||
int CRYPTO2_decrypt(const unsigned char *key,const uint32_t key_len,const unsigned char *src,const uint32_t src_len,unsigned char *dst,uint32_t *len);
|
|
||||||
|
|
||||||
/* CRYPTO3 is less secure but faster*/
|
|
||||||
int CRYPTO3_encrypt(const unsigned char *key,const uint32_t key_len,const unsigned char *src,const uint32_t src_len,unsigned char *dst,uint32_t *len);
|
|
||||||
|
|
||||||
int CRYPTO3_decrypt(const unsigned char *key,const uint32_t key_len,const unsigned char *src,const uint32_t src_len,unsigned char *dst,uint32_t *len);
|
|
||||||
|
|
||||||
/* implement of CRYPTO2 */
|
|
||||||
int CRYPTO_encrypt_without_key(const unsigned char *src,const uint32_t src_len,unsigned char *dst,uint32_t *len);
|
|
||||||
int CRYPTO_decrypt_without_key(const unsigned char *src,const uint32_t src_len,unsigned char *dst,uint32_t *len);
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,3 +0,0 @@
|
|||||||
1
|
|
||||||
com.meizu.cloud
|
|
||||||
0
|
|
@ -1,811 +0,0 @@
|
|||||||
/* Hash Tables Implementation.
|
|
||||||
*
|
|
||||||
* This file implements in memory hash tables with insert/del/replace/find/
|
|
||||||
* get-random-element operations. Hash tables will auto resize if needed
|
|
||||||
* tables of power of two in size are used, collisions are handled by
|
|
||||||
* chaining. See the source code for more information... :)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* * 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.
|
|
||||||
* * Neither the name of Redis nor the names of its contributors may be used
|
|
||||||
* to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "dict.h"
|
|
||||||
|
|
||||||
/* Using dictEnableResize() / dictDisableResize() we make possible to
|
|
||||||
* enable/disable resizing of the hash table as needed. This is very important
|
|
||||||
* for Redis, as we use copy-on-write and don't want to move too much memory
|
|
||||||
* around when there is a child performing saving operations.
|
|
||||||
*
|
|
||||||
* Note that even when dict_can_resize is set to 0, not all resizes are
|
|
||||||
* prevented: an hash table is still allowed to grow if the ratio between
|
|
||||||
* the number of elements and the buckets > dict_force_resize_ratio. */
|
|
||||||
static int dict_can_resize = 1;
|
|
||||||
static unsigned int dict_force_resize_ratio = 5;
|
|
||||||
|
|
||||||
/* -------------------------- private prototypes ---------------------------- */
|
|
||||||
|
|
||||||
static int _dictExpandIfNeeded(dict *ht);
|
|
||||||
static unsigned long _dictNextPower(unsigned long size);
|
|
||||||
static int _dictKeyIndex(dict *ht, const void *key);
|
|
||||||
static int _dictInit(dict *ht, dictType *type, void *privDataPtr);
|
|
||||||
|
|
||||||
/* -------------------------- hash functions -------------------------------- */
|
|
||||||
|
|
||||||
/* Thomas Wang's 32 bit Mix Function */
|
|
||||||
unsigned int dictIntHashFunction(unsigned int key)
|
|
||||||
{
|
|
||||||
key += ~(key << 15);
|
|
||||||
key ^= (key >> 10);
|
|
||||||
key += (key << 3);
|
|
||||||
key ^= (key >> 6);
|
|
||||||
key += ~(key << 11);
|
|
||||||
key ^= (key >> 16);
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Identity hash function for integer keys */
|
|
||||||
unsigned int dictIdentityHashFunction(unsigned int key)
|
|
||||||
{
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t dict_hash_function_seed = 5381;
|
|
||||||
|
|
||||||
void dictSetHashFunctionSeed(uint32_t seed) {
|
|
||||||
dict_hash_function_seed = seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t dictGetHashFunctionSeed(void) {
|
|
||||||
return dict_hash_function_seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MurmurHash2, by Austin Appleby
|
|
||||||
* Note - This code makes a few assumptions about how your machine behaves -
|
|
||||||
* 1. We can read a 4-byte value from any address without crashing
|
|
||||||
* 2. sizeof(int) == 4
|
|
||||||
*
|
|
||||||
* And it has a few limitations -
|
|
||||||
*
|
|
||||||
* 1. It will not work incrementally.
|
|
||||||
* 2. It will not produce the same results on little-endian and big-endian
|
|
||||||
* machines.
|
|
||||||
*/
|
|
||||||
unsigned int dictGenHashFunction(const void *key, int len) {
|
|
||||||
/* 'm' and 'r' are mixing constants generated offline.
|
|
||||||
They're not really 'magic', they just happen to work well. */
|
|
||||||
uint32_t seed = dict_hash_function_seed;
|
|
||||||
const uint32_t m = 0x5bd1e995;
|
|
||||||
const int r = 24;
|
|
||||||
|
|
||||||
/* Initialize the hash to a 'random' value */
|
|
||||||
uint32_t h = seed ^ len;
|
|
||||||
|
|
||||||
/* Mix 4 bytes at a time into the hash */
|
|
||||||
const unsigned char *data = (const unsigned char *)key;
|
|
||||||
|
|
||||||
while(len >= 4) {
|
|
||||||
uint32_t k = *(uint32_t*)data;
|
|
||||||
|
|
||||||
k *= m;
|
|
||||||
k ^= k >> r;
|
|
||||||
k *= m;
|
|
||||||
|
|
||||||
h *= m;
|
|
||||||
h ^= k;
|
|
||||||
|
|
||||||
data += 4;
|
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle the last few bytes of the input array */
|
|
||||||
switch(len) {
|
|
||||||
case 3: h ^= data[2] << 16;
|
|
||||||
case 2: h ^= data[1] << 8;
|
|
||||||
case 1: h ^= data[0]; h *= m;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Do a few final mixes of the hash to ensure the last few
|
|
||||||
* bytes are well-incorporated. */
|
|
||||||
h ^= h >> 13;
|
|
||||||
h *= m;
|
|
||||||
h ^= h >> 15;
|
|
||||||
|
|
||||||
return (unsigned int)h;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And a case insensitive hash function (based on djb hash) */
|
|
||||||
unsigned int dictGenCaseHashFunction(const unsigned char *buf, int len) {
|
|
||||||
unsigned int hash = (unsigned int)dict_hash_function_seed;
|
|
||||||
|
|
||||||
while (len--)
|
|
||||||
hash = ((hash << 5) + hash) + (tolower(*buf++)); /* hash * 33 + c */
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------- API implementation ------------------------- */
|
|
||||||
|
|
||||||
/* Reset a hash table already initialized with ht_init().
|
|
||||||
* NOTE: This function should only be called by ht_destroy(). */
|
|
||||||
static void _dictReset(dictht *ht)
|
|
||||||
{
|
|
||||||
ht->table = NULL;
|
|
||||||
ht->size = 0;
|
|
||||||
ht->sizemask = 0;
|
|
||||||
ht->used = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a new hash table */
|
|
||||||
dict *dictCreate(dictType *type,
|
|
||||||
void *privDataPtr)
|
|
||||||
{
|
|
||||||
dict *d = (dict*)malloc(sizeof(*d));
|
|
||||||
if(d == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dictInit(d,type,privDataPtr);
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the hash table */
|
|
||||||
int _dictInit(dict *d, dictType *type,
|
|
||||||
void *privDataPtr)
|
|
||||||
{
|
|
||||||
_dictReset(&d->ht[0]);
|
|
||||||
_dictReset(&d->ht[1]);
|
|
||||||
d->type = type;
|
|
||||||
d->privdata = privDataPtr;
|
|
||||||
d->rehashidx = -1;
|
|
||||||
d->iterators = 0;
|
|
||||||
return DICT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Resize the table to the minimal size that contains all the elements,
|
|
||||||
* but with the invariant of a USED/BUCKETS ratio near to <= 1 */
|
|
||||||
int dictResize(dict *d)
|
|
||||||
{
|
|
||||||
int minimal;
|
|
||||||
|
|
||||||
if (!dict_can_resize || dictIsRehashing(d)) return DICT_ERR;
|
|
||||||
minimal = d->ht[0].used;
|
|
||||||
if (minimal < DICT_HT_INITIAL_SIZE)
|
|
||||||
minimal = DICT_HT_INITIAL_SIZE;
|
|
||||||
return dictExpand(d, minimal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expand or create the hash table */
|
|
||||||
int dictExpand(dict *d, unsigned long size)
|
|
||||||
{
|
|
||||||
dictht n; /* the new hash table */
|
|
||||||
unsigned long realsize = _dictNextPower(size);
|
|
||||||
|
|
||||||
/* the size is invalid if it is smaller than the number of
|
|
||||||
* elements already inside the hash table */
|
|
||||||
if (dictIsRehashing(d) || d->ht[0].used > size)
|
|
||||||
return DICT_ERR;
|
|
||||||
|
|
||||||
/* Allocate the new hash table and initialize all pointers to NULL */
|
|
||||||
n.size = realsize;
|
|
||||||
n.sizemask = realsize-1;
|
|
||||||
n.table = (dictEntry**)calloc(1, realsize*sizeof(dictEntry*));
|
|
||||||
n.used = 0;
|
|
||||||
|
|
||||||
/* Is this the first initialization? If so it's not really a rehashing
|
|
||||||
* we just set the first hash table so that it can accept keys. */
|
|
||||||
if (d->ht[0].table == NULL) {
|
|
||||||
d->ht[0] = n;
|
|
||||||
return DICT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare a second hash table for incremental rehashing */
|
|
||||||
d->ht[1] = n;
|
|
||||||
d->rehashidx = 0;
|
|
||||||
return DICT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Performs N steps of incremental rehashing. Returns 1 if there are still
|
|
||||||
* keys to move from the old to the new hash table, otherwise 0 is returned.
|
|
||||||
* Note that a rehashing step consists in moving a bucket (that may have more
|
|
||||||
* thank one key as we use chaining) from the old to the new hash table. */
|
|
||||||
int dictRehash(dict *d, int n) {
|
|
||||||
if (!dictIsRehashing(d)) return 0;
|
|
||||||
|
|
||||||
while(n--) {
|
|
||||||
dictEntry *de, *nextde;
|
|
||||||
|
|
||||||
/* Check if we already rehashed the whole table... */
|
|
||||||
if (d->ht[0].used == 0) {
|
|
||||||
free(d->ht[0].table);
|
|
||||||
d->ht[0] = d->ht[1];
|
|
||||||
_dictReset(&d->ht[1]);
|
|
||||||
d->rehashidx = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note that rehashidx can't overflow as we are sure there are more
|
|
||||||
* elements because ht[0].used != 0 */
|
|
||||||
assert(d->ht[0].size > (unsigned)d->rehashidx);
|
|
||||||
while(d->ht[0].table[d->rehashidx] == NULL) d->rehashidx++;
|
|
||||||
de = d->ht[0].table[d->rehashidx];
|
|
||||||
/* Move all the keys in this bucket from the old to the new hash HT */
|
|
||||||
while(de) {
|
|
||||||
unsigned int h;
|
|
||||||
|
|
||||||
nextde = de->next;
|
|
||||||
/* Get the index in the new hash table */
|
|
||||||
h = dictHashKey(d, de->key) & d->ht[1].sizemask;
|
|
||||||
de->next = d->ht[1].table[h];
|
|
||||||
d->ht[1].table[h] = de;
|
|
||||||
d->ht[0].used--;
|
|
||||||
d->ht[1].used++;
|
|
||||||
de = nextde;
|
|
||||||
}
|
|
||||||
d->ht[0].table[d->rehashidx] = NULL;
|
|
||||||
d->rehashidx++;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
long long timeInMilliseconds(void) {
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
gettimeofday(&tv,NULL);
|
|
||||||
return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Rehash for an amount of time between ms milliseconds and ms+1 milliseconds */
|
|
||||||
int dictRehashMilliseconds(dict *d, int ms) {
|
|
||||||
long long start = timeInMilliseconds();
|
|
||||||
int rehashes = 0;
|
|
||||||
|
|
||||||
while(dictRehash(d,100)) {
|
|
||||||
rehashes += 100;
|
|
||||||
if (timeInMilliseconds()-start > ms) break;
|
|
||||||
}
|
|
||||||
return rehashes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function performs just a step of rehashing, and only if there are
|
|
||||||
* no safe iterators bound to our hash table. When we have iterators in the
|
|
||||||
* middle of a rehashing we can't mess with the two hash tables otherwise
|
|
||||||
* some element can be missed or duplicated.
|
|
||||||
*
|
|
||||||
* This function is called by common lookup or update operations in the
|
|
||||||
* dictionary so that the hash table automatically migrates from H1 to H2
|
|
||||||
* while it is actively used. */
|
|
||||||
static void _dictRehashStep(dict *d) {
|
|
||||||
if (d->iterators == 0) dictRehash(d,1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add an element to the target hash table */
|
|
||||||
int dictAdd(dict *d, void *key, void *val)
|
|
||||||
{
|
|
||||||
dictEntry *entry = dictAddRaw(d,key);
|
|
||||||
|
|
||||||
if (!entry) return DICT_ERR;
|
|
||||||
dictSetVal(d, entry, val);
|
|
||||||
return DICT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Low level add. This function adds the entry but instead of setting
|
|
||||||
* a value returns the dictEntry structure to the user, that will make
|
|
||||||
* sure to fill the value field as he wishes.
|
|
||||||
*
|
|
||||||
* This function is also directly exposed to user API to be called
|
|
||||||
* mainly in order to store non-pointers inside the hash value, example:
|
|
||||||
*
|
|
||||||
* entry = dictAddRaw(dict,mykey);
|
|
||||||
* if (entry != NULL) dictSetSignedIntegerVal(entry,1000);
|
|
||||||
*
|
|
||||||
* Return values:
|
|
||||||
*
|
|
||||||
* If key already exists NULL is returned.
|
|
||||||
* If key was added, the hash entry is returned to be manipulated by the caller.
|
|
||||||
*/
|
|
||||||
dictEntry *dictAddRaw(dict *d, void *key)
|
|
||||||
{
|
|
||||||
int index;
|
|
||||||
dictEntry *entry;
|
|
||||||
dictht *ht;
|
|
||||||
|
|
||||||
if (dictIsRehashing(d)) _dictRehashStep(d);
|
|
||||||
|
|
||||||
/* Get the index of the new element, or -1 if
|
|
||||||
* the element already exists. */
|
|
||||||
if ((index = _dictKeyIndex(d, key)) == -1)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Allocate the memory and store the new entry */
|
|
||||||
ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];
|
|
||||||
entry = (dictEntry*)malloc(sizeof(*entry));
|
|
||||||
entry->next = ht->table[index];
|
|
||||||
ht->table[index] = entry;
|
|
||||||
ht->used++;
|
|
||||||
|
|
||||||
/* Set the hash entry fields. */
|
|
||||||
dictSetKey(d, entry, key);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add an element, discarding the old if the key already exists.
|
|
||||||
* Return 1 if the key was added from scratch, 0 if there was already an
|
|
||||||
* element with such key and dictReplace() just performed a value update
|
|
||||||
* operation. */
|
|
||||||
int dictReplace(dict *d, void *key, void *val)
|
|
||||||
{
|
|
||||||
dictEntry *entry, auxentry;
|
|
||||||
|
|
||||||
/* Try to add the element. If the key
|
|
||||||
* does not exists dictAdd will suceed. */
|
|
||||||
if (dictAdd(d, key, val) == DICT_OK)
|
|
||||||
return 1;
|
|
||||||
/* It already exists, get the entry */
|
|
||||||
entry = dictFind(d, key);
|
|
||||||
/* Set the new value and free the old one. Note that it is important
|
|
||||||
* to do that in this order, as the value may just be exactly the same
|
|
||||||
* as the previous one. In this context, think to reference counting,
|
|
||||||
* you want to increment (set), and then decrement (free), and not the
|
|
||||||
* reverse. */
|
|
||||||
auxentry = *entry;
|
|
||||||
dictSetVal(d, entry, val);
|
|
||||||
dictFreeVal(d, &auxentry);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dictReplaceRaw() is simply a version of dictAddRaw() that always
|
|
||||||
* returns the hash entry of the specified key, even if the key already
|
|
||||||
* exists and can't be added (in that case the entry of the already
|
|
||||||
* existing key is returned.)
|
|
||||||
*
|
|
||||||
* See dictAddRaw() for more information. */
|
|
||||||
dictEntry *dictReplaceRaw(dict *d, void *key) {
|
|
||||||
dictEntry *entry = dictFind(d,key);
|
|
||||||
|
|
||||||
return entry ? entry : dictAddRaw(d,key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search and remove an element */
|
|
||||||
static int dictGenericDelete(dict *d, const void *key, int nofree)
|
|
||||||
{
|
|
||||||
unsigned int h, idx;
|
|
||||||
dictEntry *he, *prevHe;
|
|
||||||
int table;
|
|
||||||
|
|
||||||
if (d->ht[0].size == 0) return DICT_ERR; /* d->ht[0].table is NULL */
|
|
||||||
if (dictIsRehashing(d)) _dictRehashStep(d);
|
|
||||||
h = dictHashKey(d, key);
|
|
||||||
|
|
||||||
for (table = 0; table <= 1; table++) {
|
|
||||||
idx = h & d->ht[table].sizemask;
|
|
||||||
he = d->ht[table].table[idx];
|
|
||||||
prevHe = NULL;
|
|
||||||
while(he) {
|
|
||||||
if (dictCompareKeys(d, key, he->key)) {
|
|
||||||
/* Unlink the element from the list */
|
|
||||||
if (prevHe)
|
|
||||||
prevHe->next = he->next;
|
|
||||||
else
|
|
||||||
d->ht[table].table[idx] = he->next;
|
|
||||||
if (!nofree) {
|
|
||||||
dictFreeKey(d, he);
|
|
||||||
dictFreeVal(d, he);
|
|
||||||
}
|
|
||||||
free(he);
|
|
||||||
d->ht[table].used--;
|
|
||||||
return DICT_OK;
|
|
||||||
}
|
|
||||||
prevHe = he;
|
|
||||||
he = he->next;
|
|
||||||
}
|
|
||||||
if (!dictIsRehashing(d)) break;
|
|
||||||
}
|
|
||||||
return DICT_ERR; /* not found */
|
|
||||||
}
|
|
||||||
|
|
||||||
int dictDelete(dict *ht, const void *key) {
|
|
||||||
return dictGenericDelete(ht,key,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int dictDeleteNoFree(dict *ht, const void *key) {
|
|
||||||
return dictGenericDelete(ht,key,1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroy an entire dictionary */
|
|
||||||
int _dictClear(dict *d, dictht *ht)
|
|
||||||
{
|
|
||||||
unsigned long i;
|
|
||||||
|
|
||||||
/* Free all the elements */
|
|
||||||
for (i = 0; i < ht->size && ht->used > 0; i++) {
|
|
||||||
dictEntry *he, *nextHe;
|
|
||||||
|
|
||||||
if ((he = ht->table[i]) == NULL) continue;
|
|
||||||
while(he) {
|
|
||||||
nextHe = he->next;
|
|
||||||
dictFreeKey(d, he);
|
|
||||||
dictFreeVal(d, he);
|
|
||||||
free(he);
|
|
||||||
ht->used--;
|
|
||||||
he = nextHe;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Free the table and the allocated cache structure */
|
|
||||||
free(ht->table);
|
|
||||||
/* Re-initialize the table */
|
|
||||||
_dictReset(ht);
|
|
||||||
return DICT_OK; /* never fails */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear & Release the hash table */
|
|
||||||
void dictRelease(dict *d)
|
|
||||||
{
|
|
||||||
_dictClear(d,&d->ht[0]);
|
|
||||||
_dictClear(d,&d->ht[1]);
|
|
||||||
free(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
dictEntry *dictFind(dict *d, const void *key)
|
|
||||||
{
|
|
||||||
dictEntry *he;
|
|
||||||
unsigned int h, idx, table;
|
|
||||||
|
|
||||||
if (d->ht[0].size == 0) return NULL; /* We don't have a table at all */
|
|
||||||
if (dictIsRehashing(d)) _dictRehashStep(d);
|
|
||||||
h = dictHashKey(d, key);
|
|
||||||
for (table = 0; table <= 1; table++) {
|
|
||||||
idx = h & d->ht[table].sizemask;
|
|
||||||
he = d->ht[table].table[idx];
|
|
||||||
while(he) {
|
|
||||||
if (dictCompareKeys(d, key, he->key))
|
|
||||||
return he;
|
|
||||||
he = he->next;
|
|
||||||
}
|
|
||||||
if (!dictIsRehashing(d)) return NULL;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *dictFetchValue(dict *d, const void *key) {
|
|
||||||
dictEntry *he;
|
|
||||||
|
|
||||||
he = dictFind(d,key);
|
|
||||||
return he ? dictGetVal(he) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
dictIterator *dictGetIterator(dict *d)
|
|
||||||
{
|
|
||||||
dictIterator *iter = (dictIterator*)malloc(sizeof(*iter));
|
|
||||||
|
|
||||||
iter->d = d;
|
|
||||||
iter->table = 0;
|
|
||||||
iter->index = -1;
|
|
||||||
iter->safe = 0;
|
|
||||||
iter->entry = NULL;
|
|
||||||
iter->nextEntry = NULL;
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
dictIterator *dictGetSafeIterator(dict *d) {
|
|
||||||
dictIterator *i = dictGetIterator(d);
|
|
||||||
|
|
||||||
i->safe = 1;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
dictEntry *dictNext(dictIterator *iter)
|
|
||||||
{
|
|
||||||
while (1) {
|
|
||||||
if (iter->entry == NULL) {
|
|
||||||
dictht *ht = &iter->d->ht[iter->table];
|
|
||||||
if (iter->safe && iter->index == -1 && iter->table == 0)
|
|
||||||
iter->d->iterators++;
|
|
||||||
iter->index++;
|
|
||||||
if (iter->index >= (signed) ht->size) {
|
|
||||||
if (dictIsRehashing(iter->d) && iter->table == 0) {
|
|
||||||
iter->table++;
|
|
||||||
iter->index = 0;
|
|
||||||
ht = &iter->d->ht[1];
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iter->entry = ht->table[iter->index];
|
|
||||||
} else {
|
|
||||||
iter->entry = iter->nextEntry;
|
|
||||||
}
|
|
||||||
if (iter->entry) {
|
|
||||||
/* We need to save the 'next' here, the iterator user
|
|
||||||
* may delete the entry we are returning. */
|
|
||||||
iter->nextEntry = iter->entry->next;
|
|
||||||
return iter->entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dictReleaseIterator(dictIterator *iter)
|
|
||||||
{
|
|
||||||
if (iter->safe && !(iter->index == -1 && iter->table == 0))
|
|
||||||
iter->d->iterators--;
|
|
||||||
free(iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a random entry from the hash table. Useful to
|
|
||||||
* implement randomized algorithms */
|
|
||||||
dictEntry *dictGetRandomKey(dict *d)
|
|
||||||
{
|
|
||||||
dictEntry *he, *orighe;
|
|
||||||
unsigned int h;
|
|
||||||
int listlen, listele;
|
|
||||||
|
|
||||||
if (dictSize(d) == 0) return NULL;
|
|
||||||
if (dictIsRehashing(d)) _dictRehashStep(d);
|
|
||||||
if (dictIsRehashing(d)) {
|
|
||||||
do {
|
|
||||||
h = random() % (d->ht[0].size+d->ht[1].size);
|
|
||||||
he = (h >= d->ht[0].size) ? d->ht[1].table[h - d->ht[0].size] :
|
|
||||||
d->ht[0].table[h];
|
|
||||||
} while(he == NULL);
|
|
||||||
} else {
|
|
||||||
do {
|
|
||||||
h = random() & d->ht[0].sizemask;
|
|
||||||
he = d->ht[0].table[h];
|
|
||||||
} while(he == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now we found a non empty bucket, but it is a linked
|
|
||||||
* list and we need to get a random element from the list.
|
|
||||||
* The only sane way to do so is counting the elements and
|
|
||||||
* select a random index. */
|
|
||||||
listlen = 0;
|
|
||||||
orighe = he;
|
|
||||||
while(he) {
|
|
||||||
he = he->next;
|
|
||||||
listlen++;
|
|
||||||
}
|
|
||||||
listele = random() % listlen;
|
|
||||||
he = orighe;
|
|
||||||
while(listele--) he = he->next;
|
|
||||||
return he;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------- private functions ------------------------------ */
|
|
||||||
|
|
||||||
/* Expand the hash table if needed */
|
|
||||||
static int _dictExpandIfNeeded(dict *d)
|
|
||||||
{
|
|
||||||
/* Incremental rehashing already in progress. Return. */
|
|
||||||
if (dictIsRehashing(d)) return DICT_OK;
|
|
||||||
|
|
||||||
/* If the hash table is empty expand it to the initial size. */
|
|
||||||
if (d->ht[0].size == 0) return dictExpand(d, DICT_HT_INITIAL_SIZE);
|
|
||||||
|
|
||||||
/* If we reached the 1:1 ratio, and we are allowed to resize the hash
|
|
||||||
* table (global setting) or we should avoid it but the ratio between
|
|
||||||
* elements/buckets is over the "safe" threshold, we resize doubling
|
|
||||||
* the number of buckets. */
|
|
||||||
if (d->ht[0].used >= d->ht[0].size &&
|
|
||||||
(dict_can_resize ||
|
|
||||||
d->ht[0].used/d->ht[0].size > dict_force_resize_ratio))
|
|
||||||
{
|
|
||||||
return dictExpand(d, ((d->ht[0].size > d->ht[0].used) ?
|
|
||||||
d->ht[0].size : d->ht[0].used)*2);
|
|
||||||
}
|
|
||||||
return DICT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Our hash table capability is a power of two */
|
|
||||||
static unsigned long _dictNextPower(unsigned long size)
|
|
||||||
{
|
|
||||||
unsigned long i = DICT_HT_INITIAL_SIZE;
|
|
||||||
|
|
||||||
if (size >= LONG_MAX) return LONG_MAX;
|
|
||||||
while(1) {
|
|
||||||
if (i >= size)
|
|
||||||
return i;
|
|
||||||
i *= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns the index of a free slot that can be populated with
|
|
||||||
* an hash entry for the given 'key'.
|
|
||||||
* If the key already exists, -1 is returned.
|
|
||||||
*
|
|
||||||
* Note that if we are in the process of rehashing the hash table, the
|
|
||||||
* index is always returned in the context of the second (new) hash table. */
|
|
||||||
static int _dictKeyIndex(dict *d, const void *key)
|
|
||||||
{
|
|
||||||
unsigned int h, idx, table;
|
|
||||||
dictEntry *he;
|
|
||||||
|
|
||||||
/* Expand the hash table if needed */
|
|
||||||
if (_dictExpandIfNeeded(d) == DICT_ERR)
|
|
||||||
return -1;
|
|
||||||
/* Compute the key hash value */
|
|
||||||
h = dictHashKey(d, key);
|
|
||||||
for (table = 0; table <= 1; table++) {
|
|
||||||
idx = h & d->ht[table].sizemask;
|
|
||||||
/* Search if this slot does not already contain the given key */
|
|
||||||
he = d->ht[table].table[idx];
|
|
||||||
while(he) {
|
|
||||||
if (dictCompareKeys(d, key, he->key))
|
|
||||||
return -1;
|
|
||||||
he = he->next;
|
|
||||||
}
|
|
||||||
if (!dictIsRehashing(d)) break;
|
|
||||||
}
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dictEmpty(dict *d) {
|
|
||||||
_dictClear(d,&d->ht[0]);
|
|
||||||
_dictClear(d,&d->ht[1]);
|
|
||||||
d->rehashidx = -1;
|
|
||||||
d->iterators = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dictEnableResize(void) {
|
|
||||||
dict_can_resize = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dictDisableResize(void) {
|
|
||||||
dict_can_resize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
/* The following is code that we don't use for Redis currently, but that is part
|
|
||||||
of the library. */
|
|
||||||
|
|
||||||
/* ----------------------- Debugging ------------------------*/
|
|
||||||
|
|
||||||
#define DICT_STATS_VECTLEN 50
|
|
||||||
static void _dictPrintStatsHt(dictht *ht) {
|
|
||||||
unsigned long i, slots = 0, chainlen, maxchainlen = 0;
|
|
||||||
unsigned long totchainlen = 0;
|
|
||||||
unsigned long clvector[DICT_STATS_VECTLEN];
|
|
||||||
|
|
||||||
if (ht->used == 0) {
|
|
||||||
printf("No stats available for empty dictionaries\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < DICT_STATS_VECTLEN; i++) clvector[i] = 0;
|
|
||||||
for (i = 0; i < ht->size; i++) {
|
|
||||||
dictEntry *he;
|
|
||||||
|
|
||||||
if (ht->table[i] == NULL) {
|
|
||||||
clvector[0]++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
slots++;
|
|
||||||
/* For each hash entry on this slot... */
|
|
||||||
chainlen = 0;
|
|
||||||
he = ht->table[i];
|
|
||||||
while(he) {
|
|
||||||
chainlen++;
|
|
||||||
he = he->next;
|
|
||||||
}
|
|
||||||
clvector[(chainlen < DICT_STATS_VECTLEN) ? chainlen : (DICT_STATS_VECTLEN-1)]++;
|
|
||||||
if (chainlen > maxchainlen) maxchainlen = chainlen;
|
|
||||||
totchainlen += chainlen;
|
|
||||||
}
|
|
||||||
printf("Hash table stats:\n");
|
|
||||||
printf(" table size: %ld\n", ht->size);
|
|
||||||
printf(" number of elements: %ld\n", ht->used);
|
|
||||||
printf(" different slots: %ld\n", slots);
|
|
||||||
printf(" max chain length: %ld\n", maxchainlen);
|
|
||||||
printf(" avg chain length (counted): %.02f\n", (float)totchainlen/slots);
|
|
||||||
printf(" avg chain length (computed): %.02f\n", (float)ht->used/slots);
|
|
||||||
printf(" Chain length distribution:\n");
|
|
||||||
for (i = 0; i < DICT_STATS_VECTLEN-1; i++) {
|
|
||||||
if (clvector[i] == 0) continue;
|
|
||||||
printf(" %s%ld: %ld (%.02f%%)\n",(i == DICT_STATS_VECTLEN-1)?">= ":"", i, clvector[i], ((float)clvector[i]/ht->size)*100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dictPrintStats(dict *d) {
|
|
||||||
_dictPrintStatsHt(&d->ht[0]);
|
|
||||||
if (dictIsRehashing(d)) {
|
|
||||||
printf("-- Rehashing into ht[1]:\n");
|
|
||||||
_dictPrintStatsHt(&d->ht[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------- StringCopy Hash Table Type ------------------------*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static unsigned int _dictStringCopyHTHashFunction(const void *key)
|
|
||||||
{
|
|
||||||
return dictGenHashFunction(key, strlen((const char*)key));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *_dictStringDup(void *privdata, const void *key)
|
|
||||||
{
|
|
||||||
int len = strlen((const char*)key);
|
|
||||||
char *copy = (char*)malloc(len+1);
|
|
||||||
DICT_NOTUSED(privdata);
|
|
||||||
|
|
||||||
memcpy(copy, key, len);
|
|
||||||
copy[len] = '\0';
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _dictStringCopyHTKeyCompare(void *privdata, const void *key1,
|
|
||||||
const void *key2)
|
|
||||||
{
|
|
||||||
DICT_NOTUSED(privdata);
|
|
||||||
|
|
||||||
return strcmp((const char*)key1, (const char*)key2) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _dictStringDestructor(void *privdata, void *key)
|
|
||||||
{
|
|
||||||
DICT_NOTUSED(privdata);
|
|
||||||
|
|
||||||
free(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
dictType dictTypeHeapStringCopyKey = {
|
|
||||||
_dictStringCopyHTHashFunction, /* hash function */
|
|
||||||
_dictStringDup, /* key dup */
|
|
||||||
NULL, /* val dup */
|
|
||||||
_dictStringCopyHTKeyCompare, /* key compare */
|
|
||||||
_dictStringDestructor, /* key destructor */
|
|
||||||
NULL /* val destructor */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* This is like StringCopy but does not auto-duplicate the key.
|
|
||||||
* It's used for intepreter's shared strings. */
|
|
||||||
dictType dictTypeHeapStrings = {
|
|
||||||
_dictStringCopyHTHashFunction, /* hash function */
|
|
||||||
NULL, /* key dup */
|
|
||||||
NULL, /* val dup */
|
|
||||||
_dictStringCopyHTKeyCompare, /* key compare */
|
|
||||||
_dictStringDestructor, /* key destructor */
|
|
||||||
NULL /* val destructor */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* This is like StringCopy but also automatically handle dynamic
|
|
||||||
* allocated C strings as values. */
|
|
||||||
dictType dictTypeHeapStringCopyKeyValue = {
|
|
||||||
_dictStringCopyHTHashFunction, /* hash function */
|
|
||||||
_dictStringDup, /* key dup */
|
|
||||||
_dictStringDup, /* val dup */
|
|
||||||
_dictStringCopyHTKeyCompare, /* key compare */
|
|
||||||
_dictStringDestructor, /* key destructor */
|
|
||||||
_dictStringDestructor, /* val destructor */
|
|
||||||
};
|
|
@ -1,181 +0,0 @@
|
|||||||
/* Hash Tables Implementation.
|
|
||||||
*
|
|
||||||
* This file implements in-memory hash tables with insert/del/replace/find/
|
|
||||||
* get-random-element operations. Hash tables will auto-resize if needed
|
|
||||||
* tables of power of two in size are used, collisions are handled by
|
|
||||||
* chaining. See the source code for more information... :)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* * 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.
|
|
||||||
* * Neither the name of Redis nor the names of its contributors may be used
|
|
||||||
* to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifndef __DICT_H
|
|
||||||
#define __DICT_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DICT_OK 0
|
|
||||||
#define DICT_ERR 1
|
|
||||||
|
|
||||||
/* Unused arguments generate annoying warnings... */
|
|
||||||
#define DICT_NOTUSED(V) ((void) V)
|
|
||||||
|
|
||||||
typedef struct dictEntry {
|
|
||||||
void *key;
|
|
||||||
union {
|
|
||||||
void *val;
|
|
||||||
uint64_t u64;
|
|
||||||
int64_t s64;
|
|
||||||
} v;
|
|
||||||
struct dictEntry *next;
|
|
||||||
} dictEntry;
|
|
||||||
|
|
||||||
typedef struct dictType {
|
|
||||||
unsigned int (*hashFunction)(const void *key);
|
|
||||||
void *(*keyDup)(void *privdata, const void *key);
|
|
||||||
void *(*valDup)(void *privdata, const void *obj);
|
|
||||||
int (*keyCompare)(void *privdata, const void *key1, const void *key2);
|
|
||||||
void (*keyDestructor)(void *privdata, void *key);
|
|
||||||
void (*valDestructor)(void *privdata, void *obj);
|
|
||||||
} dictType;
|
|
||||||
|
|
||||||
/* This is our hash table structure. Every dictionary has two of this as we
|
|
||||||
* implement incremental rehashing, for the old to the new table. */
|
|
||||||
typedef struct dictht {
|
|
||||||
dictEntry **table;
|
|
||||||
unsigned long size;
|
|
||||||
unsigned long sizemask;
|
|
||||||
unsigned long used;
|
|
||||||
} dictht;
|
|
||||||
|
|
||||||
typedef struct dict {
|
|
||||||
dictType *type;
|
|
||||||
void *privdata;
|
|
||||||
dictht ht[2];
|
|
||||||
int rehashidx; /* rehashing not in progress if rehashidx == -1 */
|
|
||||||
int iterators; /* number of iterators currently running */
|
|
||||||
} dict;
|
|
||||||
|
|
||||||
/* If safe is set to 1 this is a safe iterator, that means, you can call
|
|
||||||
* dictAdd, dictFind, and other functions against the dictionary even while
|
|
||||||
* iterating. Otherwise it is a non safe iterator, and only dictNext()
|
|
||||||
* should be called while iterating. */
|
|
||||||
typedef struct dictIterator {
|
|
||||||
dict *d;
|
|
||||||
int table, index, safe;
|
|
||||||
dictEntry *entry, *nextEntry;
|
|
||||||
} dictIterator;
|
|
||||||
|
|
||||||
/* This is the initial size of every hash table */
|
|
||||||
#define DICT_HT_INITIAL_SIZE 4
|
|
||||||
|
|
||||||
/* ------------------------------- Macros ------------------------------------*/
|
|
||||||
#define dictFreeVal(d, entry) \
|
|
||||||
if ((d)->type->valDestructor) \
|
|
||||||
(d)->type->valDestructor((d)->privdata, (entry)->v.val)
|
|
||||||
|
|
||||||
#define dictSetVal(d, entry, _val_) do { \
|
|
||||||
if ((d)->type->valDup) \
|
|
||||||
entry->v.val = (d)->type->valDup((d)->privdata, _val_); \
|
|
||||||
else \
|
|
||||||
entry->v.val = (_val_); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define dictSetSignedIntegerVal(entry, _val_) \
|
|
||||||
do { entry->v.s64 = _val_; } while(0)
|
|
||||||
|
|
||||||
#define dictSetUnsignedIntegerVal(entry, _val_) \
|
|
||||||
do { entry->v.u64 = _val_; } while(0)
|
|
||||||
|
|
||||||
#define dictFreeKey(d, entry) \
|
|
||||||
if ((d)->type->keyDestructor) \
|
|
||||||
(d)->type->keyDestructor((d)->privdata, (entry)->key)
|
|
||||||
|
|
||||||
#define dictSetKey(d, entry, _key_) do { \
|
|
||||||
if ((d)->type->keyDup) \
|
|
||||||
entry->key = (d)->type->keyDup((d)->privdata, _key_); \
|
|
||||||
else \
|
|
||||||
entry->key = (_key_); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define dictCompareKeys(d, key1, key2) \
|
|
||||||
(((d)->type->keyCompare) ? \
|
|
||||||
(d)->type->keyCompare((d)->privdata, key1, key2) : \
|
|
||||||
(key1) == (key2))
|
|
||||||
|
|
||||||
#define dictHashKey(d, key) (d)->type->hashFunction(key)
|
|
||||||
#define dictGetKey(he) ((he)->key)
|
|
||||||
#define dictGetVal(he) ((he)->v.val)
|
|
||||||
#define dictGetSignedIntegerVal(he) ((he)->v.s64)
|
|
||||||
#define dictGetUnsignedIntegerVal(he) ((he)->v.u64)
|
|
||||||
#define dictSlots(d) ((d)->ht[0].size+(d)->ht[1].size)
|
|
||||||
#define dictSize(d) ((d)->ht[0].used+(d)->ht[1].used)
|
|
||||||
#define dictIsRehashing(ht) ((ht)->rehashidx != -1)
|
|
||||||
|
|
||||||
/* API */
|
|
||||||
dict *dictCreate(dictType *type, void *privDataPtr);
|
|
||||||
int dictExpand(dict *d, unsigned long size);
|
|
||||||
int dictAdd(dict *d, void *key, void *val);
|
|
||||||
dictEntry *dictAddRaw(dict *d, void *key);
|
|
||||||
int dictReplace(dict *d, void *key, void *val);
|
|
||||||
dictEntry *dictReplaceRaw(dict *d, void *key);
|
|
||||||
int dictDelete(dict *d, const void *key);
|
|
||||||
int dictDeleteNoFree(dict *d, const void *key);
|
|
||||||
void dictRelease(dict *d);
|
|
||||||
dictEntry * dictFind(dict *d, const void *key);
|
|
||||||
void *dictFetchValue(dict *d, const void *key);
|
|
||||||
int dictResize(dict *d);
|
|
||||||
dictIterator *dictGetIterator(dict *d);
|
|
||||||
dictIterator *dictGetSafeIterator(dict *d);
|
|
||||||
dictEntry *dictNext(dictIterator *iter);
|
|
||||||
void dictReleaseIterator(dictIterator *iter);
|
|
||||||
dictEntry *dictGetRandomKey(dict *d);
|
|
||||||
void dictPrintStats(dict *d);
|
|
||||||
unsigned int dictGenHashFunction(const void *key, int len);
|
|
||||||
unsigned int dictGenCaseHashFunction(const unsigned char *buf, int len);
|
|
||||||
void dictEmpty(dict *d);
|
|
||||||
void dictEnableResize(void);
|
|
||||||
void dictDisableResize(void);
|
|
||||||
int dictRehash(dict *d, int n);
|
|
||||||
int dictRehashMilliseconds(dict *d, int ms);
|
|
||||||
void dictSetHashFunctionSeed(unsigned int initval);
|
|
||||||
unsigned int dictGetHashFunctionSeed(void);
|
|
||||||
|
|
||||||
/* Hash table types */
|
|
||||||
extern dictType dictTypeHeapStringCopyKey;
|
|
||||||
extern dictType dictTypeHeapStrings;
|
|
||||||
extern dictType dictTypeHeapStringCopyKeyValue;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __DICT_H */
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,156 +0,0 @@
|
|||||||
#include "list.h"
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
List* CreateList()
|
|
||||||
{
|
|
||||||
List *list = (List*)malloc(sizeof(List));
|
|
||||||
if (NULL == list) return NULL;
|
|
||||||
|
|
||||||
list->head = list->tail = NULL;
|
|
||||||
list->size = 0;
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DestroyList(List* list)
|
|
||||||
{
|
|
||||||
ClearList(list);
|
|
||||||
free(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearList(List* list)
|
|
||||||
{
|
|
||||||
Node *pos = list->head;
|
|
||||||
while (NULL != pos)
|
|
||||||
{
|
|
||||||
Node *old = pos;
|
|
||||||
pos = pos->next;
|
|
||||||
free(old->data);
|
|
||||||
free(old);
|
|
||||||
}
|
|
||||||
list->head = list->tail = NULL;
|
|
||||||
list->size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PushBack(List* list, void* data)
|
|
||||||
{
|
|
||||||
if (NULL == list->tail) {
|
|
||||||
list->head = list->tail = (Node*)malloc(sizeof(Node));
|
|
||||||
if (!list->tail)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
list->tail->next = list->tail->prev = NULL;
|
|
||||||
list->tail->data = data;
|
|
||||||
++list->size;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node *newNode = (Node*)malloc(sizeof(Node));
|
|
||||||
if (!newNode)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
newNode->data = data;
|
|
||||||
newNode->next = NULL;
|
|
||||||
newNode->prev = list->tail;
|
|
||||||
list->tail->next = newNode;
|
|
||||||
list->tail = newNode;
|
|
||||||
++list->size;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PushFront(List* list, void* data)
|
|
||||||
{
|
|
||||||
if (NULL == list->head) {
|
|
||||||
list->head = list->tail = (Node*)malloc(sizeof(Node));
|
|
||||||
if (!list->tail)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
list->tail->next = list->tail->prev = NULL;
|
|
||||||
list->tail->data = data;
|
|
||||||
++list->size;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node *newNode = (Node*)malloc(sizeof(Node));
|
|
||||||
if (!newNode)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
newNode->data = data;
|
|
||||||
newNode->next = list->head;
|
|
||||||
newNode->prev = NULL;
|
|
||||||
list->head->prev = newNode;
|
|
||||||
list->head = newNode;
|
|
||||||
++list->size;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PopBack(List* list)
|
|
||||||
{
|
|
||||||
if (0 == list->size) return ;
|
|
||||||
--list->size;
|
|
||||||
|
|
||||||
if (list->head == list->tail) {
|
|
||||||
ClearList(list);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(list->tail->data);
|
|
||||||
list->tail = list->tail->prev;
|
|
||||||
free(list->tail->next);
|
|
||||||
list->tail->next = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PopFront(List* list)
|
|
||||||
{
|
|
||||||
if (0 == list->size) return ;
|
|
||||||
--list->size;
|
|
||||||
|
|
||||||
if (list->head == list->tail) {
|
|
||||||
ClearList(list);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(list->head->data);
|
|
||||||
list->head = list->head->next;
|
|
||||||
free(list->head->prev);
|
|
||||||
list->head->prev = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void* Back(List* list)
|
|
||||||
{
|
|
||||||
if (0 == list->size) return NULL;
|
|
||||||
return list->tail->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* Front(List* list)
|
|
||||||
{
|
|
||||||
if (0 == list->size) return NULL;
|
|
||||||
return list->head->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListIterator ListBegin(List* list)
|
|
||||||
{
|
|
||||||
if (!list->head) return NULL;
|
|
||||||
return &list->head->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListIterator ListNext(ListIterator itr)
|
|
||||||
{
|
|
||||||
if (!itr) return NULL;
|
|
||||||
Node *node = (Node*)itr;
|
|
||||||
if (!node->next) return NULL;
|
|
||||||
return &node->next->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Accumulate(List* list, int(*pred)(void* data))
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
Node *pos = list->head;
|
|
||||||
while (pos) {
|
|
||||||
result += pred(pos->data);
|
|
||||||
pos = pos->next;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
#ifndef __ASYNC_FCGI_LIST__
|
|
||||||
#define __ASYNC_FCGI_LIST__
|
|
||||||
|
|
||||||
typedef struct Node {
|
|
||||||
void *data;
|
|
||||||
struct Node *prev;
|
|
||||||
struct Node *next;
|
|
||||||
} Node;
|
|
||||||
|
|
||||||
typedef struct List {
|
|
||||||
Node *head;
|
|
||||||
Node *tail;
|
|
||||||
unsigned long size;
|
|
||||||
} List;
|
|
||||||
|
|
||||||
List* CreateList();
|
|
||||||
void DestroyList(List* list);
|
|
||||||
void ClearList(List* list);
|
|
||||||
int PushBack(List* list, void* data);
|
|
||||||
int PushFront(List* list, void* data);
|
|
||||||
void PopBack(List* list);
|
|
||||||
void PopFront(List* list);
|
|
||||||
void* Back(List* list);
|
|
||||||
void* Front(List* list);
|
|
||||||
|
|
||||||
// iterator
|
|
||||||
typedef void** ListIterator;
|
|
||||||
ListIterator ListBegin(List* list);
|
|
||||||
ListIterator ListNext(ListIterator itr);
|
|
||||||
|
|
||||||
// algorithm
|
|
||||||
int Accumulate(List* list, int(*pred)(void* data));
|
|
||||||
|
|
||||||
#endif //__ASYNC_FCGI_LIST__
|
|
Binary file not shown.
@ -1,132 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
||||||
|
|
||||||
#ifndef LOG_MAX_LEN
|
|
||||||
#define LOG_MAX_LEN 8192
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct logger_t {
|
|
||||||
int fd;
|
|
||||||
int level;
|
|
||||||
char* name;
|
|
||||||
}logger_t;
|
|
||||||
|
|
||||||
logger_t logger = {STDERR_FILENO, LOG_LEVEL_VERB, NULL};
|
|
||||||
|
|
||||||
static const char* strlevel[] = {
|
|
||||||
"ERROR",
|
|
||||||
"WARN",
|
|
||||||
"NOTICE",
|
|
||||||
"INFO",
|
|
||||||
"DEBUG",
|
|
||||||
"VERB"
|
|
||||||
};
|
|
||||||
|
|
||||||
void log_init(logger_t *log, const char* name, int level)
|
|
||||||
{
|
|
||||||
log->level = MAX(LOG_LEVEL_ERR, MIN(level, LOG_LEVEL_VERB));
|
|
||||||
if(name == NULL || *name == '\0'){
|
|
||||||
log->fd = STDERR_FILENO;
|
|
||||||
}else{
|
|
||||||
log->name = strdup(name);
|
|
||||||
if(log->name == NULL) {
|
|
||||||
log->fd = STDERR_FILENO;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log->fd = open(name, O_WRONLY | O_APPEND | O_CREAT, 0644);
|
|
||||||
if(log->fd < 0 ) {
|
|
||||||
log->fd = STDERR_FILENO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_deinit(logger_t *log)
|
|
||||||
{
|
|
||||||
if(log->fd > 0 && log->fd != STDERR_FILENO)
|
|
||||||
close(log->fd);
|
|
||||||
if(log->name)
|
|
||||||
free(log->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_write(logger_t *log, int level, const char *file, int line, const char* func, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
struct tm local;
|
|
||||||
struct timeval tv;
|
|
||||||
va_list args;
|
|
||||||
int len;
|
|
||||||
char buffer[LOG_MAX_LEN];
|
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
localtime_r(&tv.tv_sec, &local);
|
|
||||||
|
|
||||||
level = MAX(LOG_LEVEL_ERR, MIN(level, LOG_LEVEL_VERB));
|
|
||||||
|
|
||||||
len = snprintf(buffer, sizeof(buffer), "[%04d-%02d-%02d %02d:%02d:%02d.%06lu]|"
|
|
||||||
"%s|%s:%d:(%s):", local.tm_year+1900, local.tm_mon+1, local.tm_mday,
|
|
||||||
local.tm_hour, local.tm_min, local.tm_sec, tv.tv_usec,
|
|
||||||
strlevel[level], file, line, func);
|
|
||||||
|
|
||||||
if(len < LOG_MAX_LEN - 1){
|
|
||||||
va_start(args, fmt);
|
|
||||||
len += vsnprintf(buffer + len, LOG_MAX_LEN-len, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
len = (len >= LOG_MAX_LEN ? LOG_MAX_LEN - 1 : len);
|
|
||||||
}else{
|
|
||||||
len = LOG_MAX_LEN - 1;
|
|
||||||
}
|
|
||||||
buffer[len++] = '\n';
|
|
||||||
len = write(log->fd, buffer, len);
|
|
||||||
(void)len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int log_loggable(logger_t *log, int level)
|
|
||||||
{
|
|
||||||
if(level > log->level || level < 0)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_level_set(logger_t *log, int level)
|
|
||||||
{
|
|
||||||
log->level = MAX(LOG_LEVEL_ERR, MIN(level, LOG_LEVEL_VERB));
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_reopen(logger_t *log)
|
|
||||||
{
|
|
||||||
if(log->fd > 0 && log->fd != STDERR_FILENO){
|
|
||||||
close(log->fd);
|
|
||||||
log->fd = open(log->name, O_WRONLY | O_APPEND | O_CREAT, 0644);
|
|
||||||
if(log->fd < 0) {
|
|
||||||
log->fd = STDERR_FILENO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_level_up(logger_t *log)
|
|
||||||
{
|
|
||||||
if(log->level < LOG_LEVEL_VERB)
|
|
||||||
log->level++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_level_down(logger_t *log)
|
|
||||||
{
|
|
||||||
if(log->level > LOG_LEVEL_ERR)
|
|
||||||
log->level--;
|
|
||||||
}
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* =====================================================================================
|
|
||||||
*
|
|
||||||
* Filename: logger.h
|
|
||||||
*
|
|
||||||
* Description: 日志接口
|
|
||||||
*
|
|
||||||
* Version: 1.0
|
|
||||||
* Created: 2013年08月20日 20时09分00秒
|
|
||||||
* Revision: none
|
|
||||||
* Compiler: gcc
|
|
||||||
*
|
|
||||||
* Author: xiaoboyu,
|
|
||||||
* Organization:
|
|
||||||
*
|
|
||||||
* =====================================================================================
|
|
||||||
*/
|
|
||||||
#ifndef __LOGGER_H__
|
|
||||||
#define __LOGGER_H__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum LogLevelTypes //日志分级
|
|
||||||
{
|
|
||||||
LOG_LEVEL_ERR, /* error conditions */
|
|
||||||
LOG_LEVEL_WARN, /* warning conditions */
|
|
||||||
LOG_LEVEL_NOTICE,
|
|
||||||
LOG_LEVEL_INFO,
|
|
||||||
LOG_LEVEL_DEBUG,
|
|
||||||
LOG_LEVEL_VERB
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct logger_t logger_t;
|
|
||||||
|
|
||||||
extern logger_t logger;
|
|
||||||
|
|
||||||
#define log_error(fmt, ...) \
|
|
||||||
do{ \
|
|
||||||
if(log_loggable(&logger, LOG_LEVEL_ERR)){ \
|
|
||||||
log_write(&logger, LOG_LEVEL_ERR, __FILE__, __LINE__, __FUNCTION__, \
|
|
||||||
fmt, ## __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
#define log_warn(fmt, ...) \
|
|
||||||
do{ \
|
|
||||||
if(log_loggable(&logger, LOG_LEVEL_WARN)){ \
|
|
||||||
log_write(&logger, LOG_LEVEL_WARN, __FILE__, __LINE__, __FUNCTION__, \
|
|
||||||
fmt, ## __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define log_notice(fmt, ...) \
|
|
||||||
do{ \
|
|
||||||
if(log_loggable(&logger, LOG_LEVEL_NOTICE)){ \
|
|
||||||
log_write(&logger, LOG_LEVEL_NOTICE, __FILE__, __LINE__, __FUNCTION__, \
|
|
||||||
fmt, ## __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define log_info(fmt, ...) \
|
|
||||||
do{ \
|
|
||||||
if(log_loggable(&logger, LOG_LEVEL_INFO)){ \
|
|
||||||
log_write(&logger, LOG_LEVEL_INFO, __FILE__, __LINE__, __FUNCTION__, \
|
|
||||||
fmt, ## __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define log_debug(fmt, ...) \
|
|
||||||
do{ \
|
|
||||||
if(log_loggable(&logger, LOG_LEVEL_DEBUG)){ \
|
|
||||||
log_write(&logger, LOG_LEVEL_DEBUG, __FILE__, __LINE__, __FUNCTION__, \
|
|
||||||
fmt, ## __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define log_verb(fmt, ...) \
|
|
||||||
do{ \
|
|
||||||
if(log_loggable(&logger, LOG_LEVEL_VERB)){ \
|
|
||||||
log_write(&logger, LOG_LEVEL_VERB, __FILE__, __LINE__, __FUNCTION__, \
|
|
||||||
fmt, ## __VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
void log_init(logger_t *log, const char *name, int level);
|
|
||||||
|
|
||||||
void log_deinit(logger_t *log);
|
|
||||||
/*
|
|
||||||
* @brief 设置log的级别
|
|
||||||
*/
|
|
||||||
void log_level_set(logger_t *log, int level);
|
|
||||||
|
|
||||||
void log_reopen(logger_t *log);
|
|
||||||
|
|
||||||
void log_level_up(logger_t *log);
|
|
||||||
|
|
||||||
void log_level_down(logger_t *log);
|
|
||||||
|
|
||||||
int log_loggable(logger_t *log, int level);
|
|
||||||
|
|
||||||
void log_write(logger_t *log, int level,
|
|
||||||
const char *file, int line,
|
|
||||||
const char* func, const char *fmt, ...)
|
|
||||||
__attribute__((format(printf, 6, 7)));
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif // ~LOGGER_H_201106241335
|
|
||||||
|
|
Binary file not shown.
@ -1,84 +0,0 @@
|
|||||||
[2015-04-25 16:56:36.580062]|WARN|archive.c:61:(LoadFromFile):not found archive file:data, please confirm SDK is first startup.
|
|
||||||
[2015-04-25 16:56:36.581785]|INFO|config.c:68:(next_status):set status to eStatus_Redirect
|
|
||||||
[2015-04-25 16:56:36.612831]|INFO|redirect.c:72:(NebulaRedirect):HTTPS POST. url=https://172.16.82.71/push/redirect, params=uid=1000000010000001&nonce=y9757acx1eve7nmoigsz8fxqqqvjj&ts=1429952196&sign=ee056e8ea53f7f34133acd13e9996db9
|
|
||||||
[2015-04-25 16:56:36.627771]|INFO|redirect.c:79:(NebulaRedirect):curl_easy_perform success. response={"code":200,"hostlist":[{"ip":"172.16.82.71","port":8080}],"md5_daa":{"rule":"ssh","salt":"helloworld123"}}
|
|
||||||
|
|
||||||
[2015-04-25 16:56:36.627834]|INFO|config.c:68:(next_status):set status to eStatus_LoopTest
|
|
||||||
[2015-04-25 16:56:36.658189]|INFO|config.c:68:(next_status):set status to eStatus_Connect
|
|
||||||
[2015-04-25 16:56:36.689965]|INFO|connect.c:147:(NebulaConnect):connect to server:172.16.82.71:8080
|
|
||||||
[2015-04-25 16:56:36.690038]|INFO|config.c:68:(next_status):set status to eStatus_Connecting
|
|
||||||
[2015-04-25 16:56:36.690781]|INFO|connect.c:27:(__on_connect):connect success, server_addr:172.16.82.71:8080
|
|
||||||
[2015-04-25 16:56:36.690820]|INFO|config.c:68:(next_status):set status to eStatus_Auth1
|
|
||||||
[2015-04-25 16:56:36.691082]|DEBUG|connect.c:173:(NebulaSend):NEBULA TX REQ AUTH|0
|
|
||||||
[2015-04-25 16:56:36.691119]|INFO|config.c:68:(next_status):set status to eStatus_Auth2
|
|
||||||
[2015-04-25 16:56:51.803531]|WARN|archive.c:61:(LoadFromFile):not found archive file:data, please confirm SDK is first startup.
|
|
||||||
[2015-04-25 16:56:51.805066]|INFO|config.c:68:(next_status):set status to eStatus_Redirect
|
|
||||||
[2015-04-25 16:56:51.846343]|INFO|redirect.c:72:(NebulaRedirect):HTTPS POST. url=https://172.16.82.71/push/redirect, params=uid=1000000010000001&nonce=y9757acx1eve7nmoigsz8fxqqqvjj&ts=1429952211&sign=9c3a7e4b592185d7caca49bf5edde4ed
|
|
||||||
[2015-04-25 16:56:51.883981]|INFO|redirect.c:79:(NebulaRedirect):curl_easy_perform success. response={"code":200,"hostlist":[{"ip":"172.16.82.71","port":8080}],"md5_daa":{"rule":"ssh","salt":"helloworld123"}}
|
|
||||||
|
|
||||||
[2015-04-25 16:56:51.884123]|INFO|config.c:68:(next_status):set status to eStatus_LoopTest
|
|
||||||
[2015-04-25 16:56:51.918477]|INFO|config.c:68:(next_status):set status to eStatus_Connect
|
|
||||||
[2015-04-25 16:56:51.950683]|INFO|connect.c:147:(NebulaConnect):connect to server:172.16.82.71:8080
|
|
||||||
[2015-04-25 16:56:51.950752]|INFO|config.c:68:(next_status):set status to eStatus_Connecting
|
|
||||||
[2015-04-25 16:57:26.466943]|INFO|connect.c:27:(__on_connect):connect success, server_addr:172.16.82.71:8080
|
|
||||||
[2015-04-25 16:57:26.467027]|INFO|config.c:68:(next_status):set status to eStatus_Auth1
|
|
||||||
[2015-04-25 16:57:26.467247]|DEBUG|connect.c:173:(NebulaSend):NEBULA TX REQ AUTH|0
|
|
||||||
[2015-04-25 16:57:26.467282]|INFO|config.c:68:(next_status):set status to eStatus_Auth2
|
|
||||||
[2015-04-25 16:58:47.906217]|WARN|archive.c:61:(LoadFromFile):not found archive file:data, please confirm SDK is first startup.
|
|
||||||
[2015-04-25 16:58:47.910534]|INFO|config.c:68:(next_status):set status to eStatus_Redirect
|
|
||||||
[2015-04-25 16:58:47.946543]|INFO|redirect.c:72:(NebulaRedirect):HTTPS POST. url=https://172.16.82.71/push/redirect, params=uid=1000000010000001&nonce=y9757acx1eve7nmoigsz8fxqqqvjj&ts=1429952327&sign=169862755b312f589844a5a00068758e
|
|
||||||
[2015-04-25 16:58:47.981548]|INFO|redirect.c:79:(NebulaRedirect):curl_easy_perform success. response={"code":200,"hostlist":[{"ip":"172.16.82.71","port":8080}],"md5_daa":{"rule":"ssh","salt":"helloworld123"}}
|
|
||||||
|
|
||||||
[2015-04-25 16:58:47.981695]|INFO|config.c:68:(next_status):set status to eStatus_LoopTest
|
|
||||||
[2015-04-25 16:58:48.002549]|INFO|config.c:68:(next_status):set status to eStatus_Connect
|
|
||||||
[2015-04-25 16:58:48.034797]|INFO|connect.c:147:(NebulaConnect):connect to server:172.16.82.71:8080
|
|
||||||
[2015-04-25 16:58:48.034868]|INFO|config.c:68:(next_status):set status to eStatus_Connecting
|
|
||||||
[2015-04-25 16:58:50.241148]|INFO|connect.c:27:(__on_connect):connect success, server_addr:172.16.82.71:8080
|
|
||||||
[2015-04-25 16:58:50.241215]|INFO|config.c:68:(next_status):set status to eStatus_Auth1
|
|
||||||
[2015-04-25 16:58:50.241412]|DEBUG|connect.c:173:(NebulaSend):NEBULA TX REQ AUTH|0
|
|
||||||
[2015-04-25 16:58:50.241477]|INFO|config.c:68:(next_status):set status to eStatus_Auth2
|
|
||||||
[2015-04-25 17:13:02.157390]|WARN|archive.c:61:(LoadFromFile):not found archive file:data, please confirm SDK is first startup.
|
|
||||||
[2015-04-25 17:13:02.159225]|INFO|config.c:68:(next_status):set status to eStatus_Redirect
|
|
||||||
[2015-04-25 17:13:02.200990]|INFO|redirect.c:72:(NebulaRedirect):HTTPS POST. url=https://172.16.82.71/push/redirect, params=uid=1000000010000001&nonce=y9757acx1eve7nmoigsz8fxqqqvjj&ts=1429953182&sign=229164191ed48bd6addc3c08a5c2b830
|
|
||||||
[2015-04-25 17:13:02.237796]|INFO|redirect.c:79:(NebulaRedirect):curl_easy_perform success. response={"code":200,"hostlist":[{"ip":"172.16.82.71","port":8080}],"md5_daa":{"rule":"ssh","salt":"helloworld123"}}
|
|
||||||
|
|
||||||
[2015-04-25 17:13:02.237916]|INFO|config.c:68:(next_status):set status to eStatus_LoopTest
|
|
||||||
[2015-04-25 17:13:02.272535]|INFO|config.c:68:(next_status):set status to eStatus_Connect
|
|
||||||
[2015-04-25 17:13:02.304833]|INFO|connect.c:148:(NebulaConnect):connect to server:172.16.82.71:8080
|
|
||||||
[2015-04-25 17:13:02.304906]|INFO|config.c:68:(next_status):set status to eStatus_Connecting
|
|
||||||
[2015-04-25 17:13:02.305742]|INFO|connect.c:27:(__on_connect):connect success, server_addr:172.16.82.71:8080
|
|
||||||
[2015-04-25 17:13:02.305792]|INFO|config.c:68:(next_status):set status to eStatus_Auth1
|
|
||||||
[2015-04-25 17:13:02.305981]|DEBUG|connect.c:174:(NebulaSend):NEBULA TX REQ AUTH|0
|
|
||||||
[2015-04-25 17:13:02.306013]|INFO|config.c:68:(next_status):set status to eStatus_Auth2
|
|
||||||
[2015-04-25 17:13:44.769793]|WARN|archive.c:61:(LoadFromFile):not found archive file:data, please confirm SDK is first startup.
|
|
||||||
[2015-04-25 17:13:44.771566]|INFO|config.c:68:(next_status):set status to eStatus_Redirect
|
|
||||||
[2015-04-25 17:13:44.798173]|INFO|redirect.c:72:(NebulaRedirect):HTTPS POST. url=https://172.16.82.71/push/redirect, params=uid=1000000010000001&nonce=y9757acx1eve7nmoigsz8fxqqqvjj&ts=1429953224&sign=12a08c8573a1b13cad7ee51a56bacc01
|
|
||||||
[2015-04-25 17:13:44.812564]|INFO|redirect.c:79:(NebulaRedirect):curl_easy_perform success. response={"code":200,"hostlist":[{"ip":"172.16.82.71","port":8080}],"md5_daa":{"rule":"ssh","salt":"helloworld123"}}
|
|
||||||
|
|
||||||
[2015-04-25 17:13:44.812632]|INFO|config.c:68:(next_status):set status to eStatus_LoopTest
|
|
||||||
[2015-04-25 17:13:44.832927]|INFO|config.c:68:(next_status):set status to eStatus_Connect
|
|
||||||
[2015-04-30 11:53:58.699321]|WARN|archive.c:74:(LoadFromFile):not found archive file:data, please confirm SDK is first startup.
|
|
||||||
[2015-04-30 11:53:58.701844]|INFO|nebula_sdk.c:94:(__NebulaStart):set status to eStatus_Redirect
|
|
||||||
[2015-04-30 11:53:58.724325]|INFO|redirect.c:119:(NebulaRedirect):HTTPS POST. url=https://172.16.82.71/push/redirect, params=uid=1000000010000001&nonce=y9757acx1eve7nmoigsz8fxqqqvjj&ts=1430366038&sign=fd29cab41606e0ebd8a8abd8cf494d47
|
|
||||||
[2015-04-30 11:53:58.747141]|INFO|redirect.c:126:(NebulaRedirect):curl_easy_perform success. response={"code":200,"hostlist":[{"ip":"172.16.82.71","port":8080}],"md5_daa":{"rule":"ssh","salt":"helloworld123"}}
|
|
||||||
|
|
||||||
[2015-04-30 11:53:58.747230]|INFO|nebula_sdk.c:99:(__NebulaStart):set status to eStatus_LoopTest
|
|
||||||
[2015-04-30 11:53:58.767990]|INFO|nebula_sdk.c:107:(__NebulaStart):set status to eStatus_Connect
|
|
||||||
[2015-04-30 11:53:58.789117]|INFO|connect.c:159:(NebulaConnect):connect to server:172.16.82.71:8080
|
|
||||||
[2015-04-30 11:53:58.789144]|INFO|nebula_sdk.c:112:(__NebulaStart):set status to eStatus_Connecting
|
|
||||||
[2015-04-30 11:53:58.789429]|INFO|connect.c:31:(__on_connect):connect success, server_addr:172.16.82.71:8080
|
|
||||||
[2015-04-30 11:53:58.789442]|INFO|connect.c:34:(__on_connect):set status to eStatus_Auth1
|
|
||||||
[2015-04-30 11:53:58.789509]|DEBUG|net.c:143:(NebulaConnSend):NEBULA TX REQ AUTH|64
|
|
||||||
[2015-04-30 11:53:58.789517]|INFO|nebula_sdk.c:124:(__NebulaStart):set status to eStatus_Auth1_Waiting
|
|
||||||
[2015-04-30 11:53:58.790345]|DEBUG|connect.c:46:(__handle_message):NEBULA RX RSP AUTH|107
|
|
||||||
[2015-04-30 11:53:58.790382]|DEBUG|net.c:143:(NebulaConnSend):NEBULA TX REQ AUTH|142
|
|
||||||
[2015-04-30 11:53:58.790389]|INFO|auth.c:107:(OnAuth):set status to eStatus_Auth2
|
|
||||||
[2015-04-30 11:53:58.791374]|DEBUG|connect.c:46:(__handle_message):NEBULA RX RSP AUTH|31
|
|
||||||
[2015-04-30 11:53:58.791443]|INFO|auth.c:44:(OnAuth):set status to eStatus_Sub
|
|
||||||
[2015-04-30 11:53:58.791486]|DEBUG|net.c:143:(NebulaConnSend):NEBULA TX REQ SUB|45
|
|
||||||
[2015-04-30 11:53:58.795115]|DEBUG|connect.c:46:(__handle_message):NEBULA RX RSP SUB|77
|
|
||||||
[2015-04-30 11:53:58.795171]|INFO|subscribe.c:43:(OnSubSuccess):sub com.meizu.cloud success.
|
|
||||||
[2015-04-30 11:53:58.795188]|INFO|nebula_sdk.c:138:(__NebulaStart):set status to eStatus_Estab
|
|
||||||
[2015-04-30 11:53:58.983986]|DEBUG|net.c:143:(NebulaConnSend):NEBULA TX REQ PING|0
|
|
||||||
[2015-04-30 11:53:58.985083]|DEBUG|connect.c:46:(__handle_message):NEBULA RX RSP PING|0
|
|
||||||
[2015-04-30 11:53:58.985108]|DEBUG|connect.c:49:(__handle_message):pong.
|
|
@ -1,67 +0,0 @@
|
|||||||
#include "nebula_compress_uncompress_wrapper.h"
|
|
||||||
#include <snappy-c.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
int NebulaCompress(uint8_t type, const char* src, uint32_t src_len,
|
|
||||||
char *dst, uint32_t *dst_len)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
size_t _src_len = (size_t)src_len;
|
|
||||||
size_t _dst_len = (size_t)*dst_len;
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
case 1:
|
|
||||||
if (Z_OK != compress((uint8_t*)dst, &_dst_len, (uint8_t*)src, _src_len)) {
|
|
||||||
res = -1;
|
|
||||||
}else{
|
|
||||||
res = 0;
|
|
||||||
*dst_len = (uint32_t)_dst_len;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (0 != snappy_compress(src, _src_len, dst, &_dst_len)) {
|
|
||||||
res = -1;
|
|
||||||
}else{
|
|
||||||
res = 0;
|
|
||||||
*dst_len = (uint32_t)_dst_len;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaUnCompress(uint8_t type, const char* src, uint32_t src_len,
|
|
||||||
char *dst, uint32_t *dst_len)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
size_t _src_len = (size_t)src_len;
|
|
||||||
size_t _dst_len = (size_t)*dst_len;
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
case 1:
|
|
||||||
if (Z_OK != uncompress((uint8_t*)dst, &_dst_len, (uint8_t*)src, _src_len)) {
|
|
||||||
res = -1;
|
|
||||||
}else{
|
|
||||||
res = 0;
|
|
||||||
*dst_len = (uint32_t)_dst_len;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (0 != snappy_uncompress(src, _src_len, dst, &_dst_len)) {
|
|
||||||
res = -1;
|
|
||||||
}else{
|
|
||||||
res = 0;
|
|
||||||
*dst_len = (uint32_t)_dst_len;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* FileName: nebula_compress_uncompress_wrapper.h
|
|
||||||
* Description: 压缩和解压缩
|
|
||||||
* Version: 1.0
|
|
||||||
* History:
|
|
||||||
* yuxiaobo 2015-01-20 1.0 created
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
#ifndef __NEBULA_COMPRESS_UNCOMPRESS_H__
|
|
||||||
#define __NEBULA_COMPRESS_UNCOMPRESS_H__
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
int NebulaCompress(uint8_t type, const char* src, uint32_t src_len,
|
|
||||||
char *dst, uint32_t *dst_len);
|
|
||||||
|
|
||||||
int NebulaUnCompress(uint8_t type, const char* src, uint32_t src_len,
|
|
||||||
char *dst, uint32_t *dst_len);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Binary file not shown.
@ -1,58 +0,0 @@
|
|||||||
#include "nebula_encrypt_decrypt_wrapper.h"
|
|
||||||
#include "crypto_framwork.h"
|
|
||||||
|
|
||||||
int NebulaEncrypt(uint8_t type, const char *key, uint32_t key_len,
|
|
||||||
const char *src, uint32_t src_len,
|
|
||||||
char *dst, uint32_t* len)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
switch (type) {
|
|
||||||
case 1:
|
|
||||||
res = CRYPTO_encrypt_without_key((const uint8_t*)src, src_len, (uint8_t*)dst, len);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
res = CRYPTO1_encrypt((uint8_t*)key, key_len, (const uint8_t*)src,
|
|
||||||
src_len, (uint8_t*)dst, len);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
res = CRYPTO2_encrypt((uint8_t*)key, key_len, (const uint8_t*)src,
|
|
||||||
src_len, (uint8_t*)dst, len);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
res = CRYPTO3_encrypt((uint8_t*)key, key_len, (const uint8_t*)src,
|
|
||||||
src_len, (uint8_t*)dst, len);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaDecrypt(uint8_t type, const char *key, uint32_t key_len,
|
|
||||||
const char *src, uint32_t src_len,
|
|
||||||
char *dst, uint32_t* len)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
switch (type) {
|
|
||||||
case 1:
|
|
||||||
res = CRYPTO_decrypt_without_key((const uint8_t*)src, src_len, (uint8_t*)dst, len);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
res = CRYPTO1_decrypt((uint8_t*)key, key_len, (const uint8_t*)src,
|
|
||||||
src_len, (uint8_t*)dst, len);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
res = CRYPTO2_decrypt((uint8_t*)key, key_len, (const uint8_t*)src,
|
|
||||||
src_len, (uint8_t*)dst, len);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
res = CRYPTO3_decrypt((uint8_t*)key, key_len, (const uint8_t*)src,
|
|
||||||
src_len, (uint8_t*)dst, len);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* FileName:
|
|
||||||
* Description:
|
|
||||||
* Version:
|
|
||||||
* History:
|
|
||||||
* yuxiaobo 2014-12-25 1.0 created
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
#ifndef __NEBULA_ENCRYPT_DECRYPT_WRAPPER_H__
|
|
||||||
#define __NEBULA_ENCRYPT_DECRYPT_WRAPPER_H__
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 消息加密接口
|
|
||||||
* @param type 加密类型
|
|
||||||
* @param key 加密需要的key
|
|
||||||
* @param src 加密的原始数据
|
|
||||||
* @param dst 加密的结果数据
|
|
||||||
* @param len 加密后的数据长度
|
|
||||||
* @return 0 成功 其他 失败
|
|
||||||
*/
|
|
||||||
int NebulaEncrypt(uint8_t type, const char *key, uint32_t key_len,
|
|
||||||
const char *src, uint32_t src_len,
|
|
||||||
char *dst, uint32_t* len);
|
|
||||||
|
|
||||||
int NebulaDecrypt(uint8_t type, const char *key, uint32_t key_len,
|
|
||||||
const char *src, uint32_t src_len,
|
|
||||||
char *dst, uint32_t* len);
|
|
||||||
|
|
||||||
#endif
|
|
Binary file not shown.
@ -1,168 +0,0 @@
|
|||||||
#include "nebula_sdk.h"
|
|
||||||
#include <sys/file.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include "string.h"
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <json-c/json.h>
|
|
||||||
#include <openssl/md5.h>
|
|
||||||
#include "timer.h"
|
|
||||||
#include "str.h"
|
|
||||||
#include "logger.h"
|
|
||||||
#include "list.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "redirect.h"
|
|
||||||
#include "auth.h"
|
|
||||||
#include "subscribe.h"
|
|
||||||
#include "push.h"
|
|
||||||
#include "archive.h"
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "connect.h"
|
|
||||||
#include "net.h"
|
|
||||||
|
|
||||||
char* g_device_tag = NULL;
|
|
||||||
char* g_nebula_host = NULL;
|
|
||||||
NebulaMsgCallback g_nebula_cb[eNebulaMsg_Max] = {};
|
|
||||||
char* g_storage_file = NULL;
|
|
||||||
int g_started = 0;
|
|
||||||
timer_heap_t *g_timer;
|
|
||||||
List *g_server_list;
|
|
||||||
int g_sub_app_count = 0;
|
|
||||||
char** g_sub_apps = NULL;
|
|
||||||
|
|
||||||
int NebulaInit(const char* device_tag, const char* host, const char* file)
|
|
||||||
{
|
|
||||||
if (!g_timer)
|
|
||||||
g_timer = timer_heap_create(1024);
|
|
||||||
|
|
||||||
if (!g_server_list)
|
|
||||||
g_server_list = CreateList();
|
|
||||||
|
|
||||||
if (!device_tag || !host || !file) return -1;
|
|
||||||
if (!*device_tag || !*host || !*file) return -1;
|
|
||||||
g_device_tag = strdup(device_tag);
|
|
||||||
g_nebula_host = strdup(host);
|
|
||||||
g_storage_file = strdup(file);
|
|
||||||
|
|
||||||
log_init(&logger, "nebula.log", 4);
|
|
||||||
|
|
||||||
if (-1 == NebulaInitPush()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-1 == NebulaLoadFromFile(g_storage_file)) {
|
|
||||||
log_warn("load archive file failed...");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaSubScribe(int count, const char** app_name)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
if (g_sub_app_count) {
|
|
||||||
for (i = 0; i < g_sub_app_count; ++i) {
|
|
||||||
free(g_sub_apps[i]);
|
|
||||||
}
|
|
||||||
free(g_sub_apps);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_sub_app_count = count;
|
|
||||||
g_sub_apps = (char**)malloc(sizeof(char*) * g_sub_app_count);
|
|
||||||
for (i = 0; i < g_sub_app_count; ++i) {
|
|
||||||
g_sub_apps[i] = strdup(app_name[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NebulaMsgCallback NebulaRegister(NebulaMsgType type, NebulaMsgCallback cb)
|
|
||||||
{
|
|
||||||
NebulaMsgCallback old = g_nebula_cb[type];
|
|
||||||
g_nebula_cb[type] = cb;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* __NebulaStart(void* ptr)
|
|
||||||
{
|
|
||||||
(void)ptr;
|
|
||||||
|
|
||||||
NebulaInitAutoSave();
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
switch (Nebulaget_status()) {
|
|
||||||
case eStatus_Init:
|
|
||||||
next_status();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStatus_Redirect:
|
|
||||||
if (0 == NebulaRedirect()) {
|
|
||||||
next_status();
|
|
||||||
} else {
|
|
||||||
log_info("sleep 10 seconds, delay retry redirect.");
|
|
||||||
sleep(10);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStatus_LoopTest:
|
|
||||||
next_status();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStatus_Connect:
|
|
||||||
if (0 == NebulaConnect()) {
|
|
||||||
next_status();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStatus_Connecting:
|
|
||||||
// nothing to do.
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStatus_Auth1:
|
|
||||||
if (-1 == NebulaAuth1()) {
|
|
||||||
jump_status(eStatus_Redirect);
|
|
||||||
} else {
|
|
||||||
next_status();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStatus_Auth1_Waiting:
|
|
||||||
// nothing to do.
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStatus_Auth2:
|
|
||||||
// nothing to do.
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStatus_Sub:
|
|
||||||
if (0 == subscribe_loop()) {
|
|
||||||
next_status();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStatus_Estab:
|
|
||||||
// nothing to do. Looping...
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
timer_run(g_timer);
|
|
||||||
NebulaConnLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaStart()
|
|
||||||
{
|
|
||||||
if (g_started) return -1;
|
|
||||||
|
|
||||||
pthread_t pt;
|
|
||||||
int ret = pthread_create(&pt, NULL, __NebulaStart, NULL);
|
|
||||||
if (ret == 0) {
|
|
||||||
g_started = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
|||||||
#ifndef NEBULA_SDK_H
|
|
||||||
#define NEBULA_SDK_H
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
eNebulaMsg_Push, /// 推送 (路由器只需关心这一类消息)
|
|
||||||
eNebulaMsg_Presence, /// Presence
|
|
||||||
eNebulaMsg_Sms, /// 网络短信
|
|
||||||
eNebulaMsg_Mms, /// 网络彩信
|
|
||||||
eNebulaMsg_Max,
|
|
||||||
} NebulaMsgType;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** 初始化网络连接
|
|
||||||
* @device_tag: 硬件信息 (手机端为IMEI)
|
|
||||||
* @verify_pwd: 鉴权密码 (手机端为SN)
|
|
||||||
* @host: 服务端域名, 例如: https://p.meizu.com (结尾不要带"/", 前面要加上https)
|
|
||||||
* @file: 用于读取/存储持久化数据的文件名, 要求目录存在, 且有创建文件权限。
|
|
||||||
* @return: 如果文件打开成功, 返回0; 否则返回-1, 文件打开失败原因记录在错误码errno中.
|
|
||||||
* @只能调用一次, 重复调用无效并返回-1.
|
|
||||||
*/
|
|
||||||
int NebulaInit(const char* device_tag, const char* host, const char* file);
|
|
||||||
|
|
||||||
/** 设置订阅列表
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void NebulaSubScribe(int count, const char** app_name);
|
|
||||||
|
|
||||||
/** 消息处理回调函数
|
|
||||||
* @data: 数据块起始指针
|
|
||||||
* @len: 数据块长度
|
|
||||||
*/
|
|
||||||
typedef void (*NebulaMsgCallback)(const char* data, int len);
|
|
||||||
|
|
||||||
/** 注册消息处理回调函数
|
|
||||||
* @type: 消息类型
|
|
||||||
* @cb: 回调函数
|
|
||||||
* @return: 旧的回调函数
|
|
||||||
* @一次只能注册一个回调函数, 重复注册会覆盖.
|
|
||||||
*/
|
|
||||||
NebulaMsgCallback NebulaRegister(NebulaMsgType type, NebulaMsgCallback cb);
|
|
||||||
|
|
||||||
/** 启动
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int NebulaStart();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //NEBULA_SDK_H
|
|
||||||
|
|
Binary file not shown.
@ -1,333 +0,0 @@
|
|||||||
#include "net.h"
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/epoll.h>
|
|
||||||
#include <sys/fcntl.h>
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
#define EPOLL_SIZE 32
|
|
||||||
int g_epollfd = -1;
|
|
||||||
|
|
||||||
struct _NebulaBuf
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
int pos;
|
|
||||||
char buf[0];
|
|
||||||
};
|
|
||||||
typedef struct _NebulaBuf NebulaBuf;
|
|
||||||
|
|
||||||
static int __read(Conn* conn);
|
|
||||||
static int __write(Conn* conn);
|
|
||||||
static void __err(Conn* conn);
|
|
||||||
|
|
||||||
Conn* NebulaConnCreate()
|
|
||||||
{
|
|
||||||
if (g_epollfd == -1) {
|
|
||||||
g_epollfd = epoll_create(EPOLL_SIZE);
|
|
||||||
if (g_epollfd == -1) return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Conn* conn = (Conn*)malloc(sizeof(Conn));
|
|
||||||
memset(conn, 0, sizeof(Conn));
|
|
||||||
conn->read = __read;
|
|
||||||
conn->write = __write;
|
|
||||||
conn->err = __err;
|
|
||||||
conn->send_list = CreateList();
|
|
||||||
if (-1 == pthread_mutex_init(&conn->mtx, NULL)) {
|
|
||||||
free(conn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!conn->send_list) {
|
|
||||||
free(conn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaConnInit(Conn* conn, void(*on_connect)(Conn*, int),
|
|
||||||
void(*on_read)(Conn*, NebulaHeader*), void(*on_disconnect)(Conn*))
|
|
||||||
{
|
|
||||||
conn->on_connect = on_connect;
|
|
||||||
conn->on_read = on_read;
|
|
||||||
conn->on_disconnect = on_disconnect;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaConnConnect(Conn* conn, const char* host, uint16_t port)
|
|
||||||
{
|
|
||||||
if (!conn || !host || !port || !*host) return -1;
|
|
||||||
|
|
||||||
if (conn->state == eConnState_Estab || conn->state == eConnState_Connecting)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (conn->host) free(conn->host);
|
|
||||||
conn->host = strdup(host);
|
|
||||||
conn->port = port;
|
|
||||||
|
|
||||||
if (conn->socketfd >= 0) {
|
|
||||||
epoll_ctl(g_epollfd, EPOLL_CTL_DEL, conn->socketfd, NULL);
|
|
||||||
close(conn->socketfd);
|
|
||||||
conn->socketfd = -1;
|
|
||||||
}
|
|
||||||
conn->state = eConnState_Init;
|
|
||||||
|
|
||||||
conn->socketfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if (conn->socketfd == -1) return -1;
|
|
||||||
|
|
||||||
int flag = fcntl(conn->socketfd, F_GETFL);
|
|
||||||
if (fcntl(conn->socketfd, F_SETFL, flag | O_NONBLOCK) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(port);
|
|
||||||
addr.sin_addr.s_addr = inet_addr(host);
|
|
||||||
|
|
||||||
int ret;
|
|
||||||
retry_connect:
|
|
||||||
ret = connect(conn->socketfd, (struct sockaddr*)&addr, sizeof(addr));
|
|
||||||
if (ret == 0) {
|
|
||||||
// connect completed immediately.
|
|
||||||
conn->state = eConnState_Estab;
|
|
||||||
if (conn->on_connect)
|
|
||||||
conn->on_connect(conn, 0);
|
|
||||||
|
|
||||||
struct epoll_event ev = {EPOLLIN, {conn}};
|
|
||||||
epoll_ctl(g_epollfd, EPOLL_CTL_ADD, conn->socketfd, &ev);
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
if (errno == EINTR)
|
|
||||||
goto retry_connect;
|
|
||||||
|
|
||||||
if (errno != EINPROGRESS) {
|
|
||||||
// connect error.
|
|
||||||
conn->state = eConnState_Error;
|
|
||||||
close(conn->socketfd);
|
|
||||||
conn->socketfd = -1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// connect not completed immediately, wait from epoll_wait.
|
|
||||||
struct epoll_event ev = {EPOLLOUT, {conn}};
|
|
||||||
epoll_ctl(g_epollfd, EPOLL_CTL_ADD, conn->socketfd, &ev);
|
|
||||||
conn->state = eConnState_Connecting;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaConnSend(Conn* conn, NebulaHeader *head, ProtobufCMessage *msg)
|
|
||||||
{
|
|
||||||
if (!conn || conn->state != eConnState_Estab) return -1;
|
|
||||||
|
|
||||||
int len = sizeof(NebulaHeader);
|
|
||||||
if (msg) {
|
|
||||||
int msg_len = protobuf_c_message_get_packed_size(msg);
|
|
||||||
head->len = htons(msg_len);
|
|
||||||
len += msg_len;
|
|
||||||
}
|
|
||||||
NebulaBuf *buf = (NebulaBuf*)malloc(sizeof(NebulaBuf) + len);
|
|
||||||
buf->len = len;
|
|
||||||
buf->pos = 0;
|
|
||||||
memcpy(buf->buf, head, sizeof(NebulaHeader));
|
|
||||||
if (msg)
|
|
||||||
protobuf_c_message_pack(msg, (uint8_t*)buf->buf + sizeof(NebulaHeader));
|
|
||||||
|
|
||||||
log_debug("NEBULA TX %s|%d", MsgType2Str(head->type), (int)htons(head->len));
|
|
||||||
|
|
||||||
pthread_mutex_lock(&conn->mtx);
|
|
||||||
if (-1 == PushBack(conn->send_list, buf)) {
|
|
||||||
free(buf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&conn->mtx);
|
|
||||||
|
|
||||||
struct epoll_event ev = {EPOLLOUT | EPOLLIN, {conn}};
|
|
||||||
epoll_ctl(g_epollfd, EPOLL_CTL_MOD, conn->socketfd, &ev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaConnLoop()
|
|
||||||
{
|
|
||||||
if (g_epollfd == -1) {
|
|
||||||
g_epollfd = epoll_create(EPOLL_SIZE);
|
|
||||||
if (g_epollfd == -1) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int n, i;
|
|
||||||
struct epoll_event ev[EPOLL_SIZE];
|
|
||||||
n = epoll_wait(g_epollfd, ev, EPOLL_SIZE, 20);
|
|
||||||
if (n == -1) return ;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
Conn *c = (Conn*)ev[i].data.ptr;
|
|
||||||
|
|
||||||
if (ev[i].events & EPOLLHUP || ev[i].events & EPOLLERR) {
|
|
||||||
c->err(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ev[i].events & EPOLLIN) {
|
|
||||||
if (c->read(c) < 0) {
|
|
||||||
c->err(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ev[i].events & EPOLLOUT) {
|
|
||||||
if (c->write(c) < 0) {
|
|
||||||
c->err(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __read(Conn* conn)
|
|
||||||
{
|
|
||||||
ssize_t n;
|
|
||||||
retry_read:
|
|
||||||
n = read(conn->socketfd, conn->recv_buf + conn->recv_pos,
|
|
||||||
sizeof(conn->recv_buf) - conn->recv_pos);
|
|
||||||
if (n == -1) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
goto retry_read;
|
|
||||||
|
|
||||||
if (errno == EAGAIN)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
conn->recv_pos += n;
|
|
||||||
int pos = 0;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (conn->recv_pos - pos < sizeof(NebulaHeader))
|
|
||||||
break;
|
|
||||||
|
|
||||||
NebulaHeader *head = (NebulaHeader*)(conn->recv_buf + pos);
|
|
||||||
int pack_len = sizeof(NebulaHeader) + htons(head->len);
|
|
||||||
if (pack_len > sizeof(conn->recv_buf))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (conn->recv_pos - pos < pack_len)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (conn->on_read)
|
|
||||||
conn->on_read(conn, head);
|
|
||||||
pos += pack_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos > 0) {
|
|
||||||
conn->recv_pos -= pos;
|
|
||||||
memmove(conn->recv_buf + pos, conn->recv_buf, conn->recv_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __write(Conn* conn)
|
|
||||||
{
|
|
||||||
if (conn->state == eConnState_Connecting) {
|
|
||||||
// check connect result.
|
|
||||||
int err = 0;
|
|
||||||
socklen_t sl = sizeof(int);
|
|
||||||
int ret = getsockopt(conn->socketfd, SOL_SOCKET, SO_ERROR, &err, &sl);
|
|
||||||
if (ret == -1 || err != 0) {
|
|
||||||
// connect failed.
|
|
||||||
conn->state = eConnState_Error;
|
|
||||||
epoll_ctl(g_epollfd, EPOLL_CTL_DEL, conn->socketfd, NULL);
|
|
||||||
close(conn->socketfd);
|
|
||||||
conn->socketfd = -1;
|
|
||||||
if (conn->on_connect)
|
|
||||||
conn->on_connect(conn, (ret == -1 ? errno : err));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct epoll_event ev = {EPOLLIN, {conn}};
|
|
||||||
epoll_ctl(g_epollfd, EPOLL_CTL_MOD, conn->socketfd, &ev);
|
|
||||||
conn->state = eConnState_Estab;
|
|
||||||
if (conn->on_connect)
|
|
||||||
conn->on_connect(conn, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&conn->mtx);
|
|
||||||
struct iovec iov[UIO_MAXIOV];
|
|
||||||
ListIterator it = ListBegin(conn->send_list);
|
|
||||||
int iov_cnt = 0;
|
|
||||||
for (; it && iov_cnt < UIO_MAXIOV; it = ListNext(it), iov_cnt++)
|
|
||||||
{
|
|
||||||
NebulaBuf *buf = *(NebulaBuf **)it;
|
|
||||||
iov[iov_cnt].iov_len = buf->len - buf->pos;
|
|
||||||
iov[iov_cnt].iov_base = buf->buf + buf->pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t n;
|
|
||||||
retry_write:
|
|
||||||
n = writev(conn->socketfd, iov, iov_cnt);
|
|
||||||
if (n == -1) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
goto retry_write;
|
|
||||||
|
|
||||||
if (errno == EAGAIN)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
NebulaBuf *buf = (NebulaBuf *)Front(conn->send_list);
|
|
||||||
int len = buf->len - buf->pos;
|
|
||||||
if (len < n) {
|
|
||||||
n -= len;
|
|
||||||
PopFront(conn->send_list);
|
|
||||||
continue;
|
|
||||||
} else if (len == n) {
|
|
||||||
n -= len;
|
|
||||||
PopFront(conn->send_list);
|
|
||||||
break;
|
|
||||||
} else if (len > n) {
|
|
||||||
buf->pos += n;
|
|
||||||
n = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&conn->mtx);
|
|
||||||
|
|
||||||
if (conn->send_list->size == 0) {
|
|
||||||
struct epoll_event ev = {EPOLLIN, {conn}};
|
|
||||||
epoll_ctl(g_epollfd, EPOLL_CTL_MOD, conn->socketfd, &ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __err(Conn* conn)
|
|
||||||
{
|
|
||||||
conn->state = eConnState_Error;
|
|
||||||
epoll_ctl(g_epollfd, EPOLL_CTL_DEL, conn->socketfd, NULL);
|
|
||||||
close(conn->socketfd);
|
|
||||||
conn->socketfd = -1;
|
|
||||||
conn->on_disconnect(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaConnNebulaDisconnect(Conn* conn)
|
|
||||||
{
|
|
||||||
conn->err(conn);
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
#ifndef NEBULA_NET_H
|
|
||||||
#define NEBULA_NET_H
|
|
||||||
|
|
||||||
// Async TCP connection.
|
|
||||||
#include <google/protobuf-c/protobuf-c.h>
|
|
||||||
#include "list.h"
|
|
||||||
#include <pthread.h>
|
|
||||||
#include "nebula_proto.h"
|
|
||||||
|
|
||||||
enum _ConnState {
|
|
||||||
eConnState_Init,
|
|
||||||
eConnState_Connecting,
|
|
||||||
eConnState_Estab,
|
|
||||||
eConnState_Error,
|
|
||||||
};
|
|
||||||
typedef enum _ConnState ConnState;
|
|
||||||
|
|
||||||
typedef struct _Conn Conn;
|
|
||||||
struct _Conn
|
|
||||||
{
|
|
||||||
int socketfd;
|
|
||||||
char* host;
|
|
||||||
uint16_t port;
|
|
||||||
void (*on_connect)(Conn*, int);
|
|
||||||
void (*on_read)(Conn*, NebulaHeader*);
|
|
||||||
void (*on_disconnect)(Conn*);
|
|
||||||
int (*read)(Conn*);
|
|
||||||
int (*write)(Conn*);
|
|
||||||
void (*err)(Conn*);
|
|
||||||
char recv_buf[8192];
|
|
||||||
int recv_pos;
|
|
||||||
List* send_list;
|
|
||||||
pthread_mutex_t mtx;
|
|
||||||
ConnState state;
|
|
||||||
};
|
|
||||||
|
|
||||||
Conn* NebulaConnCreate();
|
|
||||||
|
|
||||||
void NebulaConnInit(Conn* conn, void(*on_connect)(Conn*, int),
|
|
||||||
void(*on_read)(Conn*, NebulaHeader*),
|
|
||||||
void(*on_disconnect)(Conn*));
|
|
||||||
|
|
||||||
int NebulaConnConnect(Conn* conn, const char* host, uint16_t port);
|
|
||||||
|
|
||||||
int NebulaConnSend(Conn* conn, NebulaHeader *head, ProtobufCMessage *msg);
|
|
||||||
|
|
||||||
void NebulaConnNebulaDisconnect(Conn* conn);
|
|
||||||
|
|
||||||
void NebulaConnLoop();
|
|
||||||
|
|
||||||
#endif //NEBULA_NET_H
|
|
||||||
|
|
Binary file not shown.
@ -1,29 +0,0 @@
|
|||||||
CC=gcc
|
|
||||||
CFLAGS=-g -fPIC
|
|
||||||
OBJS=$(patsubst %.proto,%.o,$(wildcard *.proto))
|
|
||||||
OBJS+=nebula_proto.o
|
|
||||||
TARGET=libnebula_proto.a
|
|
||||||
|
|
||||||
all: $(TARGET)
|
|
||||||
|
|
||||||
$(TARGET):$(OBJS)
|
|
||||||
@echo "LD $(TARGET)"
|
|
||||||
@ar -cr $@ $^
|
|
||||||
|
|
||||||
%.o:%.proto
|
|
||||||
@echo "make $@"
|
|
||||||
@protoc-c $< --c_out=.
|
|
||||||
@$(CC) $(CFLAGS) -g $(patsubst %.o,%.pb-c.c,$@) -c -o $@
|
|
||||||
|
|
||||||
%.o:%.c
|
|
||||||
@echo "make $@"
|
|
||||||
@$(CC) $(CFLAGS) -g $< -c -o $@
|
|
||||||
|
|
||||||
.PHONY: clean echo
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm *.o *.a -f
|
|
||||||
|
|
||||||
echo:
|
|
||||||
@echo "TARGET=$(TARGET)"
|
|
||||||
@echo "OBJS=$(OBJS)"
|
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,979 +0,0 @@
|
|||||||
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
|
|
||||||
|
|
||||||
#ifndef PROTOBUF_C_message_2eproto__INCLUDED
|
|
||||||
#define PROTOBUF_C_message_2eproto__INCLUDED
|
|
||||||
|
|
||||||
#include <google/protobuf-c/protobuf-c.h>
|
|
||||||
|
|
||||||
PROTOBUF_C_BEGIN_DECLS
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _Nebula__Param Nebula__Param;
|
|
||||||
typedef struct _Nebula__AccountUpdateRequest Nebula__AccountUpdateRequest;
|
|
||||||
typedef struct _Nebula__AccountUpdateResponse Nebula__AccountUpdateResponse;
|
|
||||||
typedef struct _Nebula__AuthRequest Nebula__AuthRequest;
|
|
||||||
typedef struct _Nebula__AuthResponse Nebula__AuthResponse;
|
|
||||||
typedef struct _Nebula__Message Nebula__Message;
|
|
||||||
typedef struct _Nebula__Message__Content Nebula__Message__Content;
|
|
||||||
typedef struct _Nebula__MessageSeq Nebula__MessageSeq;
|
|
||||||
typedef struct _Nebula__MessageSeq__Content Nebula__MessageSeq__Content;
|
|
||||||
typedef struct _Nebula__MessageKievAck Nebula__MessageKievAck;
|
|
||||||
typedef struct _Nebula__SubscribeRequest Nebula__SubscribeRequest;
|
|
||||||
typedef struct _Nebula__SubscribeResponse Nebula__SubscribeResponse;
|
|
||||||
typedef struct _Nebula__SubscribeResponse__Content Nebula__SubscribeResponse__Content;
|
|
||||||
typedef struct _Nebula__NotifyBody Nebula__NotifyBody;
|
|
||||||
typedef struct _Nebula__SmsRequest Nebula__SmsRequest;
|
|
||||||
typedef struct _Nebula__SmsRequest__FileInfo Nebula__SmsRequest__FileInfo;
|
|
||||||
typedef struct _Nebula__SmsResponse Nebula__SmsResponse;
|
|
||||||
typedef struct _Nebula__PresenceNotify Nebula__PresenceNotify;
|
|
||||||
typedef struct _Nebula__PresenceNotify__Content Nebula__PresenceNotify__Content;
|
|
||||||
typedef struct _Nebula__PresenceRequest Nebula__PresenceRequest;
|
|
||||||
typedef struct _Nebula__PresenceResponse Nebula__PresenceResponse;
|
|
||||||
typedef struct _Nebula__AccountStatusRequest Nebula__AccountStatusRequest;
|
|
||||||
typedef struct _Nebula__AccountStatusResponse Nebula__AccountStatusResponse;
|
|
||||||
typedef struct _Nebula__AccountStatusResponse__AccountStatus Nebula__AccountStatusResponse__AccountStatus;
|
|
||||||
typedef struct _Nebula__Address Nebula__Address;
|
|
||||||
typedef struct _Nebula__DialogRequest Nebula__DialogRequest;
|
|
||||||
typedef struct _Nebula__DialogResponse Nebula__DialogResponse;
|
|
||||||
|
|
||||||
|
|
||||||
/* --- enums --- */
|
|
||||||
|
|
||||||
typedef enum _Nebula__AuthRequest__Algorithm {
|
|
||||||
NEBULA__AUTH_REQUEST__ALGORITHM__MD5_MEIZU = 0,
|
|
||||||
NEBULA__AUTH_REQUEST__ALGORITHM__MD5_DAA = 1,
|
|
||||||
NEBULA__AUTH_REQUEST__ALGORITHM__MD5_FLYME = 2
|
|
||||||
} Nebula__AuthRequest__Algorithm;
|
|
||||||
typedef enum _Nebula__Message__Content__MsgType {
|
|
||||||
NEBULA__MESSAGE__CONTENT__MSG_TYPE__ePushMessage = 0,
|
|
||||||
NEBULA__MESSAGE__CONTENT__MSG_TYPE__ePresenceMessage = 1,
|
|
||||||
NEBULA__MESSAGE__CONTENT__MSG_TYPE__eSmsMessage = 2
|
|
||||||
} Nebula__Message__Content__MsgType;
|
|
||||||
typedef enum _Nebula__Message__Flag {
|
|
||||||
NEBULA__MESSAGE__FLAG__MESSAGE_ACK = 1,
|
|
||||||
NEBULA__MESSAGE__FLAG__MESSAGE_END = 2
|
|
||||||
} Nebula__Message__Flag;
|
|
||||||
typedef enum _Nebula__SmsRequest__SmsType {
|
|
||||||
NEBULA__SMS_REQUEST__SMS_TYPE__eShortMessage = 0,
|
|
||||||
NEBULA__SMS_REQUEST__SMS_TYPE__eMultimediaMessage = 1,
|
|
||||||
NEBULA__SMS_REQUEST__SMS_TYPE__eReportMessage = 2
|
|
||||||
} Nebula__SmsRequest__SmsType;
|
|
||||||
typedef enum _Nebula__SmsRequest__ReportType {
|
|
||||||
NEBULA__SMS_REQUEST__REPORT_TYPE__eSMSReport = 0,
|
|
||||||
NEBULA__SMS_REQUEST__REPORT_TYPE__eMMSReport = 1
|
|
||||||
} Nebula__SmsRequest__ReportType;
|
|
||||||
typedef enum _Nebula__PresenceType {
|
|
||||||
NEBULA__PRESENCE_TYPE__eIncrementSubscribe = 0,
|
|
||||||
NEBULA__PRESENCE_TYPE__eFullSubscribe = 1,
|
|
||||||
NEBULA__PRESENCE_TYPE__eUnSubscribe = 2
|
|
||||||
} Nebula__PresenceType;
|
|
||||||
|
|
||||||
/* --- messages --- */
|
|
||||||
|
|
||||||
struct _Nebula__Param
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *name;
|
|
||||||
char *value;
|
|
||||||
};
|
|
||||||
#define NEBULA__PARAM__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__param__descriptor) \
|
|
||||||
, NULL, NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__AccountUpdateRequest
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *flyme_uid;
|
|
||||||
char *phone;
|
|
||||||
protobuf_c_boolean has_capability;
|
|
||||||
int32_t capability;
|
|
||||||
};
|
|
||||||
#define NEBULA__ACCOUNT_UPDATE_REQUEST__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__account_update_request__descriptor) \
|
|
||||||
, NULL, NULL, 0,0 }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__AccountUpdateResponse
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
int32_t status;
|
|
||||||
char *flyme_uid;
|
|
||||||
char *imsi;
|
|
||||||
char *phone;
|
|
||||||
protobuf_c_boolean has_capability;
|
|
||||||
int32_t capability;
|
|
||||||
};
|
|
||||||
#define NEBULA__ACCOUNT_UPDATE_RESPONSE__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__account_update_response__descriptor) \
|
|
||||||
, 0, NULL, NULL, NULL, 0,0 }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__AuthRequest
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *uid;
|
|
||||||
char *username;
|
|
||||||
char *nonce;
|
|
||||||
char *realm;
|
|
||||||
char *token;
|
|
||||||
protobuf_c_boolean has_algorithm;
|
|
||||||
Nebula__AuthRequest__Algorithm algorithm;
|
|
||||||
size_t n_other_info;
|
|
||||||
Nebula__Param **other_info;
|
|
||||||
};
|
|
||||||
#define NEBULA__AUTH_REQUEST__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__auth_request__descriptor) \
|
|
||||||
, NULL, NULL, NULL, NULL, NULL, 0,0, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__AuthResponse
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
protobuf_c_boolean has_status;
|
|
||||||
int32_t status;
|
|
||||||
char *nonce;
|
|
||||||
char *realm;
|
|
||||||
};
|
|
||||||
#define NEBULA__AUTH_RESPONSE__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__auth_response__descriptor) \
|
|
||||||
, 0,0, NULL, NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__Message__Content
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
Nebula__Message__Content__MsgType type;
|
|
||||||
char *account;
|
|
||||||
uint32_t seq;
|
|
||||||
protobuf_c_boolean has_body;
|
|
||||||
ProtobufCBinaryData body;
|
|
||||||
};
|
|
||||||
#define NEBULA__MESSAGE__CONTENT__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__message__content__descriptor) \
|
|
||||||
, 0, NULL, 0, 0,{0,NULL} }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__Message
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
size_t n_content;
|
|
||||||
Nebula__Message__Content **content;
|
|
||||||
protobuf_c_boolean has_flag;
|
|
||||||
Nebula__Message__Flag flag;
|
|
||||||
};
|
|
||||||
#define NEBULA__MESSAGE__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__message__descriptor) \
|
|
||||||
, 0,NULL, 0,0 }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__MessageSeq__Content
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *account;
|
|
||||||
uint32_t seq;
|
|
||||||
};
|
|
||||||
#define NEBULA__MESSAGE_SEQ__CONTENT__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__message_seq__content__descriptor) \
|
|
||||||
, NULL, 0 }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__MessageSeq
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
size_t n_content;
|
|
||||||
Nebula__MessageSeq__Content **content;
|
|
||||||
};
|
|
||||||
#define NEBULA__MESSAGE_SEQ__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__message_seq__descriptor) \
|
|
||||||
, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__MessageKievAck
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
Nebula__MessageSeq *seqs;
|
|
||||||
uint32_t index;
|
|
||||||
};
|
|
||||||
#define NEBULA__MESSAGE_KIEV_ACK__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__message_kiev_ack__descriptor) \
|
|
||||||
, NULL, 0 }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__SubscribeRequest
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
size_t n_app;
|
|
||||||
char **app;
|
|
||||||
};
|
|
||||||
#define NEBULA__SUBSCRIBE_REQUEST__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__subscribe_request__descriptor) \
|
|
||||||
, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__SubscribeResponse__Content
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
protobuf_c_boolean has_status;
|
|
||||||
int32_t status;
|
|
||||||
char *app;
|
|
||||||
char *pushid;
|
|
||||||
};
|
|
||||||
#define NEBULA__SUBSCRIBE_RESPONSE__CONTENT__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__subscribe_response__content__descriptor) \
|
|
||||||
, 0,0, NULL, NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__SubscribeResponse
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
int32_t status;
|
|
||||||
size_t n_content;
|
|
||||||
Nebula__SubscribeResponse__Content **content;
|
|
||||||
};
|
|
||||||
#define NEBULA__SUBSCRIBE_RESPONSE__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__subscribe_response__descriptor) \
|
|
||||||
, 0, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__NotifyBody
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *app;
|
|
||||||
char *body;
|
|
||||||
};
|
|
||||||
#define NEBULA__NOTIFY_BODY__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__notify_body__descriptor) \
|
|
||||||
, NULL, NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__SmsRequest__FileInfo
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *mimetype;
|
|
||||||
int32_t size;
|
|
||||||
char *filename;
|
|
||||||
char *url;
|
|
||||||
};
|
|
||||||
#define NEBULA__SMS_REQUEST__FILE_INFO__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__sms_request__file_info__descriptor) \
|
|
||||||
, NULL, 0, NULL, NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__SmsRequest
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
Nebula__SmsRequest__SmsType type;
|
|
||||||
char *msgid;
|
|
||||||
char *src;
|
|
||||||
size_t n_dst;
|
|
||||||
char **dst;
|
|
||||||
protobuf_c_boolean has_body;
|
|
||||||
ProtobufCBinaryData body;
|
|
||||||
protobuf_c_boolean has_report_flag;
|
|
||||||
protobuf_c_boolean report_flag;
|
|
||||||
protobuf_c_boolean has_report_type;
|
|
||||||
Nebula__SmsRequest__ReportType report_type;
|
|
||||||
char *report_status;
|
|
||||||
char *time;
|
|
||||||
char *expires;
|
|
||||||
char *pdu;
|
|
||||||
protobuf_c_boolean has_size;
|
|
||||||
int32_t size;
|
|
||||||
char *ver;
|
|
||||||
size_t n_fileinfos;
|
|
||||||
Nebula__SmsRequest__FileInfo **fileinfos;
|
|
||||||
};
|
|
||||||
#define NEBULA__SMS_REQUEST__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__sms_request__descriptor) \
|
|
||||||
, 0, NULL, NULL, 0,NULL, 0,{0,NULL}, 0,0, 0,0, NULL, NULL, NULL, NULL, 0,0, NULL, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__SmsResponse
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *msgid;
|
|
||||||
int32_t status;
|
|
||||||
};
|
|
||||||
#define NEBULA__SMS_RESPONSE__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__sms_response__descriptor) \
|
|
||||||
, NULL, 0 }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__PresenceNotify__Content
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *account;
|
|
||||||
protobuf_c_boolean has_capability;
|
|
||||||
int32_t capability;
|
|
||||||
protobuf_c_boolean has_status;
|
|
||||||
int32_t status;
|
|
||||||
};
|
|
||||||
#define NEBULA__PRESENCE_NOTIFY__CONTENT__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__presence_notify__content__descriptor) \
|
|
||||||
, NULL, 0,0, 0,0 }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__PresenceNotify
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
size_t n_content;
|
|
||||||
Nebula__PresenceNotify__Content **content;
|
|
||||||
};
|
|
||||||
#define NEBULA__PRESENCE_NOTIFY__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__presence_notify__descriptor) \
|
|
||||||
, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__PresenceRequest
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
protobuf_c_boolean has_type;
|
|
||||||
Nebula__PresenceType type;
|
|
||||||
protobuf_c_boolean has_sequence;
|
|
||||||
uint32_t sequence;
|
|
||||||
size_t n_account;
|
|
||||||
char **account;
|
|
||||||
};
|
|
||||||
#define NEBULA__PRESENCE_REQUEST__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__presence_request__descriptor) \
|
|
||||||
, 0,0, 0,0, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__PresenceResponse
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
int32_t status;
|
|
||||||
protobuf_c_boolean has_type;
|
|
||||||
Nebula__PresenceType type;
|
|
||||||
protobuf_c_boolean has_sequence;
|
|
||||||
uint32_t sequence;
|
|
||||||
size_t n_account;
|
|
||||||
char **account;
|
|
||||||
};
|
|
||||||
#define NEBULA__PRESENCE_RESPONSE__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__presence_response__descriptor) \
|
|
||||||
, 0, 0,0, 0,0, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__AccountStatusRequest
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
size_t n_account;
|
|
||||||
char **account;
|
|
||||||
};
|
|
||||||
#define NEBULA__ACCOUNT_STATUS_REQUEST__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__account_status_request__descriptor) \
|
|
||||||
, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__AccountStatusResponse__AccountStatus
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *account;
|
|
||||||
protobuf_c_boolean has_status;
|
|
||||||
int32_t status;
|
|
||||||
protobuf_c_boolean has_capability;
|
|
||||||
int32_t capability;
|
|
||||||
};
|
|
||||||
#define NEBULA__ACCOUNT_STATUS_RESPONSE__ACCOUNT_STATUS__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__account_status_response__account_status__descriptor) \
|
|
||||||
, NULL, 0,0, 0,0 }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__AccountStatusResponse
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
int32_t status;
|
|
||||||
size_t n_result;
|
|
||||||
Nebula__AccountStatusResponse__AccountStatus **result;
|
|
||||||
};
|
|
||||||
#define NEBULA__ACCOUNT_STATUS_RESPONSE__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__account_status_response__descriptor) \
|
|
||||||
, 0, 0,NULL }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__Address
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *host;
|
|
||||||
int32_t port;
|
|
||||||
};
|
|
||||||
#define NEBULA__ADDRESS__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__address__descriptor) \
|
|
||||||
, NULL, 0 }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__DialogRequest
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *src;
|
|
||||||
char *dst;
|
|
||||||
Nebula__Address *dialog;
|
|
||||||
protobuf_c_boolean has_body;
|
|
||||||
ProtobufCBinaryData body;
|
|
||||||
};
|
|
||||||
#define NEBULA__DIALOG_REQUEST__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__dialog_request__descriptor) \
|
|
||||||
, NULL, NULL, NULL, 0,{0,NULL} }
|
|
||||||
|
|
||||||
|
|
||||||
struct _Nebula__DialogResponse
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
int32_t status;
|
|
||||||
char *src;
|
|
||||||
char *dst;
|
|
||||||
Nebula__Address *dialog;
|
|
||||||
protobuf_c_boolean has_body;
|
|
||||||
ProtobufCBinaryData body;
|
|
||||||
};
|
|
||||||
#define NEBULA__DIALOG_RESPONSE__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__dialog_response__descriptor) \
|
|
||||||
, 0, NULL, NULL, NULL, 0,{0,NULL} }
|
|
||||||
|
|
||||||
|
|
||||||
/* Nebula__Param methods */
|
|
||||||
void nebula__param__init
|
|
||||||
(Nebula__Param *message);
|
|
||||||
size_t nebula__param__get_packed_size
|
|
||||||
(const Nebula__Param *message);
|
|
||||||
size_t nebula__param__pack
|
|
||||||
(const Nebula__Param *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__param__pack_to_buffer
|
|
||||||
(const Nebula__Param *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__Param *
|
|
||||||
nebula__param__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__param__free_unpacked
|
|
||||||
(Nebula__Param *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__AccountUpdateRequest methods */
|
|
||||||
void nebula__account_update_request__init
|
|
||||||
(Nebula__AccountUpdateRequest *message);
|
|
||||||
size_t nebula__account_update_request__get_packed_size
|
|
||||||
(const Nebula__AccountUpdateRequest *message);
|
|
||||||
size_t nebula__account_update_request__pack
|
|
||||||
(const Nebula__AccountUpdateRequest *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__account_update_request__pack_to_buffer
|
|
||||||
(const Nebula__AccountUpdateRequest *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__AccountUpdateRequest *
|
|
||||||
nebula__account_update_request__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__account_update_request__free_unpacked
|
|
||||||
(Nebula__AccountUpdateRequest *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__AccountUpdateResponse methods */
|
|
||||||
void nebula__account_update_response__init
|
|
||||||
(Nebula__AccountUpdateResponse *message);
|
|
||||||
size_t nebula__account_update_response__get_packed_size
|
|
||||||
(const Nebula__AccountUpdateResponse *message);
|
|
||||||
size_t nebula__account_update_response__pack
|
|
||||||
(const Nebula__AccountUpdateResponse *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__account_update_response__pack_to_buffer
|
|
||||||
(const Nebula__AccountUpdateResponse *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__AccountUpdateResponse *
|
|
||||||
nebula__account_update_response__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__account_update_response__free_unpacked
|
|
||||||
(Nebula__AccountUpdateResponse *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__AuthRequest methods */
|
|
||||||
void nebula__auth_request__init
|
|
||||||
(Nebula__AuthRequest *message);
|
|
||||||
size_t nebula__auth_request__get_packed_size
|
|
||||||
(const Nebula__AuthRequest *message);
|
|
||||||
size_t nebula__auth_request__pack
|
|
||||||
(const Nebula__AuthRequest *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__auth_request__pack_to_buffer
|
|
||||||
(const Nebula__AuthRequest *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__AuthRequest *
|
|
||||||
nebula__auth_request__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__auth_request__free_unpacked
|
|
||||||
(Nebula__AuthRequest *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__AuthResponse methods */
|
|
||||||
void nebula__auth_response__init
|
|
||||||
(Nebula__AuthResponse *message);
|
|
||||||
size_t nebula__auth_response__get_packed_size
|
|
||||||
(const Nebula__AuthResponse *message);
|
|
||||||
size_t nebula__auth_response__pack
|
|
||||||
(const Nebula__AuthResponse *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__auth_response__pack_to_buffer
|
|
||||||
(const Nebula__AuthResponse *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__AuthResponse *
|
|
||||||
nebula__auth_response__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__auth_response__free_unpacked
|
|
||||||
(Nebula__AuthResponse *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__Message__Content methods */
|
|
||||||
void nebula__message__content__init
|
|
||||||
(Nebula__Message__Content *message);
|
|
||||||
/* Nebula__Message methods */
|
|
||||||
void nebula__message__init
|
|
||||||
(Nebula__Message *message);
|
|
||||||
size_t nebula__message__get_packed_size
|
|
||||||
(const Nebula__Message *message);
|
|
||||||
size_t nebula__message__pack
|
|
||||||
(const Nebula__Message *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__message__pack_to_buffer
|
|
||||||
(const Nebula__Message *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__Message *
|
|
||||||
nebula__message__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__message__free_unpacked
|
|
||||||
(Nebula__Message *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__MessageSeq__Content methods */
|
|
||||||
void nebula__message_seq__content__init
|
|
||||||
(Nebula__MessageSeq__Content *message);
|
|
||||||
/* Nebula__MessageSeq methods */
|
|
||||||
void nebula__message_seq__init
|
|
||||||
(Nebula__MessageSeq *message);
|
|
||||||
size_t nebula__message_seq__get_packed_size
|
|
||||||
(const Nebula__MessageSeq *message);
|
|
||||||
size_t nebula__message_seq__pack
|
|
||||||
(const Nebula__MessageSeq *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__message_seq__pack_to_buffer
|
|
||||||
(const Nebula__MessageSeq *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__MessageSeq *
|
|
||||||
nebula__message_seq__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__message_seq__free_unpacked
|
|
||||||
(Nebula__MessageSeq *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__MessageKievAck methods */
|
|
||||||
void nebula__message_kiev_ack__init
|
|
||||||
(Nebula__MessageKievAck *message);
|
|
||||||
size_t nebula__message_kiev_ack__get_packed_size
|
|
||||||
(const Nebula__MessageKievAck *message);
|
|
||||||
size_t nebula__message_kiev_ack__pack
|
|
||||||
(const Nebula__MessageKievAck *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__message_kiev_ack__pack_to_buffer
|
|
||||||
(const Nebula__MessageKievAck *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__MessageKievAck *
|
|
||||||
nebula__message_kiev_ack__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__message_kiev_ack__free_unpacked
|
|
||||||
(Nebula__MessageKievAck *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__SubscribeRequest methods */
|
|
||||||
void nebula__subscribe_request__init
|
|
||||||
(Nebula__SubscribeRequest *message);
|
|
||||||
size_t nebula__subscribe_request__get_packed_size
|
|
||||||
(const Nebula__SubscribeRequest *message);
|
|
||||||
size_t nebula__subscribe_request__pack
|
|
||||||
(const Nebula__SubscribeRequest *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__subscribe_request__pack_to_buffer
|
|
||||||
(const Nebula__SubscribeRequest *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__SubscribeRequest *
|
|
||||||
nebula__subscribe_request__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__subscribe_request__free_unpacked
|
|
||||||
(Nebula__SubscribeRequest *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__SubscribeResponse__Content methods */
|
|
||||||
void nebula__subscribe_response__content__init
|
|
||||||
(Nebula__SubscribeResponse__Content *message);
|
|
||||||
/* Nebula__SubscribeResponse methods */
|
|
||||||
void nebula__subscribe_response__init
|
|
||||||
(Nebula__SubscribeResponse *message);
|
|
||||||
size_t nebula__subscribe_response__get_packed_size
|
|
||||||
(const Nebula__SubscribeResponse *message);
|
|
||||||
size_t nebula__subscribe_response__pack
|
|
||||||
(const Nebula__SubscribeResponse *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__subscribe_response__pack_to_buffer
|
|
||||||
(const Nebula__SubscribeResponse *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__SubscribeResponse *
|
|
||||||
nebula__subscribe_response__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__subscribe_response__free_unpacked
|
|
||||||
(Nebula__SubscribeResponse *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__NotifyBody methods */
|
|
||||||
void nebula__notify_body__init
|
|
||||||
(Nebula__NotifyBody *message);
|
|
||||||
size_t nebula__notify_body__get_packed_size
|
|
||||||
(const Nebula__NotifyBody *message);
|
|
||||||
size_t nebula__notify_body__pack
|
|
||||||
(const Nebula__NotifyBody *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__notify_body__pack_to_buffer
|
|
||||||
(const Nebula__NotifyBody *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__NotifyBody *
|
|
||||||
nebula__notify_body__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__notify_body__free_unpacked
|
|
||||||
(Nebula__NotifyBody *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__SmsRequest__FileInfo methods */
|
|
||||||
void nebula__sms_request__file_info__init
|
|
||||||
(Nebula__SmsRequest__FileInfo *message);
|
|
||||||
/* Nebula__SmsRequest methods */
|
|
||||||
void nebula__sms_request__init
|
|
||||||
(Nebula__SmsRequest *message);
|
|
||||||
size_t nebula__sms_request__get_packed_size
|
|
||||||
(const Nebula__SmsRequest *message);
|
|
||||||
size_t nebula__sms_request__pack
|
|
||||||
(const Nebula__SmsRequest *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__sms_request__pack_to_buffer
|
|
||||||
(const Nebula__SmsRequest *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__SmsRequest *
|
|
||||||
nebula__sms_request__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__sms_request__free_unpacked
|
|
||||||
(Nebula__SmsRequest *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__SmsResponse methods */
|
|
||||||
void nebula__sms_response__init
|
|
||||||
(Nebula__SmsResponse *message);
|
|
||||||
size_t nebula__sms_response__get_packed_size
|
|
||||||
(const Nebula__SmsResponse *message);
|
|
||||||
size_t nebula__sms_response__pack
|
|
||||||
(const Nebula__SmsResponse *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__sms_response__pack_to_buffer
|
|
||||||
(const Nebula__SmsResponse *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__SmsResponse *
|
|
||||||
nebula__sms_response__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__sms_response__free_unpacked
|
|
||||||
(Nebula__SmsResponse *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__PresenceNotify__Content methods */
|
|
||||||
void nebula__presence_notify__content__init
|
|
||||||
(Nebula__PresenceNotify__Content *message);
|
|
||||||
/* Nebula__PresenceNotify methods */
|
|
||||||
void nebula__presence_notify__init
|
|
||||||
(Nebula__PresenceNotify *message);
|
|
||||||
size_t nebula__presence_notify__get_packed_size
|
|
||||||
(const Nebula__PresenceNotify *message);
|
|
||||||
size_t nebula__presence_notify__pack
|
|
||||||
(const Nebula__PresenceNotify *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__presence_notify__pack_to_buffer
|
|
||||||
(const Nebula__PresenceNotify *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__PresenceNotify *
|
|
||||||
nebula__presence_notify__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__presence_notify__free_unpacked
|
|
||||||
(Nebula__PresenceNotify *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__PresenceRequest methods */
|
|
||||||
void nebula__presence_request__init
|
|
||||||
(Nebula__PresenceRequest *message);
|
|
||||||
size_t nebula__presence_request__get_packed_size
|
|
||||||
(const Nebula__PresenceRequest *message);
|
|
||||||
size_t nebula__presence_request__pack
|
|
||||||
(const Nebula__PresenceRequest *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__presence_request__pack_to_buffer
|
|
||||||
(const Nebula__PresenceRequest *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__PresenceRequest *
|
|
||||||
nebula__presence_request__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__presence_request__free_unpacked
|
|
||||||
(Nebula__PresenceRequest *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__PresenceResponse methods */
|
|
||||||
void nebula__presence_response__init
|
|
||||||
(Nebula__PresenceResponse *message);
|
|
||||||
size_t nebula__presence_response__get_packed_size
|
|
||||||
(const Nebula__PresenceResponse *message);
|
|
||||||
size_t nebula__presence_response__pack
|
|
||||||
(const Nebula__PresenceResponse *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__presence_response__pack_to_buffer
|
|
||||||
(const Nebula__PresenceResponse *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__PresenceResponse *
|
|
||||||
nebula__presence_response__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__presence_response__free_unpacked
|
|
||||||
(Nebula__PresenceResponse *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__AccountStatusRequest methods */
|
|
||||||
void nebula__account_status_request__init
|
|
||||||
(Nebula__AccountStatusRequest *message);
|
|
||||||
size_t nebula__account_status_request__get_packed_size
|
|
||||||
(const Nebula__AccountStatusRequest *message);
|
|
||||||
size_t nebula__account_status_request__pack
|
|
||||||
(const Nebula__AccountStatusRequest *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__account_status_request__pack_to_buffer
|
|
||||||
(const Nebula__AccountStatusRequest *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__AccountStatusRequest *
|
|
||||||
nebula__account_status_request__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__account_status_request__free_unpacked
|
|
||||||
(Nebula__AccountStatusRequest *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__AccountStatusResponse__AccountStatus methods */
|
|
||||||
void nebula__account_status_response__account_status__init
|
|
||||||
(Nebula__AccountStatusResponse__AccountStatus *message);
|
|
||||||
/* Nebula__AccountStatusResponse methods */
|
|
||||||
void nebula__account_status_response__init
|
|
||||||
(Nebula__AccountStatusResponse *message);
|
|
||||||
size_t nebula__account_status_response__get_packed_size
|
|
||||||
(const Nebula__AccountStatusResponse *message);
|
|
||||||
size_t nebula__account_status_response__pack
|
|
||||||
(const Nebula__AccountStatusResponse *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__account_status_response__pack_to_buffer
|
|
||||||
(const Nebula__AccountStatusResponse *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__AccountStatusResponse *
|
|
||||||
nebula__account_status_response__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__account_status_response__free_unpacked
|
|
||||||
(Nebula__AccountStatusResponse *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__Address methods */
|
|
||||||
void nebula__address__init
|
|
||||||
(Nebula__Address *message);
|
|
||||||
size_t nebula__address__get_packed_size
|
|
||||||
(const Nebula__Address *message);
|
|
||||||
size_t nebula__address__pack
|
|
||||||
(const Nebula__Address *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__address__pack_to_buffer
|
|
||||||
(const Nebula__Address *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__Address *
|
|
||||||
nebula__address__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__address__free_unpacked
|
|
||||||
(Nebula__Address *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__DialogRequest methods */
|
|
||||||
void nebula__dialog_request__init
|
|
||||||
(Nebula__DialogRequest *message);
|
|
||||||
size_t nebula__dialog_request__get_packed_size
|
|
||||||
(const Nebula__DialogRequest *message);
|
|
||||||
size_t nebula__dialog_request__pack
|
|
||||||
(const Nebula__DialogRequest *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__dialog_request__pack_to_buffer
|
|
||||||
(const Nebula__DialogRequest *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__DialogRequest *
|
|
||||||
nebula__dialog_request__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__dialog_request__free_unpacked
|
|
||||||
(Nebula__DialogRequest *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* Nebula__DialogResponse methods */
|
|
||||||
void nebula__dialog_response__init
|
|
||||||
(Nebula__DialogResponse *message);
|
|
||||||
size_t nebula__dialog_response__get_packed_size
|
|
||||||
(const Nebula__DialogResponse *message);
|
|
||||||
size_t nebula__dialog_response__pack
|
|
||||||
(const Nebula__DialogResponse *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__dialog_response__pack_to_buffer
|
|
||||||
(const Nebula__DialogResponse *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__DialogResponse *
|
|
||||||
nebula__dialog_response__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__dialog_response__free_unpacked
|
|
||||||
(Nebula__DialogResponse *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* --- per-message closures --- */
|
|
||||||
|
|
||||||
typedef void (*Nebula__Param_Closure)
|
|
||||||
(const Nebula__Param *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__AccountUpdateRequest_Closure)
|
|
||||||
(const Nebula__AccountUpdateRequest *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__AccountUpdateResponse_Closure)
|
|
||||||
(const Nebula__AccountUpdateResponse *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__AuthRequest_Closure)
|
|
||||||
(const Nebula__AuthRequest *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__AuthResponse_Closure)
|
|
||||||
(const Nebula__AuthResponse *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__Message__Content_Closure)
|
|
||||||
(const Nebula__Message__Content *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__Message_Closure)
|
|
||||||
(const Nebula__Message *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__MessageSeq__Content_Closure)
|
|
||||||
(const Nebula__MessageSeq__Content *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__MessageSeq_Closure)
|
|
||||||
(const Nebula__MessageSeq *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__MessageKievAck_Closure)
|
|
||||||
(const Nebula__MessageKievAck *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__SubscribeRequest_Closure)
|
|
||||||
(const Nebula__SubscribeRequest *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__SubscribeResponse__Content_Closure)
|
|
||||||
(const Nebula__SubscribeResponse__Content *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__SubscribeResponse_Closure)
|
|
||||||
(const Nebula__SubscribeResponse *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__NotifyBody_Closure)
|
|
||||||
(const Nebula__NotifyBody *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__SmsRequest__FileInfo_Closure)
|
|
||||||
(const Nebula__SmsRequest__FileInfo *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__SmsRequest_Closure)
|
|
||||||
(const Nebula__SmsRequest *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__SmsResponse_Closure)
|
|
||||||
(const Nebula__SmsResponse *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__PresenceNotify__Content_Closure)
|
|
||||||
(const Nebula__PresenceNotify__Content *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__PresenceNotify_Closure)
|
|
||||||
(const Nebula__PresenceNotify *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__PresenceRequest_Closure)
|
|
||||||
(const Nebula__PresenceRequest *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__PresenceResponse_Closure)
|
|
||||||
(const Nebula__PresenceResponse *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__AccountStatusRequest_Closure)
|
|
||||||
(const Nebula__AccountStatusRequest *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__AccountStatusResponse__AccountStatus_Closure)
|
|
||||||
(const Nebula__AccountStatusResponse__AccountStatus *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__AccountStatusResponse_Closure)
|
|
||||||
(const Nebula__AccountStatusResponse *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__Address_Closure)
|
|
||||||
(const Nebula__Address *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__DialogRequest_Closure)
|
|
||||||
(const Nebula__DialogRequest *message,
|
|
||||||
void *closure_data);
|
|
||||||
typedef void (*Nebula__DialogResponse_Closure)
|
|
||||||
(const Nebula__DialogResponse *message,
|
|
||||||
void *closure_data);
|
|
||||||
|
|
||||||
/* --- services --- */
|
|
||||||
|
|
||||||
|
|
||||||
/* --- descriptors --- */
|
|
||||||
|
|
||||||
extern const ProtobufCEnumDescriptor nebula__presence_type__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__param__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__account_update_request__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__account_update_response__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__auth_request__descriptor;
|
|
||||||
extern const ProtobufCEnumDescriptor nebula__auth_request__algorithm__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__auth_response__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__message__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__message__content__descriptor;
|
|
||||||
extern const ProtobufCEnumDescriptor nebula__message__content__msg_type__descriptor;
|
|
||||||
extern const ProtobufCEnumDescriptor nebula__message__flag__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__message_seq__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__message_seq__content__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__message_kiev_ack__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__subscribe_request__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__subscribe_response__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__subscribe_response__content__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__notify_body__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__sms_request__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__sms_request__file_info__descriptor;
|
|
||||||
extern const ProtobufCEnumDescriptor nebula__sms_request__sms_type__descriptor;
|
|
||||||
extern const ProtobufCEnumDescriptor nebula__sms_request__report_type__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__sms_response__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__presence_notify__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__presence_notify__content__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__presence_request__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__presence_response__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__account_status_request__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__account_status_response__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__account_status_response__account_status__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__address__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__dialog_request__descriptor;
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__dialog_response__descriptor;
|
|
||||||
|
|
||||||
PROTOBUF_C_END_DECLS
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* PROTOBUF_message_2eproto__INCLUDED */
|
|
@ -1,248 +0,0 @@
|
|||||||
package Nebula;
|
|
||||||
option java_package = "com.meizu.push.proto";
|
|
||||||
option java_outer_classname = "ProtoMessages";
|
|
||||||
|
|
||||||
message Param
|
|
||||||
{
|
|
||||||
optional string name = 1;
|
|
||||||
optional string value = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
message AccountUpdateRequest
|
|
||||||
{
|
|
||||||
optional string flyme_uid = 1;
|
|
||||||
optional string phone = 2;
|
|
||||||
optional int32 capability = 3; //能力值
|
|
||||||
};
|
|
||||||
|
|
||||||
message AccountUpdateResponse
|
|
||||||
{
|
|
||||||
//200 OK
|
|
||||||
//4XX 检验错误 携带相应的正确值
|
|
||||||
//5XX 其他错误
|
|
||||||
required int32 status = 1; //账号绑定的结果 200 OK
|
|
||||||
optional string flyme_uid = 2; //正确的flyme_uid
|
|
||||||
optional string imsi = 3; //正确的imsi
|
|
||||||
optional string phone = 4; //正确的电话号码
|
|
||||||
optional int32 capability = 5; //能力值
|
|
||||||
};
|
|
||||||
|
|
||||||
//鉴权请求
|
|
||||||
message AuthRequest
|
|
||||||
{
|
|
||||||
enum Algorithm
|
|
||||||
{
|
|
||||||
MD5_MEIZU = 0;
|
|
||||||
MD5_DAA = 1;
|
|
||||||
MD5_FLYME = 2;
|
|
||||||
};
|
|
||||||
required string uid = 1; //用户的唯一标识
|
|
||||||
optional string username = 2; //鉴权使用
|
|
||||||
optional string nonce = 3; //鉴权使用
|
|
||||||
optional string realm = 4; //鉴权使用
|
|
||||||
optional string token = 5; //鉴权使用
|
|
||||||
optional Algorithm algorithm = 6; //鉴权使用
|
|
||||||
repeated Param other_info = 7; //用户的其他信息 比如 手机型号 OS版本等
|
|
||||||
};
|
|
||||||
|
|
||||||
//鉴权应答
|
|
||||||
message AuthResponse
|
|
||||||
{
|
|
||||||
optional int32 status = 1;
|
|
||||||
optional string nonce = 2;
|
|
||||||
optional string realm = 3;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//服务端向下推送的消息
|
|
||||||
message Message
|
|
||||||
{
|
|
||||||
message Content
|
|
||||||
{
|
|
||||||
enum MsgType
|
|
||||||
{
|
|
||||||
ePushMessage = 0; //push消息
|
|
||||||
ePresenceMessage = 1; //presence消息
|
|
||||||
eSmsMessage = 2; //短信消息
|
|
||||||
};
|
|
||||||
required MsgType type = 1; //消息类型
|
|
||||||
required string account = 2;
|
|
||||||
required uint32 seq = 3; //消息序列号
|
|
||||||
optional bytes body = 4; //消息内容 使用protobuf编码
|
|
||||||
};
|
|
||||||
enum Flag
|
|
||||||
{
|
|
||||||
MESSAGE_ACK = 1;
|
|
||||||
MESSAGE_END = 2;
|
|
||||||
};
|
|
||||||
repeated Content content = 1;
|
|
||||||
optional Flag flag = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ACK SYNC FIN 3种消息
|
|
||||||
message MessageSeq
|
|
||||||
{
|
|
||||||
message Content
|
|
||||||
{
|
|
||||||
required string account = 1;
|
|
||||||
required uint32 seq = 2;
|
|
||||||
};
|
|
||||||
repeated Content content = 1; //需要同步的消息编号
|
|
||||||
};
|
|
||||||
|
|
||||||
message MessageKievAck
|
|
||||||
{
|
|
||||||
required MessageSeq seqs = 1;
|
|
||||||
required uint32 index = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
//订阅请求消息
|
|
||||||
message SubscribeRequest
|
|
||||||
{
|
|
||||||
repeated string app = 1; //订阅的app
|
|
||||||
};
|
|
||||||
|
|
||||||
//订阅应答消息
|
|
||||||
message SubscribeResponse
|
|
||||||
{
|
|
||||||
message Content {
|
|
||||||
optional int32 status = 1; //订阅状态 200 ok
|
|
||||||
optional string app = 2; //订阅的app
|
|
||||||
optional string pushid = 3; //返回的pushid
|
|
||||||
};
|
|
||||||
required int32 status = 1; //应答消息的状态
|
|
||||||
repeated Content content = 2; //订阅结果
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////MessageSend的body定义/////////////////////
|
|
||||||
message NotifyBody
|
|
||||||
{
|
|
||||||
optional string app = 1;
|
|
||||||
optional string body = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//短信消息
|
|
||||||
message SmsRequest
|
|
||||||
{
|
|
||||||
enum SmsType
|
|
||||||
{
|
|
||||||
eShortMessage = 0;
|
|
||||||
eMultimediaMessage = 1;
|
|
||||||
eReportMessage = 2;
|
|
||||||
};
|
|
||||||
message FileInfo
|
|
||||||
{
|
|
||||||
required string mimetype = 1;
|
|
||||||
required int32 size = 2;
|
|
||||||
optional string filename = 3;
|
|
||||||
optional string url = 4;
|
|
||||||
};
|
|
||||||
enum ReportType
|
|
||||||
{
|
|
||||||
eSMSReport = 0;
|
|
||||||
eMMSReport = 1;
|
|
||||||
};
|
|
||||||
required SmsType type = 1; //消息类型
|
|
||||||
required string msgid = 2; //消息ID
|
|
||||||
required string src = 3;
|
|
||||||
repeated string dst = 4; //接收者
|
|
||||||
optional bytes body = 5;
|
|
||||||
optional bool report_flag = 6; //sms或者mms消息使用 report标志
|
|
||||||
optional ReportType report_type = 7;
|
|
||||||
optional string report_status = 8; //report消息使用
|
|
||||||
optional string time = 9;
|
|
||||||
optional string expires = 10;
|
|
||||||
optional string pdu = 11;
|
|
||||||
optional int32 size = 12;
|
|
||||||
optional string ver = 13;
|
|
||||||
repeated FileInfo fileinfos = 14;
|
|
||||||
};
|
|
||||||
|
|
||||||
//Message应答消息的内容
|
|
||||||
message SmsResponse
|
|
||||||
{
|
|
||||||
required string msgid = 1;
|
|
||||||
required int32 status = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
//presence推送内容格式
|
|
||||||
message PresenceNotify
|
|
||||||
{
|
|
||||||
message Content
|
|
||||||
{
|
|
||||||
optional string account = 1;
|
|
||||||
optional int32 capability = 2;
|
|
||||||
optional int32 status = 3; //在线状态
|
|
||||||
};
|
|
||||||
|
|
||||||
repeated Content content = 1;
|
|
||||||
};
|
|
||||||
/////////////////////////MessageSend body end///////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
enum PresenceType
|
|
||||||
{
|
|
||||||
eIncrementSubscribe = 0; //增量订阅
|
|
||||||
eFullSubscribe = 1; //全量订阅
|
|
||||||
eUnSubscribe = 2; //取消订阅
|
|
||||||
};
|
|
||||||
|
|
||||||
//presence订阅或取消订阅格式
|
|
||||||
message PresenceRequest
|
|
||||||
{
|
|
||||||
optional PresenceType type = 1;
|
|
||||||
optional uint32 sequence = 2;
|
|
||||||
repeated string account = 3;
|
|
||||||
};
|
|
||||||
|
|
||||||
message PresenceResponse
|
|
||||||
{
|
|
||||||
required int32 status = 1;
|
|
||||||
optional PresenceType type = 2;
|
|
||||||
optional uint32 sequence = 3;
|
|
||||||
repeated string account = 4; // Return the legal account
|
|
||||||
};
|
|
||||||
|
|
||||||
//查询账号在线状态格式
|
|
||||||
message AccountStatusRequest
|
|
||||||
{
|
|
||||||
repeated string account = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
message AccountStatusResponse
|
|
||||||
{
|
|
||||||
message AccountStatus
|
|
||||||
{
|
|
||||||
optional string account = 1;
|
|
||||||
optional int32 status = 2; //查询在线状态
|
|
||||||
optional int32 capability = 3; //能力值
|
|
||||||
};
|
|
||||||
|
|
||||||
required int32 status = 1;
|
|
||||||
repeated AccountStatus result = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
/////////////////对话协议定义////////////////////////////
|
|
||||||
message Address
|
|
||||||
{
|
|
||||||
required string host = 1;
|
|
||||||
required int32 port = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
message DialogRequest
|
|
||||||
{
|
|
||||||
required string src = 1;
|
|
||||||
required string dst = 2;
|
|
||||||
optional Address dialog = 3; //dialog服务器地址
|
|
||||||
optional bytes body = 4;
|
|
||||||
};
|
|
||||||
|
|
||||||
message DialogResponse
|
|
||||||
{
|
|
||||||
required int32 status = 1;
|
|
||||||
required string src = 2;
|
|
||||||
required string dst = 3;
|
|
||||||
optional Address dialog = 4; //dialog服务器地址
|
|
||||||
optional bytes body = 5;
|
|
||||||
};
|
|
Binary file not shown.
@ -1,102 +0,0 @@
|
|||||||
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
|
|
||||||
|
|
||||||
/* Do not generate deprecated warnings for self */
|
|
||||||
#ifndef PROTOBUF_C_NO_DEPRECATED
|
|
||||||
#define PROTOBUF_C_NO_DEPRECATED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "nebula.pb-c.h"
|
|
||||||
void nebula__nebula_msg__init
|
|
||||||
(Nebula__NebulaMsg *message)
|
|
||||||
{
|
|
||||||
static Nebula__NebulaMsg init_value = NEBULA__NEBULA_MSG__INIT;
|
|
||||||
*message = init_value;
|
|
||||||
}
|
|
||||||
size_t nebula__nebula_msg__get_packed_size
|
|
||||||
(const Nebula__NebulaMsg *message)
|
|
||||||
{
|
|
||||||
PROTOBUF_C_ASSERT (message->base.descriptor == &nebula__nebula_msg__descriptor);
|
|
||||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
|
||||||
}
|
|
||||||
size_t nebula__nebula_msg__pack
|
|
||||||
(const Nebula__NebulaMsg *message,
|
|
||||||
uint8_t *out)
|
|
||||||
{
|
|
||||||
PROTOBUF_C_ASSERT (message->base.descriptor == &nebula__nebula_msg__descriptor);
|
|
||||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
|
||||||
}
|
|
||||||
size_t nebula__nebula_msg__pack_to_buffer
|
|
||||||
(const Nebula__NebulaMsg *message,
|
|
||||||
ProtobufCBuffer *buffer)
|
|
||||||
{
|
|
||||||
PROTOBUF_C_ASSERT (message->base.descriptor == &nebula__nebula_msg__descriptor);
|
|
||||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
|
||||||
}
|
|
||||||
Nebula__NebulaMsg *
|
|
||||||
nebula__nebula_msg__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data)
|
|
||||||
{
|
|
||||||
return (Nebula__NebulaMsg *)
|
|
||||||
protobuf_c_message_unpack (&nebula__nebula_msg__descriptor,
|
|
||||||
allocator, len, data);
|
|
||||||
}
|
|
||||||
void nebula__nebula_msg__free_unpacked
|
|
||||||
(Nebula__NebulaMsg *message,
|
|
||||||
ProtobufCAllocator *allocator)
|
|
||||||
{
|
|
||||||
PROTOBUF_C_ASSERT (message->base.descriptor == &nebula__nebula_msg__descriptor);
|
|
||||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
|
||||||
}
|
|
||||||
static const ProtobufCFieldDescriptor nebula__nebula_msg__field_descriptors[2] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"msgid",
|
|
||||||
1,
|
|
||||||
PROTOBUF_C_LABEL_REQUIRED,
|
|
||||||
PROTOBUF_C_TYPE_STRING,
|
|
||||||
0, /* quantifier_offset */
|
|
||||||
PROTOBUF_C_OFFSETOF(Nebula__NebulaMsg, msgid),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* packed */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"body",
|
|
||||||
2,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_BYTES,
|
|
||||||
PROTOBUF_C_OFFSETOF(Nebula__NebulaMsg, has_body),
|
|
||||||
PROTOBUF_C_OFFSETOF(Nebula__NebulaMsg, body),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* packed */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
static const unsigned nebula__nebula_msg__field_indices_by_name[] = {
|
|
||||||
1, /* field[1] = body */
|
|
||||||
0, /* field[0] = msgid */
|
|
||||||
};
|
|
||||||
static const ProtobufCIntRange nebula__nebula_msg__number_ranges[1 + 1] =
|
|
||||||
{
|
|
||||||
{ 1, 0 },
|
|
||||||
{ 0, 2 }
|
|
||||||
};
|
|
||||||
const ProtobufCMessageDescriptor nebula__nebula_msg__descriptor =
|
|
||||||
{
|
|
||||||
PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
|
|
||||||
"Nebula.NebulaMsg",
|
|
||||||
"NebulaMsg",
|
|
||||||
"Nebula__NebulaMsg",
|
|
||||||
"Nebula",
|
|
||||||
sizeof(Nebula__NebulaMsg),
|
|
||||||
2,
|
|
||||||
nebula__nebula_msg__field_descriptors,
|
|
||||||
nebula__nebula_msg__field_indices_by_name,
|
|
||||||
1, nebula__nebula_msg__number_ranges,
|
|
||||||
(ProtobufCMessageInit) nebula__nebula_msg__init,
|
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
|
||||||
};
|
|
@ -1,66 +0,0 @@
|
|||||||
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
|
|
||||||
|
|
||||||
#ifndef PROTOBUF_C_nebula_2eproto__INCLUDED
|
|
||||||
#define PROTOBUF_C_nebula_2eproto__INCLUDED
|
|
||||||
|
|
||||||
#include <google/protobuf-c/protobuf-c.h>
|
|
||||||
|
|
||||||
PROTOBUF_C_BEGIN_DECLS
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _Nebula__NebulaMsg Nebula__NebulaMsg;
|
|
||||||
|
|
||||||
|
|
||||||
/* --- enums --- */
|
|
||||||
|
|
||||||
|
|
||||||
/* --- messages --- */
|
|
||||||
|
|
||||||
struct _Nebula__NebulaMsg
|
|
||||||
{
|
|
||||||
ProtobufCMessage base;
|
|
||||||
char *msgid;
|
|
||||||
protobuf_c_boolean has_body;
|
|
||||||
ProtobufCBinaryData body;
|
|
||||||
};
|
|
||||||
#define NEBULA__NEBULA_MSG__INIT \
|
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&nebula__nebula_msg__descriptor) \
|
|
||||||
, NULL, 0,{0,NULL} }
|
|
||||||
|
|
||||||
|
|
||||||
/* Nebula__NebulaMsg methods */
|
|
||||||
void nebula__nebula_msg__init
|
|
||||||
(Nebula__NebulaMsg *message);
|
|
||||||
size_t nebula__nebula_msg__get_packed_size
|
|
||||||
(const Nebula__NebulaMsg *message);
|
|
||||||
size_t nebula__nebula_msg__pack
|
|
||||||
(const Nebula__NebulaMsg *message,
|
|
||||||
uint8_t *out);
|
|
||||||
size_t nebula__nebula_msg__pack_to_buffer
|
|
||||||
(const Nebula__NebulaMsg *message,
|
|
||||||
ProtobufCBuffer *buffer);
|
|
||||||
Nebula__NebulaMsg *
|
|
||||||
nebula__nebula_msg__unpack
|
|
||||||
(ProtobufCAllocator *allocator,
|
|
||||||
size_t len,
|
|
||||||
const uint8_t *data);
|
|
||||||
void nebula__nebula_msg__free_unpacked
|
|
||||||
(Nebula__NebulaMsg *message,
|
|
||||||
ProtobufCAllocator *allocator);
|
|
||||||
/* --- per-message closures --- */
|
|
||||||
|
|
||||||
typedef void (*Nebula__NebulaMsg_Closure)
|
|
||||||
(const Nebula__NebulaMsg *message,
|
|
||||||
void *closure_data);
|
|
||||||
|
|
||||||
/* --- services --- */
|
|
||||||
|
|
||||||
|
|
||||||
/* --- descriptors --- */
|
|
||||||
|
|
||||||
extern const ProtobufCMessageDescriptor nebula__nebula_msg__descriptor;
|
|
||||||
|
|
||||||
PROTOBUF_C_END_DECLS
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* PROTOBUF_nebula_2eproto__INCLUDED */
|
|
@ -1,9 +0,0 @@
|
|||||||
package Nebula;
|
|
||||||
|
|
||||||
option java_package = "com.meizu.push.proto";
|
|
||||||
message NebulaMsg
|
|
||||||
{
|
|
||||||
required string msgid = 1; //消息id不加密不压缩
|
|
||||||
optional bytes body = 2; //消息内容(可能加密和压缩)
|
|
||||||
};
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
|||||||
#include "nebula_proto.h"
|
|
||||||
#include <time.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <uuid/uuid.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static const char* StrRequestType[] = {
|
|
||||||
"REQ PING",
|
|
||||||
"REQ AUTH",
|
|
||||||
"REQ MSGSYNC",
|
|
||||||
"REQ MSGPSH",
|
|
||||||
"REQ MSG",
|
|
||||||
"REQ MSGACK",
|
|
||||||
"REQ MSGFIN",
|
|
||||||
"REQ SUB",
|
|
||||||
"REQ SMS",
|
|
||||||
"REQ PRES",
|
|
||||||
"REQ ACCSTATUS",
|
|
||||||
"REQ INVITE",
|
|
||||||
"REQ ACK",
|
|
||||||
"REQ BYE",
|
|
||||||
"REQ UPDATE",
|
|
||||||
"REQ ACCUPDATE"
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char* StrResponseType[] = {
|
|
||||||
"RSP PING",
|
|
||||||
"RSP AUTH",
|
|
||||||
"RSP MSGSYNC",
|
|
||||||
"RSP MSGPSH",
|
|
||||||
"RSP MSG",
|
|
||||||
"RSP MSGACK",
|
|
||||||
"RSP MSGFIN",
|
|
||||||
"RSP SUB",
|
|
||||||
"RSP SMS",
|
|
||||||
"RSP PRES",
|
|
||||||
"RSP ACCSTATUS",
|
|
||||||
"RSP INVITE",
|
|
||||||
"RSP ACK",
|
|
||||||
"RSP BYE",
|
|
||||||
"RSP UPDATE",
|
|
||||||
"RSP ACCUPDATE"
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* MsgType2Str(uint8_t type)
|
|
||||||
{
|
|
||||||
uint8_t request_flag = (type >> 7 & 0x01);
|
|
||||||
uint8_t msg_type = type & 0x7F;
|
|
||||||
switch (msg_type) { //内部服务使用的协议
|
|
||||||
case NEBULA_KIEV_ACCOFFLINE:
|
|
||||||
return (request_flag ? "REQ ACCOFFLINE" : "RSP ACCOFFLINE");
|
|
||||||
case NEBULA_KIEV_ACCONLINE:
|
|
||||||
return (request_flag ? "REQ ACCONLINE" : "RSP ACCONLINE");
|
|
||||||
case NEBULA_KIEV_MSGACK:
|
|
||||||
return (request_flag ? "REQ KIEVACK" : "RSP KIEVACK");
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IS_VALID_TYPE(type)) {
|
|
||||||
return (request_flag ? "REQ UnKnown": "RSP UnKnown");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request_flag) {
|
|
||||||
return StrRequestType[msg_type - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return StrResponseType[msg_type-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t CreateMachineId()
|
|
||||||
{
|
|
||||||
uuid_t uuid = {0};
|
|
||||||
char str[37];
|
|
||||||
uint32_t hash = 5381;
|
|
||||||
|
|
||||||
memset(str, 0, sizeof(str));
|
|
||||||
uuid_generate(uuid);
|
|
||||||
uuid_unparse(uuid, str);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for(i=0; i<36; i++) {
|
|
||||||
hash = ((hash << 5) + hash) + str[i];
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CreateMsgid(char *msgid)
|
|
||||||
{
|
|
||||||
static uint32_t machine_id;
|
|
||||||
static uint32_t ref_cnt = 0;
|
|
||||||
if (ref_cnt == 0) {
|
|
||||||
machine_id = CreateMachineId();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MsgId {
|
|
||||||
uint32_t timestamp;
|
|
||||||
uint32_t hash:24;
|
|
||||||
uint16_t pid;
|
|
||||||
uint32_t cnt:24;
|
|
||||||
}__attribute__((packed));
|
|
||||||
|
|
||||||
struct MsgId id;
|
|
||||||
id.timestamp = time(0);
|
|
||||||
id.hash = machine_id;
|
|
||||||
id.pid = getpid();
|
|
||||||
id.cnt = ref_cnt++;
|
|
||||||
sprintf(msgid, "%08x%06x%04x%06x", id.timestamp, id.hash, id.pid, id.cnt);
|
|
||||||
msgid[24] = '\0';
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* FileName:
|
|
||||||
* Description:
|
|
||||||
* Version:
|
|
||||||
* History:
|
|
||||||
* yuxiaobo 2014-12-23 1.0 created
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
#ifndef __NEBULA_PROTO_H__
|
|
||||||
#define __NEBULA_PROTO_H__
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
struct _NebulaHeader
|
|
||||||
{
|
|
||||||
uint8_t magic;
|
|
||||||
uint8_t ver;
|
|
||||||
uint8_t flag;
|
|
||||||
uint8_t type;
|
|
||||||
uint16_t len;
|
|
||||||
}__attribute__((packed));
|
|
||||||
|
|
||||||
typedef struct _NebulaHeader NebulaHeader;
|
|
||||||
|
|
||||||
#define NEBULA_MSG_PING 0x01
|
|
||||||
#define NEBULA_MSG_AUTH 0x02
|
|
||||||
#define NEBULA_MSG_SYNC 0x03
|
|
||||||
#define NEBULA_MSG_PSH 0x04
|
|
||||||
#define NEBULA_MSG_MSG 0x05
|
|
||||||
#define NEBULA_MSG_ACK 0x06
|
|
||||||
#define NEBULA_MSG_FIN 0x07
|
|
||||||
#define NEBULA_MSG_SUB 0x08
|
|
||||||
#define NEBULA_MSG_SMS 0x09
|
|
||||||
#define NEBULA_MSG_PRES 0x0A
|
|
||||||
#define NEBULA_MSG_ACCSTATUS 0x0B
|
|
||||||
#define NEBULA_MSG_INVITE 0x0C
|
|
||||||
#define NEBULA_MSG_DIALOGACK 0x0D
|
|
||||||
#define NEBULA_MSG_BYE 0x0E
|
|
||||||
#define NEBULA_MSG_UPDATE 0x0F
|
|
||||||
#define NEBULA_MSG_ACCUPDATE 0x10
|
|
||||||
|
|
||||||
#define NEBULA_KIEV_ACCOFFLINE 0x7D
|
|
||||||
#define NEBULA_KIEV_ACCONLINE 0x7E
|
|
||||||
#define NEBULA_KIEV_MSGACK 0x7F
|
|
||||||
|
|
||||||
#define MSG_IS_REQUEST(head) (((head)->type >> 7) & 0x01)
|
|
||||||
#define MSG_SET_REQUEST(type) (0x80 | type)
|
|
||||||
|
|
||||||
const char* MsgType2Str(uint8_t type);
|
|
||||||
|
|
||||||
#define IS_VALID_TYPE(type) (((type) & 0x7F) > 0 && ((type) & 0x7F) <= 0x10)
|
|
||||||
|
|
||||||
#define HEAD_INIT(h,t) \
|
|
||||||
do { \
|
|
||||||
(h)->magic = 0xF8; \
|
|
||||||
(h)->ver = 0x01; \
|
|
||||||
(h)->flag = 0x00; \
|
|
||||||
(h)->type = (t); \
|
|
||||||
(h)->len = 0; \
|
|
||||||
}while(0)
|
|
||||||
|
|
||||||
|
|
||||||
#define MSG_ID_LEN 24
|
|
||||||
/*
|
|
||||||
* 生成msgid
|
|
||||||
* @param msgid 长度必须是MSG_ID_LEN+1
|
|
||||||
*/
|
|
||||||
void CreateMsgid(char *msgid);
|
|
||||||
|
|
||||||
#endif
|
|
Binary file not shown.
@ -1,143 +0,0 @@
|
|||||||
#include "push.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "connect.h"
|
|
||||||
#include "dict.h"
|
|
||||||
#include "message.pb-c.h"
|
|
||||||
#include "nebula_proto.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
dict *g_seq_dict = NULL;
|
|
||||||
|
|
||||||
static unsigned int __hashFunction(const void *key)
|
|
||||||
{
|
|
||||||
return dictGenHashFunction((const char*)key, strlen((const char*)key));
|
|
||||||
}
|
|
||||||
|
|
||||||
void* __keyDup(void *privdata, const void *key)
|
|
||||||
{
|
|
||||||
(void)privdata;
|
|
||||||
return strdup((const char*)key);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __keyCompare(void *privdata, const void *key1, const void *key2)
|
|
||||||
{
|
|
||||||
(void)privdata;
|
|
||||||
return strcmp((const char*)key1, (const char*)key2) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __keyDestructor(void *privdata, void *key)
|
|
||||||
{
|
|
||||||
(void)privdata;
|
|
||||||
free(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaInitPush()
|
|
||||||
{
|
|
||||||
if (g_seq_dict) return 0;
|
|
||||||
|
|
||||||
static dictType type = {
|
|
||||||
__hashFunction,
|
|
||||||
__keyDup,
|
|
||||||
NULL,
|
|
||||||
__keyCompare,
|
|
||||||
__keyDestructor,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
g_seq_dict = dictCreate(&type, NULL);
|
|
||||||
if (!g_seq_dict)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SendSync(int type)
|
|
||||||
{
|
|
||||||
Nebula__MessageSeq request;
|
|
||||||
nebula__message_seq__init(&request);
|
|
||||||
size_t seq_size = dictSize(g_seq_dict);
|
|
||||||
request.n_content = seq_size;
|
|
||||||
request.content = (Nebula__MessageSeq__Content**)malloc(sizeof(void*) * seq_size);
|
|
||||||
|
|
||||||
dictIterator *it = dictGetIterator(g_seq_dict);
|
|
||||||
dictEntry *entry = dictNext(it);
|
|
||||||
size_t i = 0;
|
|
||||||
while (entry) {
|
|
||||||
request.content[i] = (Nebula__MessageSeq__Content*)malloc(sizeof(Nebula__MessageSeq__Content));
|
|
||||||
nebula__message_seq__content__init(request.content[i]);
|
|
||||||
request.content[i]->account = (char*)entry->key;
|
|
||||||
request.content[i]->seq = entry->v.u64;
|
|
||||||
i++;
|
|
||||||
entry = dictNext(it);
|
|
||||||
}
|
|
||||||
dictReleaseIterator(it);
|
|
||||||
|
|
||||||
// send
|
|
||||||
int ret = NebulaSend(type, (ProtobufCMessage*)&request);
|
|
||||||
|
|
||||||
for (i = 0; i < seq_size; ++i)
|
|
||||||
{
|
|
||||||
free(request.content[i]);
|
|
||||||
}
|
|
||||||
free(request.content);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaOnPush(NebulaHeader *head, const char* data, int len)
|
|
||||||
{
|
|
||||||
(void)head, (void)data, (void)len;
|
|
||||||
if (-1 == SendSync(MSG_SET_REQUEST(NEBULA_MSG_SYNC))) {
|
|
||||||
log_error("SendSync failed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaOnMsg(NebulaHeader *head, const char* data, int len)
|
|
||||||
{
|
|
||||||
(void)head;
|
|
||||||
Nebula__Message *message = nebula__message__unpack(NULL, len, (const uint8_t*)data);
|
|
||||||
if (!message) {
|
|
||||||
log_error("parse NebulaMessage failed.");
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < message->n_content; ++i)
|
|
||||||
{
|
|
||||||
Nebula__Message__Content *ctn = message->content[i];
|
|
||||||
if ((int)ctn->type >= eNebulaMsg_Max) {
|
|
||||||
log_warn("discard unkown type message. type=%d", ctn->type);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dictEntry * entry = dictFind(g_seq_dict, ctn->account);
|
|
||||||
if (!entry || ctn->seq > entry->v.u64) {
|
|
||||||
log_debug("recv message. type=%s, account=%s, seq=%u, hasbody=%d, bodylength=%lu",
|
|
||||||
Nebulamsgtype_name(ctn->type), ctn->account, ctn->seq, ctn->has_body, ctn->body.len);
|
|
||||||
if (!ctn->has_body) {
|
|
||||||
log_warn("message has not body, discard it!");
|
|
||||||
} else if (g_nebula_cb[ctn->type])
|
|
||||||
g_nebula_cb[ctn->type]((const char*)ctn->body.data, ctn->body.len);
|
|
||||||
|
|
||||||
// refresh sequence
|
|
||||||
if (entry) {
|
|
||||||
entry->v.u64 = ctn->seq;
|
|
||||||
} else {
|
|
||||||
if (DICT_OK != dictAdd(g_seq_dict, ctn->account, (void*)(uint64_t)ctn->seq)) {
|
|
||||||
log_error("refresh sequence number error, maybe memory was deplete.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log_warn("discard message. type=%s, account=%s, seq=%u, hasbody=%d, bodylength=%lu",
|
|
||||||
Nebulamsgtype_name(ctn->type), ctn->account, ctn->seq, ctn->has_body, ctn->body.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message->has_flag) {
|
|
||||||
if (message->flag == NEBULA__MESSAGE__FLAG__MESSAGE_ACK)
|
|
||||||
SendSync(MSG_SET_REQUEST(NEBULA_MSG_ACK));
|
|
||||||
else if (message->flag == NEBULA__MESSAGE__FLAG__MESSAGE_END)
|
|
||||||
SendSync(MSG_SET_REQUEST(NEBULA_MSG_FIN));
|
|
||||||
}
|
|
||||||
|
|
||||||
nebula__message__free_unpacked(message, NULL);
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
|||||||
#ifndef PUSH_H
|
|
||||||
#define PUSH_H
|
|
||||||
|
|
||||||
#include "nebula_proto.h"
|
|
||||||
|
|
||||||
// push
|
|
||||||
// Send sync request to server when received MSGPUSH.
|
|
||||||
// Remember push sequences in memory.
|
|
||||||
|
|
||||||
int NebulaInitPush();
|
|
||||||
|
|
||||||
void NebulaOnPush(NebulaHeader *head, const char* data, int len);
|
|
||||||
|
|
||||||
void NebulaOnMsg(NebulaHeader *head, const char* data, int len);
|
|
||||||
|
|
||||||
#endif //PUSH_H
|
|
Binary file not shown.
@ -1,261 +0,0 @@
|
|||||||
#include "redirect.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <openssl/md5.h>
|
|
||||||
#include <json-c/json.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "str.h"
|
|
||||||
|
|
||||||
List *g_redirect_result = NULL;
|
|
||||||
time_t g_last_redirect = 0;
|
|
||||||
char* g_salt = NULL;
|
|
||||||
char* g_rule = NULL;
|
|
||||||
|
|
||||||
ssize_t NebulaRedirectOnRead(const void *ptr, size_t size, size_t nmemb, FILE *stream)
|
|
||||||
{
|
|
||||||
(void)size, (void)stream;
|
|
||||||
struct str *result = (struct str *)stream;
|
|
||||||
string_append_fast(result, (const char*)ptr, nmemb);
|
|
||||||
return nmemb;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaCloneRedirectResult()
|
|
||||||
{
|
|
||||||
if (!g_redirect_result) return -1;
|
|
||||||
if (g_redirect_result->size == 0) return -1;
|
|
||||||
|
|
||||||
if (g_server_list)
|
|
||||||
ClearList(g_server_list);
|
|
||||||
else
|
|
||||||
g_server_list = CreateList();
|
|
||||||
|
|
||||||
if (!g_server_list) goto on_error;
|
|
||||||
|
|
||||||
ListIterator it;
|
|
||||||
for (it = ListBegin(g_redirect_result); it; it = ListNext(it)) {
|
|
||||||
struct sockaddr_in *r_addr = (struct sockaddr_in *)(*it);
|
|
||||||
struct sockaddr_in *addr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
|
|
||||||
if (!addr) {
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
addr->sin_port = r_addr->sin_port;
|
|
||||||
addr->sin_addr.s_addr = r_addr->sin_addr.s_addr;
|
|
||||||
if (-1 == PushBack(g_server_list, addr)) {
|
|
||||||
free(addr);
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
on_error:
|
|
||||||
if (g_server_list)
|
|
||||||
ClearList(g_server_list);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NebulaRedirect()
|
|
||||||
{
|
|
||||||
time_t now = time(0);
|
|
||||||
if (now - g_last_redirect < 300) {
|
|
||||||
if (0 == NebulaCloneRedirectResult()) {
|
|
||||||
log_info("not timeout, use last redirect result always.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_last_redirect = now;
|
|
||||||
|
|
||||||
static const char* key = "key=89d15f8b716d4b16fae9feaa09bc4fc5&";
|
|
||||||
struct str result;
|
|
||||||
string_init(&result);
|
|
||||||
struct json_object* response = NULL;
|
|
||||||
List *server_list = NULL;
|
|
||||||
|
|
||||||
// post parameters.
|
|
||||||
struct str params;
|
|
||||||
string_init(¶ms);
|
|
||||||
string_append_fast(¶ms, "uid=", 4);
|
|
||||||
string_append_fast(¶ms, g_device_tag, strlen(g_device_tag));
|
|
||||||
string_append_fast(¶ms, "&nonce=", 7);
|
|
||||||
const char* nonce = Nebularand_string();
|
|
||||||
string_append_fast(¶ms, nonce, strlen(nonce));
|
|
||||||
string_append_fast(¶ms, "&ts=", 4);
|
|
||||||
time_t t = time(0);
|
|
||||||
char ts[32];
|
|
||||||
snprintf(ts, sizeof(ts), "%ld", t);
|
|
||||||
string_append_fast(¶ms, ts, strlen(ts));
|
|
||||||
|
|
||||||
// sign
|
|
||||||
unsigned char sign_str[MD5_DIGEST_LENGTH], sign[MD5_DIGEST_LENGTH * 2];
|
|
||||||
char md5buf[512];
|
|
||||||
snprintf(md5buf, sizeof(md5buf), "%s%s", key, params.ptr);
|
|
||||||
MD5((const unsigned char*)md5buf, strlen(md5buf), sign_str);
|
|
||||||
static const char hex[] = "0123456789abcdef";
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < MD5_DIGEST_LENGTH; i++)
|
|
||||||
{
|
|
||||||
sign[i * 2] = hex[sign_str[i] >> 4];
|
|
||||||
sign[i * 2 + 1] = hex[sign_str[i] & 0xf];
|
|
||||||
}
|
|
||||||
string_append_fast(¶ms, "&sign=", 6);
|
|
||||||
string_append_fast(¶ms, (const char*)sign, sizeof(sign));
|
|
||||||
|
|
||||||
CURL *curl = curl_easy_init();
|
|
||||||
char url[128] = {};
|
|
||||||
snprintf(url, sizeof(url), "%s/push/redirect", g_nebula_host);
|
|
||||||
//const char* url = "https://p.meizu.com/push/redirect";
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &NebulaRedirectOnRead);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, params.ptr);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, params.len);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
|
|
||||||
log_info("HTTPS POST. url=%s, params=%s", url, params.ptr);
|
|
||||||
CURLcode res = curl_easy_perform(curl);
|
|
||||||
if (res != CURLE_OK) {
|
|
||||||
log_error("curl_easy_perform(redirect) error. code=%d, info=%s",
|
|
||||||
(int)res, curl_easy_strerror(res));
|
|
||||||
goto on_error;
|
|
||||||
} else {
|
|
||||||
log_info("curl_easy_perform success. response=%s", result.ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse response json.
|
|
||||||
response = json_tokener_parse(result.ptr);
|
|
||||||
string_deinit(&result);
|
|
||||||
if (!response) {
|
|
||||||
log_error("json parse error.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct json_object* code_node = json_object_object_get(response, "code");
|
|
||||||
if (!code_node) {
|
|
||||||
log_error("json parse error, hasnot \"code\" node.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int code = json_object_get_int(code_node);
|
|
||||||
if (code != 200) {
|
|
||||||
// redirect failed.
|
|
||||||
log_error("json response code error. code=%d", code);
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct json_object *md5_daa = json_object_object_get(response, "md5_daa");
|
|
||||||
if (!md5_daa) {
|
|
||||||
log_error("json response has no md5_daa field.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
struct json_object *salt_node = json_object_object_get(md5_daa, "salt");
|
|
||||||
if (!salt_node) {
|
|
||||||
log_error("json response has no md5_daa.salt field.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
const char* salt = json_object_get_string(salt_node);
|
|
||||||
if (!salt) {
|
|
||||||
log_error("json response has no md5_daa.salt field.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
if (g_salt) free(g_salt);
|
|
||||||
g_salt = strdup(salt);
|
|
||||||
|
|
||||||
struct json_object *rule_node = json_object_object_get(md5_daa, "rule");
|
|
||||||
if (!rule_node) {
|
|
||||||
log_error("json response has no md5_daa.rule field.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
const char* rule = json_object_get_string(rule_node);
|
|
||||||
if (!rule) {
|
|
||||||
log_error("json response has no md5_daa.rule field.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
if (g_rule) free(g_rule);
|
|
||||||
g_rule = strdup(rule);
|
|
||||||
|
|
||||||
struct json_object* host_list_node = json_object_object_get(response, "hostlist");
|
|
||||||
if (!host_list_node) {
|
|
||||||
log_error("json parse error, hasnot \"hostlist\" node.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct array_list* host_list = json_object_get_array(host_list_node);
|
|
||||||
if (!host_list) {
|
|
||||||
log_error("json_object_get_array error.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int host_count = array_list_length(host_list);
|
|
||||||
if (!host_count) {
|
|
||||||
log_error("host list is empty.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
server_list = CreateList();
|
|
||||||
if (!server_list) {
|
|
||||||
log_error("create server list error, maybe memory was deplete.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < host_count; ++i)
|
|
||||||
{
|
|
||||||
struct json_object* elem = (struct json_object*)array_list_get_idx(host_list, i);
|
|
||||||
if (!elem) {
|
|
||||||
log_error("host list get idx error, i=%d.", i);
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct json_object* ip_node = json_object_object_get(elem, "ip");
|
|
||||||
if (!ip_node) {
|
|
||||||
log_error("host list get ip error, i=%d.", i);
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
const char* ip = json_object_get_string(ip_node);
|
|
||||||
int ip_len = json_object_get_string_len(ip_node);
|
|
||||||
if (!ip || !ip_len) {
|
|
||||||
log_error("host list get ip error, i=%d.", i);
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct json_object* port_node = json_object_object_get(elem, "port");
|
|
||||||
int port = json_object_get_int(port_node);
|
|
||||||
if (!port) {
|
|
||||||
log_error("host list get port error, i=%d.", i);
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in *addr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
|
|
||||||
if (!addr) {
|
|
||||||
log_error("malloc sockaddr_in failed.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr->sin_port = htons(port);
|
|
||||||
addr->sin_addr.s_addr = inet_addr(ip);
|
|
||||||
if (-1 == PushBack(server_list, addr)) {
|
|
||||||
log_error("PushBack to server_list error, maybe memory was deplete.");
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_redirect_result)
|
|
||||||
DestroyList(g_redirect_result);
|
|
||||||
|
|
||||||
g_redirect_result = server_list;
|
|
||||||
server_list = NULL;
|
|
||||||
return NebulaCloneRedirectResult();
|
|
||||||
|
|
||||||
on_error:
|
|
||||||
string_deinit(&result);
|
|
||||||
if (response)
|
|
||||||
json_object_put(response);
|
|
||||||
if (server_list)
|
|
||||||
DestroyList(server_list);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
|||||||
#ifndef REDIRECT_H
|
|
||||||
#define REDIRECT_H
|
|
||||||
|
|
||||||
/** redirect
|
|
||||||
* @Launch http request to p.meizu.com, get server ip list.
|
|
||||||
* @Block function.
|
|
||||||
*/
|
|
||||||
int NebulaRedirect();
|
|
||||||
|
|
||||||
#endif //REDIRECT_H
|
|
Binary file not shown.
@ -1,131 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "str.h"
|
|
||||||
|
|
||||||
#define DEFAULT_STRING_SIZE 32
|
|
||||||
#define SMAX(a, b) ((a) > (b) ? (a) : (b))
|
|
||||||
|
|
||||||
void string_init(struct str *str)
|
|
||||||
{
|
|
||||||
str->size = 0;
|
|
||||||
str->len = 0;
|
|
||||||
str->ptr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void string_deinit(struct str *str)
|
|
||||||
{
|
|
||||||
if(str->ptr){
|
|
||||||
free(str->ptr);
|
|
||||||
string_init(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool string_empty(const struct str *str)
|
|
||||||
{
|
|
||||||
return str->len == 0 ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int string_duplicate(struct str *dst, const struct str *src)
|
|
||||||
{
|
|
||||||
string_reset(dst);
|
|
||||||
return string_append(dst, src->ptr, src->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int string_copy(struct str *dst, const char *src, size_t srclen)
|
|
||||||
{
|
|
||||||
string_reset(dst);
|
|
||||||
return string_append(dst, src, srclen);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
|
||||||
static int vasprintf(char **buf, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
static char _T_emptybuffer = '\0';
|
|
||||||
int chars;
|
|
||||||
char *b;
|
|
||||||
|
|
||||||
if(!buf) { return -1; }
|
|
||||||
|
|
||||||
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
|
|
||||||
if(chars < 0) {
|
|
||||||
chars *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
b = (char*)malloc(sizeof(char)*chars);
|
|
||||||
if(!b) { return -1; }
|
|
||||||
if((chars = vsprintf(b, fmt, ap)) < 0)
|
|
||||||
{
|
|
||||||
free(b);
|
|
||||||
} else {
|
|
||||||
*buf = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
return chars;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int string_sprintf(struct str *str, const char* fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
char *t = NULL;
|
|
||||||
int size;
|
|
||||||
char buf[128];
|
|
||||||
|
|
||||||
// string_reset(str);
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
size = vsnprintf(buf, 128, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if(size == -1 || size > 127) {
|
|
||||||
va_start(ap, fmt);
|
|
||||||
if((size = vasprintf(&t, fmt, ap)) == -1) {
|
|
||||||
va_end(ap);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
size = string_append(str, t, size);
|
|
||||||
free(t);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string_append(str, buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int string_compare(const struct str *s1, const struct str *s2)
|
|
||||||
{
|
|
||||||
if (s1->len != s2->len) {
|
|
||||||
return s1->len - s2->len > 0 ? 1 : -1;
|
|
||||||
}
|
|
||||||
return strncmp(s1->ptr, s2->ptr, s1->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void string_reset(struct str *str)
|
|
||||||
{
|
|
||||||
if(str->ptr) {
|
|
||||||
str->len = 0;
|
|
||||||
str->ptr[0] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int string_append(struct str *str, const char *buf, size_t buflen)
|
|
||||||
{
|
|
||||||
if( str->size - str->len <= buflen ) {
|
|
||||||
size_t new_size = SMAX(DEFAULT_STRING_SIZE,
|
|
||||||
SMAX(str->size * 2, str->len + buflen + 8));
|
|
||||||
char *t = (char*)realloc(str->ptr, new_size);
|
|
||||||
if( t == NULL )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
str->size = new_size;
|
|
||||||
str->ptr = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(str->ptr + str->len, buf, buflen);
|
|
||||||
str->len += buflen;
|
|
||||||
str->ptr[str->len] = '\0';
|
|
||||||
return buflen;
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
#ifndef __STUN_STRING_H__
|
|
||||||
#define __STUN_STRING_H__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
struct str{
|
|
||||||
size_t size; /*buf所占内存长度*/
|
|
||||||
size_t len; /*buf字符长度*/
|
|
||||||
char* ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
void string_init(struct str *str);
|
|
||||||
|
|
||||||
void string_deinit(struct str *str);
|
|
||||||
|
|
||||||
bool string_empty(const struct str *str);
|
|
||||||
|
|
||||||
int string_duplicate(struct str *dst, const struct str *src);
|
|
||||||
|
|
||||||
int string_copy(struct str *dst, const char *src, size_t srclen);
|
|
||||||
|
|
||||||
int string_sprintf(struct str *str, const char* fmt, ...);
|
|
||||||
|
|
||||||
int string_compare(const struct str *s1, const struct str *s2);
|
|
||||||
|
|
||||||
void string_reset(struct str *str);
|
|
||||||
|
|
||||||
int string_append(struct str *str, const char *buf, size_t buflen);
|
|
||||||
|
|
||||||
#define string_length(s) ((s)->len)
|
|
||||||
|
|
||||||
#define string_append_fast(s, bufptr, bufsize) \
|
|
||||||
do { \
|
|
||||||
if (((s)->size - (s)->len) > bufsize) { \
|
|
||||||
memcpy((s)->ptr + (s)->len, (bufptr), bufsize); \
|
|
||||||
(s)->len += bufsize; \
|
|
||||||
(s)->ptr[(s)->len] = '\0'; \
|
|
||||||
} else { \
|
|
||||||
string_append((s), (bufptr), bufsize); \
|
|
||||||
} \
|
|
||||||
}while(0)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Binary file not shown.
@ -1,108 +0,0 @@
|
|||||||
#include "subscribe.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "message.pb-c.h"
|
|
||||||
#include "nebula_proto.h"
|
|
||||||
#include "connect.h"
|
|
||||||
#include <time.h>
|
|
||||||
#include "archive.h"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
eSubStatus_Init,
|
|
||||||
eSubStatus_WaitResponse,
|
|
||||||
eSubStatus_Done,
|
|
||||||
} eSubStatus;
|
|
||||||
|
|
||||||
static eSubStatus g_sub_status = eSubStatus_Init;
|
|
||||||
static time_t g_sub_tick = 0;
|
|
||||||
|
|
||||||
int subscribe()
|
|
||||||
{
|
|
||||||
int count = 0, i;
|
|
||||||
char** sub_apps = (char**)malloc(g_sub_app_count * sizeof(char*));
|
|
||||||
if (!sub_apps) return -1;
|
|
||||||
|
|
||||||
for (i = 0; i < g_sub_app_count; ++i)
|
|
||||||
{
|
|
||||||
if (NebulaIsSubscribed(g_sub_apps[i])) continue;
|
|
||||||
sub_apps[count++] = g_sub_apps[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!count) return 1;
|
|
||||||
|
|
||||||
Nebula__SubscribeRequest request;
|
|
||||||
nebula__subscribe_request__init(&request);
|
|
||||||
request.n_app = count;
|
|
||||||
request.app = sub_apps;
|
|
||||||
int ret = NebulaSend(MSG_SET_REQUEST(NEBULA_MSG_SUB), (ProtobufCMessage*)&request);
|
|
||||||
free(sub_apps);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaOnSubSuccess(const char* appname)
|
|
||||||
{
|
|
||||||
// TODO: save subscribe app and sub time.
|
|
||||||
log_info("sub %s success.", appname);
|
|
||||||
NebulaAddSubApp(appname);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NebulaOnSub(NebulaHeader *head, const char* data, int len)
|
|
||||||
{
|
|
||||||
Nebula__SubscribeResponse *response = nebula__subscribe_response__unpack(NULL, len, (const uint8_t*)data);
|
|
||||||
if (!response) {
|
|
||||||
log_error("subcribe response parse error.");
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response->status != 200) {
|
|
||||||
log_error("subcribe failed. status=%d", response->status);
|
|
||||||
nebula__subscribe_response__free_unpacked(response, NULL);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < response->n_content; ++i)
|
|
||||||
{
|
|
||||||
Nebula__SubscribeResponse__Content *ctn = response->content[i];
|
|
||||||
if (ctn->status == 200) {
|
|
||||||
NebulaOnSubSuccess(ctn->app);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_sub_status = eSubStatus_Done;
|
|
||||||
nebula__subscribe_response__free_unpacked(response, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int subscribe_loop()
|
|
||||||
{
|
|
||||||
if (!g_sub_app_count) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret;
|
|
||||||
switch (g_sub_status) {
|
|
||||||
case eStatus_Init:
|
|
||||||
ret = subscribe();
|
|
||||||
if (ret == 0) {
|
|
||||||
g_sub_status = eSubStatus_WaitResponse;
|
|
||||||
g_sub_tick = clock();
|
|
||||||
} else if (ret == 1) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eSubStatus_WaitResponse:
|
|
||||||
if (clock() - g_sub_tick > 10000) {
|
|
||||||
// timeout
|
|
||||||
g_sub_status = eSubStatus_Init;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eSubStatus_Done:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
#ifndef SUBSCRIBE_H
|
|
||||||
#define SUBSCRIBE_H
|
|
||||||
|
|
||||||
#include "nebula_proto.h"
|
|
||||||
|
|
||||||
int subscribe_loop();
|
|
||||||
|
|
||||||
void NebulaOnSub(NebulaHeader *head, const char* data, int len);
|
|
||||||
|
|
||||||
#endif //SUBSCRIBE_H
|
|
Binary file not shown.
@ -1,12 +0,0 @@
|
|||||||
CC=gcc
|
|
||||||
CFALGS=-g
|
|
||||||
INCLUDES=-I..
|
|
||||||
LINK=-L.. -lnebula_sdk
|
|
||||||
|
|
||||||
test:test.c
|
|
||||||
$(CC) $(CFALGS) $^ -o $@ $(INCLUDES) $(LINK)
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm test -f
|
|
@ -1,5 +0,0 @@
|
|||||||
2
|
|
||||||
com.meizu.cloud
|
|
||||||
com.meizu.router
|
|
||||||
1
|
|
||||||
R10WZOANC5400EE&0 21
|
|
Binary file not shown.
@ -1,56 +0,0 @@
|
|||||||
#ifndef NEBULA_SDK_H
|
|
||||||
#define NEBULA_SDK_H
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
eNebulaMsg_Push, /// 推送 (路由器只需关心这一类消息)
|
|
||||||
eNebulaMsg_Presence, /// Presence
|
|
||||||
eNebulaMsg_Sms, /// 网络短信
|
|
||||||
eNebulaMsg_Mms, /// 网络彩信
|
|
||||||
eNebulaMsg_Max,
|
|
||||||
} NebulaMsgType;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** 初始化网络连接
|
|
||||||
* @device_tag: 硬件信息 (手机端为IMEI)
|
|
||||||
* @verify_pwd: 鉴权密码 (手机端为SN)
|
|
||||||
* @host: 服务端域名, 例如: https://p.meizu.com (结尾不要带"/", 前面要加上https)
|
|
||||||
* @file: 用于读取/存储持久化数据的文件名, 要求目录存在, 且有创建文件权限。
|
|
||||||
* @return: 如果文件打开成功, 返回0; 否则返回-1, 文件打开失败原因记录在错误码errno中.
|
|
||||||
* @只能调用一次, 重复调用无效并返回-1.
|
|
||||||
*/
|
|
||||||
int NebulaInit(const char* device_tag, const char* host, const char* file);
|
|
||||||
|
|
||||||
/** 设置订阅列表
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void NebulaSubScribe(int count, const char** app_name);
|
|
||||||
|
|
||||||
/** 消息处理回调函数
|
|
||||||
* @app: App名
|
|
||||||
* @msg: 消息内容
|
|
||||||
*/
|
|
||||||
typedef void (*NebulaMsgCallback)(const char* app, const char* msg);
|
|
||||||
|
|
||||||
/** 注册消息处理回调函数
|
|
||||||
* @type: 消息类型
|
|
||||||
* @cb: 回调函数
|
|
||||||
* @return: 旧的回调函数
|
|
||||||
* @一次只能注册一个回调函数, 重复注册会覆盖.
|
|
||||||
*/
|
|
||||||
NebulaMsgCallback NebulaRegister(NebulaMsgType type, NebulaMsgCallback cb);
|
|
||||||
|
|
||||||
/** 启动
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int NebulaStart();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //NEBULA_SDK_H
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
|||||||
#ifndef NEBULA_SDK_H
|
|
||||||
#define NEBULA_SDK_H
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
eNebulaMsg_Push, /// 推送 (路由器只需关心这一类消息)
|
|
||||||
eNebulaMsg_Presence, /// Presence
|
|
||||||
eNebulaMsg_Sms, /// 网络短信
|
|
||||||
eNebulaMsg_Mms, /// 网络彩信
|
|
||||||
eNebulaMsg_Max,
|
|
||||||
} NebulaMsgType;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** 初始化网络连接
|
|
||||||
* @device_tag: 硬件信息 (手机端为IMEI)
|
|
||||||
* @verify_pwd: 鉴权密码 (手机端为SN)
|
|
||||||
* @host: 服务端域名, 例如: https://p.meizu.com (结尾不要带"/", 前面要加上https)
|
|
||||||
* @file: 用于读取/存储持久化数据的文件名, 要求目录存在, 且有创建文件权限。
|
|
||||||
* @return: 如果文件打开成功, 返回0; 否则返回-1, 文件打开失败原因记录在错误码errno中.
|
|
||||||
* @只能调用一次, 重复调用无效并返回-1.
|
|
||||||
*/
|
|
||||||
int NebulaInit(const char* device_tag, const char* host, const char* file);
|
|
||||||
|
|
||||||
/** 设置订阅列表
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void NebulaSubScribe(int count, const char** app_name);
|
|
||||||
|
|
||||||
/** 消息处理回调函数
|
|
||||||
* @data: 数据块起始指针
|
|
||||||
* @len: 数据块长度
|
|
||||||
*/
|
|
||||||
typedef void (*NebulaMsgCallback)(const char* data, int len);
|
|
||||||
|
|
||||||
/** 注册消息处理回调函数
|
|
||||||
* @type: 消息类型
|
|
||||||
* @cb: 回调函数
|
|
||||||
* @return: 旧的回调函数
|
|
||||||
* @一次只能注册一个回调函数, 重复注册会覆盖.
|
|
||||||
*/
|
|
||||||
NebulaMsgCallback NebulaRegister(NebulaMsgType type, NebulaMsgCallback cb);
|
|
||||||
|
|
||||||
/** 启动
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int NebulaStart();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //NEBULA_SDK_H
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
@ -1,20 +0,0 @@
|
|||||||
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
|
||||||
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
|
||||||
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
|
|
||||||
!_TAG_PROGRAM_NAME Exuberant Ctags //
|
|
||||||
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
|
|
||||||
!_TAG_PROGRAM_VERSION 5.9~svn20110310 //
|
|
||||||
CC Makefile /^CC=gcc$/;" m
|
|
||||||
CFALGS Makefile /^CFALGS=-g$/;" m
|
|
||||||
INCLUDES Makefile /^INCLUDES=-I..$/;" m
|
|
||||||
LINK Makefile /^LINK=-L.. -lnebula_sdk$/;" m
|
|
||||||
NEBULA_SDK_H nebula_sdk/nebula_sdk.h 2;" d
|
|
||||||
NebulaMsgCallback nebula_sdk/nebula_sdk.h /^ typedef void (*NebulaMsgCallback)(const char* app, const char* msg);$/;" t
|
|
||||||
NebulaMsgType nebula_sdk/nebula_sdk.h /^} NebulaMsgType;$/;" t typeref:enum:__anon1
|
|
||||||
OnPush test.c /^void OnPush(const char* app, const char *msg)$/;" f
|
|
||||||
eNebulaMsg_Max nebula_sdk/nebula_sdk.h /^ eNebulaMsg_Max,$/;" e enum:__anon1
|
|
||||||
eNebulaMsg_Mms nebula_sdk/nebula_sdk.h /^ eNebulaMsg_Mms, \/\/\/ 网络彩信$/;" e enum:__anon1
|
|
||||||
eNebulaMsg_Presence nebula_sdk/nebula_sdk.h /^ eNebulaMsg_Presence, \/\/\/ Presence$/;" e enum:__anon1
|
|
||||||
eNebulaMsg_Push nebula_sdk/nebula_sdk.h /^ eNebulaMsg_Push, \/\/\/ 推送 (路由器只需关心这一类消息)$/;" e enum:__anon1
|
|
||||||
eNebulaMsg_Sms nebula_sdk/nebula_sdk.h /^ eNebulaMsg_Sms, \/\/\/ 网络短信$/;" e enum:__anon1
|
|
||||||
main test.c /^int main()$/;" f
|
|
@ -1,74 +0,0 @@
|
|||||||
#include "nebula_sdk/nebula_sdk.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
*void OnPush(const char* data, int len)
|
|
||||||
*{
|
|
||||||
* char *body = strndup(data, len);
|
|
||||||
* printf("karldbg %s %d\n", __func__, len);
|
|
||||||
* do {
|
|
||||||
* int cnt = 0;
|
|
||||||
* for(cnt=0; cnt<len; cnt++) {
|
|
||||||
* printf("karldbg %s pos: 0x%02x, 0x%02x, %c\n", __func__, cnt, (char)*(body+cnt), *(body+cnt));
|
|
||||||
* }
|
|
||||||
* } while(0);
|
|
||||||
* printf("recv push:%s\n", body);
|
|
||||||
* free(body);
|
|
||||||
*}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void OnPush(const char* app, const char *msg)
|
|
||||||
{
|
|
||||||
printf("karldbg %s %d %s\n", __func__, __LINE__, app);
|
|
||||||
printf("karldbg %s %d %s\n", __func__, __LINE__, msg);
|
|
||||||
/*
|
|
||||||
*do {
|
|
||||||
* int cnt = 0;
|
|
||||||
* for(cnt=0; cnt<len; cnt++) {
|
|
||||||
* printf("karldbg %s pos: 0x%02x, 0x%02x, %c\n", __func__, cnt, (char)*(body+cnt), *(body+cnt));
|
|
||||||
* }
|
|
||||||
*} while(0);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
//??
|
|
||||||
struct rlimit no_limit = {RLIM_INFINITY, RLIM_INFINITY};
|
|
||||||
setrlimit(RLIMIT_CORE, &no_limit);
|
|
||||||
|
|
||||||
/*if (-1 == NebulaInit("1000000010000001", "https://172.16.82.71", "data")) {*/
|
|
||||||
if (-1 == NebulaInit("R10WZOANC5400EE", "https://172.16.82.71", "data")) {
|
|
||||||
printf("Init error.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*const char * apps[] = {"com.meizu.cloud"};*/
|
|
||||||
const char * apps[] = {"com.meizu.router"};
|
|
||||||
|
|
||||||
NebulaSubScribe(1, apps);
|
|
||||||
|
|
||||||
NebulaMsgCallback cb = OnPush;
|
|
||||||
|
|
||||||
/*NebulaRegister(eNebulaMsg_Push, &OnPush);*/
|
|
||||||
NebulaRegister(eNebulaMsg_Push, cb);
|
|
||||||
|
|
||||||
if (-1 == NebulaStart()) {
|
|
||||||
printf("Start error.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("start success.\n");
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,176 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include "timer.h"
|
|
||||||
|
|
||||||
#define DEFAULT_TIMER_LIMIT_SIZE 256
|
|
||||||
|
|
||||||
struct timer_heap_t
|
|
||||||
{
|
|
||||||
int32_t limit_size; //一次超时的元素个数
|
|
||||||
util_rbtree_t rbtree;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*{{{ timer_heap_create*/
|
|
||||||
timer_heap_t* timer_heap_create(int32_t limit_size)
|
|
||||||
{
|
|
||||||
timer_heap_t* ht;
|
|
||||||
|
|
||||||
ht = (timer_heap_t*)malloc(sizeof(timer_heap_t));
|
|
||||||
if(ht == NULL){
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ht->limit_size = (limit_size <=0 ? DEFAULT_TIMER_LIMIT_SIZE : limit_size);
|
|
||||||
util_rbtree_init(&ht->rbtree);
|
|
||||||
|
|
||||||
return ht;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_timer_limit(timer_heap_t *ht, int32_t limit)
|
|
||||||
{
|
|
||||||
if(ht == NULL)
|
|
||||||
return;
|
|
||||||
if (limit > 0) {
|
|
||||||
ht->limit_size = limit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*}}}*/
|
|
||||||
|
|
||||||
/*{{{ timer_add*/
|
|
||||||
int32_t timer_add( timer_heap_t* ht, timer_entry* entry, uint32_t expires)
|
|
||||||
{
|
|
||||||
struct timeval now;
|
|
||||||
long msec;
|
|
||||||
if(!ht || !entry)
|
|
||||||
{
|
|
||||||
return -1; /*参数错误*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*获取当前时间*/
|
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
msec = now.tv_sec*1000 + now.tv_usec/1000 + expires;
|
|
||||||
if (entry->in_rbtree) {
|
|
||||||
//已经在红黑树中 先删除再插入
|
|
||||||
util_rbtree_delete(&ht->rbtree, &entry->rbnode);
|
|
||||||
entry->in_rbtree = 0;
|
|
||||||
rbt_clear_node(&entry->rbnode);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry->rbnode.key = msec;
|
|
||||||
util_rbtree_insert(&ht->rbtree, &entry->rbnode);
|
|
||||||
entry->in_rbtree = 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*}}}*/
|
|
||||||
|
|
||||||
/*{{{ timer_del*/
|
|
||||||
void timer_del( timer_heap_t* ht, timer_entry* entry)
|
|
||||||
{
|
|
||||||
if(!ht || !entry)
|
|
||||||
return;
|
|
||||||
if (!entry->in_rbtree)
|
|
||||||
return;
|
|
||||||
|
|
||||||
util_rbtree_delete(&ht->rbtree, &entry->rbnode);
|
|
||||||
entry->in_rbtree = 0;
|
|
||||||
rbt_clear_node(&entry->rbnode);
|
|
||||||
}
|
|
||||||
/*}}}*/
|
|
||||||
|
|
||||||
int32_t timer_update(timer_heap_t* ht, timer_entry *entry, uint32_t expires)
|
|
||||||
{
|
|
||||||
return timer_add(ht, entry, expires);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t timer_earliest_time(timer_heap_t* ht)
|
|
||||||
{
|
|
||||||
struct timeval now;
|
|
||||||
long msec;
|
|
||||||
util_rbtree_node_t *rbnode;
|
|
||||||
|
|
||||||
if(!ht)
|
|
||||||
return -1;
|
|
||||||
if(ht->rbtree.size == 0)
|
|
||||||
return -1;
|
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
|
|
||||||
rbnode = util_rbtree_min(&ht->rbtree);
|
|
||||||
if (rbnode == NULL)
|
|
||||||
return -1;
|
|
||||||
msec = rbnode->key - (now.tv_sec*1000 + now.tv_usec/1000);
|
|
||||||
if(msec < 0)
|
|
||||||
msec = 0;
|
|
||||||
return (int32_t)msec;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t timer_size(timer_heap_t* ht)
|
|
||||||
{
|
|
||||||
if(!ht)
|
|
||||||
return 0;
|
|
||||||
return (int32_t)ht->rbtree.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t timer_run(timer_heap_t* ht)
|
|
||||||
{
|
|
||||||
struct timeval now;
|
|
||||||
long msec;
|
|
||||||
int i;
|
|
||||||
int count = 0;
|
|
||||||
if(!ht || util_rbtree_isempty(&ht->rbtree)){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
msec = now.tv_sec*1000 + now.tv_usec/1000;
|
|
||||||
for (i=0; i<ht->limit_size; ++i) {
|
|
||||||
timer_entry *entry;
|
|
||||||
util_rbtree_node_t *node = util_rbtree_min(&ht->rbtree);
|
|
||||||
if (node == NULL) break;
|
|
||||||
entry = (timer_entry*)node->data;
|
|
||||||
if (node->key <= msec) {
|
|
||||||
++count;
|
|
||||||
util_rbtree_delete(&ht->rbtree, node);
|
|
||||||
rbt_clear_node(node);
|
|
||||||
entry->in_rbtree = 0;
|
|
||||||
if (entry->timeout_cb) {
|
|
||||||
entry->timeout_cb(ht, entry);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void timer_entry_init(timer_entry* entry, int32_t id, void* user_data, \
|
|
||||||
void (*timeout_cb)(timer_heap_t* ht, struct timer_entry *entry))
|
|
||||||
{
|
|
||||||
entry->user_data = user_data;
|
|
||||||
entry->timeout_cb = timeout_cb;
|
|
||||||
entry->id = id;
|
|
||||||
entry->in_rbtree = 0;
|
|
||||||
rbt_clear_node(&entry->rbnode);
|
|
||||||
entry->rbnode.data = entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void timer_destroy( timer_heap_t* ht)
|
|
||||||
{
|
|
||||||
if(!ht)
|
|
||||||
return;
|
|
||||||
while(!util_rbtree_isempty(&ht->rbtree)) {
|
|
||||||
timer_entry *entry;
|
|
||||||
util_rbtree_node_t *node = util_rbtree_min(&ht->rbtree);
|
|
||||||
entry = (timer_entry*)node->data;
|
|
||||||
util_rbtree_delete(&ht->rbtree, node);
|
|
||||||
rbt_clear_node(node);
|
|
||||||
entry->in_rbtree = 0;
|
|
||||||
if (entry->timeout_cb) {
|
|
||||||
entry->timeout_cb(ht, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(ht);
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* =====================================================================================
|
|
||||||
*
|
|
||||||
* Filename: timer.h
|
|
||||||
*
|
|
||||||
* Description: 小根堆定时器实现(非多线程安全)
|
|
||||||
*
|
|
||||||
* Version: 1.0
|
|
||||||
* Created: 2013-08-20
|
|
||||||
* Revision: none
|
|
||||||
* Compiler: gcc
|
|
||||||
*
|
|
||||||
* Author: xiaoboyu
|
|
||||||
* Organization:
|
|
||||||
*
|
|
||||||
* =====================================================================================
|
|
||||||
*/
|
|
||||||
#ifndef __TIMER_HEAP_H__
|
|
||||||
#define __TIMER_HEAP_H__
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "util_rbtree.h"
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct timer_heap_t timer_heap_t;
|
|
||||||
|
|
||||||
typedef struct timer_entry
|
|
||||||
{
|
|
||||||
int32_t id;
|
|
||||||
uint8_t in_rbtree; /*是否在红黑树中*/
|
|
||||||
util_rbtree_node_t rbnode;
|
|
||||||
void *user_data;
|
|
||||||
void (*timeout_cb)(timer_heap_t* ht, struct timer_entry *entry);
|
|
||||||
}timer_entry;
|
|
||||||
|
|
||||||
void timer_entry_init(timer_entry* entry, int32_t id, void* user_data, \
|
|
||||||
void (*timeout_cb)(timer_heap_t* ht, struct timer_entry *entry));
|
|
||||||
/*
|
|
||||||
* 创建定时器
|
|
||||||
* @param limit_size 一次超时的元素个数
|
|
||||||
*/
|
|
||||||
timer_heap_t* timer_heap_create(int32_t limit_size);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 设置定时器每次最大超时元素的个数 默认是256个
|
|
||||||
*/
|
|
||||||
void set_timer_limit(timer_heap_t *ht, int32_t limit);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @ref 添加元素到定时器
|
|
||||||
* @param expires 超时时间ms
|
|
||||||
* @return 成功返回0 失败返回-1
|
|
||||||
*/
|
|
||||||
int32_t timer_add( timer_heap_t* ht, timer_entry *entry, uint32_t expires );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @ref 从定时器中删除一个元素
|
|
||||||
*/
|
|
||||||
void timer_del( timer_heap_t* ht, timer_entry* entry );
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 更新超时时间(前提是这个entry必须在定时器内, 否则可能导致不可预知的错误)
|
|
||||||
*/
|
|
||||||
int32_t timer_update(timer_heap_t* ht, timer_entry *entry, uint32_t expires);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief 获取最近超时时间
|
|
||||||
* @return -1 没有超时
|
|
||||||
*/
|
|
||||||
int32_t timer_earliest_time(timer_heap_t* ht);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @ref 获取定时器元素的个数
|
|
||||||
*/
|
|
||||||
int32_t timer_size ( timer_heap_t* ht );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @ref 扫描定时器,执行那些超时的定时器元素
|
|
||||||
* @return 返回已经处理的超时定时器元素的个数
|
|
||||||
*/
|
|
||||||
int32_t timer_run(timer_heap_t* ht);
|
|
||||||
|
|
||||||
void timer_destroy( timer_heap_t* ht);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Binary file not shown.
@ -1,486 +0,0 @@
|
|||||||
|
|
||||||
/* Copyright (C) 2010. sparkling.liang@hotmail.com. All rights reserved. */
|
|
||||||
|
|
||||||
#include "util_rbtree.h"
|
|
||||||
|
|
||||||
/* the NULL node of tree */
|
|
||||||
#define _NULL(rbtree) (&((rbtree)->null))
|
|
||||||
|
|
||||||
/* structues uesed to check a rb tree */
|
|
||||||
struct rbtree_check_s
|
|
||||||
{
|
|
||||||
short rbh; /* rb height of the tree */
|
|
||||||
short maxd; /* max depth of the tree */
|
|
||||||
int fini; /* check failed ? */
|
|
||||||
const util_rbtree_node_t *null; /* sentinel of the tree */
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct rbtree_check_s rbtree_check_t;
|
|
||||||
|
|
||||||
static void rbtree_left_rotate(util_rbtree_node_t **root,
|
|
||||||
util_rbtree_node_t* sentinel,
|
|
||||||
util_rbtree_node_t *node);
|
|
||||||
static void rbtree_right_rotate(util_rbtree_node_t **root,
|
|
||||||
util_rbtree_node_t* sentinel,
|
|
||||||
util_rbtree_node_t *node);
|
|
||||||
|
|
||||||
void util_rbtree_init(util_rbtree_t *rbtree)
|
|
||||||
{
|
|
||||||
if(rbtree != NULL)
|
|
||||||
{
|
|
||||||
util_rbt_black(_NULL(rbtree)); /* null MUST be black */
|
|
||||||
rbtree->root = _NULL(rbtree);
|
|
||||||
rbtree->size = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
util_rbtree_node_t* util_rbsubtree_min(util_rbtree_node_t *node, util_rbtree_node_t *sentinel)
|
|
||||||
{
|
|
||||||
if(node == sentinel) return NULL;
|
|
||||||
while(node->left != sentinel) node = node->left;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
util_rbtree_node_t* util_rbsubtree_max(util_rbtree_node_t *node, util_rbtree_node_t *sentinel)
|
|
||||||
{
|
|
||||||
if(node == sentinel) return NULL;
|
|
||||||
while(node->right != sentinel) node = node->right;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void util_rbtree_insert(util_rbtree_t *rbtree, util_rbtree_node_t *node)
|
|
||||||
{
|
|
||||||
util_rbtree_node_t **root = &rbtree->root;
|
|
||||||
util_rbtree_node_t *sentinel = _NULL(rbtree);
|
|
||||||
util_rbtree_node_t *temp, **p;
|
|
||||||
|
|
||||||
/* empty tree */
|
|
||||||
|
|
||||||
if (*root == sentinel) {
|
|
||||||
node->parent = NULL;
|
|
||||||
node->left = sentinel;
|
|
||||||
node->right = sentinel;
|
|
||||||
util_rbt_black(node);
|
|
||||||
*root = node;
|
|
||||||
++rbtree->size;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* a binary tree insert */
|
|
||||||
temp = *root;
|
|
||||||
for (;;) {
|
|
||||||
p = (node->key < temp->key) ? &temp->left : &temp->right;
|
|
||||||
if (*p == sentinel) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
temp = *p;
|
|
||||||
}
|
|
||||||
|
|
||||||
*p = node;
|
|
||||||
node->parent = temp;
|
|
||||||
node->left = sentinel;
|
|
||||||
node->right = sentinel;
|
|
||||||
util_rbt_red(node);
|
|
||||||
|
|
||||||
/* re-balance tree */
|
|
||||||
while (node != *root && util_rbt_isred(node->parent)) {
|
|
||||||
|
|
||||||
if (node->parent == node->parent->parent->left) {
|
|
||||||
temp = node->parent->parent->right;
|
|
||||||
|
|
||||||
if (util_rbt_isred(temp)) {
|
|
||||||
util_rbt_black(node->parent);
|
|
||||||
util_rbt_black(temp);
|
|
||||||
util_rbt_red(node->parent->parent);
|
|
||||||
node = node->parent->parent;
|
|
||||||
} else {
|
|
||||||
if (node == node->parent->right) {
|
|
||||||
node = node->parent;
|
|
||||||
rbtree_left_rotate(root, sentinel, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
util_rbt_black(node->parent);
|
|
||||||
util_rbt_red(node->parent->parent);
|
|
||||||
rbtree_right_rotate(root, sentinel, node->parent->parent);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
temp = node->parent->parent->left;
|
|
||||||
|
|
||||||
if (util_rbt_isred(temp)) {
|
|
||||||
util_rbt_black(node->parent);
|
|
||||||
util_rbt_black(temp);
|
|
||||||
util_rbt_red(node->parent->parent);
|
|
||||||
node = node->parent->parent;
|
|
||||||
} else {
|
|
||||||
if (node == node->parent->left) {
|
|
||||||
node = node->parent;
|
|
||||||
rbtree_right_rotate(root, sentinel, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
util_rbt_black(node->parent);
|
|
||||||
util_rbt_red(node->parent->parent);
|
|
||||||
rbtree_left_rotate(root, sentinel, node->parent->parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
util_rbt_black(*root);
|
|
||||||
++rbtree->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void util_rbtree_delete(util_rbtree_t *rbtree, util_rbtree_node_t *node)
|
|
||||||
{
|
|
||||||
util_rbtree_node_t **root = &rbtree->root;
|
|
||||||
util_rbtree_node_t *sentinel = _NULL(rbtree);
|
|
||||||
util_rbtree_node_t *subst, *temp, *w;
|
|
||||||
uint8_t red;
|
|
||||||
|
|
||||||
/* a binary tree delete */
|
|
||||||
--rbtree->size;
|
|
||||||
if (node->left == sentinel) {
|
|
||||||
temp = node->right;
|
|
||||||
subst = node;
|
|
||||||
} else if (node->right == sentinel) {
|
|
||||||
temp = node->left;
|
|
||||||
subst = node;
|
|
||||||
} else {
|
|
||||||
subst = util_rbsubtree_min(node->right, sentinel);
|
|
||||||
if (subst->left != sentinel) {
|
|
||||||
temp = subst->left;
|
|
||||||
} else {
|
|
||||||
temp = subst->right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subst == *root) {
|
|
||||||
*root = temp;
|
|
||||||
util_rbt_black(temp);
|
|
||||||
|
|
||||||
rbt_clear_node(node);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
red = util_rbt_isred(subst);
|
|
||||||
|
|
||||||
if (subst == subst->parent->left) {
|
|
||||||
subst->parent->left = temp;
|
|
||||||
} else {
|
|
||||||
subst->parent->right = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subst == node) {
|
|
||||||
temp->parent = subst->parent;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (subst->parent == node) {
|
|
||||||
temp->parent = subst;
|
|
||||||
} else {
|
|
||||||
temp->parent = subst->parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
subst->left = node->left;
|
|
||||||
subst->right = node->right;
|
|
||||||
subst->parent = node->parent;
|
|
||||||
subst->color = node->color;
|
|
||||||
|
|
||||||
if (node == *root) {
|
|
||||||
*root = subst;
|
|
||||||
} else {
|
|
||||||
if (node == node->parent->left) {
|
|
||||||
node->parent->left = subst;
|
|
||||||
} else {
|
|
||||||
node->parent->right = subst;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subst->left != sentinel) {
|
|
||||||
subst->left->parent = subst;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subst->right != sentinel) {
|
|
||||||
subst->right->parent = subst;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rbt_clear_node(node);
|
|
||||||
|
|
||||||
if (red) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* a delete fixup */
|
|
||||||
while (temp != *root && util_rbt_isblack(temp)) {
|
|
||||||
|
|
||||||
if (temp == temp->parent->left) {
|
|
||||||
w = temp->parent->right;
|
|
||||||
|
|
||||||
if (util_rbt_isred(w)) {
|
|
||||||
util_rbt_black(w);
|
|
||||||
util_rbt_red(temp->parent);
|
|
||||||
rbtree_left_rotate(root, sentinel, temp->parent);
|
|
||||||
w = temp->parent->right;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (util_rbt_isblack(w->left) && util_rbt_isblack(w->right)) {
|
|
||||||
util_rbt_red(w);
|
|
||||||
temp = temp->parent;
|
|
||||||
} else {
|
|
||||||
if (util_rbt_isblack(w->right)) {
|
|
||||||
util_rbt_black(w->left);
|
|
||||||
util_rbt_red(w);
|
|
||||||
rbtree_right_rotate(root, sentinel, w);
|
|
||||||
w = temp->parent->right;
|
|
||||||
}
|
|
||||||
|
|
||||||
w->color = temp->parent->color;
|
|
||||||
util_rbt_black(temp->parent);
|
|
||||||
util_rbt_black(w->right);
|
|
||||||
rbtree_left_rotate(root, sentinel, temp->parent);
|
|
||||||
temp = *root;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
w = temp->parent->left;
|
|
||||||
|
|
||||||
if (util_rbt_isred(w)) {
|
|
||||||
util_rbt_black(w);
|
|
||||||
util_rbt_red(temp->parent);
|
|
||||||
rbtree_right_rotate(root, sentinel, temp->parent);
|
|
||||||
w = temp->parent->left;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (util_rbt_isblack(w->left) && util_rbt_isblack(w->right)) {
|
|
||||||
util_rbt_red(w);
|
|
||||||
temp = temp->parent;
|
|
||||||
} else {
|
|
||||||
if (util_rbt_isblack(w->left)) {
|
|
||||||
util_rbt_black(w->right);
|
|
||||||
util_rbt_red(w);
|
|
||||||
rbtree_left_rotate(root, sentinel, w);
|
|
||||||
w = temp->parent->left;
|
|
||||||
}
|
|
||||||
|
|
||||||
w->color = temp->parent->color;
|
|
||||||
util_rbt_black(temp->parent);
|
|
||||||
util_rbt_black(w->left);
|
|
||||||
rbtree_right_rotate(root, sentinel, temp->parent);
|
|
||||||
temp = *root;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
util_rbt_black(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rbtree_left_rotate(util_rbtree_node_t **root,
|
|
||||||
util_rbtree_node_t* sentinel,
|
|
||||||
util_rbtree_node_t *node)
|
|
||||||
{
|
|
||||||
util_rbtree_node_t *temp;
|
|
||||||
|
|
||||||
temp = node->right;
|
|
||||||
node->right = temp->left;
|
|
||||||
|
|
||||||
if (temp->left != sentinel) {
|
|
||||||
temp->left->parent = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp->parent = node->parent;
|
|
||||||
|
|
||||||
if (node == *root) {
|
|
||||||
*root = temp;
|
|
||||||
} else if (node == node->parent->left) {
|
|
||||||
node->parent->left = temp;
|
|
||||||
} else {
|
|
||||||
node->parent->right = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp->left = node;
|
|
||||||
node->parent = temp;
|
|
||||||
}
|
|
||||||
static void rbtree_right_rotate(util_rbtree_node_t **root,
|
|
||||||
util_rbtree_node_t* sentinel,
|
|
||||||
util_rbtree_node_t *node)
|
|
||||||
{
|
|
||||||
util_rbtree_node_t *temp;
|
|
||||||
|
|
||||||
temp = node->left;
|
|
||||||
node->left = temp->right;
|
|
||||||
|
|
||||||
if (temp->right != sentinel) {
|
|
||||||
temp->right->parent = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp->parent = node->parent;
|
|
||||||
|
|
||||||
if (node == *root) {
|
|
||||||
*root = temp;
|
|
||||||
} else if (node == node->parent->right) {
|
|
||||||
node->parent->right = temp;
|
|
||||||
} else {
|
|
||||||
node->parent->left = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp->right = node;
|
|
||||||
node->parent = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
util_rbtree_node_t* util_rbtree_search(util_rbtree_t *rbtree, long key)
|
|
||||||
{
|
|
||||||
if(rbtree != NULL)
|
|
||||||
{
|
|
||||||
util_rbtree_node_t *node = rbtree->root;
|
|
||||||
util_rbtree_node_t *null = _NULL(rbtree);
|
|
||||||
while(node != null)
|
|
||||||
{
|
|
||||||
if(key < node->key) node = node->left;
|
|
||||||
else if(key > node->key) node = node->right;
|
|
||||||
else if(node->key == key) return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
util_rbtree_node_t* util_rbtree_lookup(util_rbtree_t *rbtree, long key)
|
|
||||||
{
|
|
||||||
if((rbtree != NULL) && !util_rbtree_isempty(rbtree))
|
|
||||||
{
|
|
||||||
util_rbtree_node_t *node = NULL;
|
|
||||||
util_rbtree_node_t *temp = rbtree->root;
|
|
||||||
util_rbtree_node_t *null = _NULL(rbtree);
|
|
||||||
while(temp != null)
|
|
||||||
{
|
|
||||||
if(key <= temp->key)
|
|
||||||
{
|
|
||||||
node = temp; /* update node */
|
|
||||||
temp = temp->left;
|
|
||||||
}
|
|
||||||
else if(key > temp->key)
|
|
||||||
{
|
|
||||||
temp = temp->right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* if node==NULL return the minimum node */
|
|
||||||
return ((node != NULL) ? node : util_rbtree_min(rbtree));
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rbtree_check_subtree(const util_rbtree_node_t *node, rbtree_check_t *check,
|
|
||||||
int level, int curheight)
|
|
||||||
{
|
|
||||||
if(check->fini) /* already failed */
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* check node color */
|
|
||||||
if(util_rbt_isblack(node))
|
|
||||||
{
|
|
||||||
curheight++;
|
|
||||||
}
|
|
||||||
else if(!util_rbt_isred(node))
|
|
||||||
{
|
|
||||||
check->fini = 2;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* check left */
|
|
||||||
if(node->left != check->null)
|
|
||||||
{
|
|
||||||
if(util_rbt_isred(node) && util_rbt_isred(node->left))
|
|
||||||
{
|
|
||||||
check->fini = 4;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(node->key < node->left->key)
|
|
||||||
{
|
|
||||||
check->fini = 5;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rbtree_check_subtree(node->left, check, level+1, curheight);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
goto __check_rb_height;
|
|
||||||
}
|
|
||||||
/* check right */
|
|
||||||
if(node->right != check->null)
|
|
||||||
{
|
|
||||||
if(util_rbt_isred(node) && util_rbt_isred(node->right))
|
|
||||||
{
|
|
||||||
check->fini = 4;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(node->key > node->right->key)
|
|
||||||
{
|
|
||||||
check->fini = 5;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rbtree_check_subtree(node->right, check, level+1, curheight);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
goto __check_rb_height;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
__check_rb_height:
|
|
||||||
if(check->rbh == 0)
|
|
||||||
{
|
|
||||||
check->rbh = curheight;
|
|
||||||
}
|
|
||||||
if(check->maxd < level)
|
|
||||||
{
|
|
||||||
check->maxd = level;
|
|
||||||
}
|
|
||||||
if(check->rbh != curheight)
|
|
||||||
{
|
|
||||||
check->fini = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int util_rbtree_check(const util_rbtree_t *rbtree, int *blackheight, int *maxdepth)
|
|
||||||
{
|
|
||||||
rbtree_check_t check;
|
|
||||||
if(rbtree->root == _NULL(rbtree))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(!util_rbt_isblack(rbtree->root))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
check.fini = check.maxd = check.rbh = 0;
|
|
||||||
check.null = _NULL(rbtree);
|
|
||||||
rbtree_check_subtree(rbtree->root, &check, 1, 0);
|
|
||||||
if(blackheight)
|
|
||||||
{
|
|
||||||
*blackheight = check.rbh;
|
|
||||||
}
|
|
||||||
if(maxdepth)
|
|
||||||
{
|
|
||||||
*maxdepth = check.maxd;
|
|
||||||
}
|
|
||||||
return check.fini;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rbtree_mid_travel(util_rbtree_node_t *node, util_rbtree_node_t *sentinel,
|
|
||||||
void(*opera)(util_rbtree_node_t *, void *), void *data)
|
|
||||||
{
|
|
||||||
if(node->left != sentinel)
|
|
||||||
{
|
|
||||||
rbtree_mid_travel(node->left, sentinel, opera, data);
|
|
||||||
}
|
|
||||||
opera(node, data);
|
|
||||||
if(node->right != sentinel)
|
|
||||||
{
|
|
||||||
rbtree_mid_travel(node->right, sentinel, opera, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void util_rbtree_mid_travel(util_rbtree_t *rbtree,
|
|
||||||
void(*opera)(util_rbtree_node_t *, void *), void *data)
|
|
||||||
{
|
|
||||||
if((rbtree!=NULL) && !util_rbtree_isempty(rbtree))
|
|
||||||
{
|
|
||||||
rbtree_mid_travel(rbtree->root, _NULL(rbtree), opera, data);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,114 +0,0 @@
|
|||||||
|
|
||||||
/* Copyright (C) 2010. sparkling.liang@hotmail.com. All rights reserved. */
|
|
||||||
|
|
||||||
#ifndef __UTIL_RLTREE_H_
|
|
||||||
#define __UTIL_RLTREE_H_
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct util_rbtree_s util_rbtree_t;
|
|
||||||
typedef struct util_rbtree_node_s util_rbtree_node_t;
|
|
||||||
|
|
||||||
struct util_rbtree_node_s
|
|
||||||
{
|
|
||||||
long key;
|
|
||||||
util_rbtree_node_t *parent;
|
|
||||||
util_rbtree_node_t *right;
|
|
||||||
util_rbtree_node_t *left;
|
|
||||||
int color;
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct util_rbtree_s
|
|
||||||
{
|
|
||||||
util_rbtree_node_t *root;
|
|
||||||
util_rbtree_node_t null;
|
|
||||||
uint32_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define util_rbt_black(rbnode) ((rbnode)->color = 1)
|
|
||||||
#define util_rbt_red(rbnode) ((rbnode)->color = 0)
|
|
||||||
#define util_rbt_isblack(rbnode) ((rbnode)->color == 1)
|
|
||||||
#define util_rbt_isred(rbnode) ((rbnode)->color == 0)
|
|
||||||
|
|
||||||
/* clear a node's link */
|
|
||||||
#define rbt_clear_node(node) do{ \
|
|
||||||
(node)->left = NULL; \
|
|
||||||
(node)->right = NULL; \
|
|
||||||
(node)->parent = NULL; \
|
|
||||||
}while(0)
|
|
||||||
|
|
||||||
/* is the tree empty */
|
|
||||||
#define util_rbtree_isempty(rbtree) ((rbtree)->root == &(rbtree)->null)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find the min node of tree
|
|
||||||
* return NULL is tree is empty
|
|
||||||
*/
|
|
||||||
#define util_rbtree_min(rbtree) util_rbsubtree_min((rbtree)->root, &(rbtree)->null)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find the max node of tree
|
|
||||||
* return NULL is tree is empty
|
|
||||||
*/
|
|
||||||
#define util_rbtree_max(rbtree) util_rbsubtree_max((rbtree)->root, &(rbtree)->null)
|
|
||||||
|
|
||||||
void util_rbtree_init(util_rbtree_t *rbtree);
|
|
||||||
void util_rbtree_insert(util_rbtree_t *rbtree, util_rbtree_node_t *node);
|
|
||||||
void util_rbtree_delete(util_rbtree_t *rbtree, util_rbtree_node_t *node);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* search node with key = @key in the tree
|
|
||||||
* if no such node exist, return NULL
|
|
||||||
*/
|
|
||||||
util_rbtree_node_t* util_rbtree_search(util_rbtree_t *rbtree, long key);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* look node in the tree
|
|
||||||
* return the first node with key >= @key;
|
|
||||||
* if @key > all the key values in the tree, return the node with minimum key
|
|
||||||
* return NULL if tree is empty
|
|
||||||
*/
|
|
||||||
util_rbtree_node_t* util_rbtree_lookup(util_rbtree_t *rbtree, long key);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find the min node of subtree
|
|
||||||
* @rbnode: root of the subtree
|
|
||||||
* @sentinel : the sentinel node
|
|
||||||
* return NULL if subtree is empty
|
|
||||||
*/
|
|
||||||
util_rbtree_node_t* util_rbsubtree_min(util_rbtree_node_t *node, util_rbtree_node_t *sentinel);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* find the max node of subtree
|
|
||||||
* @rbnode: root of the subtree
|
|
||||||
* @sentinel : the sentinel node
|
|
||||||
* return NULL if subtree is empty
|
|
||||||
*/
|
|
||||||
util_rbtree_node_t* util_rbsubtree_max(util_rbtree_node_t *node, util_rbtree_node_t *sentinel);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check whether a tree is a rb tree, the null node is n't checked
|
|
||||||
* return 0: yes
|
|
||||||
* return 1: root isn't black
|
|
||||||
* return 2: node is in other color than black and red
|
|
||||||
* return 3: tree's black height isn't unique
|
|
||||||
* return 4: a red node with parent in red exists
|
|
||||||
* return 5: volatile binary search properties
|
|
||||||
*
|
|
||||||
* when return !0, @blackheight & @maxdepth is uselsess
|
|
||||||
* when return 0, @blackheight contains the tree's black height
|
|
||||||
*
|
|
||||||
* @maxdepth contains the max length of all simple roads from root to it's leaf nodes
|
|
||||||
*/
|
|
||||||
int util_rbtree_check(const util_rbtree_t *rbtree, int *blackheight, int *maxdepth);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* travel through a rb tree in sequence: left-root-right
|
|
||||||
* you CAN NOT do any operations that will break the RB properties
|
|
||||||
*/
|
|
||||||
void util_rbtree_mid_travel(util_rbtree_t *rbtree, void(*opera)(util_rbtree_node_t *, void *), void *data);
|
|
||||||
|
|
||||||
#endif /* end __UTIL_RLTREE_H_ */
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Loading…
Reference in New Issue
Block a user