selfcare init

This commit is contained in:
zhangsz
2025-03-03 11:40:37 +08:00
parent 19f09dd7ea
commit aca2bace68
692 changed files with 273972 additions and 0 deletions

32
proxy_c/Makefile Normal file
View File

@@ -0,0 +1,32 @@
TOPDIR:=.
TGT:=./restproxy
DIR=$(TOPDIR)
SRCS=$(foreach dir, $(DIR), $(wildcard $(dir)/*.c))
OBJS:=$(patsubst %.c,%.o,$(SRCS))
DIR_LIBEVENT = ./third-lib/libevent/include/
DIR_JSON = ./third-lib/json-lib/inc/
DIR_CURL = ./third-lib/libcurl/include/curl/
INCDIR = $(foreach dir, $(DIR), -I $(dir)/ )
INCDIR += -I $(DIR_LIBEVENT)
INCDIR += -I $(DIR_JSON)
INCDIR += -I $(DIR_CURL)
LIBS = ./dba/lib/libdba.a ./smcli_client/lib/libclient.a ./pstn_cli/lib/libpstncli.a ./tcp/lib/libtcp.a /usr/lib/x86_64-linux-gnu/libidn.a -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient ./third-lib/libcurl/lib/libcurl.a -lrt -lcrypto -lssl -lpthread ./third-lib/libevent/lib/libevent.a ./third-lib/libevent/lib/libevent_pthreads.a ./third-lib/json-lib/libmjson.a -L/usr/local/lib -lglib-2.0 -lz
CFLAGS = -Wall -g -DX86_64 -DTEST_RESTPROXY $(LIBS)
CC = gcc
$(TGT):$(OBJS)
$(CC) -o $(TGT) $(CFLAGS) $(SRCS) $(INCDIR) $(LIBS)
chmod a+x $(TGT)
$(OBJS):%.o:%.c
$(CC) $(CFLAGS) -c -o $@ $< $(INCDIR)
clean:
rm -rf $(OBJS) $(TGT)

33
proxy_c/Makefile.bak Normal file
View File

@@ -0,0 +1,33 @@
TOPDIR:=.
TGT:=./restproxy
DIR=$(TOPDIR)
SRCS=$(foreach dir, $(DIR), $(wildcard $(dir)/*.c))
OBJS:=$(patsubst %.c,%.o,$(SRCS))
DIR_LIBEVENT = ./third-lib/libevent/include/
DIR_JSON = ./third-lib/json-lib/inc/
DIR_CURL = ./third-lib/libcurl/include/curl/
INCDIR = $(foreach dir, $(DIR), -I $(dir)/ )
INCDIR += -I $(DIR_LIBEVENT)
INCDIR += -I $(DIR_JSON)
INCDIR += -I $(DIR_CURL)
LIBS = /usr/lib/x86_64-linux-gnu/libidn.a ./third-lib/libcurl/lib/libcurl.a -lrt -lcrypto -lssl -lpthread ./third-lib/libevent/lib/libevent.a ./third-lib/json-lib/libmjson.a
CFLAGS = -Wall -g -DX86_64 -DTEST_RESTPROXY $(LIBS)
CC = gcc
$(TGT):$(OBJS)
$(CC) -o $(TGT) $(CFLAGS) $(SRCS) $(INCDIR) $(LIBS)
chmod a+x $(TGT)
$(OBJS):%.o:%.c
$(CC) $(CFLAGS) -c -o $@ $< $(INCDIR)
clean:
rm -rf $(OBJS) $(TGT)

BIN
proxy_c/Makefile_rules.tgz Normal file

Binary file not shown.

12
proxy_c/Readme.txt Normal file
View File

@@ -0,0 +1,12 @@
1)<29><>װlibmysqlclient
apt-get install libmysqlclient-dev
2)make dba
<EFBFBD><EFBFBD>װglib
#cd dba;make
3)xlocale.h not found
ln -s /usr/include/locale.h /usr/include/xlocale.h
4)undefined reference to idn2_free
third-lib/curl-7.52.1#>./configure --without-libidn --without-libidn2

181
proxy_c/common.c Normal file
View File

@@ -0,0 +1,181 @@
#include<time.h>
#include "common.h"
extern char *strptime(const char *s, const char *format, struct tm *tm);
void BcdToAscii (char *ascii_buf, const BYTE *bcd_buf, int len)
{
int i;
char ch;
for (i=0; i<len; i++) {
if (i & 1) ch = *(bcd_buf++) & 0x0f;
else ch = *bcd_buf >> 4;
ascii_buf[i] = ch + ((ch > 9)? 'A'-10 : '0');
}
ascii_buf[i] = '\0';
}
void BcdToAsciiR(char *ascii_buf, const unsigned char *bcd_buf, int len)
{
char ch;
int i;
for(i=0;i<len;i++)
{
sprintf(&ascii_buf[i*2],"%02X",bcd_buf[i]);
ch = ascii_buf[i*2];
ascii_buf[i*2] = ascii_buf[i*2+1];
ascii_buf[i*2+1] = ch;
}
}
char *GetAsciiTime()
{
char *pAscTime;
time_t tCurTime;
tCurTime = time(NULL);
pAscTime = ctime(&tCurTime);
return (char *)pAscTime;
}
int GetCurrentTime( char *pNowTime )
{
struct tm *pTMNowTime;
time_t tTemptime;
tTemptime = time(NULL);
pTMNowTime = localtime(&tTemptime);
if( pTMNowTime == NULL )
return 0;
pNowTime[0] = pTMNowTime->tm_year-100;
pNowTime[1] = pTMNowTime->tm_mon+1;
pNowTime[2] = pTMNowTime->tm_mday;
pNowTime[3] = pTMNowTime->tm_hour;
pNowTime[4] = pTMNowTime->tm_min;
pNowTime[5] = pTMNowTime->tm_sec;
return 1;
}
int GetMonthDay()
{
struct tm *pTMNowTime;
time_t tTemptime;
tTemptime = time(NULL);
pTMNowTime = localtime(&tTemptime);
if( pTMNowTime == NULL )
return 1;
return pTMNowTime->tm_mday;
}
ulong TransStrTimeToSecond(const char *str_time)//YYYY-MM-DD HH:MM:YY
{
struct tm nowTm;
time_t longT;
if(str_time == NULL)
return 0;
strptime(str_time,"%Y-%m-%d %H:%M:%S",&nowTm);
longT = mktime(&nowTm);
return longT;
}
int print_buf_in_fmt_ascii(char *ascii_buf, unsigned char *bcd_buf, int len)
{
int i;
char tmp_buf[128];
memset(ascii_buf, 0x00, len*3);
for(i=0;i<len%300; i++)
{
sprintf(tmp_buf,"%02x ",bcd_buf[i]);
strcat(ascii_buf, tmp_buf);
if((i+1)%16 == 0)
{
strcat(ascii_buf, "\r\n");
}
else if((i+1) %8 == 0)
{
strcat(ascii_buf," ");
}
}
return 1;
}
void SetTermSignal(struct termios *ptermio, void (*handler)(int))
{
/*
ioctl(0,TCGETA, ptermio);
ptermio->c_cc[VINTR] = '\x03';
ioctl(0,TCSETA, ptermio);
*/
signal(SIGINT, handler);
signal(SIGKILL,handler);
signal(SIGSTOP,handler);
signal(SIGTERM,handler);
signal(SIGSEGV,handler);
}
void Terminate(int sig)
{
exit(1);
}
void SetFSMTimer()
{
struct itimerval *ptv, tv;
ptv = (struct itimerval *) &tv;
ptv->it_interval.tv_sec = 0;
ptv->it_value.tv_sec = 0;
ptv->it_interval.tv_usec = 10000;
ptv->it_value.tv_usec = 10000;
setitimer(ITIMER_REAL, ptv, NULL);
}
void sysDaemonInit()
{
int i;
pid_t pid;
if ( (pid = fork()) < 0) /* parent terminates */
printf("%s: %s: fork (%d)", __FILE__, __FUNCTION__, __LINE__);
else if (pid != 0)
exit(0); /* parent goes bye-bye */
setsid(); /* become session leader */
for (i = 0; i<3; i++)
close(i);
}
extern int sys_timer10ms;
void sysTimer_IRQ()
{
sys_timer10ms = 1;
}
void SigactionSystem()
{
struct sigaction action;//,actsegv;
action.sa_handler = sysTimer_IRQ;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_RESTART;
if(sigaction(SIGALRM, &action, NULL)<0)
{
printf("sigactin sigalarm failed\n");
}
}

100
proxy_c/common.h Normal file
View File

@@ -0,0 +1,100 @@
#ifndef _COMMON_TYPE_H_
#define _COMMON_TYPE_H_
#include <unistd.h>
#include <sys/types.h> /* basic system data types */
#include <sys/socket.h> /* basic socket definitions */
#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
#include <arpa/inet.h> /* inet(3) functions */
#include <netinet/sctp.h>
#include <sys/epoll.h> /* epoll function */
#include <fcntl.h> /* nonblocking */
#include <sys/resource.h> /*setrlimit */
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <sys/ioctl.h>
#include <termio.h>
#include <sys/stat.h>
#include <sys/io.h>
#include <sys/utsname.h>
#include <pthread.h>
#include <netinet/in.h>
#include <ctype.h>
#include <sys/prctl.h>
#ifndef u8
typedef unsigned char u8;
#endif
#ifndef u16
typedef unsigned short int u16;
#endif
#ifndef u32
typedef unsigned int u32;
#endif
#ifndef u64
typedef unsigned long long u64;
#endif
#ifndef BYTE
typedef unsigned char BYTE;
#endif
#ifndef NULL
#define NULL 0
#endif
#ifndef SUCCESS
#define SUCCESS (0)
#endif
#ifndef FAILURE
#define FAILURE (-1)
#endif
#define MAX_BUFFER 1024
/* common.c */
extern void BcdToAscii (char *ascii_buf, const BYTE *bcd_buf, int len);
extern void BcdToAsciiR(char *ascii_buf, const unsigned char *bcd_buf, int len);
extern char *GetAsciiTime();
extern int GetCurrentTime( char *pNowTime );
extern int print_buf_in_fmt_ascii(char *ascii_buf, unsigned char *bcd_buf, int len);
extern void SetTermSignal(struct termios *ptermio, void (*handler)(int));
extern void Terminate(int sig);
extern void SetFSMTimer();
extern void sysDaemonInit();
extern void sysTimer_IRQ();
extern void SigactionSystem();
/* sock_if.c */
extern int init_socket(unsigned int local_addr, short local_port, char stype, int noblock_flag);
extern int udp_recv_with_ip_info(int fd, char *buf, short MAX_LEN, int *peer_ip, short *peer_port);
extern int udp_send(int fd, int peer_ip, short peer_port, char *buf, short len);
/* mini_cli.c */
extern int cli_read_cmd(char *buf);
extern void debug_monitor(void *arg);
#endif

View File

@@ -0,0 +1,33 @@
#rest proxy local ip and port as server
localIPPort=192.168.139.131:4951
#restfull query ip&port
queryIPPort=192.168.139.131:8080
#restfull vourcher recharge ip&port
rechargeIPPort=192.168.139.131:8080
#user/passwrd
username=external
password=password
subsystem=Selfcare
customerIP=10.60.1.37
#url_walletbalance=/rest-services/%s/xxx
#url_rechargevoucher=/rest-services/%s/yyy
query_topup_getscriberid_switch=1
url_walletbalance_getscriberid=/rest-services/subscriber/serviceinfo/MSISDN/%s/subscriberId
url_walletbalance=/rest-services/subscriber/%s/allowances?identifierName=MSISDN&identifierValue=%s
url_rechargevoucher_getscriberid=/rest-services/subscriber/serviceinfo/MSISDN/%s/subscriberId
url_rechargevoucher=/rest-services/subscriber/%s/refillAccountByVoucher
url_trans_getsubsid_sender=/rest-services/subscriber/serviceinfo/MSISDN/%s/subscriberId
url_trans_getsubsid_receiver=/rest-services/subscriber/serviceinfo/MSISDN/%s/subscriberId
#url_trans=/rest-services/subscriber/%s/giftCredit
url_trans=/rest-services/generic/giftCredit
#test MSISDN
test_msisdn=6924500002
test_msisdn_in=6924500004
#test_msisdn=77922417981167
test_pin=63555825498329

View File

@@ -0,0 +1,33 @@
udp_localIPPort=192.168.1.229:4900
udp_ocsIPPort=192.168.1.229:4951
http_localPort=8080
#authcode url
authcode_url=/authcode
#query_userdata url
query_userdata_url=/query_userdata
#bundle_subs url
bundle_subs_url=/bundle_subs
#bundle_usage url
bundle_usage_url=/bundle_usage
#recharge url
recharge_url=/recharge
#transfer url
transfer_url=/transfer
#recharge_card url
recharge_card_url=/recharge_card
#check_balance url
check_balance_url=/check_balance
#query_balane url
query_balane_url=/query_balane
#errcodes and their meanings
errcode_map_message=[2001,success]
errcode_map_message=[3001,command unsupported]
errcode_map_message=[3010,unknown peer]
errcode_map_message=[4001,invalid user status]
errcode_map_message=[4008,dest user not allowed]
errcode_map_message=[4012,credit limit]
errcode_map_message=[5004,invalid parameter value]
errcode_map_message=[5005,missing parameter]
errcode_map_message=[5006,invalid recharge password]
errcode_map_message=[5012,unable to comply]
errcode_map_message=[5030,user unknown]

638
proxy_c/curl_adaptor.c Normal file
View File

@@ -0,0 +1,638 @@
#include <pthread.h>
#include <sys/prctl.h>
#include "curl_adaptor.h"
#include "utils_queue.h"
// #include "json_adaptor.h"
#include "rest_proxy.h"
#include "log.h"
SRestFulInfo g_restful;
typedef struct _STablCurl
{
ECurlType curlType;
char* curlFormat;
}STablCurl;
/* curl table */
STablCurl g_tab_url[] =
{
// {URL_FETCH_SUB, URLFetchSub},
{URL_FETCH_UPBalance, URLFetchUPBalance},
{URL_FETCH_InfoBalance, URLFetchInfoBalance},
{URL_FETCH_WalletBalance_Getsubsid, URLFetchWalletBalanceGetsubsid},
{URL_FETCH_WalletBalance, URLFetchWalletBalance},
{URL_RECHAGRGE_Getsubsid, URLRechargeGetsubsid},
{URL_RECHAGRGE, URLRecharge},
{URL_TRANS_GetsubsidSender, URLTransGetsubidSender},
{URL_TRANS_GetsubsidReceiver, URLTransGetsubidReceiver},
{URL_TRANS, URLTrans},
};
/* curl cache */
static const int CURL_MAX_CONN = 200;
static const int CURL_WAIT_TIME_US = 30*1000;
static const int CURL_CB_TIME_OUT_MS = 500;
static CURL_ADAPTOR_APP_CB g_curl_adaptor_app_cb;
static queueADT g_curl_queue;
static int g_curl_thread_running;
char *get_val_by_name(const char *str, const char *name, char dst_buf[], const int len)
{
char *p = strstr(str, name);
if(p)
{
char val[2][64] = {{0}};
sscanf(p, "%64[^:]: \"%64[^\"]", val[0], val[1]);
snprintf(dst_buf, len, "%s", val[1]);
LOG_D("[curl][recv] [%s]=>[%s],[%s]\n", str, val[0], val[1]);
return dst_buf;
}
return NULL;
}
int curl_adaptor_resolve_cb_walletbalance(const char *str, unsigned int *balance)
{
char *p_1 = NULL;
char *p_2 = NULL;
char *p_3 = NULL;
if( (p_1 = strstr(str, "balance") ) != NULL &&
(p_2 = strstr(p_1, ":") ) != NULL &&
(p_3 = strstr(p_2, "\"") ) != NULL)
{
char *p_4 = p_3 + 1;
char *p = p_4;
while(*p_4 != '"')
{
p_4++;
}
*p_4 = '\0';
*balance = atof(p) * 100;
return 1;
}
return 0;
}
int curl_adaptor_resolve_cb_validitydate_mon(const char* str, int *mon)
{
static char *str_mon[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int mon_num = sizeof(str_mon)/sizeof(str_mon[0]);
int i = 0;
for( ; i < mon_num; ++i)
{
if(strcmp(str, str_mon[i]) == 0)
{
*mon = i;
return 1;
}
}
return 0;
}
int curl_adaptor_resolve_cb_validitydate(const char *str, unsigned int *validitydate)
{
char data[48] = {0};
if(get_val_by_name(str, "validitydate", data, sizeof(data)) == NULL)
{
return 0;
}
char str_dd[8] = {0};
char str_mon[8] = {0};
char str_year[8]= {0};
char str_h[8] = {0};
char str_m[8] = {0};
char str_s[8] = {0};
int ret = sscanf(data, "%7[^-]-%7[^-]-%7[^ ] %7[^:]:%7[^:]:%7s",
str_dd, str_mon, str_year, str_h, str_m, str_s);
if(ret == 6 || ret == 3)
{
struct tm tm;
time_t time;
tm.tm_year = atoi(str_year) - 1900;
curl_adaptor_resolve_cb_validitydate_mon(str_mon, &tm.tm_mon);
tm.tm_mday = atoi(str_dd);
tm.tm_hour = atoi(str_h);
tm.tm_min = atoi(str_m);
tm.tm_sec = atoi(str_s);
time = mktime(&tm);
*validitydate = time;
LOG_D("[curl][recv] [%s-%s-%s %s:%s:%s]=>[%u]\n", str_year, str_mon, str_dd, str_h, str_m, str_s, *validitydate);
return 1;
}
return 0;
}
/*
* function: handle receive http response and resovle the raw data
*/
static size_t curl_adaptor_resolve_cb(char *d, size_t n, size_t l, void *p)
{
char *p_find, *p_start;
SCurlAdaptor *curAdaptor = (SCurlAdaptor*)p;
switch(curAdaptor->urlType)
{
case URL_FETCH_UPBalance:
break;
case URL_FETCH_InfoBalance:
p_find = strstr(d, ":");
if(p_find == NULL)
{
curAdaptor->msg.query_res.result = FAILURE;
curAdaptor->msg.query_res.error_code = 0;
curAdaptor->msg.query_res.optional_flag = 0;
break;
}
p_find = p_start = strstr(p_find, "\"");
p_find++;
while((*p_find) != '\"')
{
p_find++;
}
*p_find = '\0';
curAdaptor->msg.query_res.balance = (unsigned int)(atoi(p_start+1));
curAdaptor->msg.query_res.result = SUCCESS;
curAdaptor->msg.query_res.error_code = 0;
curAdaptor->msg.query_res.optional_flag = 0;
break;
case URL_FETCH_WalletBalance_Getsubsid:
get_val_by_name(d, "subscriberId", curAdaptor->msg.query.subsid, RESTFUL_SUBSID_LEN);
break;
case URL_FETCH_WalletBalance:
{
int ret = 0;
if(d != NULL)
{
char *tmp = (char*)malloc(strlen(d) + 1);
// char tmp[512] = {0};
strcpy(tmp, d);
ret = curl_adaptor_resolve_cb_walletbalance(tmp, &curAdaptor->msg.query_res.balance);
if(ret != 0)
{
strcpy(tmp, d);
ret = curl_adaptor_resolve_cb_validitydate(tmp, &curAdaptor->msg.query_res.mo_expiry);
}
free(tmp);
}
if(ret != 0)
{
curAdaptor->msg.query_res.result = SUCCESS;
curAdaptor->msg.query_res.mt_expiry = curAdaptor->msg.query_res.mo_expiry;
}
else
{
curAdaptor->msg.query_res.result = FAILURE;
}
curAdaptor->msg.query_res.error_code = 0;
curAdaptor->msg.query_res.optional_flag = 0;
}
break;
case URL_RECHAGRGE_Getsubsid:
get_val_by_name(d, "subscriberId", curAdaptor->msg.topup.subsid, RESTFUL_SUBSID_LEN);
break;
case URL_RECHAGRGE:
{
curAdaptor->msg.topup_res.result = SUCCESS;
curAdaptor->msg.topup_res.error_code = 0;
curAdaptor->msg.topup_res.balance = 0;
curAdaptor->msg.topup_res.mo_expiry = 0;
curAdaptor->msg.topup_res.mt_expiry = 0;
curAdaptor->msg.topup_res.optional_flag = 0;
}
break;
case URL_TRANS_GetsubsidSender:
get_val_by_name(d, "subscriberId", curAdaptor->msg.transfer.subsid_sender, RESTFUL_SUBSID_LEN);
break;
case URL_TRANS_GetsubsidReceiver:
get_val_by_name(d, "subscriberId", curAdaptor->msg.transfer.subsid_receiver, RESTFUL_SUBSID_LEN);
break;
case URL_TRANS:
{
curAdaptor->msg.transfer_res.result = SUCCESS;
curAdaptor->msg.transfer_res.error_code = 0;
curAdaptor->msg.transfer_res.optional_flag = 0;
}
break;
case URL_PPC_OfferGetAllV2_1:
break;
default:
break;
}
return n*l;
}
static void curl_adaptor_easy_init(CURLM *cm, const SCurlAdaptor* curAdaptor)
{
CURL *eh = curl_easy_init();
char userNamePasswordBuf[64] = {0};
/* <20><><EFBFBD><EFBFBD>query<72><79>get-subscriberid<69><64>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>http-request<73><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD> */
if(curAdaptor->urlType == URL_FETCH_WalletBalance ||
curAdaptor->urlType == URL_FETCH_WalletBalance_Getsubsid ||
curAdaptor->urlType == URL_RECHAGRGE_Getsubsid ||
curAdaptor->urlType == URL_TRANS_GetsubsidSender ||
curAdaptor->urlType == URL_TRANS_GetsubsidReceiver)
{
curl_easy_setopt(eh, CURLOPT_WRITEDATA, (void *)(curAdaptor));
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, curl_adaptor_resolve_cb);
// curl_easy_setopt(eh, CURLOPT_HEADER, 0L);
curl_easy_setopt(eh, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(eh, CURLOPT_URL, curAdaptor->urlBuf);
// <20><><EFBFBD><EFBFBD>basic <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1B9A9>֤<EFBFBD><D6A4>Ϣ
curl_easy_setopt(eh, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
snprintf(userNamePasswordBuf, sizeof(userNamePasswordBuf), "%s:%s",
g_rest_proxy_env.cnf.username, g_rest_proxy_env.cnf.password);
curl_easy_setopt(eh, CURLOPT_USERPWD, userNamePasswordBuf);
curl_easy_setopt(eh, CURLOPT_PRIVATE, curAdaptor);
// curl_easy_setopt(eh, CURLOPT_VERBOSE, 0L);
curl_easy_setopt(eh, CURLOPT_TIMEOUT_MS, CURL_CB_TIME_OUT_MS);
curl_easy_setopt(eh, CURLOPT_FORBID_REUSE, 1);
LOG_D(" urlType:%d, curl:%s\n", curAdaptor->urlType, curAdaptor->urlBuf);
}
else if(curAdaptor->urlType == URL_RECHAGRGE ||
curAdaptor->urlType == URL_TRANS)
{
/* <20><><EFBFBD><EFBFBD>topup<75><70>˵<EFBFBD><CBB5>topup<75><70>Ҫ<EFBFBD><D2AA>http-post<73><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.*/
/* ע<><D7A2>: <20><><EFBFBD><EFBFBD>param<61><6D>ȫ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳̿<DFB3><CCBF>ܳ<EFBFBD><DCB3><EFBFBD>. <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>°<EFBFBD>ȫ<EFBFBD><C8AB>. 2019/06/23 22:58:30 */
static char param[512] = {0};
// <20><><EFBFBD><EFBFBD><EFBFBD>ʷ<EFBFBD>0<EFBFBD><30>ʾ<EFBFBD><CABE><EFBFBD>β<EFBFBD><CEB2><EFBFBD>Ϊpost
curl_easy_setopt(eh, CURLOPT_POST, 1);
// url<72><6C>ַ
curl_easy_setopt(eh, CURLOPT_URL,curAdaptor->urlBuf);
// <20><><EFBFBD><EFBFBD>basic <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1B9A9>֤<EFBFBD><D6A4>Ϣ
curl_easy_setopt(eh, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
snprintf(userNamePasswordBuf, sizeof(userNamePasswordBuf), "%s:%s",
g_rest_proxy_env.cnf.username, g_rest_proxy_env.cnf.password);
curl_easy_setopt(eh, CURLOPT_USERPWD, userNamePasswordBuf);
if(curAdaptor->urlType == URL_RECHAGRGE)
{
if(REST_PROXY_SUBSCRIBID_FLAG)
{
/* <20><><EFBFBD><EFBFBD>Ϊquery/topup<75><70><EFBFBD>̶<EFBFBD>Ҫ<EFBFBD>Ȼ<EFBFBD>ȡsubscriber-id<69>Ļ<EFBFBD><C4BB><EFBFBD> topup<75>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: */
/* msisdn=90909093&&pin=39977093792343 */
snprintf(param, sizeof(param), "msisdn=%s&pin=%s",
curAdaptor->msg.topup.msisdn, curAdaptor->msg.topup.pin);
}
else
{
/* <20><><EFBFBD><EFBFBD>Ϊquery/topup<75><70><EFBFBD>̲<EFBFBD><CCB2><EFBFBD><EFBFBD>Ȼ<EFBFBD>ȡsubscriber-id<69><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>query/topup<75><70>self-http, topup<75>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: */
/* char *post_para = "actor=4559936&pin=57160898969922&customerIp=10.60.1.42&voucherId=&subscriberId=4559936&subsystem=Selfcare&rechargeTransactiontId=1503&msisdn=6924559936" */
snprintf(param, sizeof(param), "actor=%s&pin=%s&customerIp=%s&voucherId=%s&subscriberId=%s&subsystem=%s&msisdn=%s",
curAdaptor->msg.topup.msisdn,
curAdaptor->msg.topup.pin,
g_rest_proxy_env.cnf.customer_ip,
"",
curAdaptor->msg.topup.msisdn,
g_rest_proxy_env.cnf.subsystem,
curAdaptor->msg.topup.msisdn);
}
}
else
{
snprintf(param, sizeof(param), "gifteeSubscriptionIdentifier=%s&&gifterSubscriptionIdentifier=%s&&BankTypeToCredit=WalletBank;;%u&&Comments=Gift WalletBank of $%u from %s to %s",
curAdaptor->msg.transfer.msisdn_receiver,
curAdaptor->msg.transfer.msisdn_sender,
curAdaptor->msg.transfer.money,
curAdaptor->msg.transfer.money,
curAdaptor->msg.transfer.msisdn_sender,
curAdaptor->msg.transfer.msisdn_receiver);
}
// post<73><74><EFBFBD><EFBFBD>
curl_easy_setopt(eh, CURLOPT_POSTFIELDS, param);
curl_easy_setopt(eh, CURLOPT_POSTFIELDSIZE, strlen(param) );
// <20>Է<EFBFBD><D4B7>ص<EFBFBD><D8B5><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD><EFBFBD><EFBFBD>ַ
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, curl_adaptor_resolve_cb);
// <20><><EFBFBD><EFBFBD>write_data<74>ĵ<EFBFBD><C4B5>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD>ֵ
curl_easy_setopt(eh, CURLOPT_WRITEDATA, curAdaptor);
curl_easy_setopt(eh, CURLOPT_PRIVATE, curAdaptor);
{
struct curl_slist *chunk = NULL;
/* Remove a header curl would otherwise add by itself */
chunk = curl_slist_append(chunk, "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2");
/* set our custom set of headers */
curl_easy_setopt(eh, CURLOPT_HTTPHEADER, chunk);
}
// <20><>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
// curl_easy_setopt(eh, CURLOPT_VERBOSE, 1);
// <20><><EFBFBD><EFBFBD>Ӧͷ<D3A6><CDB7>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>һ<EFBFBD>𴫸<EFBFBD>write_data
curl_easy_setopt(eh, CURLOPT_HEADER, 1);
// <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>0,<2C><>Ӧͷ<D3A6><CDB7>Ϣlocation
// curl_easy_setopt(eh, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(eh, CURLOPT_FORBID_REUSE, 1);
LOG_D(" urlType:%d, curl:%s param:%s\n", curAdaptor->urlType, curAdaptor->urlBuf, param);
}
curl_multi_add_handle(cm, eh);
}
int curl_adaptor_init_cb(CURL_ADAPTOR_APP_CB appCB)
{
g_curl_adaptor_app_cb = appCB;
return SUCCESS;
}
static int curl_adaptor_init_restfulInfo(const char* queryIP, unsigned int queryPort, const char* rechargeIP, unsigned int rechargePort)
{
strcpy(g_restful.queryIP, queryIP);
g_restful.queryPort = queryPort;
strcpy(g_restful.recharegeIP, rechargeIP);
g_restful.recharegePort = rechargePort;
return SUCCESS;
}
int curl_adaptor_add(SCurlAdaptor* curAdaptor)
{
int len = 0;
int rc = FAILURE;
if(QueueIsFull(g_curl_queue))
{
rc = FAILURE;
goto END;
}
int urlType = curAdaptor->urlType;
switch(urlType)
{
case URL_FETCH_UPBalance:
case URL_FETCH_InfoBalance:
case URL_FETCH_WalletBalance_Getsubsid:
{
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
URLPrefix, g_restful.queryIP, g_restful.queryPort);
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType].curlFormat, curAdaptor->msg.query.msisdn);
}
break;
case URL_FETCH_WalletBalance:
{
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
URLPrefix, g_restful.queryIP, g_restful.queryPort);
if(REST_PROXY_SUBSCRIBID_FLAG)
{
/* <20><><EFBFBD><EFBFBD>Ϊquery/topup<75><70><EFBFBD>̶<EFBFBD>Ҫ<EFBFBD>Ȼ<EFBFBD>ȡsubscriber-id. query/topup<75><70>ʱ<EFBFBD><CAB1>Ҫ<EFBFBD><D2AA>subscriber-id<69>ͳ<EFBFBD>ȥ */
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType].curlFormat, curAdaptor->msg.query.subsid, curAdaptor->msg.query.msisdn);
}
else
{
/* <20><><EFBFBD><EFBFBD>Ϊquery/topup<75><70><EFBFBD>̲<EFBFBD><CCB2><EFBFBD><EFBFBD>Ȼ<EFBFBD>ȡsubscriber-id<69><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>subscriber-id<69>ͳ<EFBFBD>ȥ */
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType].curlFormat, curAdaptor->msg.query.msisdn);
}
}
break;
case URL_RECHAGRGE_Getsubsid:
{
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
URLPrefix, g_restful.recharegeIP, g_restful.recharegePort);
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType].curlFormat, curAdaptor->msg.topup.msisdn);
}
break;
case URL_RECHAGRGE:
{
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
URLPrefix, g_restful.recharegeIP, g_restful.recharegePort);
if(REST_PROXY_SUBSCRIBID_FLAG)
{
/* <20><><EFBFBD><EFBFBD>Ϊquery/topup<75><70><EFBFBD>̶<EFBFBD>Ҫ<EFBFBD>Ȼ<EFBFBD>ȡsubscriber-id. query/topup<75><70>ʱ<EFBFBD><CAB1>Ҫ<EFBFBD><D2AA>subscriber-id<69>ͳ<EFBFBD>ȥ */
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType].curlFormat, curAdaptor->msg.topup.subsid);
}
else
{
/* <20><><EFBFBD><EFBFBD>Ϊquery/topup<75><70><EFBFBD>̲<EFBFBD><CCB2><EFBFBD><EFBFBD>Ȼ<EFBFBD>ȡsubscriber-id<69><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>subscriber-id<69>ͳ<EFBFBD>ȥ */
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType].curlFormat, curAdaptor->msg.topup.msisdn);
}
}
break;
case URL_TRANS_GetsubsidSender:
{
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
URLPrefix, g_restful.recharegeIP, g_restful.recharegePort);
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType].curlFormat, curAdaptor->msg.transfer.msisdn_sender);
}
break;
case URL_TRANS_GetsubsidReceiver:
{
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
URLPrefix, g_restful.recharegeIP, g_restful.recharegePort);
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType].curlFormat, curAdaptor->msg.transfer.msisdn_receiver);
}
break;
case URL_TRANS:
{
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
URLPrefix, g_restful.recharegeIP, g_restful.recharegePort);
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len, "%s",
g_tab_url[urlType].curlFormat/*, curAdaptor->msg.transfer.subsid_sender*/);
}
break;
case URL_PPC_OfferGetAllV2_1:
{
len = snprintf(curAdaptor->urlBuf, RESTFUL_CUL_BUF_MAX, "%s%s:%d",
URLPrefix, g_restful.queryIP, g_restful.queryPort);
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType%URL_MAX_NUM].curlFormat, "-weekly,daily");
}
break;
default:
{
rc = FAILURE;
goto END;
}
break;
}
if(SUCCESS_QUEUE == QueueEnter(g_curl_queue, (queueElementT)curAdaptor) )
{
rc = SUCCESS;
}
else
{
rc = FAILURE;
}
END:
return rc;
}
/* curl_multi_perform() + curl_multi_wait() */
int curl_adaptor_go(SCurlAdaptor *curlAdaptor)
{
CURLM *cm = NULL;
CURL *eh = NULL;
CURLMsg *msg = NULL;
CURLcode return_code = 0;
int still_running = 0, msgs_left = 0;
int http_status_code;
cm = curl_multi_init();
if(cm == NULL) return FAILURE;
/* we can optionally limit the total amount of connections this multi handle uses */
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, (long)CURL_MAX_CONN);
curl_adaptor_easy_init(cm, curlAdaptor);
curl_multi_perform(cm, &still_running);
do
{
int numfds=0;
int res = curl_multi_wait(cm, NULL, 0, CURL_WAIT_TIME_US, &numfds);
if(res != CURLM_OK)
{
LOG_E("[curl][recv] error: curl_multi_wait() returned %d\n", res);
return FAILURE;
}
curl_multi_perform(cm, &still_running);
}while(still_running);
while((msg = curl_multi_info_read(cm, &msgs_left)))
{
if (msg->msg == CURLMSG_DONE)
{
curlAdaptor = NULL;
eh = msg->easy_handle;
return_code = msg->data.result;
curl_easy_getinfo(eh, CURLINFO_PRIVATE, &curlAdaptor);
if(return_code != CURLE_OK)
{
LOG_E("[curl][recv] error: curl_multi_info_read() returned %d\n", return_code);
g_curl_adaptor_app_cb(curlAdaptor, msg->data.result);
curl_multi_remove_handle(cm, eh);
curl_easy_cleanup(eh);
continue;
}
/* Get HTTP status code */
http_status_code = 0;
curl_easy_getinfo(eh, CURLINFO_RESPONSE_CODE, &http_status_code);
if(http_status_code != 200)
{
LOG_E("[curl][recv] get of %p returned http status code %d\n", curlAdaptor, http_status_code);
}
g_curl_adaptor_app_cb(curlAdaptor, http_status_code);
curl_multi_remove_handle(cm, eh);
curl_easy_cleanup(eh);
}
else
{
LOG_E("[curl][recv] error: after curl_multi_info_read(), CURLMsg=%d\n", msg->msg);
}
}
curl_multi_cleanup(cm);
return SUCCESS;
}
int curl_adaptor_init_queue()
{
g_curl_queue = QueueCreate(3000);
return g_curl_queue != NULL;
}
static void *curl_adaptor_thread(void *data)
{
prctl(PR_SET_NAME, "curl_queue");
SCurlAdaptor *curAdaptor;
while(g_curl_thread_running)
{
if( !QueueIsEmpty(g_curl_queue) )
{
curAdaptor = (SCurlAdaptor *)QueueDelete(g_curl_queue);
if(curAdaptor)
{
curl_adaptor_go(curAdaptor);
}
}
usleep(10);
}
pthread_exit(NULL);
return NULL;
}
int curl_adaptor_init_thread()
{
pthread_t handle;
g_curl_thread_running = 1;
if(pthread_create(&handle, NULL, curl_adaptor_thread, NULL))
{
printf("Thread create err !!!\n");
return FAILURE;
if ( pthread_detach(handle) )
{
printf("Thread detached err !!!\n");
return FAILURE;
}
}
return SUCCESS;
}
int curl_adaptor_init(CURL_ADAPTOR_APP_CB appCB,
const char* queryIP,
unsigned int queryPort,
const char* rechargeIP,
unsigned int rechargePort)
{
curl_adaptor_init_queue();
curl_adaptor_init_thread();
curl_adaptor_init_cb(appCB);
curl_adaptor_init_restfulInfo(queryIP, queryPort, rechargeIP, rechargePort);
return SUCCESS;
}
int curl_adaptor_fini()
{
g_curl_thread_running = 0;
QueueDestroy(g_curl_queue);
return SUCCESS;
}

206
proxy_c/curl_adaptor.h Normal file
View File

@@ -0,0 +1,206 @@
#ifndef __CURL_ADAPTOR_H__
#define __CURL_ADAPTOR_H__
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "multi.h"
#include "curl.h"
#include "easy.h"
#include "common.h"
/* for For querying monetary or wallet balance */
#define URLPrefix "" // "http://"
#define URLFetchSub "/rest-services/subscriber/%s"
#define URLFetchUPBalance "/rest-services/subscriber/%s/info/userpaymentbalance"
#define URLFetchInfoBalance "/rest-services/subscriber/%s/info/balance"
/* url: <20><>ѯ */
#define URLFetchWalletBalanceGetsubsid g_rest_proxy_env.cnf.url_fetchwalletbalance_getsubsid
#define URLFetchWalletBalance g_rest_proxy_env.cnf.url_fetchwalletbalance
/* url: <20><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>ֵ */
#define URLRechargeGetsubsid g_rest_proxy_env.cnf.url_recharge_getsubsid
#define URLRecharge g_rest_proxy_env.cnf.url_recharge
/* url: <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA> */
#define URLTransGetsubidSender g_rest_proxy_env.cnf.url_trans_getsubsid_sender
#define URLTransGetsubidReceiver g_rest_proxy_env.cnf.url_trans_getsubsid_receiver
#define URLTrans g_rest_proxy_env.cnf.url_trans
#define RESTFUL_IP_SIZE 32
#define RESTFUL_CUL_BUF_MAX 256
#define RESTFUL_SUBSID_LEN 24
#define RESTFUL_MSISDN_LEN 24
#define RESTFUL_USERNAME 64
#define RESTFUL_PASSWOR 64
typedef struct _SRestfulInfo
{
char queryIP[RESTFUL_IP_SIZE];
unsigned int queryPort;
char recharegeIP[RESTFUL_IP_SIZE];
unsigned int recharegePort;
}SRestFulInfo;
extern SRestFulInfo g_restful;
typedef struct _SubscriberIdentity
{
unsigned char identityChoice; /*1:imsi,2:msisdn*/
unsigned char msisdn[8+1]; /* TBCD */
unsigned char imsi[8+1]; /* TBCD */
}SubscriberIdentity;
typedef enum _ECurlType
{
// URL_FETCH_SUB = 0x00,
URL_FETCH_UPBalance = 0x00,
URL_FETCH_InfoBalance,
URL_FETCH_WalletBalance_Getsubsid,
URL_FETCH_WalletBalance, /* for For querying monetary or wallet balance */
URL_RECHAGRGE_Getsubsid,
URL_RECHAGRGE, /* for Voucher recharge */
URL_TRANS_GetsubsidSender, /* ת<>˻<EFBFBD>ȡsender<65><72>subscriberID<49><44>url */
URL_TRANS_GetsubsidReceiver, /* ת<>˻<EFBFBD>ȡreceiver<65><72>subscriberID<49><44>url */
URL_TRANS, /* ת<>˵<EFBFBD>url */
URL_PPC_OfferGetAllV2_1,
URL_MAX_NUM,
}ECurlType;
typedef struct _SCurlRestAdaptorHeader
{
unsigned short ppsAppID;
unsigned short restproxyAppID;
}SCurlRestAdaptorHeader;
typedef struct _SCurlDataFetchSubscribe
{
SubscriberIdentity subID;
}SCurlDataFetchSubscribe;
typedef union _UCurlAdaptorVal
{
SCurlDataFetchSubscribe subscribeID;
}UCurlAdaptorVal;
/* restful query struct */
typedef struct _SCurlRestAdaptorQuery
{
char msisdn[RESTFUL_MSISDN_LEN];
char subsid[RESTFUL_SUBSID_LEN];
}SCurlRestAdaptorQuery;
/* restful query response struct */
typedef struct _SCurlRestAdatptorQueryRes
{
char optional_flag;
char result;
char error_code;
unsigned int balance;
unsigned int mo_expiry;
unsigned int mt_expiry;
}SCurlRestAdatptorQueryRes;
/* restful topup struct */
typedef struct _SCurlRestAdatptorTopup
{
char msisdn[RESTFUL_MSISDN_LEN];
char pin[RESTFUL_MSISDN_LEN];
char subsid[RESTFUL_SUBSID_LEN];
}SCurlRestAdatptorTopup;
/* restful topup response struct */
typedef struct _SCurlRestAdatptorTopupRes
{
char optional_flag;
char result;
char error_code;
unsigned int balance;
unsigned int mo_expiry;
unsigned int mt_expiry;
}SCurlRestAdatptorTopupRes;
typedef struct _SCurlRestAdatptorTransfer
{
char msisdn_sender[24]; // ת<><D7AA><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD>
char msisdn_receiver[24]; // ת<><D7AA><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD>
unsigned int money; // ת<>˽<EFBFBD><CBBD><EFBFBD>
char subsid_sender[RESTFUL_SUBSID_LEN]; // ת<><D7AA><EFBFBD>˺Ŷ<CBBA>Ӧ<EFBFBD><D3A6>subscriber-id
char subsid_receiver[RESTFUL_SUBSID_LEN]; // ת<><D7AA><EFBFBD>˺Ŷ<CBBA>Ӧ<EFBFBD><D3A6>subscriber-id
}SCurlRestAdatptorTransfer;
typedef struct _SCurlRestAdatptorTransferRes
{
unsigned char optional_flag;
unsigned char result;
unsigned char error_code;
}SCurlRestAdatptorTransferRes;
typedef struct _SCurlAdaptor
{
ECurlType urlType;
char urlBuf[RESTFUL_CUL_BUF_MAX];
SCurlRestAdaptorHeader header;
union
{
SCurlRestAdaptorQuery query;
SCurlRestAdatptorQueryRes query_res;
SCurlRestAdatptorTopup topup;
SCurlRestAdatptorTopupRes topup_res;
SCurlRestAdatptorTransfer transfer;
SCurlRestAdatptorTransferRes transfer_res;
}msg;
}SCurlAdaptor;
/*
* curl adaptor deliver the http request, receive and resolve the reponse, then pass the info to up layer
* curAdaptor: resolve information
* retCode: 200->success
*/
typedef int (*CURL_ADAPTOR_APP_CB)(SCurlAdaptor *curAdaptor, int retCode);
/*
* function: init curl adaptor.
* appCB: curl upper layer call back
* restfulIP: restful host ip. host order
* restfulPort: restful port. host order
* ret: SUCCESS or FAILURE
*/
int curl_adaptor_init(CURL_ADAPTOR_APP_CB appCB, const char* queryIP, unsigned int queryPort, const char* recharegeIP, unsigned int recharegePort);
/*
* function: prepare to call restful api
* curAdaptor: para that to be send as parameter
* ret: SUCCESS or FAILURE
*/
int curl_adaptor_add(SCurlAdaptor* curAdaptor);
/*
* function: relese curl adaptor resource
* ret: SUCCESS or FAILURE
*/
int curl_adaptor_fini();
#endif /* __CURL_ADAPTOR_H__ */

53
proxy_c/dba/Makefile Normal file
View File

@@ -0,0 +1,53 @@
MODULE = dba
TYPE = plat
DBUG_FLAGS_ADD =
RELS_FLAGS_ADD =
##Default commonly as below
BUILD = lib
CFG = debug
PLT_LIB = -DDEBUG
APP_LIB =
LIB_ADD =
SRC_PATH = ./src
INC_PATH = ./src/include
PLT_PATH = ../../plat
APP_PATH = ../../mss
OBJ_ADD =
TEST_OBJ_PATH =
PREPROC_CMD =
POSTPROC_CMD =
##---------------------------------------------------------------------##
##--------------------------------------
##
## Make configuration(Customer define)
##
##--------------------------------------
## CCFLAG_SWITCH = on/off => gcc flag show on/off
## COVER_NEED = yes/no => PTF cover report needed
## COVER_REPORT_PATH = [path ] => PTF cover report path
CCFLAG_SWITCH = off
COVER_NEED = no
COVER_REPORT_PATH = ./output
##---------------------------------------------------------------------##
##--------------------------------------
##
## include makefile.rules (Do not change)
##
##--------------------------------------
include ./scripts/Makefile.rules

View File

@@ -0,0 +1,345 @@
##----------------------------------------------------------##
## ##
## Universal Makefile Rules ##
## ##
## Created : Wei Liu 07/03/07 ##
## Revision: [Last]Wei Liu 07/07/07 ##
## ##
##----------------------------------------------------------##
UMAKE_VERSION := V2.0
##-------------------------------------
##
## Work Directory : /usr/local/include
## Default Target : all
##
##-------------------------------------
default: all
.PHONY: all clean rebuild test indent splint doc \
dir config check bk lsbk rmbk unzip umakever usage\
FORCE
.SUFFIXES:
umakever:
@echo "Universal Makefile (UMake) Version: $(UMAKE_VERSION)"
##--------------------------------------
##
## Makefile CFG defination check
##
##--------------------------------------
ifeq "$(MODULE)" ""
$(error Please input the module name (MODULE = )in makefile. )
endif
ifeq "$(CFG)" ""
CFG=debug
$(warnning No configuration specified for CFG. Defaulting to $(MODULE) - debug. )
endif
ifeq "$(BUILD)" ""
BUILD=lib
$(warnning No configuration specified for BUILD. Defaulting to create lib$(MODULE).a. )
endif
ifeq "$(SRC_PATH)" ""
SRC_PATH=.
$(warnning No configuration specified for SRC_PATH. Defaulting to ./. )
endif
COVER_NEED ?= no
PLT_PATH ?= ../../plat
APP_PATH ?= ../../app
TYPE ?= plat
##--------------------------------------
##
## Gcc Flag for debug or release
##
##--------------------------------------
CC := gcc
GCC_CFLAGS := -Wall -MM
AR_LINK := ar -r
RELS_FLAGS_ADD += -DNDEBUG
RELEASE_CFLAGS += -g -Wall -I. $(RELS_FLAGS_ADD) -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient
RELEASE_LINK_CFLAGS = -g $(RELS_FLAGS_ADD) -o
DEBUG_CFLAGS += -g -Wall -rdynamic -DDEBUG -I. $(DBUG_FLAGS_ADD) -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient -I/usr/include/openssl
DEBUG_LINK_CFLAGS = -g -rdynamic -DDEBUG -o
GLIB_CFLAGS = -I/usr/include/glib-2.0
GLIB_CFLAGS1 = -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
ifeq "$(COVER_NEED)" "yes"
DEBUG_CFLAGS += -fprofile-arcs -ftest-coverage -pg
endif
GCC_CFLAGS=$(DEBUG_CFLAGS) $(GLIB_CFLAGS) $(GLIB_CFLAGS1)
GCC_LINK_CFLAGS=$(DEBUG_LINK_CFLAGS)
##--------------------------------------
##
## Project setting
##
##--------------------------------------
OBJDIR:=./obj
LIBDIR:=./lib
UTDIR :=./ut
DOCDIR:=./doc
DIRBUILD=$(OBJDIR)
ifeq "$(BUILD)" "lib"
BINDIR:=./bin
OUTFILE=$(LIBDIR)/lib$(MODULE).a
DIRNEED=$(UTDIR) $(DOCDIR)
DIRBUILD+=$(LIBDIR)
else
BINDIR:=.
OUTFILE=$(BINDIR)/$(MODULE)
DIRNEED=
DIRBUILD+=$(BINDIR)
endif
##--------------------------------------
##
## source , object and dependencies files
##
##--------------------------------------
SRC_SUBDIR := $(shell find $(SRC_PATH) -type d)
vpath %.c $(SRC_SUBDIR)
vpath %.o $(OBJDIR)
vpath %.d $(OBJDIR)
SRC_FULL_PATH = $(foreach dir,$(SRC_SUBDIR),$(wildcard $(dir)/*.c))
SRC_FILES = $(foreach file, $(notdir $(SRC_FULL_PATH)) ,$(OBJDIR)/$(file))
COMMON_OBJ = $(SRC_FILES:%.c=%.o)
TEST_OBJ_PATH ?= ../../obj
TEST_OBJ = $(foreach dir,$(TEST_OBJ_PATH),$(wildcard $(dir)/*.o))
OBJ=$(COMMON_OBJ) $(OBJ_ADD)
ALL_OBJ := $(OBJ) $(TEST_OBJ)
##--------------------------------------
##
## Lib setting
##
##--------------------------------------
ifeq "$(COVER_NEED)" "yes"
LIBCOVER=-lgcov
endif
MODULE_PLT_LIB=$(foreach lib,$(PLT_LIB), -L$(PLT_PATH)/$(lib)/lib/ -l$(lib) )
MODULE_PLT_LIB+=-lm
MODULE_APP_LIB=$(foreach lib,$(APP_LIB),-L$(APP_PATH)/$(lib)/lib -l$(lib))
##--------------------------------------
##
## Rules
##
##--------------------------------------
CCFLAG_SWITCH ?= off
CC_COMPILE =$(CC) $(GCC_CFLAGS) -c $< -o $@
CC_PRG_LINK=$(CC) $(GCC_LINK_CFLAGS) $(OUTFILE) $(ALL_OBJ) $(LIBCOVER) $(MODULE_APP_LIB) $(MODULE_PLT_LIB) $(LIB_ADD)
CC_LIB_LINK=$(AR_LINK) $(OUTFILE) $(ALL_OBJ)
COMPILE=$(CC_COMPILE)
PRG_LINK=$(CC_PRG_LINK)
LIB_LINK=$(CC_LIB_LINK)
ifeq "$(BUILD)" "exef"
LINK=$(PRG_LINK)
else
LINK=$(LIB_LINK)
endif
# Build rules
all: preproc start dir $(ALL_OBJ) #prtdebug
@echo Linking :$(OUTFILE)
ifeq "$(CCFLAG_SWITCH)" "off"
@$(LINK)
else
$(LINK)
endif
@$(POSTPROC_CMD)
@echo -e "\n================================================================================\n"
sinclude $(DEPENDS)
release : CC_COMPILE =$(CC) $(RELEASE_CFLAGS) -c $< -o $@
release : CC_PRG_LINK=$(CC) $(RELEASE_LINK_CFLAGS) $(OUTFILE) $(ALL_OBJ) $(MODULE_APP_LIB) $(MODULE_PLT_LIB) $(LIB_ADD)
release : all
##--------------------------------------
##
## Make command to use for dependencies
##
##--------------------------------------
MAKE :=make
RM :=rm
MKDIR :=mkdir
preproc:
@$(PREPROC_CMD)
start:
@echo -e "\n================================================================================\n"
@echo "[Building Project]: $(notdir $(MODULE))"
ifeq "$(CCFLAG_SWITCH)" "off"
@echo "Show Gcc Flags switch = OFF"
endif
prtdebug:
@echo "$(MODULE)-$(BUILD)[$(CFG)] build source file:" "$(SRC_FULL_PATH)"
@echo SRC_SUBDIR: $(SRC_SUBDIR)
@echo SRC_FULL_PATH : $(SRC_FULL_PATH)
@echo SRC_FILES : $(SRC_FILES)
@echo ALL_OBJ : $(ALL_OBJ)
@echo LIB:$(MODULE_PLT_LIB)
@echo PLT_LIB: $(PLT_LIB)
@echo CCFLAG_SWITCH :$(CCFLAG_SWITCH)
config: dir
dir:
@$(foreach dir,$(DIRNEED),$(MKDIR) -p $(DIRNEED) --mode=0777; )
@$(foreach dir,$(DIRBUILD),$(MKDIR) -p $(dir) --mode=0777; )
##--------------------------------------
##
## Make Rebuild and clean
##
##--------------------------------------
ifneq "$(PROJ)" ""
FRIEND_PROJ := $(shell )
endif
jumprebuild:
ifneq "$(PROJ)" ""
@cd $(FRIEND_PROJ); mak rebuild ; cd -
endif
# Rebuild this project
rebuild: jumprebuild cleanall all
# Clean this project and all dependencies
cleanall: clean
# Clean this project
clean:
@echo -e "||--------------------------------------------------------------- "
@echo -e "|| Umake clean gcc , lcov, doxygen generated and temporary files. "
@echo -e "||--------------------------------------------------------------- "
@$(RM) -rf $(OBJDIR) $(OUTFILE) $(COVER_REPORT_PATH) ./doc/doxygen.conf ./doc/html ./doc/latex ./doc/rtf $(foreach dir,$(SRC_SUBDIR),$(dir)/*~)
##--------------------------------------
##
## indent Makefile.indent
##
##--------------------------------------
include Makefile.indent
indent:
@chmod 777 $(SRC_FULL_PATH)
@echo ===================================Indent START=================================
@echo
@echo "[Indent source file ]: $(SRC_FULL_PATH)"
$(call MAKE_INDENT , $(SRC_FULL_PATH))
##--------------------------------------
##
## splint makefile.splint
##
##--------------------------------------
include Makefile.splint
SPLINT_FLAG_SWITCH ?= off
splint:
@chmod 777 $(SRC_FULL_PATH)
@echo =================================Splint START==================================
@echo
ifeq "$(SPLINT_FLAG_SWITCH)" "on"
@echo "[Splint flags ]: $(SPLINT_FLAGS)"
endif
@echo "[Lint Clean Project]: $(notdir $(MODULE))"
$(call MAKE_SPLINT, $(SRC_FULL_PATH))
##--------------------------------------
##
## doc Makefile.doxygen
##
##--------------------------------------
include Makefile.doxygen
doc:
@chmod 777 $(SRC_FULL_PATH)
@echo ==================================Doxygen START=================================
@echo
$(call MAKE_DOC, $(SRC_FULL_PATH))
##--------------------------------------
##
## backup Makefile.backup
##
##--------------------------------------
include Makefile.backup
##--------------------------------------
##
## cov Makefile.cov
##
##--------------------------------------
include Makefile.cov
##--------------------------------------
##
## usage Makefile.usage
##
##--------------------------------------
include Makefile.usage
##--------------------------------------
##
## Make dependencies
##
##--------------------------------------
$(OBJDIR)/%.d:%.c
@$(CC) $< -MM -MD -o $@
$(OBJDIR)/%.o:%.c
ifeq "$(CCFLAG_SWITCH)" "off"
@echo -e "building: $(notdir $@) \t\t\t\t please wait ..."
@$(COMPILE)
else
$(COMPILE)
endif
DEPENDS=$(COMMON_OBJ:.o=.d)
##--------------------------------------
##
## Make force
##
##--------------------------------------
FORCE:

138
proxy_c/dba/src/dba_cfg.c Normal file
View File

@@ -0,0 +1,138 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <time.h>
#include "./include/db_adaptor.h"
#define DBA_CFG "./conf/db_adapotr.cfg"
_db_cfg db_cfg;
int dba_read_cfg()
{
char s[80],s1[80];
int len;
unsigned char conf_state=0xFF;
FILE *fpConf;
_db_link *db_ptr=NULL;
memset(&db_cfg, 0x00, sizeof(_db_cfg));
fpConf = fopen(DBA_CFG,"rb");
if(fpConf == NULL)
{
return 0;
}
strcpy(s,"");
strcpy(s1,"");
while(fgets(s,1024,fpConf) !=(char *)0)
{
if( (int *)strchr(s,'#') !=NULL) continue;
if( !strlen(s) ) continue;
len = strlen(s);
if(len < 2) continue;
if(s[len-1] == 0x0d ||s[len-1] == 0x0a)
{
if(s[len-2] == 0x0d ||s[len-2] == 0x0a)
{
s[len-2] = 0;
len -= 2;
}
else
{
s[len-1] = 0;
len -= 1;
}
}
if(!strncasecmp(s,"[db0]",5))
{
conf_state = 0;
db_ptr = &db_cfg.db_link[0];
continue;
}
else if(!strncasecmp(s,"[db1]",5))
{
conf_state = 1;
db_ptr = &db_cfg.db_link[1];
continue;
}
else if(!strncasecmp(s,"[db2]",5))
{
conf_state = 2;
db_ptr = &db_cfg.db_link[2];
continue;
}
else if(!strncasecmp(s,"[db3]",5))
{
conf_state = 3;
db_ptr = &db_cfg.db_link[3];
continue;
}
switch(conf_state)
{
case 0:
case 1:
case 2:
case 3:
if(strncasecmp(s,"enable=",7)==0)
{
if(strncasecmp(&s[7],"on", 2) == 0)
db_ptr->enable = 1;
else
db_ptr->enable = 0;
}
else if(strncasecmp(s,"role=",5)==0)
{
db_ptr->role = atoi(&s[5]);
}
else if(strncasecmp(s,"host_ip=",8)==0)
{
strcpy(db_ptr->str_host_ip, &s[8]);
db_ptr->host_ip = inet_addr(&s[8]);
}
else if(strncasecmp(s,"host_port=",10)==0)
{
db_ptr->host_port = atoi(&s[10]);
}
else if(strncasecmp(s,"db_name=",8)==0)
{
strcpy(db_ptr->db_name, &s[8]);
}
else if(strncasecmp(s,"client_name=",12)==0)
{
strcpy(db_ptr->client_name, &s[12]);
}
else if(strncasecmp(s,"client_pwd=",11)==0)
{
strcpy(db_ptr->client_pwd, &s[11]);
}
break;
}
}
fclose(fpConf);
return 1;
}
int dba_crm_set_prefix_table_created()
{
db_cfg.prefix_file_created = 1;
return 1;
}
int dba_crm_get_prefix_table_flag()
{
return db_cfg.prefix_file_created;
}

350
proxy_c/dba/src/dba_conn.c Normal file
View File

@@ -0,0 +1,350 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "./include/db_adaptor.h"
extern _db_cfg db_cfg;
extern char *GetAsciiTime();
struct timeval tv;
/*-------------------------------------------------*/
int dbc_connect_host(u8 db_index)
{
char host_info[128];
_db_link *db_ptr=NULL;
unsigned int timeout = 20;
MYSQL*tmp_conn = NULL;
db_ptr = &db_cfg.db_link[db_index];
if(db_ptr->enable == 0 || db_ptr->conn_status == 1)
return 0;
if ((db_ptr->db_conn = mysql_init(NULL)) == NULL) {
myLOG_D("DBA: mysql_init():failed\n");
return -1;
}
//unsigned int sslmode = SSL_MODE_DISABLED;
mysql_options(db_ptr->db_conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&timeout);
//mysql_options(db_ptr->db_conn, MYSQL_OPT_SSL_MODE, (const char *)&sslmode);
sprintf(host_info,"%s", db_ptr->str_host_ip);
tmp_conn = mysql_real_connect(db_ptr->db_conn, host_info, db_ptr->client_name, db_ptr->client_pwd, db_ptr->db_name, 0, NULL, 0 );
if(tmp_conn != NULL)
{
db_ptr->conn_status = 1;
db_cfg.total_active_links ++;
myLOG_D("DBA: MYSQL connect to SERVER [%d] succeed @%s\n", db_index, GetAsciiTime());
}
else
{
db_ptr->conn_status = 0;
myLOG_D("DBA: MYSQL connect to SERVER [%d] failed @%s, %s\n", db_index, GetAsciiTime(), mysql_error(db_ptr->db_conn));
mysql_close(db_ptr->db_conn);
return -1;
}
if(db_cfg.total_active_links == 1)
{
db_cfg.current_working_link_id = db_index;
}
return 1;
}
MYSQL *dba_get_working_conn(int db_index)
{
MYSQL *db_conn = NULL;
//u8 index = db_cfg.current_working_link_id;
u8 index = db_index;
if(db_cfg.total_active_links == 0)
return NULL;
if( index < MAX_DB_CONN)
{
db_conn = db_cfg.db_link[index].db_conn;
}
//*db_index = index;
return db_conn;
}
int dba_close_conn(int index)
{
if(index>=MAX_DB_CONN)
return 0;
//mysql_close(db_cfg.db_link[index].db_conn);
//free(db_cfg.db_link[index].db_conn);
db_cfg.db_link[index].conn_status = 0;
db_cfg.total_active_links --;
return 1;
}
int dba_my_ping()
{
int i;
int length;
char ping_sql[256]={"Replace" };
MYSQL *db_conn;
int rc;
for(i=0; i<MAX_DB_CONN; i++)
{
if(db_cfg.db_link[i].conn_status == 0)
continue;
db_conn = db_cfg.db_link[i].db_conn;
if(db_conn == NULL)
continue;
sprintf(ping_sql, "INSERT INTO %s.tb_ping values(%ld)", db_cfg.db_link[i].db_name, tv.tv_sec);
length = strlen(ping_sql);
rc = mysql_real_query(db_conn, ping_sql, length);
if(rc != 0)
{
myLOG_D("DBA: Server [%d] is down by ping @%s error [errno = %d]: [%s]\n", i, GetAsciiTime(), mysql_errno(db_conn),mysql_error(db_conn));
dba_close_conn(i);
if(db_cfg.current_working_link_id == i)
{
if(db_cfg.db_link[1-i].conn_status == 1) //here only support 2 links
{
db_cfg.current_working_link_id = 1 - i;
}
else
db_cfg.current_working_link_id = INVALID_DB_LINK_ID;
}
}
}
return 1;
}
dba_db_sql_execute_crm(const char *sql, char result[][1024], int MAX_ROWS, int MAX_FIELDS, int dump_flag, FILE *fp)
{
int index = 0;
return dba_db_sql_execute_real(index, sql, result, MAX_ROWS, MAX_FIELDS, dump_flag, fp);
}
dba_db_sql_execute_ocs(const char *sql, char result[][1024], int MAX_ROWS, int MAX_FIELDS, int dump_flag, FILE *fp)
{
int index = 1;
return dba_db_sql_execute_real(index, sql, result, MAX_ROWS, MAX_FIELDS, dump_flag, fp);
}
int dba_db_sql_execute_real(int index, const char *sql, char result[][1024], int MAX_ROWS, int MAX_FIELDS, int dump_flag, FILE *fp)
{
int rc;
int i, rows, fields;
u16 length;
MYSQL *db_conn;
MYSQL_RES *res_ptr;
MYSQL_ROW row;
if(sql == NULL)
return 0;
db_conn = dba_get_working_conn(index);
if(db_conn == NULL)
return 0;
if(0)
{
if(dump_flag != 2)
{
if(strlen(sql)<256)
{
myLOG_D(sql);
myLOG_D("\n");
}
else
{
char tmpbuf[512]={""};
memcpy(tmpbuf, sql, 256);
myLOG_D(tmpbuf);
myLOG_D("\n");
}
}
}
length = strlen(sql);
rc = mysql_real_query(db_conn, sql, length);
if(rc != 0)
{
myLOG_D("mysql_real_query error [errno = %d]: [%s]\n",mysql_errno(db_conn),mysql_error(db_conn));
dba_close_conn(index);
//release_mysql_connection(db_conn);
return 0;
}
if(MAX_ROWS == 0)//update not query
return 1;
res_ptr = mysql_store_result(db_conn);
if(res_ptr == NULL)
{
myLOG_D("mysql_store_result error [errno = %d]: [%s]\n",mysql_errno(db_conn),mysql_error(db_conn));
return 0;
}
rows = mysql_num_rows(res_ptr);
if(rows == 0)
goto empty;
rows = 0;
fields = mysql_num_fields(res_ptr);
if(fields > MAX_FIELDS)
fields = MAX_FIELDS;
while ((row = mysql_fetch_row(res_ptr)))
{
if(dump_flag == 1)
{
if(fp != NULL)
{
for (i = 0; i < fields; i++)
{
if(i == fields - 1)
fprintf(fp, "%s\r\n", row[i]);
else
fprintf(fp, "%s,", row[i]);
}
}
}
else
{
for (i = 0; i < fields; i++)
{
if(row[i] == NULL)
{
result[i][0] = 0;
if(0)
{
fields = 0;
rows = 0;
goto empty;
}
}
else
strcpy(result[i], row[i]);
}
}
if(rows++ >= MAX_ROWS)
break;
}
empty:
mysql_free_result(res_ptr);
return rows;//fields;
}
static int sql_query_only_counter = 0;
int dba_db_sql_query_only_execute_real(const char *sql, char result[][1024], int MAX_ROWS, int MAX_FIELDS )
{
int index;
_db_link *db_ptr=NULL;
//load balance for tariff query, db_conn#1/2 always
if(sql == NULL)
return 0;
index = sql_query_only_counter%2;
sql_query_only_counter ++;
db_ptr = &db_cfg.db_link[index+1];
if(db_ptr->enable == 0 || db_ptr->conn_status == 1)
{
db_ptr = &db_cfg.db_link[(1-index)+1];
if(db_ptr->enable == 0 || db_ptr->conn_status == 1)
{
return 0;
}
else
index = (1-index) + 1;
}
else
index = index + 1;
return dba_db_sql_execute_real(index, sql, result, MAX_ROWS, MAX_FIELDS, 0, NULL);
}
int dba_conn_thread(void *param)
{
register u32 check_conn_timer = 1;
register u32 check_sms_notification_timer = 0;
db_cfg.current_working_link_id = INVALID_DB_LINK_ID;
gettimeofday(&tv, NULL);
dba_init_tariff_sql();
crm_pxy_plan_record_init();
while(1)
{
if(check_conn_timer % 1000 == 0)//10s
{
dbc_connect_host(0);
dbc_connect_host(1);
//dbc_connect_host(2);
if(0)
dba_my_ping();
gettimeofday(&tv, NULL);
crm_pxy_plan_record_timer();
}
if(dba_crm_get_prefix_table_flag() == 0)
{
dba_crm_dump_prefix_table_into_file();
}
if(rest_provsioning_enabled())
{
if(check_sms_notification_timer%100 == 0) //1seconds==>2S 100==>200
{
subs_provisioning_command_process();
#if 1//def ENABLE_CRM_REST_AND_Z1
sms_notification_process();
#endif
//dba_crm_scan_bundle_thread(tv.tv_sec);
}
}
logWriter_rt();
check_conn_timer ++;
check_sms_notification_timer ++;
usleep(10000); //10ms
}
return 1;
}

1735
proxy_c/dba/src/dba_crm.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "./include/db_adaptor.h"
extern int dba_conn_thread(void *param);
int dba_main(int argc, char **argv)
{
int i=0;
pthread_t th[MAX_DB_CONN];
u8 param[2];
dba_read_cfg();
logWriter_init();
i = 0;
param[0] = i;
if(1)
{
pthread_create(&th[i],NULL,dba_conn_thread, (void *)param);
//pthread_join(th[i],NULL);
}
else
dba_conn_thread(NULL);
if(0)
{
while(1)
{
logWriter_rt();
sleep(5);
}
}
return 1;
}
void dba_init()
{
dba_read_cfg();
logWriter_init();
}

View File

@@ -0,0 +1,62 @@
/*
** hmac_md5 -- implements RFC 2104
** This hmac_md5 function requires an OpenSSL-compatible MD5
** implementation. There are Public Domain MD5 implementations by Colin
** Plumb and by Solar Designer. You probably want to use one of these.
*/
#include <string.h>
#include "md5.h"
const int blocksize = 64;
const int hashsize = 16;
/*
** The computed HMAC will be written to `digest'.
** Ensure digest points to hashsize bytes of allocated memory.
*/
void
hmac_md5(unsigned char *text, int textlen, unsigned char *key, int keylen,
unsigned char *digest)
{
int i;
MD5_CTX context;
unsigned char ipad[blocksize];
unsigned char opad[blocksize];
/* too long keys are replaced by their hash value */
if (keylen > blocksize) {
MD5_Init(&context);
MD5_Update(&context, key, keylen);
MD5_Final(digest, &context);
key = digest;
keylen = hashsize;
}
/* copy the key into the pads */
memset(ipad, 0, sizeof(ipad));
memcpy(ipad, key, keylen);
memset(opad, 0, sizeof(opad));
memcpy(opad, key, keylen);
/* xor the pads with their ``basic'' value */
for (i=0; i<blocksize; i++) {
ipad[i] ^= 0x36;
opad[i] ^= 0x5c;
}
/* inner pass (ipad ++ message) */
MD5_Init(&context);
MD5_Update(&context, ipad, sizeof(ipad));
MD5_Update(&context, text, textlen);
MD5_Final(digest, &context);
/* outer pass (opad ++ result of inner pass) */
MD5_Init(&context);
MD5_Update(&context, opad, sizeof(opad));
MD5_Update(&context, digest, hashsize);
MD5_Final(digest, &context);
}

View File

@@ -0,0 +1,47 @@
#ifndef __DB_ADAPTOR_H
#define __DB_ADAPTOR_H
#include "mysql.h"
#include "errmsg.h"
#include <dirent.h>
#ifndef _T_TYPE
#define _T_TYPE
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long DWORD;
typedef unsigned long long u64;
#endif
#define MAX_DB_CONN 4
#define DB_NAME_LEN 32
#define DB_PWD_LEN 16
#define INVALID_DB_LINK_ID 0xFF
typedef struct db_link
{
u8 enable;
u8 role; /*1=master, 0=slave */
u8 conn_status; /*0=not connected, 1=connected */
char str_host_ip[16];
u32 host_ip;
u16 host_port;
char db_name[DB_NAME_LEN];
char client_name[DB_NAME_LEN];
char client_pwd[DB_PWD_LEN];
MYSQL *db_conn;
}_db_link;
typedef struct db_cfg
{
u8 total_active_links;
u8 current_working_link_id;
u8 prefix_file_created;
_db_link db_link[MAX_DB_CONN];
}_db_cfg;
#endif

201
proxy_c/dba/src/logWrite.c Normal file
View File

@@ -0,0 +1,201 @@
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <termio.h>
#include <sys/stat.h>
#include <sys/io.h>
#include <sys/utsname.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdarg.h>
static int new_file_flag = 1;
static char system_name[128]="dba";
static char log_file_name[256] = {0};
static char log_path[256]="/var/log";
static int log_max_files=100;
static int max_file_size=10240; //10M
FILE *logFile_fp = NULL;
void logWriter_read_param()
{
char cnf_file[]="./conf/logWriter.conf";
char info_str[512], *buf_ptr;;
FILE *fp=NULL;
fp = fopen(cnf_file,"r");
if(fp == NULL)
return;
while (!feof(fp))
{
info_str[0] = '\n';
fgets(info_str, 500, fp);
if (info_str[0] == '#' || info_str[0] == '\n')
continue;
buf_ptr = info_str;
if(!strncasecmp(info_str,"sysName=",8))
{
strsep(&(buf_ptr), "=\n");
snprintf(system_name, sizeof(system_name), "%s", strsep(&(buf_ptr), "=\n") );
}
if(!strncasecmp(info_str,"logPath=",8))
{
strsep(&(buf_ptr), "=\n");
snprintf(log_path, sizeof(log_path), "%s", strsep(&(buf_ptr), "=\n") );
}
if(!strncasecmp(info_str,"logMaxFiles=",12))
{
log_max_files = atoi(&info_str[12]);
if ( log_max_files > 500 )
{
log_max_files = 500;
}
continue;
}
if(!strncasecmp(info_str,"logMaxFileSize(KB)=",19))
{
max_file_size = atoi(&info_str[19]);
// Set the min file size to 100KB to control the CPU loading
if (max_file_size < 100)
{
max_file_size = 100;
}
continue;
}
}
printf(" sysName = %s\n logPath = %s\n logMaxFiles = %d\n logMaxFileSize(KB) = %d\n", \
system_name, log_path, log_max_files, max_file_size);
}
int logWriter_init()
{
logWriter_read_param();
if(access(log_path,0) == -1 )
{
if (mkdir(log_path,0777))
{
printf("creat log_path %s failed!!!", log_path );
}
}
snprintf(log_file_name, sizeof(log_file_name), "%s/%s.log", log_path, system_name);
logFile_fp = fopen ( log_file_name, "a" );
printf("logWriter Init Complete!\n");
return 1;
}
int logWriter_write_log_to_disk(char *log_record)
{
short len;
if(log_record == NULL)
return 0;
len = strlen(log_record);
fwrite ( log_record, len, 1, logFile_fp );
fflush ( logFile_fp ); // force to write to harddisk
return 1;
}
int myLOG_D( const char *fmt, ...)
{
va_list apa;
char buf[10240];
//return 0;
va_start(apa, fmt);
vsprintf(buf, fmt, apa);
va_end(apa);
logWriter_write_log_to_disk(buf);
return 1;
}
void logWriter_rename_log_file()
{
int i;
char old_file_name[256], new_file_name[256];
if (log_max_files == 0)
{
return;
}
for ( i=(log_max_files-1); i>0; i-- )
{
snprintf(old_file_name, sizeof(old_file_name), "%s/%s.log.%d", log_path, system_name, i);
if (1 == i)
{
snprintf(new_file_name, sizeof(new_file_name), "%s/%s.log", log_path, system_name);
}
else
{
snprintf(new_file_name, sizeof(new_file_name), "%s/%s.log.%d", log_path, system_name, (i-1) );
}
if ( access(new_file_name, R_OK) == 0 )
{
rename(new_file_name, old_file_name);
}
}
}
int logWriter_rt()
{
struct stat buf;
char real_path[128];
if (log_file_name[0] != 0)
{
realpath(log_file_name, real_path);
stat(real_path, &buf);
if ( buf.st_size >= (max_file_size*1024) )
{
new_file_flag = 1;
logWriter_rename_log_file();
}
}
if ( 1 == new_file_flag )
{
if (logFile_fp != NULL)
{
fclose ( logFile_fp );
logFile_fp = NULL;
}
logFile_fp = fopen ( log_file_name, "a" );
new_file_flag = 0;
}
return 1;
}
//int main(int argc, char **argv)
//{
// logWriter_init();
//
// while(1)
// {
// logWriter_rt();
// usleep(10);
// }
//
// return 1;
//}

View File

@@ -0,0 +1,188 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <sys/time.h>
#include <time.h>
typedef unsigned char u8;
typedef unsigned int u32;
typedef unsigned short u16;
#define PLAN_RECORDS 60000
#define INVALID_PLAN_INDEX 0xFFFFFFFF
typedef struct plan_record
{
u32 index;
u8 used_flag;
u32 plan_id;
u32 updated_time;
}__attribute__((packed)) _plan_record;
typedef struct plan_table
{
u32 record_num;
u32 cur_index;
_plan_record plan_record[PLAN_RECORDS+1];
}__attribute__((packed)) _plan_table;
/* ------------ Variables --------------*/
static GHashTable *htb_plan = NULL;
static _plan_table plan_table;
extern struct timeval tv;
/* ------------ resouce functions --------------*/
void free_mem(gpointer data)
{
free(data);
}
int crm_pxy_init_hash_table()
{
if(htb_plan != NULL)
g_hash_table_destroy(htb_plan);
htb_plan = g_hash_table_new(g_direct_hash,g_direct_equal);
return 1;
}
int hash_add_plan_entity(_plan_record *plan_ptr)
{
if(plan_ptr != NULL)
g_hash_table_insert(htb_plan, GINT_TO_POINTER(plan_ptr->plan_id), plan_ptr);
return 1;
}
int hash_clean_plan_entity(_plan_record *plan_ptr)
{
if(plan_ptr != NULL)
g_hash_table_remove(htb_plan, GINT_TO_POINTER(plan_ptr->plan_id));
return 1;
}
int crm_pxy_get_plan_index(u32 plan_id)
{
u32 index = INVALID_PLAN_INDEX;
_plan_record *ptr=NULL;
ptr = (_plan_record *)g_hash_table_lookup(htb_plan, GINT_TO_POINTER(plan_id));
if(ptr != NULL)
index = ptr->index;
return index;
}
int crm_pxy_get_plan_record(u32 plan_id, _plan_record *plan_ptr)
{
u32 index = crm_pxy_get_plan_index(plan_id);
return index;
if(index != INVALID_PLAN_INDEX)
{
plan_ptr = &plan_table.plan_record[index];
return 1;
}
return 0;
}
_plan_record *crm_pxy_assign_plan_index(u32 plan_id)
{
register int loop;
int index;
_plan_record *plan_ptr;
for(loop = 0; loop < PLAN_RECORDS; loop++)
{
index = plan_table.cur_index++;
plan_table.cur_index %= PLAN_RECORDS;
if(plan_table.plan_record[index].used_flag == 0)
{
plan_table.record_num ++;
plan_ptr = &plan_table.plan_record[index];
plan_ptr->used_flag = 1;
plan_ptr->index = index;
plan_ptr->plan_id = plan_id;
plan_ptr->updated_time = tv.tv_sec;
return plan_ptr;
}
}
return NULL;
}
int crm_pxy_purge_plan_record(_plan_record *plan_ptr)
{
hash_clean_plan_entity(plan_ptr);
plan_ptr->used_flag = 0;
plan_table.record_num --;
return 1;
}
int crm_pxy_add_plan_record(u32 plan_id)
{
_plan_record *plan_ptr = NULL;
plan_ptr = crm_pxy_assign_plan_index(plan_id);
if(plan_ptr == NULL)
return 0;
hash_add_plan_entity(plan_ptr);
return 1;
}
int crm_pxy_check_plan_record(u32 plan_id)
{
u32 index = crm_pxy_get_plan_index(plan_id);
if(index != INVALID_PLAN_INDEX)
{
return 1;
}
return 0;
}
void crm_pxy_plan_record_init()
{
crm_pxy_init_hash_table();
}
static int EXPIRED_TIME_SEC = (86400)*(15);
void crm_pxy_plan_record_timer()
{
static int crm_pxy_scan_ptr=0;
int i;
_plan_record *plan_ptr = NULL;
for(i=0; i<1000; i++)
{
plan_ptr = &plan_table.plan_record[crm_pxy_scan_ptr++];
crm_pxy_scan_ptr %= PLAN_RECORDS;
if(plan_ptr->used_flag == 1)
{
if((plan_ptr->updated_time + EXPIRED_TIME_SEC)<tv.tv_sec)
hash_clean_plan_entity(plan_ptr);
}
}
}

102
proxy_c/log.c Normal file
View File

@@ -0,0 +1,102 @@
#include "log.h"
#include "common.h"
struct log_s g_log_env;
int log_print(int index)
{
char file_name[200];
char now_time[12];
if(index == 0)
{
g_log_env.log_flag = 1;
GetCurrentTime(now_time);
sprintf(file_name, "%s_%02d_%02d_%02d_%02d_%02d_%02d.log",
g_log_env.log_file,
now_time[0],
now_time[1],
now_time[2],
now_time[3],
now_time[4],
now_time[5]);
g_log_env.log_fp = fopen(file_name, "a+");
if(g_log_env.log_fp != NULL)
{
fprintf(g_log_env.log_fp, "Rest Proxy: Start @%s\r\n", GetAsciiTime());
}
}
else
{
if(g_log_env.log_fp != NULL)
fclose(g_log_env.log_fp);
GetCurrentTime(now_time);
sprintf(file_name, "%s_%02d_%02d_%02d_%02d_%02d_%02d.log", g_log_env.log_file,
now_time[0],
now_time[1],
now_time[2],
now_time[3],
now_time[4],
now_time[5]);
g_log_env.log_fp = fopen(file_name, "a+");
if(g_log_env.log_fp != NULL)
{
fprintf(g_log_env.log_fp, "< Log file opened @%s >\r\n", GetAsciiTime());
}
}
return 1;
}
int rest_proxy_open_log(int index)
{
char file_name[200];
char now_time[12];
if(index == 0)
{
g_log_env.log_flag = 1;
GetCurrentTime(now_time);
sprintf(file_name, "%s_%02d_%02d_%02d_%02d_%02d_%02d.log",
g_log_env.log_file,
now_time[0],
now_time[1],
now_time[2],
now_time[3],
now_time[4],
now_time[5]);
g_log_env.log_fp = fopen(file_name, "a+");
if(g_log_env.log_fp != NULL)
{
fprintf(g_log_env.log_fp, "Rest Proxy: Start @%s\r\n", GetAsciiTime());
}
}
else
{
if(g_log_env.log_fp != NULL)
fclose(g_log_env.log_fp);
GetCurrentTime(now_time);
sprintf(file_name, "%s_%02d_%02d_%02d_%02d_%02d_%02d.log", g_log_env.log_file,
now_time[0],
now_time[1],
now_time[2],
now_time[3],
now_time[4],
now_time[5]);
g_log_env.log_fp = fopen(file_name, "a+");
if(g_log_env.log_fp != NULL)
{
fprintf(g_log_env.log_fp, "< Log file opened @%s >\r\n", GetAsciiTime());
}
}
return SUCCESS;
}

60
proxy_c/log.h Normal file
View File

@@ -0,0 +1,60 @@
#ifndef _LOG_H__
#define _LOG_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "rest_proxy.h"
struct log_s
{
int log_flag; /* log information */
char log_file[128];
FILE *log_fp;
unsigned int log_nums;
};
extern struct log_s g_log_env;
#define LOG_D(...) \
do{ \
if(g_log_env.log_flag) \
{ \
g_log_env.log_nums ++; \
fprintf(g_log_env.log_fp, __VA_ARGS__); \
printf( __VA_ARGS__); \
fflush(g_log_env.log_fp); \
if(g_log_env.log_nums % 2000000==0) \
log_print(1); \
} \
}while(0)
#define LOG_E(...) \
do{ \
if(g_log_env.log_flag) \
{ \
g_log_env.log_nums ++; \
fprintf(g_log_env.log_fp, __VA_ARGS__); \
printf( __VA_ARGS__); \
fflush(g_log_env.log_fp); \
if(g_log_env.log_nums % 2000000==0) \
log_print(1); \
} \
}while(0)
int log_print(int index);
int rest_proxy_open_log(int index);
#ifdef __cplusplus
}
#endif
#endif

198
proxy_c/main.c Normal file
View File

@@ -0,0 +1,198 @@
#include "rest_proxy.h"
#include "selfcare_proxy.h"
#include "log.h"
int sys_timer10ms;
static int proxy_run_mode = 0;
// <20><><EFBFBD><EFBFBD>ģʽ
#define RUN_MODE_WITH_ALPOOCS 1 /* alpo_ocs<--restful-->restproxy<--udp-->pps */
#define RUN_MODE_WITH_ERSTFUL 2 /* user<------restful-->restproxy<--udp-->ocs */
#define RUN_MODE_WITH_CRM 4 /* user<--CRM--restful-->restproxy<--udp-->ocs, recharge card/tariff in CRM */
extern int dba_main(int argc, char **argv);
extern int smcli_client_thread(void *param);
extern int pstn_client_thread(void *param);
extern void _selfcare_udp_process();
extern void _selfcare_res_fsm(void);
int get_proxy_run_mode()
{
return proxy_run_mode;
}
int fsm_debug()
{
char buf[MAX_BUFFER];
if(cli_read_cmd(buf) == 0)
return 0;
if(strncasecmp(buf, "log off", 7) == 0)
{
g_log_env.log_flag = 0x00;
}
else if(strncasecmp(buf, "log all", 7) == 0)
{
g_log_env.log_flag = 0xff;
}
return 1;
}
int init_comm(const int log_flag, const char *log_file)
{
if(log_flag)
{
strcpy(g_log_env.log_file, log_file);
}
else
{
strcpy(g_log_env.log_file, "./log/log");
}
int ret = rest_proxy_open_log(0);
return ret;
}
int init_modes(int run_mode, int argc, char **argv)
{
int ret = SUCCESS;
pthread_t tid;
pthread_create(&tid, NULL, (void *)debug_monitor, NULL);
if(run_mode == RUN_MODE_WITH_ALPOOCS)
{
/* <20><>ʼ<EFBFBD><CABC>rest proxy. alpo_ocs<-----restful_http-->rest_proxy<------udp----->pps */
ret = rest_proxy_init();
if(ret != SUCCESS)
{
return ret;;
}
}
if(run_mode == RUN_MODE_WITH_ERSTFUL || run_mode == RUN_MODE_WITH_CRM )
{
pthread_create(&tid, NULL, (void *)smcli_client_thread, NULL);
pthread_create(&tid, NULL, (void *)pstn_client_thread, NULL);
if(run_mode == RUN_MODE_WITH_CRM)
{
dba_main(0, NULL);
}
#if 1//def ENABLE_CRM_REST_AND_Z1
/* <20><>ʼ<EFBFBD><CABC>selfcare proxy. self_care<-----restful_http----->rest_proxy<-----udp---->ocs */
ret = selfcare_proxy_init(argc, argv);
if(ret != SUCCESS)
{
return ret;;
}
#endif
}
return ret;
}
void run_modes_fsm(int run_mode)
{
if(run_mode == RUN_MODE_WITH_ALPOOCS)
{
rest_proxy_fsm_main();
}
fsm_debug();
}
int main(int argc, char **argv)
{
int ret;
int err_flag = 0;
char log_file[128]= {0};
int run_mode = RUN_MODE_WITH_ALPOOCS;
int log_flag = 0;
int daemon_flag = 0;
struct termios prev_termio;
while ((ret = getopt(argc, argv, "a:d:f:r:e")) != -1)
{
switch (ret)
{
case 'd':
daemon_flag = 1;
break;
case 'f':
if(optarg != NULL)
{
log_flag = 1;
strcpy(log_file, optarg);
}
break;
case 'r':
if(optarg != NULL)
{
run_mode = atoi(optarg) ;//== RUN_MODE_WITH_ERSTFUL ? RUN_MODE_WITH_ERSTFUL : RUN_MODE_WITH_ALPOOCS;
}
break;
case '?':
err_flag = 1;
break;
}
}
if (err_flag)
{
printf("Usage: %s -c restproxy [-f /va/log/sgs_log_file.txt] [-d] [-r 1(with alpo ocs))|2(with selfcare)]\n", argv[0]);
exit(1);
}
proxy_run_mode = run_mode;
if(daemon_flag)
{
sysDaemonInit();
}
SetTermSignal(&prev_termio, Terminate);
SigactionSystem();
SetFSMTimer();
ret = init_comm(log_flag, log_file);
if(ret != 0)
{
goto INITFAIL;
}
ret = init_modes(run_mode, argc, argv);
if(ret != 0)
{
goto INITFAIL;
}
sys_timer10ms = 1;
while(1)
{
if(sys_timer10ms)
{
run_modes_fsm(run_mode);
}
if(0)
{
_selfcare_udp_process();
_selfcare_res_fsm();
}
usleep(5000);
}
INITFAIL:
rest_proxy_uninit();
selfcare_proxy_uninit();
return 0;
}

234
proxy_c/mini_cli.c Normal file
View File

@@ -0,0 +1,234 @@
#include "common.h"
#include "rest_proxy.h"
#define DEBUG_PORT 4865
static int sockfd = 0;
static int client_fd = -1;
extern int init_socket(unsigned int local_addr, short local_port, char stype, int noblock_flag);
extern int setnodelay(int fd);
extern int printf_stat(FILE *fd);
extern int reset_data_sn();
extern void rest_proxy_print_stat();
extern int dba_verify_vc_with_pwd(const char *vc_pwd, char card_info[][1024], char *enc_password);
extern int dba_db_sql_query_only_execute_real(const char *sql, char result[][1024], int MAX_ROWS, int MAX_FIELDS );
extern void crm_set_notificaton_flag(int flag);
extern void crm_set_test_mode_flag(int flag);
char cli_cmd[128];
int cli_cmd_len = 0;
int cli_read_cmd(char *buf)
{
int len = cli_cmd_len;
if(len>0)
strcpy(buf, cli_cmd);
cli_cmd_len = 0;
return len;
}
int cli_send_debug(char *buf)
{
if(buf != NULL)
send(client_fd,buf,strlen(buf),MSG_NOSIGNAL);
return 1;
}
int save_cli_cmd(char *cmd)
{
strcpy(cli_cmd, cmd);
cli_cmd_len = strlen(cmd);
return 1;
}
#ifdef TEST_RESTPROXY
extern int g_pps_sendquery_to_restproxy_num;
extern int g_pps_sendtopup_to_restproxy_num;
extern int g_pps_sendtrans_to_restproxy_num;
#endif
int recv_command()
{
int i = 0;
socklen_t server_addr_len = 0;
int nbytes/*, len*/;
struct sockaddr_in sin;
char buf[128],cmd;
FILE *fp = NULL;
// len = sizeof(struct sockaddr);
nbytes = recvfrom(client_fd, buf, 128, 0,(struct sockaddr *) &sin, &server_addr_len);
if(nbytes == 0)
{
client_fd = -1;
return 0;
}
if(nbytes < 0)
return 0;
if(toupper(buf[0]) == 'Q')
{
close(client_fd);
client_fd = -1;
return 0;
}
save_cli_cmd(buf);
// send(client_fd,">",1,MSG_NOSIGNAL);
// return 1;
for(i = 0; i < nbytes; ++i)
{
if(buf[i] == '\r' && buf[i+1] == '\n')
{
buf[i] = '\0';
}
}
if(strncasecmp(buf, "test query", 10) == 0)
{
send(client_fd, ">test query OK!\n", 16, MSG_NOSIGNAL);
#ifdef TEST_RESTPROXY
if(!g_pps_sendquery_to_restproxy_num)
g_pps_sendquery_to_restproxy_num = atoi(&buf[11]);
#endif
goto END;
}
if(strncasecmp(buf, "test topup", 10) == 0)
{
send(client_fd, ">test topup OK!\n", 16, MSG_NOSIGNAL);
#ifdef TEST_RESTPROXY
if(!g_pps_sendtopup_to_restproxy_num)
g_pps_sendtopup_to_restproxy_num = atoi(&buf[11]);
#endif
goto END;
}
if(strncasecmp(buf, "test transfer", 13) == 0)
{
send(client_fd, ">test transfer OK!\n", 19, MSG_NOSIGNAL);
#ifdef TEST_RESTPROXY
if(!g_pps_sendtrans_to_restproxy_num)
g_pps_sendtrans_to_restproxy_num = atoi(&buf[14]);
#endif
goto END;
}
if(strncasecmp(buf, "emu enable=", 11) == 0)
{
int ivalue = atoi(&buf[11]);
if(ivalue == 0)
send(client_fd, ">Disable Emulator, OK!\n", 23, MSG_NOSIGNAL);
else
send(client_fd, ">Enable Emulator, OK!\n", 22, MSG_NOSIGNAL);
rest_conf_set_emulator_flag(ivalue);
goto END;
}
if(strncasecmp(buf, "get stat", 8) == 0)
{
rest_proxy_print_stat();
send(client_fd, ">get stat OK!\n", 15, MSG_NOSIGNAL);
goto END;
}
if(strncasecmp(buf, "test card=", 10) == 0)
{
dba_verify_vc_with_pwd(&buf[10], NULL, NULL);
send(client_fd, ">get stat OK!\n", 15, MSG_NOSIGNAL);
goto END;
}
if(strncasecmp(buf, "test query", 10) == 0)
{
char sql[4096]="select * from tb_sms_info limt 1";
char result[30][1024];
dba_db_sql_query_only_execute_real(sql, result, 1, 30);
send(client_fd, ">test tariff query OK!\n", 15, MSG_NOSIGNAL);
goto END;
}
if(strncasecmp(buf, "enable notification", 19) == 0)
{
crm_set_notificaton_flag(1);
goto END;
}
if(strncasecmp(buf, "disable notification", 20) == 0)
{
crm_set_notificaton_flag(0);
goto END;
}
if(strncasecmp(buf, "test mode=", 10) == 0)
{
crm_set_test_mode_flag((int)(buf[10]));
send(client_fd, ">set test mode OK!\n", 15, MSG_NOSIGNAL);
goto END;
}
if(nbytes>0)
{
cmd = toupper(buf[0]);
switch(cmd)
{
case 'P':
fp = fopen("stat.txt","w");
// printf_stat(fp);
send(client_fd,">OK!\n",4,MSG_NOSIGNAL);
fclose(fp);
break;
case 'S':
send(client_fd,">OK!\n",4,MSG_NOSIGNAL);
// reset_data_sn();
break;
case 'Q':
close(client_fd);
client_fd = -1;
break;
/*
default:
send(client_fd,">UNK CMD!\n",15,MSG_NOSIGNAL);
send(client_fd,">",6,MSG_NOSIGNAL);
break;
*/
}
send(client_fd,">",1,MSG_NOSIGNAL);
}
END:
return nbytes;
}
int debug_init()
{
sockfd = init_socket(0, DEBUG_PORT,1,1);
listen(sockfd, 2);
return 1;
}
void debug_monitor(void *arg)
{
prctl(PR_SET_NAME, "debug_monitor");
socklen_t clilen;
struct sockaddr_in cliaddr;
debug_init();
while(1)
{
if(client_fd<0)
{
client_fd = accept(sockfd,(struct sockaddr *)&cliaddr,&clilen);
if(client_fd>0)
{
setnodelay(client_fd);
send(client_fd, ">", 1, MSG_NOSIGNAL);
}
}
else
{
recv_command();
}
usleep(10000);
}
}

BIN
proxy_c/pkg.tgz Normal file

Binary file not shown.

53
proxy_c/pstn_cli/Makefile Normal file
View File

@@ -0,0 +1,53 @@
MODULE = pstncli
TYPE = plat
DBUG_FLAGS_ADD =
RELS_FLAGS_ADD =
##Default commonly as below
BUILD = lib
CFG = debug
PLT_LIB = -DDEBUG
APP_LIB =
LIB_ADD =
SRC_PATH = ./src
INC_PATH = ./src/include
PLT_PATH = ../../plat
APP_PATH = ../../mss
OBJ_ADD =
TEST_OBJ_PATH =
PREPROC_CMD =
POSTPROC_CMD =
##---------------------------------------------------------------------##
##--------------------------------------
##
## Make configuration(Customer define)
##
##--------------------------------------
## CCFLAG_SWITCH = on/off => gcc flag show on/off
## COVER_NEED = yes/no => PTF cover report needed
## COVER_REPORT_PATH = [path ] => PTF cover report path
CCFLAG_SWITCH = off
COVER_NEED = no
COVER_REPORT_PATH = ./output
##---------------------------------------------------------------------##
##--------------------------------------
##
## include makefile.rules (Do not change)
##
##--------------------------------------
include ./scripts/Makefile.rules

View File

@@ -0,0 +1,342 @@
##----------------------------------------------------------##
## ##
## Universal Makefile Rules ##
## ##
## Created : Wei Liu 07/03/07 ##
## Revision: [Last]Wei Liu 07/07/07 ##
## ##
##----------------------------------------------------------##
UMAKE_VERSION := V2.0
##-------------------------------------
##
## Work Directory : /usr/local/include
## Default Target : all
##
##-------------------------------------
default: all
.PHONY: all clean rebuild test indent splint doc \
dir config check bk lsbk rmbk unzip umakever usage\
FORCE
.SUFFIXES:
umakever:
@echo "Universal Makefile (UMake) Version: $(UMAKE_VERSION)"
##--------------------------------------
##
## Makefile CFG defination check
##
##--------------------------------------
ifeq "$(MODULE)" ""
$(error Please input the module name (MODULE = )in makefile. )
endif
ifeq "$(CFG)" ""
CFG=debug
$(warnning No configuration specified for CFG. Defaulting to $(MODULE) - debug. )
endif
ifeq "$(BUILD)" ""
BUILD=lib
$(warnning No configuration specified for BUILD. Defaulting to create lib$(MODULE).a. )
endif
ifeq "$(SRC_PATH)" ""
SRC_PATH=.
$(warnning No configuration specified for SRC_PATH. Defaulting to ./. )
endif
COVER_NEED ?= no
PLT_PATH ?= ../../plat
APP_PATH ?= ../../app
TYPE ?= plat
##--------------------------------------
##
## Gcc Flag for debug or release
##
##--------------------------------------
CC := gcc
GCC_CFLAGS := -Wall -MM
AR_LINK := ar -r
RELS_FLAGS_ADD += -DNDEBUG
RELEASE_CFLAGS += -g -Wall -I. $(RELS_FLAGS_ADD) -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient
RELEASE_LINK_CFLAGS = -g $(RELS_FLAGS_ADD) -o
DEBUG_CFLAGS += -g -Wall -rdynamic -DDEBUG -I. $(DBUG_FLAGS_ADD) -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient -I/usr/include/openssl
DEBUG_LINK_CFLAGS = -g -rdynamic -DDEBUG -o
ifeq "$(COVER_NEED)" "yes"
DEBUG_CFLAGS += -fprofile-arcs -ftest-coverage -pg
endif
GCC_CFLAGS=$(DEBUG_CFLAGS)
GCC_LINK_CFLAGS=$(DEBUG_LINK_CFLAGS)
##--------------------------------------
##
## Project setting
##
##--------------------------------------
OBJDIR:=./obj
LIBDIR:=./lib
UTDIR :=./ut
DOCDIR:=./doc
DIRBUILD=$(OBJDIR)
ifeq "$(BUILD)" "lib"
BINDIR:=./bin
OUTFILE=$(LIBDIR)/lib$(MODULE).a
DIRNEED=$(UTDIR) $(DOCDIR)
DIRBUILD+=$(LIBDIR)
else
BINDIR:=.
OUTFILE=$(BINDIR)/$(MODULE)
DIRNEED=
DIRBUILD+=$(BINDIR)
endif
##--------------------------------------
##
## source , object and dependencies files
##
##--------------------------------------
SRC_SUBDIR := $(shell find $(SRC_PATH) -type d)
vpath %.c $(SRC_SUBDIR)
vpath %.o $(OBJDIR)
vpath %.d $(OBJDIR)
SRC_FULL_PATH = $(foreach dir,$(SRC_SUBDIR),$(wildcard $(dir)/*.c))
SRC_FILES = $(foreach file, $(notdir $(SRC_FULL_PATH)) ,$(OBJDIR)/$(file))
COMMON_OBJ = $(SRC_FILES:%.c=%.o)
TEST_OBJ_PATH ?= ../../obj
TEST_OBJ = $(foreach dir,$(TEST_OBJ_PATH),$(wildcard $(dir)/*.o))
OBJ=$(COMMON_OBJ) $(OBJ_ADD)
ALL_OBJ := $(OBJ) $(TEST_OBJ)
##--------------------------------------
##
## Lib setting
##
##--------------------------------------
ifeq "$(COVER_NEED)" "yes"
LIBCOVER=-lgcov
endif
MODULE_PLT_LIB=$(foreach lib,$(PLT_LIB), -L$(PLT_PATH)/$(lib)/lib/ -l$(lib) )
MODULE_PLT_LIB+=-lm
MODULE_APP_LIB=$(foreach lib,$(APP_LIB),-L$(APP_PATH)/$(lib)/lib -l$(lib))
##--------------------------------------
##
## Rules
##
##--------------------------------------
CCFLAG_SWITCH ?= off
CC_COMPILE =$(CC) $(GCC_CFLAGS) -c $< -o $@
CC_PRG_LINK=$(CC) $(GCC_LINK_CFLAGS) $(OUTFILE) $(ALL_OBJ) $(LIBCOVER) $(MODULE_APP_LIB) $(MODULE_PLT_LIB) $(LIB_ADD)
CC_LIB_LINK=$(AR_LINK) $(OUTFILE) $(ALL_OBJ)
COMPILE=$(CC_COMPILE)
PRG_LINK=$(CC_PRG_LINK)
LIB_LINK=$(CC_LIB_LINK)
ifeq "$(BUILD)" "exef"
LINK=$(PRG_LINK)
else
LINK=$(LIB_LINK)
endif
# Build rules
all: preproc start dir $(ALL_OBJ) #prtdebug
@echo Linking :$(OUTFILE)
ifeq "$(CCFLAG_SWITCH)" "off"
@$(LINK)
else
$(LINK)
endif
@$(POSTPROC_CMD)
@echo -e "\n================================================================================\n"
sinclude $(DEPENDS)
release : CC_COMPILE =$(CC) $(RELEASE_CFLAGS) -c $< -o $@
release : CC_PRG_LINK=$(CC) $(RELEASE_LINK_CFLAGS) $(OUTFILE) $(ALL_OBJ) $(MODULE_APP_LIB) $(MODULE_PLT_LIB) $(LIB_ADD)
release : all
##--------------------------------------
##
## Make command to use for dependencies
##
##--------------------------------------
MAKE :=make
RM :=rm
MKDIR :=mkdir
preproc:
@$(PREPROC_CMD)
start:
@echo -e "\n================================================================================\n"
@echo "[Building Project]: $(notdir $(MODULE))"
ifeq "$(CCFLAG_SWITCH)" "off"
@echo "Show Gcc Flags switch = OFF"
endif
prtdebug:
@echo "$(MODULE)-$(BUILD)[$(CFG)] build source file:" "$(SRC_FULL_PATH)"
@echo SRC_SUBDIR: $(SRC_SUBDIR)
@echo SRC_FULL_PATH : $(SRC_FULL_PATH)
@echo SRC_FILES : $(SRC_FILES)
@echo ALL_OBJ : $(ALL_OBJ)
@echo LIB:$(MODULE_PLT_LIB)
@echo PLT_LIB: $(PLT_LIB)
@echo CCFLAG_SWITCH :$(CCFLAG_SWITCH)
config: dir
dir:
@$(foreach dir,$(DIRNEED),$(MKDIR) -p $(DIRNEED) --mode=0777; )
@$(foreach dir,$(DIRBUILD),$(MKDIR) -p $(dir) --mode=0777; )
##--------------------------------------
##
## Make Rebuild and clean
##
##--------------------------------------
ifneq "$(PROJ)" ""
FRIEND_PROJ := $(shell )
endif
jumprebuild:
ifneq "$(PROJ)" ""
@cd $(FRIEND_PROJ); mak rebuild ; cd -
endif
# Rebuild this project
rebuild: jumprebuild cleanall all
# Clean this project and all dependencies
cleanall: clean
# Clean this project
clean:
@echo -e "||--------------------------------------------------------------- "
@echo -e "|| Umake clean gcc , lcov, doxygen generated and temporary files. "
@echo -e "||--------------------------------------------------------------- "
@$(RM) -rf $(OBJDIR) $(OUTFILE) $(COVER_REPORT_PATH) ./doc/doxygen.conf ./doc/html ./doc/latex ./doc/rtf $(foreach dir,$(SRC_SUBDIR),$(dir)/*~)
##--------------------------------------
##
## indent Makefile.indent
##
##--------------------------------------
include Makefile.indent
indent:
@chmod 777 $(SRC_FULL_PATH)
@echo ===================================Indent START=================================
@echo
@echo "[Indent source file ]: $(SRC_FULL_PATH)"
$(call MAKE_INDENT , $(SRC_FULL_PATH))
##--------------------------------------
##
## splint makefile.splint
##
##--------------------------------------
include Makefile.splint
SPLINT_FLAG_SWITCH ?= off
splint:
@chmod 777 $(SRC_FULL_PATH)
@echo =================================Splint START==================================
@echo
ifeq "$(SPLINT_FLAG_SWITCH)" "on"
@echo "[Splint flags ]: $(SPLINT_FLAGS)"
endif
@echo "[Lint Clean Project]: $(notdir $(MODULE))"
$(call MAKE_SPLINT, $(SRC_FULL_PATH))
##--------------------------------------
##
## doc Makefile.doxygen
##
##--------------------------------------
include Makefile.doxygen
doc:
@chmod 777 $(SRC_FULL_PATH)
@echo ==================================Doxygen START=================================
@echo
$(call MAKE_DOC, $(SRC_FULL_PATH))
##--------------------------------------
##
## backup Makefile.backup
##
##--------------------------------------
include Makefile.backup
##--------------------------------------
##
## cov Makefile.cov
##
##--------------------------------------
include Makefile.cov
##--------------------------------------
##
## usage Makefile.usage
##
##--------------------------------------
include Makefile.usage
##--------------------------------------
##
## Make dependencies
##
##--------------------------------------
$(OBJDIR)/%.d:%.c
@$(CC) $< -MM -MD -o $@
$(OBJDIR)/%.o:%.c
ifeq "$(CCFLAG_SWITCH)" "off"
@echo -e "building: $(notdir $@) \t\t\t\t please wait ..."
@$(COMPILE)
else
$(COMPILE)
endif
DEPENDS=$(COMMON_OBJ:.o=.d)
##--------------------------------------
##
## Make force
##
##--------------------------------------
FORCE:

View File

@@ -0,0 +1,199 @@
#ifndef _PSTN_CLIENT_H
#define _PSTN_CLIENT_H
#define MAX_COMMAND_LEN 2048
#define MAX_PSTN_PROCS 8
#define MSG_TIMER 6000
#define MSG_WAIT_TIMER 400
#define MSG_WAIT_LTIMER 1600
#define MAX_SLOTS 100
typedef struct msan_param_t
{
u_char server_enable;
char server_ip[16];
u_short server_port;
char user_name[16];
char password[16];
}_msan_param_t;
typedef struct pair_2_slot_param_t
{
int used;
int pair_group; /* every 64 pairs is a group */
int msan_id; /*1/2 */
int slot_id; /* paris are mapped to : slot+port */
}_pair_2_slot_param_t;
typedef struct pstn_server_param_t
{
char local_ip[16];
u_short local_port;
u_char server_enable;
char server_ip[16];
u_short server_port;
char user_name[16];
char password[16];
int krone_pair_id_in_crm;
int ss_entry_id_in_crm;
_msan_param_t msan[2];
_pair_2_slot_param_t pair_slot_info[MAX_SLOTS];
}_pstn_server_param_t;
typedef enum PORT_STATE
{
PS_NULL,
PS_CREATE,
PS_UPDATE,
PS_DELETE,
PS_BAR_OUT,
PS_UNBAR_OUT,
PS_BAR_IN,
PS_UNBAR_IN,
PS_CREATE_MSAN,
PS_DELETE_MSAN,
PS_RELEASE,
}_PORT_STATE;
typedef enum PORT_CRT_STATE
{
PCS_NULL,
PCS_INIT,
PCS_ECHO,
PCS_LOGIN,
PCS_PSSWD,
PCS_NOGUI,
PCS_QUERY_DSTN,
PCS_ENTRY,
PCS_STATION,
PCS_DSTN,
PCS_NAME,
PCS_SIGNAL,
PCS_SIP_USER,
PCS_VOIP_GRP,
PCS_TOLL,
PCS_EXTI,
PCS_ACTIVE,
PCS_LOGOUT,
PCS_LOGOUT_AGAIN,
PCS_TRANS_TO_MSAN,
// PCS_ENTRY,
// PCS_VOIP_GRP,
PCS_MAX,
}_PORT_CRT_STATE;
typedef enum PORT_UPDATE_STATE
{
PUS_NULL,
PUS_INIT,
PUS_LOGIN,
PUS_PSSWD,
PUS_NOGUI,
PUS_DSTN,
PUS_TOLL,
PUS_LOCKI,
PUS_EXTI,
PUS_ACTIVATE,
PUS_LOGOUT,
PUS_MAX,
}_PORT_UPDATE_STATE;
typedef enum PORT_DEL_STATE
{
PDS_NULL,
PDS_INIT,
PDS_LOGIN,
PDS_PSSWD,
PDS_NOGUI,
PDS_DSTN,
PDS_ENTRY,
PDS_DEL,
PDS_EXTI,
PDS_LOGOUT,
PDS_LOGOUT_AGAIN,
PDS_MAX,
}_PORT_DEL_STATE;
typedef enum MSAN_CRT_STATE
{
MCS_NULL,
MCS_INIT,
MCS_ECHO,
MCS_LOGIN,
MCS_PSSWD,
MCS_CREATE,
MCS_BRING_UP,
MCS_SAVE,
MCS_EXIT,
MCS_WAIT_EXIT,
MCS_MAX,
}_MSAN_CRT_STATE;
typedef enum MSAN_DEL_STATE
{
MDS_NULL,
MDS_INIT,
MDS_LOGIN,
MDS_PSSWD,
MDS_DELETE,
MDS_BRING_DOWN,
MDS_SAVE,
MDS_LOGOUT,
MDS_MAX,
}_MSAN_DEL_STATE;
typedef enum PSTN_PROV_CMD
{
PC_NULL,
PC_CREATE,
PC_UPDATE,
PC_DELETE,
PC_BAR,
PC_UNBAR,
}_PSTN_PROV_CMD;
typedef struct pstn_prov_t
{
int command;
long pre_id;
char isdn_number[16];
char user_name[64];
int ss_entry;
int krone_pair_id;
int msan_id;
int msan_slot_id;
int msan_slot_port_id;
int update_status;
}_pstn_prov_t;
typedef struct pstn_proc_t
{
char flag;
int id;
int tcp_port_id;
int state;
int sub_state;
int timer;
int dstn_entry;
int recv_msg_flag;
int msg_len;
char recv_msg[MAX_COMMAND_LEN];
_pstn_prov_t prov;
}_pstn_proc_t;
typedef struct pstn_procs_t
{
_pstn_proc_t procs[MAX_PSTN_PROCS];
}_pstn_procs_t;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,133 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <malloc.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUF_SIZE 1024
#define RES_LENGTH 10240
static int client_fd=0;
static int client_connect_flag = -1;
static char server_ip[16];
static short server_port;
int connect_socket(char * server,int serverPort);
int send_msg(int sockfd,char * sendBuff);
char * recv_msg(int sockfd);
int close_socket(int sockfd);
int init_socketfd()
{
int sockfd = -1;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
herror("Init socket error!");
}
return sockfd;
}
void tcp_init_client_fd()
{
client_fd = init_socketfd();
}
void tcp_connect_server(char *ip, u_short port)
{
tcp_init_client_fd();
strcpy(server_ip, ip);
server_port = port;
client_connect_flag = connect_socket(ip, port);
}
int is_tcp_connected()
{
return client_connect_flag;
}
/* * ********************************************************/
int connect_socket(char * server,int serverPort)
{
struct sockaddr_in addr;
struct hostent * phost;
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(serverPort);
addr.sin_addr.s_addr = inet_addr(server);
if(addr.sin_addr.s_addr == INADDR_NONE){
phost = (struct hostent*)gethostbyname(server);
if(phost==NULL){
herror("Init socket s_addr error!");
return -1;
}
addr.sin_addr.s_addr =((struct in_addr*)phost->h_addr)->s_addr;
}
if(connect(client_fd,(struct sockaddr*)&addr, sizeof(addr))<0)
{
// perror("Connect server fail!");
return -1; //0<><30>ʾ<EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD>-1<><31>ʾʧ<CABE><CAA7>
}
else
return 0;
}
int tcp_send_msg( u_char *sendbuf, short len)
{
int sendSize=0;
if((sendSize=send(client_fd,sendbuf,len,MSG_NOSIGNAL))<=0){
close_socket(client_fd);
herror("Send msg error!");
return -1;
}
return sendSize;
}
int tcp_recv_msg(u_char *recvbuf)
{
int recLenth=0;
if(( recLenth=recv(client_fd,recvbuf, BUF_SIZE,0))==-1 )
{
close_socket(client_fd);
return -1;
}
if( recLenth>0)
recvbuf[recLenth] = 0;
return recLenth;
}
int tcp_check_connection()
{
//if(client_connect_flag == -1)
// connect_socket(server_ip, server_port);
return client_connect_flag;
}
/**************************************************
*<2A>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD>
* **********************************************/
int close_socket(int sockfd)
{
client_connect_flag = -1;
close(sockfd);
smcli_connection_is_broken();
return 0;
}

1404
proxy_c/rest_proxy.c Normal file

File diff suppressed because it is too large Load Diff

150
proxy_c/rest_proxy.h Normal file
View File

@@ -0,0 +1,150 @@
#ifndef __REST_PROXY_H__
#define __REST_PROXY_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "restapi.h"
#include "curl_adaptor.h"
#include "rest_proxy_conf.h"
#define HTTP_OK 200
#define SERVER_PORT 4949
#define WAIT_TIMER 500 //5seconds
// #define RESTPROXY_MISISDN_LEN 24
#define MAX_THREADS 1024//256
#define THREAD_INVALID_INDEX 0xFFFF
typedef enum _STATE
{
ST_SEND_QUERY_SUBSID = 1,
ST_SEND_QUERY,
ST_SEND_TOPUP,
ST_SEND_TOPUP_SUBSCRIBID,
ST_SEND_TRANS_SUBSID_SENDER,
ST_SEND_TRANS_SUBSID_RECEIVER,
ST_SEND_TRANS,
ST_WAIT_RESTAPI_TRANS_SUBSID_SENDER,
ST_WAIT_RESTAPI_TRANS_SUBID_RECEIVER,
ST_WAIT_RESTAPI_TRANS,
ST_WAIT_RESTAPI,
ST_WAIT_RESTAPI_QUERY_SUBSID,
ST_WAIT_RESTAPI_TOPUP_SUBID,
}STATE;
typedef enum _STATISTICS
{
STAT_QUERY_REQ,
STAT_QUERY_RES,
STAT_QUERY_REST_SUBSID_REQ, /* <20><><EFBFBD><EFBFBD>subscriber id<69><64><EFBFBD><EFBFBD>ͳ<EFBFBD><CDB3> */
STAT_QUERY_REST_SUBSID_RES, /* <20><><EFBFBD><EFBFBD>subscriber id<69>ظ<EFBFBD>ͳ<EFBFBD><CDB3> */
STAT_QUERY_REST_REQ,
STAT_QUERY_REST_RES,
STAT_TRANSFER_REQ,
STAT_TRANSFER_RES,
STAT_TRANSFER_REST_SUBSID_REQ_SENDER,
STAT_TRANSFER_REST_SUBSID_RES_SENDER,
STAT_TRANSFER_REST_SUBSID_REQ_RECEIVER,
STAT_TRANSFER_REST_SUBSID_RES_RECEIVER,
STAT_TRANSFER_REST_REQ,
STAT_TRANSFER_REST_RES,
STAT_TOPUP_REQ,
STAT_TOPUP_RES,
STAT_TOPUP_REST_SUBSID_REQ, /* <20><><EFBFBD><EFBFBD>subscriber id<69><64><EFBFBD><EFBFBD>ͳ<EFBFBD><CDB3> */
STAT_TOPUP_REST_SUBSID_RES, /* <20><><EFBFBD><EFBFBD>subscriber id<69>ظ<EFBFBD>ͳ<EFBFBD><CDB3> */
STAT_TOPUP_REST_REQ,
STAT_TOPUP_REST_RES,
STAT_MAX,
}STATISTICS;
typedef struct rest_thread
{
char used;
char state;
int timer;
short ppsAppID;
short restproxyAppID;
char msisdn[RESTFUL_MSISDN_LEN];
char pin[RESTFUL_MSISDN_LEN];
char msisdn_out[RESTFUL_MSISDN_LEN];
char msisdn_in[RESTFUL_MSISDN_LEN];
u32 money;
char username[RESTFUL_USERNAME];
char password[RESTFUL_PASSWOR];
int pps_ip;
short pps_port;
SCurlAdaptor curAdaptor;
}_rest_thread;
typedef struct _s_rest_proxy_env
{
s_restproxy_conf cnf; /* rest proxy configure infor */
_rest_thread threads[MAX_THREADS]; /* handle messge from/to pps&rest */
int work_as_proxy_emulator;
int query_req_num; /* counts pps<->restproxy<->restful */
int query_res_num;
int query_rest_subscrib_req_num;
int query_rest_subscrib_res_num;
int query_rest_req_num;
int query_rest_res_num;
int trans_req_num; /* counts pps<->restproxy<->restful */
int trans_res_num;
int trans_rest_subscrib_req_num_out;
int trans_rest_subscrib_res_num_out;
int trans_rest_subscrib_req_num_in;
int trans_rest_subscrib_res_num_in;
int trans_rest_req_num;
int trans_rest_res_num;
int topup_req_num;
int topup_res_num;
int topup_rest_subscrib_req_num;
int topup_rest_subscrib_res_num;
int topup_rest_req_num;
int topup_rest_res_num;
}s_rest_proxy_env;
#define REST_PROXY_SUBSCRIBID_FLAG (g_rest_proxy_env.cnf.b_fetch_subscribid)
extern s_rest_proxy_env g_rest_proxy_env;
int rest_conf_set_emulator_flag(int flag);
int rest_proxy_init();
void rest_proxy_uninit();
int rest_proxy_fsm_main();
#ifdef __cplusplus
}
#endif
#endif /* __REST_PROXY_H__ */

132
proxy_c/rest_proxy_conf.c Normal file
View File

@@ -0,0 +1,132 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "rest_proxy_conf.h"
void rest_proxy_load_conf_ipport(const char* buffer,
const char* key,
unsigned int* ip,
char* ip_str,
unsigned short* port)
{
char buffer_ip[16] = {0};
// char buffer_port[4] = {0};
char *pos = NULL;
char *pos_ip_start = NULL;
char *pos_ip_end = NULL;
/* first address is start of the line */
pos = strstr(buffer, key);
if(NULL != pos && buffer == pos)
{
pos_ip_start = strstr(pos, "=");
if(NULL != pos_ip_start)
{
pos_ip_end = strstr(pos_ip_start + 1, ":");
if(NULL != pos_ip_end)
{
memcpy(buffer_ip, pos_ip_start + 1, (pos_ip_end - 1) - (pos_ip_start + 1) + 1);
if(ip_str)
{
strcpy(ip_str, buffer_ip);
}
*ip = inet_addr(buffer_ip);
*port = atoi(pos_ip_end + 1);
}
}
}
}
void rest_proxy_load_conf_str(const char* buffer, const char* key, char* val)
{
char *pos = NULL;
char *pos_val_start = NULL;
/* first address is start of the line */
pos = strstr(buffer, key);
if(NULL != pos && buffer == pos && buffer[strlen(key)] == '=')
{
pos_val_start = strstr(pos, "=");
/* remove \r or \n which first appear */
pos = pos_val_start;
while(pos)
{
if(*pos == '\r' || *pos == '\n' || *pos == '\0')
break;
pos++;
}
if(pos)
*pos = '\0';
if(NULL != pos_val_start)
{
strcpy(val, pos_val_start + 1);
}
}
}
void rest_proxy_load_conf_int(const char* buffer, const char* key, int* val)
{
char tmp_buf[64] = {0};
rest_proxy_load_conf_str(buffer, key, tmp_buf);
if(tmp_buf[0] != '\0')
{
*val = atoi(tmp_buf);
}
}
int rest_proxy_load_cnf(s_restproxy_conf *conf)
{
#define BUFFER_LEN 1024
FILE* fd;
char buffer[BUFFER_LEN] = {0};
if(NULL == conf->cnf_file)
{
conf->cnf_file = REST_PROXY_DEFAULT_CONF_FILE;
}
/* Create input file descriptor */
fd = fopen (conf->cnf_file, "r");
if (fd == NULL)
{
perror ("open");
return 2;
}
/* Copy process */
while((fgets(buffer, BUFFER_LEN, fd)) != NULL)
{
if(buffer[0] == '#')
continue;
rest_proxy_load_conf_ipport(buffer, "localIPPort", &conf->local_ip, NULL, &conf->local_port);
rest_proxy_load_conf_ipport(buffer, "queryIPPort", &conf->query_ip, conf->query_ip_str, &conf->query_port);
rest_proxy_load_conf_ipport(buffer, "rechargeIPPort", &conf->recharege_ip, conf->recharge_ip_str, &conf->recharge_port);
#ifdef TEST_RESTPROXY
rest_proxy_load_conf_str(buffer, "test_msisdn", conf->msisdn);
rest_proxy_load_conf_str(buffer, "test_msisdn_in", conf->msisdn_in);
rest_proxy_load_conf_str(buffer, "test_pin", conf->pin);
#endif
rest_proxy_load_conf_str(buffer, "username", conf->username);
rest_proxy_load_conf_str(buffer, "password", conf->password);
rest_proxy_load_conf_str(buffer, "subsystem", conf->subsystem);
rest_proxy_load_conf_str(buffer, "customerIP", conf->customer_ip);
rest_proxy_load_conf_str(buffer, "url_walletbalance", conf->url_fetchwalletbalance);
rest_proxy_load_conf_str(buffer, "url_rechargevoucher", conf->url_recharge);
rest_proxy_load_conf_str(buffer, "url_walletbalance_getscriberid", conf->url_fetchwalletbalance_getsubsid);
rest_proxy_load_conf_str(buffer, "url_rechargevoucher_getscriberid", conf->url_recharge_getsubsid);
rest_proxy_load_conf_int(buffer, "query_topup_getscriberid_switch", &conf->b_fetch_subscribid);
rest_proxy_load_conf_str(buffer, "url_trans_getsubsid_sender", conf->url_trans_getsubsid_sender);
rest_proxy_load_conf_str(buffer, "url_trans_getsubsid_receiver", conf->url_trans_getsubsid_receiver);
rest_proxy_load_conf_str(buffer, "url_trans", conf->url_trans);
memset(buffer, 0x00, BUFFER_LEN);
}
fclose (fd);
return 0;
}

65
proxy_c/rest_proxy_conf.h Normal file
View File

@@ -0,0 +1,65 @@
#ifndef __REST_PROXY_CONF_H__
#define __REST_PROXY_CONF_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "common.h"
#define REST_PROXY_DEFAULT_CONF_FILE "./conf/rest_proxy.conf"
typedef struct _s_restproxy_conf
{
const char* cnf_file; /* rest proxy configure name */
unsigned int local_ip; /* rest proxy host udp ip. host order */
unsigned short local_port; /* rest proxy host udp port. host order */
int as_server_fd; /* fd when rest proxy as server */
unsigned int query_ip; /* restful http ip. host order */
char query_ip_str[24];
unsigned short query_port; /* restful http port. host order */
unsigned int recharege_ip; /* restful http vourchar ip. host order */
char recharge_ip_str[24];
unsigned short recharge_port; /* restful http vourchar port. host order */
#ifdef TEST_RESTPROXY
char msisdn[24];
char msisdn_in[24];
char pin[24];
#endif
char username[24];
char password[24];
char subsystem[24];
char customer_ip[24];
int b_fetch_subscribid; /* <20><>ʶquery/recharge <20>Ƿ<EFBFBD><C7B7><EFBFBD>Ҫ<EFBFBD><D2AA>ȡsubscriberID */
char url_fetchwalletbalance_getsubsid[128];
char url_fetchwalletbalance[128];
char url_recharge_getsubsid[128];
char url_recharge[128];
char url_trans_getsubsid_sender[128];
char url_trans_getsubsid_receiver[128];
char url_trans[128];
}s_restproxy_conf;
int rest_proxy_load_cnf(s_restproxy_conf *conf);
char *rest_proxy_errcodemsg(const unsigned int errcode);
#ifdef __cplusplus
}
#endif
#endif /* __REST_PROXY_CONF_H__ */

View File

@@ -0,0 +1,85 @@
#include "rest_proxy_print.h"
#include "rest_proxy.h"
#include "log.h"
void rest_proxy_print_stat()
{
LOG_D("query: pps->restproxy->rest[%d, %d] response: pps<-restproxy<-rest[%d, %d]\n",
g_rest_proxy_env.query_req_num, g_rest_proxy_env.query_rest_req_num,
g_rest_proxy_env.query_res_num, g_rest_proxy_env.query_rest_res_num);
LOG_D(" get-subscribid: restproxy->rest[%d]\n", g_rest_proxy_env.query_rest_subscrib_req_num);
LOG_D(" restproxy<-rest[%d]\n", g_rest_proxy_env.query_rest_subscrib_res_num);
LOG_D("topup: pps->restproxy->rest[%d, %d] response: pps<-restproxy<-rest[%d, %d]\n",
g_rest_proxy_env.topup_req_num, g_rest_proxy_env.topup_rest_req_num,
g_rest_proxy_env.topup_res_num, g_rest_proxy_env.topup_rest_res_num);
LOG_D(" get-subscribid: restproxy->rest[%d]\n", g_rest_proxy_env.topup_rest_subscrib_req_num);
LOG_D(" restproxy<-rest[%d]\n", g_rest_proxy_env.topup_rest_subscrib_res_num);
LOG_D("trans: pps->restproxy->rest[%d, %d] response: pps<-restproxy<-rest[%d, %d]\n",
g_rest_proxy_env.trans_req_num, g_rest_proxy_env.trans_rest_req_num,
g_rest_proxy_env.trans_res_num, g_rest_proxy_env.trans_rest_res_num);
LOG_D(" get-subscribid_out: restproxy->rest[%d]\n", g_rest_proxy_env.trans_rest_subscrib_req_num_out);
LOG_D(" restproxy<-rest[%d]\n", g_rest_proxy_env.trans_rest_subscrib_res_num_out);
LOG_D(" get-subscribid_in: restproxy->rest[%d]\n", g_rest_proxy_env.trans_rest_subscrib_req_num_in);
LOG_D(" restproxy<-rest[%d]\n", g_rest_proxy_env.trans_rest_subscrib_res_num_in);
}
void rest_proxy_print_msg(const struct rest_msg_s* msg, int b_is_request, const char* tip)
{
return ;
switch(msg->msg_type)
{
case REST_QUERY:
if(b_is_request)
{
LOG_D("%s MsgType:%d SrcDstRef[%d, %d] MSISDN:%s\n",
tip, msg->msg_type, msg->header.src_ref, msg->header.dst_ref,
msg->msg.query.msisdn);
}
else
{
LOG_D("%s msgType:%d SrcDstRef[%d, %d] Res:%d ErrCode:%d Balance:%u MOMTExpiry[%u, %u].\n",
tip, msg->msg_type, msg->header.src_ref, msg->header.dst_ref,
msg->msg.query_res.result, msg->msg.query_res.error_code, msg->msg.query_res.balance,
msg->msg.query_res.mo_expiry, msg->msg.query_res.mt_expiry);
}
break;
case REST_TOPUP:
if(b_is_request)
{
LOG_D("%s MsgType:%d SrcDstRef[%d, %d] MSISDN:%s PIN:%s\n",
tip, msg->msg_type, msg->header.src_ref, msg->header.dst_ref,
msg->msg.topup.msisdn, msg->msg.topup.password);
}
else
{
LOG_D("%s msgType:%d SrcDstRef[%d, %d] Res:%d ErrCode:%d Balance:%u MOMTExpiry[%u, %u].\n",
tip, msg->msg_type, msg->header.src_ref, msg->header.dst_ref,
msg->msg.topup_res.result, msg->msg.topup_res.error_code, msg->msg.topup_res.balance,
msg->msg.topup_res.mo_expiry, msg->msg.topup_res.mt_expiry);
}
break;
case REST_TRANSFER:
if(b_is_request)
{
LOG_D("%s MsgType:%d SrcDstRef[%d, %d] MSISDN_OUT:%s MSISDN_IN:%s Money:%d\n",
tip, msg->msg_type, msg->header.src_ref, msg->header.dst_ref,
msg->msg.transfer.transferOutMsisdn, msg->msg.transfer.transferInMsisdn, msg->msg.transfer.amount);
}
else
{
LOG_D("%s msgType:%d SrcDstRef[%d, %d] Res:%d ErrCode:%d balance:%d\n",
tip, msg->msg_type, msg->header.src_ref, msg->header.dst_ref,
msg->msg.transfer_res.result, msg->msg.transfer_res.error_code, msg->msg.transfer_res.balance);
}
break;
default:
/* print err msg. Or else? */
LOG_D("%s err. msgType:%d\n", __FUNCTION__, msg->msg_type);
break;
}
}

View File

@@ -0,0 +1,11 @@
#ifndef __REST_PROXY_PRINT_H__
#define __REST_PROXY_PRINT_H__
#include "restapi.h"
void rest_proxy_print_stat();
void rest_proxy_print_msg(const struct rest_msg_s* msg, int b_is_request, const char* tip);
#endif /* __REST_PROXY_PRINT_H__ */

83
proxy_c/rest_proxy_stat.c Normal file
View File

@@ -0,0 +1,83 @@
#include "rest_proxy_stat.h"
#include "rest_proxy.h"
/* -------------------------------------*/
void rest_proxy_stat_count(int stat_type)
{
static int *state_count[STAT_MAX];
static char b_loaded = 0;
if(b_loaded == 0)
{
state_count[STAT_QUERY_REQ] = &g_rest_proxy_env.query_req_num;
state_count[STAT_QUERY_RES] = &g_rest_proxy_env.query_res_num;
state_count[STAT_QUERY_REST_SUBSID_REQ] = &g_rest_proxy_env.query_rest_subscrib_req_num;
state_count[STAT_QUERY_REST_SUBSID_RES] = &g_rest_proxy_env.query_rest_subscrib_res_num;
state_count[STAT_QUERY_REST_REQ] = &g_rest_proxy_env.query_rest_req_num;
state_count[STAT_QUERY_REST_RES] = &g_rest_proxy_env.query_rest_res_num;
state_count[STAT_TOPUP_REQ] = &g_rest_proxy_env.topup_req_num;
state_count[STAT_TOPUP_RES] = &g_rest_proxy_env.topup_res_num;
state_count[STAT_TOPUP_REST_SUBSID_REQ] = &g_rest_proxy_env.topup_rest_subscrib_req_num;
state_count[STAT_TOPUP_REST_SUBSID_RES] = &g_rest_proxy_env.topup_rest_subscrib_res_num;
state_count[STAT_TOPUP_REST_REQ] = &g_rest_proxy_env.topup_rest_req_num;
state_count[STAT_TOPUP_REST_RES] = &g_rest_proxy_env.topup_rest_res_num;
state_count[STAT_TRANSFER_REQ] = &g_rest_proxy_env.trans_req_num;
state_count[STAT_TRANSFER_RES] = &g_rest_proxy_env.trans_res_num;
state_count[STAT_TRANSFER_REST_SUBSID_REQ_SENDER] = &g_rest_proxy_env.trans_rest_subscrib_req_num_out;
state_count[STAT_TRANSFER_REST_SUBSID_RES_SENDER] = &g_rest_proxy_env.trans_rest_subscrib_res_num_out;
state_count[STAT_TRANSFER_REST_SUBSID_REQ_RECEIVER] = &g_rest_proxy_env.trans_rest_subscrib_req_num_in;
state_count[STAT_TRANSFER_REST_SUBSID_RES_RECEIVER] = &g_rest_proxy_env.trans_rest_subscrib_res_num_in;
state_count[STAT_TRANSFER_REST_REQ] = &g_rest_proxy_env.trans_rest_req_num;
state_count[STAT_TRANSFER_REST_RES] = &g_rest_proxy_env.trans_rest_res_num;
b_loaded = 1;
}
(*state_count[stat_type]) += 1;
#if 0
switch(stat_type)
{
case STAT_QUERY_REQ:
g_rest_proxy_env.query_req_num++;
break;
case STAT_QUERY_RES:
g_rest_proxy_env.query_res_num++;
break;
case STAT_QUERY_REST_SUBSID_REQ:
g_rest_proxy_env.query_rest_subscrib_req_num++;
break;
case STAT_QUERY_REST_SUBSID_RES:
g_rest_proxy_env.query_rest_subscrib_res_num++;
break;
case STAT_QUERY_REST_REQ:
g_rest_proxy_env.query_rest_req_num++;
break;
case STAT_QUERY_REST_RES:
g_rest_proxy_env.query_rest_res_num++;
break;
case STAT_TOPUP_REQ:
g_rest_proxy_env.topup_req_num++;
break;
case STAT_TOPUP_RES:
g_rest_proxy_env.topup_res_num++;
break;
case STAT_TOPUP_REST_SUBSID_REQ:
g_rest_proxy_env.topup_rest_subscrib_req_num++;
break;
case STAT_TOPUP_REST_SUBSID_RES:
g_rest_proxy_env.topup_rest_subscrib_res_num++;
break;
case STAT_TOPUP_REST_REQ:
g_rest_proxy_env.topup_rest_req_num++;
break;
case STAT_TOPUP_REST_RES:
g_rest_proxy_env.topup_rest_res_num++;
break;
}
#endif
}

View File

@@ -0,0 +1,9 @@
#ifndef __REST_PROXY_STAT_H__
#define __REST_PROXY_STAT_H__
#include "restapi.h"
void rest_proxy_stat_count(int stat_type);
#endif /* __REST_PROXY_STAT_H__ */

3365
proxy_c/restapi.c Normal file

File diff suppressed because it is too large Load Diff

687
proxy_c/restapi.h Normal file
View File

@@ -0,0 +1,687 @@
#ifndef _RESTAPI_H
#define _RESTAPI_H
#ifdef __cplusplus
extern "C" {
#endif
#include "common.h"
#define MAX_BODY_LEN 1024
#define REST_PROXY_PORT 4951
enum RESULT_TYPE
{
RES_SUCCEED = 0,
RES_FAILED,
};
enum OCS_RESULT_TYPE
{
OCS_RES_SUCCEED = 2001,
};
enum ERROR_CODE
{
ERR_UNKNOWN_SUBS = 1,
ERR_WRONG_PWD,
ERR_WRONG_CARD_STATUS,
ERR_WRONG_CARD_EXPIRED,
ERR_TIMEROUT,
ERR_NO_PREFIX,
};
enum REST_PROXY_MSG_TYPE
{
REST_QUERY=1,
REST_TOPUP=2,
REST_TRANSFER=3,
// for selfcare
REST_SEND_AUTHCODE_REQ=5, // <20>û<EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD>Žӿ<C5BD>
REST_SEND_AUTHCODE_RSP=6,
REST_QUERY_USERDATA_REQ=7, // <20>û<EFBFBD><C3BB><EFBFBD>Ϣ<EFBFBD><CFA2>ѯ<EFBFBD>ӿ<EFBFBD>
REST_QUERY_USERDATA_RSP=8,
REST_BUNDLE_SUBS_REQ=9, // <20>ײͶ<D7B2><CDB6><EFBFBD><EFBFBD>ӿ<EFBFBD>
REST_BUNDLE_SUBS_RSP=10,
REST_BUNDLE_USAGE_REQ=11, // <20>Ѷ<EFBFBD><D1B6><EFBFBD><EFBFBD>ײͲ<D7B2>ѯ
REST_BUNDLE_USAGE_RSP=12,
REST_RECHARGE_REQ=13, // <20><>ֵ<EFBFBD>ӿ<EFBFBD>
REST_RECHARGE_RSP=14,
REST_TRANSFER_REQ=15, // ת<>˽ӿ<CBBD>
REST_TRANSFER_RSP=16,
REST_RECHARGE_CARD_REQ=17, // <20><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>ֵ<EFBFBD>ӿ<EFBFBD>
REST_RECHARGE_CARD_RSP=18,
REST_CHECK_BALANCE_REQ=19, // <20>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>ӿ<EFBFBD>
REST_CHECK_BALANCE_RSP=20,
REST_QUERY_BALANCE_REQ=21, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD>ӿ<EFBFBD>
REST_QUERY_BALANCE_RSP=22,
REST_QUERY_RECHARGE_CARD_REQ=23, // query recharge card interface from CRM
REST_QUERY_RECHARGE_CARD_RSP=24,
REST_UPDATE_RECHARGE_CARD_REQ=25, // update recharge card interface with CRM
REST_UPDATE_RECHARGE_CARD_RSP=26,
REST_CRM_PAYMENT_REQ=27,
REST_CRM_PAYMENT_RES=28,
REST_CRM_SMS_DELIVER_REQ=29,
REST_CRM_SMS_DELIVER_RES=30,
REST_CRM_CREATE_ACCT_REQ=31,
REST_CRM_CREATE_ACCT_RES=32,
REST_CRM_QUERY_TARIFF_REQ=33,
REST_CRM_QUERY_TARIFF_RES=34,
REST_CRM_UPDATE_SUBS_REQ=35,
REST_CRM_UPDATE_SUBS_RES=36,
REST_CRM_DELETE_SUBS_REQ=37,
REST_CRM_DELETE_SUBS_RES=38,
REST_CRM_UPDATE_SESS_INFO_REQ=39,
REST_CRM_UPDATE_SESS_INFO_RES=40,
REST_CRM_UPDATE_PLAN_INFO_REQ=41,
REST_CRM_UPDATE_PLAN_INFO_RES=42,
REST_CRM_RENT_CHARGE=43,
//
};
#if 0
enum PAY_TYPE
{
PAY_TYPE_BALANCE = 1,
PAY_TYPE_PAYPAL = 2,
PAY_TYPE_VISA = 3,
PAY_TYPE_MASTER = 4,
};
enum ACCT_STATUS
{
AS_FRESH, /* fresh account, can't dial in or out,
but can recharge. */
AS_NORMAL, /* normal account */
AS_SUSPEND,
AS_BLACKLIST,
AS_RELEASED,
AS_OPRTRIAL,
//AS_MAX_USER_TYPE,
AS_EXTERNAL=10,
};
#endif
enum REST_IE_TAG
{
IE_SRC_REF=1,
IE_DST_REF,
IE_MSISDN,
IE_RESULT,
IE_ERROR_CODE,
IE_BALANCE,
IE_MO_EXPIRY,
IE_MT_EXPIRY,
IE_USERNAME,
IE_PASSWORD,
IE_MSG_CONTENT,//value=11
IE_STATUS,
IE_REMARK,
IE_GROUP_NAME,
IE_MO_VOICE_MIN,// in minute
IE_REMAIN_MO_VOICE_SEC,// in second
IE_REMAIN_MO_VOICE_MIN,// in minute
IE_MT_VOICE_MIN,// in minute
IE_REMAIN_MT_VOICE_SEC,// in second
IE_REMAIN_MT_VOICE_MIN,// in minute
IE_SMS_NUM, //value=21
IE_REMAIN_SMS_NUM,
IE_DATA_VOL_MB,// in MB
IE_REMAIN_DATA_VOL_KB,// in KB
IE_REMAIN_DATA_VOL_MB,// in MB
IE_PAY_TYPE,
IE_AMOUNT,
IE_VALID_DAYS,
IE_EXPIRY_TIME,
IE_MSISDN_TRANS_OUT,
IE_MSISDN_TRANS_IN, //value=31
IE_BALANCE_AVAILABLE,
IE_RECHARGE_AMOUNT,
IE_RECHARGE_TYPE,
IE_RECHARGE_CARD_STATUS,
IE_RECHARGE_CARD_FACE_VALUE,
IE_RECHARGE_CARD_EXPIRED_TS,
IE_RECHARGE_CARD_UPDATED_TS,
IE_CUSTOMER_ID,
IE_ACCOUNT_ID,
IE_PRODUCT_ID, //value=41
IE_PLAN_ID,
IE_RENT_CHARGE,
IE_BIRTHDAY,
IE_SMS_CONTENT,
IE_SERVICE_TYPE,
IE_TARIIFF_PREFIX,
IE_TARIFF_UNIT,
IE_TARIFF_CHARGE,
IE_TARIFF_DISCOUNT,
IE_PLAN_VALUE,//value=51
IE_PLAN_USED_VALUE,
IE_BUNDLE_ID,
IE_CAUSE,
IE_SESS_FLAG,
IE_TIMESTAMP,
IE_CONSUME_VALUE,
IE_CALLED_NUMBER,
IE_UE_IP,
IE_GW_IP,
IE_CUG_ID,
IE_VAS_CUG_STATUS,
IE_SESS_UPDATE_TIME,
IE_PLAN_VALUE_ADD_THIS_TIME,
IE_USER_CLASS,
IE_MAX_NUM,
};
typedef struct rest_header
{
u16 src_ref;
u16 dst_ref;
}_rest_header;
typedef struct rest_query
{
char msisdn[24];
}_rest_query;
typedef struct rest_query_res
{
u8 optional_flag;
u8 result;
u8 error_code;
u32 balance;
u32 mo_expiry;
u32 mt_expiry;
}_rest_query_res;
typedef struct rest_topup
{
u8 optional_flag; /* optional=1 ,account_id is presented */
char msisdn[24];
char username[24];
char password[24];
u32 balance;
long account_id;
}_rest_topup;
typedef struct rest_topup_res
{
u8 optional_flag;
u8 result;
u8 error_code;
u32 balance;
u32 mo_expiry;
u32 mt_expiry;
}_rest_topup_res;
// for selfcare =============================
typedef struct rest_send_authcode
{
char msisdn[24];
char sms_content[MAX_BODY_LEN];
}_rest_send_authcode;
typedef struct rest_send_authcode_res
{
u8 optional_flag;
u8 result;
u32 error_code;
}_rest_send_authcode_res;
typedef struct rest_query_user_data
{
char msisdn[24];
}_rest_query_user_data;
typedef struct rest_query_user_data_res
{
u8 optional_flag;
u8 result;
u32 error_code;
char msisdn[24];
u8 status;// use ACCT_STATUS
char remark[64];
char usrGrpName[32];// usr data==>cos id==>cos title
u32 balance;
u64 mo_expiry;
u32 mo_voc_min;// in Min
u32 remain_mo_voc_min;
u32 mt_voc_min;// in Min
u32 remain_mt_voc_min;
u32 total_sms_num;// reserved, set to 0 or do not send
u32 remain_sms_num;
u32 total_data_vol;// reserved, set to 0 or do not send
u32 remain_data_vol;
}_rest_query_user_data_res;
typedef struct rest_bundle_subs
{
char msisdn[24];
u8 payType;// 1: balance; 2: paypal; 3: visa; 4: master, use PAY_TYPE
u32 charge;// Conditional, mandatory if balance
u32 moVoiceMinute;
u32 mtVoiceMinute;
u32 dataVolume;// MB
u32 smsNum;
u32 validDays;
}_rest_bundle_subs;
typedef struct rest_bundle_subs_res
{
u8 optional_flag;
u8 result;
u32 error_code;
}_rest_bundle_subs_res;
typedef struct rest_bundle_usage
{
char msisdn[24];
}_rest_bundle_usage;
typedef struct rest_bundle_usage_res
{
u8 optional_flag;
u8 result;
u32 error_code;
u32 moVoiceInSec;// remained mo voice in second
u32 mtVoiceInSec;// remained mt voice in second
u32 dataVolInKB;// remained data volume in KB
u32 smsNum;// remained sms
u64 expiredTime;// expired time
}_rest_bundle_usage_res;
typedef struct rest_recharge
{
char msisdn[24];
u32 amount;// mandatory, add to balance
u8 op_type; //0=charge, 1=recharge
u16 valid_days;
}_rest_recharge;
typedef struct rest_recharge_res
{
u8 optional_flag;
u8 result;
u32 error_code;
u8 status;
u32 balance;// current balance
u64 expiredTime;// expired time
}_rest_recharge_res;
typedef struct rest_transfer
{
char transferOutMsisdn[24];
char transferInMsisdn[24];
u32 amount;// mandatory
}_rest_transfer;
typedef struct rest_transfer_res
{
u8 optional_flag;
u8 result;
u32 error_code;
u32 balance;
}_rest_transfer_res;
typedef struct rest_recharge_card
{
char msisdn[24];
char cardPwd[32];// rechare card password
}_rest_recharge_card;
typedef struct rest_recharge_card_res
{
u8 optional_flag;
u8 result;
u32 error_code;
u32 rechargeAmount;// mandatory, add to balance
u32 balance;// current balance
u64 expiredTime;// expired time
}_rest_recharge_card_res;
typedef struct rest_check_balance
{
char msisdn[24];
u32 amount;// mandatory
}_rest_check_balance;
typedef struct rest_check_balance_res
{
u8 optional_flag;
u8 result;
u32 error_code;
u8 available;// 0: enough balance; 1: else
}_rest_check_balance_res;
typedef struct rest_query_balance
{
char msisdn[24];
}_rest_query_balance;
typedef struct rest_query_balance_res
{
u8 optional_flag;
u8 result;
u32 error_code;
u8 status;
u32 balance;// current balance
u32 mo_expiry;
}_rest_query_balance_res;
typedef struct rest_query_recharge_card
{
char cardPwd[32];// rechare card password
}_rest_query_recharge_card;
typedef struct rest_query_recharge_card_res
{
u8 optional_flag;
u8 result; //0=succeed, 1=failed
u32 error_code;//1=no such instance
u32 status;//0=fresh, 1= used
u32 face_value;
u32 expiredTime;// expired time
}_rest_query_recharge_card_res;
typedef struct rest_update_recharge_card
{
char cardPwd[32];// rechare card password
u8 status;
u64 updatedTime;
char msisdn[32];
}_rest_update_recharge_card;
typedef struct rest_update_recharge_card_res
{
u8 optional_flag;
u8 result;
u32 error_code;
}_rest_update_recharge_card_res;
typedef struct rest_payment
{
char msisdn[24];
u32 amount;// mandatory, add to balance
}_rest_payment;
typedef struct rest_payment_res
{
u8 optional_flag;
u8 result;
u32 error_code;
u32 balance;// current balance
u64 expiredTime;// expired time
}_rest_payment_res;
typedef struct rest_sms_deliver_req
{
char msisdn[24];
u16 sms_len;
char sms_content[MAX_BODY_LEN];
}_rest_sms_deliver_req;
typedef struct rest_sms_deliver_res
{
u8 optional_flag;
u8 result;
u32 error_code;
}_rest_sms_deliver_res;
typedef struct rest_create_acct_req
{
char msisdn[24];
u32 customer_id;
u32 account_id;
u32 product_id;
u32 plan_id; /* basic plan */
u8 user_class;
u32 balance;
u32 expiry_date;
u32 rent_charge;
u32 birthday;
u32 cug_id;
}_rest_create_acct_req;
typedef struct rest_create_acct_res
{
u8 optional_flag;
u8 result;
u32 error_code;
}_rest_create_acct_res;
typedef struct rest_query_tariff_req
{
char msisdn[24];
u8 service_type; /*0=mo call, 1=mt call, 2=sms, 3=data */
char called_number[24];
}_rest_query_tariff_req;
typedef struct rest_query_tariff_res
{
u8 optional_flag;
u8 result;
u32 error_code;
char prefix[24];
u32 unit_time;
u32 unit_charge;
u32 discount;
u32 plan_id;
u32 bundle_plan_id;
u64 total_plan_value;
u64 used_plan_value;
}_rest_query_tariff_res;
typedef struct rest_update_subs_req
{
u32 optional_flag;
char msisdn[24];
u32 account_id;
u8 status; /*falg=1*/
u32 balance;
u32 balance_expiry_date;
u32 basic_plan_id;
u32 basic_plan_rent;
u8 vas_cug_status;
}_rest_update_subs_req;
typedef struct rest_update_subs_res
{
u8 optional_flag;
u8 result;
u32 error_code;
}_rest_update_subs_res;
typedef struct rest_delete_subs_req
{
char msisdn[24];
u8 account_type;
u32 account_id;
u8 cause;
}_rest_delete_subs_req;
typedef struct rest_delete_subs_res
{
u8 optional_flag;
u8 result;
u32 error_code;
}_rest_delete_subs_res;
typedef struct rest_update_sess_info_req
{
u32 optional_flag; /*bit 0=called, 1= ue_ip, 2=pgw ip */
char msisdn[24];
u8 first_sess; /*if 1 then clear all session in database */
u8 service_type; /*0=mo call, 1=mt call, 2=mo sms, 3= data*/
u32 start_time;
u32 consumed_value; /*duration of call, bytes of data */
char called[24]; /*for call/sms */
u32 ue_ip;
u32 gw_ip;
}_rest_update_sess_info_req;
typedef struct rest_update_plan_info_req
{
u32 optional_flag; /*bit 0=called, 1= ue_ip, 2=pgw ip */
char msisdn[24];
u8 service_type; /*0=mo call, 1=mt call, 2=mo sms, 3= data*/
u32 account_id;
u32 plan_id;
u32 bundle_id;
u64 plan_total_value;
u64 plan_used_value;
u32 sess_update_times;
u64 this_time_add_value;
}_rest_update_plan_info_req;
typedef struct rest_rent_charge_req
{
u32 optional_flag;
char msisdn[24];
u32 balance;
u32 rent_charge;
}_rest_rent_charge_req;
//======================================
typedef struct rest_msg_s
{
u8 msg_type;
_rest_header header;
union
{
//OCS->CRM
_rest_query query;
_rest_query_res query_res;
_rest_topup topup;
_rest_topup_res topup_res;
// for selfcare
_rest_send_authcode send_authcode;
_rest_send_authcode_res send_authcode_res;
_rest_query_user_data query_user_data;
_rest_query_user_data_res query_user_data_res;
_rest_bundle_subs bundle_subs;
_rest_bundle_subs_res bundle_subs_res;
_rest_bundle_usage bundle_usage;
_rest_bundle_usage_res bundle_usage_res;
_rest_recharge recharge;
_rest_recharge_res recharge_res;
_rest_transfer transfer;
_rest_transfer_res transfer_res;
_rest_recharge_card recharge_card;
_rest_recharge_card_res recharge_card_res;
_rest_check_balance check_balance;
_rest_check_balance_res check_balance_res;
_rest_query_balance query_balance;
_rest_query_balance_res query_balance_res;
_rest_query_recharge_card query_recharge_card;
_rest_query_recharge_card_res query_recharge_card_res;
_rest_update_recharge_card update_recharge_card;
_rest_update_recharge_card_res update_recharge_card_res;
_rest_payment payment;
_rest_payment_res payment_res;
_rest_sms_deliver_req sms_deliver;
_rest_sms_deliver_res sms_deliver_res;
_rest_create_acct_req create_acct;
_rest_create_acct_res create_acct_res;
_rest_query_tariff_req query_tariff;
_rest_query_tariff_res query_tariff_res;
_rest_update_subs_req update_subs;
_rest_update_subs_res update_subs_res;
_rest_delete_subs_req delete_subs;
_rest_delete_subs_res delete_subs_res;
_rest_update_sess_info_req update_sess_info;
_rest_update_plan_info_req update_plan_info;
_rest_rent_charge_req rent_charge;
//
}msg;
}_rest_msg_s;
int encode_rest_query(_rest_msg_s *ptr, u8 *buf);
int encode_rest_query_res(_rest_msg_s *ptr, u8 *buf);
int encode_rest_topup(_rest_msg_s *ptr, u8 *buf);
int encode_rest_topup_res(_rest_msg_s *ptr, u8 *buf);
int decode_rest_api_msg(u8 *buf, int len, _rest_msg_s *ptr);
// for selfcare======================================
int encode_rest(_rest_msg_s *ptr, u8 *buf);
int decode_rest_api_msg(u8 *buf, int len, _rest_msg_s *ptr);
int encode_rest_send_authcode(_rest_msg_s *ptr, u8 *buf);
int encode_rest_send_authcode_res(_rest_msg_s *ptr, u8 *buf);
int encode_rest_query_user_data(_rest_msg_s *ptr, u8 *buf);
int encode_rest_query_user_data_res(_rest_msg_s *ptr, u8 *buf);
int encode_rest_bundle_subs(_rest_msg_s *ptr, u8 *buf);
int encode_rest_bundle_subs_res(_rest_msg_s *ptr, u8 *buf);
int encode_rest_bundle_usage(_rest_msg_s *ptr, u8 *buf);
int encode_rest_bundle_usage_res(_rest_msg_s *ptr, u8 *buf);
int encode_rest_recharge(_rest_msg_s *ptr, u8 *buf);
int encode_rest_recharge_res(_rest_msg_s *ptr, u8 *buf);
int encode_rest_transfer(_rest_msg_s *ptr, u8 *buf);
int encode_rest_transfer_res(_rest_msg_s *ptr, u8 *buf);
int encode_rest_recharge_card(_rest_msg_s *ptr, u8 *buf);
int encode_rest_recharge_card_res(_rest_msg_s *ptr, u8 *buf);
int encode_rest_check_balance(_rest_msg_s *ptr, u8 *buf);
int encode_rest_check_balance_res(_rest_msg_s *ptr, u8 *buf);
int encode_rest_query_balance(_rest_msg_s *ptr, u8 *buf);
int encode_rest_query_balance_res(_rest_msg_s *ptr, u8 *buf);
//
#ifdef __cplusplus
}
#endif
#endif

229
proxy_c/selfcare_config.c Normal file
View File

@@ -0,0 +1,229 @@
#include "selfcare_config.h"
#include "common.h"
#include "log.h"
#define SELFCARE_PROXY_DEFAULT_CONF_FILE "./conf/selfcare_proxy.conf"
#define MAX_ERRCODE (5000)
#define MAX_MESSAGE_LEN (100)
static char g_errcode_map_message[MAX_ERRCODE][MAX_MESSAGE_LEN];
static selfcare_config_s g_selfcare_conf;
void _selfcare_config_str(const char* buffer, const char* key, char* val)
{
char *pos = NULL;
char *pos_val_start = NULL;
/* first address is start of the line */
pos = strstr(buffer, key);
if(NULL != pos && buffer == pos)
{
pos_val_start = strstr(pos, "=");
/* remove \r or \n which first appear */
pos = pos_val_start;
while(pos)
{
if(*pos == '\r' || *pos == '\n' || *pos == '\0')
break;
pos++;
}
if(pos)
*pos = '\0';
if(NULL != pos_val_start)
{
strcpy(val, pos_val_start + 1);
}
}
}
void _selfcare_config_i16(const char* buffer, const char* key, short unsigned int* val)
{
char *pos = NULL;
char *pos_val_start = NULL;
/* first address is start of the line */
pos = strstr(buffer, key);
if(NULL != pos && buffer == pos)
{
pos_val_start = strstr(pos, "=");
/* remove \r or \n which first appear */
pos = pos_val_start;
while(pos)
{
if(*pos == '\r' || *pos == '\n' || *pos == '\0')
break;
pos++;
}
if(pos)
*pos = '\0';
if(NULL != pos_val_start)
{
*val = atoi( pos_val_start + 1);
}
}
}
void _selfcare_config_i32(const char* buffer, const char* key, unsigned int* val)
{
char *pos = NULL;
char *pos_val_start = NULL;
/* first address is start of the line */
pos = strstr(buffer, key);
if(NULL != pos && buffer == pos)
{
pos_val_start = strstr(pos, "=");
/* remove \r or \n which first appear */
pos = pos_val_start;
while(pos)
{
if(*pos == '\r' || *pos == '\n' || *pos == '\0')
break;
pos++;
}
if(pos)
*pos = '\0';
if(NULL != pos_val_start)
{
*val = atoi( pos_val_start + 1);
}
}
}
static void _selfcare_config_ipport(const char* buffer,
const char* key,
unsigned int* ip,
char* ip_str,
unsigned short* port)
{
char buffer_ip[16] = {0};
// char buffer_port[4] = {0};
char *pos = NULL;
char *pos_ip_start = NULL;
char *pos_ip_end = NULL;
/* first address is start of the line */
pos = strstr(buffer, key);
if(NULL != pos && buffer == pos)
{
pos_ip_start = strstr(pos, "=");
if(NULL != pos_ip_start)
{
pos_ip_end = strstr(pos_ip_start + 1, ":");
if(NULL != pos_ip_end)
{
memcpy(buffer_ip, pos_ip_start + 1, (pos_ip_end - 1) - (pos_ip_start + 1) + 1);
if(ip_str)
{
strcpy(ip_str, buffer_ip);
}
*ip = inet_addr(buffer_ip);
*port = atoi(pos_ip_end + 1);
}
}
}
}
void _selfcare_config_errcodemapmsg(const char* buffer)
{
char buf_map[MAX_MESSAGE_LEN] = {0};
_selfcare_config_str(buffer, "errcode_map_message", buf_map);
if(buf_map[0] != '\0')
{
char *p_1 = strstr(buf_map, "[");
char *p_2 = strstr(buf_map, ",");
char *p_3 = strstr(buf_map, "]");
if(p_1 && p_2 && p_3)
{
char errcode_str[MAX_MESSAGE_LEN] = {0};
memcpy(errcode_str, p_1 + 1, p_2 - (p_1 + 1) );
char errmsg_str[MAX_MESSAGE_LEN] = {0};
memcpy(errmsg_str, p_2 + 1, p_3 - (p_2 + 1) );
int err_code = atoi(errcode_str);
strcpy(g_errcode_map_message[err_code%MAX_ERRCODE], errmsg_str);
LOG_D("[rest_proxy] load errorcodemap. [%d,%s]\n", err_code, errmsg_str);
}
}
}
char *rest_proxy_errcodemsg(const unsigned int errcode)
{
if(g_errcode_map_message[errcode%MAX_ERRCODE][0] == '\0')
{
return "unkow";
}
return g_errcode_map_message[errcode%MAX_ERRCODE];
}
int selfcare_config_init(const char *cnf_file)
{
#define BUFFER_LEN 1024
FILE* fd;
char buffer[BUFFER_LEN] = {0};
if(cnf_file == NULL)
{
g_selfcare_conf.cnf_file = SELFCARE_PROXY_DEFAULT_CONF_FILE;
}
/* Create input file descriptor */
fd = fopen (g_selfcare_conf.cnf_file, "r");
if (fd == NULL)
{
perror ("open");
return 2;
}
/* Copy process */
while((fgets(buffer, BUFFER_LEN, fd)) != NULL)
{
if(buffer[0] == '#')
continue;
_selfcare_config_ipport(buffer, "udp_localIPPort", &g_selfcare_conf.udp_local_ip, NULL, &g_selfcare_conf.udp_local_port);
_selfcare_config_ipport(buffer, "udp_ocsIPPort", &g_selfcare_conf.udp_ocs_ip, NULL, &g_selfcare_conf.udp_ocs_port);
_selfcare_config_i16(buffer, "http_localPort", &g_selfcare_conf.http_local_port);
_selfcare_config_i32(buffer, "sms_notify_usage_75", &g_selfcare_conf.sms_notify_type);
_selfcare_config_str(buffer, "authcode_url", g_selfcare_conf.authcode_url);
_selfcare_config_str(buffer, "query_userdata_url", g_selfcare_conf.query_userdata_url);
_selfcare_config_str(buffer, "bundle_subs_url", g_selfcare_conf.bundle_subs_url);
_selfcare_config_str(buffer, "bundle_usage_url", g_selfcare_conf.bundle_usage_url);
_selfcare_config_str(buffer, "recharge_url", g_selfcare_conf.recharge_url);
_selfcare_config_str(buffer, "transfer_url", g_selfcare_conf.transfer_url);
_selfcare_config_str(buffer, "recharge_card_url", g_selfcare_conf.recharge_card_url);
_selfcare_config_str(buffer, "check_balance_url", g_selfcare_conf.check_balance_url);
_selfcare_config_str(buffer, "query_balane_url", g_selfcare_conf.query_balane_url);
_selfcare_config_str(buffer, "payment_url", g_selfcare_conf.payment_url);
_selfcare_config_str(buffer, "sms_deliver_url", g_selfcare_conf.sms_deliver_url);
_selfcare_config_str(buffer, "create_account_url", g_selfcare_conf.create_account_url);
_selfcare_config_str(buffer, "update_subs_url", g_selfcare_conf.update_subs_url);
_selfcare_config_str(buffer, "delete_subs_url", g_selfcare_conf.delete_subs_url);
_selfcare_config_errcodemapmsg(buffer);
memset(buffer, 0x00, BUFFER_LEN);
}
fclose (fd);
return 0;
}
int selfcare_config_uninit(void)
{
return 0;
}
selfcare_config_s* selfcare_config_get(void)
{
return &g_selfcare_conf;
}

54
proxy_c/selfcare_config.h Normal file
View File

@@ -0,0 +1,54 @@
#ifndef __SELFCARE_CONFIG_H__
#define __SELFCARE_CONFIG_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _selfcare_config_s
{
const char *cnf_file;
unsigned int udp_local_ip;
unsigned short int udp_local_port;
unsigned int udp_ocs_ip;
unsigned short int udp_ocs_port;
unsigned int http_local_ip;
unsigned short int http_local_port;
unsigned int sms_notify_type;
char authcode_url[128];
char query_userdata_url[128];
char bundle_subs_url[128];
char bundle_usage_url[128];
char recharge_url[128];
char transfer_url[128];
char recharge_card_url[128];
char check_balance_url[128];
char query_balane_url[128];
char payment_url[128];
char sms_deliver_url[128];
char create_account_url[128];
char update_subs_url[128];
char delete_subs_url[128];
}selfcare_config_s;
int selfcare_config_init(const char *cnf_file);
int selfcare_config_uninit(void);
selfcare_config_s* selfcare_config_get(void);
#ifdef __cplusplus
}
#endif
#endif /* __SELFCARE_CONFIG_H__ */

852
proxy_c/selfcare_endecode.c Normal file
View File

@@ -0,0 +1,852 @@
#include "selfcare_endecode.h"
#include "selfcare_httpsrv.h"
#include "json.h"
#include "restapi.h"
#include "log.h"
extern ulong TransStrTimeToSecond(const char *str_time);//YYYY-MM-DD HH:MM:YY
extern int dba_crm_get_product_rent(int from, int package_id);
char* _find_name(json_t *node, const char* name)
{
if(node == NULL || node->type != JSON_STRING)
{
return NULL;
}
if(strcmp(node->text, name) == 0)
{
if(node->child)
{
LOG_D("[httpserv] name[%s] val[%s]\n", name, node->child->text);
return node->child->text;
}
}
return _find_name(node->next, name);
}
int _selfcare_set_str(json_t *root, char *buf, const char *name)
{
int ret = 0;
char *val = _find_name(root->child, name);
if(val)
{
strcpy(buf, val);
ret = 1;
}
return ret;
}
void _selfcare_set_u8(json_t *root, u8 *val, const char *name)
{
char *tmp = _find_name(root->child, name);
if(tmp)
{
*val = atoi(tmp);
}
}
void _selfcare_set_u16(json_t *root, u16 *val, const char *name)
{
char *tmp = _find_name(root->child, name);
if(tmp)
{
*val = atoi(tmp);
}
}
int _selfcare_set_u32(json_t *root, u32 *val, const char *name)
{
char *tmp = _find_name(root->child, name);
if(tmp)
{
*val = atol(tmp);
return 1;
}
else
return 0;
}
void _print_name(json_t *node, const char* name)
{
char *val = _find_name(node->child, name);
if(val != NULL)
{
LOG_D("[httpserv] name[%s] val[%s]\n", name, val);
}
else
{
LOG_E("[httpserv] name[%s] not found\n", name);
}
}
static int _selfcare_decode_authcode(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_SEND_AUTHCODE_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.send_authcode.msisdn, "telNumber");
_selfcare_set_str(root, msg->msg.send_authcode.sms_content, "content");
}
LOG_D("[httpserv] decode autchcode suc\n");
}
else
{
LOG_E("[httpserv] decode autchcode fail\n");
}
return 0;
}
static int _selfcare_decode_query_user_data(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_QUERY_USERDATA_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.query_user_data.msisdn, "telNumber");
}
LOG_D("[httpserv] decode query_user_data suc\n");
}
else
{
LOG_E("[httpserv] decode query_user_data fail\n");
}
return 0;
}
static int _selfcare_decode_bundle_subs(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_BUNDLE_SUBS_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.bundle_subs.msisdn, "telNumber");
_selfcare_set_u8(root, &msg->msg.bundle_subs.payType, "payType");
_selfcare_set_u32(root, &msg->msg.bundle_subs.charge, "chargedAmount");
_selfcare_set_u32(root, &msg->msg.bundle_subs.moVoiceMinute, "moVoiceMinute");
_selfcare_set_u32(root, &msg->msg.bundle_subs.mtVoiceMinute, "mtVoiceMinute");
_selfcare_set_u32(root, &msg->msg.bundle_subs.dataVolume, "dataVolume");
_selfcare_set_u32(root, &msg->msg.bundle_subs.smsNum, "smsVolume");
_selfcare_set_u32(root, &msg->msg.bundle_subs.validDays, "validPeriod");
}
LOG_D("[httpserv] decode bundle_subs suc\n");
}
else
{
LOG_E("[httpserv] decode bundle_subs fail\n");
}
return 0;
}
static int _selfcare_decode_bundle_usage(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_BUNDLE_USAGE_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.bundle_usage.msisdn, "telNumber");
}
LOG_D("[httpserv] decode bundle_usage suc\n");
}
else
{
LOG_E("[httpserv] decode bundle_usage fail\n");
}
return 0;
}
static int _selfcare_decode_recharge(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_RECHARGE_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.recharge.msisdn, "telNumber");
_selfcare_set_u32(root, &msg->msg.recharge.amount, "amount");
_selfcare_set_u8(root, &msg->msg.recharge.op_type, "opType");
_selfcare_set_u16(root, &msg->msg.recharge.valid_days, "validyDays");
if(msg->msg.recharge.op_type == 1) //recharge with cash
{
//if(msg->msg.recharge.valid_days<=1)
// msg->msg.recharge.valid_days = 7;
}
}
LOG_D("[httpserv] decode recharge suc\n");
}
else
{
LOG_E("[httpserv] decode recharge fail\n");
}
return 0;
}
static int _selfcare_decode_transfer(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_TRANSFER_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.transfer.transferOutMsisdn, "transferOut");
_selfcare_set_str(root, msg->msg.transfer.transferInMsisdn, "transferIn");
_selfcare_set_u32(root, &msg->msg.transfer.amount, "amount");
}
LOG_D("[httpserv] decode transfer suc\n");
}
else
{
LOG_E("[httpserv] decode transfer fail\n");
}
return 0;
}
static int _selfcare_decode_recharge_card(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_RECHARGE_CARD_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.recharge_card.msisdn, "telNumber");
_selfcare_set_str(root, msg->msg.recharge_card.cardPwd, "cardPwd");
//_selfcare_set_u32(root, &msg->msg.recharge_card.amount, "rechargeAmount");
}
LOG_D("[httpserv] decode recharge_card suc\n");
}
else
{
LOG_E("[httpserv] decode recharge_card fail\n");
}
return 0;
}
static int _selfcare_decode_check_balance(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_CHECK_BALANCE_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.check_balance.msisdn, "telNumber");
_selfcare_set_u32(root, &msg->msg.check_balance.amount, "amount");
}
LOG_D("[httpserv] decode check_balance suc\n");
}
else
{
LOG_E("[httpserv] decode check_balance fail\n");
}
return 0;
}
static int _selfcare_decode_query_balance(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_QUERY_BALANCE_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.query_balance.msisdn, "telNumber");
}
LOG_D("[httpserv] decode query_balance suc\n");
}
else
{
LOG_E("[httpserv] decode query_balance fail\n");
}
return 0;
}
static int _selfcare_decode_crm_payment(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_CRM_PAYMENT_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.recharge.msisdn, "telNumber");
_selfcare_set_u32(root, &msg->msg.recharge.amount, "amount");
}
LOG_D("[httpserv] decode crm payment suc\n");
}
else
{
LOG_E("[httpserv] decode crm payment fail\n");
}
return 0;
}
static int _selfcare_decode_sms_deliver(const char *buff, const int len, _rest_msg_s *msg)
{
msg->msg_type = REST_CRM_SMS_DELIVER_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.sms_deliver.msisdn, "telNumber");
_selfcare_set_str(root, (char *)&msg->msg.sms_deliver.sms_content, "content");
}
LOG_D("[httpserv] decode sms_dliver suc\n");
}
else
{
LOG_E("[httpserv] decode sms_dliver fail\n");
}
return 0;
}
static int _selfcare_decode_create_account(const char *buff, const int len, _rest_msg_s *msg)
{
char buf[128];
msg->msg_type = REST_CRM_CREATE_ACCT_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.create_acct.msisdn, "serviceNbr");
_selfcare_set_u32(root, &msg->msg.create_acct.customer_id, "custId");
_selfcare_set_u32(root, &msg->msg.create_acct.account_id, "accountId");
_selfcare_set_u32(root, &msg->msg.create_acct.product_id, "productInstId");
_selfcare_set_u32(root, &msg->msg.create_acct.plan_id, "packageId");
_selfcare_set_u32(root, &msg->msg.create_acct.balance, "balance");
_selfcare_set_str(root, buf, "balanceExpDate");
msg->msg.create_acct.expiry_date = TransStrTimeToSecond(buf);
_selfcare_set_str(root, buf, "birthday");
msg->msg.create_acct.birthday = TransStrTimeToSecond(buf);
msg->msg.create_acct.rent_charge = dba_crm_get_product_rent(1, msg->msg.create_acct.plan_id);
}
LOG_D("[httpserv] decode create_account suc\n");
}
else
{
LOG_E("[httpserv] decode create_account fail\n");
}
return 0;
}
typedef enum CRM_STATUS
{
CRM_STATUS_FRESH = 1000,
CRM_STATUS_NORMAL = 1001,
CRM_STATUS_SUSPEND = 1205,
CRM_STATUS_DISABLE = 1202,
CRM_STATUS_BLACKLIST = 1601,
CRM_STATUS_RECYCLE = 1101,
}_CRM_STATUS;
typedef enum OCS_STATUS
{
OCS_STATUS_FRESH = 0,
OCS_STATUS_NORMAL = 1,
OCS_STATUS_SUSPEND = 2,
OCS_STATUS_BLACKLIST = 3,
OCS_STATUS_RECYCLE = 4,
OCS_STATUS_OPRTRAIL= 5,
OCS_STATUS_DISABLE = 6,
}_OCS_STATUS;
int crm_subs_status(u32 crm_status)
{
int status = CRM_STATUS_NORMAL;
switch(crm_status)
{
case CRM_STATUS_FRESH:
status = OCS_STATUS_FRESH;
break;
case CRM_STATUS_NORMAL:
status = OCS_STATUS_NORMAL;
break;
case CRM_STATUS_SUSPEND:
status = OCS_STATUS_SUSPEND;
break;
case CRM_STATUS_DISABLE:
status = OCS_STATUS_DISABLE;
break;
case CRM_STATUS_BLACKLIST:
status = OCS_STATUS_BLACKLIST;
break;
case CRM_STATUS_RECYCLE:
status = OCS_STATUS_RECYCLE;
break;
default:
status = OCS_STATUS_SUSPEND;
break;
}
return status;
}
static int _selfcare_decode_update_subs(const char *buff, const int len, _rest_msg_s *msg)
{
char buf[128];
u32 value;
msg->msg_type = REST_CRM_UPDATE_SUBS_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.update_subs.msisdn, "telNumber");
if(_selfcare_set_u32(root, &value, "status"))
{
msg->msg.update_subs.status = value; //crm_subs_status(value);
msg->msg.update_subs.optional_flag |= 0x01;
}
if(_selfcare_set_u32(root, &msg->msg.update_subs.balance, "balance"))
{
msg->msg.update_subs.optional_flag |= 0x02;
}
if(_selfcare_set_str(root, buf, "balanceExpDate"))
{
msg->msg.update_subs.balance_expiry_date = TransStrTimeToSecond(buf);
msg->msg.update_subs.optional_flag |= 0x04;
}
if(_selfcare_set_u32(root, &msg->msg.update_subs.basic_plan_id, "packageId"))
{
int rent;
rent = dba_crm_get_product_rent(1, msg->msg.update_subs.basic_plan_id);
msg->msg.update_subs.optional_flag |= 0x08;
msg->msg.update_subs.basic_plan_rent = rent;
msg->msg.update_subs.optional_flag |= 0x10;
}
}
LOG_D("[httpserv] _selfcare_decode_update_subs suc\n");
}
else
{
LOG_E("[httpserv] _selfcare_decode_update_subs fail\n");
}
return 0;
}
static int _selfcare_decode_delete_subs(const char *buff, const int len, _rest_msg_s *msg)
{
//char buf[128];
u32 cause=0;
msg->msg_type = REST_CRM_DELETE_SUBS_REQ;
json_t *root = NULL;
if(json_parse_document(&root, buff) == JSON_OK)
{
if(root != NULL && root->type == JSON_OBJECT)
{
LOG_D("\n");
_selfcare_set_str(root, msg->msg.delete_subs.msisdn, "telNumber");
_selfcare_set_u8(root, &msg->msg.delete_subs.account_type, "acctType");
_selfcare_set_u32(root, &msg->msg.delete_subs.account_id, "acctID");
//_selfcare_set_u32(root, &cause, "reason");
msg->msg.delete_subs.cause = cause;
}
LOG_D("[httpserv] _selfcare_decode_deletee_subs suc\n");
}
else
{
LOG_E("[httpserv] _selfcare_decode_deletee_subs fail\n");
}
return 0;
}
int selfcare_decode(struct evhttp_request *req,
const SELFCARE_URL_E req_type,
_rest_msg_s *msg)
{
typedef struct
{
int (*handle)(const char *buff, const int len, _rest_msg_s *msg);
}ss;
ss hd[SELFCARE_TYPE_MAX];
hd[SELFCARE_AUTHCODE].handle = _selfcare_decode_authcode;
hd[SELFCARE_QUERY_USERDATA].handle =_selfcare_decode_query_user_data;
hd[SELFCARE_BUNDLE_SUBS].handle = _selfcare_decode_bundle_subs;
hd[SELFCARE_BUNDLE_USAGE].handle = _selfcare_decode_bundle_usage;
hd[SELFCARE_RECHARGE].handle = _selfcare_decode_recharge;
hd[SELFCARE_TRANSFER].handle = _selfcare_decode_transfer;
hd[SELFCARE_RECHARGE_CARD].handle = _selfcare_decode_recharge_card;
hd[SELFCARE_CHECK_BALANCE].handle = _selfcare_decode_check_balance;
hd[SELFCARE_QUERY_BALANCE].handle = _selfcare_decode_query_balance;
hd[SELFCARE_CRM_PAYMENT].handle = _selfcare_decode_crm_payment;
hd[SELFCARE_SMS_DELIVER].handle = _selfcare_decode_sms_deliver;
hd[SELFCARE_CREATE_ACCT].handle = _selfcare_decode_create_account;
hd[SELFCARE_UPDATE_SUBS].handle = _selfcare_decode_update_subs;
hd[SELFCARE_DELETE_SUBS].handle = _selfcare_decode_delete_subs;
struct evkeyvalq *headers;
struct evkeyval *header;
struct evbuffer *buf;
headers = evhttp_request_get_input_headers(req);
for (header = headers->tqh_first; header; header = header->next.tqe_next)
{
LOG_D(" %s: %s\n", header->key, header->value);
}
buf = evhttp_request_get_input_buffer(req);
while (evbuffer_get_length(buf))
{
int n;
char cbuf[1024] = {0};
n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
if (n > 0)
{
(void)fwrite(cbuf, 1, n, stdout);
hd[req_type].handle(cbuf, n, msg);
}
}
return 0;
}
void _httpsrv_encode_str(json_t* p_obj, const char* key, const char* value)
{
json_t *key_child = NULL;
json_t *key_value = NULL;
char* in_key = (char *)malloc(strlen((char *)value)+1);
memset (in_key, 0, strlen((char *)value)+1);
memcpy (in_key, (char *)value, strlen((char *)value)+1);
key_child = json_new_string(key);
key_value = json_new_string((char *)in_key);
json_insert_child(key_child, key_value);
json_insert_child(p_obj, key_child);
free(in_key);
}
void _httpsrv_encode_u32(json_t* p_obj, const char* key, int value)
{
char value_str[8] = {0};
snprintf(value_str, 8, "%d", value);
_httpsrv_encode_str(p_obj, key, value_str);
}
void _httpsrv_encode_u64(json_t* p_obj, const char* key, u64 value)
{
char value_str[8] = {0};
snprintf(value_str, 8, "%llu", value);
_httpsrv_encode_str(p_obj, key, value_str);
}
void _httpsrv_encode_time(json_t* p_obj, const char* key, u64 value)
{
struct tm *pTMNowTime;
time_t tTemptime;
tTemptime = value;
pTMNowTime = localtime(&tTemptime);
if( pTMNowTime == NULL )
return ;
char value_str[32] = {0};
snprintf(value_str, 32, "%02d-%02d-%02d %02d:%02d:%02d",
pTMNowTime->tm_year + 1900,
pTMNowTime->tm_mon + 1,
pTMNowTime->tm_mday,
pTMNowTime->tm_hour,
pTMNowTime->tm_min,
pTMNowTime->tm_sec);
_httpsrv_encode_str(p_obj, key, value_str);
}
static int _httpsrv_encode_autchcode_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.send_authcode_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.send_authcode_res.error_code));
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] send_authcode_res suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_queryusrdata_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.query_user_data_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.query_user_data_res.error_code));
_httpsrv_encode_u32(root, "status", udp_msg->msg.query_user_data_res.status);
_httpsrv_encode_str(root, "remark", udp_msg->msg.query_user_data_res.remark);
_httpsrv_encode_str(root, "telNumber", udp_msg->msg.query_user_data_res.msisdn);
_httpsrv_encode_str(root, "userGroupName", udp_msg->msg.query_user_data_res.usrGrpName);
_httpsrv_encode_u32(root, "balance", udp_msg->msg.query_user_data_res.balance);
_httpsrv_encode_time(root, "expireDate", udp_msg->msg.query_user_data_res.mo_expiry);
_httpsrv_encode_u32(root, "VoiceMinute", udp_msg->msg.query_user_data_res.mo_voc_min);
_httpsrv_encode_u32(root, "remainVoiceMinute", udp_msg->msg.query_user_data_res.remain_mo_voc_min);
//_httpsrv_encode_u32(root, "mtVoiceMinute", udp_msg->msg.query_user_data_res.mt_voc_min);
//_httpsrv_encode_u32(root, "remainMtVoiceMinute", udp_msg->msg.query_user_data_res.remain_mt_voc_min);
_httpsrv_encode_u32(root, "smsVolume", udp_msg->msg.query_user_data_res.total_sms_num);
_httpsrv_encode_u32(root, "remainSmsVolume", udp_msg->msg.query_user_data_res.remain_sms_num);
_httpsrv_encode_u64(root, "dataVolume", udp_msg->msg.query_user_data_res.total_data_vol);
_httpsrv_encode_u64(root, "remainDataVolume", udp_msg->msg.query_user_data_res.remain_data_vol);
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] query_user_data_res suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_bundlesubs_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.bundle_subs_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.bundle_subs_res.error_code));
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] bundle_subs_res suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_bundleusage_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.bundle_usage_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.bundle_usage_res.error_code));
json_t *data_key = json_new_string("data");
json_t *data_arr = json_new_array();
json_insert_child(root, data_key);
json_insert_child(data_key, data_arr);
json_t* tmp = json_new_object();
_httpsrv_encode_u32(tmp, "moVoiceInSecond", udp_msg->msg.bundle_usage_res.moVoiceInSec);
_httpsrv_encode_u32(tmp, "mtVoiceInSecond", udp_msg->msg.bundle_usage_res.mtVoiceInSec);
_httpsrv_encode_u32(tmp, "dataVolumeInKB", udp_msg->msg.bundle_usage_res.dataVolInKB);
_httpsrv_encode_u32(tmp, "smsVolume", udp_msg->msg.bundle_usage_res.smsNum);
_httpsrv_encode_time(tmp, "expiredTimestamp", udp_msg->msg.bundle_usage_res.expiredTime);
json_insert_child(data_arr, tmp);
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] bundle_usage_res suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_recharge_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
int error_code = udp_msg->msg.recharge_res.error_code;
if(error_code == 0)
error_code = 2001;
_httpsrv_encode_u32(root, "code", error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.recharge_res.error_code));
_httpsrv_encode_u32(root, "status", udp_msg->msg.recharge_res.status);
_httpsrv_encode_u32(root, "balance", udp_msg->msg.recharge_res.balance);
_httpsrv_encode_time(root, "expiredTimestamp", udp_msg->msg.recharge_res.expiredTime);
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] recharge_res suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_transfer_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.transfer_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.transfer_res.error_code));
_httpsrv_encode_u32(root, "balance", udp_msg->msg.transfer_res.balance);
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] transfer_res suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_rechargecard_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.recharge_card_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.recharge_card_res.error_code));
_httpsrv_encode_u32(root, "rechargeAmount", udp_msg->msg.recharge_card_res.rechargeAmount);
_httpsrv_encode_u32(root, "balance", udp_msg->msg.recharge_card_res.balance);
_httpsrv_encode_time(root, "expiredTimestamp", udp_msg->msg.recharge_card_res.expiredTime);
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] recharge_card_res suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_checkbalance_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.check_balance_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.check_balance_res.error_code));
_httpsrv_encode_u32(root, "available", udp_msg->msg.check_balance_res.available);
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] check_balance_res suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_querybalance_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.query_balance_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.query_balance_res.error_code));
_httpsrv_encode_u32(root, "status", udp_msg->msg.query_balance_res.status);
_httpsrv_encode_u32(root, "balance", udp_msg->msg.query_balance_res.balance);
_httpsrv_encode_time(root, "expireDate", udp_msg->msg.query_balance_res.mo_expiry);
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] query_balance_res suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_createaccount_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.create_acct_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.create_acct_res.error_code));
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] _httpsrv_encode_createaccount_resp suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_updatesubs_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.update_subs_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.update_subs_res.error_code));
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] _httpsrv_encode_updatesubs_resp suc. resp[%s]\n", *buf);
return SUCCESS;
}
static int _httpsrv_encode_deletesubs_resp(const _rest_msg_s *udp_msg, char **buf)
{
json_t* root = json_new_object();
_httpsrv_encode_u32(root, "code", udp_msg->msg.delete_subs_res.error_code);
_httpsrv_encode_str(root, "message", rest_proxy_errcodemsg(udp_msg->msg.delete_subs_res.error_code));
json_tree_to_string(root, buf);
LOG_D("[httpsrv-encode] _httpsrv_encode_deletesubs_resp suc. resp[%s]\n", *buf);
return SUCCESS;
}
int selfcare_encode(const SELFCARE_URL_E req_type, const _rest_msg_s *udp_msg, char **buf)
{
typedef struct
{
int (*handle)(const _rest_msg_s *udp_msg, char **buf);
}ss;
ss hd[SELFCARE_TYPE_MAX];
hd[SELFCARE_AUTHCODE].handle = _httpsrv_encode_autchcode_resp;
hd[SELFCARE_QUERY_USERDATA].handle =_httpsrv_encode_queryusrdata_resp;
hd[SELFCARE_BUNDLE_SUBS].handle = _httpsrv_encode_bundlesubs_resp;
hd[SELFCARE_BUNDLE_USAGE].handle = _httpsrv_encode_bundleusage_resp;
hd[SELFCARE_RECHARGE].handle = _httpsrv_encode_recharge_resp;
hd[SELFCARE_TRANSFER].handle = _httpsrv_encode_transfer_resp;
hd[SELFCARE_RECHARGE_CARD].handle = _httpsrv_encode_rechargecard_resp;
hd[SELFCARE_CHECK_BALANCE].handle = _httpsrv_encode_checkbalance_resp;
hd[SELFCARE_QUERY_BALANCE].handle = _httpsrv_encode_querybalance_resp;
hd[SELFCARE_CREATE_ACCT].handle = _httpsrv_encode_createaccount_resp;
hd[SELFCARE_UPDATE_SUBS].handle = _httpsrv_encode_updatesubs_resp;
hd[SELFCARE_DELETE_SUBS].handle = _httpsrv_encode_deletesubs_resp;
hd[req_type].handle(udp_msg, buf);
return SUCCESS;
}

View File

@@ -0,0 +1,48 @@
#ifndef __SELFCARE_ENDECODE_H__
#define __SELFCARE_ENDECODE_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <event2/event.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <event2/util.h>
#include <event2/keyvalq_struct.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <json.h>
#include "selfcare_httpsrv.h"
#include "restapi.h"
int selfcare_decode(struct evhttp_request *req,
const SELFCARE_URL_E req_type,
_rest_msg_s *msg);
int selfcare_encode(const SELFCARE_URL_E req_type, const _rest_msg_s *udp_msg, char **buf);
#ifdef __cplusplus
}
#endif
#endif /* __SELFCARE_ENDECODE_H__ */

463
proxy_c/selfcare_httpsrv.c Normal file
View File

@@ -0,0 +1,463 @@
#include <event2/thread.h>
#include "selfcare_httpsrv.h"
#include "log.h"
#include "selfcare_config.h"
static selfcare_elem_s g_elems_arr[SELFCARE_TYPE_MAX];
char uri_root[512];
static const struct table_entry {
const char *extension;
const char *content_type;
} content_type_table[] = {
{ "txt", "text/plain" },
{ "c", "text/plain" },
{ "h", "text/plain" },
{ "html", "text/html" },
{ "htm", "text/html" },
{ "css", "text/css" },
{ "gif", "image/gif" },
{ "jpg", "image/jpg" },
{ "jpeg", "image/jpeg" },
{ "png", "image/png" },
{ "pdf", "application/pdf" },
{ "ps", "application/postscript" },
{ NULL, NULL },
};
/* Try to guess a good content-type for 'path' */
const char* guess_content_type(const char *path)
{
const char *last_period, *extension;
const struct table_entry *ent;
last_period = strrchr(path, '.');
if (!last_period || strchr(last_period, '/'))
{
goto not_found;
}
extension = last_period + 1;
for (ent = &content_type_table[0]; ent->extension; ++ent)
{
if (!evutil_ascii_strcasecmp(ent->extension, extension))
{
return ent->content_type;
}
}
not_found:
return "application/misc";
}
/* Callbase used for the /dump URI, and for every non-get request:
** dumps all information to stdout and gives base a trivial 200 ok */
static void _httpserv_request_cb(struct evhttp_request *req, void *arg)
{
int ret;
ret = selfcare_httpsrv_check(req, arg);
if(ret != SUCCESS)
{
return ;
}
// _httpserv_queue_enter(req, arg);
}
/* This callback gets invoked when we get and http request than doesn't match
* any other callback. Like any evhttp server callback, it has a simple job:
* it must eventually call evhttp_send_error() or evhttp_send_reply().
*/
void _httpserv_senddoc_cb(struct evhttp_request *req, void *arg)
{
struct evbuffer *evb = NULL;
const char *docroot = arg;
const char *uri = evhttp_request_get_uri(req);
struct evhttp_uri *decoded = NULL;
const char *path;
char *decoded_path;
char *whole_path = NULL;
size_t len;
int fd = -1;
struct stat st;
if (evhttp_request_get_command(req) != EVHTTP_REQ_GET)
{
_httpserv_request_cb(req, arg);
return;
}
LOG_D("Got a GET request for <%s>\n", uri);
/* Decode the URI */
decoded = evhttp_uri_parse(uri);
if (!decoded)
{
LOG_E("It's not a good URI, Sneding BADREQUEST\n");
evhttp_send_error(req, HTTP_BADREQUEST, 0);
return;
}
/* Let's see what path the user asked for. */
path = evhttp_uri_get_path(decoded);
if (!path)
{
path = "/";
}
/* We need to decode it, to see what path the user really wanted */
decoded_path = evhttp_uridecode(path, 0, NULL);
if (decoded_path == NULL)
{
goto err;
}
/* Don't allow any ".."'s in the path, to avoid exposing stuff outside
* of the docroot. This test is both overzealous and underzealous:
* it forbids aceptable paths like "/this/one..here", but it doesn't
* do anything to prevent symlink following. */
if (strstr(decoded_path, ".."))
{
goto err;
}
len = strlen(decoded_path) + strlen(docroot) + 2;
if (!(whole_path = malloc(len)))
{
perror("malloc");
goto err;
}
evutil_snprintf(whole_path, len, "%s/%s", docroot, decoded_path);
if (stat(whole_path, &st) < 0)
{
goto err;
}
/* This holds the content we're sending */
evb = evbuffer_new();
if (S_ISDIR(st.st_mode))
{
/* If it's a directory, read the comments and make a little index page */
DIR *d;
struct dirent *ent;
const char *trailing_slash = "";
if (!strlen(path) || path[strlen(path) - 1] != '/')
{
trailing_slash = "/";
}
if (!(d = opendir(whole_path)))
{
goto err;
}
evbuffer_add_printf(evb,
"<!DOCTYPE html>\n"
"<html>\n "
" <head>\n"
" <meta charset='utf-8'>\n"
" <title>%s</title>\n"
" <base href='%s%s'>\n"
" </head>\n"
" <body>\n"
" <h1>%s</h1>\n"
" <ul>\n",
decoded_path, /* xxx html-escape this. */
path, /* xxx html-escape this? */
trailing_slash,
decoded_path /* xx html-escape this */
);
while ((ent = readdir(d)))
{
const char *name = ent->d_name;
evbuffer_add_printf(evb,
" <li><a href=\"%s\">%s</a>\n", name, name);
}
evbuffer_add_printf(evb, "</ul></body></html>\n");
closedir(d);
evhttp_add_header(evhttp_request_get_output_headers(req),
"Content-Type", "text/html");
}
else
{
/* Otherwise it's a file; and it to the buffer to get send via sendfile */
const char *type = guess_content_type(decoded_path);
if ((fd = open(whole_path, O_RDONLY)) < 0)
{
perror("open");
goto err;
}
if (fstat(fd, &st) < 0)
{
/* Make sure the length still matches, now that we opened the file :/ */
perror("fstat");
goto err;
}
evhttp_add_header(evhttp_request_get_output_headers(req),
"Content-Type", type);
evbuffer_add_file(evb, fd, 0, st.st_size);
}
evhttp_send_reply(req, 200, "OK", evb);
goto done;
err:
evhttp_send_error(req, 404, "Document was not found");
if (fd >= 0)
{
close(fd);
}
done:
if (decoded)
{
evhttp_uri_free(decoded);
}
if (decoded_path)
{
free(decoded_path);
}
if (whole_path)
{
free(whole_path);
}
if (evb)
{
evbuffer_free(evb);
}
}
static int _httpserv_init(int argc, char **argv)
{
struct event_base *base;
struct evhttp *http;
struct evhttp_bound_socket *handle;
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
{
printf("signal error, errno[%d], error[%s]", errno, strerror(errno));
return -1;
}
evthread_use_pthreads();
base = event_base_new();
if (!base)
{
printf("Couldn't create an event_base:exiting\n");
return -1;
}
/* Create a new http oject to handle request */
http = evhttp_new(base);
if (!http)
{
printf("Couldn't create evhttp.Exiting\n");
return -1;
}
/* The /dump URI will dump all requests to stdout and say 200 ok */
int i;
for(i = SELFCARE_TYPE_MIN; i < SELFCARE_TYPE_MAX; ++i)
{
if(g_elems_arr[i].handle != NULL)
{
/* ע<><D7A2><EFBFBD>ص<EFBFBD><D8B5>ϲ<CFB2><E3B6A8><EFBFBD>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
evhttp_set_cb(http, g_elems_arr[i].url_addr, g_elems_arr[i].handle, NULL);
}
else
{
/* ע<><D7A2>Ĭ<EFBFBD>ϵĻص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
evhttp_set_cb(http, "/dump", _httpserv_request_cb, NULL);
}
}
/* We want to accept arbitrary requests, so we need to set a "generic" cb
* We can also add callbacks for specific paths */
// evhttp_set_gencb(http, _httpserv_senddoc_cb, argv[1]);
/* Now we teel the evhttp what port to listen on */
handle = evhttp_bind_socket_with_handle(http, "0.0.0.0", selfcare_config_get()->http_local_port);
if (!handle)
{
printf("Couldn't bind to port[%d], exiting\n", selfcare_config_get()->http_local_port);
return -1;
}
{
/* Extract and display the address we're listening on. */
struct sockaddr_storage ss;
evutil_socket_t fd;
ev_socklen_t socklen = sizeof(ss);
char addrbuf[128];
void *inaddr;
const char *addr;
int got_port = -1;
fd = evhttp_bound_socket_get_fd(handle);
memset(&ss, 0, sizeof(ss));
if (getsockname(fd, (struct sockaddr *)&ss, &socklen))
{
perror("getsockname() failed");
return -1;
}
if (ss.ss_family == AF_INET)
{
got_port = ntohs(((struct sockaddr_in*)&ss)->sin_port);
inaddr = &((struct sockaddr_in*)&ss)->sin_addr;
}
else if (ss.ss_family == AF_INET6)
{
got_port = ntohs(((struct sockaddr_in6*)&ss)->sin6_port);
inaddr = &((struct sockaddr_in6*)&ss)->sin6_addr;
}
else
{
printf("Weird address family\n");
return 1;
}
addr = evutil_inet_ntop(ss.ss_family, inaddr, addrbuf, sizeof(addrbuf));
if (addr)
{
LOG_D("Listening on %s:%d\n", addr, got_port);
evutil_snprintf(uri_root, sizeof(uri_root), "http://%s:%d", addr, got_port);
}
else
{
printf("evutil_inet_ntop failed\n");
return -1;
}
}
event_base_dispatch(base);
return SUCCESS;
}
int selfcare_httpsrv_init(int argc, char **argv)
{
int ret;
ret = _httpserv_init(argc, argv);
return ret;
}
void selfcare_httpsrv_uninit(void)
{
}
int selfcare_httpsrv_check(struct evhttp_request *req, void *arg)
{
return SUCCESS;
const char *cmdtype;
struct evkeyvalq *headers;
struct evkeyval *header;
struct evbuffer *buf;
switch (evhttp_request_get_command(req))
{
case EVHTTP_REQ_GET:
cmdtype = "GET";
break;
case EVHTTP_REQ_POST:
cmdtype = "POST";
break;
case EVHTTP_REQ_HEAD:
cmdtype = "HEAD";
break;
case EVHTTP_REQ_PUT:
cmdtype = "PUT";
break;
case EVHTTP_REQ_DELETE:
cmdtype = "DELETE";
break;
case EVHTTP_REQ_OPTIONS:
cmdtype = "OPTIONS";
break;
case EVHTTP_REQ_TRACE:
cmdtype = "TRACE";
break;
case EVHTTP_REQ_CONNECT:
break;
case EVHTTP_REQ_PATCH:
cmdtype = "PATCH";
break;
default:
cmdtype = "unknown";
break;
}
LOG_D("Received a %s request for %s\nHeader:\n", cmdtype, evhttp_request_get_uri(req));
headers = evhttp_request_get_input_headers(req);
for (header = headers->tqh_first; header; header = header->next.tqe_next)
{
LOG_D(" %s: %s\n", header->key, header->value);
}
buf = evhttp_request_get_input_buffer(req);
puts("Input data: <<<<");
while (evbuffer_get_length(buf))
{
int n;
char cbuf[128];
n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
if (n > 0)
{
(void)fwrite(cbuf, 1, n, stdout);
}
}
puts(">>>");
evhttp_send_reply(req, 200, "ok", NULL);
return SUCCESS;
}
int selfcare_httpsrv_reg(const selfcare_elem_s *elem)
{
memcpy(&g_elems_arr[elem->url_type], elem, sizeof(selfcare_elem_s));
return SUCCESS;
}
int selfcare_httpsrv_send(struct evhttp_request *req, const int ret_code, char *buf)
{
struct evbuffer *evb = NULL;
evb = evbuffer_new();
evbuffer_add_printf(evb, "%s", buf);
evhttp_add_header(evhttp_request_get_output_headers(req),
"Content-Type", "application/json");
evhttp_send_reply(req, ret_code, "OK", evb);
if (evb)
{
evbuffer_free(evb);
}
return SUCCESS;
}

View File

@@ -0,0 +1,82 @@
#ifndef __SELFCARE_HTTPSRV_H__
#define __SELFCARE_HTTPSRV_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <event2/event.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <event2/util.h>
#include <event2/keyvalq_struct.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <json.h>
#include "restapi.h"
typedef enum _SELFCARE_URL_E
{
SELFCARE_TYPE_MIN = 0,
SELFCARE_AUTHCODE, // <20>û<EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD>Žӿ<C5BD>
SELFCARE_QUERY_USERDATA, // <20>û<EFBFBD><C3BB><EFBFBD>Ϣ<EFBFBD><CFA2>ѯ<EFBFBD>ӿ<EFBFBD>
SELFCARE_BUNDLE_SUBS, // <20>ײͶ<D7B2><CDB6><EFBFBD><EFBFBD>ӿ<EFBFBD>
SELFCARE_BUNDLE_USAGE, // <20>Ѷ<EFBFBD><D1B6><EFBFBD><EFBFBD>ײͲ<D7B2>ѯ
SELFCARE_RECHARGE, // <20><>ֵ<EFBFBD>ӿ<EFBFBD>
SELFCARE_TRANSFER, // ת<>˽ӿ<CBBD>
SELFCARE_RECHARGE_CARD, // <20><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>ֵ<EFBFBD>ӿ<EFBFBD>
SELFCARE_CHECK_BALANCE, // <20>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>ӿ<EFBFBD>
SELFCARE_QUERY_BALANCE, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD>ӿ<EFBFBD>
SELFCARE_CRM_PAYMENT, // CRM charge interface
SELFCARE_SMS_DELIVER,
SELFCARE_CREATE_ACCT,
SELFCARE_UPDATE_SUBS,
SELFCARE_DELETE_SUBS,
SELFCARE_TYPE_MAX,
}SELFCARE_URL_E;
#define SELFCARE_URL_LEN (128)
typedef struct _selfcare_elem_s
{
SELFCARE_URL_E url_type;
char url_addr[SELFCARE_URL_LEN];
void (*handle)(struct evhttp_request *req, void *arg);
}selfcare_elem_s;
int selfcare_httpsrv_init(int argc, char **argv);
void selfcare_httpsrv_uninit(void);
int selfcare_httpsrv_reg(const selfcare_elem_s *elem);
int selfcare_httpsrv_check(struct evhttp_request *req, void *arg);
int selfcare_httpsrv_send(struct evhttp_request *req, const int ret_code, char *buf);
#ifdef __cplusplus
}
#endif
#endif /* __SELFCARE_HTTPSRV_H__ */

445
proxy_c/selfcare_proxy.c Normal file
View File

@@ -0,0 +1,445 @@
#include "selfcare_proxy.h"
#include "utils_queue.h"
#include "selfcare_udp.h"
#include "selfcare_endecode.h"
#include "selfcare_res.h"
#include "log.h"
extern int get_proxy_run_mode();
extern int rest_query_recharge_card_proc( struct rest_msg_s *rest_ptr);
extern int rest_query_tariff_proc(struct rest_msg_s *rest_ptr);
extern int rest_update_plan_info_proc(struct rest_msg_s *rest_ptr);
extern int rest_update_ocs_del_result(struct rest_msg_s *rest_ptr);
extern int rest_rent_charge_behalf_on_ocs(struct rest_msg_s *rest_ptr);
extern int rest_update_subs_info_proc(struct rest_msg_s *rest_ptr);
static int _httpserv_handle_udpresp(char *buff, int len)
{
/* <20><><EFBFBD><EFBFBD>ocs<63><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>udp<64><70>Ϣ */
int ret;
_rest_msg_s msg;
memset(&msg, 0x00, sizeof(msg));
ret = decode_rest_api_msg((u8*)buff, len, &msg);
if(ret != 1)
{
LOG_E("[udp-handle] decode ocs resp err.ret[%d]\n", ret);
return ret;
}
if(get_proxy_run_mode() == 4)//OCS+CRM mode
{
if(msg.msg_type == REST_UPDATE_RECHARGE_CARD_REQ)
{
LOG_E("[udp-handle] proc ocs REST_UPDATE_RECHARGE_CARD_REQ\n");
rest_query_recharge_card_proc(&msg);
return ret;
}
if(msg.msg_type == REST_CRM_QUERY_TARIFF_REQ)
{
// LOG_E("[udp-handle] proc ocs REST_CRM_QUERY_TARIFF_REQ\n");
rest_query_tariff_proc(&msg);
return ret;
}
if(msg.msg_type == REST_CRM_UPDATE_PLAN_INFO_REQ)
{
// LOG_E("[udp-handle] proc ocs REST_CRM_UPDATE_PLAN_INFO_REQ\n");
rest_update_plan_info_proc( &msg);
return ret;
}
if(msg.msg_type == REST_CRM_DELETE_SUBS_RES)
{
// LOG_E("[udp-handle] proc ocs REST_CRM_DELETE_SUBS_RES\n");
rest_update_ocs_del_result( &msg);
return ret;
}
if(msg.msg_type == REST_CRM_RENT_CHARGE)
{
// LOG_E("[udp-handle] proc ocs REST_CRM_RENT_CHARGE\n");
rest_rent_charge_behalf_on_ocs( &msg);
return ret;
}
if(msg.msg_type == REST_CRM_UPDATE_SUBS_REQ)
{
// LOG_E("[udp-handle] proc ocs REST_CRM_UPDATE_SUBS_INFO_REQ\n");
rest_update_subs_info_proc( &msg);
return ret;
}
}
int res_id = msg.header.dst_ref;
if(res_id >= SELFCARE_RES_NUM)
{
LOG_E("[udp-handle] proc ocs resp err. res_id[%d], msg_type=%d\n", res_id, msg.msg_type);
return FAILURE;
}
if(g_res_arr[res_id].state != SELFCARE_WAIT_OCS_RESP)
{
LOG_E("[udp-handle] recv udp err.res_id[%d] state[%s] expect[%s] \n",
res_id,
selfcare_res_stateprint(g_res_arr[res_id].state),
selfcare_res_stateprint(SELFCARE_WAIT_OCS_RESP) );
return SUCCESS;
}
_rest_msg_s *resp = &g_res_arr[res_id].resp;
memcpy(resp, &msg, sizeof(msg));
if(g_res_arr[res_id].local_init_flag == 1)
g_res_arr[res_id].state = SELFCARE_LOCAL_INIT_RESP;
else
g_res_arr[res_id].state = SELFCARE_WAIT_SEND2SELFCARE_RESP;
LOG_D("[udp-handle] recv udp suc.res_id[%d] state[%s=>%s]\n",
res_id,
selfcare_res_stateprint(SELFCARE_WAIT_OCS_RESP),
selfcare_res_stateprint(g_res_arr[res_id].state) );
return SUCCESS;
}
static int _httpserv_handle_httpreq(struct evhttp_request *req, void *arg, SELFCARE_URL_E req_type)
{
int ret;
ret = selfcare_httpsrv_check(req, arg);
if(ret != SUCCESS)
{
LOG_E("[httpserv] check failed\n");
return ret;
}
int res_id;
ret = selfcare_res_get(&res_id);
if(ret != SUCCESS)
{
LOG_D("[httpserv] no res.\n");
// send http-resp failed
return ret;
}
selfcare_res_s *res = &g_res_arr[res_id];
memset(res, 0x00, sizeof(selfcare_res_s));
res->id = res_id;
res->state = SELFCARE_WAIT_SEND2OCS_REQ;
res->req = req;
res->arg = arg;
res->req_type = req_type;
LOG_D("[httpserv] res_id[%d] get suc. state[%s] for type[%d]\n", res->id, selfcare_res_stateprint(res->state), req_type);
return SUCCESS;
}
selfcare_res_s *selfcare_assign_res()
{
int res_id, ret;
selfcare_res_s *res=NULL;
ret = selfcare_res_get(&res_id);
if(ret != SUCCESS)
{
LOG_D("[httpserv] no res.\n");
return NULL;
}
res = &g_res_arr[res_id];
memset(res, 0x00, sizeof(selfcare_res_s));
res->id = res_id;
LOG_D("[httpserv] res_id[%d] get suc. state[%s]\n", res->id, selfcare_res_stateprint(res->state));
return res;
}
static void _httpserv_handle_authcode(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_AUTHCODE);
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle authcode err.\n");
return ;
}
LOG_D("[httpserv] handle authcode suc.req[%p]\n", req);
return ;
}
static void _httpserv_handle_queryuserdata(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_QUERY_USERDATA);
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle queryuserdata err.\n");
return ;
}
LOG_D("[httpserv] handle queryuserdata suc.\n");
return ;
}
static void _httpserv_handle_bundlesubs(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_BUNDLE_SUBS);
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle bundlesubs err.\n");
return ;
}
LOG_D("[httpserv] handle bundlesubs suc.\n");
return ;
}
static void _httpserv_handle_bundleusage(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_BUNDLE_USAGE);
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle bundleusage err.\n");
return;
}
LOG_D("[httpserv] handle bundleusage suc.\n");
return ;
}
static void _httpserv_handle_recharge(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_RECHARGE);
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle recharge err.\n");
return ;
}
LOG_D("[httpserv] handle recharge suc.\n");
return ;
}
static void _httpserv_handle_transfer(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_TRANSFER);
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle transfer err.\n");
return ;
}
LOG_D("[httpserv] handle transfer suc.\n");
return ;
}
static void _httpserv_handle_rechargecard(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_RECHARGE_CARD );
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle rechargecard err.\n");
return ;
}
LOG_D("[httpserv] handle rechargecard suc.\n");
return ;
}
static void _httpserv_handle_checkbalance(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_CHECK_BALANCE );
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle checkbalance err.\n");
return ;
}
LOG_D("[httpserv] handle checkbalance suc.\n");
return ;
}
static void _httpserv_handle_querybalane(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_QUERY_BALANCE );
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle querybalane err.\n");
return ;
}
LOG_D("[httpserv] handle querybalane suc.\n");
return ;
}
static void _httpserv_handle_payment(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_CRM_PAYMENT );
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle crm payment err.\n");
return ;
}
LOG_D("[httpserv] handle crm payment suc.\n");
return ;
}
static void _httpserv_handle_smsdeliver(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_SMS_DELIVER);
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle sms_deliver err.\n");
return ;
}
LOG_D("[httpserv] handle sms_deliver suc.\n");
return ;
}
static void _httpserv_handle_createaccount(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_CREATE_ACCT);
if(ret != SUCCESS)
{
LOG_E("[httpserv] handle create_account err.\n");
return ;
}
LOG_D("[httpserv] handle create_account suc.\n");
return ;
}
static void _httpserv_handle_updatesubs(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_UPDATE_SUBS);
if(ret != SUCCESS)
{
LOG_E("[httpserv] _httpserv_handle_updatesubs err.\n");
return ;
}
LOG_D("[httpserv] _httpserv_handle_updatesubs suc.\n");
return ;
}
static void _httpserv_handle_deletesubs(struct evhttp_request *req, void *arg)
{
int ret;
ret = _httpserv_handle_httpreq(req, arg, SELFCARE_DELETE_SUBS);
if(ret != SUCCESS)
{
LOG_E("[httpserv] _httpserv_handle_updatesubs err.\n");
return ;
}
LOG_D("[httpserv] _httpserv_handle_updatesubs suc.\n");
return ;
}
static int _selfcare_proxy_reg(const SELFCARE_URL_E url_type,
const char *url_addr,
void (*handle)(struct evhttp_request *req, void *arg) )
{
selfcare_elem_s elem;
memset(&elem, 0x00, sizeof(elem));
elem.url_type = url_type;
strncpy(elem.url_addr, url_addr, SELFCARE_URL_LEN);
elem.handle = handle;
return selfcare_httpsrv_reg(&elem);
}
int selfcare_proxy_init(int argc, char **argv)
{
int ret;
/* <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
ret = selfcare_config_init(NULL);
if(ret != SUCCESS)
{
return ret;
}
/* <20><>ʼ<EFBFBD><CABC>udp socket */
ret = selfcare_udp_init();
if(ret != SUCCESS)
{
return ret;
}
/* ע<><D7A2>selfcare<72><65><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD> */
ret = _selfcare_proxy_reg(SELFCARE_AUTHCODE, selfcare_config_get()->authcode_url, _httpserv_handle_authcode);
ret += _selfcare_proxy_reg(SELFCARE_QUERY_USERDATA, selfcare_config_get()->query_userdata_url, _httpserv_handle_queryuserdata);
ret += _selfcare_proxy_reg(SELFCARE_BUNDLE_SUBS, selfcare_config_get()->bundle_subs_url, _httpserv_handle_bundlesubs);
ret += _selfcare_proxy_reg(SELFCARE_BUNDLE_USAGE, selfcare_config_get()->bundle_usage_url, _httpserv_handle_bundleusage);
ret += _selfcare_proxy_reg(SELFCARE_RECHARGE, selfcare_config_get()->recharge_url, _httpserv_handle_recharge);
ret += _selfcare_proxy_reg(SELFCARE_TRANSFER, selfcare_config_get()->transfer_url, _httpserv_handle_transfer);
ret += _selfcare_proxy_reg(SELFCARE_RECHARGE_CARD, selfcare_config_get()->recharge_card_url, _httpserv_handle_rechargecard);
ret += _selfcare_proxy_reg(SELFCARE_CHECK_BALANCE, selfcare_config_get()->check_balance_url, _httpserv_handle_checkbalance);
ret += _selfcare_proxy_reg(SELFCARE_QUERY_BALANCE, selfcare_config_get()->query_balane_url, _httpserv_handle_querybalane);
ret += _selfcare_proxy_reg(SELFCARE_CRM_PAYMENT, selfcare_config_get()->payment_url , _httpserv_handle_payment);
ret += _selfcare_proxy_reg(SELFCARE_SMS_DELIVER, selfcare_config_get()->sms_deliver_url, _httpserv_handle_smsdeliver);
ret += _selfcare_proxy_reg(SELFCARE_CREATE_ACCT, selfcare_config_get()->create_account_url, _httpserv_handle_createaccount);
ret += _selfcare_proxy_reg(SELFCARE_UPDATE_SUBS, selfcare_config_get()->update_subs_url, _httpserv_handle_updatesubs);
ret += _selfcare_proxy_reg(SELFCARE_DELETE_SUBS, selfcare_config_get()->delete_subs_url, _httpserv_handle_deletesubs);
/* ע<><D7A2>ocs udp<64><70>Ϣ<EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD> */
selfcare_udp_handle_s handle;
handle.handle = _httpserv_handle_udpresp;
ret = selfcare_udp_reg(&handle);
if(ret != SUCCESS)
{
return ret;
}
ret = selfcare_res_init(argc, argv);
if(ret != SUCCESS)
{
return ret;
}
ret = selfcare_httpsrv_init(argc, argv);
if(ret != SUCCESS)
{
return ret;
}
return SUCCESS;
}
void selfcare_proxy_uninit(void)
{
selfcare_config_uninit();
selfcare_udp_uninit();
selfcare_httpsrv_uninit();
selfcare_res_uninit();
}

23
proxy_c/selfcare_proxy.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef __SELFCARE_PROXY_H__
#define __SELFCARE_PROXY_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "selfcare_httpsrv.h"
#include "selfcare_config.h"
int selfcare_proxy_init(int argc, char **argv);
void selfcare_proxy_uninit(void);
#ifdef __cplusplus
}
#endif
#endif /* __SELFCARE_PROXY_H__ */

379
proxy_c/selfcare_res.c Normal file
View File

@@ -0,0 +1,379 @@
#include "selfcare_res.h"
#include "utils_queue.h"
#include "selfcare_udp.h"
#include "selfcare_endecode.h"
#include "log.h"
extern selfcare_res_s *selfcare_assign_res();
extern void crm_delete_subscriber_profile(char *service_num, int account_type, int account_id);
extern int crm_prov_handle_response(selfcare_res_s *res);
extern ulong TransStrTimeToSecond(const char *str_time);//YYYY-MM-DD HH:MM:YY
extern int dba_crm_get_product_rent(int from, int package_id);
extern void _selfcare_udp_process();
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>*/
static queueADT g_res_queue;
static int g_res[SELFCARE_RES_NUM];
/* <20><>Դ */
selfcare_res_s g_res_arr[SELFCARE_RES_NUM];
static int g_res_run_flag;
static int _selfcare_fsm_sendudp(selfcare_res_s *res)
{
int ret;
/* 1. <20><><EFBFBD><EFBFBD>selfcareϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ */
_rest_msg_s msg;
memset(&msg, 0x00, sizeof(msg));
ret = selfcare_decode(res->req,res->req_type, &msg);
if(ret != SUCCESS)
{
LOG_E("[httpserv] decode failed\n");
return ret;
}
LOG_D("[httpserv] decode suc. res_id[%d]\n", res->id);
/* 2. <20><><EFBFBD><EFBFBD> */
char buf[1024];
int len;
msg.header.src_ref = res->id;
len = encode_rest(&msg, (u8*)buf);
if(msg.msg_type == REST_CRM_DELETE_SUBS_REQ)
{
crm_delete_subscriber_profile(msg.msg.delete_subs.msisdn, msg.msg.delete_subs.account_type, msg.msg.delete_subs.account_id);
if(msg.msg.delete_subs.account_type != 1)//not mobile
{
//return OK to CRM here
res->resp.msg_type = REST_CRM_DELETE_SUBS_RES;
res->resp.msg.delete_subs_res.result = 0;
res->resp.msg.delete_subs_res.error_code = 2001;
res->state = SELFCARE_WAIT_SEND2SELFCARE_RESP;
return SUCCESS;
}
}
/* 3. <20><><EFBFBD><EFBFBD>udp<64><70>Ϣ<EFBFBD><CFA2> ocs */
if(len > 0)
{
ret = selfcare_udp_send(buf, len);
LOG_D("[httpserv] send udp suc.res_id[%d] ret[%d]\n", res->id, ret);
return SUCCESS;
}
LOG_E("[httpserv] err.send udp err. res_id[%d]\n", res->id);
return FAILURE;
}
static int _selfcare_fsm_sendudp_local(selfcare_res_s *res, _rest_msg_s msg)
{
int ret;
char buf[1024];
int len;
msg.header.src_ref = res->id;
len = encode_rest(&msg, (u8*)buf);
/* 3. <20><><EFBFBD><EFBFBD>udp<64><70>Ϣ<EFBFBD><CFA2> ocs */
if(len > 0)
{
ret = selfcare_udp_send(buf, len);
LOG_D("[httpserv] send udp suc.res_id[%d] ret[%d]\n", res->id, ret);
return SUCCESS;
}
LOG_E("[httpserv] err.send udp err. res_id[%d]\n", res->id);
return FAILURE;
}
/* <20><><EFBFBD>ͻظ<CDBB><D8B8><EFBFBD>selfcareϵͳ */
static void _selfcare_fsm_send2selfcare(const selfcare_res_s *res)
{
/* <20><><EFBFBD><EFBFBD> */
char *buf = NULL;
selfcare_encode(res->req_type, &res->resp, &buf);
/* <20>ظ<EFBFBD> */
selfcare_httpsrv_send(res->req, 200, buf);
}
void _selfcare_res_fsm(void)
//static void _selfcare_res_fsm(void)
{
int i;
selfcare_res_s *res;
for(i = 1; i < SELFCARE_RES_NUM; ++i)
{
res = &g_res_arr[i];
res->timer++;
switch(res->state)
{
case SELFCARE_IDLE:
break;
case SELFCARE_WAIT_SELFCARE_REQ:
break;
case SELFCARE_WAIT_SEND2OCS_REQ:
LOG_D("[httpserv] res_id[%d] state[%s->%s]\n",
res->id, selfcare_res_stateprint(res->state), selfcare_res_stateprint(SELFCARE_WAIT_OCS_RESP));
_selfcare_fsm_sendudp(res);
res->state = SELFCARE_WAIT_OCS_RESP;
res->timer = 0;
break;
case SELFCARE_WAIT_OCS_RESP:
/* 3<><33>û<EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> */
if(res->timer >= 3000)
{
// send httpserv time out ???
LOG_D("[httpserv] res_id[%d] timeout state[%s->%s]\n",
res->id, selfcare_res_stateprint(res->state), selfcare_res_stateprint(SELFCARE_RELEASE));
res->state = SELFCARE_RELEASE;
}
break;
case SELFCARE_WAIT_SEND2SELFCARE_RESP:
LOG_D("[httpserv] res_id[%d] state[%s->%s]\n",
res->id, selfcare_res_stateprint(res->state), selfcare_res_stateprint(SELFCARE_RELEASE));
_selfcare_fsm_send2selfcare(res);
res->state = SELFCARE_RELEASE;
res->timer = 0;
break;
case SELFCARE_LOCAL_INIT_REQ:
LOG_D("[httpserv] res_id[%d] state[%s->%s]\n",
res->id, selfcare_res_stateprint(res->state), selfcare_res_stateprint(SELFCARE_WAIT_OCS_RESP));
res->state = SELFCARE_WAIT_OCS_RESP;
res->timer = 0;
// _selfcare_fsm_sendudp(res);
break;
case SELFCARE_LOCAL_INIT_RESP:
LOG_D("[httpserv] res_id[%d] state[%s->%s]\n",
res->id, selfcare_res_stateprint(res->state), selfcare_res_stateprint(SELFCARE_RELEASE));
crm_prov_handle_response(res);
res->state = SELFCARE_RELEASE;
res->timer = 0;
break;
case SELFCARE_RELEASE:
case SELFCARE_STATE_MAX:
default:
memset(&g_res_arr[i], 0x00, sizeof(selfcare_res_s));
selfcare_res_release(i);
LOG_D("[httpserv] release suc. res_id[%d] state[%s]\n",
i, selfcare_res_stateprint(SELFCARE_IDLE));
break;
}
}
}
/*--------------------------------------------------------*/
int crm_prov_mobile_prepaid_account(char sub_data[][1024], int cug_id, int user_class)
{//user class=1/2 local / tourist
selfcare_res_s *res = selfcare_assign_res();
_rest_msg_s *msg=NULL, rest_msg;
if(res == NULL)
return 0;
msg = &rest_msg;
msg->msg_type = REST_CRM_CREATE_ACCT_REQ;
strcpy(msg->msg.create_acct.msisdn, sub_data[3]);
msg->msg.create_acct.customer_id = atoi(sub_data[6]);
msg->msg.create_acct.account_id = atoi(sub_data[7]);
msg->msg.create_acct.product_id = atoi(sub_data[8]);
msg->msg.create_acct.plan_id = atoi(sub_data[14]);
msg->msg.create_acct.user_class = user_class;
msg->msg.create_acct.cug_id = cug_id;//atoi(sub_data[16]);
msg->msg.create_acct.balance = atoi(sub_data[12]);
msg->msg.create_acct.expiry_date = TransStrTimeToSecond(sub_data[13]);
msg->msg.create_acct.birthday = TransStrTimeToSecond(sub_data[11]);
msg->msg.create_acct.rent_charge = dba_crm_get_product_rent(0, msg->msg.create_acct.plan_id);
res->local_init_db_key = atoi(sub_data[0]);
res->local_init_flag = 1;
res->local_init_oc = REST_CRM_CREATE_ACCT_REQ;
_selfcare_fsm_sendudp_local(res, rest_msg);
res->state = SELFCARE_LOCAL_INIT_REQ;
return 1;
}
int crm_prov_handle_response(selfcare_res_s *res)
{
char sql[2048];
if(res == NULL)
return 0;
switch(res->local_init_oc)
{
case REST_CRM_CREATE_ACCT_REQ:
if(res->resp.msg.create_acct_res.error_code == OCS_RES_SUCCEED)
{
sprintf(sql, "UPDATE tb_sync_mobile set STATE=2, OPER_RESULT=1 where PRE_ID=%d", res->local_init_db_key);
}
else
{
sprintf(sql, "UPDATE tb_sync_mobile set STATE=2, OPER_RESULT=2 where PRE_ID=%d", res->local_init_db_key);
}
//subs_provisioning_update_result(sql);
break;
default:
break;
}
return 1;
}
/*--------------------------------------------------------*/
static void *_selfcare_res_thread(void *data)
{
prctl(PR_SET_NAME, "selfcare-fsm");
while(g_res_run_flag)
{
_selfcare_udp_process();
_selfcare_res_fsm();
usleep(1000);
}
pthread_exit(NULL);
return NULL;
}
static int _selfcare_res_inittask()
{
pthread_t handle;
g_res_run_flag = 1;
if(pthread_create(&handle, NULL, _selfcare_res_thread, NULL))
{
printf("Thread create err !!!\n");
return FAILURE;
if ( pthread_detach(handle) )
{
printf("Thread detached err !!!\n");
return FAILURE;
}
}
return SUCCESS;
}
int selfcare_res_get(int *res_id)
{
queueElementT elem = QueueDelete(g_res_queue);
if(elem == NULL)
{
LOG_E("[selfcare-res] get err. null\n");
return FAILURE;
}
*res_id = *(int*)elem;
return SUCCESS;
}
int selfcare_res_release(const int res_id)
{
int ret;
if(res_id>=SELFCARE_RES_NUM)
return FAILURE;
ret = QueueEnter(g_res_queue, &g_res[res_id]);
if(ret != SUCCESS_QUEUE)
{
return FAILURE;
}
return SUCCESS;
}
const char *selfcare_res_stateprint(selfcare_state_e state)
{
switch(state)
{
case SELFCARE_IDLE:
return "idle";
case SELFCARE_WAIT_SELFCARE_REQ:
return "wait_selfcare_req";
case SELFCARE_WAIT_SEND2OCS_REQ:
return "send2ocs_req";
case SELFCARE_WAIT_OCS_RESP:
return "wait_ocs_resp";
case SELFCARE_WAIT_SEND2SELFCARE_RESP:
return "wait_send2selfcare_resp";
case SELFCARE_LOCAL_INIT_REQ:
return "local initiating process - send request";
case SELFCARE_LOCAL_INIT_RESP:
return "local initiating process-wait for response";
case SELFCARE_RELEASE:
return "release";
default:
return "unknow";
}
return "unknow";
}
int selfcare_res_init(int argc, char **argv)
{
int ret;
/* <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>*/
g_res_queue = QueueCreate(SELFCARE_RES_NUM);
if(g_res_queue == NULL)
{
return FAILURE;
}
/* <20><><EFBFBD>ؿ<EFBFBD><D8BF><EFBFBD><EFBFBD><EFBFBD>Դ */
int i = 0;
for(i = 1; i < SELFCARE_RES_NUM; ++i)
{
g_res[i] = i;
ret = QueueEnter(g_res_queue, &g_res[i]);
if(ret != SUCCESS_QUEUE)
{
return FAILURE;
}
}
_selfcare_res_inittask();
return SUCCESS;
}
void selfcare_res_uninit(void)
{
QueueDestroy(g_res_queue);
g_res_run_flag = 0;
}

66
proxy_c/selfcare_res.h Normal file
View File

@@ -0,0 +1,66 @@
#ifndef __SELFCARE_RES_H__
#define __SELFCARE_RES_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "selfcare_httpsrv.h"
#include "selfcare_config.h"
typedef enum _selfcare_state_e
{
SELFCARE_IDLE = 0,
SELFCARE_WAIT_SELFCARE_REQ,
SELFCARE_WAIT_SEND2OCS_REQ,
SELFCARE_WAIT_OCS_RESP,
SELFCARE_WAIT_SEND2SELFCARE_RESP,
SELFCARE_LOCAL_INIT_REQ,
SELFCARE_LOCAL_INIT_RESP,
SELFCARE_RELEASE,
SELFCARE_STATE_MAX,
}selfcare_state_e;
#define SELFCARE_RES_NUM (1024)
typedef struct _selfcare_res_s
{
int id;
unsigned int timer;
selfcare_state_e state; /* ״̬ */
struct evhttp_request *req; /* selfcare <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8> */
char *arg; /* libevent <20>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD> */
SELFCARE_URL_E req_type; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
_rest_msg_s resp; /* OCS <20>ظ<EFBFBD><D8B8><EFBFBD>udp<64><70>Ϣ */
int local_init_flag;
int local_init_oc;
int local_init_db_key;
}selfcare_res_s;
extern selfcare_res_s g_res_arr[SELFCARE_RES_NUM];
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դid */
int selfcare_res_get(int *res_id);
/* <20>ͷ<EFBFBD>id */
int selfcare_res_release(const int res_id);
const char *selfcare_res_stateprint(selfcare_state_e state);
/* <20><>ʼ<EFBFBD><CABC> */
int selfcare_res_init(int argc, char **argv);
/* <20><><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC> */
void selfcare_res_uninit(void);
#ifdef __cplusplus
}
#endif
#endif /* __SELFCARE_RES_H__ */

122
proxy_c/selfcare_udp.c Normal file
View File

@@ -0,0 +1,122 @@
#include "selfcare_udp.h"
#include "selfcare_config.h"
#include "selfcare_proxy.h"
#include "rest_proxy.h"
#include "log.h"
/* <20><><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD>udp<64>˿<EFBFBD> */
static int g_udp_listfd;
/* <20>߳<EFBFBD><DFB3><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD> */
static int g_udp_runflag;
/* <20>յ<EFBFBD>udp<64><70>Ϣ<EFBFBD>ص<EFBFBD> */
static selfcare_udp_handle_s g_udp_handle;
extern int init_socket(unsigned int local_addr, short local_port, char stype, int noblock_flag);
static int _selfcare_udp_initfd(const unsigned int local_addr, const short local_port)
{
int fd;
fd = init_socket(local_addr, local_port, 0, 1);
if(fd <= 0)
{
LOG_E("[selfcare] init udp fd err. IPPort[%u:%d]\n", local_addr, local_port);
exit(-1);
}
return fd;
}
static void *_selfcare_udp_thread(void *data)
{
prctl(PR_SET_NAME, "selfcare-udpserver");
char buf[MAX_BUFFER];
int len;
int ip;
short port;
while(g_udp_runflag)
{
len = udp_recv_with_ip_info(g_udp_listfd, buf, MAX_BUFFER, &ip, &port);
if(len > 0)
{
g_udp_handle.handle(buf, len);
}
usleep(10);
}
pthread_exit(NULL);
return NULL;
}
void _selfcare_udp_process()
{
char buf[MAX_BUFFER];
int len;
int ip;
short port;
{
len = udp_recv_with_ip_info(g_udp_listfd, buf, MAX_BUFFER, &ip, &port);
if(len > 0)
{
g_udp_handle.handle(buf, len);
}
}
}
static int _selfcare_udp_inittask()
{
pthread_t handle;
g_udp_runflag = 1;
if(pthread_create(&handle, NULL, _selfcare_udp_thread, NULL))
{
printf("Thread create err !!!\n");
return FAILURE;
if ( pthread_detach(handle) )
{
printf("Thread detached err !!!\n");
return FAILURE;
}
}
return SUCCESS;
}
int selfcare_udp_init(void)
{
/* <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD>udp<64>˿<EFBFBD> */
g_udp_listfd = _selfcare_udp_initfd(selfcare_config_get()->udp_local_ip, selfcare_config_get()->udp_local_port);
int ret=SUCCESS;
//ret = _selfcare_udp_inittask();
if(ret != SUCCESS)
{
return ret;
}
return SUCCESS;
}
void selfcare_udp_uninit(void)
{
g_udp_runflag = 0;
}
int selfcare_udp_reg(selfcare_udp_handle_s *handle)
{
memcpy(&g_udp_handle, handle, sizeof(selfcare_udp_handle_s));
return SUCCESS;
}
int selfcare_udp_send(char *buf, short len)
{
return udp_send(g_udp_listfd, selfcare_config_get()->udp_ocs_ip, selfcare_config_get()->udp_ocs_port, buf, len);
}

26
proxy_c/selfcare_udp.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef __SELFCARE_UDP_H__
#define __SELFCARE_UDP_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _selfcare_udp_handle_s
{
int (*handle)(char *buff, int len);
}selfcare_udp_handle_s;
int selfcare_udp_init(void);
void selfcare_udp_uninit(void);
int selfcare_udp_reg(selfcare_udp_handle_s *handle);
int selfcare_udp_send(char *buf, short len);
#ifdef __cplusplus
}
#endif
#endif /* __SELFCARE_UDP_H__ */

View File

@@ -0,0 +1,53 @@
MODULE = client
TYPE = plat
DBUG_FLAGS_ADD =
RELS_FLAGS_ADD =
##Default commonly as below
BUILD = lib
CFG = debug
PLT_LIB = -DDEBUG
APP_LIB =
LIB_ADD =
SRC_PATH = ./src
INC_PATH = ./src/include
PLT_PATH = ../../plat
APP_PATH = ../../mss
OBJ_ADD =
TEST_OBJ_PATH =
PREPROC_CMD =
POSTPROC_CMD =
##---------------------------------------------------------------------##
##--------------------------------------
##
## Make configuration(Customer define)
##
##--------------------------------------
## CCFLAG_SWITCH = on/off => gcc flag show on/off
## COVER_NEED = yes/no => PTF cover report needed
## COVER_REPORT_PATH = [path ] => PTF cover report path
CCFLAG_SWITCH = off
COVER_NEED = no
COVER_REPORT_PATH = ./output
##---------------------------------------------------------------------##
##--------------------------------------
##
## include makefile.rules (Do not change)
##
##--------------------------------------
include ./scripts/Makefile.rules

View File

@@ -0,0 +1,342 @@
##----------------------------------------------------------##
## ##
## Universal Makefile Rules ##
## ##
## Created : Wei Liu 07/03/07 ##
## Revision: [Last]Wei Liu 07/07/07 ##
## ##
##----------------------------------------------------------##
UMAKE_VERSION := V2.0
##-------------------------------------
##
## Work Directory : /usr/local/include
## Default Target : all
##
##-------------------------------------
default: all
.PHONY: all clean rebuild test indent splint doc \
dir config check bk lsbk rmbk unzip umakever usage\
FORCE
.SUFFIXES:
umakever:
@echo "Universal Makefile (UMake) Version: $(UMAKE_VERSION)"
##--------------------------------------
##
## Makefile CFG defination check
##
##--------------------------------------
ifeq "$(MODULE)" ""
$(error Please input the module name (MODULE = )in makefile. )
endif
ifeq "$(CFG)" ""
CFG=debug
$(warnning No configuration specified for CFG. Defaulting to $(MODULE) - debug. )
endif
ifeq "$(BUILD)" ""
BUILD=lib
$(warnning No configuration specified for BUILD. Defaulting to create lib$(MODULE).a. )
endif
ifeq "$(SRC_PATH)" ""
SRC_PATH=.
$(warnning No configuration specified for SRC_PATH. Defaulting to ./. )
endif
COVER_NEED ?= no
PLT_PATH ?= ../../plat
APP_PATH ?= ../../app
TYPE ?= plat
##--------------------------------------
##
## Gcc Flag for debug or release
##
##--------------------------------------
CC := gcc
GCC_CFLAGS := -Wall -MM
AR_LINK := ar -r
RELS_FLAGS_ADD += -DNDEBUG
RELEASE_CFLAGS += -g -Wall -I. $(RELS_FLAGS_ADD) -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient
RELEASE_LINK_CFLAGS = -g $(RELS_FLAGS_ADD) -o
DEBUG_CFLAGS += -g -Wall -rdynamic -DDEBUG -I. $(DBUG_FLAGS_ADD) -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient -I/usr/include/openssl
DEBUG_LINK_CFLAGS = -g -rdynamic -DDEBUG -o
ifeq "$(COVER_NEED)" "yes"
DEBUG_CFLAGS += -fprofile-arcs -ftest-coverage -pg
endif
GCC_CFLAGS=$(DEBUG_CFLAGS)
GCC_LINK_CFLAGS=$(DEBUG_LINK_CFLAGS)
##--------------------------------------
##
## Project setting
##
##--------------------------------------
OBJDIR:=./obj
LIBDIR:=./lib
UTDIR :=./ut
DOCDIR:=./doc
DIRBUILD=$(OBJDIR)
ifeq "$(BUILD)" "lib"
BINDIR:=./bin
OUTFILE=$(LIBDIR)/lib$(MODULE).a
DIRNEED=$(UTDIR) $(DOCDIR)
DIRBUILD+=$(LIBDIR)
else
BINDIR:=.
OUTFILE=$(BINDIR)/$(MODULE)
DIRNEED=
DIRBUILD+=$(BINDIR)
endif
##--------------------------------------
##
## source , object and dependencies files
##
##--------------------------------------
SRC_SUBDIR := $(shell find $(SRC_PATH) -type d)
vpath %.c $(SRC_SUBDIR)
vpath %.o $(OBJDIR)
vpath %.d $(OBJDIR)
SRC_FULL_PATH = $(foreach dir,$(SRC_SUBDIR),$(wildcard $(dir)/*.c))
SRC_FILES = $(foreach file, $(notdir $(SRC_FULL_PATH)) ,$(OBJDIR)/$(file))
COMMON_OBJ = $(SRC_FILES:%.c=%.o)
TEST_OBJ_PATH ?= ../../obj
TEST_OBJ = $(foreach dir,$(TEST_OBJ_PATH),$(wildcard $(dir)/*.o))
OBJ=$(COMMON_OBJ) $(OBJ_ADD)
ALL_OBJ := $(OBJ) $(TEST_OBJ)
##--------------------------------------
##
## Lib setting
##
##--------------------------------------
ifeq "$(COVER_NEED)" "yes"
LIBCOVER=-lgcov
endif
MODULE_PLT_LIB=$(foreach lib,$(PLT_LIB), -L$(PLT_PATH)/$(lib)/lib/ -l$(lib) )
MODULE_PLT_LIB+=-lm
MODULE_APP_LIB=$(foreach lib,$(APP_LIB),-L$(APP_PATH)/$(lib)/lib -l$(lib))
##--------------------------------------
##
## Rules
##
##--------------------------------------
CCFLAG_SWITCH ?= off
CC_COMPILE =$(CC) $(GCC_CFLAGS) -c $< -o $@
CC_PRG_LINK=$(CC) $(GCC_LINK_CFLAGS) $(OUTFILE) $(ALL_OBJ) $(LIBCOVER) $(MODULE_APP_LIB) $(MODULE_PLT_LIB) $(LIB_ADD)
CC_LIB_LINK=$(AR_LINK) $(OUTFILE) $(ALL_OBJ)
COMPILE=$(CC_COMPILE)
PRG_LINK=$(CC_PRG_LINK)
LIB_LINK=$(CC_LIB_LINK)
ifeq "$(BUILD)" "exef"
LINK=$(PRG_LINK)
else
LINK=$(LIB_LINK)
endif
# Build rules
all: preproc start dir $(ALL_OBJ) #prtdebug
@echo Linking :$(OUTFILE)
ifeq "$(CCFLAG_SWITCH)" "off"
@$(LINK)
else
$(LINK)
endif
@$(POSTPROC_CMD)
@echo -e "\n================================================================================\n"
sinclude $(DEPENDS)
release : CC_COMPILE =$(CC) $(RELEASE_CFLAGS) -c $< -o $@
release : CC_PRG_LINK=$(CC) $(RELEASE_LINK_CFLAGS) $(OUTFILE) $(ALL_OBJ) $(MODULE_APP_LIB) $(MODULE_PLT_LIB) $(LIB_ADD)
release : all
##--------------------------------------
##
## Make command to use for dependencies
##
##--------------------------------------
MAKE :=make
RM :=rm
MKDIR :=mkdir
preproc:
@$(PREPROC_CMD)
start:
@echo -e "\n================================================================================\n"
@echo "[Building Project]: $(notdir $(MODULE))"
ifeq "$(CCFLAG_SWITCH)" "off"
@echo "Show Gcc Flags switch = OFF"
endif
prtdebug:
@echo "$(MODULE)-$(BUILD)[$(CFG)] build source file:" "$(SRC_FULL_PATH)"
@echo SRC_SUBDIR: $(SRC_SUBDIR)
@echo SRC_FULL_PATH : $(SRC_FULL_PATH)
@echo SRC_FILES : $(SRC_FILES)
@echo ALL_OBJ : $(ALL_OBJ)
@echo LIB:$(MODULE_PLT_LIB)
@echo PLT_LIB: $(PLT_LIB)
@echo CCFLAG_SWITCH :$(CCFLAG_SWITCH)
config: dir
dir:
@$(foreach dir,$(DIRNEED),$(MKDIR) -p $(DIRNEED) --mode=0777; )
@$(foreach dir,$(DIRBUILD),$(MKDIR) -p $(dir) --mode=0777; )
##--------------------------------------
##
## Make Rebuild and clean
##
##--------------------------------------
ifneq "$(PROJ)" ""
FRIEND_PROJ := $(shell )
endif
jumprebuild:
ifneq "$(PROJ)" ""
@cd $(FRIEND_PROJ); mak rebuild ; cd -
endif
# Rebuild this project
rebuild: jumprebuild cleanall all
# Clean this project and all dependencies
cleanall: clean
# Clean this project
clean:
@echo -e "||--------------------------------------------------------------- "
@echo -e "|| Umake clean gcc , lcov, doxygen generated and temporary files. "
@echo -e "||--------------------------------------------------------------- "
@$(RM) -rf $(OBJDIR) $(OUTFILE) $(COVER_REPORT_PATH) ./doc/doxygen.conf ./doc/html ./doc/latex ./doc/rtf $(foreach dir,$(SRC_SUBDIR),$(dir)/*~)
##--------------------------------------
##
## indent Makefile.indent
##
##--------------------------------------
include Makefile.indent
indent:
@chmod 777 $(SRC_FULL_PATH)
@echo ===================================Indent START=================================
@echo
@echo "[Indent source file ]: $(SRC_FULL_PATH)"
$(call MAKE_INDENT , $(SRC_FULL_PATH))
##--------------------------------------
##
## splint makefile.splint
##
##--------------------------------------
include Makefile.splint
SPLINT_FLAG_SWITCH ?= off
splint:
@chmod 777 $(SRC_FULL_PATH)
@echo =================================Splint START==================================
@echo
ifeq "$(SPLINT_FLAG_SWITCH)" "on"
@echo "[Splint flags ]: $(SPLINT_FLAGS)"
endif
@echo "[Lint Clean Project]: $(notdir $(MODULE))"
$(call MAKE_SPLINT, $(SRC_FULL_PATH))
##--------------------------------------
##
## doc Makefile.doxygen
##
##--------------------------------------
include Makefile.doxygen
doc:
@chmod 777 $(SRC_FULL_PATH)
@echo ==================================Doxygen START=================================
@echo
$(call MAKE_DOC, $(SRC_FULL_PATH))
##--------------------------------------
##
## backup Makefile.backup
##
##--------------------------------------
include Makefile.backup
##--------------------------------------
##
## cov Makefile.cov
##
##--------------------------------------
include Makefile.cov
##--------------------------------------
##
## usage Makefile.usage
##
##--------------------------------------
include Makefile.usage
##--------------------------------------
##
## Make dependencies
##
##--------------------------------------
$(OBJDIR)/%.d:%.c
@$(CC) $< -MM -MD -o $@
$(OBJDIR)/%.o:%.c
ifeq "$(CCFLAG_SWITCH)" "off"
@echo -e "building: $(notdir $@) \t\t\t\t please wait ..."
@$(COMPILE)
else
$(COMPILE)
endif
DEPENDS=$(COMMON_OBJ:.o=.d)
##--------------------------------------
##
## Make force
##
##--------------------------------------
FORCE:

View File

@@ -0,0 +1,492 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "./include/client.h"
#define CLIENT_CFG "./conf/smcli_client.cfg"
_client_param_t client_cfg;
static int smcli_cmd_res=0;
static char smcli_result[256];
int client_read_conf()
{
char s[80],s1[80];
int len;
unsigned char conf_state=0xFF;
FILE *fpConf;
memset(&client_cfg, 0x00, sizeof(_client_param_t));
fpConf = fopen(CLIENT_CFG,"rb");
if(fpConf == NULL)
{
return 0;
}
strcpy(s,"");
strcpy(s1,"");
while(fgets(s,1024,fpConf) !=(char *)0)
{
if( (int *)strchr(s,'#') !=NULL) continue;
if( !strlen(s) ) continue;
len = strlen(s);
if(len < 2) continue;
if(s[len-1] == 0x0d ||s[len-1] == 0x0a)
{
if(s[len-2] == 0x0d ||s[len-2] == 0x0a)
{
s[len-2] = 0;
len -= 2;
}
else
{
s[len-1] = 0;
len -= 1;
}
}
if(!strncasecmp(s,"[EMS]",5))
{
conf_state = 0;
continue;
}
else if(!strncasecmp(s,"[HSS]",5))
{
conf_state = 1;
continue;
}
else if(!strncasecmp(s,"[AUC]",5))
{
conf_state = 2;
continue;
}
else if(!strncasecmp(s,"[VMS]",5))
{
conf_state = 3;
continue;
}
else if(!strncasecmp(s,"[Provision]",11))
{
conf_state = 4;
continue;
}
switch(conf_state)
{
case 0:
if(strncasecmp(s,"ems0_ip=",8)==0)
{
client_cfg.ems_servers.host0_enable = 1;
strcpy(client_cfg.ems_servers.host0_ip, &s[8]);
//host_ip = inet_addr(&s[8]);
}
else if(strncasecmp(s,"ems0_port=",10)==0)
{
client_cfg.ems_servers.host0_port = atoi(&s[10]);
}
else if(strncasecmp(s,"ems1_ip=",8)==0)
{
client_cfg.ems_servers.host1_enable = 1;
strcpy(client_cfg.ems_servers.host1_ip, &s[8]);
//host_ip = inet_addr(&s[8]);
}
else if(strncasecmp(s,"ems1_port=",10)==0)
{
client_cfg.ems_servers.host1_port = atoi(&s[10]);
}
else if(strncasecmp(s,"user_name=",10)==0)
{
strcpy(client_cfg.ems_servers.user_name, &s[10]);
}
else if(strncasecmp(s,"password=", 9)==0)
{
strcpy(client_cfg.ems_servers.password, &s[9]);
}
else if(strncasecmp(s,"connect_hss=",12)==0)
{
client_cfg.connect_configured[SYS_T_HSS] = 1;
strcpy(client_cfg.connect_command[SYS_T_HSS], &s[12]);
}
else if(strncasecmp(s,"connect_auc=",12)==0)
{
client_cfg.connect_configured[SYS_T_AUC] = 1;
strcpy(client_cfg.connect_command[SYS_T_AUC], &s[12]);
}
else if(strncasecmp(s,"connect_vms=",12)==0)
{
client_cfg.connect_configured[SYS_T_VMS] = 1;
strcpy(client_cfg.connect_command[SYS_T_VMS], &s[12]);
}
break;
case 1:
strcpy(client_cfg.cli_command[SYS_T_HSS], s);
break;
case 2:
strcpy(client_cfg.cli_command[SYS_T_AUC], s);
break;
case 3:
strcpy(client_cfg.cli_command[SYS_T_VMS], s);
break;
case 4:
if(strncasecmp(s,"enable", 6) == 0)
{
client_cfg.provsioning_flag = 1;
}
break;
}
}
fclose(fpConf);
return 1;
}
int rest_provsioning_enabled()
{
return client_cfg.provsioning_flag;
}
int smcli_reset_result()
{
smcli_cmd_res = 0;
}
int smcli_get_result(char* result_des)
{
if(smcli_cmd_res != 0)
strcpy(result_des, smcli_result);
return smcli_cmd_res;
}
int smcli_connect_ems()
{
if(client_cfg.ems_servers.host0_enable)
tcp_connect_server(client_cfg.ems_servers.host0_ip, client_cfg.ems_servers.host0_port);
else if(client_cfg.ems_servers.host1_enable)
tcp_connect_server(client_cfg.ems_servers.host1_ip, client_cfg.ems_servers.host1_port);
return 1;
}
void smcli_send_user_name_pwd(int flag)
{
char user_name[128];
char password[128];
if(flag == 0)
{
sprintf(user_name, "%s\r\n", client_cfg.ems_servers.user_name);
tcp_send_msg(user_name, strlen(user_name));
}
else
{
sprintf(password, "%s\r\n", client_cfg.ems_servers.password);
tcp_send_msg(password, strlen(password));
}
}
void smcli_connect_cn_nodes(int sys_type)
{
char command[128];
sprintf(command, "%s\r\n", client_cfg.connect_command[sys_type]);
tcp_send_msg(command, strlen(command));
}
void smcli_send_command(char *command)
{
tcp_send_msg(command, strlen(command));
smcli_reset_result();
}
void crm_create_vms_account(char *number)
{
char cli_command[1024];
sprintf(cli_command,"create vmsSubscriber -msisdn %s", number);
smcli_send_command(cli_command);
}
void crm_prov_hlr_auc_vms_account(char sub_data[][1024])
{//PRE_ID, IMSI, SERVICE_NBR, KI, OPC, ACCT_TYPE,CUST_ID, ACCT_ID, PRD_INST_ID, MOBILE_TYPE, VMS_FLAG
char cli_command[1024];
if(1)//HLR
{
sprintf(cli_command,"create subscriber -imsi %s -msisdn %s -eps_user_tpl def_eps -impi %s@ims.mnc010.mcc505.3gppnetwork.org",
sub_data[2], sub_data[3], sub_data[2]);
smcli_send_command(cli_command);
}
sleep(2);
if(1)
{
if(sub_data[5][0] == 0)
sprintf(cli_command,"create aucSubscriber -imsi %s -ki %s", sub_data[2], sub_data[4]);
else
sprintf(cli_command,"create aucSubscriber -imsi %s -ki %s -opc %s", sub_data[2], sub_data[4], sub_data[5]);
smcli_send_command(cli_command);
}
sleep(2);
if(atoi(sub_data[10]))//VMS enabled
{
crm_create_vms_account(sub_data[3]);
}
}
int smcli_link_fsm()
{
u_char recvbuf[1024];
int len = 0;
int state = 0;
state = client_cfg.smcli_link_state;
switch(state)
{
case 0: //do nothing
break;
case 1:
len = tcp_recv_msg(recvbuf);
if(len>0)
{
if(strstr(recvbuf, "username:"))
{
smcli_send_user_name_pwd(0);
}
//if(strstr(recvbuf, "Welcome to"))
client_cfg.smcli_link_state = 2;
}
break;
case 2:
len = tcp_recv_msg(recvbuf);
if(len>0)
{
if(strstr(recvbuf, "username:"))
{
smcli_send_user_name_pwd(0);
}
else if(strstr(recvbuf,"password:"))
{
smcli_send_user_name_pwd(1);
client_cfg.smcli_link_state = 3;
client_cfg.smcli_verified = 1;
}
else if(strstr(recvbuf, "Login incorrect"))
{
printf("error username/password\r\n");
exit(128);
}
}
break;
case 3:
len = tcp_recv_msg(recvbuf);
if(len>0)
{
if(strstr(recvbuf,"CLI>")) //login succeed
{
client_cfg.smcli_link_state = 10;
}
}
break;
case 10:
if(client_cfg.connect_configured[SYS_T_HSS])
{
smcli_connect_cn_nodes(SYS_T_HSS);
client_cfg.smcli_link_state = 11;
}
else
{
client_cfg.smcli_link_state = 20;
}
break;
case 11:
len = tcp_recv_msg(recvbuf);
if(len>0)
{
if(strstr(recvbuf,"Login incorrec"))
{
printf("connect hlr failed\r\n");
}
client_cfg.smcli_link_state = 12;
}
break;
case 12:
len = tcp_recv_msg(recvbuf);
if(len>0)
{
if(strstr(recvbuf,"CLI>")) //input mode
{
client_cfg.smcli_link_state = 20;
}
}
break;
case 20:
if(client_cfg.connect_configured[SYS_T_AUC])
{
smcli_connect_cn_nodes(SYS_T_AUC);
client_cfg.smcli_link_state = 21;
}
else
{
client_cfg.smcli_link_state = 30;
}
break;
case 21:
len = tcp_recv_msg(recvbuf);
if(len>0)
{
if(strstr(recvbuf,"Login incorrec") )
{
printf("connect auc failed\r\n");
}
client_cfg.smcli_link_state = 22;
}
break;
case 22:
len = tcp_recv_msg(recvbuf);
if(len>0)
{
if(strstr(recvbuf,"CLI>")) //input mode
{
client_cfg.smcli_link_state = 30;//100;
}
}
break;
case 30:
if(client_cfg.connect_configured[SYS_T_VMS])
{
smcli_connect_cn_nodes(SYS_T_VMS);
client_cfg.smcli_link_state = 31;
}
else
{
client_cfg.smcli_link_state = 100;
}
break;
case 31:
len = tcp_recv_msg(recvbuf);
if(len>0)
{
if(strstr(recvbuf,"Login incorrec") )
{
printf("connect vms failed\r\n");
}
client_cfg.smcli_link_state = 32;
}
break;
case 32:
len = tcp_recv_msg(recvbuf);
if(len>0)
{
if(strstr(recvbuf,"CLI>")) //input mode
{
client_cfg.smcli_link_state = 100;
}
}
break;
case 100://normal state, can handle cli command
len = tcp_recv_msg(recvbuf);
if(len>6)
{
if(strstr(recvbuf,"Login incorrect"))
{
printf("smcli link is discounneted\r\n");
client_cfg.smcli_link_state = 1;
smcli_cmd_res = 2;
strcpy(smcli_result, recvbuf);
}
else if(strstr(recvbuf, "success"))
{
smcli_cmd_res = 1;
strcpy(smcli_result, recvbuf);
}
else
{
smcli_cmd_res = 2;
strcpy(smcli_result, recvbuf);
}
}
break;
}
return state;
}
void smlci_connection_check()
{
if(client_cfg.client_connected == 1)
return;
if(is_tcp_connected()>=0)
{
client_cfg.client_connected = 1;
client_cfg.smcli_link_state = 1;
}
}
void smcli_connection_is_broken()
{
client_cfg.client_connected = 0;
client_cfg.smcli_link_state = 0;
client_cfg.smcli_verified = 0;
}
int smcli_client_thread(void *param)
{
static int smcli_timer= 0;
client_read_conf();
smcli_connect_ems();
while(1)
{
if(smcli_timer % 10000)
{
tcp_check_connection();
smlci_connection_check();
smcli_timer = 0;
}
smcli_link_fsm();
smcli_timer ++;
usleep(10000);
}
return 1;
}

View File

@@ -0,0 +1,50 @@
#ifndef _SMCLI_CLIENT_H
#define _SMCLI_CLIENT_H
#define CLI_COMMAND_LEN 8192
#define CONNECT_COMMAND_LEN 128
typedef enum ACCT_TYPE
{
ACCT_T_MOBILE,
ACCT_T_PSTN,
ACCT_T_ADSL,
}_ACCT_TYPE;
typedef enum SYS_TYPE
{
SYS_T_EMS,
SYS_T_HSS,
SYS_T_AUC,
SYS_T_VMS,
SYS_T_PSTN,
SYS_T_ADSL,
SYS_T_MAX,
}_SYS_TYPE;
typedef struct server_param_t
{
u_char host0_enable;
char host0_ip[16];
u_short host0_port;
u_char host1_enable;
char host1_ip[16];
u_short host1_port;
char user_name[16];
char password[16];
}server_param_t;
typedef struct client_param_t
{
int client_connected;
int smcli_verified;
int smcli_link_state;
int provsioning_flag;
server_param_t ems_servers;
char connect_configured[SYS_T_MAX];
char connect_command[SYS_T_MAX][CONNECT_COMMAND_LEN];
char cli_command[SYS_T_MAX][CLI_COMMAND_LEN];
}_client_param_t;
#endif

View File

@@ -0,0 +1,143 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <malloc.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUF_SIZE 1024
#define RES_LENGTH 10240
static int client_fd=0;
static int client_connect_flag = -1;
static char server_ip[16];
static short server_port;
int connect_socket(char * server,int serverPort);
int send_msg(int sockfd,char * sendBuff);
char * recv_msg(int sockfd);
int close_socket(int sockfd);
int init_socketfd()
{
int sockfd = -1;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
herror("Init socket error!");
}
return sockfd;
}
void tcp_init_client_fd()
{
client_fd = init_socketfd();
}
void tcp_connect_server(char *ip, u_short port)
{
tcp_init_client_fd();
strcpy(server_ip, ip);
server_port = port;
client_connect_flag = connect_socket(ip, port);
}
int is_tcp_connected()
{
return client_connect_flag;
}
/* * ********************************************************/
int connect_socket(char * server,int serverPort)
{
struct sockaddr_in addr;
struct hostent * phost;
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(serverPort);
addr.sin_addr.s_addr = inet_addr(server);
if(addr.sin_addr.s_addr == INADDR_NONE){
phost = (struct hostent*)gethostbyname(server);
if(phost==NULL){
herror("Init socket s_addr error!");
return -1;
}
addr.sin_addr.s_addr =((struct in_addr*)phost->h_addr)->s_addr;
}
if(connect(client_fd,(struct sockaddr*)&addr, sizeof(addr))<0)
{
// perror("Connect server fail!");
return -1; //0<><30>ʾ<EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD>-1<><31>ʾʧ<CABE><CAA7>
}
else
return 0;
}
int tcp_send_msg( u_char *sendbuf, short len)
{
int sendSize=0;
if((sendSize=send(client_fd,sendbuf,len,MSG_NOSIGNAL))<=0){
close_socket(client_fd);
herror("Send msg error!");
return -1;
}
return sendSize;
}
int tcp_recv_msg(u_char *recvbuf)
{
int recLenth=0;
if(( recLenth=recv(client_fd,recvbuf, BUF_SIZE,0))==-1 )
{
close_socket(client_fd);
return -1;
}
if(recLenth == 0)
{
close_socket(client_fd);
return -1;
}
if( recLenth>0)
recvbuf[recLenth] = 0;
return recLenth;
}
int tcp_check_connection()
{
if(client_connect_flag == -1)
{
client_connect_flag = connect_socket(server_ip, server_port);
}
return client_connect_flag;
}
/**************************************************
*<2A>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD>
* **********************************************/
int close_socket(int sockfd)
{
client_connect_flag = -1;
close(sockfd);
smcli_connection_is_broken();
tcp_init_client_fd();
return 0;
}

122
proxy_c/sock_if.c Normal file
View File

@@ -0,0 +1,122 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <net/ethernet.h>
#include <netinet/ether.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <net/if.h>
#include <linux/sockios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define INET_UDP 0
int init_socket(unsigned int local_addr, short local_port, char stype, int noblock_flag)
{
struct sockaddr_in sin_addr;
int on=1, sockfd;
memset((void *)&sin_addr,0x00,sizeof(struct sockaddr_in));
sin_addr.sin_family = AF_INET;
sin_addr.sin_port = htons(local_port);
if(local_addr == 0)
sin_addr.sin_addr.s_addr = htonl(INADDR_ANY);
else
sin_addr.sin_addr.s_addr = local_addr;
//sin_addr.sin_addr.s_addr = htonl(local_addr);
bzero((void *)&(sin_addr.sin_zero),8);
if(stype == INET_UDP)
sockfd = socket(AF_INET,SOCK_DGRAM,0);
else
sockfd = socket(AF_INET,SOCK_STREAM,0);
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
if(stype != INET_UDP)
{
setsockopt(sockfd,IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
setsockopt(sockfd,SOL_TCP, TCP_NODELAY, &on, sizeof(on));
}
if(noblock_flag)
fcntl(sockfd,F_SETFL,O_NONBLOCK);
bind(sockfd,(struct sockaddr*)&sin_addr,sizeof(struct sockaddr));
// listen(sockfd,1);
return sockfd;
}
int setnodelay(int fd)
{
int on=1;
setsockopt(fd,IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
setsockopt(fd,SOL_TCP, TCP_NODELAY, &on, sizeof(on));
return 1;
}
void set_peer_addr(struct sockaddr_in *peer_addr, char *peer_ip,short peer_port)
{
peer_addr->sin_family = AF_INET;
peer_addr->sin_port = htons(peer_port);
peer_addr->sin_addr.s_addr = inet_addr(peer_ip);
bzero((void *)&(peer_addr->sin_zero),8);
}/*set_config*/
int udp_send(int fd, int peer_ip, short peer_port, char *buf, short len)
{
struct sockaddr_in sin_addr;
int ret;
memset(&sin_addr, 0, sizeof(struct sockaddr));
sin_addr.sin_addr.s_addr = peer_ip;
sin_addr.sin_port = htons(peer_port);
ret = sendto(fd, buf, len, 0, (struct sockaddr*)&sin_addr, sizeof(struct sockaddr));
return ret;
}
int udp_recv(int fd, char *buf, short MAX_LEN)
{
int len, addr_len;
struct sockaddr_in sin_addr;
addr_len = sizeof(struct sockaddr);
memset(&sin_addr, 0, addr_len);
len = recvfrom(fd, buf, MAX_LEN, 0, (struct sockaddr*)&sin_addr, (socklen_t*)&addr_len);
if(len < 0)
return 0;
return len;
}
int udp_recv_with_ip_info(int fd, char *buf, short MAX_LEN, int *peer_ip, short *peer_port)
{
int len, addr_len;
struct sockaddr_in sin_addr;
addr_len = sizeof(struct sockaddr);
memset(&sin_addr, 0, addr_len);
len = recvfrom(fd, buf, MAX_LEN, 0, (struct sockaddr*)&sin_addr, (socklen_t*)&addr_len);
if(len < 0)
return 0;
*peer_ip = sin_addr.sin_addr.s_addr;
*peer_port = htons(sin_addr.sin_port);
return len;
}

98
proxy_c/tcp/Makefile Normal file
View File

@@ -0,0 +1,98 @@
##----------------------------------------------------------##
## ##
## Universal Makefile for module template : V1.6.3 ##
## ##
## Created : Wei Liu 07/04/11 ##
## Revision: [Last]Wei Liu 07/07/07 ##
## ##
##----------------------------------------------------------##
##---------------------------------------------------------------------##
##--------------------------------------
##
## Project correlation(Customer define)
##
##--------------------------------------
## MODULE= [Module Name]
## TYPE = app/plat => Module Type
## DBUG_FLAGS_ADD = [Module Define Gcc Flags for Debug ]
## DBUG_FLAGS_ADD = [Module Define Gcc Flags for Release]
## BUILD = lib/exef => Output file format
## CFG = debug/release => Build Configuration
## SRC_PATH = [Source file path]
## INC_PATH = [Include file path]
## APP_PATH = [App Module path]
## PLT_PATH = [Plat Module path]
## PLT_LIB = [Needed plat lib for Link] => just for test or wxc2main
## APP_LIB = [Needed app lib for Link] => just for test or wxc2main
## LIB_ADD = [Needed Extend lib for Link] => just for test or wxc2main
## PLT_LIB e.g. = haepub fsm mng proto kernel aif mgc mgcp sip rtp \
## 8ecp bicc smpp xapp tcap mtp3 m2ua \
## snmp iptrans debug sccp public
##
## APP_LIB e.g. = msc vlr ssf hlr ae pps mnp smsc vms aas
## LIB_ADD e.g. = -liba3a8 -lm
## OBJ_ADD = [Extend third party object files needed]
## TEST_OBJ_PATH = [module object files Path for test ] => just for test
##---------------------------------------------------------------------##
MODULE = tcp
TYPE = plat
DBUG_FLAGS_ADD = -DDEBUG
RELS_FLAGS_ADD =
##Default commonly as below
BUILD = lib
CFG = debug
PLT_LIB =
APP_LIB =
LIB_ADD =
SRC_PATH = ./src
INC_PATH = ./src/include
PLT_PATH = ../../plat
APP_PATH = ../../mss
OBJ_ADD =
TEST_OBJ_PATH =
PREPROC_CMD =
POSTPROC_CMD =
##---------------------------------------------------------------------##
##--------------------------------------
##
## Make configuration(Customer define)
##
##--------------------------------------
## CCFLAG_SWITCH = on/off => gcc flag show on/off
## COVER_NEED = yes/no => PTF cover report needed
## COVER_REPORT_PATH = [path ] => PTF cover report path
CCFLAG_SWITCH = off
COVER_NEED = no
COVER_REPORT_PATH = ./output
##---------------------------------------------------------------------##
##--------------------------------------
##
## include makefile.rules (Do not change)
##
##--------------------------------------
include Makefile.rules

View File

@@ -0,0 +1,32 @@
#ifndef _TCP_IF_H_
#define _TCP_IF_H_
#include "tcp_inc.h"
#include "tcp_port.h"
#define TCP_MAX_NUM_OF_SAP 4
#define TCP_MAX_USER_NAME_LEN 16
typedef int (*tcp_recv_callback)(WORD usr_port, BYTE *pdata, WORD datalen);
typedef struct _tcp_sap_t
{
BYTE id;
char name[TCP_MAX_USER_NAME_LEN];
tcp_recv_callback recv_cb;
}tcp_sap_t;
extern void tcp_init(void);
extern void tcp_timer(void);
extern int tcp_bind(tcp_sap_t *ptr_sap);
extern int tcp_unbind(tcp_sap_t *ptr_sap, BYTE index);
extern tcp_sap_t *tcp_sap_get_by_index(int index);
//rtp_port.c
extern int tcp_port_alloc_port(int sap_id, WORD usr_port, tcp_session_t *pSess);
extern int tcp_port_release_port(int sap_id, WORD usr_port, WORD pid);
extern int tcp_send(int sap_id, WORD usr_port, WORD pid, BYTE *payload, WORD len);
extern tcp_session_t *tcp_port_update_sess(int sap_id, WORD usr_port, WORD pid, tcp_session_t *ptr_sess);
#endif

View File

@@ -0,0 +1,129 @@
#ifndef _TCP_INC_H_
#define _TCP_INC_H_
//#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <math.h>
#include <netdb.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <termio.h>
#include <time.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#include <memory.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/io.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#ifndef _T_BYTE
#define _T_BYTE
typedef unsigned char BYTE;
#endif
#ifndef _T_WORD
#define _T_WORD
typedef unsigned short WORD;
#endif
#ifndef _T_DWORD
#define _T_DWORD
typedef unsigned long DWORD;
#endif
#ifndef _T_ULL
#define _T_ULL
typedef unsigned long long ull;
#endif
#ifndef _T_U8
#define _T_U8
typedef unsigned char u8;
#endif
#ifndef _T_U16
#define _T_U16
typedef unsigned short u16;
#endif
#ifndef _T_U32
#define _T_U32
typedef unsigned long u32;
#endif
#ifndef _T_U64
#define _T_U64
typedef unsigned long long u64;
#endif
#ifndef _T_BOOL
#define _T_BOOL
typedef int BOOL;
#endif
#ifndef SUCCESS
#define SUCCESS (0)
#endif
#ifndef FAILURE
#define FAILURE (-1)
#endif
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef YES
#define YES (1)
#endif
#ifndef NO
#define NO (0)
#endif
#ifndef ERROR
#define ERROR (-1)
#endif
#ifndef EMPTY
#define EMPTY (0)
#endif
#ifndef NULL
#define NULL 0
#endif
#define BUFSIZE 8192
#define MAXBUFLEN 8192
#define MAXLINE 8192
#endif

View File

@@ -0,0 +1,59 @@
#ifndef _TCP_PORT_H_
#define _TCP_PORT_H_
#include "tcp_inc.h"
#define TCP_MAX_NUM_OF_PORT 16
#define TCP_MAX_RECV_MSG_LEN 1500
#define TCP_MAX_SEND_MSG_LEN 1500
#define TCP_MAX_PAYLOAD_SIZE 1350
#define TCP_MAX_RECV_BUF_LEN 8192
#define TCP_MAX_RECV_COUNT 4
typedef struct _tcp_header_t
{
BYTE ver; // version
BYTE pt; // payload type
WORD sn; // sequence number
DWORD timestamp;
DWORD ssrc; //synchronization src
}tcp_header_t;
typedef struct _tcp_session_t
{
DWORD src_ip;
WORD src_port;
DWORD dst_ip;
WORD dst_port;
BYTE bServer; // tcp client: 0; server: 1;
}tcp_session_t;
typedef struct _tcp_port_t
{
BYTE flag;
int index;
BYTE status;
int timer;
int retry_num;
WORD usr_port;
int fd;
int cli_fd;
BYTE rv_buf[TCP_MAX_RECV_BUF_LEN];
int buf_len;
int connected_num;
int disconnect_num;
int sent_fail_num;
tcp_session_t sess;
struct _tcp_sap_t *ptr_sap;
}tcp_port_t;
extern void tcp_port_init(WORD id);
extern void tcp_port_recv_msg(void);
extern int tcp_link_fsm();
int get_tcp_sess(WORD hdlPort, tcp_session_t *sess);
#endif

95
proxy_c/tcp/src/tcp_if.c Normal file
View File

@@ -0,0 +1,95 @@
/*
*
*/
#include "./include/tcp_if.h"
#include "./include/tcp_port.h"
static tcp_sap_t tcp_sap[TCP_MAX_NUM_OF_SAP];
static void tcp_sap_init(tcp_sap_t *ptr_sap, BYTE index)
{
if((ptr_sap == NULL) || (index >= TCP_MAX_NUM_OF_SAP))
{
return;
}
ptr_sap->id = index;
strcpy(ptr_sap->name, "\0");
ptr_sap->recv_cb = NULL;
}
tcp_sap_t *tcp_sap_get_by_index(int index)
{
if(index < 0 || index >= TCP_MAX_NUM_OF_SAP)
return NULL;
return &tcp_sap[index];
}
void tcp_init(void)
{
WORD i;
for(i = 0; i < TCP_MAX_NUM_OF_SAP; i++)
{
tcp_sap_init(&tcp_sap[i], (BYTE)i);
}
for(i = 0; i < TCP_MAX_NUM_OF_PORT; i++)
{
tcp_port_init(i);
}
return;
}
void tcp_timer(void)
{
tcp_link_fsm();
tcp_port_recv_msg();
}
int tcp_bind(tcp_sap_t *ptr_sap)
{
BYTE i;
tcp_sap_t *ptr_tmp = NULL;
if((ptr_sap == NULL) || (ptr_sap->recv_cb == NULL))
{
return -1;
}
for(i = 0; i < TCP_MAX_NUM_OF_SAP; i++)
{
ptr_tmp = &tcp_sap[i];
if(ptr_tmp->recv_cb != NULL)
{
continue;
}
memcpy((BYTE*)ptr_tmp, ptr_sap, sizeof(tcp_sap_t));
ptr_tmp->id = i;
ptr_tmp->name[TCP_MAX_USER_NAME_LEN-1] = '\0';
return i;
}
return -1;
}
int tcp_unbind(tcp_sap_t *ptr_sap, BYTE index)
{
if((ptr_sap == NULL) || (index >= TCP_MAX_NUM_OF_SAP))
{
return -1;
}
if(ptr_sap->id != index)
{
return -1;
}
tcp_sap_init(ptr_sap, index);
return 0;
}

867
proxy_c/tcp/src/tcp_port.c Normal file
View File

@@ -0,0 +1,867 @@
/*
* tcp port
*/
#include "./include/tcp_port.h"
#include "./include/tcp_if.h"
#define TCP_F_BB1 0x7E // Begin: The first byte
#define TCP_F_BB2 0xA5 // Begin: The second byte
#define TCP_F_EB1 0x7E // End: The first byte
#define TCP_F_EB2 0x0D // End: The second byte
#define TCP_F_INF_BEGIN_FLAG_LEN 2 // length of begin flag
#define TCP_F_INF_MSG_LEN_LEN 2 // length of msg length field
//#define TCP_F_INF_MSG_TYPE_LEN 2 // length of msg type
#define TCP_F_INF_END_FLAG_LEN 2 // length of end flag
#define TCP_F_INF_HEAD_LEN 4 // length of format begin+lengthField
#define TCP_F_INF_ALL_LEN 6 // total length of format
#define TCP_IsfBegin(f1,f2) ((f1==TCP_F_BB1) && (f2==TCP_F_BB2))// Begin flag of msg
#define TCP_IsfEnd(f1,f2) ((f1==TCP_F_EB1) && (f2==TCP_F_EB2))// End flag of msg
#define TCP_MSG_DATA 1 // Data
#define TCP_MSG_HB 2 // HB
#define TCP_MSG_HB_ACK 3 // HB_ACK
#define TCP_TIMER_1_SEC (100) // 10ms * 100
#define TCP_TIMER_WAIT_CONNECT (5) // 50ms
#define TCP_TIMER_REINIT (3*TCP_TIMER_1_SEC) // 3 Sec
#define TCP_TIMER_RECONNECT (3*TCP_TIMER_1_SEC) // 3 Sec
#define TCP_TIMER_HB (3*TCP_TIMER_1_SEC) // 3 Sec
#define TCP_MAX_RETRY_NUM (3)
typedef enum
{
TCP_STATUS_NULL,
TCP_STATUS_INITING,
TCP_STATUS_INITED,
TCP_STATUS_CONNECTING,
TCP_STATUS_TESTING,
TCP_STATUS_CONNECTED,
TCP_STATUS_MAX,
}e_tcp_status;
typedef struct
{
WORD usMsgId; // Tcp internal message Id, 1: Data; 2: HB; 3: HB_ACK
WORD usPlLen; // Payload length
DWORD param1; // App param1, optional
DWORD param2; // App param2, optional
DWORD param3; // App param3, optional
} tcp_head_t;
static char tcp_status_str[TCP_STATUS_MAX][64] = {\
"null", \
"initing", \
"inited", \
"connecting", \
"testing", \
"connected"
};
static tcp_port_t tcp_port[TCP_MAX_NUM_OF_PORT];
void tcp_port_init(WORD id)
{
tcp_port_t *ptr_port = NULL;
if(id >= TCP_MAX_NUM_OF_PORT)
{
return;
}
ptr_port = &tcp_port[id];
memset((BYTE*)ptr_port, 0, sizeof(tcp_port_t));
ptr_port->fd = -1;
ptr_port->cli_fd = -1;
ptr_port->ptr_sap = NULL;
return;
}
long tcp_str_to_uip(char *src_ip)
{
return inet_addr(src_ip);
}
static tcp_port_t *tcp_port_get_by_index(WORD index)
{
if (index >= TCP_MAX_NUM_OF_PORT)
{
return NULL;
}
return &tcp_port[index];
}
static int tcp_port_get_unused_pid(void)
{
static WORD index = 0;
WORD id, i;
tcp_port_t *ptr_port = NULL;
i = index;
do
{
id = i;
ptr_port = &tcp_port[id];
if(++i >= TCP_MAX_NUM_OF_PORT)
{
i = 0;
}
if(ptr_port->flag != FALSE)
{
continue;
}
index = i;
return id;
}while(i != index);
return -1;
}
static int tcp_init_socket(tcp_session_t *pSess)
{
int sock = -1, on = 1, timeout = 20;
struct sockaddr_in srcaddr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
return -1;
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
{
close(sock);
return -2;
}
//if (bServer)
{
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &timeout, sizeof(timeout)) != 0)
{
return -3;
}
}
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)
{
close(sock);
return -4;
}
memset( (void *)&srcaddr, 0, sizeof(srcaddr) );
srcaddr.sin_family = AF_INET;
srcaddr.sin_addr.s_addr = pSess->src_ip;//htonl( INADDR_ANY );
srcaddr.sin_port = htons(pSess->src_port);
if (bind(sock, (struct sockaddr *)&srcaddr, sizeof(srcaddr)) < 0)
{
close(sock);
return -5;
}
if (pSess->bServer)
{
// change to passive socket
if (listen(sock, 5))
{
close(sock);
return -6;
}
}
return sock;
}
static int tcp_set_status(tcp_port_t *ptr_port, WORD new_status)
{
if ((ptr_port == NULL) || (ptr_port->status == new_status) || (new_status >= TCP_STATUS_MAX))
{
return -1;
}
if (ptr_port->status == TCP_STATUS_CONNECTED)
{
ptr_port->disconnect_num++;
}
ptr_port->status = new_status;
return 0;
}
static int tcp_connect(tcp_port_t *ptr_port)
{
int ret;
struct sockaddr_in serv_addr;
if (ptr_port == NULL)
{
return -1;
}
/* set family to internet */
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = ptr_port->sess.dst_ip;
serv_addr.sin_port = htons(ptr_port->sess.dst_port);
ret = connect(ptr_port->fd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr));
if (ret < 0)
{
if (errno == EINPROGRESS)
{
return 0;
}
/*if((106 == errno)//Transport endpoint is already connected
||(89 == errno))//Destination address required
{
return 0;
}*/
return -1;
}
else
{
return 0;
}
}
static int tcp_check_conn(tcp_port_t *ptr_port)
{
int client_sock;
int timeout = 20;
struct sockaddr_in remote;
socklen_t len = sizeof(struct sockaddr_in);
tcp_session_t *pSess = NULL;
if (ptr_port == NULL)
{
return -1;
}
pSess = &ptr_port->sess;
// fill with zero terms
memset(&remote, 0, sizeof( remote));
// wait for connetion
client_sock = accept(ptr_port->fd, (struct sockaddr *)&(remote), &len);
if ( client_sock < 0 )
{
return -1;
}
if ((remote.sin_port != htons(pSess->dst_port)) || (remote.sin_addr.s_addr != pSess->dst_ip))
{
close(client_sock);
return -2;
}
if (setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, &timeout, sizeof(timeout)) != 0)
{
//return -3;
}
if (fcntl(client_sock, F_SETFL, O_NONBLOCK) < 0)
{
//return -4;
}
ptr_port->cli_fd = client_sock;
return client_sock;
}
int tcp_port_alloc_port(int sap_id, WORD usr_port, tcp_session_t *pSess)
{
int pid;
tcp_port_t *ptr_port = NULL;
tcp_sap_t *ptr_sap = NULL;
if(pSess == NULL || pSess->src_ip == 0 || pSess->src_port == 0 \
|| pSess->dst_ip == 0 || pSess->dst_port == 0)
{
return -1;
}
if((ptr_sap = tcp_sap_get_by_index(sap_id)) == NULL)
{
return -1;
}
if((pid = tcp_port_get_unused_pid()) < 0)
{
return -1;
}
ptr_port = &tcp_port[pid];
if((ptr_port->fd = tcp_init_socket(pSess)) < 0)
{
return -1;
}
ptr_port->flag = TRUE;
ptr_port->index = pid;
tcp_set_status(ptr_port, TCP_STATUS_INITED);
ptr_port->timer = 5;
ptr_port->retry_num = 0;
ptr_port->ptr_sap = ptr_sap;
ptr_port->usr_port = usr_port;
ptr_port->cli_fd = -1;
ptr_port->buf_len = 0;
ptr_port->connected_num = 0;
ptr_port->disconnect_num = 0;
ptr_port->sent_fail_num = 0;
memcpy(&ptr_port->sess, pSess, sizeof(tcp_session_t));
return pid;
}
int tcp_port_release_port(int sap_id, WORD usr_port, WORD pid)
{
tcp_sap_t *ptr_sap = NULL;
tcp_port_t *ptr_port = NULL;
if((ptr_sap = tcp_sap_get_by_index(sap_id)) == NULL)
{
return -1;
}
if((ptr_port = tcp_port_get_by_index(pid)) == NULL)
{
return -1;
}
if((ptr_port->ptr_sap != ptr_sap) || (ptr_port->usr_port != usr_port))
{
return -1;
}
if(ptr_port->fd >= 0)
{
close(ptr_port->fd);
}
tcp_port_init(pid);
return 0;
}
tcp_session_t *tcp_port_update_sess(int sap_id, WORD usr_port, WORD pid, tcp_session_t *ptr_sess)
{
tcp_sap_t *ptr_sap = NULL;
tcp_port_t *ptr_port = NULL;
if(ptr_sess == NULL)
{
return NULL;
}
if((ptr_sap = tcp_sap_get_by_index(sap_id)) == NULL)
{
return NULL;
}
if((ptr_port = tcp_port_get_by_index(pid)) == NULL)
{
return NULL;
}
if((ptr_port->ptr_sap != ptr_sap) || (ptr_port->usr_port != usr_port))
{
return NULL;
}
memcpy((BYTE*)&ptr_port->sess, (BYTE*)ptr_sess, sizeof(tcp_session_t));
return &ptr_port->sess;
}
int get_tcp_sess(WORD pid, tcp_session_t *sess)
{
tcp_port_t *ptr_port = NULL;
if (pid >= TCP_MAX_NUM_OF_PORT)
{
return -1;
}
if(sess == NULL)
{
return -1;
}
if((ptr_port = tcp_port_get_by_index(pid)) == NULL)
{
return -1;
}
memcpy(sess, &ptr_port->sess, sizeof(tcp_session_t));
return 0;
}
static int tcp_send_msg(tcp_port_t *ptr_port, BYTE *msg, WORD len)
{
int fd;
if((ptr_port == NULL) || (len > TCP_MAX_SEND_MSG_LEN))
{
return -1;
}
if (ptr_port->sess.bServer)
{
fd = ptr_port->cli_fd;
}
else
{
fd = ptr_port->fd;
}
if (fd < 0)
{
return -1;
}
if (send(fd, msg, len, MSG_NOSIGNAL) < 0)// add MSG_NOSIGNAL, to avoid Broken pipe, while sending data after received FIN and sent FIN_ACK
{
return -1;
}
else
{
}
return 0;
}
static int tcp_send_hb(tcp_port_t *ptr_port, WORD msg_id)
{
int ret = -1;
BYTE msg_buf[TCP_MAX_SEND_MSG_LEN];
WORD msg_len;
DWORD pos = 0;
BYTE *pDst = NULL;
tcp_head_t *pHead = NULL;
if(ptr_port == NULL || ptr_port->flag == FALSE)
{
return -1;
}
pDst = msg_buf;
// Begin flag
pDst[pos++] = TCP_F_BB1;
pDst[pos++] = TCP_F_BB2;
//
// len, 2 Bytes
msg_len = htons(sizeof(tcp_head_t));
memcpy(&pDst[pos], (BYTE *)&msg_len, sizeof(msg_len));
pos += sizeof(msg_len);
//
// Head
pHead = (tcp_head_t *)&pDst[pos];
pHead->usMsgId = htons(msg_id);
pHead->usPlLen = 0;
pHead->param1 = 0;
pHead->param2 = 0;
pHead->param3 = 0;
memcpy(&pDst[pos], (BYTE *)pHead, sizeof(tcp_head_t));
pos += sizeof(tcp_head_t);
//
// flagEnd
pDst[pos++] = TCP_F_EB1;
pDst[pos++] = TCP_F_EB2;
//
msg_len = pos;
ret = tcp_send_msg(ptr_port, msg_buf, msg_len);
return ret;
}
static int tcp_handle_hb(tcp_port_t *ptr_port, tcp_head_t *pTcpHead)
{
WORD usMsgId = 0;
if (ptr_port == NULL || pTcpHead == NULL)
{
return -1;
}
if (pTcpHead->usPlLen != 0)
{
return -1;
}
usMsgId = ntohs(pTcpHead->usMsgId);
if (usMsgId == TCP_MSG_HB)
{
tcp_send_hb(ptr_port, TCP_MSG_HB_ACK);
}
else if (usMsgId == TCP_MSG_HB_ACK)
{
if (ptr_port->status == TCP_STATUS_TESTING)
{
tcp_set_status(ptr_port, TCP_STATUS_CONNECTED);
ptr_port->connected_num++;
ptr_port->retry_num = 0;
}
else if (ptr_port->status == TCP_STATUS_CONNECTED)
{
ptr_port->retry_num = 0;
}
}
return 0;
}
//static int tcp_port_handle_recv_msg(WORD pid, BYTE *buf, WORD len)
static int tcp_port_handle_recv_msg(tcp_port_t *ptr_port)
{
tcp_sap_t *ptr_sap = NULL;
if(ptr_port == NULL || ptr_port->ptr_sap == NULL)
{
return -1;
}
ptr_sap = ptr_port->ptr_sap;
if(ptr_sap->recv_cb == NULL)
{
return -1;
}
ptr_sap->recv_cb(ptr_port->usr_port, ptr_port->rv_buf, ptr_port->buf_len);
return 0;
}
void tcp_port_recv_msg(void)
{
int index, i, len, addr_len, fd, pos;
BYTE msg_buf[TCP_MAX_RECV_MSG_LEN];
//struct timeval tv;
struct sockaddr_in sin_addr;
tcp_port_t *ptr_port = NULL;
addr_len = sizeof(struct sockaddr);
memset(&sin_addr, 0, addr_len);
for(index = 0; index < TCP_MAX_NUM_OF_PORT; index++)
{
ptr_port = &tcp_port[index];
if(ptr_port->flag == FALSE)
{
continue;
}
if(((ptr_port->sess.bServer) && (ptr_port->fd < 0 || ptr_port->cli_fd < 0)) \
|| ((!ptr_port->sess.bServer) && (ptr_port->fd < 0)))
{
continue;
}
if (ptr_port->sess.bServer)
{
fd = ptr_port->cli_fd;
}
else
{
fd = ptr_port->fd;
}
for(i = 0; i < TCP_MAX_RECV_COUNT; i++)
{
pos = ptr_port->buf_len;
len = recv(fd, msg_buf, TCP_MAX_RECV_MSG_LEN, 0);
if(len <= 0)
{
break;
}
if((pos + len) >= TCP_MAX_RECV_BUF_LEN)
{
ptr_port->buf_len = 0;
pos = 0;
break;
}
memcpy(&ptr_port->rv_buf[pos], msg_buf, len);
ptr_port->buf_len += len;
tcp_port_handle_recv_msg(ptr_port);
}
}
return;
}
int tcp_send(int sap_id, WORD usr_port, WORD pid, BYTE *payload, WORD len)
{
int ret = -1;
BYTE msg_buf[TCP_MAX_SEND_MSG_LEN];
WORD msg_len;
tcp_sap_t *ptr_sap = NULL;
tcp_port_t *ptr_port = NULL;
WORD pos = 0;
BYTE *pDst = NULL;
if((payload == NULL) || (len > TCP_MAX_PAYLOAD_SIZE))
{
return -1;
}
if((ptr_sap = tcp_sap_get_by_index(sap_id)) == NULL)
{
return -1;
}
if(pid >= TCP_MAX_NUM_OF_PORT)
{
return -1;
}
ptr_port = &tcp_port[pid];
if((ptr_port->flag == FALSE) || (ptr_port->ptr_sap != ptr_sap) || (ptr_port->usr_port != usr_port))
{
return -1;
}
/*
if (ptr_port->status != TCP_STATUS_CONNECTED)
{
return -1;
}
*/
pDst = msg_buf;
memcpy(&pDst[pos], payload, len);
pos += len;
msg_len = pos;
ret = tcp_send_msg(ptr_port, msg_buf, msg_len);
if(ret < 0)
{
ptr_port->sent_fail_num++;
}
return ret;
}
int tcp_link_fsm()
{
int i;
tcp_port_t *ptr_port = NULL;
tcp_session_t *pSess = NULL;
for (i=0; i<TCP_MAX_NUM_OF_PORT; i++)
{
ptr_port = &tcp_port[i];
if (!ptr_port->flag)
{
continue;
}
//if (ptr_port->fd < 0)
//{
// tcp_port_init(i);
// continue;
//}
pSess = &ptr_port->sess;
switch (ptr_port->status)
{
case TCP_STATUS_INITING:
if (--ptr_port->timer > 0)
{
continue;
}
ptr_port->fd = tcp_init_socket(pSess);
if (ptr_port->fd < 0)
{
ptr_port->timer = TCP_TIMER_REINIT;
}
else
{
tcp_set_status(ptr_port, TCP_STATUS_INITED);
}
break;
case TCP_STATUS_INITED:
if (--ptr_port->timer > 0)
{
continue;
}
if (pSess->bServer)
{
if (tcp_check_conn(ptr_port) < 0)
{
ptr_port->timer = TCP_TIMER_WAIT_CONNECT;
}
else
{
ptr_port->timer = 0;
ptr_port->retry_num = 0;
tcp_set_status(ptr_port, TCP_STATUS_TESTING);
}
}
else
{
if (tcp_connect(ptr_port) < 0)
{
close(ptr_port->fd);
ptr_port->fd = -1;
tcp_set_status(ptr_port, TCP_STATUS_INITING);
ptr_port->timer = TCP_TIMER_REINIT;
}
else
{
ptr_port->timer = TCP_TIMER_WAIT_CONNECT;
ptr_port->retry_num = 0;
tcp_set_status(ptr_port, TCP_STATUS_TESTING);
}
}
break;
case TCP_STATUS_TESTING:// sending HB
case TCP_STATUS_CONNECTED:
break;
if (--ptr_port->timer > 0)
{
continue;
}
if (ptr_port->retry_num++ >= TCP_MAX_RETRY_NUM)
{
if (ptr_port->sess.bServer)
{
close(ptr_port->cli_fd);
ptr_port->cli_fd = -1;
ptr_port->timer = 0;
tcp_set_status(ptr_port, TCP_STATUS_INITED);
}
else
{
close(ptr_port->fd);
ptr_port->fd = -1;
ptr_port->timer = 0;
tcp_set_status(ptr_port, TCP_STATUS_INITING);
}
}
else
{
//tcp_send_hb(ptr_port, TCP_MSG_HB);
ptr_port->timer = TCP_TIMER_HB;
}
break;
default:
break;
}
}
return 0;
}
BOOL tcp_print_all_port(void)
{
int j = 0, i;
char buf[516], tmp_buf[8];
tcp_port_t *ptr_port = NULL;
strcpy(buf, "\0");
for(i = 0; i < TCP_MAX_NUM_OF_PORT; i++)
{
ptr_port = &tcp_port[i];
if(ptr_port->flag == TRUE)
{
if(j % 20 == 0 && j != 0)
{
strcpy(buf, "\0");
}
sprintf(tmp_buf, "%d ", i);
strcat(buf, tmp_buf);
j++;
}
}
if(j % 20)
{
}
return TRUE;
}
BOOL tcp_print_port(int pid)
{
tcp_port_t *ptr_port = NULL;
if((pid < 0) || (pid >= TCP_MAX_NUM_OF_PORT))
{
return FALSE;
}
ptr_port = &tcp_port[pid];
if(ptr_port->flag == FALSE)
{
return TRUE;
}
if (ptr_port->status < TCP_STATUS_MAX)
{
}
if (ptr_port->sess.bServer)
{
}
return TRUE;
}
BOOL tcp_clear_stat(int pid)
{
tcp_port_t *ptr_port = NULL;
if((pid < 0) || (pid >= TCP_MAX_NUM_OF_PORT))
{
return FALSE;
}
ptr_port = &tcp_port[pid];
if(ptr_port->flag == FALSE)
{
return TRUE;
}
ptr_port->connected_num = 0;
ptr_port->disconnect_num = 0;
ptr_port->sent_fail_num = 0;
return TRUE;
}

View File

@@ -0,0 +1,5 @@
libevent-c
http://libevent.org
libevent-2.1.8-stable.tar.gz

Binary file not shown.

View File

@@ -0,0 +1,44 @@
release = no
cover = no
CC = gcc
CPP = g++
LD = ld
AR = ar
CP = cp
ifeq ($(release), no)
CFLAGS += -Wall -Werror -g -fPIC
else
CFLAGS += -Wall -Werror -O3 -fPIC
endif
LIB_DIR = ./lib
CSRC_DIR = ./src
OBJ_DIR = ./obj
CSRCS = $(wildcard $(CSRC_DIR)/*.c)
COBJS := $(patsubst %.c, $(OBJ_DIR)/%.o, $(notdir $(CSRCS)))
TARGET_LIB = $(OBJ_DIR)/libjson.a
all : chkobjdir $(TARGET_LIB)
chkobjdir:
@if test ! -d $(OBJ_DIR); \
then \
mkdir $(OBJ_DIR);\
fi
$(OBJ_DIR)/%.o : $(CSRC_DIR)/%.c
@echo "COMPILE $<"
@$(CC) -fPIC $(CFLAGS) -c $< -o $@
$(TARGET_LIB) : $(COBJS)
@echo "AR $(TARGET_LIB)"
@$(AR) cr $(TARGET_LIB) $(COBJS)
@$(CP) $(TARGET_LIB) $(LIB_DIR)
.PHONY:clean
clean:
@echo "CLEAN $(TARGET_LIB)"
@rm -rf $(TARGET_LIB) $(OBJ_DIR)

View File

@@ -0,0 +1,70 @@
/*
* $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Internal methods for working with json_type_array objects.
* Although this is exposed by the json_object_get_array() method,
* it is not recommended for direct use.
*/
#ifndef _arraylist_h_
#define _arraylist_h_
#ifdef __cplusplus
extern "C" {
#endif
#define ARRAY_LIST_DEFAULT_SIZE 32
typedef void (array_list_free_fn) (void *data);
struct array_list
{
void **array;
size_t length;
size_t size;
array_list_free_fn *free_fn;
};
typedef struct array_list array_list;
extern struct array_list*
array_list_new(array_list_free_fn *free_fn);
extern void
array_list_free(struct array_list *al);
extern void*
array_list_get_idx(struct array_list *al, size_t i);
extern int
array_list_put_idx(struct array_list *al, size_t i, void *data);
extern int
array_list_add(struct array_list *al, void *data);
extern size_t
array_list_length(struct array_list *al);
extern void
array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *));
extern void* array_list_bsearch(const void **key,
struct array_list *arr,
int (*sort_fn)(const void *, const void *));
extern int
array_list_del_idx(struct array_list *arr, size_t idx, size_t count);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,42 @@
/*
* $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief A convenience header that may be included instead of other individual ones.
*/
#ifndef _json_h_
#define _json_h_
#ifdef __cplusplus
extern "C" {
#endif
/* BEGIN lihua 2018-07-11 PN: 屏蔽此行 */
#if 0
#include "debug.h"
#endif
/* BEGIN lihua 2018-07-11 */
#include "linkhash.h"
#include "arraylist.h"
#include "json_util.h"
#include "json_object.h"
#include "json_pointer.h"
#include "json_tokener.h"
#include "json_object_iterator.h"
#include "json_c_version.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2012,2017 Eric Haszlakiewicz
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
/**
* @file
* @brief Methods for retrieving the json-c version.
*/
#ifndef _json_c_version_h_
#define _json_c_version_h_
#define JSON_C_MAJOR_VERSION 0
#define JSON_C_MINOR_VERSION 13
#define JSON_C_MICRO_VERSION 99
#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \
(JSON_C_MINOR_VERSION << 8) | \
JSON_C_MICRO_VERSION)
#define JSON_C_VERSION "0.13.99"
/**
* @see JSON_C_VERSION
* @return the version of the json-c library as a string
*/
const char *json_c_version(void); /* Returns JSON_C_VERSION */
/**
* The json-c version encoded into an int, with the low order 8 bits
* being the micro version, the next higher 8 bits being the minor version
* and the next higher 8 bits being the major version.
* For example, 7.12.99 would be 0x00070B63.
*
* @see JSON_C_VERSION_NUM
* @return the version of the json-c library as an int
*/
int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */
#endif

View File

@@ -0,0 +1,4 @@
/* json_config.h. Generated from json_config.h.in by configure. */
/* Define to 1 if you have the <inttypes.h> header file. */
#define JSON_C_HAVE_INTTYPES_H 1

View File

@@ -0,0 +1,23 @@
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#ifndef _json_inttypes_h_
#define _json_inttypes_h_
#include "json_config.h"
#ifdef JSON_C_HAVE_INTTYPES_H
/* inttypes.h includes stdint.h */
#include <inttypes.h>
#else
#include <stdint.h>
#define PRId64 "I64d"
#define SCNd64 "I64d"
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,240 @@
/**
*******************************************************************************
* @file json_object_iterator.h
*
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
* @brief An API for iterating over json_type_object objects,
* styled to be familiar to C++ programmers.
* Unlike json_object_object_foreach() and
* json_object_object_foreachC(), this avoids the need to expose
* json-c internals like lh_entry.
*
* API attributes: <br>
* * Thread-safe: NO<br>
* * Reentrant: NO
*
*******************************************************************************
*/
#ifndef JSON_OBJECT_ITERATOR_H
#define JSON_OBJECT_ITERATOR_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Forward declaration for the opaque iterator information.
*/
struct json_object_iter_info_;
/**
* The opaque iterator that references a name/value pair within
* a JSON Object instance or the "end" iterator value.
*/
struct json_object_iterator {
const void* opaque_;
};
/**
* forward declaration of json-c's JSON value instance structure
*/
struct json_object;
/**
* Initializes an iterator structure to a "default" value that
* is convenient for initializing an iterator variable to a
* default state (e.g., initialization list in a class'
* constructor).
*
* @code
* struct json_object_iterator iter = json_object_iter_init_default();
* MyClass() : iter_(json_object_iter_init_default())
* @endcode
*
* @note The initialized value doesn't reference any specific
* pair, is considered an invalid iterator, and MUST NOT
* be passed to any json-c API that expects a valid
* iterator.
*
* @note User and internal code MUST NOT make any assumptions
* about and dependencies on the value of the "default"
* iterator value.
*
* @return json_object_iterator
*/
struct json_object_iterator
json_object_iter_init_default(void);
/** Retrieves an iterator to the first pair of the JSON Object.
*
* @warning Any modification of the underlying pair invalidates all
* iterators to that pair.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator If the JSON Object has at
* least one pair, on return, the iterator refers
* to the first pair. If the JSON Object doesn't
* have any pairs, the returned iterator is
* equivalent to the "end" iterator for the same
* JSON Object instance.
*
* @code
* struct json_object_iterator it;
* struct json_object_iterator itEnd;
* struct json_object* obj;
*
* obj = json_tokener_parse("{'first':'george', 'age':100}");
* it = json_object_iter_begin(obj);
* itEnd = json_object_iter_end(obj);
*
* while (!json_object_iter_equal(&it, &itEnd)) {
* printf("%s\n",
* json_object_iter_peek_name(&it));
* json_object_iter_next(&it);
* }
*
* @endcode
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj);
/** Retrieves the iterator that represents the position beyond the
* last pair of the given JSON Object instance.
*
* @warning Do NOT write code that assumes that the "end"
* iterator value is NULL, even if it is so in a
* particular instance of the implementation.
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The "end" iterator and the
* equality test method, on the other hand, permit us to
* cleanly abstract pretty much any reasonable underlying
* representation without burdening the iterator
* structure with unnecessary data.
*
* @note For performance reasons, memorize the "end" iterator prior
* to any loop.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator On return, the iterator refers
* to the "end" of the Object instance's pairs
* (i.e., NOT the last pair, but "beyond the last
* pair" value)
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj);
/** Returns an iterator to the next pair, if any
*
* @warning Any modification of the underlying pair
* invalidates all iterators to that pair.
*
* @param iter [IN/OUT] Pointer to iterator that references a
* name/value pair; MUST be a valid, non-end iterator.
* WARNING: bad things will happen if invalid or "end"
* iterator is passed. Upon return will contain the
* reference to the next pair if there is one; if there
* are no more pairs, will contain the "end" iterator
* value, which may be compared against the return value
* of json_object_iter_end() for the same JSON Object
* instance.
*/
void
json_object_iter_next(struct json_object_iterator* iter);
/** Returns a const pointer to the name of the pair referenced
* by the given iterator.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if an invalid or
* "end" iterator is passed.
*
* @return const char* Pointer to the name of the referenced
* name/value pair. The name memory belongs to the
* name/value pair, will be freed when the pair is
* deleted or modified, and MUST NOT be modified or
* freed by the user.
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter);
/** Returns a pointer to the json-c instance representing the
* value of the referenced name/value pair, without altering
* the instance's reference count.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if invalid or
* "end" iterator is passed.
*
* @return struct json_object* Pointer to the json-c value
* instance of the referenced name/value pair; the
* value's reference count is not changed by this
* function: if you plan to hold on to this json-c node,
* take a look at json_object_get() and
* json_object_put(). IMPORTANT: json-c API represents
* the JSON Null value as a NULL json_object instance
* pointer.
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter);
/** Tests two iterators for equality. Typically used to test
* for end of iteration by comparing an iterator to the
* corresponding "end" iterator (that was derived from the same
* JSON Object instance).
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The equality test method, on
* the other hand, permits us to cleanly abstract pretty
* much any reasonable underlying representation.
*
* @param iter1 Pointer to first valid, non-NULL iterator
* @param iter2 POinter to second valid, non-NULL iterator
*
* @warning if a NULL iterator pointer or an uninitialized
* or invalid iterator, or iterators derived from
* different JSON Object instances are passed, bad things
* will happen!
*
* @return json_bool non-zero if iterators are equal (i.e., both
* reference the same name/value pair or are both at
* "end"); zero if they are not equal.
*/
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2);
#ifdef __cplusplus
}
#endif
#endif /* JSON_OBJECT_ITERATOR_H */

View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2016 Alexadru Ardelean.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief JSON Pointer (RFC 6901) implementation for retrieving
* objects from a json-c object tree.
*/
#ifndef _json_pointer_h_
#define _json_pointer_h_
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Retrieves a JSON sub-object from inside another JSON object
* using the JSON pointer notation as defined in RFC 6901
* https://tools.ietf.org/html/rfc6901
*
* The returned JSON sub-object is equivalent to parsing manually the
* 'obj' JSON tree ; i.e. it's not a new object that is created, but rather
* a pointer inside the JSON tree.
*
* Internally, this is equivalent to doing a series of 'json_object_object_get()'
* and 'json_object_array_get_idx()' along the given 'path'.
*
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
* is added after the 'res' param will be treated as an argument for 'path'
* Example: json_pointer_get(obj, "/foo/%d/%s", &res, 0, bar)
* This means, that you need to escape '%' with '%%' (just like in printf())
*
* @param obj the json_object instance/tree from where to retrieve sub-objects
* @param path a (RFC6901) string notation for the sub-object to retrieve
* @param res a pointer where to store a reference to the json_object
* associated with the given path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res);
/**
* This is a variant of 'json_pointer_get()' that supports printf() style arguments.
*
* Example: json_pointer_getf(obj, res, "/foo/%d/%s", 0, bak)
* This also means that you need to escape '%' with '%%' (just like in printf())
*
* Please take into consideration all recommended 'printf()' format security
* aspects when using this function.
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param res a pointer where to store a reference to the json_object
* associated with the given path
* @param path_fmt a printf() style format for the path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...);
/**
* Sets JSON object 'value' in the 'obj' tree at the location specified
* by the 'path'. 'path' is JSON pointer notation as defined in RFC 6901
* https://tools.ietf.org/html/rfc6901
*
* Note that 'obj' is a double pointer, mostly for the "" (empty string)
* case, where the entire JSON object would be replaced by 'value'.
* In the case of the "" path, the object at '*obj' will have it's refcount
* decremented with 'json_object_put()' and the 'value' object will be assigned to it.
*
* For other cases (JSON sub-objects) ownership of 'value' will be transferred into
* '*obj' via 'json_object_object_add()' & 'json_object_array_put_idx()', so the
* only time the refcount should be decremented for 'value' is when the return value of
* 'json_pointer_set()' is negative (meaning the 'value' object did not get set into '*obj').
*
* That also implies that 'json_pointer_set()' does not do any refcount incrementing.
* (Just that single decrement that was mentioned above).
*
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
* is added after the 'value' param will be treated as an argument for 'path'
* Example: json_pointer_set(obj, "/foo/%d/%s", value, 0, bak)
* This means, that you need to escape '%' with '%%' (just like in printf())
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param path a (RFC6901) string notation for the sub-object to set in the tree
* @param value object to set at path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value);
/**
* This is a variant of 'json_pointer_set()' that supports printf() style arguments.
*
* Example: json_pointer_setf(obj, value, "/foo/%d/%s", 0, bak)
* This also means that you need to escape '%' with '%%' (just like in printf())
*
* Please take into consideration all recommended 'printf()' format security
* aspects when using this function.
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param value object to set at path
* @param path_fmt a printf() style format for the path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,216 @@
/*
* $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Methods to parse an input string into a tree of json_object objects.
*/
#ifndef _json_tokener_h_
#define _json_tokener_h_
#include <stddef.h>
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
enum json_tokener_error {
json_tokener_success,
json_tokener_continue,
json_tokener_error_depth,
json_tokener_error_parse_eof,
json_tokener_error_parse_unexpected,
json_tokener_error_parse_null,
json_tokener_error_parse_boolean,
json_tokener_error_parse_number,
json_tokener_error_parse_array,
json_tokener_error_parse_object_key_name,
json_tokener_error_parse_object_key_sep,
json_tokener_error_parse_object_value_sep,
json_tokener_error_parse_string,
json_tokener_error_parse_comment,
json_tokener_error_size
};
enum json_tokener_state {
json_tokener_state_eatws,
json_tokener_state_start,
json_tokener_state_finish,
json_tokener_state_null,
json_tokener_state_comment_start,
json_tokener_state_comment,
json_tokener_state_comment_eol,
json_tokener_state_comment_end,
json_tokener_state_string,
json_tokener_state_string_escape,
json_tokener_state_escape_unicode,
json_tokener_state_boolean,
json_tokener_state_number,
json_tokener_state_array,
json_tokener_state_array_add,
json_tokener_state_array_sep,
json_tokener_state_object_field_start,
json_tokener_state_object_field,
json_tokener_state_object_field_end,
json_tokener_state_object_value,
json_tokener_state_object_value_add,
json_tokener_state_object_sep,
json_tokener_state_array_after_sep,
json_tokener_state_object_field_start_after_sep,
json_tokener_state_inf
};
struct json_tokener_srec
{
enum json_tokener_state state, saved_state;
struct json_object *obj;
struct json_object *current;
char *obj_field_name;
};
#define JSON_TOKENER_DEFAULT_DEPTH 32
struct json_tokener
{
char *str;
struct printbuf *pb;
int max_depth, depth, is_double, st_pos, char_offset;
enum json_tokener_error err;
unsigned int ucs_char;
char quote_char;
struct json_tokener_srec *stack;
int flags;
};
/**
* @deprecated Unused in json-c code
*/
typedef struct json_tokener json_tokener;
/**
* Be strict when parsing JSON input. Use caution with
* this flag as what is considered valid may become more
* restrictive from one release to the next, causing your
* code to fail on previously working input.
*
* This flag is not set by default.
*
* @see json_tokener_set_flags()
*/
#define JSON_TOKENER_STRICT 0x01
/**
* Given an error previously returned by json_tokener_get_error(),
* return a human readable description of the error.
*
* @return a generic error message is returned if an invalid error value is provided.
*/
const char *json_tokener_error_desc(enum json_tokener_error jerr);
/**
* Retrieve the error caused by the last call to json_tokener_parse_ex(),
* or json_tokener_success if there is no error.
*
* When parsing a JSON string in pieces, if the tokener is in the middle
* of parsing this will return json_tokener_continue.
*
* See also json_tokener_error_desc().
*/
JSON_EXPORT enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
JSON_EXPORT struct json_tokener* json_tokener_new(void);
JSON_EXPORT struct json_tokener* json_tokener_new_ex(int depth);
JSON_EXPORT void json_tokener_free(struct json_tokener *tok);
JSON_EXPORT void json_tokener_reset(struct json_tokener *tok);
JSON_EXPORT struct json_object* json_tokener_parse(const char *str);
JSON_EXPORT struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);
/**
* Set flags that control how parsing will be done.
*/
JSON_EXPORT void json_tokener_set_flags(struct json_tokener *tok, int flags);
/**
* Parse a string and return a non-NULL json_object if a valid JSON value
* is found. The string does not need to be a JSON object or array;
* it can also be a string, number or boolean value.
*
* A partial JSON string can be parsed. If the parsing is incomplete,
* NULL will be returned and json_tokener_get_error() will return
* json_tokener_continue.
* json_tokener_parse_ex() can then be called with additional bytes in str
* to continue the parsing.
*
* If json_tokener_parse_ex() returns NULL and the error is anything other than
* json_tokener_continue, a fatal error has occurred and parsing must be
* halted. Then, the tok object must not be reused until json_tokener_reset() is
* called.
*
* When a valid JSON value is parsed, a non-NULL json_object will be
* returned. Also, json_tokener_get_error() will return json_tokener_success.
* Be sure to check the type with json_object_is_type() or
* json_object_get_type() before using the object.
*
* @b XXX this shouldn't use internal fields:
* Trailing characters after the parsed value do not automatically cause an
* error. It is up to the caller to decide whether to treat this as an
* error or to handle the additional characters, perhaps by parsing another
* json value starting from that point.
*
* Extra characters can be detected by comparing the tok->char_offset against
* the length of the last len parameter passed in.
*
* The tokener does \b not maintain an internal buffer so the caller is
* responsible for calling json_tokener_parse_ex with an appropriate str
* parameter starting with the extra characters.
*
* This interface is presently not 64-bit clean due to the int len argument
* so the function limits the maximum string size to INT32_MAX (2GB).
* If the function is called with len == -1 then strlen is called to check
* the string length is less than INT32_MAX (2GB)
*
* Example:
* @code
json_object *jobj = NULL;
const char *mystring = NULL;
int stringlen = 0;
enum json_tokener_error jerr;
do {
mystring = ... // get JSON string, e.g. read from file, etc...
stringlen = strlen(mystring);
jobj = json_tokener_parse_ex(tok, mystring, stringlen);
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
if (jerr != json_tokener_success)
{
fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
// Handle errors, as appropriate for your application.
}
if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
{
// Handle extra characters after parsed object as desired.
// e.g. issue an error, parse another object from that point, etc...
}
// Success, use jobj here.
@endcode
*
* @param tok a json_tokener previously allocated with json_tokener_new()
* @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated.
* @param len the length of str
*/
JSON_EXPORT struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,106 @@
/*
* $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Miscllaneous utility functions and macros.
*/
#ifndef _json_util_h_
#define _json_util_h_
#include "json_object.h"
#ifndef json_min
#define json_min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef json_max
#define json_max(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define JSON_FILE_BUF_SIZE 4096
/* utility functions */
/**
* Read the full contents of the given file, then convert it to a
* json_object using json_tokener_parse().
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern struct json_object* json_object_from_file(const char *filename);
/**
* Create a JSON object from already opened file descriptor.
*
* This function can be helpful, when you opened the file already,
* e.g. when you have a temp file.
* Note, that the fd must be readable at the actual position, i.e.
* use lseek(fd, 0, SEEK_SET) before.
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern struct json_object* json_object_from_fd(int fd);
/**
* Equivalent to:
* json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern int json_object_to_file(const char *filename, struct json_object *obj);
/**
* Open and truncate the given file, creating it if necessary, then
* convert the json_object to a string and write it to the file.
*
* Returns -1 if something fails. See json_util_get_last_err() for details.
*/
extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags);
/**
* Convert the json_object to a string and write it to the file descriptor.
* Handles partial writes and will keep writing until done, or an error
* occurs.
*
* @param fd an open, writable file descriptor to write to
* @param obj the object to serializer and write
* @param flags flags to pass to json_object_to_json_string_ext()
* @return -1 if something fails. See json_util_get_last_err() for details.
*/
extern int json_object_to_fd(int fd, struct json_object *obj, int flags);
/**
* Return the last error from various json-c functions, including:
* json_object_to_file{,_ext}, json_object_to_fd() or
* json_object_from_{file,fd}, or NULL if there is none.
*/
const char *json_util_get_last_err(void);
extern int json_parse_int64(const char *buf, int64_t *retval);
extern int json_parse_double(const char *buf, double *retval);
/**
* Return a string describing the type of the object.
* e.g. "int", or "object", etc...
*/
extern const char *json_type_to_name(enum json_type o_type);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,381 @@
/*
* $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Internal methods for working with json_type_object objects. Although
* this is exposed by the json_object_get_object() function and within the
* json_object_iter type, it is not recommended for direct use.
*/
#ifndef _linkhash_h_
#define _linkhash_h_
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* golden prime used in hash functions
*/
#define LH_PRIME 0x9e370001UL
/**
* The fraction of filled hash buckets until an insert will cause the table
* to be resized.
* This can range from just above 0 up to 1.0.
*/
#define LH_LOAD_FACTOR 0.66
/**
* sentinel pointer value for empty slots
*/
#define LH_EMPTY (void*)-1
/**
* sentinel pointer value for freed slots
*/
#define LH_FREED (void*)-2
/**
* default string hash function
*/
#define JSON_C_STR_HASH_DFLT 0
/**
* perl-like string hash function
*/
#define JSON_C_STR_HASH_PERLLIKE 1
/**
* This function sets the hash function to be used for strings.
* Must be one of the JSON_C_STR_HASH_* values.
* @returns 0 - ok, -1 if parameter was invalid
*/
int json_global_set_string_hash(const int h);
struct lh_entry;
/**
* callback function prototypes
*/
typedef void (lh_entry_free_fn) (struct lh_entry *e);
/**
* callback function prototypes
*/
typedef unsigned long (lh_hash_fn) (const void *k);
/**
* callback function prototypes
*/
typedef int (lh_equal_fn) (const void *k1, const void *k2);
/**
* An entry in the hash table
*/
struct lh_entry {
/**
* The key. Use lh_entry_k() instead of accessing this directly.
*/
const void *k;
/**
* A flag for users of linkhash to know whether or not they
* need to free k.
*/
int k_is_constant;
/**
* The value. Use lh_entry_v() instead of accessing this directly.
*/
const void *v;
/**
* The next entry
*/
struct lh_entry *next;
/**
* The previous entry.
*/
struct lh_entry *prev;
};
/**
* The hash table structure.
*/
struct lh_table {
/**
* Size of our hash.
*/
int size;
/**
* Numbers of entries.
*/
int count;
/**
* The first entry.
*/
struct lh_entry *head;
/**
* The last entry.
*/
struct lh_entry *tail;
struct lh_entry *table;
/**
* A pointer onto the function responsible for freeing an entry.
*/
lh_entry_free_fn *free_fn;
lh_hash_fn *hash_fn;
lh_equal_fn *equal_fn;
};
typedef struct lh_table lh_table;
/**
* Convenience list iterator.
*/
#define lh_foreach(table, entry) \
for(entry = table->head; entry; entry = entry->next)
/**
* lh_foreach_safe allows calling of deletion routine while iterating.
*
* @param table a struct lh_table * to iterate over
* @param entry a struct lh_entry * variable to hold each element
* @param tmp a struct lh_entry * variable to hold a temporary pointer to the next element
*/
#define lh_foreach_safe(table, entry, tmp) \
for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
/**
* Create a new linkhash table.
*
* @param size initial table size. The table is automatically resized
* although this incurs a performance penalty.
* @param free_fn callback function used to free memory for entries
* when lh_table_free or lh_table_delete is called.
* If NULL is provided, then memory for keys and values
* must be freed by the caller.
* @param hash_fn function used to hash keys. 2 standard ones are defined:
* lh_ptr_hash and lh_char_hash for hashing pointer values
* and C strings respectively.
* @param equal_fn comparison function to compare keys. 2 standard ones defined:
* lh_ptr_hash and lh_char_hash for comparing pointer values
* and C strings respectively.
* @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned.
*/
extern struct lh_table* lh_table_new(int size,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn);
/**
* Convenience function to create a new linkhash table with char keys.
*
* @param size initial table size.
* @param free_fn callback function used to free memory for entries.
* @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned.
*/
extern struct lh_table* lh_kchar_table_new(int size,
lh_entry_free_fn *free_fn);
/**
* Convenience function to create a new linkhash table with ptr keys.
*
* @param size initial table size.
* @param free_fn callback function used to free memory for entries.
* @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned.
*/
extern struct lh_table* lh_kptr_table_new(int size,
lh_entry_free_fn *free_fn);
/**
* Free a linkhash table.
*
* If a lh_entry_free_fn callback free function was provided then it is
* called for all entries in the table.
*
* @param t table to free.
*/
extern void lh_table_free(struct lh_table *t);
/**
* Insert a record into the table.
*
* @param t the table to insert into.
* @param k a pointer to the key to insert.
* @param v a pointer to the value to insert.
*
* @return On success, <code>0</code> is returned.
* On error, a negative value is returned.
*/
extern int lh_table_insert(struct lh_table *t, const void *k, const void *v);
/**
* Insert a record into the table using a precalculated key hash.
*
* The hash h, which should be calculated with lh_get_hash() on k, is provided by
* the caller, to allow for optimization when multiple operations with the same
* key are known to be needed.
*
* @param t the table to insert into.
* @param k a pointer to the key to insert.
* @param v a pointer to the value to insert.
* @param h hash value of the key to insert
* @param opts if set to JSON_C_OBJECT_KEY_IS_CONSTANT, sets lh_entry.k_is_constant
* so t's free function knows to avoid freeing the key.
*/
extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts);
/**
* Lookup a record in the table.
*
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @return a pointer to the record structure of the value or NULL if it does not exist.
*/
extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k);
/**
* Lookup a record in the table using a precalculated key hash.
*
* The hash h, which should be calculated with lh_get_hash() on k, is provided by
* the caller, to allow for optimization when multiple operations with the same
* key are known to be needed.
*
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @param h hash value of the key to lookup
* @return a pointer to the record structure of the value or NULL if it does not exist.
*/
extern struct lh_entry* lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, const unsigned long h);
/**
* Lookup a record in the table.
*
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @param v a pointer to a where to store the found value (set to NULL if it doesn't exist).
* @return whether or not the key was found
*/
extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v);
/**
* Delete a record from the table.
*
* If a callback free function is provided then it is called for the
* for the item being deleted.
* @param t the table to delete from.
* @param e a pointer to the entry to delete.
* @return 0 if the item was deleted.
* @return -1 if it was not found.
*/
extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
/**
* Delete a record from the table.
*
* If a callback free function is provided then it is called for the
* for the item being deleted.
* @param t the table to delete from.
* @param k a pointer to the key to delete.
* @return 0 if the item was deleted.
* @return -1 if it was not found.
*/
extern int lh_table_delete(struct lh_table *t, const void *k);
extern int lh_table_length(struct lh_table *t);
/**
* Resizes the specified table.
*
* @param t Pointer to table to resize.
* @param new_size New table size. Must be positive.
*
* @return On success, <code>0</code> is returned.
* On error, a negative value is returned.
*/
int lh_table_resize(struct lh_table *t, int new_size);
/**
* @deprecated Don't use this outside of linkhash.h:
*/
#if !defined(_MSC_VER) || (_MSC_VER > 1800)
/* VS2010 can't handle inline funcs, so skip it there */
#define _LH_INLINE inline
#else
#define _LH_INLINE
#endif
/**
* Calculate the hash of a key for a given table.
*
* This is an exension to support functions that need to calculate
* the hash several times and allows them to do it just once and then pass
* in the hash to all utility functions. Depending on use case, this can be a
* considerable performance improvement.
* @param t the table (used to obtain hash function)
* @param k a pointer to the key to lookup
* @return the key's hash
*/
static _LH_INLINE unsigned long lh_get_hash(const struct lh_table *t, const void *k)
{
return t->hash_fn(k);
}
#undef _LH_INLINE
/**
* @deprecated Don't use this outside of linkhash.h:
*/
#ifdef __UNCONST
#define _LH_UNCONST(a) __UNCONST(a)
#else
#define _LH_UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
#endif
/**
* Return a non-const version of lh_entry.k.
*
* lh_entry.k is const to indicate and help ensure that linkhash itself doesn't modify
* it, but callers are allowed to do what they want with it.
* See also lh_entry.k_is_constant
*/
#define lh_entry_k(entry) _LH_UNCONST((entry)->k)
/**
* Return a non-const version of lh_entry.v.
*
* v is const to indicate and help ensure that linkhash itself doesn't modify
* it, but callers are allowed to do what they want with it.
*/
#define lh_entry_v(entry) _LH_UNCONST((entry)->v)
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,122 @@
/*
* $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* @file
* @brief Internal string buffer handing. Unless you're writing a
* json_object_to_json_string_fn implementation for use with
* json_object_set_serializer() direct use of this is not
* recommended.
*/
#ifndef _printbuf_h_
#define _printbuf_h_
#ifdef __cplusplus
extern "C" {
#endif
struct printbuf {
char *buf;
int bpos;
int size;
};
typedef struct printbuf printbuf;
extern struct printbuf*
printbuf_new(void);
/* As an optimization, printbuf_memappend_fast() is defined as a macro
* that handles copying data if the buffer is large enough; otherwise
* it invokes printbuf_memappend() which performs the heavy
* lifting of realloc()ing the buffer and copying data.
*
* Your code should not use printbuf_memappend() directly unless it
* checks the return code. Use printbuf_memappend_fast() instead.
*/
extern int
printbuf_memappend(struct printbuf *p, const char *buf, int size);
#define printbuf_memappend_fast(p, bufptr, bufsize) \
do { \
if ((p->size - p->bpos) > bufsize) { \
memcpy(p->buf + p->bpos, (bufptr), bufsize); \
p->bpos += bufsize; \
p->buf[p->bpos]= '\0'; \
} else { printbuf_memappend(p, (bufptr), bufsize); } \
} while (0)
#define printbuf_length(p) ((p)->bpos)
/**
* Results in a compile error if the argument is not a string literal.
*/
#define _printbuf_check_literal(mystr) ("" mystr)
/**
* This is an optimization wrapper around printbuf_memappend() that is useful
* for appending string literals. Since the size of string constants is known
* at compile time, using this macro can avoid a costly strlen() call. This is
* especially helpful when a constant string must be appended many times. If
* you got here because of a compilation error caused by passing something
* other than a string literal, use printbuf_memappend_fast() in conjunction
* with strlen().
*
* See also:
* printbuf_memappend_fast()
* printbuf_memappend()
* sprintbuf()
*/
#define printbuf_strappend(pb, str) \
printbuf_memappend ((pb), _printbuf_check_literal(str), sizeof(str) - 1)
/**
* Set len bytes of the buffer to charvalue, starting at offset offset.
* Similar to calling memset(x, charvalue, len);
*
* The memory allocated for the buffer is extended as necessary.
*
* If offset is -1, this starts at the end of the current data in the buffer.
*/
extern int
printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len);
/**
* Formatted print to printbuf.
*
* This function is the most expensive of the available functions for appending
* string data to a printbuf and should be used only where convenience is more
* important than speed. Avoid using this function in high performance code or
* tight loops; in these scenarios, consider using snprintf() with a static
* buffer in conjunction with one of the printbuf_*append() functions.
*
* See also:
* printbuf_memappend_fast()
* printbuf_memappend()
* printbuf_strappend()
*/
extern int
sprintbuf(struct printbuf *p, const char *msg, ...);
extern void
printbuf_reset(struct printbuf *p);
extern void
printbuf_free(struct printbuf *p);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,146 @@
/*
* $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config_json_c.h"
#include <limits.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#endif /* STDC_HEADERS */
#if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD)
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#ifndef SIZE_T_MAX
#if SIZEOF_SIZE_T == SIZEOF_INT
#define SIZE_T_MAX UINT_MAX
#elif SIZEOF_SIZE_T == SIZEOF_LONG
#define SIZE_T_MAX ULONG_MAX
#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
#define SIZE_T_MAX ULLONG_MAX
#else
#error Unable to determine size of size_t
#endif
#endif
#include "arraylist.h"
struct array_list*
array_list_new(array_list_free_fn *free_fn)
{
struct array_list *arr;
arr = (struct array_list*)calloc(1, sizeof(struct array_list));
if(!arr) return NULL;
arr->size = ARRAY_LIST_DEFAULT_SIZE;
arr->length = 0;
arr->free_fn = free_fn;
if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) {
free(arr);
return NULL;
}
return arr;
}
extern void
array_list_free(struct array_list *arr)
{
size_t i;
for(i = 0; i < arr->length; i++)
if(arr->array[i]) arr->free_fn(arr->array[i]);
free(arr->array);
free(arr);
}
void*
array_list_get_idx(struct array_list *arr, size_t i)
{
if(i >= arr->length) return NULL;
return arr->array[i];
}
static int array_list_expand_internal(struct array_list *arr, size_t max)
{
void *t;
size_t new_size;
if(max < arr->size) return 0;
/* Avoid undefined behaviour on size_t overflow */
if( arr->size >= SIZE_T_MAX / 2 )
new_size = max;
else
{
new_size = arr->size << 1;
if (new_size < max)
new_size = max;
}
if (new_size > (~((size_t)0)) / sizeof(void*)) return -1;
if (!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1;
arr->array = (void**)t;
(void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*));
arr->size = new_size;
return 0;
}
int
array_list_put_idx(struct array_list *arr, size_t idx, void *data)
{
if (idx > SIZE_T_MAX - 1 ) return -1;
if(array_list_expand_internal(arr, idx+1)) return -1;
if(idx < arr->length && arr->array[idx])
arr->free_fn(arr->array[idx]);
arr->array[idx] = data;
if(arr->length <= idx) arr->length = idx + 1;
return 0;
}
int
array_list_add(struct array_list *arr, void *data)
{
return array_list_put_idx(arr, arr->length, data);
}
void
array_list_sort(struct array_list *arr, int(*sort_fn)(const void *, const void *))
{
qsort(arr->array, arr->length, sizeof(arr->array[0]), sort_fn);
}
void* array_list_bsearch(const void **key, struct array_list *arr,
int (*sort_fn)(const void *, const void *))
{
return bsearch(key, arr->array, arr->length, sizeof(arr->array[0]),
sort_fn);
}
size_t
array_list_length(struct array_list *arr)
{
return arr->length;
}
int
array_list_del_idx( struct array_list *arr, size_t idx, size_t count )
{
size_t i, stop;
stop = idx + count;
if ( idx >= arr->length || stop > arr->length ) return -1;
for ( i = idx; i < stop; ++i ) {
if ( arr->array[i] ) arr->free_fn( arr->array[i] );
}
memmove( arr->array + idx, arr->array + stop, (arr->length - stop) * sizeof(void*) );
arr->length -= count;
return 0;
}

View File

@@ -0,0 +1,70 @@
/*
* $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Internal methods for working with json_type_array objects.
* Although this is exposed by the json_object_get_array() method,
* it is not recommended for direct use.
*/
#ifndef _arraylist_h_
#define _arraylist_h_
#ifdef __cplusplus
extern "C" {
#endif
#define ARRAY_LIST_DEFAULT_SIZE 32
typedef void (array_list_free_fn) (void *data);
struct array_list
{
void **array;
size_t length;
size_t size;
array_list_free_fn *free_fn;
};
typedef struct array_list array_list;
extern struct array_list*
array_list_new(array_list_free_fn *free_fn);
extern void
array_list_free(struct array_list *al);
extern void*
array_list_get_idx(struct array_list *al, size_t i);
extern int
array_list_put_idx(struct array_list *al, size_t i, void *data);
extern int
array_list_add(struct array_list *al, void *data);
extern size_t
array_list_length(struct array_list *al);
extern void
array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *));
extern void* array_list_bsearch(const void **key,
struct array_list *arr,
int (*sort_fn)(const void *, const void *));
extern int
array_list_del_idx(struct array_list *arr, size_t idx, size_t count);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,200 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Enable RDRAND Hardware RNG Hash Seed */
/* #undef ENABLE_RDRAND */
/* Enable partial threading support */
/* #undef ENABLE_THREADING */
/* Define if .gnu.warning accepts long strings. */
/* #undef HAS_GNU_WARNING_LONG */
/* Has atomic builtins */
#define HAVE_ATOMIC_BUILTINS 1
/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you
don't. */
#define HAVE_DECL_INFINITY 1
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
*/
#define HAVE_DECL_ISINF 1
/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
*/
#define HAVE_DECL_ISNAN 1
/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */
#define HAVE_DECL_NAN 1
/* Define to 1 if you have the declaration of `_finite', and to 0 if you
don't. */
#define HAVE_DECL__FINITE 0
/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't.
*/
#define HAVE_DECL__ISNAN 0
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */
/* Define to 1 if you have the <endian.h> header file. */
#define HAVE_ENDIAN_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `open' function. */
#define HAVE_OPEN 1
/* Define to 1 if you have the `realloc' function. */
#define HAVE_REALLOC 1
/* Define to 1 if you have the `setlocale' function. */
#define HAVE_SETLOCALE 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strncasecmp' function. */
#define HAVE_STRNCASECMP 1
/* Define to 1 if you have the <syslog.h> header file. */
#define HAVE_SYSLOG_H 1
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#define HAVE_SYS_CDEFS_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `uselocale' function. */
#define HAVE_USELOCALE 1
/* Define to 1 if you have the `vasprintf' function. */
//#define HAVE_VASPRINTF 1
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* Define to 1 if you have the `vsyslog' function. */
#define HAVE_VSYSLOG 1
/* Define to 1 if you have the <xlocale.h> header file. */
#define HAVE_XLOCALE_H 1
/* Have __thread */
#define HAVE___THREAD 1
/* Public define for json_inttypes.h */
#define JSON_C_HAVE_INTTYPES_H 1
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Name of package */
#define PACKAGE "json-c"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "json-c@googlegroups.com"
/* Define to the full name of this package. */
#define PACKAGE_NAME "json-c"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "json-c 0.13.99"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "json-c"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.13.99"
/* The number of bytes in type int */
#define SIZEOF_INT 4
/* The number of bytes in type int64_t */
#define SIZEOF_INT64_T 8
/* The number of bytes in type long */
#define SIZEOF_LONG 8
/* The number of bytes in type long long */
#define SIZEOF_LONG_LONG 8
/* The number of bytes in type size_t */
#define SIZEOF_SIZE_T 8
/* Specifier for __thread */
#define SPEC___THREAD __thread
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.13.99"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */

View File

@@ -0,0 +1,83 @@
/*
* $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config_json_c.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#if HAVE_SYSLOG_H
# include <syslog.h>
#endif /* HAVE_SYSLOG_H */
#if HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
#include "debug.h"
static int _syslog = 0;
static int _debug = 0;
void mc_set_debug(int debug) { _debug = debug; }
int mc_get_debug(void) { return _debug; }
extern void mc_set_syslog(int syslog)
{
_syslog = syslog;
}
void mc_debug(const char *msg, ...)
{
va_list ap;
if(_debug) {
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_DEBUG, msg, ap);
} else
#endif
vprintf(msg, ap);
va_end(ap);
}
}
void mc_error(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_ERR, msg, ap);
} else
#endif
vfprintf(stderr, msg, ap);
va_end(ap);
}
void mc_info(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_INFO, msg, ap);
} else
#endif
vfprintf(stderr, msg, ap);
va_end(ap);
}

View File

@@ -0,0 +1,75 @@
/*
* $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#ifndef _DEBUG_H_
#define _DEBUG_H_
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void mc_set_debug(int debug);
extern int mc_get_debug(void);
extern void mc_set_syslog(int syslog);
extern void mc_debug(const char *msg, ...);
extern void mc_error(const char *msg, ...);
extern void mc_info(const char *msg, ...);
#ifndef __STRING
#define __STRING(x) #x
#endif
#ifndef PARSER_BROKEN_FIXED
#define JASSERT(cond) do {} while(0)
#else
#define JASSERT(cond) do { \
if (!(cond)) { \
mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \
*(int *)0 = 1;\
abort(); \
}\
} while(0)
#endif
#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__)
#ifdef MC_MAINTAINER_MODE
#define MC_SET_DEBUG(x) mc_set_debug(x)
#define MC_GET_DEBUG() mc_get_debug()
#define MC_SET_SYSLOG(x) mc_set_syslog(x)
#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__)
#else
#define MC_SET_DEBUG(x) if (0) mc_set_debug(x)
#define MC_GET_DEBUG() (0)
#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x)
#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,38 @@
/*
* $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief A convenience header that may be included instead of other individual ones.
*/
#ifndef _json_h_
#define _json_h_
#ifdef __cplusplus
extern "C" {
#endif
#include "debug.h"
#include "linkhash.h"
#include "arraylist.h"
#include "json_util.h"
#include "json_object.h"
#include "json_pointer.h"
#include "json_tokener.h"
#include "json_object_iterator.h"
#include "json_c_version.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2012 Eric Haszlakiewicz
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
#include "config_json_c.h"
#include "json_c_version.h"
const char *json_c_version(void)
{
return JSON_C_VERSION;
}
int json_c_version_num(void)
{
return JSON_C_VERSION_NUM;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2012,2017 Eric Haszlakiewicz
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
/**
* @file
* @brief Methods for retrieving the json-c version.
*/
#ifndef _json_c_version_h_
#define _json_c_version_h_
#define JSON_C_MAJOR_VERSION 0
#define JSON_C_MINOR_VERSION 13
#define JSON_C_MICRO_VERSION 99
#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \
(JSON_C_MINOR_VERSION << 8) | \
JSON_C_MICRO_VERSION)
#define JSON_C_VERSION "0.13.99"
/**
* @see JSON_C_VERSION
* @return the version of the json-c library as a string
*/
const char *json_c_version(void); /* Returns JSON_C_VERSION */
/**
* The json-c version encoded into an int, with the low order 8 bits
* being the micro version, the next higher 8 bits being the minor version
* and the next higher 8 bits being the major version.
* For example, 7.12.99 would be 0x00070B63.
*
* @see JSON_C_VERSION_NUM
* @return the version of the json-c library as an int
*/
int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */
#endif

View File

@@ -0,0 +1,4 @@
/* json_config.h. Generated from json_config.h.in by configure. */
/* Define to 1 if you have the <inttypes.h> header file. */
#define JSON_C_HAVE_INTTYPES_H 1

View File

@@ -0,0 +1,23 @@
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#ifndef _json_inttypes_h_
#define _json_inttypes_h_
#include "json_config.h"
#ifdef JSON_C_HAVE_INTTYPES_H
/* inttypes.h includes stdint.h */
#include <inttypes.h>
#else
#include <stdint.h>
#define PRId64 "I64d"
#define SCNd64 "I64d"
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,163 @@
/**
*******************************************************************************
* @file json_object_iterator.c
*
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*******************************************************************************
*/
#include <stddef.h>
#include "json.h"
#include "json_object_private.h"
#include "json_object_iterator.h"
/**
* How It Works
*
* For each JSON Object, json-c maintains a linked list of zero
* or more lh_entry (link-hash entry) structures inside the
* Object's link-hash table (lh_table).
*
* Each lh_entry structure on the JSON Object's linked list
* represents a single name/value pair. The "next" field of the
* last lh_entry in the list is set to NULL, which terminates
* the list.
*
* We represent a valid iterator that refers to an actual
* name/value pair via a pointer to the pair's lh_entry
* structure set as the iterator's opaque_ field.
*
* We follow json-c's current pair list representation by
* representing a valid "end" iterator (one that refers past the
* last pair) with a NULL value in the iterator's opaque_ field.
*
* A JSON Object without any pairs in it will have the "head"
* field of its lh_table structure set to NULL. For such an
* object, json_object_iter_begin will return an iterator with
* the opaque_ field set to NULL, which is equivalent to the
* "end" iterator.
*
* When iterating, we simply update the iterator's opaque_ field
* to point to the next lh_entry structure in the linked list.
* opaque_ will become NULL once we iterate past the last pair
* in the list, which makes the iterator equivalent to the "end"
* iterator.
*/
/// Our current representation of the "end" iterator;
///
/// @note May not always be NULL
static const void* kObjectEndIterValue = NULL;
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj)
{
struct json_object_iterator iter;
struct lh_table* pTable;
/// @note json_object_get_object will return NULL if passed NULL
/// or a non-json_type_object instance
pTable = json_object_get_object(obj);
JASSERT(NULL != pTable);
/// @note For a pair-less Object, head is NULL, which matches our
/// definition of the "end" iterator
iter.opaque_ = pTable->head;
return iter;
}
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj)
{
struct json_object_iterator iter;
JASSERT(NULL != obj);
JASSERT(json_object_is_type(obj, json_type_object));
iter.opaque_ = kObjectEndIterValue;
return iter;
}
/**
* ****************************************************************************
*/
void
json_object_iter_next(struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
iter->opaque_ = ((const struct lh_entry *)iter->opaque_)->next;
}
/**
* ****************************************************************************
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
return (const char*)(((const struct lh_entry *)iter->opaque_)->k);
}
/**
* ****************************************************************************
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
return (struct json_object*)lh_entry_v((const struct lh_entry *)iter->opaque_);
}
/**
* ****************************************************************************
*/
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2)
{
JASSERT(NULL != iter1);
JASSERT(NULL != iter2);
return (iter1->opaque_ == iter2->opaque_);
}
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_init_default(void)
{
struct json_object_iterator iter;
/**
* @note Make this a negative, invalid value, such that
* accidental access to it would likely be trapped by the
* hardware as an invalid address.
*/
iter.opaque_ = NULL;
return iter;
}

View File

@@ -0,0 +1,240 @@
/**
*******************************************************************************
* @file json_object_iterator.h
*
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
* @brief An API for iterating over json_type_object objects,
* styled to be familiar to C++ programmers.
* Unlike json_object_object_foreach() and
* json_object_object_foreachC(), this avoids the need to expose
* json-c internals like lh_entry.
*
* API attributes: <br>
* * Thread-safe: NO<br>
* * Reentrant: NO
*
*******************************************************************************
*/
#ifndef JSON_OBJECT_ITERATOR_H
#define JSON_OBJECT_ITERATOR_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Forward declaration for the opaque iterator information.
*/
struct json_object_iter_info_;
/**
* The opaque iterator that references a name/value pair within
* a JSON Object instance or the "end" iterator value.
*/
struct json_object_iterator {
const void* opaque_;
};
/**
* forward declaration of json-c's JSON value instance structure
*/
struct json_object;
/**
* Initializes an iterator structure to a "default" value that
* is convenient for initializing an iterator variable to a
* default state (e.g., initialization list in a class'
* constructor).
*
* @code
* struct json_object_iterator iter = json_object_iter_init_default();
* MyClass() : iter_(json_object_iter_init_default())
* @endcode
*
* @note The initialized value doesn't reference any specific
* pair, is considered an invalid iterator, and MUST NOT
* be passed to any json-c API that expects a valid
* iterator.
*
* @note User and internal code MUST NOT make any assumptions
* about and dependencies on the value of the "default"
* iterator value.
*
* @return json_object_iterator
*/
struct json_object_iterator
json_object_iter_init_default(void);
/** Retrieves an iterator to the first pair of the JSON Object.
*
* @warning Any modification of the underlying pair invalidates all
* iterators to that pair.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator If the JSON Object has at
* least one pair, on return, the iterator refers
* to the first pair. If the JSON Object doesn't
* have any pairs, the returned iterator is
* equivalent to the "end" iterator for the same
* JSON Object instance.
*
* @code
* struct json_object_iterator it;
* struct json_object_iterator itEnd;
* struct json_object* obj;
*
* obj = json_tokener_parse("{'first':'george', 'age':100}");
* it = json_object_iter_begin(obj);
* itEnd = json_object_iter_end(obj);
*
* while (!json_object_iter_equal(&it, &itEnd)) {
* printf("%s\n",
* json_object_iter_peek_name(&it));
* json_object_iter_next(&it);
* }
*
* @endcode
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj);
/** Retrieves the iterator that represents the position beyond the
* last pair of the given JSON Object instance.
*
* @warning Do NOT write code that assumes that the "end"
* iterator value is NULL, even if it is so in a
* particular instance of the implementation.
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The "end" iterator and the
* equality test method, on the other hand, permit us to
* cleanly abstract pretty much any reasonable underlying
* representation without burdening the iterator
* structure with unnecessary data.
*
* @note For performance reasons, memorize the "end" iterator prior
* to any loop.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator On return, the iterator refers
* to the "end" of the Object instance's pairs
* (i.e., NOT the last pair, but "beyond the last
* pair" value)
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj);
/** Returns an iterator to the next pair, if any
*
* @warning Any modification of the underlying pair
* invalidates all iterators to that pair.
*
* @param iter [IN/OUT] Pointer to iterator that references a
* name/value pair; MUST be a valid, non-end iterator.
* WARNING: bad things will happen if invalid or "end"
* iterator is passed. Upon return will contain the
* reference to the next pair if there is one; if there
* are no more pairs, will contain the "end" iterator
* value, which may be compared against the return value
* of json_object_iter_end() for the same JSON Object
* instance.
*/
void
json_object_iter_next(struct json_object_iterator* iter);
/** Returns a const pointer to the name of the pair referenced
* by the given iterator.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if an invalid or
* "end" iterator is passed.
*
* @return const char* Pointer to the name of the referenced
* name/value pair. The name memory belongs to the
* name/value pair, will be freed when the pair is
* deleted or modified, and MUST NOT be modified or
* freed by the user.
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter);
/** Returns a pointer to the json-c instance representing the
* value of the referenced name/value pair, without altering
* the instance's reference count.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if invalid or
* "end" iterator is passed.
*
* @return struct json_object* Pointer to the json-c value
* instance of the referenced name/value pair; the
* value's reference count is not changed by this
* function: if you plan to hold on to this json-c node,
* take a look at json_object_get() and
* json_object_put(). IMPORTANT: json-c API represents
* the JSON Null value as a NULL json_object instance
* pointer.
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter);
/** Tests two iterators for equality. Typically used to test
* for end of iteration by comparing an iterator to the
* corresponding "end" iterator (that was derived from the same
* JSON Object instance).
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The equality test method, on
* the other hand, permits us to cleanly abstract pretty
* much any reasonable underlying representation.
*
* @param iter1 Pointer to first valid, non-NULL iterator
* @param iter2 POinter to second valid, non-NULL iterator
*
* @warning if a NULL iterator pointer or an uninitialized
* or invalid iterator, or iterators derived from
* different JSON Object instances are passed, bad things
* will happen!
*
* @return json_bool non-zero if iterators are equal (i.e., both
* reference the same name/value pair or are both at
* "end"); zero if they are not equal.
*/
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2);
#ifdef __cplusplus
}
#endif
#endif /* JSON_OBJECT_ITERATOR_H */

View File

@@ -0,0 +1,64 @@
/*
* $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Do not use, json-c internal, may be changed or removed at any time.
*/
#ifndef _json_object_private_h_
#define _json_object_private_h_
#ifdef __cplusplus
extern "C" {
#endif
#define LEN_DIRECT_STRING_DATA 32 /**< how many bytes are directly stored in json_object for strings? */
typedef void (json_object_private_delete_fn)(struct json_object *o);
struct json_object
{
enum json_type o_type;
json_object_private_delete_fn *_delete;
json_object_to_json_string_fn *_to_json_string;
uint_fast32_t _ref_count;
struct printbuf *_pb;
union data {
json_bool c_boolean;
double c_double;
int64_t c_int64;
struct lh_table *c_object;
struct array_list *c_array;
struct {
union {
/* optimize: if we have small strings, we can store them
* directly. This saves considerable CPU cycles AND memory.
*/
char *ptr;
char data[LEN_DIRECT_STRING_DATA];
} str;
int len;
} c_string;
} o;
json_object_delete_fn *_user_delete;
void *_userdata;
};
void _json_c_set_last_err(const char *err_fmt, ...);
extern const char *json_number_chars;
extern const char *json_hex_chars;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,327 @@
/*
* Copyright (c) 2016 Alexandru Ardelean.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config_json_c.h"
#include "strerror_override.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "json_pointer.h"
#include "strdup_compat.h"
#include "vasprintf_compat.h"
/**
* JavaScript Object Notation (JSON) Pointer
* RFC 6901 - https://tools.ietf.org/html/rfc6901
*/
static void string_replace_all_occurrences_with_char(char *s, const char *occur, char repl_char)
{
int slen = strlen(s);
int skip = strlen(occur) - 1; /* length of the occurence, minus the char we're replacing */
char *p = s;
while ((p = strstr(p, occur))) {
*p = repl_char;
p++;
slen -= skip;
memmove(p, (p + skip), slen - (p - s) + 1); /* includes null char too */
}
}
static int is_valid_index(struct json_object *jo, const char *path, int32_t *idx)
{
int i, len = strlen(path);
/* this code-path optimizes a bit, for when we reference the 0-9 index range in a JSON array
and because leading zeros not allowed */
if (len == 1) {
if (isdigit((int)path[0])) {
*idx = (path[0] - '0');
goto check_oob;
}
errno = EINVAL;
return 0;
}
/* leading zeros not allowed per RFC */
if (path[0] == '0') {
errno = EINVAL;
return 0;
}
/* RFC states base-10 decimals */
for (i = 0; i < len; i++) {
if (!isdigit((int)path[i])) {
errno = EINVAL;
return 0;
}
}
*idx = strtol(path, NULL, 10);
if (*idx < 0) {
errno = EINVAL;
return 0;
}
check_oob:
len = json_object_array_length(jo);
if (*idx >= len) {
errno = ENOENT;
return 0;
}
return 1;
}
static int json_pointer_get_single_path(struct json_object *obj, char *path, struct json_object **value)
{
if (json_object_is_type(obj, json_type_array)) {
int32_t idx;
if (!is_valid_index(obj, path, &idx))
return -1;
obj = json_object_array_get_idx(obj, idx);
if (obj) {
if (value)
*value = obj;
return 0;
}
/* Entry not found */
errno = ENOENT;
return -1;
}
/* RFC states that we first must eval all ~1 then all ~0 */
string_replace_all_occurrences_with_char(path, "~1", '/');
string_replace_all_occurrences_with_char(path, "~0", '~');
if (!json_object_object_get_ex(obj, path, value)) {
errno = ENOENT;
return -1;
}
return 0;
}
static int json_pointer_set_single_path(
struct json_object *parent,
const char *path,
struct json_object *value)
{
if (json_object_is_type(parent, json_type_array)) {
int32_t idx;
/* RFC (Chapter 4) states that '-' may be used to add new elements to an array */
if (path[0] == '-' && path[1] == '\0')
return json_object_array_add(parent, value);
if (!is_valid_index(parent, path, &idx))
return -1;
return json_object_array_put_idx(parent, idx, value);
}
/* path replacements should have been done in json_pointer_get_single_path(),
and we should still be good here */
if (json_object_is_type(parent, json_type_object))
return json_object_object_add(parent, path, value);
/* Getting here means that we tried to "dereference" a primitive JSON type (like string, int, bool).
i.e. add a sub-object to it */
errno = ENOENT;
return -1;
}
static int json_pointer_get_recursive(
struct json_object *obj,
char *path,
struct json_object **value)
{
char *endp;
int rc;
/* All paths (on each recursion level must have a leading '/' */
if (path[0] != '/') {
errno = EINVAL;
return -1;
}
path++;
endp = strchr(path, '/');
if (endp)
*endp = '\0';
/* If we err-ed here, return here */
if ((rc = json_pointer_get_single_path(obj, path, &obj)))
return rc;
if (endp) {
*endp = '/'; /* Put the slash back, so that the sanity check passes on next recursion level */
return json_pointer_get_recursive(obj, endp, value);
}
/* We should be at the end of the recursion here */
if (value)
*value = obj;
return 0;
}
int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res)
{
char *path_copy = NULL;
int rc;
if (!obj || !path) {
errno = EINVAL;
return -1;
}
if (path[0] == '\0') {
if (res)
*res = obj;
return 0;
}
/* pass a working copy to the recursive call */
if (!(path_copy = strdup(path))) {
errno = ENOMEM;
return -1;
}
rc = json_pointer_get_recursive(obj, path_copy, res);
free(path_copy);
return rc;
}
int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...)
{
char *path_copy = NULL;
int rc = 0;
va_list args;
if (!obj || !path_fmt) {
errno = EINVAL;
return -1;
}
va_start(args, path_fmt);
rc = vasprintf(&path_copy, path_fmt, args);
va_end(args);
if (rc < 0)
return rc;
if (path_copy[0] == '\0') {
if (res)
*res = obj;
goto out;
}
rc = json_pointer_get_recursive(obj, path_copy, res);
out:
free(path_copy);
return rc;
}
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value)
{
const char *endp;
char *path_copy = NULL;
struct json_object *set = NULL;
int rc;
if (!obj || !path) {
errno = EINVAL;
return -1;
}
if (path[0] == '\0') {
json_object_put(*obj);
*obj = value;
return 0;
}
if (path[0] != '/') {
errno = EINVAL;
return -1;
}
/* If there's only 1 level to set, stop here */
if ((endp = strrchr(path, '/')) == path) {
path++;
return json_pointer_set_single_path(*obj, path, value);
}
/* pass a working copy to the recursive call */
if (!(path_copy = strdup(path))) {
errno = ENOMEM;
return -1;
}
path_copy[endp - path] = '\0';
rc = json_pointer_get_recursive(*obj, path_copy, &set);
free(path_copy);
if (rc)
return rc;
endp++;
return json_pointer_set_single_path(set, endp, value);
}
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...)
{
char *endp;
char *path_copy = NULL;
struct json_object *set = NULL;
va_list args;
int rc = 0;
if (!obj || !path_fmt) {
errno = EINVAL;
return -1;
}
/* pass a working copy to the recursive call */
va_start(args, path_fmt);
rc = vasprintf(&path_copy, path_fmt, args);
va_end(args);
if (rc < 0)
return rc;
if (path_copy[0] == '\0') {
json_object_put(*obj);
*obj = value;
goto out;
}
if (path_copy[0] != '/') {
errno = EINVAL;
rc = -1;
goto out;
}
/* If there's only 1 level to set, stop here */
if ((endp = strrchr(path_copy, '/')) == path_copy) {
set = *obj;
goto set_single_path;
}
*endp = '\0';
rc = json_pointer_get_recursive(*obj, path_copy, &set);
if (rc)
goto out;
set_single_path:
endp++;
rc = json_pointer_set_single_path(set, endp, value);
out:
free(path_copy);
return rc;
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2016 Alexadru Ardelean.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief JSON Pointer (RFC 6901) implementation for retrieving
* objects from a json-c object tree.
*/
#ifndef _json_pointer_h_
#define _json_pointer_h_
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Retrieves a JSON sub-object from inside another JSON object
* using the JSON pointer notation as defined in RFC 6901
* https://tools.ietf.org/html/rfc6901
*
* The returned JSON sub-object is equivalent to parsing manually the
* 'obj' JSON tree ; i.e. it's not a new object that is created, but rather
* a pointer inside the JSON tree.
*
* Internally, this is equivalent to doing a series of 'json_object_object_get()'
* and 'json_object_array_get_idx()' along the given 'path'.
*
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
* is added after the 'res' param will be treated as an argument for 'path'
* Example: json_pointer_get(obj, "/foo/%d/%s", &res, 0, bar)
* This means, that you need to escape '%' with '%%' (just like in printf())
*
* @param obj the json_object instance/tree from where to retrieve sub-objects
* @param path a (RFC6901) string notation for the sub-object to retrieve
* @param res a pointer where to store a reference to the json_object
* associated with the given path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res);
/**
* This is a variant of 'json_pointer_get()' that supports printf() style arguments.
*
* Example: json_pointer_getf(obj, res, "/foo/%d/%s", 0, bak)
* This also means that you need to escape '%' with '%%' (just like in printf())
*
* Please take into consideration all recommended 'printf()' format security
* aspects when using this function.
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param res a pointer where to store a reference to the json_object
* associated with the given path
* @param path_fmt a printf() style format for the path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...);
/**
* Sets JSON object 'value' in the 'obj' tree at the location specified
* by the 'path'. 'path' is JSON pointer notation as defined in RFC 6901
* https://tools.ietf.org/html/rfc6901
*
* Note that 'obj' is a double pointer, mostly for the "" (empty string)
* case, where the entire JSON object would be replaced by 'value'.
* In the case of the "" path, the object at '*obj' will have it's refcount
* decremented with 'json_object_put()' and the 'value' object will be assigned to it.
*
* For other cases (JSON sub-objects) ownership of 'value' will be transferred into
* '*obj' via 'json_object_object_add()' & 'json_object_array_put_idx()', so the
* only time the refcount should be decremented for 'value' is when the return value of
* 'json_pointer_set()' is negative (meaning the 'value' object did not get set into '*obj').
*
* That also implies that 'json_pointer_set()' does not do any refcount incrementing.
* (Just that single decrement that was mentioned above).
*
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
* is added after the 'value' param will be treated as an argument for 'path'
* Example: json_pointer_set(obj, "/foo/%d/%s", value, 0, bak)
* This means, that you need to escape '%' with '%%' (just like in printf())
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param path a (RFC6901) string notation for the sub-object to set in the tree
* @param value object to set at path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value);
/**
* This is a variant of 'json_pointer_set()' that supports printf() style arguments.
*
* Example: json_pointer_setf(obj, value, "/foo/%d/%s", 0, bak)
* This also means that you need to escape '%' with '%%' (just like in printf())
*
* Please take into consideration all recommended 'printf()' format security
* aspects when using this function.
*
* @param obj the json_object instance/tree to which to add a sub-object
* @param value object to set at path
* @param path_fmt a printf() style format for the path
*
* @return negative if an error (or not found), or 0 if succeeded
*/
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,997 @@
/*
* $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
#include "config_json_c.h"
#include <math.h>
#include "math_compat.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include "debug.h"
#include "printbuf.h"
#include "arraylist.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_object_private.h"
#include "json_tokener.h"
#include "json_util.h"
#include "strdup_compat.h"
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif /* HAVE_LOCALE_H */
#ifdef HAVE_XLOCALE_H
#include <xlocale.h>
#endif
#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
#if !HAVE_STRNCASECMP && defined(_MSC_VER)
/* MSC has the version as _strnicmp */
# define strncasecmp _strnicmp
#elif !HAVE_STRNCASECMP
# error You do not have strncasecmp on your system.
#endif /* HAVE_STRNCASECMP */
/* Use C99 NAN by default; if not available, nan("") should work too. */
#ifndef NAN
#define NAN nan("")
#endif /* !NAN */
static const char json_null_str[] = "null";
static const int json_null_str_len = sizeof(json_null_str) - 1;
static const char json_inf_str[] = "Infinity";
static const char json_inf_str_lower[] = "infinity";
static const unsigned int json_inf_str_len = sizeof(json_inf_str) - 1;
static const char json_nan_str[] = "NaN";
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
static const char json_true_str[] = "true";
static const int json_true_str_len = sizeof(json_true_str) - 1;
static const char json_false_str[] = "false";
static const int json_false_str_len = sizeof(json_false_str) - 1;
static const char* json_tokener_errors[] = {
"success",
"continue",
"nesting too deep",
"unexpected end of data",
"unexpected character",
"null expected",
"boolean expected",
"number expected",
"array value separator ',' expected",
"quoted object property name expected",
"object property name separator ':' expected",
"object value separator ',' expected",
"invalid string sequence",
"expected comment",
"buffer size overflow"
};
const char *json_tokener_error_desc(enum json_tokener_error jerr)
{
int jerr_int = (int) jerr;
if (jerr_int < 0 ||
jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
return "Unknown error, "
"invalid json_tokener_error value passed to json_tokener_error_desc()";
return json_tokener_errors[jerr];
}
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
{
return tok->err;
}
/* Stuff for decoding unicode sequences */
#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00)
#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD };
struct json_tokener* json_tokener_new_ex(int depth)
{
struct json_tokener *tok;
tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
if (!tok) return NULL;
tok->stack = (struct json_tokener_srec *) calloc(depth,
sizeof(struct json_tokener_srec));
if (!tok->stack) {
free(tok);
return NULL;
}
tok->pb = printbuf_new();
tok->max_depth = depth;
json_tokener_reset(tok);
return tok;
}
struct json_tokener* json_tokener_new(void)
{
return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
}
void json_tokener_free(struct json_tokener *tok)
{
json_tokener_reset(tok);
if (tok->pb) printbuf_free(tok->pb);
free(tok->stack);
free(tok);
}
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
{
tok->stack[depth].state = json_tokener_state_eatws;
tok->stack[depth].saved_state = json_tokener_state_start;
json_object_put(tok->stack[depth].current);
tok->stack[depth].current = NULL;
free(tok->stack[depth].obj_field_name);
tok->stack[depth].obj_field_name = NULL;
}
void json_tokener_reset(struct json_tokener *tok)
{
int i;
if (!tok)
return;
for(i = tok->depth; i >= 0; i--)
json_tokener_reset_level(tok, i);
tok->depth = 0;
tok->err = json_tokener_success;
}
struct json_object* json_tokener_parse(const char *str)
{
enum json_tokener_error jerr_ignored;
struct json_object* obj;
obj = json_tokener_parse_verbose(str, &jerr_ignored);
return obj;
}
struct json_object* json_tokener_parse_verbose(const char *str,
enum json_tokener_error *error)
{
struct json_tokener* tok;
struct json_object* obj;
tok = json_tokener_new();
if (!tok)
return NULL;
obj = json_tokener_parse_ex(tok, str, -1);
*error = tok->err;
if(tok->err != json_tokener_success) {
if (obj != NULL)
json_object_put(obj);
obj = NULL;
}
json_tokener_free(tok);
return obj;
}
#define state tok->stack[tok->depth].state
#define saved_state tok->stack[tok->depth].saved_state
#define current tok->stack[tok->depth].current
#define obj_field_name tok->stack[tok->depth].obj_field_name
/* Optimization:
* json_tokener_parse_ex() consumed a lot of CPU in its main loop,
* iterating character-by character. A large performance boost is
* achieved by using tighter loops to locally handle units such as
* comments and strings. Loops that handle an entire token within
* their scope also gather entire strings and pass them to
* printbuf_memappend() in a single call, rather than calling
* printbuf_memappend() one char at a time.
*
* PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
* common to both the main loop and the tighter loops.
*/
/* PEEK_CHAR(dest, tok) macro:
* Peeks at the current char and stores it in dest.
* Returns 1 on success, sets tok->err and returns 0 if no more chars.
* Implicit inputs: str, len vars
*/
#define PEEK_CHAR(dest, tok) \
(((tok)->char_offset == len) ? \
(((tok)->depth == 0 && \
state == json_tokener_state_eatws && \
saved_state == json_tokener_state_finish \
) ? \
(((tok)->err = json_tokener_success), 0) \
: \
(((tok)->err = json_tokener_continue), 0) \
) : \
(((dest) = *str), 1) \
)
/* ADVANCE_CHAR() macro:
* Incrementes str & tok->char_offset.
* For convenience of existing conditionals, returns the old value of c (0 on eof)
* Implicit inputs: c var
*/
#define ADVANCE_CHAR(str, tok) \
( ++(str), ((tok)->char_offset)++, c)
/* End optimization macro defs */
struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len)
{
struct json_object *obj = NULL;
char c = '\1';
#ifdef HAVE_USELOCALE
locale_t oldlocale = uselocale(NULL);
locale_t newloc;
#elif defined(HAVE_SETLOCALE)
char *oldlocale = NULL;
#endif
tok->char_offset = 0;
tok->err = json_tokener_success;
/* this interface is presently not 64-bit clean due to the int len argument
and the internal printbuf interface that takes 32-bit int len arguments
so the function limits the maximum string size to INT32_MAX (2GB).
If the function is called with len == -1 then strlen is called to check
the string length is less than INT32_MAX (2GB) */
if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) {
tok->err = json_tokener_error_size;
return NULL;
}
#ifdef HAVE_USELOCALE
{
locale_t duploc = duplocale(oldlocale);
newloc = newlocale(LC_NUMERIC, "C", duploc);
// XXX at least Debian 8.4 has a bug in newlocale where it doesn't
// change the decimal separator unless you set LC_TIME!
if (newloc)
{
duploc = newloc; // original duploc has been freed by newlocale()
newloc = newlocale(LC_TIME, "C", duploc);
}
if (newloc == NULL)
{
freelocale(duploc);
return NULL;
}
uselocale(newloc);
}
#elif defined(HAVE_SETLOCALE)
{
char *tmplocale;
tmplocale = setlocale(LC_NUMERIC, NULL);
if (tmplocale) oldlocale = strdup(tmplocale);
setlocale(LC_NUMERIC, "C");
}
#endif
while (PEEK_CHAR(c, tok)) {
redo_char:
switch(state) {
case json_tokener_state_eatws:
/* Advance until we change state */
while (isspace((int)c)) {
if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
goto out;
}
if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) {
printbuf_reset(tok->pb);
printbuf_memappend_fast(tok->pb, &c, 1);
state = json_tokener_state_comment_start;
} else {
state = saved_state;
goto redo_char;
}
break;
case json_tokener_state_start:
switch(c) {
case '{':
state = json_tokener_state_eatws;
saved_state = json_tokener_state_object_field_start;
current = json_object_new_object();
if(current == NULL)
goto out;
break;
case '[':
state = json_tokener_state_eatws;
saved_state = json_tokener_state_array;
current = json_object_new_array();
if(current == NULL)
goto out;
break;
case 'I':
case 'i':
state = json_tokener_state_inf;
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
case 'N':
case 'n':
state = json_tokener_state_null; // or NaN
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
case '\'':
if (tok->flags & JSON_TOKENER_STRICT) {
/* in STRICT mode only double-quote are allowed */
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
/* FALLTHRU */
case '"':
state = json_tokener_state_string;
printbuf_reset(tok->pb);
tok->quote_char = c;
break;
case 'T':
case 't':
case 'F':
case 'f':
state = json_tokener_state_boolean;
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
state = json_tokener_state_number;
printbuf_reset(tok->pb);
tok->is_double = 0;
goto redo_char;
default:
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
break;
case json_tokener_state_finish:
if(tok->depth == 0) goto out;
obj = json_object_get(current);
json_tokener_reset_level(tok, tok->depth);
tok->depth--;
goto redo_char;
case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
{
/* If we were guaranteed to have len set, then we could (usually) handle
* the entire "Infinity" check in a single strncmp (strncasecmp), but
* since len might be -1 (i.e. "read until \0"), we need to check it
* a character at a time.
* Trying to handle it both ways would make this code considerably more
* complicated with likely little performance benefit.
*/
int is_negative = 0;
const char *_json_inf_str = json_inf_str;
if (!(tok->flags & JSON_TOKENER_STRICT))
_json_inf_str = json_inf_str_lower;
/* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
while (tok->st_pos < (int)json_inf_str_len)
{
char inf_char = *str;
if (!(tok->flags & JSON_TOKENER_STRICT))
inf_char = tolower((int)*str);
if (inf_char != _json_inf_str[tok->st_pos])
{
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
tok->st_pos++;
(void)ADVANCE_CHAR(str, tok);
if (!PEEK_CHAR(c, tok))
{
/* out of input chars, for now at least */
goto out;
}
}
/* We checked the full length of "Infinity", so create the object.
* When handling -Infinity, the number parsing code will have dropped
* the "-" into tok->pb for us, so check it now.
*/
if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
{
is_negative = 1;
}
current = json_object_new_double(is_negative
? -INFINITY : INFINITY);
if (current == NULL)
goto out;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
break;
case json_tokener_state_null: /* aka starts with 'n' */
{
int size;
int size_nan;
printbuf_memappend_fast(tok->pb, &c, 1);
size = json_min(tok->st_pos+1, json_null_str_len);
size_nan = json_min(tok->st_pos+1, json_nan_str_len);
if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_null_str, tok->pb->buf, size) == 0)
|| (strncmp(json_null_str, tok->pb->buf, size) == 0)
) {
if (tok->st_pos == json_null_str_len) {
current = NULL;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
}
else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
(strncmp(json_nan_str, tok->pb->buf, size_nan) == 0)
)
{
if (tok->st_pos == json_nan_str_len)
{
current = json_object_new_double(NAN);
if (current == NULL)
goto out;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else {
tok->err = json_tokener_error_parse_null;
goto out;
}
tok->st_pos++;
}
break;
case json_tokener_state_comment_start:
if(c == '*') {
state = json_tokener_state_comment;
} else if(c == '/') {
state = json_tokener_state_comment_eol;
} else {
tok->err = json_tokener_error_parse_comment;
goto out;
}
printbuf_memappend_fast(tok->pb, &c, 1);
break;
case json_tokener_state_comment:
{
/* Advance until we change state */
const char *case_start = str;
while(c != '*') {
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
state = json_tokener_state_comment_end;
}
break;
case json_tokener_state_comment_eol:
{
/* Advance until we change state */
const char *case_start = str;
while(c != '\n') {
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
state = json_tokener_state_eatws;
}
break;
case json_tokener_state_comment_end:
printbuf_memappend_fast(tok->pb, &c, 1);
if(c == '/') {
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
state = json_tokener_state_eatws;
} else {
state = json_tokener_state_comment;
}
break;
case json_tokener_state_string:
{
/* Advance until we change state */
const char *case_start = str;
while(1) {
if(c == tok->quote_char) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
if(current == NULL)
goto out;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
break;
} else if(c == '\\') {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
saved_state = json_tokener_state_string;
state = json_tokener_state_string_escape;
break;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
}
break;
case json_tokener_state_string_escape:
switch(c) {
case '"':
case '\\':
case '/':
printbuf_memappend_fast(tok->pb, &c, 1);
state = saved_state;
break;
case 'b':
case 'n':
case 'r':
case 't':
case 'f':
if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1);
state = saved_state;
break;
case 'u':
tok->ucs_char = 0;
tok->st_pos = 0;
state = json_tokener_state_escape_unicode;
break;
default:
tok->err = json_tokener_error_parse_string;
goto out;
}
break;
case json_tokener_state_escape_unicode:
{
unsigned int got_hi_surrogate = 0;
/* Handle a 4-byte sequence, or two sequences if a surrogate pair */
while(1) {
if (c && strchr(json_hex_chars, c)) {
tok->ucs_char += ((unsigned int)jt_hexdigit(c) << ((3-tok->st_pos++)*4));
if(tok->st_pos == 4) {
unsigned char unescaped_utf[4];
if (got_hi_surrogate) {
if (IS_LOW_SURROGATE(tok->ucs_char)) {
/* Recalculate the ucs_char, then fall thru to process normally */
tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
} else {
/* Hi surrogate was not followed by a low surrogate */
/* Replace the hi and process the rest normally */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
got_hi_surrogate = 0;
}
if (tok->ucs_char < 0x80) {
unescaped_utf[0] = tok->ucs_char;
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1);
} else if (tok->ucs_char < 0x800) {
unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2);
} else if (IS_HIGH_SURROGATE(tok->ucs_char)) {
/* Got a high surrogate. Remember it and look for the
* the beginning of another sequence, which should be the
* low surrogate.
*/
got_hi_surrogate = tok->ucs_char;
/* Not at end, and the next two chars should be "\u" */
if ((len == -1 || len > (tok->char_offset + 2)) &&
// str[0] != '0' && // implied by json_hex_chars, above.
(str[1] == '\\') &&
(str[2] == 'u'))
{
/* Advance through the 16 bit surrogate, and move on to the
* next sequence. The next step is to process the following
* characters.
*/
if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) {
printbuf_memappend_fast(tok->pb,
(char*) utf8_replacement_char, 3);
}
/* Advance to the first char of the next sequence and
* continue processing with the next sequence.
*/
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb,
(char*) utf8_replacement_char, 3);
goto out;
}
tok->ucs_char = 0;
tok->st_pos = 0;
continue; /* other json_tokener_state_escape_unicode */
} else {
/* Got a high surrogate without another sequence following
* it. Put a replacement char in for the hi surrogate
* and pretend we finished.
*/
printbuf_memappend_fast(tok->pb,
(char*) utf8_replacement_char, 3);
}
} else if (IS_LOW_SURROGATE(tok->ucs_char)) {
/* Got a low surrogate not preceded by a high */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
} else if (tok->ucs_char < 0x10000) {
unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3);
} else if (tok->ucs_char < 0x110000) {
unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4);
} else {
/* Don't know what we got--insert the replacement char */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
state = saved_state;
break;
}
} else {
tok->err = json_tokener_error_parse_string;
goto out;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
if (got_hi_surrogate) /* Clean up any pending chars */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
goto out;
}
}
}
break;
case json_tokener_state_boolean:
{
int size1, size2;
printbuf_memappend_fast(tok->pb, &c, 1);
size1 = json_min(tok->st_pos+1, json_true_str_len);
size2 = json_min(tok->st_pos+1, json_false_str_len);
if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_true_str, tok->pb->buf, size1) == 0)
|| (strncmp(json_true_str, tok->pb->buf, size1) == 0)
) {
if(tok->st_pos == json_true_str_len) {
current = json_object_new_boolean(1);
if(current == NULL)
goto out;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_false_str, tok->pb->buf, size2) == 0)
|| (strncmp(json_false_str, tok->pb->buf, size2) == 0)) {
if(tok->st_pos == json_false_str_len) {
current = json_object_new_boolean(0);
if(current == NULL)
goto out;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else {
tok->err = json_tokener_error_parse_boolean;
goto out;
}
tok->st_pos++;
}
break;
case json_tokener_state_number:
{
/* Advance until we change state */
const char *case_start = str;
int case_len=0;
int is_exponent=0;
int negativesign_next_possible_location=1;
while(c && strchr(json_number_chars, c)) {
++case_len;
/* non-digit characters checks */
/* note: since the main loop condition to get here was
an input starting with 0-9 or '-', we are
protected from input starting with '.' or
e/E. */
if (c == '.') {
if (tok->is_double != 0) {
/* '.' can only be found once, and out of the exponent part.
Thus, if the input is already flagged as double, it
is invalid. */
tok->err = json_tokener_error_parse_number;
goto out;
}
tok->is_double = 1;
}
if (c == 'e' || c == 'E') {
if (is_exponent != 0) {
/* only one exponent possible */
tok->err = json_tokener_error_parse_number;
goto out;
}
is_exponent = 1;
tok->is_double = 1;
/* the exponent part can begin with a negative sign */
negativesign_next_possible_location = case_len + 1;
}
if (c == '-' && case_len != negativesign_next_possible_location) {
/* If the negative sign is not where expected (ie
start of input or start of exponent part), the
input is invalid. */
tok->err = json_tokener_error_parse_number;
goto out;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, case_len);
goto out;
}
}
if (case_len>0)
printbuf_memappend_fast(tok->pb, case_start, case_len);
// Check for -Infinity
if (tok->pb->buf[0] == '-' && case_len <= 1 &&
(c == 'i' || c == 'I'))
{
state = json_tokener_state_inf;
tok->st_pos = 0;
goto redo_char;
}
}
{
int64_t num64;
double numd;
if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
if (num64 && tok->pb->buf[0]=='0' &&
(tok->flags & JSON_TOKENER_STRICT)) {
/* in strict mode, number must not start with 0 */
tok->err = json_tokener_error_parse_number;
goto out;
}
current = json_object_new_int64(num64);
if(current == NULL)
goto out;
}
else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0)
{
current = json_object_new_double_s(numd, tok->pb->buf);
if(current == NULL)
goto out;
} else {
tok->err = json_tokener_error_parse_number;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
break;
case json_tokener_state_array_after_sep:
case json_tokener_state_array:
if(c == ']') {
if (state == json_tokener_state_array_after_sep &&
(tok->flags & JSON_TOKENER_STRICT))
{
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else {
if(tok->depth >= tok->max_depth-1) {
tok->err = json_tokener_error_depth;
goto out;
}
state = json_tokener_state_array_add;
tok->depth++;
json_tokener_reset_level(tok, tok->depth);
goto redo_char;
}
break;
case json_tokener_state_array_add:
if( json_object_array_add(current, obj) != 0 )
goto out;
saved_state = json_tokener_state_array_sep;
state = json_tokener_state_eatws;
goto redo_char;
case json_tokener_state_array_sep:
if(c == ']') {
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if(c == ',') {
saved_state = json_tokener_state_array_after_sep;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_array;
goto out;
}
break;
case json_tokener_state_object_field_start:
case json_tokener_state_object_field_start_after_sep:
if(c == '}') {
if (state == json_tokener_state_object_field_start_after_sep &&
(tok->flags & JSON_TOKENER_STRICT))
{
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if (c == '"' || c == '\'') {
tok->quote_char = c;
printbuf_reset(tok->pb);
state = json_tokener_state_object_field;
} else {
tok->err = json_tokener_error_parse_object_key_name;
goto out;
}
break;
case json_tokener_state_object_field:
{
/* Advance until we change state */
const char *case_start = str;
while(1) {
if(c == tok->quote_char) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
obj_field_name = strdup(tok->pb->buf);
saved_state = json_tokener_state_object_field_end;
state = json_tokener_state_eatws;
break;
} else if(c == '\\') {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
saved_state = json_tokener_state_object_field;
state = json_tokener_state_string_escape;
break;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
}
break;
case json_tokener_state_object_field_end:
if(c == ':') {
saved_state = json_tokener_state_object_value;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_object_key_sep;
goto out;
}
break;
case json_tokener_state_object_value:
if(tok->depth >= tok->max_depth-1) {
tok->err = json_tokener_error_depth;
goto out;
}
state = json_tokener_state_object_value_add;
tok->depth++;
json_tokener_reset_level(tok, tok->depth);
goto redo_char;
case json_tokener_state_object_value_add:
json_object_object_add(current, obj_field_name, obj);
free(obj_field_name);
obj_field_name = NULL;
saved_state = json_tokener_state_object_sep;
state = json_tokener_state_eatws;
goto redo_char;
case json_tokener_state_object_sep:
/* { */
if(c == '}') {
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if(c == ',') {
saved_state = json_tokener_state_object_field_start_after_sep;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_object_value_sep;
goto out;
}
break;
}
if (!ADVANCE_CHAR(str, tok))
goto out;
} /* while(PEEK_CHAR) */
out:
if (c &&
(state == json_tokener_state_finish) &&
(tok->depth == 0) &&
(tok->flags & JSON_TOKENER_STRICT)) {
/* unexpected char after JSON data */
tok->err = json_tokener_error_parse_unexpected;
}
if (!c) { /* We hit an eof char (0) */
if(state != json_tokener_state_finish &&
saved_state != json_tokener_state_finish)
tok->err = json_tokener_error_parse_eof;
}
#ifdef HAVE_USELOCALE
uselocale(oldlocale);
freelocale(newloc);
#elif defined(HAVE_SETLOCALE)
setlocale(LC_NUMERIC, oldlocale);
free(oldlocale);
#endif
if (tok->err == json_tokener_success)
{
json_object *ret = json_object_get(current);
int ii;
/* Partially reset, so we parse additional objects on subsequent calls. */
for(ii = tok->depth; ii >= 0; ii--)
json_tokener_reset_level(tok, ii);
return ret;
}
MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
json_tokener_errors[tok->err], tok->char_offset);
return NULL;
}
void json_tokener_set_flags(struct json_tokener *tok, int flags)
{
tok->flags = flags;
}

View File

@@ -0,0 +1,216 @@
/*
* $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
/**
* @file
* @brief Methods to parse an input string into a tree of json_object objects.
*/
#ifndef _json_tokener_h_
#define _json_tokener_h_
#include <stddef.h>
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
enum json_tokener_error {
json_tokener_success,
json_tokener_continue,
json_tokener_error_depth,
json_tokener_error_parse_eof,
json_tokener_error_parse_unexpected,
json_tokener_error_parse_null,
json_tokener_error_parse_boolean,
json_tokener_error_parse_number,
json_tokener_error_parse_array,
json_tokener_error_parse_object_key_name,
json_tokener_error_parse_object_key_sep,
json_tokener_error_parse_object_value_sep,
json_tokener_error_parse_string,
json_tokener_error_parse_comment,
json_tokener_error_size
};
enum json_tokener_state {
json_tokener_state_eatws,
json_tokener_state_start,
json_tokener_state_finish,
json_tokener_state_null,
json_tokener_state_comment_start,
json_tokener_state_comment,
json_tokener_state_comment_eol,
json_tokener_state_comment_end,
json_tokener_state_string,
json_tokener_state_string_escape,
json_tokener_state_escape_unicode,
json_tokener_state_boolean,
json_tokener_state_number,
json_tokener_state_array,
json_tokener_state_array_add,
json_tokener_state_array_sep,
json_tokener_state_object_field_start,
json_tokener_state_object_field,
json_tokener_state_object_field_end,
json_tokener_state_object_value,
json_tokener_state_object_value_add,
json_tokener_state_object_sep,
json_tokener_state_array_after_sep,
json_tokener_state_object_field_start_after_sep,
json_tokener_state_inf
};
struct json_tokener_srec
{
enum json_tokener_state state, saved_state;
struct json_object *obj;
struct json_object *current;
char *obj_field_name;
};
#define JSON_TOKENER_DEFAULT_DEPTH 32
struct json_tokener
{
char *str;
struct printbuf *pb;
int max_depth, depth, is_double, st_pos, char_offset;
enum json_tokener_error err;
unsigned int ucs_char;
char quote_char;
struct json_tokener_srec *stack;
int flags;
};
/**
* @deprecated Unused in json-c code
*/
typedef struct json_tokener json_tokener;
/**
* Be strict when parsing JSON input. Use caution with
* this flag as what is considered valid may become more
* restrictive from one release to the next, causing your
* code to fail on previously working input.
*
* This flag is not set by default.
*
* @see json_tokener_set_flags()
*/
#define JSON_TOKENER_STRICT 0x01
/**
* Given an error previously returned by json_tokener_get_error(),
* return a human readable description of the error.
*
* @return a generic error message is returned if an invalid error value is provided.
*/
const char *json_tokener_error_desc(enum json_tokener_error jerr);
/**
* Retrieve the error caused by the last call to json_tokener_parse_ex(),
* or json_tokener_success if there is no error.
*
* When parsing a JSON string in pieces, if the tokener is in the middle
* of parsing this will return json_tokener_continue.
*
* See also json_tokener_error_desc().
*/
JSON_EXPORT enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
JSON_EXPORT struct json_tokener* json_tokener_new(void);
JSON_EXPORT struct json_tokener* json_tokener_new_ex(int depth);
JSON_EXPORT void json_tokener_free(struct json_tokener *tok);
JSON_EXPORT void json_tokener_reset(struct json_tokener *tok);
JSON_EXPORT struct json_object* json_tokener_parse(const char *str);
JSON_EXPORT struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);
/**
* Set flags that control how parsing will be done.
*/
JSON_EXPORT void json_tokener_set_flags(struct json_tokener *tok, int flags);
/**
* Parse a string and return a non-NULL json_object if a valid JSON value
* is found. The string does not need to be a JSON object or array;
* it can also be a string, number or boolean value.
*
* A partial JSON string can be parsed. If the parsing is incomplete,
* NULL will be returned and json_tokener_get_error() will return
* json_tokener_continue.
* json_tokener_parse_ex() can then be called with additional bytes in str
* to continue the parsing.
*
* If json_tokener_parse_ex() returns NULL and the error is anything other than
* json_tokener_continue, a fatal error has occurred and parsing must be
* halted. Then, the tok object must not be reused until json_tokener_reset() is
* called.
*
* When a valid JSON value is parsed, a non-NULL json_object will be
* returned. Also, json_tokener_get_error() will return json_tokener_success.
* Be sure to check the type with json_object_is_type() or
* json_object_get_type() before using the object.
*
* @b XXX this shouldn't use internal fields:
* Trailing characters after the parsed value do not automatically cause an
* error. It is up to the caller to decide whether to treat this as an
* error or to handle the additional characters, perhaps by parsing another
* json value starting from that point.
*
* Extra characters can be detected by comparing the tok->char_offset against
* the length of the last len parameter passed in.
*
* The tokener does \b not maintain an internal buffer so the caller is
* responsible for calling json_tokener_parse_ex with an appropriate str
* parameter starting with the extra characters.
*
* This interface is presently not 64-bit clean due to the int len argument
* so the function limits the maximum string size to INT32_MAX (2GB).
* If the function is called with len == -1 then strlen is called to check
* the string length is less than INT32_MAX (2GB)
*
* Example:
* @code
json_object *jobj = NULL;
const char *mystring = NULL;
int stringlen = 0;
enum json_tokener_error jerr;
do {
mystring = ... // get JSON string, e.g. read from file, etc...
stringlen = strlen(mystring);
jobj = json_tokener_parse_ex(tok, mystring, stringlen);
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
if (jerr != json_tokener_success)
{
fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
// Handle errors, as appropriate for your application.
}
if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
{
// Handle extra characters after parsed object as desired.
// e.g. issue an error, parse another object from that point, etc...
}
// Success, use jobj here.
@endcode
*
* @param tok a json_tokener previously allocated with json_tokener_new()
* @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated.
* @param len the length of str
*/
JSON_EXPORT struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,243 @@
/*
* $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config_json_c.h"
#undef realloc
#include "strerror_override.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif /* HAVE_SYS_STAT_H */
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#ifdef WIN32
# if MSC_VER < 1800
/* strtoll is available only since Visual Studio 2013 */
# define strtoll _strtoi64
# endif
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <io.h>
#endif /* defined(WIN32) */
#if !defined(HAVE_OPEN) && defined(WIN32)
# define open _open
#endif
#include "snprintf_compat.h"
#include "debug.h"
#include "printbuf.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_tokener.h"
#include "json_util.h"
static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename);
static char _last_err[256] = "";
const char *json_util_get_last_err()
{
if (_last_err[0] == '\0')
return NULL;
return _last_err;
}
void _json_c_set_last_err(const char *err_fmt, ...)
{
va_list ap;
va_start(ap, err_fmt);
// Ignore (attempted) overruns from snprintf
(void)vsnprintf(_last_err, sizeof(_last_err), err_fmt, ap);
va_end(ap);
}
struct json_object* json_object_from_fd(int fd)
{
struct printbuf *pb;
struct json_object *obj;
char buf[JSON_FILE_BUF_SIZE];
int ret;
if(!(pb = printbuf_new())) {
_json_c_set_last_err("json_object_from_file: printbuf_new failed\n");
return NULL;
}
while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
printbuf_memappend(pb, buf, ret);
}
if(ret < 0) {
_json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd, strerror(errno));
printbuf_free(pb);
return NULL;
}
obj = json_tokener_parse(pb->buf);
printbuf_free(pb);
return obj;
}
struct json_object* json_object_from_file(const char *filename)
{
struct json_object *obj;
int fd;
if((fd = open(filename, O_RDONLY)) < 0) {
_json_c_set_last_err("json_object_from_file: error opening file %s: %s\n",
filename, strerror(errno));
return NULL;
}
obj = json_object_from_fd(fd);
close(fd);
return obj;
}
/* extended "format and write to file" function */
int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags)
{
int fd, ret;
int saved_errno;
if (!obj) {
_json_c_set_last_err("json_object_to_file: object is null\n");
return -1;
}
if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
_json_c_set_last_err("json_object_to_file: error opening file %s: %s\n",
filename, strerror(errno));
return -1;
}
ret = _json_object_to_fd(fd, obj, flags, filename);
saved_errno = errno;
close(fd);
errno = saved_errno;
return ret;
}
int json_object_to_fd(int fd, struct json_object *obj, int flags)
{
if (!obj) {
_json_c_set_last_err("json_object_to_fd: object is null\n");
return -1;
}
return _json_object_to_fd(fd, obj, flags, NULL);
}
static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename)
{
int ret;
const char *json_str;
unsigned int wpos, wsize;
filename = filename ? filename : "(fd)";
if (!(json_str = json_object_to_json_string_ext(obj,flags))) {
return -1;
}
wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
wpos = 0;
while(wpos < wsize) {
if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
_json_c_set_last_err("json_object_to_file: error writing file %s: %s\n",
filename, strerror(errno));
return -1;
}
/* because of the above check for ret < 0, we can safely cast and add */
wpos += (unsigned int)ret;
}
return 0;
}
// backwards compatible "format and write to file" function
int json_object_to_file(const char *filename, struct json_object *obj)
{
return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
}
int json_parse_double(const char *buf, double *retval)
{
char *end;
*retval = strtod(buf, &end);
return end == buf ? 1 : 0;
}
int json_parse_int64(const char *buf, int64_t *retval)
{
char *end = NULL;
int64_t val;
errno = 0;
val = strtoll(buf, &end, 10);
if (end != buf)
*retval = val;
return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0;
}
#ifndef HAVE_REALLOC
void* rpl_realloc(void* p, size_t n)
{
if (n == 0)
n = 1;
if (p == 0)
return malloc(n);
return realloc(p, n);
}
#endif
#define NELEM(a) (sizeof(a) / sizeof(a[0]))
static const char* json_type_name[] = {
/* If you change this, be sure to update the enum json_type definition too */
"null",
"boolean",
"double",
"int",
"object",
"array",
"string",
};
const char *json_type_to_name(enum json_type o_type)
{
int o_type_int = (int)o_type;
if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name))
{
_json_c_set_last_err("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name));
return NULL;
}
return json_type_name[o_type];
}

Some files were not shown because too many files have changed in this diff Show More