Compare commits

..
21 Commits
Author SHA1 Message Date
zhangsz 35a4c7eb47 fix: ... 2025-03-25 10:13:04 +08:00
zhangsz 63ec6e5b14 fix: adjustment directory structure 2025-03-25 09:46:16 +08:00
zhangsz e9b29a109d fix: third lib make 2025-03-24 16:11:31 +08:00
zhangsz 68f2b6b91f feat: get arch and os from runtime 2025-03-08 16:23:59 +08:00
zhangsz 8109caf178 fix: ... 2025-03-07 16:56:19 +08:00
zhangsz 3eae0a7615 fix:... 2025-03-07 16:54:33 +08:00
zhangsz 29c5eb74bc fix>>> 2025-03-07 16:53:47 +08:00
zhangsz 3357dc9ddf fix:... 2025-03-07 16:52:57 +08:00
zhangsz 4089d29ba4 fix:.. 2025-03-07 16:52:30 +08:00
zhangsz f512d2aca2 fix: remove third-lib file 2025-03-07 16:51:30 +08:00
zhangsz 9b8bf9595f fix: remove third party lib git save 2025-03-07 15:55:58 +08:00
zhangsz 0057e78368 fix: remove duplicate lib 2025-03-07 15:37:13 +08:00
zhangsz cd3ba91b68 fix: update third-party libraries to latest version 2025-03-07 15:36:27 +08:00
zhangsz a479988f92 fix: ... 2025-03-07 15:27:30 +08:00
zhangsz 6ed53865c3 fix: config.yaml path 2025-03-07 10:31:15 +08:00
zhangsz af262f265f fix: make hmac_md5.c issue 2025-03-06 20:33:08 +08:00
zhangsz 1f4188893b feat: backup archive file 2025-03-06 20:21:45 +08:00
zhangsz 7f9c6cf0f6 fix: exclude logs files 2025-03-06 20:10:29 +08:00
zhangsz fea044e6fe feat: build proect for restproxy 2025-03-06 20:02:40 +08:00
zhangsz aca2bace68 selfcare init 2025-03-03 11:40:37 +08:00
zhangsz 19f09dd7ea Initial commit 2025-03-03 11:04:03 +08:00
143 changed files with 32038 additions and 0 deletions

No files matched your search

+90
View File
@@ -0,0 +1,90 @@
# ---> Go
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
# ---> C
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
*.sum
# logs files
*.log
# third party libraries
.cache
third-lib
!third-lib/README.txt
# binary files
bin
public
+20
View File
@@ -0,0 +1,20 @@
src_dir=`pwd`
.PHONY: all clean
all: goproxy
clean: cproxy_clean goproxy_clean
cproxy_clean:
$(MAKE) -C proxy_c clean
goproxy_clean:
$(MAKE) -C proxy clean
cproxy:
$(MAKE) -C proxy_c
goproxy:
$(MAKE) -C proxy build
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+8
View File
@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/redis" charset="GBK" />
</component>
</project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/selfcare_proxy_go.iml" filepath="$PROJECT_DIR$/.idea/selfcare_proxy_go.iml" />
</modules>
</component>
</project>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/public/protobuf@v1.5.0" vcs="Git" />
<mapping directory="$PROJECT_DIR$/public/protobuf@v1.5.2" vcs="Git" />
</component>
</project>
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>selfcare_proxy</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>
+26
View File
@@ -0,0 +1,26 @@
# Makefile for rest agent project
PROJECT = restproxy_go
VERSION = 2.2502.3
PLATFORM = amd64
# ARMPLATFORM = aarch64
# BUILDDIR = ../../build
# DEBBUILDDIR = ../../debbuild
# RPMBUILDDIR = $(HOME)/goprojects/rpmbuild
# INSTALLDIR = /usr/local/omc
# RELEASEDIR = ../../release
# LIBDIR = be.ems/lib
BINDIR = ../bin
BINNAME = $(BINDIR)/restproxy_go
.PHONY: build $(BINNAME)
build $(BINNAME):
go build -o $(BINNAME) -v -ldflags "-s -w -X '$(LIBDIR)/global.Version=$(VERSION)' \
-X '$(LIBDIR)/global.BuildTime=`date`' \
-X '$(LIBDIR)/global.GoVer=`go version`'"
run: $(BINNAME)
./$(BINNAME)
clean:
rm ./$(BINNAME)
+177
View File
@@ -0,0 +1,177 @@
package MsgDef
const (
TbAcctInfo = "tb_prd_prd_inst_551"
TbOfrDetail = "tb_prd_ofr_detail_inst_551"
TbTariff = "tb_bil_tariff"
TbOfrInfo = "tb_prd_ofr"
TbPricingStrategy = "tb_bil_evt_pricing_strategy"
TbConfigArea = "config_area"
TbPricingArea = "tb_bil_pricing_area"
TbRr = "ratable_history"
TbHoliday = "tb_bil_holiday_rel"
TbBilHoliday = "tb_bil_holiday"
TbSmsInfo = "tb_sms_info"
TbSyncMobile = "tb_sync_mobile"
)
type RecordChange struct {
TableName string
EventType string//entry.EventType
ChgAcctInfo []ChgAcctInfo
ChgOfrDetail []ChgOfrDetail
ChgTariff []ChgTariff
ChgOfrInfo []ChgOfrInfo
ChgPricingStrategy []ChgPricingStrategy
ChgConfigArea []ChgConfigArea
ChgPricingArea []ChgPricingArea
ChgRr []ChgRr
ChgHoliday []ChgHoliday
ChgBilHoliday []ChgBilHoliday
ChgAlertSms []ChgAlertSms
ChgSyncMobile []ChgSyncMobile
}
type ChgAcctInfo struct {
PrdInstId int//string
ServiceNbr string
IfPrepaid string
OldPrdInstStasId string
NewPrdInstStasId string
BUpdate bool
}
type ChgOfrDetail struct {
OfrDetailInstId int//string
OfrDetailTypeId string
OldEffDate string
NewEffDate string
OldExpDate string
NewExpDate string
//OldCalcPriority string
//NewCalcPriority string
BUpdate bool
}
type ChgTariff struct {
TariffId int//string
}
type ChgOfrInfo struct {
OfrId int//string
OfrTypeId string
IfPrepaid string
OldCalcPriority string
NewCalcPriority string
OldOfrState string
NewOfrState string
BUpdate bool
}
type ChgPricingStrategy struct {
EventPricingStrategyId int//string
OldEventPriority string
NewEventPriority string
OldCallType string
NewCallType string
BUpdate bool
}
type ChgConfigArea struct {
AreaId int//string
OldAreaCode string
NewAreaCode string
OldState string
NewState string
BUpdate bool
}
type ChgPricingArea struct {
OldStrategyId int//string
NewStrategyId int//string
OldAreaId int//string
NewAreaId int//string
BUpdate bool
}
type ChgRr struct {
Id int64//tring
OldBeginTime string
NewBeginTime string
OldEndTime string
NewEndTime string
OldFreeValue int64//string
NewFreeValue int64//string
OldValue int64//string
NewValue int64//string
OldOwnId string
NewOwnId string
OldOfrInstId string
NewOfrInstId string
OldPricingSubSectionId string
NewPricingSubSectionId string
BUpdate bool
}
type ChgHoliday struct {
OldState string
NewState string
OldTariffId int//string
NewTariffId int//string
OldTariffSeq int//string
NewTariffSeq int//string
BUpdate bool
}
type ChgBilHoliday struct {
HolidayId int//string
OldState string
NewState string
BUpdate bool
}
type ChgAlertSms struct {
AlertId int
ServiceNbr string
SmsContent string
OldState int
NewState int
BUpdate bool
}
type ChgSyncMobile struct {
PreId int `redis:"preId,omitempty"`// key
OperType int `redis:"operType"`// == 1, new; 2, replace imsi
State int `redis:"state"`// == 1
//Imsi string
ServiceNbr string `redis:"serviceNbr"`
CustId int `redis:"custId"`
AcctId int `redis:"acctId"`
PrdInstId int `redis:"prdInstId"`
MobileType int `redis:"mobileType"`// == 1, mobile type
BirthDate string `redis:"birthDate"`// date
Balance int `redis:"balance"`
BalanceExpDate string `redis:"balanceExpDate"`// datetime
OfrId int `redis:"ofrId"`
Imsi string `redis:"imsi"`
Ki string `redis:"ki"`
Opc string `redis:"opc"`
VmsFlag int `redis:"vmsFlag"`
ExpDate string `redis:"expDate"`// datetime
CugId int `redis:"cugId"`
OldState int// == 1
//BUpdate bool
}
+95
View File
@@ -0,0 +1,95 @@
package MsgDef
import (
)
//&prd_inst_id, &service_nbr, &prd_inst_stas_id, &acct_id, &cust_id
type AcctData struct {
AcctType int `redis:"acctType"`
PrdInstId int `redis:"prdInstId"`
ServiceNbr string `redis:"serviceNbr"`
PrdInstStasId int `redis:"prdInstStasId"`
AcctId int `redis:"acctId"`
CustId int `redis:"custId"`
OfrId int `redis:"ofrId"`
OfrInstId int `redis:"ofrInstId"`
EffTime string `redis:"effTime"`
ExpTime string `redis:"expTime"`
}
//SELECT rr.ID ratableId, rr.PRICING_SUB_SECTION_ID, rr.OFR_INST_ID, rr.BEGIN_TIME, rr.END_TIME,
//rr.FREE_VALUE AS ratableValue, rr.`VALUE` usedRatable, g.MEASURE_DOMAIN, c.OFR_ID,
//c.OFR_NAME, g.TARIFF_ID, g.START_REF_VALUE, g.END_REF_VALUE, c.CALC_PRIORITY, h.EVENT_PRIORITY
type RrData struct {
RrId int64 `redis:"rrId"`
ServiceNbr string `redis:"serviceNbr"`
PrdInstId int `redis:"prdInstId"`
PricingSectionId int `redis:"pricingSectionId"`
OfrInstId int `redis:"ofrInstId"`
OfrId int `redis:"ofrId"`
OfrName string `redis:"ofrName"`
BeginTime string `redis:"beginTime"`
EndTime string `redis:"endTime"`
FreeValue int64 `redis:"freeValue"`
UsedValue int64 `redis:"usedValue"`
MeasureDomain string `redis:"measureDomain"`
TariffId int `redis:"tariffId"`
StartRefTime int `redis:"startRefTime"`
EndRefTime int `redis:"endRefTime"`
CalcPriority int `redis:"calcPriority"`
EventPriority int `redis:"eventPriority"`
StrategyId int `redis:"strategyId"`
UnitFee int `redis:"unitFee"`
RateUnit int `redis:"rateUnit"`
}
// g.MEASURE_DOMAIN, time_to_sec(g.START_REF_VALUE) startTime, time_to_sec(g.END_REF_VALUE) endTime, g.SCALED_RATE_VALUE_ID feeUnit,
// g.rate_unit rateUnit, c.CALC_PRIORITY,h.EVENT_PRIORITY,h.event_pricing_strategy_id,h.EVENT_PRICING_STRATEGY_NAME,c.ofr_id,c.OFR_NAME
type TariffData struct {
TariffId int `redis:"tariffId"`
TariffSeq int `redis:"tariffSeq"`
MeasureDomain string `redis:"measureDomain"`
StartTime int `redis:"startTime"`
EndTime int `redis:"endTime"`
FeeUnit int `redis:"feeUnit"`
RateUnit int `redis:"rateUnit"`
CalcPriority int `redis:"calcPriority"`
EventPriority int `redis:"eventPriority"`
OfrId int `redis:"ofrId"`
OfrName string `redis:"ofrName"`
StrategyId int `redis:"strategyId"`
StrategyName string `redis:"strategyName"`
}
// SELECT DISTINCT ca.area_name, ca.area_code FROM TB_BIL_PRICING_AREA ar INNER JOIN config_area ca ON ca.area_id = ar.area_id WHERE ar.STRATEGY_ID = ?;
type PrefixData struct {
StrategyId int `redis:"StrategyId"`
AreaName string `redis:"areaName"`
AreaCode string `redis:"areaCode"`
}
/*
HD table import
SELECT hr.ofr_id, hr.tariff_id, hr.tariff_seq, hr.holiday_group, hr.state hr_state, hr.holiday_discount,
hd.HOLIDAY_ID, hd.STATE hd_state, hd.HOLIDAY_PRIORITY, hd.HOLIDAY_NAME, hd.HOLIDAY_TYPE, hd.HOLIDAY_BEGIN_DATE, hd.HOLIDAY_END_DATE
FROM tb_bil_holiday_rel hr
INNER JOIN tb_bil_holiday hd ON hr.holiday_group = hd.HOLIDAY_GROUP
WHERE hr.tariff_id=? AND hr.tariff_seq=? AND hr.state = 1 AND hd.STATE = 'L0R';
*/
type HolidayDiscountData struct {
OfrId int `redis:"ofrId"`
TariffId int `redis:"tariffId"`
TariffSeq int `redis:"tariffSeq"`
HdGroup int `redis:"hdGroup"`
HrState int `redis:"hrState"`
HrDiscount int `redis:"hrDiscount"`
HdId int `redis:"hdId"`
HdName string `redis:"hdName"`
HdType string `redis:"hdType"`
HdState string `redis:"hdState"`
HdPriority int `redis:"hdPriority"`
HdBeginDate string `redis:"hdBeginDate"`
HdEndDate string `redis:"hdEndDate"`
}
+35
View File
@@ -0,0 +1,35 @@
package Nmysql
import (
// "fmt"
l4g "proxy/logger"
)
func SetAlertSmsState2Sent(alertId int) error {
stmt, _ := MySqlDb.Prepare("update tb_sms_info set sms_state=2 where sms_alert_id=?;")
defer stmt.Close()
_, err := stmt.Exec(alertId)
if err != nil {
l4g.MysqlLog.Errorf("SetAlertSmsState2Sent err: %v", err)
return err
}
l4g.MysqlLog.Debugf("SetAlertSmsState2Sent succ!")
return nil
}
func InsertExpiredNotifySms(accountId uint32, planId uint32, expiredDate int64) error {
stmt, _ := MySqlDb.Prepare("INSERT into tb_sync_msg SET msg_type=1, acct_id=?, ofr_inst_id=?, exp_date=FROM_UNIXTIME(?), state=1;")
defer stmt.Close()
_, err := stmt.Exec(accountId, planId, expiredDate)
if err != nil {
l4g.MysqlLog.Errorf("InsertExpiredNotifySms acctId[%d], planId[%d], expiredDate[%d] err: %v", accountId, planId, expiredDate, err)
return err
}
l4g.MysqlLog.Debugf("InsertExpiredNotifySms acctId[%d], planId[%d], expiredDate[%d] succ!", accountId, planId, expiredDate)
return nil
}
+72
View File
@@ -0,0 +1,72 @@
package Nmysql
import (
"fmt"
l4g "proxy/logger"
)
func QueryOfrIdByPrdInstId(prdInstId int) (int, error) {
sqlStr := fmt.Sprintf("select OFR_ID from tb_prd_sub_prd_inst_551 where MAIN_PRD_INST_ID=%d limit 1;", prdInstId)
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query tb_prd_sub_prd_inst_551, prdInstId[%d] fail: %v", prdInstId, err)
return 0, err
}
defer rows.Close()
var ofrId int
for rows.Next(){
if err = rows.Scan(&ofrId); err != nil {
l4g.MysqlLog.Errorf("query row of TB_RESOURCE_EXAM fail: %v", err)
return 0, err
}
return ofrId, nil
}
return 0, nil
}
func QueryOfrLevelByOfrId(ofrId int) (int, error) {
sqlStr := fmt.Sprintf("select OFR_LEVEL from tb_prd_ofr where OFR_ID=%d limit 1;", ofrId)
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query tb_prd_ofr, ofrId[%d] fail: %v", ofrId, err)
return 0, err
}
defer rows.Close()
var ofrLevel int
for rows.Next(){
if err = rows.Scan(&ofrLevel); err != nil {
l4g.MysqlLog.Errorf("query row of tb_prd_ofr fail: %v", err)
return 0, err
}
return ofrLevel, nil
}
return 0, nil
}
func QueryRentByOfrId(ofrId int) (int, error) {
sqlStr := fmt.Sprintf("SELECT f.FEE_VALUE rentValue FROM tb_prd_prd_once_fee f WHERE f.PRD_ID = %d AND f.TYPE = 2 AND f.FEE_TYPE = 5;", ofrId)
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query tb_prd_prd_once_fee, ofrId[%d] fail: %v", ofrId, err)
return 0, err
}
defer rows.Close()
var onceFee int
for rows.Next(){
if err = rows.Scan(&onceFee); err != nil {
l4g.MysqlLog.Errorf("query row of tb_prd_prd_once_fee fail: %v", err)
return 0, err
}
return onceFee, nil
}
return 0, nil
}
+4
View File
@@ -0,0 +1,4 @@
package Nmysql
type void struct{}
var member void
File diff suppressed because it is too large. Load diff
+175
View File
@@ -0,0 +1,175 @@
package Nmysql
import (
"fmt"
l4g "proxy/logger"
)
func QuerySyncMobileInfo() ([]SyncMobileInfo, error) {
sqlStr := fmt.Sprintf("select PRE_ID, OPER_TYPE, IMSI, SERVICE_NBR, KI, IFNULL(OPC,'') as OPC, CUST_ID, ACCT_ID, PRD_INST_ID, MOBILE_TYPE, VMS_FLAG, IFNULL(BIRTH_DATE,'') as BIRTH_DATE, BALANCE, BALANCE_EXP_DATE, OFR_ID, EXP_DATE, IFNULL(CUG_ID,0) as CUG_ID from tb_sync_mobile where STATE=1 limit 10;")
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query tb_sync_mobile fail: %v", err)
return nil, err
}
defer rows.Close()
var rsp []SyncMobileInfo= nil
for rows.Next(){
var si SyncMobileInfo
if err = rows.Scan(&si.PreId, &si.OperType, &si.Imsi, &si.ServiceNbr, &si.Ki, &si.Opc, &si.CustId, &si.AcctId, &si.PrdInstId,
&si.MobileType, &si.VmsFlag, &si.BirthDate, &si.Balance, &si.BalanceExpDate, &si.OfrId, &si.ExpDate, &si.CugId); err != nil {
l4g.MysqlLog.Errorf("query row of tb_sync_mobile fail: %v", err)
return nil, err
}
if si.BirthDate == "" {
si.BirthDate = "2000-01-01"
}
rsp = append(rsp, si)
}
return rsp, nil
}
type SyncMobileInfo struct {
PreId int// auto incr
OperType int// 1: create subs, 2: replace IMSI
Imsi string
ServiceNbr string
Ki string
Opc string
CustId int
AcctId int
PrdInstId int
MobileType int//0: postpaid, 1: prepaid
VmsFlag int//0: not VMS service, 1: VMS service
BirthDate string
Balance int
BalanceExpDate string
OfrId int
ExpDate string
CugId int// 1: staff, 2: customer
}
func QueryOldImsiInfo(serviceNbr string) (*OldImsiInfo, error) {
sqlStr := fmt.Sprintf("select PRE_ID, IMSI, PRD_INST_ID from tb_sync_mobile WHERE SERVICE_NBR='%s' and STATE>1 ORDER BY PRE_ID DESC limit 1;", serviceNbr)
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query tb_sync_mobile fail: %v", err)
return nil, err
}
defer rows.Close()
var rsp OldImsiInfo
for rows.Next(){
if err = rows.Scan(&rsp.PreId, &rsp.Imsi, &rsp.PrdInstId); err != nil {
l4g.MysqlLog.Errorf("query row of tb_sync_mobile fail: %v", err)
return nil, err
}
return &rsp, nil
}
return nil, nil
}
type OldImsiInfo struct {
PreId int
Imsi string
PrdInstId int
}
func AddSmcliCmd2Mysql(cmdType int, nt int, serviceNbr string, cmdStr string) error {
sqlStr := fmt.Sprintf("INSERT INTO tb_sync_cn_cmd SET cmd_type=%d, node_type=%d, node_name='%s', srv_num='%s', command='%s', state=1, result=0, timestamp=NOW();",
cmdType, nt, NodeName[nt], serviceNbr, cmdStr)
stmt, _ := MySqlDb.Prepare(sqlStr)
defer stmt.Close()
_, err := stmt.Exec()
if err != nil {
l4g.MysqlLog.Errorf("AddSmcliCmd2Mysql, cmdType[%d], nt[%d], prdInstId[%s], cmd[%s] error: %v", cmdType, nt, serviceNbr, cmdStr, err)
return err
}
l4g.MysqlLog.Debugf("AddSmcliCmd2Mysql, cmdType[%d], nt[%d], prdInstId[%s], cmd[%s] succ!", cmdType, nt, serviceNbr, cmdStr)
return nil
}
func AddSmcliCmdSucc2Mysql(cmdType int, nt int, serviceNbr string, cmdStr string) error {
cause := "000:Command Successful"
sqlStr := fmt.Sprintf("INSERT INTO tb_sync_cn_cmd SET cmd_type=%d, node_type=%d, node_name='%s', srv_num='%s', command='%s', state=2, result=1, cause='%s', timestamp=NOW();",
cmdType, nt, NodeName[nt], serviceNbr, cmdStr, cause)
stmt, _ := MySqlDb.Prepare(sqlStr)
defer stmt.Close()
_, err := stmt.Exec()
if err != nil {
l4g.MysqlLog.Errorf("AddSmcliCmd2Mysql, cmdType[%d], nt[%d], prdInstId[%s], cmd[%s] error: %v", cmdType, nt, serviceNbr, cmdStr, err)
return err
}
l4g.MysqlLog.Debugf("AddSmcliCmd2Mysql, cmdType[%d], nt[%d], prdInstId[%s], cmd[%s] succ!", cmdType, nt, serviceNbr, cmdStr)
return nil
}
func UpdateSyncMobileState(preId int, state int) error {
sqlStr := fmt.Sprintf("UPDATE tb_sync_mobile set STATE=%d where PRE_ID=%d;", state, preId)
stmt, _ := MySqlDb.Prepare(sqlStr)
defer stmt.Close()
_, err := stmt.Exec()
if err != nil {
l4g.MysqlLog.Errorf("UpdateSyncMobileState, preId[%d], state[%d] error: %v", preId, state, err)
return err
}
l4g.MysqlLog.Debugf("UpdateSyncMobileState, preId[%d], state[%d] succ!", preId, state)
return nil
}
func QuerySyncCnCmd() ([]CnCmdInfo, error) {
sqlStr := fmt.Sprintf("select id, node_type, command from tb_sync_cn_cmd where state=1 limit 40;")
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query tb_sync_cn_cmd fail: %v", err)
return nil, err
}
defer rows.Close()
var rsp []CnCmdInfo= nil
for rows.Next(){
var si CnCmdInfo
if err = rows.Scan(&si.Id, &si.NodeType, &si.Command); err != nil {
l4g.MysqlLog.Errorf("query row of tb_sync_cn_cmd fail: %v", err)
return nil, err
}
rsp = append(rsp, si)
}
return rsp, nil
}
type CnCmdInfo struct {
Id int// auto incr
NodeType int
Command string
}
func UpdateCnCmdResult(id int, state int, result int, desc string) error {
sqlStr := fmt.Sprintf("update tb_sync_cn_cmd set state=%d,result=%d,cause='%s',timestamp=NOW() where id=%d;",
state, result, desc, id)
stmt, _ := MySqlDb.Prepare(sqlStr)
defer stmt.Close()
_, err := stmt.Exec()
if err != nil {
l4g.MysqlLog.Errorf("UpdateCnCmdResult, id[%d], state[%d], result[%d], cause[%s] error: %v", id, state, result, desc, err)
return err
}
l4g.MysqlLog.Debugf("UpdateCnCmdResult, id[%d], state[%d], result[%d], cause[%s] succ!", id, state, result, desc)
return nil
}
+29
View File
@@ -0,0 +1,29 @@
package Nmysql
const (
CT_CREATE_NA int= 0
CT_CREATE_SUB int= 1
CT_REPLACE_SUB int= 2
CT_SUSPEND_ACCOUNT int= 3
CT_DISABLE_ACCOUNT int= 4
CT_RESUME_ACCOUNT int= 5
CT_DISCONNECT_ACCOUNT int= 6
CT_UPDATE_SUB int= 7
CT_MAX int= 8
)
const (
NT_NA int= 0
NT_OCS int= 1
NT_HSS int= 2
NT_AUC int= 3
NT_VMS int= 4
NT_PSTN int= 5
NT_MSAN int= 6
NT_ADSL int= 7
NT_PCRF int= 8
NT_MAX int= 9
)
var NodeName = []string{"NULL","OCS","HSS","AUC","VMS","PSTN","MSAN","ADSL","PCRF"}
+68
View File
@@ -0,0 +1,68 @@
package Nmysql
import (
l4g "proxy/logger"
)
func UpdateDataPlanInfo(bundleId uint32, thisTimeAdded uint64, opFlag bool) error {
var sqlStr string
if !opFlag {
sqlStr = "UPDATE ratable_history SET `VALUE`= `VALUE`+? WHERE ID=?;"
} else {
sqlStr = "UPDATE ratable_history SET `VALUE`= `VALUE`-? WHERE ID=?;"
}
stmt, _ := MySqlDb.Prepare(sqlStr)
defer stmt.Close()
_, err := stmt.Exec(thisTimeAdded, bundleId)
if err != nil {
l4g.MysqlLog.Errorf("UpdateDataPlanInfo for bundle[%d], added[%d], op[%t] error: %v", bundleId, thisTimeAdded, opFlag, err)
return err
}
l4g.MysqlLog.Debugf("UpdateDataPlanInfo for bundle[%d], added[%d], op[%t] succ!", bundleId, thisTimeAdded, opFlag)
return nil
}
func UpdateVoiceAndSmsPlanInfo(serviceType byte, bundleId uint32, usedValue uint64, totalValue uint64, updateExpiryDate bool) error {
var sqlStr string
var value uint64
if updateExpiryDate {
sqlStr = "UPDATE ratable_history SET `VALUE`=? WHERE ID=?;"
value = totalValue
} else {
sqlStr = "UPDATE ratable_history SET `VALUE`=? WHERE ID=?;"
value = usedValue
}
stmt, _ := MySqlDb.Prepare(sqlStr)
defer stmt.Close()
_, err := stmt.Exec(value, bundleId)
if err != nil {
l4g.MysqlLog.Errorf("UpdateVoiceAndSmsPlanInfo for bundle[%d], value[%d] error: %v", bundleId, value, err)
return err
}
l4g.MysqlLog.Debugf("UpdateVoiceAndSmsPlanInfo for bundle[%d], value[%d] succ!", bundleId, value)
return nil
}
func AddNotificationSms(accountId uint32, planId uint32, serviceType byte, updateExpiryDate bool, rateUsed int) error {
var sqlStr string= "INSERT into tb_sync_msg SET msg_type=2, rate_type=?, acct_id=?, rate_value=?, state=1, ofr_inst_id=?;"
rate := rateUsed
//if updateExpiryDate {
// rate = 100
//}
stmt, _ := MySqlDb.Prepare(sqlStr)
defer stmt.Close()
_, err := stmt.Exec(serviceType, accountId, rate, planId)
if err != nil {
l4g.MysqlLog.Errorf("AddNotificationSms for plan[%d], acct[%d], type[%d], rate[%d/100] error: %v", planId, accountId, serviceType, rate, err)
return err
}
l4g.MysqlLog.Debugf("AddNotificationSms for plan[%d], acct[%d], type[%d], rate[%d/100] succ!", planId, accountId, serviceType, rate)
return nil
}
+303
View File
@@ -0,0 +1,303 @@
package Nmysql
import "C"
import (
"fmt"
. "proxy/config"
l4g "proxy/logger"
"strconv"
)
func UpdateUserStatus2Mdb(accountId uint32, status byte) error {
statusInCrm := 1001
switch status {
case 1:
statusInCrm = 1001
case 2:
statusInCrm = 1205
case 4:
statusInCrm = 1101
case 6:
statusInCrm = 1202
}
if false {
stmt, _ := MySqlDb.Prepare("update tb_prd_prd_inst_551 set PRD_INST_STAS_ID=?, MOD_DATE=NOW() where ACCT_ID=?;")
defer stmt.Close()
_, _ = stmt.Exec(statusInCrm, accountId)
}
if status == 4 {
stmt, _ := MySqlDb.Prepare("INSERT INTO tb_mobile_disc_cmd set ACCT_ID=?, ACCT_STATUS=0, UPDATE_DATE=NOW();")
defer stmt.Close()
_, err := stmt.Exec(accountId)
if err != nil {
l4g.MysqlLog.Errorf("UpdateUserStatus2Mdb acctId[%d] err: %v", accountId, err)
//return err
}
l4g.MysqlLog.Debugf("UpdateUserStatus2Mdb acctId[%d] succ!", accountId)
_ = InsertPrepaidUserDeleteCliCmd(accountId)
}
return nil
}
func InsertPrepaidUserDeleteCliCmd(accountId uint32) error {
//sqlStr := "select PRE_ID, OPER_TYPE, IMSI, SERVICE_NBR, KI, OPC, CUST_ID, STATE, PRD_INST_ID, MOBILE_TYPE, VMS_FLAG, BIRTH_DATE, BALANCE, "
//sqlStr += "BALANCE_EXP_DATE, OFR_ID, EXP_DATE, CUG_ID from tb_sync_mobile where ACCT_ID=? ORDER BY PRE_ID DESC limit 1;"
sqlStr := "select IMSI, SERVICE_NBR, PRD_INST_ID "
sqlStr += "from tb_sync_mobile where ACCT_ID=" + strconv.Itoa(int(accountId)) + " ORDER BY PRE_ID DESC limit 1;"
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query tb_sync_mobile, accountId[%d] fail: %v", accountId, err)
return err
}
//defer rows.Close()
var imsi, msisdn string
var prdInstId int
for rows.Next(){
if err = rows.Scan(&imsi, &msisdn, &prdInstId); err != nil {
l4g.MysqlLog.Errorf("query row of tb_sync_mobile fail: %v", err)
_ = rows.Close()
return err
}
break
}
_ = rows.Close()
if imsi != "" {
cmd := "delete subscriber -imsi " + imsi
stmt, _ := MySqlDb.Prepare("INSERT INTO tb_sync_cn_cmd SET cmd_type=?, node_type=?, node_name=?, srv_num=?, command=?, state=1, result=0, timestamp=NOW();")
//defer stmt.Close()
_, err := stmt.Exec(CT_DISCONNECT_ACCOUNT, NT_HSS, NodeName[NT_HSS], prdInstId, cmd)
if err != nil {
l4g.MysqlLog.Errorf("add cmd[%s], msisdn[%s], prdInstId[%d] err: %v", cmd, msisdn, prdInstId, err)
//return err
} else {
l4g.MysqlLog.Debugf("add cmd[%s], msisdn[%s], prdInstId[%d]", cmd, msisdn, prdInstId)
}
stmt.Close()
cmd = "delete aucSubscriber -imsi " + imsi
stmt, _ = MySqlDb.Prepare("INSERT INTO tb_sync_cn_cmd SET cmd_type=?, node_type=?, node_name=?, srv_num=?, command=?, state=1, result=0, timestamp=NOW();")
//defer stmt.Close()
_, err = stmt.Exec(CT_DISCONNECT_ACCOUNT, NT_AUC, NodeName[NT_AUC], prdInstId, cmd)
if err != nil {
l4g.MysqlLog.Errorf("add cmd[%s], msisdn[%s], prdInstId[%d] err: %v", cmd, msisdn, prdInstId, err)
//return err
} else {
l4g.MysqlLog.Debugf("add cmd[%s], msisdn[%s], prdInstId[%d]", cmd, msisdn, prdInstId)
}
stmt.Close()
cmd = "delete vmsSubscriber -msisdn " + msisdn
stmt, _ = MySqlDb.Prepare("INSERT INTO tb_sync_cn_cmd SET cmd_type=?, node_type=?, node_name=?, srv_num=?, command=?, state=1, result=0, timestamp=NOW();")
//defer stmt.Close()
_, err = stmt.Exec(CT_DISCONNECT_ACCOUNT, NT_VMS, NodeName[NT_VMS], prdInstId, cmd)
if err != nil {
l4g.MysqlLog.Errorf("add cmd[%s], msisdn[%s], prdInstId[%d] err: %v", cmd, msisdn, prdInstId, err)
//return err
} else {
l4g.MysqlLog.Debugf("add cmd[%s], msisdn[%s], prdInstId[%d]", cmd, msisdn, prdInstId)
}
stmt.Close()
}
return nil
}
func CrmDeleteSubsProfile(serviceNbr string, acctType string, acctId string) {
if acctType == "1" {
//sqlStr := "select PRE_ID, OPER_TYPE, IMSI, SERVICE_NBR, KI, OPC, CUST_ID, STATE, PRD_INST_ID, MOBILE_TYPE, VMS_FLAG, BIRTH_DATE, BALANCE, "
//sqlStr += "BALANCE_EXP_DATE, OFR_ID, EXP_DATE, CUG_ID from tb_sync_mobile where ACCT_ID=? ORDER BY PRE_ID DESC limit 1;"
sqlStr := "select IMSI, SERVICE_NBR, PRD_INST_ID, MOBILE_TYPE, VMS_FLAG "
sqlStr += "from tb_sync_mobile where ACCT_ID=" + acctId + " ORDER BY PRE_ID DESC limit 1;"
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query tb_sync_mobile, accountId[%d] fail: %v", acctId, err)
return
}
//defer rows.Close()
var imsi, msisdn string
var prdInstId, mobileType, vmsFlag int
for rows.Next(){
if err = rows.Scan(&imsi, &msisdn, &prdInstId, &mobileType, &vmsFlag); err != nil {
l4g.MysqlLog.Errorf("query row of tb_sync_mobile fail: %v", err)
_ = rows.Close()
return
}
break
}
_ = rows.Close()
if imsi != "" {
cmd := "delete subscriber -imsi " + imsi
stmt, _ := MySqlDb.Prepare("INSERT INTO tb_sync_cn_cmd SET cmd_type=?, node_type=?, node_name=?, srv_num=?, command=?, state=1, result=0, timestamp=NOW();")
//defer stmt.Close()
_, err := stmt.Exec(CT_DISCONNECT_ACCOUNT, NT_HSS, NodeName[NT_HSS], strconv.Itoa(prdInstId), cmd)
if err != nil {
l4g.MysqlLog.Errorf("add cmd[%s], msisdn[%s], prdInstId[%d] err: %v", cmd, msisdn, prdInstId, err)
//return err
} else {
l4g.MysqlLog.Debugf("add cmd[%s], msisdn[%s], prdInstId[%d]", cmd, msisdn, prdInstId)
}
stmt.Close()
cmd = "delete aucSubscriber -imsi " + imsi
stmt, _ = MySqlDb.Prepare("INSERT INTO tb_sync_cn_cmd SET cmd_type=?, node_type=?, node_name=?, srv_num=?, command=?, state=1, result=0, timestamp=NOW();")
//defer stmt.Close()
_, err = stmt.Exec(CT_DISCONNECT_ACCOUNT, NT_AUC, NodeName[NT_AUC], strconv.Itoa(prdInstId), cmd)
if err != nil {
l4g.MysqlLog.Errorf("add cmd[%s], msisdn[%s], prdInstId[%d] err: %v", cmd, msisdn, prdInstId, err)
//return err
} else {
l4g.MysqlLog.Debugf("add cmd[%s], msisdn[%s], prdInstId[%d]", cmd, msisdn, prdInstId)
}
stmt.Close()
if mobileType == 1{
cmd = "delete ppsSubscriber -msisdn " + msisdn
stmt, _ = MySqlDb.Prepare("INSERT INTO tb_sync_cn_cmd SET cmd_type=?, node_type=?, node_name=?, srv_num=?, command=?, state=2, result=1, cause='0000:Command successful', timestamp=NOW();")
//defer stmt.Close()
_, err = stmt.Exec(CT_DISCONNECT_ACCOUNT, NT_OCS, NodeName[NT_OCS], strconv.Itoa(prdInstId), cmd)
if err != nil {
l4g.MysqlLog.Errorf("add cmd[%s], msisdn[%s], prdInstId[%d] err: %v", cmd, msisdn, prdInstId, err)
//return err
} else {
l4g.MysqlLog.Debugf("add cmd[%s], msisdn[%s], prdInstId[%d]", cmd, msisdn, prdInstId)
}
stmt.Close()
}
if vmsFlag == 1{
cmd = "delete vmsSubscriber -msisdn " + msisdn
stmt, _ = MySqlDb.Prepare("INSERT INTO tb_sync_cn_cmd SET cmd_type=?, node_type=?, node_name=?, srv_num=?, command=?, state=1, result=0, timestamp=NOW();")
//defer stmt.Close()
_, err = stmt.Exec(CT_DISCONNECT_ACCOUNT, NT_VMS, NodeName[NT_VMS], strconv.Itoa(prdInstId), cmd)
if err != nil {
l4g.MysqlLog.Errorf("add cmd[%s], msisdn[%s], prdInstId[%d] err: %v", cmd, msisdn, prdInstId, err)
//return err
} else {
l4g.MysqlLog.Debugf("add cmd[%s], msisdn[%s], prdInstId[%d]", cmd, msisdn, prdInstId)
}
stmt.Close()
}
}
} else if acctType == "2" {
ssEntryIdInCrm := Config.Provision.SsEntryIdInCrm
orderId := queryOrderIdByServiceNbr(serviceNbr)
if orderId == 0 {
return
}
examNumStr := queryResourceExamNumByOrderId(orderId)
if examNumStr == "" {
return
}
kronePairId, _ := strconv.Atoi(examNumStr)
if kronePairId <= 0 {
return
}
examNumStr = querySsEntryByResIdAndOrderId(ssEntryIdInCrm, orderId)
if examNumStr == "" {
return
}
ssEntry, _ := strconv.Atoi(examNumStr)
cmdDelPstn := fmt.Sprintf("delete pstn user isdn=%s, krone_pair_id=%d, ssentry=%d, state=Deleted, account_id=%s;",
serviceNbr,kronePairId, ssEntry,acctId)
insertCmdDelPstn(cmdDelPstn, serviceNbr)
}
return
}
func insertCmdDelPstn(cmd string, serviceNbr string) {
stmt, _ := MySqlDb.Prepare("INSERT INTO tb_sync_cn_cmd SET cmd_type=?, node_type=?, node_name=?, srv_num=?, command=?, state=1, result=1, timestamp=NOW();")
//defer stmt.Close()
_, err := stmt.Exec(CT_DISCONNECT_ACCOUNT, NT_PSTN, NodeName[NT_PSTN], serviceNbr, cmd)
if err != nil {
l4g.MysqlLog.Errorf("insertCmdDelPstn cmd[%s], msisdn[%s] err: %v", cmd, serviceNbr, err)
//return err
} else {
l4g.MysqlLog.Debugf("insertCmdDelPstn cmd[%s], msisdn[%s]", cmd, serviceNbr)
}
stmt.Close()
}
func queryOrderIdByServiceNbr(serviceNbr string) int {
sqlStr := "select ORDER_ID from tb_sync_pstn where SERVICE_NBR=" + serviceNbr + " ORDER by ORDER_ID desc limit 1;"
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query tb_sync_pstn, serviceNbr[%s] fail: %v", serviceNbr, err)
return 0
}
defer rows.Close()
var orderId int
for rows.Next(){
if err = rows.Scan(&orderId); err != nil {
l4g.MysqlLog.Errorf("query row of tb_sync_pstn fail: %v", err)
//_ = rows.Close()
return 0
}
return orderId
}
//_ = rows.Close()
return 0
}
func queryResourceExamNumByOrderId(orderId int) string {
sqlStr := "SELECT C.RESOURCE_EXAM_NUM FROM TB_PRD_RES_INST_551 A, TB_PRD_RES_INST_DETAIL_551 B, TB_RESOURCE_EXAM C "
sqlStr += "WHERE A.RES_INST_ID=B.RES_INST_ID AND B.RESOURCE_EXAM_ID=C.RESOURCE_EXAM_ID AND C.RESOURCE_ID=1046 AND A.ORDER_ID=" + strconv.Itoa(orderId)+";"
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query TB_RESOURCE_EXAM, orderId[%d] fail: %v", orderId, err)
return ""
}
defer rows.Close()
var resExamNum string
for rows.Next(){
if err = rows.Scan(&resExamNum); err != nil {
l4g.MysqlLog.Errorf("query row of TB_RESOURCE_EXAM fail: %v", err)
//_ = rows.Close()
return ""
}
return resExamNum
}
//_ = rows.Close()
return ""
}
func querySsEntryByResIdAndOrderId(resId, orderId int) string {
sqlStr := fmt.Sprintf("%s%sC.RESOURCE_ID=%d AND A.ORDER_ID=%d;",
"SELECT C.RESOURCE_EXAM_NUM FROM TB_PRD_RES_INST_551 A, TB_PRD_RES_INST_DETAIL_551 B, TB_RESOURCE_EXAM C ",
"WHERE A.RES_INST_ID=B.RES_INST_ID AND B.RESOURCE_EXAM_ID=C.RESOURCE_EXAM_ID AND ", resId, orderId)
rows, err := MySqlDb.Query(sqlStr)
if err != nil {
l4g.MysqlLog.Errorf("Query TB_RESOURCE_EXAM, orderId[%d] fail: %v", orderId, err)
return ""
}
defer rows.Close()
var resExamNum string
for rows.Next(){
if err = rows.Scan(&resExamNum); err != nil {
l4g.MysqlLog.Errorf("query row of TB_RESOURCE_EXAM fail: %v", err)
return ""
}
return resExamNum
}
return ""
}
+115
View File
@@ -0,0 +1,115 @@
package Nredis
import (
"fmt"
. "proxy/MsgDef"
l4g "proxy/logger"
"strconv"
)
// "Acct:"+acctData.ServiceNbr
func RdbDelAcctRecord(serviceNbr string) {
var cursor uint64= 0
for {
keys, cursorNew, err := rdb.SScan(ctx, "Acct:"+serviceNbr, cursor, "", 0).Result()
if err != nil {
l4g.RedisLog.Errorf("SScan Acct:%s, err: %v", serviceNbr, err)
break
}
//fmt.Printf("\nfound %d keys\n", len(keys))
for _, key := range keys {
acctKey := "Acct:"+serviceNbr+":"+key
err := rdb.Del(ctx, acctKey).Err()
if err != nil {
l4g.RedisLog.Errorf("Del %s, err: %v", acctKey, err)
} else {
//subFields := strings.Split(key, ":")
//if len(subFields) == 3 && subFields[2] != "" {
_ = rdb.SRem(ctx, "Acct:"+serviceNbr, key)
//return srem.Err()
//}
}
}
if cursorNew == 0 {
break
} else {
cursor = cursorNew
}
}
_ = rdb.Del(ctx, "Acct:"+serviceNbr).Err()
return
}
func RdbDelAcctOfr(serviceNbr string, ofrId int) error {
acctKey := "Acct:"+serviceNbr+":"+strconv.Itoa(ofrId)
err := rdb.Del(ctx, acctKey).Err()
if err != nil {
l4g.RedisLog.Errorf("Del %s, err: %v", acctKey, err)
} else {
_ = rdb.SRem(ctx, "Acct:"+serviceNbr, strconv.Itoa(ofrId))
}
return err
}
func RdbSetAcctRecord(acctData *AcctData) error {
//&prd_inst_id, &service_nbr, &prd_inst_stas_id, &acct_id, &cust_id
key := "Acct:"+acctData.ServiceNbr+":"+strconv.Itoa(acctData.OfrId)
err := rdb.HMSet(ctx, key, "acctType", acctData.AcctType, "prdInstId", acctData.PrdInstId, "serviceNbr", acctData.ServiceNbr,
"prdInstStasId", acctData.PrdInstStasId, "acctId", acctData.AcctId, "custId", acctData.CustId, "ofrId", acctData.OfrId, "ofrInstId", acctData.OfrInstId,
"effTime", acctData.EffTime, "expTime", acctData.ExpTime).Err()
if err != nil {
l4g.RedisLog.Errorf("HMSet Acct:%s, err: %v", acctData.ServiceNbr, err)
} else {
sadd := rdb.SAdd(ctx, "Acct:"+acctData.ServiceNbr, strconv.Itoa(acctData.OfrId))
if sadd.Err() != nil {
l4g.RedisLog.Errorf("SAdd Acct:%s %d, err: %v", acctData.ServiceNbr, acctData.OfrId, sadd.Err())
return sadd.Err()
} else {
l4g.RedisLog.Debugf("SAdd Acct:%s %d", acctData.ServiceNbr, acctData.OfrId)
}
}
return err
}
func RdbGetAcctRecordByServiceNbr(serviceNbr string) (rsp string, err error) {
var cursor uint64= 0
for {
keys, cursorNew, err := rdb.SScan(ctx, "Acct:"+serviceNbr, cursor, "", 0).Result()
if err != nil {
l4g.RedisLog.Errorf("SScan Acct:%s, err: %v", serviceNbr, err)
break
}
//fmt.Printf("\nfound %d keys\n", len(keys))
for _, key := range keys {
acctKey := "Acct:"+serviceNbr+":"+key
res := rdb.HGetAll(ctx, acctKey)
if res.Err() != nil {
l4g.RedisLog.Errorf("HGetAll %s, err: %v", acctKey, err)
} else {
var acctData AcctData
if err = res.Scan(&acctData); err != nil {
l4g.RedisLog.Errorf("HGetAll Scan %s, err: %v", acctKey, err)
} else {
l4g.RedisLog.Debugf("Get %s, [%v]", acctKey, acctData)
rsp += fmt.Sprintf("%s:***************************************\r\nPrdInstId: %d\r\nPrdInstStasId: %d\r\nCustId: %d\r\nAcctId: %d\r\n",
acctKey, acctData.PrdInstId, acctData.PrdInstStasId, acctData.CustId, acctData.AcctId)
rsp += fmt.Sprintf("OfrId: %d\r\nOfrInstId: %d\r\nEffTime: %s\r\nExpTime: %s\r\n",
acctData.OfrId, acctData.OfrInstId, acctData.EffTime, acctData.ExpTime)
return rsp, err
}
}
}
if cursorNew == 0 {
break
} else {
cursor = cursorNew
}
}
return "", err
}
+63
View File
@@ -0,0 +1,63 @@
package Nredis
import (
l4g "proxy/logger"
"strconv"
)
func RdbSetAlertSmsRecord(alertId int, serviceNbr, smsContent string) error {
key := "AlertSms:"+serviceNbr+":"+strconv.Itoa(alertId)
err := rdb.Set(ctx, key, smsContent, 0).Err()
if err != nil {
l4g.RedisLog.Errorf("Set %s, err: %v", key, err)
} else {
l4g.RedisLog.Debugf("Set %s, err: %s", key, smsContent)
sadd := rdb.SAdd(ctx, "Msg2OcsSet", key)
if sadd.Err() != nil {
l4g.RedisLog.Errorf("SAdd Msg2OcsSet %s, err: %v", key, sadd.Err())
return sadd.Err()
} else {
l4g.RedisLog.Debugf("SAdd Msg2OcsSet %s", key)
}
}
return err
}
func RdbGetAlertSmsContent(key string) string {
var sms string
var err error
sms, err = rdb.Get(ctx, key).Result()
if err != nil {
return ""
} else {
return sms
}
}
func RdbScanAlertSmsRecord() []string {
var cursor uint64= 0
var keysFound []string
for {
keys, cursor, err := rdb.SScan(ctx, "Msg2OcsSet", cursor, "", 50).Result()
if err != nil {
l4g.RedisLog.Errorf("SScan Msg2OcsSet, err: %v", err)
break
}
keysFound = append(keysFound, keys...)
if cursor == 0 {
break
} else {
break
}
}
return keysFound
}
func RdsDelMsg2OcsKey(key string) {
_ = rdb.SRem(ctx, "Msg2OcsSet", key)
_ = rdb.Del(ctx, key).Err()
}
+169
View File
@@ -0,0 +1,169 @@
package Nredis
import (
"proxy/MsgDef"
. "proxy/MsgDef"
l4g "proxy/logger"
"strings"
"time"
)
func CheckIfRrExpired(rr *MsgDef.RrData) bool {
if rr == nil {
return false
}
if rr.MeasureDomain == "01" || rr.MeasureDomain == "03" {
if rr.UsedValue >= rr.FreeValue {
return true
}
nowStr := time.Now().Format("20060102150405")
if strings.Compare(nowStr, rr.EndTime) > 0 {
return true
}
return false
}
if rr.MeasureDomain == "02" {
nowStr := time.Now().Format("20060102150405")
if strings.Compare(nowStr, rr.EndTime) > 0 {
return true
}
}
return false
}
func RdbGetRrByKey(key string) (*RrData, error) {
res := rdb.HGetAll(ctx, key)
err := res.Err()
if err != nil {
l4g.RedisLog.Errorf("HGetAll %s, err: %v", key, err)
return nil, err
}
var rr RrData
if err = res.Scan(&rr); err != nil {
l4g.RedisLog.Errorf("HGetAll Scan %s, err: %v", key, err)
return nil, err
} else {
//l4g.RedisLog.Debugf("Get %s, [%v]", key, rr)
}
return &rr, err
}
func RdbClrExpireRrRecord() error {
l4g.RedisLog.Warnf("cron clear expire rr!")
var cursor uint64= 0
var err error
for {
var keys []string
keys, cursor, err = rdb.Scan(ctx, cursor, "Rr:*", 30).Result()
if err != nil {
l4g.RedisLog.Errorf("Scan Rr:*, err: %v", err)
break
}
for _, key := range keys {
subFields := strings.Split(key, ":")
if len(subFields) == 4 {
rr, err1 := RdbGetRrByKey(key)
if rr != nil && err1 == nil && CheckIfRrExpired(rr) {
err1 = rdb.Del(ctx, key).Err()
if err1 != nil {
l4g.RedisLog.Errorf("Del Rr[%s], err: %v", key, err1)
} else {
l4g.RedisLog.Warnf("Del Rr[%s] succ", key)
l4g.RedisLog.Warnf("SRem RrSet:%s:%s %s", subFields[1], subFields[2], subFields[3])
_ = rdb.SRem(ctx, "RrSet:"+subFields[1]+":"+subFields[2], subFields[3])
l4g.RedisLog.Warnf("Del RrId:%s", subFields[3])
_ = rdb.Del(ctx, "RrId:"+subFields[3]).Err()
//return srem.Err()
}
}
}
}
if cursor == 0 {
break
}
}
return err
}
func RdbGetAcctPlanByKey(key string) (*AcctData, error) {
res := rdb.HGetAll(ctx, key)
err := res.Err()
if err != nil {
l4g.RedisLog.Errorf("HGetAll %s, err: %v", key, err)
return nil, err
}
var acct AcctData
if err = res.Scan(&acct); err != nil {
l4g.RedisLog.Errorf("HGetAll Scan %s, err: %v", key, err)
return nil, err
} else {
//l4g.RedisLog.Debugf("Get %s, [%v]", key, acct)
}
return &acct, err
}
func CheckIfAcctExpired(acct *MsgDef.AcctData) bool {
if acct == nil {
return false
}
nowStr := time.Now().Format("2006-01-02 15:04:05")
if strings.Compare(nowStr, acct.ExpTime[:len(nowStr)]) > 0 {
return true
}
return false
}
func RdbClrExpirePlanRecord() error {
l4g.RedisLog.Warnf("cron clear expire plan!")
var cursor uint64= 0
var err error
for {
var keys []string
keys, cursor, err = rdb.Scan(ctx, cursor, "Acct:*", 30).Result()
if err != nil {
l4g.RedisLog.Errorf("Scan Acct:*, err: %v", err)
break
}
for _, key := range keys {
subFields := strings.Split(key, ":")
if len(subFields) == 3 {
acct, err1 := RdbGetAcctPlanByKey(key)
if acct != nil && err1 == nil && CheckIfAcctExpired(acct) {
err1 = rdb.Del(ctx, key).Err()
if err1 != nil {
l4g.RedisLog.Errorf("Del Acct Plan[%s], err: %v", key, err1)
} else {
l4g.RedisLog.Warnf("Del Acct Plan[%s] succ", key)
l4g.RedisLog.Warnf("SRem Acct:%s %s", subFields[1], subFields[2])
_ = rdb.SRem(ctx, "Acct:"+subFields[1], subFields[2])
//return srem.Err()
}
}
}
}
if cursor == 0 {
break
}
}
return err
}
func ClrExpRes() {
_ = RdbClrExpireRrRecord()
_ = RdbClrExpirePlanRecord()
}
+40
View File
@@ -0,0 +1,40 @@
package Nredis
import (
l4g "proxy/logger"
)
type BinLogPos struct {
File string `redis:"file"`
Position uint32 `redis:"position"`
}
func RdbSetBinLogPos(file string, pos uint32) error {
err := rdb.HMSet(ctx, "binlogpos", "file", file, "position", pos).Err()
if err != nil {
l4g.RedisLog.Errorf("HMSet binlogpos %s %d, err: %v", file, pos, err)
}
return err
}
func RdbGetBinLogPos() *BinLogPos {
// Get the map. The same approach works for HmGet().
res := rdb.HGetAll(ctx, "binlogpos")
err := res.Err()
if err != nil {
l4g.RedisLog.Errorf("HGetAll binlogpos, err: %v", err)
return nil
}
// Scan the results into the struct.
var pos BinLogPos
if err = res.Scan(&pos); err != nil {
l4g.RedisLog.Errorf("HGetAll Scan binlogpos, err: %v", err)
return nil
} else {
l4g.RedisLog.Debugf("Get binlogpos, [%v]", pos)
return &pos
}
}
+47
View File
@@ -0,0 +1,47 @@
package Nredis
import (
"proxy/MsgDef"
l4g "proxy/logger"
"strconv"
)
func RdbSetCreateAcctRecord(r *MsgDef.ChgSyncMobile) error {
key := "CreateAcct:"+r.ServiceNbr+":"+strconv.Itoa(r.PreId)
err := rdb.HMSet(ctx, key, "prdInstId", r.PrdInstId, "serviceNbr", r.ServiceNbr,
"operType", r.OperType, "state", r.State, "ofrId", r.OfrId,
"custId", r.CustId, "acctId", r.AcctId, "mobileType", r.MobileType, "balance", r.Balance, "birthDate", r.BirthDate, "balanceExpDate", r.BalanceExpDate).Err()
if err != nil {
l4g.RedisLog.Errorf("HMSet %s, err: %v", key, err)
} else {
l4g.RedisLog.Debugf("HMSet %s, [%#v]", key, r)
sadd := rdb.SAdd(ctx, "Msg2OcsSet", key)
if sadd.Err() != nil {
l4g.RedisLog.Errorf("SAdd Msg2OcsSet %s, err: %v", key, sadd.Err())
return sadd.Err()
} else {
l4g.RedisLog.Debugf("SAdd Msg2OcsSet %s", key)
}
}
return err
}
func RdbGetCreateAcct(key string) *MsgDef.ChgSyncMobile {
res := rdb.HGetAll(ctx, key)
err := res.Err()
if err != nil {
l4g.RedisLog.Errorf("HGetAll %s, err: %v", key, err)
return nil
}
// Scan the results into the struct.
var acctInfo MsgDef.ChgSyncMobile
if err = res.Scan(&acctInfo); err != nil {
l4g.RedisLog.Errorf("HGetAll Scan %s, err: %v", key, err)
return nil
} else {
l4g.RedisLog.Debugf("Get %s, [%v]", key, acctInfo)
return &acctInfo
}
}
+30
View File
@@ -0,0 +1,30 @@
package Nredis
import (
l4g "proxy/logger"
"strconv"
)
func SetHdId2TariffId(id int, tariffId int) bool {
err := rdb.Set(ctx, "HdId:"+strconv.Itoa(id), strconv.Itoa(tariffId), 0).Err()
if err != nil {
l4g.RedisLog.Errorf("Set HdId:%d %s, err: %v", id, strconv.Itoa(tariffId), err)
return false
} else {
l4g.RedisLog.Infof("Set HdId:%d %s", id, tariffId)
return true
}
}
func GetTariffIdByHdId(id int) string {
var tariffIdStr string
var err error
tariffIdStr, err = rdb.Get(ctx, "HdId:"+strconv.Itoa(id)).Result()
if err != nil {
return ""
} else {
return tariffIdStr
}
}
+33
View File
@@ -0,0 +1,33 @@
package Nredis
import (
l4g "proxy/logger"
"strconv"
"time"
)
func CheckIfBundleLimitSent(planId uint32, rate int) bool {
n, err := rdb.Exists(ctx, "BundleLimit:"+strconv.Itoa(int(planId))+":"+strconv.Itoa(rate)).Result()
if err != nil {
l4g.RedisLog.Errorf("Check Exists PlanExpiry:%d, err: %v", planId, err)
return false
} else {
if n >= 1 {
return true
} else {
return false
}
}
}
func SetPlanExpire(planId uint32, rate int) error {
key := "BundleLimit:"+strconv.Itoa(int(planId))+":"+strconv.Itoa(rate)
err := rdb.Set(ctx, key, "1", time.Hour * 24 * 15).Err()
if err != nil {
l4g.RedisLog.Errorf("Set BundleLimit:%d:%d, err: %v", planId, rate, err)
} else {
l4g.RedisLog.Debugf("Set BundleLimit:%d:%d, succ", planId, rate)
}
return err
}
+601
View File
@@ -0,0 +1,601 @@
package Nredis
import (
"context"
"fmt"
rds "github.com/go-redis/redis/v8"
"os"
l4g "proxy/logger" //"github.com/sirupsen/logrus"
"strconv"
"strings"
. "proxy/MsgDef"
)
var ctx = context.Background()
var rdb *rds.Client
var locRdb *rds.Client
func NewRedisClient(netType, addr, passwd string, sentinels []string) {
if sentinels != nil {
rdb = rds.NewFailoverClient(&rds.FailoverOptions{
MasterName: "mymaster",
SentinelAddrs: sentinels,
Password: passwd,
DB: 0,
PoolSize: 5,
})
locRdb = rds.NewClient(&rds.Options{
Network: netType,// The network type, either tcp or unix. Default is tcp.
Addr: addr,// can be: /var/run/redis/redis-server.sock???
Password: passwd, // no password set
DB: 0, // use default DB
PoolSize: 5,
})
} else {
rdb = rds.NewClient(&rds.Options{
Network: netType,// The network type, either tcp or unix. Default is tcp.
Addr: addr,// can be: /var/run/redis/redis-server.sock???
Password: passwd, // no password set
DB: 0, // use default DB
PoolSize: 5,
})
locRdb = rdb
}
pong, err := rdb.Ping(ctx).Result()
if err != nil {
l4g.RedisLog.Errorf("%v, err: %v", pong, err)// Output: PONG <nil>
os.Exit(1)
} else {
l4g.RedisLog.Debugf("%v", pong)// Output: PONG <nil>
}
return
}
func CheckIfNeedToSyncDb() (bool, error) {
/*if CheckIfRdbMaster() == false {
return false, nil
}*/
size, err := rdb.DBSize(ctx).Result()
if err == nil {
if size < 10 {
return true, nil
} else {
return false, nil
}
} else {
return false, err
}
}
func ClrTariffAndBundle() {
rdb.FlushDB(ctx)
/*n, err := rdb.Del(ctx, "Acct:*").Result()
if err != nil {
l4g.Errorf("Del Acct, err: %v", err)
} else {
l4g.Debugf("Del Acct, num[%d]", n)
}
n, err = rdb.Del(ctx, "Rr:*").Result()
if err != nil {
l4g.Errorf("Del Rr, err: %v", err)
} else {
l4g.Debugf("Del Rr, num[%d]", n)
}
n, err = rdb.Del(ctx, "Prefix:*").Result()
if err != nil {
l4g.Errorf("Del Prefix, err: %v", err)
} else {
l4g.Debugf("Del Prefix, num[%d]", n)
}
n, err = rdb.Del(ctx, "Tariff:*").Result()
if err != nil {
l4g.Errorf("Del Tariff, err: %v", err)
} else {
l4g.Debugf("Del Tariff, num[%d]", n)
}*/
}
func CheckIfRdbMaster() bool {
info := locRdb.Info(ctx, "Replication")
if strings.Contains(info.Val(), "role:master") || strings.Contains(info.Val(), "role:active-replica") {
return true
} else {
return false
}
}
func SetRrId2RrKey(id int64, rrKey string) bool {
err := rdb.Set(ctx, "RrId:"+strconv.FormatInt(id, 10), rrKey, 0).Err()
if err != nil {
l4g.RedisLog.Errorf("Set RrId:%d %s, err: %v", id, rrKey, err)
return false
} else {
l4g.RedisLog.Infof("Set RrId:%d %s", id, rrKey)
return true
}
}
func GetRrKeyByRrId(id int64) string {
var rrKey string
var err error
rrKey, err = rdb.Get(ctx, "RrId:"+strconv.FormatInt(id, 10)).Result()
if err != nil {
return ""
} else {
return rrKey
}
}
func RdbSetRrRecord(rr *RrData) error {
key := "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.FormatInt(rr.RrId, 10)
err := rdb.HMSet(ctx, key, "prdInstId", rr.PrdInstId, "serviceNbr", rr.ServiceNbr,
"pricingSectionId", rr.PricingSectionId, "ofrInstId", rr.OfrInstId, "ofrId", rr.OfrId,
"ofrName", rr.OfrName, "beginTime", rr.BeginTime, "endTime", rr.EndTime, "freeValue", rr.FreeValue, "rateUnit", rr.RateUnit, "unitFee", rr.UnitFee,
"usedValue", rr.UsedValue, "measureDomain", rr.MeasureDomain, "tariffId", rr.TariffId, "strategyId", rr.StrategyId,
"startRefTime", rr.StartRefTime, "endRefTime", rr.EndRefTime, "calcPriority", rr.CalcPriority, "eventPriority", rr.EventPriority).Err()
if err != nil {
l4g.RedisLog.Errorf("HMSet Rr:%s, err: %v", rr.ServiceNbr, err)
} else {
l4g.RedisLog.Debugf("HMSet Rr:%s, [%#v]", rr.ServiceNbr, rr)
sadd := rdb.SAdd(ctx, "RrSet:"+rr.ServiceNbr+":"+rr.MeasureDomain, strconv.FormatInt(rr.RrId, 10))
if sadd.Err() != nil {
l4g.RedisLog.Errorf("SAdd RrSet:%s:%s %d, err: %v", rr.ServiceNbr, rr.MeasureDomain, rr.RrId, sadd.Err())
return sadd.Err()
} else {
l4g.RedisLog.Debugf("SAdd RrSet:%s:%s %d", rr.ServiceNbr, rr.MeasureDomain, rr.RrId)
}
SetRrId2RrKey(rr.RrId, key)
}
return err
}
func RdbSetStrategyEventPriority(rr *RrData) error {
err := rdb.HMSet(ctx, "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.FormatInt(rr.RrId, 10), "eventPriority", rr.EventPriority).Err()
if err != nil {
l4g.RedisLog.Errorf("HMSet Rr:%s, err: %v", rr.ServiceNbr, err)
}
return err
}
func RdbSetOfrCalcPriority(rr *RrData) error {
err := rdb.HMSet(ctx, "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.FormatInt(rr.RrId, 10), "calcPriority", rr.CalcPriority).Err()
if err != nil {
l4g.RedisLog.Errorf("HMSet Rr:%s, err: %v", rr.ServiceNbr, err)
}
return err
}
// "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.Itoa(rr.RrId)
func RdbUpdateRrRecordOnly(rrId int64, ratableVal, usedVal int64, beginTime, endTime string) (int, error) {
key := GetRrKeyByRrId(rrId)
if key != "" {
err := rdb.HMSet(ctx, key, "beginTime", beginTime, "endTime", endTime, "freeValue", ratableVal,
"usedValue", usedVal).Err()
if err != nil {
l4g.RedisLog.Errorf("HMSet %s, err: %v", key, err)
return -1, err
} else {
l4g.RedisLog.Debugf("HMSet %s, beginTime[%s], endTime[%s], free/used:[%d/%d]", key, beginTime, endTime, ratableVal, usedVal)
return 1, nil
}
} else {
l4g.RedisLog.Errorf("HMSet rrId[%d], err not found, beginTime[%s], endTime[%s], free/used:[%d/%d]", rrId, beginTime, endTime, ratableVal, usedVal)
return 0, nil
}
/*var cursor uint64
var err error
for {
var keys []string
// 20 keys each scan
keys, cursor, err = rdb.Scan(ctx, cursor, "Rr:*:"+strconv.FormatInt(rrId, 10), 2).Result()
if err != nil {
l4g.RedisLog.Errorf("Scan Rr:*:%d, err: %v", rrId, err)
break
}
//fmt.Printf("\nfound %d keys\n", len(keys))
for _, key := range keys {
err := rdb.HMSet(ctx, key, "beginTime", beginTime, "endTime", endTime, "freeValue", ratableVal,
"usedValue", usedVal).Err()
if err != nil {
l4g.RedisLog.Errorf("HMSet %s, err: %v", key, err)
}
}
if cursor == 0 {
break
}
}
return err*/
}
// "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.Itoa(rr.RrId)
func RdbDelRrRecordByRrId(rrId int64) error {
key := GetRrKeyByRrId(rrId)
if key != "" {
err := rdb.Del(ctx, key).Err()
if err != nil {
l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
} else {
l4g.RedisLog.Infof("Del %s succ", key)
subFields := strings.Split(key, ":")
if len(subFields) == 4 {
_ = rdb.SRem(ctx, "RrSet:"+subFields[1]+":"+subFields[2], strconv.FormatInt(rrId, 10))
l4g.RedisLog.Infof("SRem %d from RrSet:%s:%s", rrId, subFields[1], subFields[2])
//return srem.Err()
}
}
rdb.Del(ctx, "RrId:"+strconv.FormatInt(rrId, 10))
l4g.RedisLog.Infof("Del RrId:%d", rrId)
return nil
}
return nil
}
// "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.Itoa(rr.RrId)
func RdbDelRrRecordByServiceNbr(serviceNbr string) error {
var cursor uint64
var err error
for {
var keys []string
// 20 keys each scan
keys, cursor, err = rdb.Scan(ctx, cursor, "Rr:"+serviceNbr+":*", 30).Result()
if err != nil {
l4g.RedisLog.Errorf("Scan Rr:%s:*, err: %v", serviceNbr, err)
break
}
//fmt.Printf("\nfound %d keys\n", len(keys))
for _, key := range keys {
err = rdb.Del(ctx, key).Err()
if err != nil {
l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
} else {
subFields := strings.Split(key, ":")
if len(subFields) == 4 {
_ = rdb.SRem(ctx, "RrSet:"+serviceNbr+":"+subFields[2], subFields[3])
//return srem.Err()
}
}
}
if cursor == 0 {
break
}
}
return err
}
func RdbDelRrRecord(rr *RrData) error {
err := rdb.Del(ctx, "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.FormatInt(rr.RrId, 10)).Err()
if err != nil {
l4g.RedisLog.Errorf("Del Rr:%s:%d, err: %v", rr.ServiceNbr, rr.RrId, err)
} else {
_ = rdb.SRem(ctx, "RrSet:"+rr.ServiceNbr+":"+rr.MeasureDomain, strconv.FormatInt(rr.RrId, 10))
}
return err
}
func RdbSetOfrRecord(ofrId int) error {
err := rdb.Set(ctx, "Ofr:"+strconv.Itoa(ofrId), ofrId, 0).Err()
if err != nil {
l4g.RedisLog.Errorf("Set Ofr:%d, err: %v", ofrId, err)
}
return err
}
func RdbCheckIfOfrExist(ofrId int) bool {
n, err := rdb.Exists(ctx, "Ofr:"+strconv.Itoa(ofrId)).Result()
if err != nil {
l4g.RedisLog.Errorf("Check Exists Ofr:%d, err: %v", ofrId, err)
return false
} else {
if n >= 1 {
return true
} else {
return false
}
}
}
func RdbSetPrefixRecord(prefix *PrefixData) error {
sadd := rdb.SAdd(ctx, "Prefix:"+strconv.Itoa(prefix.StrategyId), prefix.AreaCode)
return sadd.Err()
}
// Add holiday discount table
// Hd:tariff_id:tariff_seq:hdId, group, name, discount, state;;; type, subState, priority, begin, end;
// triggers: 1, create, modify(state), delete of tb_bil_holiday_rel;
// 2, modify(STATE), delete of tb_bil_holiday;
/* holiday discount
SELECT hd.HOLIDAY_GROUP, hd.HOLIDAY_PRIORITY, COUNT(1) AS HOLIDAY_COUNT FROM tb_bil_holiday hd
WHERE (((hd.HOLIDAY_TYPE = '02' AND hd.HOLIDAY_BEGIN_DATE <= (WEEKDAY(SYSDATE()) + 1) AND hd.holiday_end_date >= (WEEKDAY(SYSDATE()) + 1))
OR (hd.holiday_type = '03' AND DATE_FORMAT(SYSDATE(),'%m%d') >= DATE_FORMAT(CONCAT('2020', hd.HOLIDAY_BEGIN_DATE), '%m%d') AND DATE_FORMAT(SYSDATE(),'%m%d') <= DATE_FORMAT(CONCAT('2020', hd.holiday_end_date), '%m%d'))
OR (hd.holiday_type = '04' AND DATE_FORMAT(SYSDATE(), '%H%i%s') >= DATE_FORMAT(STR_TO_DATE(CONCAT('20200101', hd.HOLIDAY_BEGIN_DATE), '%Y%m%d%H%i%s'),'%H%i%s')
AND DATE_FORMAT(SYSDATE(), '%H%i%s') <= DATE_FORMAT(STR_TO_DATE(CONCAT('20200101', hd.holiday_end_date), '%Y%m%d%H%i%s'),'%H%i%s')))
and hd.STATE='L0R')
GROUP BY hd.HOLIDAY_PRIORITY, hd.HOLIDAY_GROUP;
*/
func RdbSetHolidayDiscountRecord(hd *HolidayDiscountData) error {
err := rdb.HMSet(ctx, "Hd:"+strconv.Itoa(hd.TariffId)+":"+strconv.Itoa(hd.HdId),
"ofrId", hd.OfrId, "tariffId", hd.TariffId, "tariffSeq", hd.TariffSeq, "hdGroup", hd.HdGroup,
"hrState", hd.HrState, "hrDiscount", hd.HrDiscount, "hdId", hd.HdId, "hdName", hd.HdName,
"hdType", hd.HdType, "hdState", hd.HdState, "hdPriority", hd.HdPriority,
"hdBeginDate", hd.HdBeginDate, "hdEndDate", hd.HdEndDate).Err()
if err != nil {
l4g.RedisLog.Errorf("HMSet Hd:%d:%d, err: %v", hd.TariffId, hd.HdId, err)
} else {
sadd := rdb.SAdd(ctx, "HdSet:"+strconv.Itoa(hd.TariffId), strconv.Itoa(hd.HdId))
if sadd.Err() != nil {
l4g.RedisLog.Errorf("SAdd HdSet:%d %d, err: %v", hd.TariffId, hd.HdId, sadd.Err())
return sadd.Err()
}
SetHdId2TariffId(hd.HdId, hd.TariffId)
}
return err
}
func RdbDelHolidayDiscountRecord(tariffId int) {
var cursor uint64= 0
for {
// 20 keys each scan
keys, cursorNew, err := rdb.SScan(ctx, "HdSet:"+strconv.Itoa(tariffId), cursor, "", 0).Result()
if err != nil {
l4g.RedisLog.Errorf("SScan HdSet:%d, err: %v", tariffId, err)
break
}
//fmt.Printf("\nfound %d keys\n", len(keys))
for _, key := range keys {
hdKey := "Hd:"+strconv.Itoa(tariffId) + ":" + key
err := rdb.Del(ctx, hdKey).Err()
if err != nil {
l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
} else {
//subFields := strings.Split(key, ":")
//if len(subFields) == 3 && subFields[2] != "" {
_ = rdb.SRem(ctx, "HdSet:"+strconv.Itoa(tariffId), key)
//return srem.Err()
//}
}
}
if cursorNew == 0 {
break
} else {
cursor = cursorNew
}
}
_ = rdb.Del(ctx, "HdSet:"+strconv.Itoa(tariffId)).Err()
return
}
func RdbDelHolidayDiscountRecordByHd(holidayId int) error {
tariffIdStr := GetTariffIdByHdId(holidayId)
tariffId, err := strconv.Atoi(tariffIdStr)
if err != nil {
l4g.RedisLog.Errorf("Get tariffId by HdId %d, err: %v", holidayId, err)
} else {
key := "Hd:" + strconv.Itoa(tariffId) + ":"+strconv.Itoa(holidayId)
err := rdb.Del(ctx, key).Err()
if err != nil {
l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
} else {
_ = rdb.SRem(ctx, "HdSet:"+tariffIdStr, strconv.Itoa(holidayId))
}
}
/*var cursor uint64
for {
var keys []string
// 20 keys each scan
keys, cursor, err = rdb.Scan(ctx, cursor, "Hd:*:"+strconv.Itoa(holidayId), 200).Result()
if err != nil {
l4g.RedisLog.Errorf("Scan Hd:*:%d, err: %v", holidayId, err)
break
}
//fmt.Printf("\nfound %d keys\n", len(keys))
for _, key := range keys {
err := rdb.Del(ctx, key).Err()
if err != nil {
l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
} else {
subFields := strings.Split(key, ":")
if len(subFields) == 3 && subFields[1] != "" {
_ = rdb.SRem(ctx, "HdSet:"+subFields[1], strconv.Itoa(holidayId))
//return srem.Err()
}
}
}
if cursor == 0 {
break
}
}*/
return err
}
// "Tariff:"+strconv.Itoa(tariff.OfrId)+":"+tariff.MeasureDomain+":"+strconv.Itoa(tariff.TariffId)
func RdbDelTariffRecord(tariffId int) error {
var cursor uint64
var err error
for {
var keys []string
// 20 keys each scan
keys, cursor, err = rdb.Scan(ctx, cursor, "Tariff:*:"+strconv.Itoa(tariffId), 2).Result()
if err != nil {
l4g.RedisLog.Errorf("Scan Tariff:*:%d, err: %v", tariffId, err)
break
}
//fmt.Printf("\nfound %d keys\n", len(keys))
for _, key := range keys {
err := rdb.Del(ctx, key).Err()
if err != nil {
l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
} else {
subFields := strings.Split(key, ":")
if len(subFields) == 4 {
_ = rdb.SRem(ctx, "TariffSet:"+subFields[1]+":"+subFields[2], strconv.Itoa(tariffId))
//return srem.Err()
}
}
}
if cursor == 0 {
break
}
}
return err
}
// "Tariff:"+strconv.Itoa(tariff.OfrId)+":"+tariff.MeasureDomain+":"+strconv.Itoa(tariff.TariffId)
func RdbDelTariffRecordByOfr(ofrId int) error {
var cursor uint64
var err error
for {
var keys []string
// 20 keys each scan
keys, cursor, err = rdb.Scan(ctx, cursor, "Tariff:"+strconv.Itoa(ofrId)+":*", 2).Result()
if err != nil {
l4g.RedisLog.Errorf("Scan Tariff:%d:*, err: %v", ofrId, err)
break
}
//fmt.Printf("\nfound %d keys\n", len(keys))
for _, key := range keys {
err := rdb.Del(ctx, key).Err()
if err != nil {
l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
} else {
subFields := strings.Split(key, ":")
if len(subFields) == 4 {
_ = rdb.SRem(ctx, "TariffSet:"+subFields[1]+":"+subFields[2], subFields[3])
//return srem.Err()
}
}
}
if cursor == 0 {
break
}
}
return err
}
func RdbDelPrefixRecord(strategyId int, areaCode string) error {
srem := rdb.SRem(ctx, "Prefix:"+strconv.Itoa(strategyId), areaCode)
return srem.Err()
}
func RdbSetTariffRecord(tariff *TariffData) error {
//&prd_inst_id, &service_nbr, &prd_inst_stas_id, &acct_id, &cust_id
err := rdb.HMSet(ctx, "Tariff:"+strconv.Itoa(tariff.OfrId)+":"+tariff.MeasureDomain+":"+strconv.Itoa(tariff.TariffId), "tariffId", tariff.TariffId,
"tariffSeq", tariff.TariffSeq, "measureDomain", tariff.MeasureDomain,
"startTime", tariff.StartTime, "endTime", tariff.EndTime, "feeUnit", tariff.FeeUnit,
"rateUnit", tariff.RateUnit, "calcPriority", tariff.CalcPriority, "eventPriority", tariff.EventPriority, "ofrId", tariff.OfrId,
"ofrName", tariff.OfrName, "strategyId", tariff.StrategyId, "strategyName", tariff.StrategyName).Err()
if err != nil {
l4g.RedisLog.Errorf("HMSet Tariff:%d, err: %v", tariff.TariffId, err)
} else {
sadd := rdb.SAdd(ctx, "TariffSet:"+strconv.Itoa(tariff.OfrId)+":"+tariff.MeasureDomain, strconv.Itoa(tariff.TariffId))
if sadd.Err() != nil {
l4g.RedisLog.Errorf("SAdd TariffSet:%d:%s %d, err: %v", tariff.OfrId, tariff.MeasureDomain, tariff.TariffId, sadd.Err())
return sadd.Err()
}
}
return err
}
func RdbGetRrByServiceNbrAndDomain(serviceNbrAndDomain string) (rsp string, err error) {
var cursor uint64= 0
for {
keys, cursorNew, err := rdb.SScan(ctx, "RrSet:"+serviceNbrAndDomain, cursor, "", 0).Result()
if err != nil {
l4g.RedisLog.Errorf("SScan RrSet:%s, err: %v", serviceNbrAndDomain, err)
break
}
//fmt.Printf("\nfound %d keys\n", len(keys))
for _, key := range keys {
rrKey := "Rr:"+serviceNbrAndDomain+":"+key
res := rdb.HGetAll(ctx, rrKey)
if res.Err() != nil {
l4g.RedisLog.Errorf("HGetAll %s, err: %v", rrKey, err)
return "err: HGetAll "+rrKey, err
} else {
var rrData RrData
if err = res.Scan(&rrData); err != nil {
l4g.RedisLog.Errorf("HGetAll Scan %s, err: %v", rrKey, err)
return "err: Scan "+rrKey, err
} else {
l4g.RedisLog.Debugf("Get %s, [%v]", rrKey, rrData)
rsp += fmt.Sprintf("%s:***************************************\r\nPrdInstId: %d\r\nOfrInstId: %d\r\nOfrId: %d\r\nOfrName: %s\r\nBeginTime: %s\r\nEndTime: %s\r\n",
rrKey, rrData.PrdInstId, rrData.OfrInstId, rrData.OfrId, rrData.OfrName, rrData.BeginTime, rrData.EndTime)
rsp += fmt.Sprintf("FreeValue: %d\r\nUsedValue: %d\r\nTariffId: %d\r\nStrategyId: %d\r\nCalcPriority: %d\r\nEventPriority: %d\r\nRateUnit: %d\r\nUnitFee: %d\r\n",
rrData.FreeValue, rrData.UsedValue, rrData.TariffId, rrData.StrategyId, rrData.CalcPriority, rrData.EventPriority, rrData.RateUnit, rrData.UnitFee)
}
}
}
if cursorNew == 0 {
break
} else {
cursor = cursorNew
}
}
return rsp, err
}
func RdbGetTariffByOfrId(ofrId string) (*TariffData, error) {
keys := rdb.Keys(ctx, "Tariff:"+ofrId+":*")
err := keys.Err()
if err != nil {
l4g.RedisLog.Errorf("Get Keys of Tariff:%s:*, err: %v", ofrId, err)
return nil, err
} else {
l4g.RedisLog.Debugf("Get Keys of Tariff:%s:*, keys:%v", ofrId, keys.Val())
}
// Scan the results into the struct.
var ta TariffData
for _, value := range keys.Val() {
// Get the map. The same approach works for HmGet().
res := rdb.HGetAll(ctx, value)
err := res.Err()
if err != nil {
l4g.RedisLog.Errorf("HGetAll %s, err: %v", value, err)
return nil, err
}
if err = res.Scan(&ta); err != nil {
l4g.RedisLog.Errorf("HGetAll Scan %s, err: %v", value, err)
} else {
l4g.RedisLog.Debugf("Get %s, [%v]", value, ta)
// Get prefix related tariff
sMembers := rdb.SMembers(ctx, "Prefix:"+strconv.Itoa(ta.StrategyId))
if sMembers.Err() == nil {
l4g.RedisLog.Debugf("Prefix, [%v]", sMembers.Val())
}
}
}
return &ta, err
}
+51
View File
@@ -0,0 +1,51 @@
package Nrestful
import (
mysql "proxy/Nmysql"
rdb "proxy/Nredis"
"strconv"
"strings"
)
func RdbScanAlertSmsRecord() {
keys := rdb.RdbScanAlertSmsRecord()
for _, key := range keys {
if strings.HasPrefix(key, "AlertSms:") {
smsContent := rdb.RdbGetAlertSmsContent(key)
if smsContent != "" {
ss := strings.Split(key, ":")
if len(ss) >= 3 {
SendNtfSms2Ocs(ss[1], smsContent)
alertId, _ := strconv.Atoi(ss[2])
_ = mysql.SetAlertSmsState2Sent(alertId)
}
}
rdb.RdsDelMsg2OcsKey(key)
} else if strings.HasPrefix(key, "CreateAcct:") {
ai := rdb.RdbGetCreateAcct(key)
if ai != nil {
ss := strings.Split(key, ":")
if len(ss) >= 3 {
cugId, err := mysql.QueryOfrIdByPrdInstId(ai.PrdInstId)
userClass := 1
ofrLevel, err := mysql.QueryOfrLevelByOfrId(ai.OfrId)
if err == nil {
userClass = ofrLevel
}
rent, _ := mysql.QueryRentByOfrId(ai.OfrId)
//SendCrtAcct2Ocs(ss[1], ai, cugId, userClass, rent)
CreateAcct2Ocs(ss[1], ai, cugId, userClass, rent, key)
}
}
}
}
//for _, key := range keys {
// rdb.RdsDelMsg2OcsKey(key)
//}
return
}
+575
View File
@@ -0,0 +1,575 @@
package Nrestful
import (
"time"
"encoding/binary"
_ "strings"
"strconv"
l4g "proxy/logger"//"github.com/sirupsen/logrus"
)
func decode_authcode_rsp(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
var result byte = 1
for {
if offset >= msglen {
break
}
tag = buf[offset];
offset++
vallen = buf[offset];
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_RESULT:
result = buf[offset]
if result == 0 {
rsp.AuthCodeRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
rsp.AuthCodeRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
}
case IE_ERROR_CODE:
err_code := binary.BigEndian.Uint32(buf[offset:offset+4])
rsp.AuthCodeRsp.Code = strconv.Itoa(int(err_code))
rsp.AuthCodeRsp.Message = Rest_proxy_errcodemsg(err_code)
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decode_authcode_rsp: %#v", rsp.AuthCodeRsp)
return 0;
}
func decode_query_userData_rsp(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
var result byte = 1
for {
if offset >= msglen {
break
}
tag = buf[offset];
offset++
vallen = buf[offset];
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_RESULT:
result = buf[offset]
if result == 0 {
rsp.QueryUserDataRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
rsp.QueryUserDataRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
}
case IE_ERROR_CODE:
err_code := binary.BigEndian.Uint32(buf[offset:offset+4])
rsp.QueryUserDataRsp.Code = strconv.Itoa(int(err_code))
rsp.QueryUserDataRsp.Message = Rest_proxy_errcodemsg(err_code)
case IE_MSISDN:
rsp.QueryUserDataRsp.TelNumber = string(buf[offset:offset+int(vallen)])
case IE_REMARK:
rsp.QueryUserDataRsp.Remark = string(buf[offset:offset+int(vallen)])
case IE_GROUP_NAME:
rsp.QueryUserDataRsp.UserGroupName = string(buf[offset:offset+int(vallen)])
case IE_STATUS:
rsp.QueryUserDataRsp.Status = strconv.Itoa(int(buf[offset]))
case IE_BALANCE:
rsp.QueryUserDataRsp.Balance = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
case IE_EXPIRY_TIME:
tm := time.Unix(int64(binary.BigEndian.Uint64(buf[offset:offset+8])), 0)
rsp.QueryUserDataRsp.ExpireDate = tm.Format("2006-01-02 15:04:05")
case IE_REMAIN_MO_VOICE_MIN:
rsp.QueryUserDataRsp.RemainMoVoiceMinute = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
case IE_REMAIN_MT_VOICE_MIN:
rsp.QueryUserDataRsp.RemainMtVoiceMinute = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
case IE_REMAIN_SMS_NUM:
rsp.QueryUserDataRsp.RemainSmsVolume = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
case IE_REMAIN_DATA_VOL_MB:
rsp.QueryUserDataRsp.RemainDataVolume = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decode_query_userData_rsp: %#v", rsp.QueryUserDataRsp)
return 0;
}
func decode_bundleSubs_rsp(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
var result byte = 1
for {
if offset >= msglen {
break
}
tag = buf[offset];
offset++
vallen = buf[offset];
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_RESULT:
result = buf[offset]
if result == 0 {
rsp.BundleSubsRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
rsp.BundleSubsRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
}
case IE_ERROR_CODE:
err_code := binary.BigEndian.Uint32(buf[offset:offset+4])
rsp.BundleSubsRsp.Code = strconv.Itoa(int(err_code))
rsp.BundleSubsRsp.Message = Rest_proxy_errcodemsg(err_code)
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decode_bundleSubs_rsp: %#v", rsp.BundleSubsRsp)
return 0
}
func decode_query_balance_rsp(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
var result byte = 1
for {
if offset >= msglen {
break
}
tag = buf[offset];
offset++
vallen = buf[offset];
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_RESULT:
result = buf[offset]
if result == 0 {
rsp.QueryBalanceRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
rsp.QueryBalanceRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
}
case IE_ERROR_CODE:
err_code := binary.BigEndian.Uint32(buf[offset:offset+4])
rsp.QueryBalanceRsp.Code = strconv.Itoa(int(err_code))
rsp.QueryBalanceRsp.Message = Rest_proxy_errcodemsg(err_code)
case IE_STATUS:
rsp.QueryBalanceRsp.Status = strconv.Itoa(int(buf[offset]))
case IE_BALANCE:
rsp.QueryBalanceRsp.Balance = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
case IE_MO_EXPIRY:
tm := time.Unix(int64(binary.BigEndian.Uint32(buf[offset:offset+4])), 0)
rsp.QueryBalanceRsp.ExpireDate = tm.Format("2006-01-02 15:04:05")
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decode_query_balance_rsp: %#v", rsp.QueryBalanceRsp)
return 0
}
func decode_recharge_rsp(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
var result byte = 1
for {
if offset >= msglen {
break
}
tag = buf[offset];
offset++
vallen = buf[offset];
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_RESULT:
result = buf[offset]
if result == 0 {
rsp.RechargeRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
rsp.RechargeRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
}
case IE_ERROR_CODE:
var err_code uint32
if vallen == 1 {
err_code = uint32(buf[offset])
} else {
err_code = binary.BigEndian.Uint32(buf[offset:offset+4])
}
rsp.RechargeRsp.Code = strconv.Itoa(int(err_code))
rsp.RechargeRsp.Message = Rest_proxy_errcodemsg(err_code)
case IE_STATUS:
rsp.RechargeRsp.Status = strconv.Itoa(int(buf[offset]))
case IE_BALANCE:
rsp.RechargeRsp.Balance = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
case IE_MO_EXPIRY:
tm := time.Unix(int64(binary.BigEndian.Uint32(buf[offset:offset+4])), 0)
rsp.RechargeRsp.ExpiredTimestamp = tm.Format("2006-01-02 15:04:05")
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decode_recharge_rsp: %#v", rsp.RechargeRsp)
return 0
}
func decode_transfer_rsp(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
var result byte = 1
for {
if offset >= msglen {
break
}
tag = buf[offset];
offset++
vallen = buf[offset];
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_RESULT:
result = buf[offset]
if result == 0 {
rsp.TransferRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
rsp.TransferRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
}
case IE_ERROR_CODE:
var err_code uint32
if vallen == 1 {
err_code = uint32(buf[offset])
} else {
err_code = binary.BigEndian.Uint32(buf[offset:offset+4])
}
rsp.TransferRsp.Code = strconv.Itoa(int(err_code))
rsp.TransferRsp.Message = Rest_proxy_errcodemsg(err_code)
case IE_AMOUNT:
rsp.TransferRsp.Balance = strconv.Itoa(int(binary.BigEndian.Uint32(buf[offset:offset+4])))
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decode_transfer_rsp: %#v", rsp.TransferRsp)
return 0
}
func decode_create_acct_rsp(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
var result byte = 1
for {
if offset >= msglen {
break
}
tag = buf[offset];
offset++
vallen = buf[offset];
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_RESULT:
result = buf[offset]
if result == 0 {
rsp.CreateAccountRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
rsp.CreateAccountRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
}
case IE_ERROR_CODE:
var err_code uint32
if vallen == 1 {
err_code = uint32(buf[offset])
} else {
err_code = binary.BigEndian.Uint32(buf[offset:offset+4])
}
rsp.CreateAccountRsp.Code = strconv.Itoa(int(err_code))
rsp.CreateAccountRsp.Message = Rest_proxy_errcodemsg(err_code)
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decode_create_acct_rsp: %#v", rsp.CreateAccountRsp)
return 0
}
func decode_update_subs_req(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
rsp.UpdateSubsReq.OptFlag = 0
for {
if offset >= msglen {
break
}
tag = buf[offset]
offset++
vallen = buf[offset]
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_MSISDN:
rsp.UpdateSubsReq.TelNumber = string(buf[offset:offset+int(vallen)])
case IE_ACCOUNT_ID:
rsp.UpdateSubsReq.AccountIdU32 = binary.BigEndian.Uint32(buf[offset:offset+4])
case IE_STATUS:
rsp.UpdateSubsReq.StatusU8 = buf[offset]
rsp.UpdateSubsReq.OptFlag |= 0x01
case IE_BALANCE:
rsp.UpdateSubsReq.BalanceU32 = binary.BigEndian.Uint32(buf[offset:offset+4])
rsp.UpdateSubsReq.OptFlag |= 0x02
case IE_EXPIRY_TIME:
rsp.UpdateSubsReq.ExpDateU32 = binary.BigEndian.Uint32(buf[offset:offset+4])
rsp.UpdateSubsReq.OptFlag |= 0x04
case IE_PLAN_ID:
rsp.UpdateSubsReq.PackageIdU32 = binary.BigEndian.Uint32(buf[offset:offset+4])
rsp.UpdateSubsReq.OptFlag |= 0x08
case IE_RENT_CHARGE:
rsp.UpdateSubsReq.RentChargeU32 = binary.BigEndian.Uint32(buf[offset:offset+4])
rsp.UpdateSubsReq.OptFlag |= 0x10
case IE_VAS_CUG_STATUS:
rsp.UpdateSubsReq.VasCugStatusU8 = buf[offset]
rsp.UpdateSubsReq.OptFlag |= 0x20
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decode_update_subs_req: %#v", rsp.UpdateSubsReq)
return 0
}
func decode_update_subs_rsp(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
var result byte = 1
for {
if offset >= msglen {
break
}
tag = buf[offset];
offset++
vallen = buf[offset];
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_RESULT:
result = buf[offset]
if result == 0 {
rsp.UpdateSubsRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
rsp.UpdateSubsRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
}
case IE_ERROR_CODE:
var err_code uint32
if vallen == 1 {
err_code = uint32(buf[offset])
} else {
err_code = binary.BigEndian.Uint32(buf[offset:offset+4])
}
rsp.UpdateSubsRsp.Code = strconv.Itoa(int(err_code))
rsp.UpdateSubsRsp.Message = Rest_proxy_errcodemsg(err_code)
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decode_update_subs_rsp: %#v", rsp.UpdateSubsRsp)
return 0
}
func decode_delete_subs_rsp(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
var result byte = 1
for {
if offset >= msglen {
break
}
tag = buf[offset]
offset++
vallen = buf[offset]
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_RESULT:
result = buf[offset]
rsp.DeleteSubsRsp.Result = result
if result == 0 {
rsp.DeleteSubsRsp.Code = strconv.Itoa(int(ERRCODE_SUCCESS))
rsp.DeleteSubsRsp.Message = Rest_proxy_errcodemsg(ERRCODE_SUCCESS)
}
case IE_ERROR_CODE:
var err_code uint32
if vallen == 1 {
err_code = uint32(buf[offset])
} else {
err_code = binary.BigEndian.Uint32(buf[offset:offset+4])
}
rsp.DeleteSubsRsp.ErrorCode = err_code
rsp.DeleteSubsRsp.Code = strconv.Itoa(int(err_code))
rsp.DeleteSubsRsp.Message = Rest_proxy_errcodemsg(err_code)
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decode_update_subs_rsp: %#v", rsp.UpdateSubsRsp)
return 0
}
func decodeUpdateBundleUsageReq(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
var tag byte = 0
var vallen byte = 0
for {
if offset >= msglen {
break
}
tag = buf[offset]
offset++
vallen = buf[offset]
offset++
switch tag {
case IE_SRC_REF:
rsp.Src_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_DST_REF:
rsp.Dst_id = binary.BigEndian.Uint16(buf[offset:offset+2])
case IE_MSISDN:
rsp.UpdateBundleUsageReq.Msisdn = string(buf[offset:offset+int(vallen)])
case IE_SERVICE_TYPE:
rsp.UpdateBundleUsageReq.ServiceType = buf[offset]
case IE_ACCOUNT_ID:
rsp.UpdateBundleUsageReq.AccountId = binary.BigEndian.Uint32(buf[offset:offset+4])
case IE_PLAN_ID:
rsp.UpdateBundleUsageReq.PlanId = binary.BigEndian.Uint32(buf[offset:offset+4])
case IE_BUNDLE_ID:
rsp.UpdateBundleUsageReq.BundleId = binary.BigEndian.Uint32(buf[offset:offset+4])
case IE_PLAN_VALUE:
rsp.UpdateBundleUsageReq.PlanValue = binary.BigEndian.Uint64(buf[offset:offset+8])
case IE_PLAN_USED_VALUE:
rsp.UpdateBundleUsageReq.PlanUsedValue = binary.BigEndian.Uint64(buf[offset:offset+8])
case IE_SESS_UPDATE_TIME:
rsp.UpdateBundleUsageReq.SessUpdateTime = binary.BigEndian.Uint32(buf[offset:offset+4])
case IE_PLAN_VALUE_ADD_THIS_TIME:
rsp.UpdateBundleUsageReq.PlanValueAddThisTime = binary.BigEndian.Uint64(buf[offset:offset+8])
default:
}
offset += int(vallen)
}
l4g.RestLog.Debugf("decodeUpdateBundleUsageReq: %#v", rsp.UpdateSubsRsp)
return 0
}
func Decode_udp_msg(buf []byte, msglen int, rsp *RestRsp) int {
var offset int = 0
if msglen <= 9 {
return -1
}
rsp.MsgType = buf[offset]
offset++
switch (rsp.MsgType) {
case REST_SEND_AUTHCODE_RSP:
return decode_authcode_rsp(buf[1:], msglen-1, rsp)
case REST_QUERY_USERDATA_RSP:
return decode_query_userData_rsp(buf[1:], msglen-1, rsp)
case REST_BUNDLE_SUBS_RSP:
return decode_bundleSubs_rsp(buf[1:], msglen-1, rsp)
case REST_RECHARGE_RSP:
return decode_recharge_rsp(buf[1:], msglen-1, rsp)
case REST_TRANSFER_RSP:
return decode_transfer_rsp(buf[1:], msglen-1, rsp)
case REST_QUERY_BALANCE_RSP:
return decode_query_balance_rsp(buf[1:], msglen-1, rsp)
case REST_CRM_CREATE_ACCT_RES:
return decode_create_acct_rsp(buf[1:], msglen-1, rsp)
case REST_CRM_UPDATE_SUBS_REQ:
return decode_update_subs_req(buf[1:], msglen-1, rsp)
case REST_CRM_UPDATE_SUBS_RES:
return decode_update_subs_rsp(buf[1:], msglen-1, rsp)
case REST_CRM_DELETE_SUBS_RES:
return decode_delete_subs_rsp(buf[1:], msglen-1, rsp)
case REST_CRM_UPDATE_PLAN_INFO_REQ:
return decodeUpdateBundleUsageReq(buf[1:], msglen-1, rsp)
default:
return -1
}
}
+44
View File
@@ -0,0 +1,44 @@
package Nrestful
import (
)
const ERRCODE_SUCCESS uint32 = 2001
const ERRCODE_COM_UNSUPPORT uint32 = 3001
const ERRCODE_UNKNOWN_PEER uint32 = 3011
const ERRCODE_INVALID_USER_STATUS uint32 = 4001
const ERRCODE_DEST_USER_NOT_ALLOWED uint32 = 4008
const ERRCODE_CREDIT_LIMIT uint32 = 4012
const ERRCODE_INVALID_PARAM_VALUE uint32 = 5004
const ERRCODE_MISSING_PARAM uint32 = 5005
const ERRCODE_INVALID_RECHARGE_PASSWORD uint32 = 5006
const ERRCODE_UNABLE_TO_COMPLY uint32 = 5012
const ERRCODE_USER_UNKNOWN uint32 = 5030
const MAX_ERRCODE uint32 = 5000
var restCode2StrMap = make(map[uint32]string)
func init() {
restCode2StrMap[ERRCODE_SUCCESS] = "success"
restCode2StrMap[ERRCODE_COM_UNSUPPORT] = "command unsupported"
restCode2StrMap[ERRCODE_UNKNOWN_PEER] = "unknown peer"
restCode2StrMap[ERRCODE_INVALID_USER_STATUS] = "invalid user status"
restCode2StrMap[ERRCODE_DEST_USER_NOT_ALLOWED] = "dest user not allowed"
restCode2StrMap[ERRCODE_CREDIT_LIMIT] = "credit limit"
restCode2StrMap[ERRCODE_INVALID_PARAM_VALUE] = "invalid parameter value"
restCode2StrMap[ERRCODE_MISSING_PARAM] = "missing parameter"
restCode2StrMap[ERRCODE_INVALID_RECHARGE_PASSWORD] = "invalid recharge password"
restCode2StrMap[ERRCODE_UNABLE_TO_COMPLY] = "unable to comply"
restCode2StrMap[ERRCODE_USER_UNKNOWN] = "user unknown"
}
func Rest_proxy_errcodemsg(errcode uint32) string {
errStr, ok := restCode2StrMap[errcode]
if !ok {
return "unkown"
} else {
return errStr
}
}
+104
View File
@@ -0,0 +1,104 @@
package Nrestful
import (
mysql "proxy/Nmysql"
rds "proxy/Nredis"
"proxy/config"
)
func handleOcsDeleteSubsRsp(req *RestRsp) {
}
func handleOcsUpdateSubsReq(req *RestRsp) {
expNtfFlag := false
var expiredDate int64= 0
if req.UpdateSubsReq.OptFlag & 0x04 == 0x04 {
expNtfFlag = true
expiredDate = int64(req.UpdateSubsReq.ExpDateU32)
}
accountId := req.UpdateSubsReq.AccountIdU32
if expNtfFlag {
planId := req.UpdateSubsReq.PackageIdU32
_ = mysql.InsertExpiredNotifySms(accountId, planId, expiredDate)
} else {
status := req.UpdateSubsReq.StatusU8
_ = mysql.UpdateUserStatus2Mdb(accountId, status)
}
}
func handleUpdatePlanUsage(req *RestRsp) {
opFlag := false
thisTimeAdded := req.UpdateBundleUsageReq.PlanValueAddThisTime
if thisTimeAdded & 0x8000000000000000 == 0x8000000000000000 {
opFlag = true
}
thisTimeAdded &= 0x7FFFFFFFFFFFFFFF
totalValue := req.UpdateBundleUsageReq.PlanValue
if totalValue <= 0 {
return
}
usedValue := req.UpdateBundleUsageReq.PlanUsedValue
serviceType := req.UpdateBundleUsageReq.ServiceType
rateUsed, oldRateUsed := 0, 0
sendNotifyFlag := false
if bSendNotifySms(serviceType) {//(service_type == 2)//data only; 1: voice; 2: data; 3: sms;
rateUsed = int(usedValue*100 / totalValue)
if rateUsed > 75 {
oldRateUsed = int((usedValue-thisTimeAdded)*100 / totalValue)
if oldRateUsed <= 75 {
sendNotifyFlag = true
rateUsed = 75
}
}
}
updateExpiryDate := false
if usedValue >= totalValue {
usedValue = totalValue
rateUsed = 100
updateExpiryDate = true
if false {
sendNotifyFlag = true
}
}
bundleId := req.UpdateBundleUsageReq.BundleId
if serviceType == 2 {
mysql.UpdateDataPlanInfo(bundleId, thisTimeAdded, opFlag)
} else {
mysql.UpdateVoiceAndSmsPlanInfo(serviceType, bundleId, usedValue, totalValue, updateExpiryDate)
}
if sendNotifyFlag {
planId := req.UpdateBundleUsageReq.PlanId
if !rds.CheckIfBundleLimitSent(planId, rateUsed) {
accountId := req.UpdateBundleUsageReq.AccountId
mysql.AddNotificationSms(accountId, planId, serviceType, updateExpiryDate, rateUsed)
rds.SetPlanExpire(planId, rateUsed)
}
}
}
func bSendNotifySms(serviceType byte) bool {
ntfCfg := &config.Config.BundleUsageNotify
switch serviceType {
case 1:
if ntfCfg.Voice75Percent {
return true
}
case 2:
if ntfCfg.Data75Percent {
return true
}
case 3:
if ntfCfg.Sms75Percent {
return true
}
default:
}
return true
}
+92
View File
@@ -0,0 +1,92 @@
package Nrestful
import (
l4g "proxy/logger" //"github.com/sirupsen/logrus"
"sync"
)
var mutex sync.Mutex
type Port struct {
CurIndex int
UseFlag int
Dst_id uint16
Rsp chan RestRsp
}
const MAX_PORT_NUM uint16 = 8192
type PortMngt struct {
Seq uint16
CurIndex uint16
Ports [MAX_PORT_NUM]Port
}
var portMngt PortMngt
func AssignPort(req *RestReq) *Port {
var id uint16 = 0
var i uint16 = 0
var port *Port = nil
mutex.Lock()
for i=0; i<MAX_PORT_NUM; i++ {
id = (i+portMngt.CurIndex) % MAX_PORT_NUM
if portMngt.Ports[id].UseFlag == 0 {
portMngt.CurIndex = (id + 1) % MAX_PORT_NUM
portMngt.Ports[id].UseFlag = 1
req.Src_id = id
req.Dst_id = portMngt.Seq
portMngt.Ports[id].Dst_id = req.Dst_id
portMngt.Seq ++
port = &portMngt.Ports[id]
break
}
}
mutex.Unlock()
return port
}
func GetPortInfo(src_id uint16, dst_id uint16) *Port {
if src_id < 0 || src_id >= MAX_PORT_NUM {
return nil
}
port := &portMngt.Ports[src_id]
if port.UseFlag == 0 || port.Dst_id != dst_id {
l4g.RestLog.Errorf("Get port error, src[%d], dst[%d], used_flag[%d]", src_id, dst_id, port.UseFlag)
return nil
}
return port
}
/*func ClosePortChan(id int, ts int64) {
if id < 0 || id >= MAX_PORT_NUM {
return
}
mutex.Lock()
if portMngt.Ports[id].UseFlag && (ts == portMngt.Ports[id].Ts) {
close(portMngt.Ports[id].Rsp)
}
mutex.Unlock()
return
}*/
func ReleasePort(id uint16) int {
if id < 0 || id >= MAX_PORT_NUM {
return -1
}
mutex.Lock()
portMngt.Ports[id].UseFlag = 0
mutex.Unlock()
return 0
}
+353
View File
@@ -0,0 +1,353 @@
package Nrestful
import (
)
type AuthCodeReq struct {
CODE_TYPE string `json:"CODE_TYPE"`// ignore?
CUST_CODE uint32 `json:"CUST_CODE"`// ignore?
Content string `json:"content"`
TelNumber string `json:"telNumber"`
}
type AuthCodeRsp struct {
Code string `json:"code"`// 2001: succ; else: fail, from uint32
Message string `json:"message"`
}
type QueryUserDataReq struct {
TelNumber string `json:"telNumber"`
}
type QueryUserDataRsp struct {
Code string `json:"code"`// 2001: succ; else: fail, from uint32
Message string `json:"message"`
Status string `json:"status"`// from uint8
Remark string `json:"remark"`
TelNumber string `json:"telNumber"`
UserGroupName string `json:"userGroupName"`
Balance string `json:"balance"`// from uint32
ExpireDate string `json:"expireDate"`// "YYYY-MM-DD HH:MM:SS"
VoiceMinute string `json:"VoiceMinute,omitempty"`// from uint32
RemainMoVoiceMinute string `json:"remainVoiceMinute"`// from uint32
RemainMtVoiceMinute string `json:"remainMtVoiceMinute,omitempty"`// from uint32
SmsVolume string `json:"smsVolume,omitempty"`// from uint32
RemainSmsVolume string `json:"remainSmsVolume"`// from uint32
DataVolume string `json:"dataVolume,omitempty"`// from uint32
RemainDataVolume string `json:"remainDataVolume"`// from uint32
}
type BundleSubsReq struct {
TelNumber string `json:"telNumber"`
PayType string `json:"payType"`// from uint8
ChargedAmount string `json:"chargedAmount"`// from uint32
MoVoiceMinute string `json:"moVoiceMinute"`// from uint32
MtVoiceMinute string `json:"mtVoiceMinute"`// from uint32
DataVolume string `json:"dataVolume"`// from uint32, in MB
SmsVolume string `json:"smsVolume"`// from uint32
ValidPeriod string `json:"validPeriod"`// from uint32
}
type BundleSubsRsp struct {
Code string `json:"code"`// 2001: succ; else: fail// from uint32
Message string `json:"message"`
}
type BundleUsageReq struct {
TelNumber string `json:"telNumber"`
}
type BundleUsageRsp struct {
Code uint32 `json:"code"`// 2001: succ; else: fail
Message string `json:"message"`
MoVoiceInSecond uint32 `json:"moVoiceInSecond"`
MtVoiceInSecond uint32 `json:"mtVoiceInSecond"`
DataVolumeInKB uint32 `json:"dataVolumeInKB"`
SmsVolume uint32 `json:"smsVolume"`
ExpiredTimestamp string `json:"expiredTimestamp"`// "YYYY-MM-DD HH:MM:SS"
}
type RechargeReq struct {
AccountId string `json:"accountId"`
Amount string `json:"amount"`// to uint32
OpType string `json:"opType"`// to uint8
StaffId string `json:"staffId"`
TelNumber string `json:"telNumber"`
ValidyDays string `json:"validyDays"`// to uint16
}
type RechargeRsp struct {
Code string `json:"code"`// 2001: succ; else: fail, from uint32
Message string `json:"message"`
Status string `json:"status"` // from uint8
Balance string `json:"balance"`// from uint32
ExpiredTimestamp string `json:"expiredTimestamp"`// "YYYY-MM-DD HH:MM:SS"
}
type TransferReq struct {
TransferOut string `json:"transferOut"`
TransferIn string `json:"transferIn"`
Amount string `json:"amount"`// from uint32
}
type TransferRsp struct {
Code string `json:"code"`// 2001: succ; else: fail, from uint32
Message string `json:"message"`
Balance string `json:"balance"`// from uint32
}
type RechargeCardReq struct {
TelNumber string `json:"telNumber"`
CardPwd string `json:"cardPwd"`
}
type RechargeCardRsp struct {
Code uint32 `json:"code"`// 2001: succ; else: fail
Message string `json:"message"`
RechargeAmount uint32 `json:"rechargeAmount"`
Balance uint32 `json:"balance"`
ExpiredTimestamp string `json:"expiredTimestamp"`// "%02d-%02d-%02d %02d:%02d:%02d"
}
type CheckBalanceReq struct {
TelNumber string `json:"telNumber"`
Amount uint32 `json:"amount"`
}
type CheckBalanceRsp struct {
Code uint32 `json:"code"`// 2001: succ; else: fail
Message string `json:"message"`
Available uint32 `json:"available"`
}
type QueryBalanceReq struct {
TelNumber string `json:"telNumber"`
}
type QueryBalanceRsp struct {
Code string `json:"code"`// 2001: succ; else: fail, from uint32
Message string `json:"message"`
Status string `json:"status"`// from uint8
Balance string `json:"balance"`// from uint32
ExpireDate string `json:"expireDate"`// "YYYY-MM-DD HH:MM:SS"
}
type QueryRechargeCardReq struct {
TelNumber string `json:"telNumber"`
}
type QueryRechargeCardRsp struct {
Code uint32 `json:"code"`// 2001: succ; else: fail
Message string `json:"message"`
}
type UpdateRechargeCardReq struct {
TelNumber string `json:"telNumber"`
}
type UpdateRechargeCardRsp struct {
Code uint32 `json:"code"`// 2001: succ; else: fail
Message string `json:"message"`
}
type CreateAccountReq struct {
ServiceNbr string `json:"serviceNbr"`
CustId string `json:"custId"`// from uint32
AccountId string `json:"accountId"`// from uint32
ProductInstId string `json:"productInstId"`// from uint32
PackageId string `json:"packageId"`// from uint32
Balance string `json:"balance"`// from uint32
//CustIdUint32 uint32 `json:"custIdUint32,omitempty"`// from uint32
//AcctIdUint32 uint32 `json:"acctIdUint32,omitempty"`// from uint32
BalanceExpDate string `json:"balanceExpDate"`
Birthday string `json:"birthday"`
RentCharge string `json:"rentCharge,omitempty"`// from uint32
CugId string `json:"cugId,omitempty"`// from uint32
UserClass string `json:"userClass,omitempty"`// from uint32
}
type CreateAccountRsp struct {
Code string `json:"code"`// 2001: succ; else: fail, from uint32
Message string `json:"message"`
}
type UpdateSubsReq struct {
TelNumber string `json:"telNumber"`
AccountId string `json:"accountId,omitempty"`// from uint32
Status string `json:"status,omitempty"`// from uint8
Balance string `json:"balance,omitempty"`// from uint32
BalanceExpDate string `json:"balanceExpDate,omitempty"`
AccountIdU32 uint32 `json:"accountIdU32,omitempty"`
StatusU8 byte `json:"statusU8,omitempty"`
BalanceU32 uint32 `json:"balanceU32,omitempty"`
ExpDateU32 uint32 `json:"balanceExpDateU32,omitempty"`
OptFlag uint32 `json:"optFlagU32,omitempty"`
PackageIdU32 uint32 `json:"packageIdU32,omitempty"`// from uint32
RentChargeU32 uint32 `json:"rentChargeU32,omitempty"`// from uint32
VasCugStatusU8 byte `json:"vasCugStatusU8,omitempty"`// from uint8
PackageId string `json:"packageId,omitempty"`// from uint32
RentCharge string `json:"rentCharge,omitempty"`// from uint32
VasCugStatus string `json:"vasCugStatus,omitempty"`// from uint8
//Optional_flag uint32 `json:"optional_flag,omitempty"`
}
type UpdateSubsRsp struct {
Code string `json:"code"`// 2001: succ; else: fail, from uint32
Message string `json:"message"`
}
type DeleteSubsReq struct {
TelNumber string `json:"telNumber"`
AcctType string `json:"acctType,omitempty"`// from uint8
AcctId string `json:"acctID,omitempty"`// from uint32
Cause string `json:"reason,omitempty"`// from uint8
}
type DeleteSubsRsp struct {
Result byte
ErrorCode uint32
Code string `json:"code"`// 2001: succ; else: fail, from uint32
Message string `json:"message"`
}
type UpdateBundleUsageReq struct {
Msisdn string // tag 2
ServiceType byte
AccountId uint32
PlanId uint32
BundleId uint32
PlanValue uint64
PlanUsedValue uint64
SessUpdateTime uint32
PlanValueAddThisTime uint64
}
//type RestMsgType int
const (
REST_SEND_AUTHCODE_REQ byte = 5
REST_SEND_AUTHCODE_RSP byte = 6
REST_QUERY_USERDATA_REQ byte = 7
REST_QUERY_USERDATA_RSP byte = 8
REST_BUNDLE_SUBS_REQ byte = 9
REST_BUNDLE_SUBS_RSP byte = 10
REST_BUNDLE_USAGE_REQ byte = 11
REST_BUNDLE_USAGE_RSP byte = 12
REST_RECHARGE_REQ byte = 13
REST_RECHARGE_RSP byte = 14
REST_TRANSFER_REQ byte = 15
REST_TRANSFER_RSP byte = 16
REST_RECHARGE_CARD_REQ byte = 17
REST_RECHARGE_CARD_RSP byte = 18
REST_CHECK_BALANCE_REQ byte = 19
REST_CHECK_BALANCE_RSP byte = 20
REST_QUERY_BALANCE_REQ byte = 21
REST_QUERY_BALANCE_RSP byte = 22
REST_QUERY_RECHARGE_CARD_REQ byte = 23
REST_QUERY_RECHARGE_CARD_RSP byte = 24
REST_UPDATE_RECHARGE_CARD_REQ byte = 25
REST_UPDATE_RECHARGE_CARD_RSP byte = 26
REST_CRM_PAYMENT_REQ byte = 27
REST_CRM_PAYMENT_RES byte = 28
REST_CRM_SMS_DELIVER_REQ byte = 29
REST_CRM_SMS_DELIVER_RES byte = 30
REST_CRM_CREATE_ACCT_REQ byte = 31
REST_CRM_CREATE_ACCT_RES byte = 32
REST_CRM_QUERY_TARIFF_REQ byte = 33
REST_CRM_QUERY_TARIFF_RES byte = 34
REST_CRM_UPDATE_SUBS_REQ byte = 35
REST_CRM_UPDATE_SUBS_RES byte = 36
REST_CRM_DELETE_SUBS_REQ byte = 37
REST_CRM_DELETE_SUBS_RES byte = 38
REST_CRM_UPDATE_SESS_INFO_REQ byte = 39
REST_CRM_UPDATE_SESS_INFO_RES byte = 40
REST_CRM_UPDATE_PLAN_INFO_REQ byte = 41
REST_CRM_UPDATE_PLAN_INFO_RES byte = 42
REST_CRM_RENT_CHARGE byte = 43
)
type RestReq struct {
MsgType byte
Src_id uint16
Dst_id uint16
AuthCodeReq AuthCodeReq
QueryUserDataReq QueryUserDataReq
BundleSubsReq BundleSubsReq
BundleUsageReq BundleUsageReq
RechargeReq RechargeReq
TransferReq TransferReq
RechargeCardReq RechargeCardReq
CheckBalanceReq CheckBalanceReq
QueryBalanceReq QueryBalanceReq
QueryRechargeCardReq QueryRechargeCardReq
UpdateRechargeCardReq UpdateRechargeCardReq
CreateAccountReq CreateAccountReq
UpdateSubsReq UpdateSubsReq
DeleteSubsReq DeleteSubsReq
}
type RestRsp struct {
MsgType byte
Src_id uint16
Dst_id uint16
AuthCodeRsp AuthCodeRsp
QueryUserDataRsp QueryUserDataRsp
BundleSubsRsp BundleSubsRsp
BundleUsageRsp BundleUsageRsp
RechargeRsp RechargeRsp
TransferRsp TransferRsp
RechargeCardRsp RechargeCardRsp
CheckBalanceRsp CheckBalanceRsp
QueryBalanceRsp QueryBalanceRsp
QueryRechargeCardRsp QueryRechargeCardRsp
UpdateRechargeCardRsp UpdateRechargeCardRsp
CreateAccountRsp CreateAccountRsp
UpdateSubsRsp UpdateSubsRsp
DeleteSubsRsp DeleteSubsRsp
UpdateBundleUsageReq UpdateBundleUsageReq
UpdateSubsReq UpdateSubsReq
}
+148
View File
@@ -0,0 +1,148 @@
package Nrestful
import (
"net/http"
//"fmt"
//"log"
"encoding/json"
"strconv"
//"time"
l4g "proxy/logger"//"github.com/sirupsen/logrus"
)
func sendAuthCodeRsp(w http.ResponseWriter, statusCode int, rsp *RestRsp) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if statusCode != http.StatusOK {
rsp.AuthCodeRsp.Code = strconv.Itoa(5001)
} else {
//rsp.AuthCodeRsp.Code = 2001
}
w.WriteHeader(statusCode)
l4g.RestLog.Warnf("Send AuthCodeRsp: %v", rsp.AuthCodeRsp)
// w.Write at last
json.NewEncoder(w).Encode(rsp.AuthCodeRsp)
//
}
func sendQueryUserDataRsp(w http.ResponseWriter, statusCode int, rsp *RestRsp) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if statusCode != http.StatusOK {
rsp.QueryUserDataRsp.Code = strconv.Itoa(5001)
} else {
//rsp.QueryUserDataRsp.Code = 2001
}
w.WriteHeader(statusCode)
l4g.RestLog.Warnf("Send QueryUserDataRsp: %v", rsp.QueryUserDataRsp)
// w.Write at last
json.NewEncoder(w).Encode(rsp.QueryUserDataRsp)
//
}
func sendBundleSubsRsp(w http.ResponseWriter, statusCode int, rsp *RestRsp) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if statusCode != http.StatusOK {
rsp.BundleSubsRsp.Code = strconv.Itoa(5001)
} else {
//rsp.BundleSubsRsp.Code = 2001
}
w.WriteHeader(statusCode)
l4g.RestLog.Warnf("Send QueryUserDataRsp: %v", rsp.BundleSubsRsp)
// w.Write at last
json.NewEncoder(w).Encode(rsp.BundleSubsRsp)
//
}
func sendRechargeRsp(w http.ResponseWriter, statusCode int, rsp *RestRsp) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if statusCode != http.StatusOK {
rsp.RechargeRsp.Code = strconv.Itoa(5001)
} else {
//rsp.RechargeRsp.Code = 2001
}
w.WriteHeader(statusCode)
l4g.RestLog.Warnf("Send RechargeRsp: %v", rsp.RechargeRsp)
// w.Write at last
json.NewEncoder(w).Encode(rsp.RechargeRsp)
//
}
func sendTransferRsp(w http.ResponseWriter, statusCode int, rsp *RestRsp) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if statusCode != http.StatusOK {
rsp.TransferRsp.Code = strconv.Itoa(5001)
} else {
//rsp.TransferRsp.Code = 2001
}
w.WriteHeader(statusCode)
l4g.RestLog.Warnf("Send TransferRsp: %v", rsp.TransferRsp)
// w.Write at last
json.NewEncoder(w).Encode(rsp.TransferRsp)
//
}
func sendQueryBalanceRsp(w http.ResponseWriter, statusCode int, rsp *RestRsp) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if statusCode != http.StatusOK {
rsp.QueryBalanceRsp.Code = strconv.Itoa(5001)
} else {
//rsp.QueryBalanceRsp.Code = 2001
}
w.WriteHeader(statusCode)
l4g.RestLog.Warnf("Send QueryBalanceRsp: %v", rsp.QueryBalanceRsp)
// w.Write at last
json.NewEncoder(w).Encode(rsp.QueryBalanceRsp)
//
}
func sendCreateAccountRsp(w http.ResponseWriter, statusCode int, rsp *RestRsp) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if statusCode != http.StatusOK {
rsp.CreateAccountRsp.Code = strconv.Itoa(5001)
} else {
//rsp.CreateAccountRsp.Code = 2001
}
w.WriteHeader(statusCode)
l4g.RestLog.Warnf("Send CreateAccountRsp: %v", rsp.CreateAccountRsp)
// w.Write at last
json.NewEncoder(w).Encode(rsp.CreateAccountRsp)
//
}
func sendUpdateSubsRsp(w http.ResponseWriter, statusCode int, rsp *RestRsp) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if statusCode != http.StatusOK {
rsp.UpdateSubsRsp.Code = strconv.Itoa(5001)
} else {
//rsp.UpdateSubsRsp.Code = 2001
}
w.WriteHeader(statusCode)
l4g.RestLog.Warnf("Send UpdateSubsRsp: %v", rsp.UpdateSubsRsp)
// w.Write at last
json.NewEncoder(w).Encode(rsp.UpdateSubsRsp)
//
}
func sendDeleteSubsRsp(w http.ResponseWriter, statusCode int, rsp *RestRsp) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if statusCode != http.StatusOK {
rsp.DeleteSubsRsp.Code = strconv.Itoa(5001)
} else {
//rsp.DeleteSubsRsp.Code = 2001
}
w.WriteHeader(statusCode)
l4g.RestLog.Warnf("Send DeleteSubsRsp: %v", rsp.DeleteSubsRsp)
// w.Write at last
json.NewEncoder(w).Encode(rsp.DeleteSubsRsp)
//
}
+423
View File
@@ -0,0 +1,423 @@
package Nrestful
import (
"net/http"
"fmt"
"log"
"encoding/json"
mysql "proxy/Nmysql"
//"strconv"
"time"
l4g "proxy/logger"//"github.com/sirupsen/logrus"
)
func StartHttpServer(addr string) {
http.HandleFunc("/", handler)
http.HandleFunc("/authcode", authcodeHandler)
http.HandleFunc("/query_userdata", query_userdataHandler)
http.HandleFunc("/bundle_subs", bundle_subsHandler)
//http.HandleFunc("/bundle_usage", bundle_usageHandler)
http.HandleFunc("/recharge", rechargeHandler)
http.HandleFunc("/transfer", transferHandler)
//http.HandleFunc("/recharge_card", recharge_cardHandler)
//http.HandleFunc("/check_balance", check_balanceHandler)
http.HandleFunc("/query_balane", query_balanceHandler)// query_balane in Pcap from CRM
http.HandleFunc("/openPackage", openPackageHandler)
http.HandleFunc("/updateSubs", updateSubsHandler)
http.HandleFunc("/deleteSubs", deleteSubsHandler)
log.Fatal(http.ListenAndServe(addr, nil))
}
// handler echoes the Path component of the requested URL.
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
}
func authcodeHandler(w http.ResponseWriter, r *http.Request) {
rsp := RestRsp{MsgType: REST_SEND_AUTHCODE_RSP}
var pRsp *RestRsp = &rsp
if r.Body == nil {
rsp.AuthCodeRsp.Message = "request body missing"
sendAuthCodeRsp(w, http.StatusBadRequest, pRsp)
return
}
var req RestReq
req.MsgType = REST_SEND_AUTHCODE_REQ
err := json.NewDecoder(r.Body).Decode(&req.AuthCodeReq)
if err != nil {
rsp.AuthCodeRsp.Message = "err decode authCodeReq"
sendAuthCodeRsp(w, http.StatusBadRequest, pRsp)
return
}
l4g.RestLog.Debugf("Got authcode request: %v", req.AuthCodeReq)
// handle ==========================================
port := AssignPort(&req)
if port == nil {
rsp.AuthCodeRsp.Message = "err port full"
sendAuthCodeRsp(w, http.StatusInternalServerError, pRsp)
return
}
l4g.RestLog.Debugf("Assign port for authcode request, src[%d], dst[%d]", req.Src_id, req.Dst_id)
ocsRsp := getOcsRsp(&req, port)
if ocsRsp == nil {
rsp.AuthCodeRsp.Message = "ocs rsp timeout"
sendAuthCodeRsp(w, http.StatusInternalServerError, pRsp)
} else {
sendAuthCodeRsp(w, http.StatusOK, ocsRsp)
}
return
}
func query_userdataHandler(w http.ResponseWriter, r *http.Request) {
rsp := RestRsp{MsgType: REST_QUERY_USERDATA_RSP}
var pRsp *RestRsp = &rsp
if r.Body == nil {
rsp.QueryUserDataRsp.Message = "request body missing"
sendQueryUserDataRsp(w, http.StatusBadRequest, pRsp)
return
}
var req RestReq
req.MsgType = REST_QUERY_USERDATA_REQ
err := json.NewDecoder(r.Body).Decode(&req.QueryUserDataReq)
if err != nil {
rsp.QueryUserDataRsp.Message = "err decode QueryUserDataReq"
sendQueryUserDataRsp(w, http.StatusBadRequest, pRsp)
return
}
l4g.RestLog.Debugf("Got query_userdata request: %v", req.QueryUserDataReq)
// handle ==========================================
port := AssignPort(&req)
if port == nil {
rsp.QueryUserDataRsp.Message = "err port full"
sendQueryUserDataRsp(w, http.StatusInternalServerError, pRsp)
return
}
l4g.RestLog.Debugf("Assign port for query_userdata request, src[%d], dst[%d]", req.Src_id, req.Dst_id)
ocsRsp := getOcsRsp(&req, port)
if ocsRsp == nil {
rsp.QueryUserDataRsp.Message = "ocs rsp timeout"
sendQueryUserDataRsp(w, http.StatusInternalServerError, pRsp)
} else {
sendQueryUserDataRsp(w, http.StatusOK, ocsRsp)
}
return
}
func bundle_subsHandler(w http.ResponseWriter, r *http.Request) {
rsp := RestRsp{MsgType: REST_BUNDLE_SUBS_RSP}
var pRsp *RestRsp = &rsp
if r.Body == nil {
rsp.BundleSubsRsp.Message = "request body missing"
sendBundleSubsRsp(w, http.StatusBadRequest, pRsp)
return
}
var req RestReq
req.MsgType = REST_BUNDLE_SUBS_REQ
err := json.NewDecoder(r.Body).Decode(&req.BundleSubsReq)
if err != nil {
rsp.BundleSubsRsp.Message = "err decode BundleSubsReq"
sendBundleSubsRsp(w, http.StatusBadRequest, pRsp)
return
}
l4g.RestLog.Debugf("Got BundleSubs request: %v", req.BundleSubsReq)
// handle ==========================================
port := AssignPort(&req)
if port == nil {
rsp.BundleSubsRsp.Message = "err port full"
sendBundleSubsRsp(w, http.StatusInternalServerError, pRsp)
return
}
l4g.RestLog.Debugf("Assign port for BundleSubs request, src[%d], dst[%d]", req.Src_id, req.Dst_id)
ocsRsp := getOcsRsp(&req, port)
if ocsRsp == nil {
rsp.BundleSubsRsp.Message = "ocs rsp timeout"
sendBundleSubsRsp(w, http.StatusInternalServerError, pRsp)
} else {
sendBundleSubsRsp(w, http.StatusOK, ocsRsp)
}
return
}
func rechargeHandler(w http.ResponseWriter, r *http.Request) {
rsp := RestRsp{MsgType: REST_RECHARGE_RSP}
var pRsp *RestRsp = &rsp
if r.Body == nil {
rsp.RechargeRsp.Message = "request body missing"
sendRechargeRsp(w, http.StatusBadRequest, pRsp)
return
}
var req RestReq
req.MsgType = REST_RECHARGE_REQ
err := json.NewDecoder(r.Body).Decode(&req.RechargeReq)
if err != nil {
rsp.RechargeRsp.Message = "err decode RechargeReq"
sendRechargeRsp(w, http.StatusBadRequest, pRsp)
return
}
l4g.RestLog.Debugf("Got query_userdata request: %v", req.RechargeReq)
// handle ==========================================
port := AssignPort(&req)
if port == nil {
rsp.RechargeRsp.Message = "err port full"
sendRechargeRsp(w, http.StatusInternalServerError, pRsp)
return
}
l4g.RestLog.Debugf("Assign port for query_userdata request, src[%d], dst[%d]", req.Src_id, req.Dst_id)
ocsRsp := getOcsRsp(&req, port)
if ocsRsp == nil {
rsp.RechargeRsp.Message = "ocs rsp timeout"
sendRechargeRsp(w, http.StatusInternalServerError, pRsp)
} else {
sendRechargeRsp(w, http.StatusOK, ocsRsp)
}
return
}
func transferHandler(w http.ResponseWriter, r *http.Request) {
rsp := RestRsp{MsgType: REST_TRANSFER_RSP}
var pRsp *RestRsp = &rsp
if r.Body == nil {
rsp.TransferRsp.Message = "request body missing"
sendTransferRsp(w, http.StatusBadRequest, pRsp)
return
}
var req RestReq
req.MsgType = REST_TRANSFER_REQ
err := json.NewDecoder(r.Body).Decode(&req.TransferReq)
if err != nil {
rsp.TransferRsp.Message = "err decode TransferReq"
sendTransferRsp(w, http.StatusBadRequest, pRsp)
return
}
l4g.RestLog.Debugf("Got Transfer request: %v", req.TransferReq)
// handle ==========================================
port := AssignPort(&req)
if port == nil {
rsp.TransferRsp.Message = "err port full"
sendTransferRsp(w, http.StatusInternalServerError, pRsp)
return
}
l4g.RestLog.Debugf("Assign port for Transfer request, src[%d], dst[%d]", req.Src_id, req.Dst_id)
ocsRsp := getOcsRsp(&req, port)
if ocsRsp == nil {
rsp.TransferRsp.Message = "ocs rsp timeout"
sendTransferRsp(w, http.StatusInternalServerError, pRsp)
} else {
sendTransferRsp(w, http.StatusOK, ocsRsp)
}
return
}
func query_balanceHandler(w http.ResponseWriter, r *http.Request) {
rsp := RestRsp{MsgType: REST_QUERY_BALANCE_RSP}
var pRsp *RestRsp = &rsp
if r.Body == nil {
rsp.QueryBalanceRsp.Message = "request body missing"
sendQueryBalanceRsp(w, http.StatusBadRequest, pRsp)
return
}
var req RestReq
req.MsgType = REST_QUERY_BALANCE_REQ
err := json.NewDecoder(r.Body).Decode(&req.QueryBalanceReq)
if err != nil {
rsp.QueryBalanceRsp.Message = "err decode QueryBalanceReq"
sendQueryBalanceRsp(w, http.StatusBadRequest, pRsp)
return
}
l4g.RestLog.Debugf("Got QueryBalance request: %v", req.QueryBalanceReq)
// handle ==========================================
port := AssignPort(&req)
if port == nil {
rsp.QueryBalanceRsp.Message = "err port full"
sendQueryBalanceRsp(w, http.StatusInternalServerError, pRsp)
return
}
l4g.RestLog.Debugf("Assign port for QueryBalance request, src[%d], dst[%d]", req.Src_id, req.Dst_id)
ocsRsp := getOcsRsp(&req, port)
if ocsRsp == nil {
rsp.QueryBalanceRsp.Message = "ocs rsp timeout"
sendQueryBalanceRsp(w, http.StatusInternalServerError, pRsp)
} else {
sendQueryBalanceRsp(w, http.StatusOK, ocsRsp)
}
return
}
func openPackageHandler(w http.ResponseWriter, r *http.Request) {
rsp := RestRsp{MsgType: REST_CRM_CREATE_ACCT_RES}
var pRsp *RestRsp = &rsp
if r.Body == nil {
rsp.CreateAccountRsp.Message = "request body missing"
sendCreateAccountRsp(w, http.StatusBadRequest, pRsp)
return
}
var req RestReq
req.MsgType = REST_CRM_CREATE_ACCT_REQ
err := json.NewDecoder(r.Body).Decode(&req.CreateAccountReq)
if err != nil {
rsp.CreateAccountRsp.Message = "err decode CreateAccountReq"
sendCreateAccountRsp(w, http.StatusBadRequest, pRsp)
return
}
l4g.RestLog.Debugf("Got CreateAccount request: %v", req.CreateAccountReq)
// handle ==========================================
port := AssignPort(&req)
if port == nil {
rsp.CreateAccountRsp.Message = "err port full"
sendCreateAccountRsp(w, http.StatusInternalServerError, pRsp)
return
}
l4g.RestLog.Debugf("Assign port for CreateAccount request, src[%d], dst[%d]", req.Src_id, req.Dst_id)
ocsRsp := getOcsRsp(&req, port)
if ocsRsp == nil {
rsp.CreateAccountRsp.Message = "ocs rsp timeout"
sendCreateAccountRsp(w, http.StatusInternalServerError, pRsp)
} else {
sendCreateAccountRsp(w, http.StatusOK, ocsRsp)
}
return
}
func updateSubsHandler(w http.ResponseWriter, r *http.Request) {
rsp := RestRsp{MsgType: REST_CRM_UPDATE_SUBS_RES}
var pRsp *RestRsp = &rsp
if r.Body == nil {
rsp.UpdateSubsRsp.Message = "request body missing"
sendUpdateSubsRsp(w, http.StatusBadRequest, pRsp)
return
}
var req RestReq
req.MsgType = REST_CRM_UPDATE_SUBS_REQ
err := json.NewDecoder(r.Body).Decode(&req.UpdateSubsReq)
if err != nil {
rsp.UpdateSubsRsp.Message = "err decode UpdateSubsReq"
sendUpdateSubsRsp(w, http.StatusBadRequest, pRsp)
return
}
l4g.RestLog.Debugf("Got UpdateSubs request: %v", req.UpdateSubsReq)
// handle ==========================================
port := AssignPort(&req)
if port == nil {
rsp.UpdateSubsRsp.Message = "err port full"
sendUpdateSubsRsp(w, http.StatusInternalServerError, pRsp)
return
}
l4g.RestLog.Debugf("Assign port for UpdateSubs request, src[%d], dst[%d]", req.Src_id, req.Dst_id)
ocsRsp := getOcsRsp(&req, port)
if ocsRsp == nil {
rsp.UpdateSubsRsp.Message = "ocs rsp timeout"
sendUpdateSubsRsp(w, http.StatusInternalServerError, pRsp)
} else {
sendUpdateSubsRsp(w, http.StatusOK, ocsRsp)
}
return
}
func deleteSubsHandler(w http.ResponseWriter, r *http.Request) {
rsp := RestRsp{MsgType: REST_CRM_DELETE_SUBS_RES}
var pRsp *RestRsp = &rsp
if r.Body == nil {
rsp.DeleteSubsRsp.Message = "request body missing"
sendDeleteSubsRsp(w, http.StatusBadRequest, pRsp)
return
}
var req RestReq
req.MsgType = REST_CRM_DELETE_SUBS_REQ
err := json.NewDecoder(r.Body).Decode(&req.DeleteSubsReq)
if err != nil {
rsp.DeleteSubsRsp.Message = "err decode DeleteSubsReq"
sendDeleteSubsRsp(w, http.StatusBadRequest, pRsp)
return
}
l4g.RestLog.Debugf("Got DeleteSubs request: %v", req.DeleteSubsReq)
mysql.CrmDeleteSubsProfile(req.DeleteSubsReq.TelNumber, req.DeleteSubsReq.AcctType, req.DeleteSubsReq.AcctId)
if req.DeleteSubsReq.AcctType != "1" {// not mobile
pRsp.DeleteSubsRsp.Result = 0
pRsp.DeleteSubsRsp.ErrorCode = 2001
sendDeleteSubsRsp(w, http.StatusOK, pRsp)
return
}
// handle ==========================================
port := AssignPort(&req)
if port == nil {
rsp.DeleteSubsRsp.Message = "err port full"
sendDeleteSubsRsp(w, http.StatusInternalServerError, pRsp)
return
}
l4g.RestLog.Debugf("Assign port for DeleteSubs request, src[%d], dst[%d]", req.Src_id, req.Dst_id)
ocsRsp := getOcsRsp(&req, port)
if ocsRsp == nil {
rsp.DeleteSubsRsp.Message = "ocs rsp timeout"
sendDeleteSubsRsp(w, http.StatusInternalServerError, pRsp)
} else {
sendDeleteSubsRsp(w, http.StatusOK, ocsRsp)
}
return
}
func getOcsRsp(req *RestReq, port *Port) (*RestRsp) {
c := make(chan RestRsp)
//port.Rsp = make(chan RestRsp)
port.Rsp = c
go SendOcsUdpReq(req)
defer ReleasePort(req.Src_id)
timeout := time.After(5 * time.Second)
select {
case rsp, ok := <-c:
if !ok {// chan closed
l4g.RestLog.Warnf("chan getOcsRsp closed by other!")
return nil
} else {
close(c)
l4g.RestLog.Debugf("getOcsRsp succ, close chan.")
return &rsp
}
case <-timeout:
l4g.RestLog.Warnf("chan getOcsRsp timeout, close chan!")
close(c)
return nil
}
}
+5
View File
@@ -0,0 +1,5 @@
package Nrestful
import (
)
+688
View File
@@ -0,0 +1,688 @@
package Nrestful
import (
"encoding/binary"
"fmt"
"net"
"proxy/MsgDef"
rdb "proxy/Nredis"
"strconv"
_ "strings"
"time"
l4g "proxy/logger" //"github.com/sirupsen/logrus"
)
var ocsConn *net.UDPConn
func closeConnect() {
ocsConn.Close()
ocsConn = nil
}
var locIp, ocsIp string
var locPort, ocsPort int
func Connect_ocs(loc string, rem string, loc_port int, rem_port int) error {
locIp = loc
ocsIp = rem
locPort = loc_port
ocsPort = rem_port
return connect_ocs()
}
func connect_ocs() error {
loc_ip := net.ParseIP(locIp)
rem_ip := net.ParseIP(ocsIp)
srcAddr := &net.UDPAddr{IP: loc_ip, Port: locPort}
dstAddr := &net.UDPAddr{IP: rem_ip, Port: ocsPort}
var err error
ocsConn, err = net.DialUDP("udp", srcAddr, dstAddr)
if err != nil {
fmt.Println(err)
return err
}
defer closeConnect()
//conn.Write([]byte("hello"))
data := make([]byte, 1500)
//var recLen uint16 = 0
//var msgId uint8 = 0
for {
n, err := ocsConn.Read(data)
//msgId = data[1]
//recLen = uint16(data[2])
//recLen = (recLen << 8) + uint16(data[3])
if err != nil {
//break
} else {
// check param
handle_udp_msg_from_ocs(data, n)
}
//fmt.Printf("read %s from <%s>\n", data[:n], conn.RemoteAddr())
}
l4g.RestLog.Errorln("ocs read thread exit")
return nil
}
//type UdpMsgIE byte
const (
IE_NULL = iota
IE_SRC_REF // UdpMsgIE = 1
IE_DST_REF
IE_MSISDN
IE_RESULT
IE_ERROR_CODE
IE_BALANCE// 6
IE_MO_EXPIRY
IE_MT_EXPIRY
IE_USERNAME
IE_PASSWORD
IE_MSG_CONTENT //value=11
IE_STATUS
IE_REMARK
IE_GROUP_NAME// 0x0e
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
)
func handle_udp_msg_from_ocs(buf []byte, msglen int) {
var rsp RestRsp
ret := Decode_udp_msg(buf, msglen, &rsp)
if ret < 0 {
l4g.RestLog.Errorf("Deocde UDP msg fail, msg[%v]", buf[:msglen])
return
}
switch rsp.MsgType {
case REST_CRM_UPDATE_PLAN_INFO_REQ:
go handleUpdatePlanUsage(&rsp)
return
case REST_CRM_DELETE_SUBS_RES:
handleOcsDeleteSubsRsp(&rsp)
case REST_CRM_CREATE_ACCT_RES:
//handleOcsDeleteSubsRsp(&rsp)
case REST_CRM_UPDATE_SUBS_REQ:
go handleOcsUpdateSubsReq(&rsp)
return
}
l4g.RestLog.Debugf("Recv UDP msg from OCS, msg_id[%d], src[%d], dst[%d]", rsp.MsgType, rsp.Src_id, rsp.Dst_id)
if rsp.Dst_id >= MAX_PORT_NUM {
return
}
port := GetPortInfo(rsp.Dst_id, rsp.Src_id)
if port == nil {
l4g.RestLog.Errorf("Get port by dst_id[%d] fail, msg id[%d]", rsp.Dst_id, rsp.MsgType)
return
}
l4g.RestLog.Debugf("Get port by dst_id[%d] from UDP rsp, msg id[%d]", rsp.Dst_id, rsp.MsgType)
go func() {
port.Rsp <- rsp
}()
return
}
func encode_udp_msg(req *RestReq, buf []byte) int {
switch req.MsgType {
case REST_SEND_AUTHCODE_REQ:
case REST_QUERY_USERDATA_REQ:
case REST_BUNDLE_SUBS_REQ:
case REST_RECHARGE_REQ:
case REST_TRANSFER_REQ:
case REST_QUERY_BALANCE_REQ:
case REST_CRM_CREATE_ACCT_REQ:
case REST_CRM_UPDATE_SUBS_REQ:
case REST_CRM_DELETE_SUBS_REQ:
default:
l4g.RestLog.Errorf("Encode rest unsupport msg id[%d]", req.MsgType)
return 0
}
var msglen int = 0
buf[msglen] = req.MsgType
msglen++
buf[msglen] = IE_SRC_REF
msglen++
buf[msglen] = 0x02
msglen++
binary.BigEndian.PutUint16(buf[msglen:msglen+2], req.Src_id)
msglen += 2
buf[msglen] = IE_DST_REF
msglen++
buf[msglen] = 0x02
msglen++
binary.BigEndian.PutUint16(buf[msglen:msglen+2], req.Dst_id)
msglen += 2
var vallen int = 0
switch (req.MsgType) {
case REST_SEND_AUTHCODE_REQ:
l4g.RestLog.Debugf("Encode REST_SEND_AUTHCODE_REQ[%d], %#v", req.MsgType, req.AuthCodeReq)
// IE_MSISDN
buf[msglen] = IE_MSISDN
msglen++
vallen = len(req.AuthCodeReq.TelNumber)
buf[msglen] = byte(vallen)
msglen++
copy(buf[msglen:msglen+vallen], ([]byte(req.AuthCodeReq.TelNumber)))
msglen += vallen
// IE_MSG_CONTENT
buf[msglen] = IE_MSG_CONTENT
msglen++
vallen = len(req.AuthCodeReq.Content)
binary.BigEndian.PutUint16(buf[msglen:msglen+2], uint16(vallen))
msglen += 2
copy(buf[msglen:msglen+vallen], ([]byte(req.AuthCodeReq.Content)))
msglen += vallen
case REST_QUERY_USERDATA_REQ:
l4g.RestLog.Debugf("Encode REST_QUERY_USERDATA_REQ[%d], %#v", req.MsgType, req.QueryUserDataReq)
// IE_MSISDN
buf[msglen] = IE_MSISDN
msglen++
vallen = len(req.QueryUserDataReq.TelNumber)
buf[msglen] = byte(vallen)
msglen++
copy(buf[msglen:msglen+vallen], ([]byte(req.QueryUserDataReq.TelNumber)))
msglen += vallen
case REST_BUNDLE_SUBS_REQ:
l4g.RestLog.Debugf("Encode REST_BUNDLE_SUBS_REQ[%d], %#v", req.MsgType, req.BundleSubsReq)
// IE_MSISDN
buf[msglen] = IE_MSISDN
msglen++
vallen = len(req.BundleSubsReq.TelNumber)
buf[msglen] = byte(vallen)
msglen++
copy(buf[msglen:msglen+vallen], ([]byte(req.BundleSubsReq.TelNumber)))
msglen += vallen
buf[msglen] = IE_PAY_TYPE
msglen++
buf[msglen] = 0x01
msglen++
pay_type, _ := strconv.Atoi(req.BundleSubsReq.PayType)
buf[msglen] = uint8(pay_type)
msglen += 0x01
buf[msglen] = IE_AMOUNT
msglen++
buf[msglen] = 0x04
msglen++
amount, _ := strconv.Atoi(req.BundleSubsReq.ChargedAmount)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(amount))
msglen += 0x04
buf[msglen] = IE_MO_VOICE_MIN
msglen++
buf[msglen] = 0x04
msglen++
moVocMin, _ := strconv.Atoi(req.BundleSubsReq.MoVoiceMinute)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(moVocMin))
msglen += 0x04
buf[msglen] = IE_MT_VOICE_MIN
msglen++
buf[msglen] = 0x04
msglen++
mtVocMin, _ := strconv.Atoi(req.BundleSubsReq.MtVoiceMinute)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(mtVocMin))
msglen += 0x04
buf[msglen] = IE_SMS_NUM
msglen++
buf[msglen] = 0x04
msglen++
smsNum, _ := strconv.Atoi(req.BundleSubsReq.SmsVolume)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(smsNum))
msglen += 0x04
buf[msglen] = IE_DATA_VOL_MB
msglen++
buf[msglen] = 0x04
msglen++
dataVol, _ := strconv.Atoi(req.BundleSubsReq.DataVolume)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(dataVol))
msglen += 0x04
buf[msglen] = IE_VALID_DAYS
msglen++
buf[msglen] = 0x04
msglen++
validDays, _ := strconv.Atoi(req.BundleSubsReq.ValidPeriod)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(validDays))
msglen += 0x04
case REST_RECHARGE_REQ:
l4g.RestLog.Debugf("Encode REST_RECHARGE_REQ[%d], %#v", req.MsgType, req.RechargeReq)
// IE_MSISDN
buf[msglen] = IE_MSISDN
msglen++
vallen = len(req.RechargeReq.TelNumber)
buf[msglen] = byte(vallen)
msglen++
copy(buf[msglen:msglen+vallen], ([]byte(req.RechargeReq.TelNumber)))
msglen += vallen
buf[msglen] = IE_AMOUNT
msglen++
buf[msglen] = 0x04
msglen++
amount, _ := strconv.Atoi(req.RechargeReq.Amount)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(amount))
msglen += 0x04
buf[msglen] = IE_RECHARGE_TYPE
msglen++
buf[msglen] = 0x01
msglen++
op_type, _ := strconv.Atoi(req.RechargeReq.OpType)
buf[msglen] = uint8(op_type)
msglen += 0x01
buf[msglen] = IE_VALID_DAYS
msglen++
buf[msglen] = 0x02
msglen++
valid_days, _ := strconv.Atoi(req.RechargeReq.ValidyDays)
binary.BigEndian.PutUint16(buf[msglen:msglen+2], uint16(valid_days))
msglen += 0x02
case REST_TRANSFER_REQ:
l4g.RestLog.Debugf("Encode REST_TRANSFER_REQ[%d], %#v", req.MsgType, req.TransferReq)
// IE_MSISDN_TRANS_OUT
buf[msglen] = IE_MSISDN_TRANS_OUT
msglen++
vallen = len(req.TransferReq.TransferOut)
buf[msglen] = byte(vallen)
msglen++
copy(buf[msglen:msglen+vallen], ([]byte(req.TransferReq.TransferOut)))
msglen += vallen
buf[msglen] = IE_MSISDN_TRANS_IN
msglen++
vallen = len(req.TransferReq.TransferIn)
buf[msglen] = byte(vallen)
msglen++
copy(buf[msglen:msglen+vallen], ([]byte(req.TransferReq.TransferIn)))
msglen += vallen
buf[msglen] = IE_AMOUNT
msglen++
buf[msglen] = 0x04
msglen++
amount, _ := strconv.Atoi(req.TransferReq.Amount)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(amount))
msglen += 0x04
case REST_QUERY_BALANCE_REQ:
l4g.RestLog.Debugf("Encode REST_QUERY_BALANCE_REQ[%d], %#v", req.MsgType, req.QueryBalanceReq)
// IE_MSISDN
buf[msglen] = IE_MSISDN
msglen++
vallen = len(req.QueryBalanceReq.TelNumber)
buf[msglen] = byte(vallen)
msglen++
copy(buf[msglen:msglen+vallen], ([]byte(req.QueryBalanceReq.TelNumber)))
msglen += vallen
case REST_CRM_CREATE_ACCT_REQ:
l4g.RestLog.Debugf("Encode REST_CRM_CREATE_ACCT_REQ[%d], %#v", req.MsgType, req.CreateAccountReq)
// IE_MSISDN
buf[msglen] = IE_MSISDN
msglen++
vallen = len(req.CreateAccountReq.ServiceNbr)
buf[msglen] = byte(vallen)
msglen++
copy(buf[msglen:msglen+vallen], ([]byte(req.CreateAccountReq.ServiceNbr)))
msglen += vallen
buf[msglen] = IE_CUSTOMER_ID
msglen++
buf[msglen] = 0x04
msglen++
custId, _ := strconv.Atoi(req.CreateAccountReq.CustId)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(custId))
msglen += 0x04
buf[msglen] = IE_ACCOUNT_ID
msglen++
buf[msglen] = 0x04
msglen++
acctId, _ := strconv.Atoi(req.CreateAccountReq.AccountId)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(acctId))
msglen += 0x04
buf[msglen] = IE_PRODUCT_ID
msglen++
buf[msglen] = 0x04
msglen++
prdId, _ := strconv.Atoi(req.CreateAccountReq.ProductInstId)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(prdId))
msglen += 0x04
buf[msglen] = IE_PLAN_ID
msglen++
buf[msglen] = 0x04
msglen++
planId, _ := strconv.Atoi(req.CreateAccountReq.PackageId)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(planId))
msglen += 0x04
buf[msglen] = IE_BALANCE
msglen++
buf[msglen] = 0x04
msglen++
balance, _ := strconv.Atoi(req.CreateAccountReq.Balance)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(balance))
msglen += 0x04
buf[msglen] = IE_EXPIRY_TIME
msglen++
buf[msglen] = 0x04
msglen++
expire_time, err := time.Parse("2006-01-02 15:04:05", req.CreateAccountReq.BalanceExpDate)
if err != nil {
l4g.RestLog.Errorf("Error CreateAccountReq BalanceExpDate[%s]", req.CreateAccountReq.BalanceExpDate)
return -1
}
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(expire_time.Unix()))
msglen += 0x04
buf[msglen] = IE_RENT_CHARGE
msglen++
buf[msglen] = 0x04
msglen++
rent_charge, _ := strconv.Atoi(req.CreateAccountReq.RentCharge)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(rent_charge))
msglen += 0x04
buf[msglen] = IE_BIRTHDAY
msglen++
buf[msglen] = 0x04
msglen++
birthday, err := time.Parse("2006-01-02", req.CreateAccountReq.Birthday)
if err != nil {
l4g.RestLog.Errorf("Error CreateAccountReq Birthday[%s]", req.CreateAccountReq.Birthday)
return -1
}
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(birthday.Unix()))
msglen += 0x04
buf[msglen] = IE_CUG_ID
msglen++
buf[msglen] = 0x04
msglen++
cugId, _ := strconv.Atoi(req.CreateAccountReq.CugId)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(cugId))
msglen += 0x04
buf[msglen] = IE_USER_CLASS
msglen++
buf[msglen] = 0x01
msglen++
userClass, _ := strconv.Atoi(req.CreateAccountReq.UserClass)
buf[msglen] = byte(userClass)
msglen += 0x01
case REST_CRM_UPDATE_SUBS_REQ:
l4g.RestLog.Debugf("Encode REST_CRM_UPDATE_SUBS_REQ[%d], %#v", req.MsgType, req.UpdateSubsReq)
// IE_MSISDN
buf[msglen] = IE_MSISDN
msglen++
vallen = len(req.UpdateSubsReq.TelNumber)
buf[msglen] = byte(vallen)
msglen++
copy(buf[msglen:msglen+vallen], ([]byte(req.UpdateSubsReq.TelNumber)))
msglen += vallen
buf[msglen] = IE_ACCOUNT_ID
msglen++
buf[msglen] = 0x04
msglen++
acctId, _ := strconv.Atoi(req.UpdateSubsReq.AccountId)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(acctId))
msglen += 0x04
if (len(req.UpdateSubsReq.Status) > 0) {
buf[msglen] = IE_STATUS
msglen++
buf[msglen] = 0x01
msglen++
status, _ := strconv.Atoi(req.UpdateSubsReq.Status)
buf[msglen] = byte(status)
msglen += 0x01
}
if (len(req.UpdateSubsReq.Balance) > 0) {
buf[msglen] = IE_BALANCE
msglen++
buf[msglen] = 0x04
msglen++
balance, _ := strconv.Atoi(req.UpdateSubsReq.Balance)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(balance))
msglen += 0x04
}
if (len(req.UpdateSubsReq.BalanceExpDate) > 0) {
buf[msglen] = IE_EXPIRY_TIME
msglen++
buf[msglen] = 0x04
msglen++
expiryTime, err := time.Parse("2006-01-02 15:04:05", req.UpdateSubsReq.BalanceExpDate)
if err != nil {
l4g.RestLog.Errorf("Error UpdateSubsReq BalanceExpDate[%s]", req.UpdateSubsReq.BalanceExpDate)
return -1
}
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(expiryTime.Unix()))
msglen += 0x04
}
if (len(req.UpdateSubsReq.PackageId) > 0) {
buf[msglen] = IE_PLAN_ID
msglen++
buf[msglen] = 0x04
msglen++
planId, _ := strconv.Atoi(req.UpdateSubsReq.PackageId)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(planId))
msglen += 0x04
}
if (len(req.UpdateSubsReq.RentCharge) > 0) {
buf[msglen] = IE_RENT_CHARGE
msglen++
buf[msglen] = 0x04
msglen++
rentCharge, _ := strconv.Atoi(req.UpdateSubsReq.RentCharge)
binary.BigEndian.PutUint32(buf[msglen:msglen+4], uint32(rentCharge))
msglen += 0x04
}
if (len(req.UpdateSubsReq.VasCugStatus) > 0) {
buf[msglen] = IE_VAS_CUG_STATUS
msglen++
buf[msglen] = 0x01
msglen++
vasCugStatus, _ := strconv.Atoi(req.UpdateSubsReq.VasCugStatus)
buf[msglen] = byte(vasCugStatus)
msglen += 0x01
}
case REST_CRM_DELETE_SUBS_REQ:
l4g.RestLog.Debugf("Encode REST_CRM_DELETE_SUBS_REQ[%d], %#v", req.MsgType, req.DeleteSubsReq)
// IE_MSISDN
buf[msglen] = IE_MSISDN
msglen++
vallen = len(req.DeleteSubsReq.TelNumber)
buf[msglen] = byte(vallen)
msglen++
copy(buf[msglen:msglen+vallen], ([]byte(req.DeleteSubsReq.TelNumber)))
msglen += vallen
buf[msglen] = IE_CAUSE
msglen++
buf[msglen] = 0x01
msglen++
buf[msglen] = 0
msglen += 0x01
default:
return 0
}
return msglen
}
func SendOcsUdpReq(req *RestReq) {
if ocsConn == nil {
return
}
l4g.RestLog.Debugf("Send UDP msg to OCS, msg_id[%d], src[%d], dst[%d]", req.MsgType, req.Src_id, req.Dst_id)
buf := make([]byte, 1024)
msglen := encode_udp_msg(req, buf)
if msglen > 0 {
ocsConn.Write([]byte(buf[:msglen]))
}
return
}
func SendNtfSms2Ocs(serviceNbr string, smsContent string) {
var req RestReq
req.MsgType = REST_SEND_AUTHCODE_REQ
req.Src_id = 0xFFFF
req.Dst_id = 0xFFFF
req.AuthCodeReq.TelNumber = serviceNbr
req.AuthCodeReq.Content = smsContent
SendOcsUdpReq(&req)
}
func SendCrtAcct2Ocs(serviceNbr string, ai *MsgDef.ChgSyncMobile, cugId, userClass, rent int) {
var req RestReq
req.MsgType = REST_CRM_CREATE_ACCT_REQ
req.Src_id = 0xFFFF
req.Dst_id = 0xFFFF
req.CreateAccountReq.ServiceNbr = serviceNbr
req.CreateAccountReq.CustId = strconv.Itoa(ai.CustId)
req.CreateAccountReq.AccountId = strconv.Itoa(ai.AcctId)
req.CreateAccountReq.ProductInstId = strconv.Itoa(ai.PrdInstId)
req.CreateAccountReq.PackageId = strconv.Itoa(ai.OfrId)
req.CreateAccountReq.UserClass = strconv.Itoa(userClass)
req.CreateAccountReq.CugId = strconv.Itoa(cugId)
req.CreateAccountReq.Balance = strconv.Itoa(ai.Balance)
//t, _ := time.Parse("2006-01-02 15:04:05", ai.BirthDate)
req.CreateAccountReq.Birthday = ai.BirthDate
//t, _ := time.Parse("2006-01-02 15:04:05", ai.BalanceExpDate)
req.CreateAccountReq.BalanceExpDate = ai.BalanceExpDate
req.CreateAccountReq.RentCharge = strconv.Itoa(rent)
SendOcsUdpReq(&req)
}
func CreateAcct2Ocs(serviceNbr string, ai *MsgDef.ChgSyncMobile, cugId, userClass, rent int, key string) {
var req RestReq
req.MsgType = REST_CRM_CREATE_ACCT_REQ
req.Src_id = 0xFFFF
req.Dst_id = 0xFFFF
req.CreateAccountReq.ServiceNbr = serviceNbr
req.CreateAccountReq.CustId = strconv.Itoa(ai.CustId)
req.CreateAccountReq.AccountId = strconv.Itoa(ai.AcctId)
req.CreateAccountReq.ProductInstId = strconv.Itoa(ai.PrdInstId)
req.CreateAccountReq.PackageId = strconv.Itoa(ai.OfrId)
req.CreateAccountReq.UserClass = strconv.Itoa(userClass)
req.CreateAccountReq.CugId = strconv.Itoa(cugId)
req.CreateAccountReq.Balance = strconv.Itoa(ai.Balance)
//t, _ := time.Parse("2006-01-02 15:04:05", ai.BirthDate)
req.CreateAccountReq.Birthday = ai.BirthDate
//t, _ := time.Parse("2006-01-02 15:04:05", ai.BalanceExpDate)
req.CreateAccountReq.BalanceExpDate = ai.BalanceExpDate
req.CreateAccountReq.RentCharge = strconv.Itoa(rent)
l4g.RestLog.Debugf("Got createAcct request: %v", req.CreateAccountReq)
// handle ==========================================
port := AssignPort(&req)
if port == nil {
l4g.RestLog.Warnf("Assign port for createAcct request fail, serviceNbr[%s], key[%s]", serviceNbr, key)
return
}
l4g.RestLog.Debugf("Assign port for createAcct request, serviceNbr, src[%d], dst[%d]", serviceNbr, req.Src_id, req.Dst_id)
ocsRsp := getOcsRsp(&req, port)
if ocsRsp == nil {
l4g.RestLog.Warnf("getOcsRsp timeout for createAcct request, serviceNbr[%s], key[%s]", serviceNbr, key)
} else {
l4g.RestLog.Infof("getOcsRsp succ for createAcct request, serviceNbr[%s], key[%s]", serviceNbr, key)
rdb.RdsDelMsg2OcsKey(key)
}
return
}
+80
View File
@@ -0,0 +1,80 @@
Ubuntu18.04
1.安装redis-server
#apt-get install redis-server
#vim /etc/redis/redis.conf
1)配置master
bind 192.168.7.90
protected-mode no
unixsocket /var/run/redis/redis-server.sock
unixsocketperm 700
2)配置slave
bind 192.168.4.61
protected-mode no
unixsocket /var/run/redis/redis-server.sock
unixsocketperm 700
slaveof 192.168.7.90 6379
2.安装redis-sentinel
#apt-get install redis-sentinel
#vim /etc/redis/sentinel.conf
1)sentinel 1
bind 192.168.4.63
protected-mode no
sentinel monitor mymaster 192.168.4.63 6379 1
2)sentinel 2
bind 192.168.4.64
protected-mode no
sentinel monitor mymaster 192.168.4.63 6379 1
2.安装sctp
sudo apt install lksctp-tools
sudo apt install libsctp-dev
Ubuntu20.04编译时
diam/diam_adaptor的makefile文件,CFLAGS加 -DOLD_SCTP_SOCKET_API
3.安装libhiredis
sudo apt install libhiredis-dev
安装glib
#sudo apt-get install libglib2.0-dev ## 20.04
安装idn
#sudo apt -y install idn
安装gnutls
#sudo apt-get install -y libgnutls-dev
#apt-get install libghc-gnutls-dev ## 20.04
#apt-get install libgcrypt20-dev
#idna.h: No such file or directory解决方法
#apt-get install libidn11-dev
4.安装mysqldump
先运行mysqldump,然后按提示安装需要的版本
#apt install mysql-client-5.7 ## 18.04
#apt install mysql-client libmysqlclient-dev ## mysql-server 20.04
5.安装canal
#dpkg -i canal-1.0.1.amd64.deb
配置canal:
#vim /usr/local/etc/canal/config.yaml
log:
output: file
level: info #log级别
path: /var/log/proxy.log
maxAge: 120
rotationTime: 3
mysqlDb:
addr: 192.168.1.211:3306 #mysql DB,nfk mysql DB: 10.10.1.156:3306
username: canal
password: canal
redisDb:
netType: unix
addr: /var/run/kvdb.sock
# sentinelAddrs: # 配sentinel addr
# - 192.168.7.90:26379
# - 192.168.4.61:26379
telnetServer:
addr: 192.168.7.90:4100
canalServer:
reinit: true # 启动时是否重新全量同步mysql到redis
standalone: false # 是否单机运行,true时总是实时同步mysql增量;false时只有本端redis是master时才同步增量,不需要两个canal都同步;
6.安装ocs
+331
View File
@@ -0,0 +1,331 @@
package TelnetShellServer
import (
"github.com/reiver/go-oi"
"github.com/reiver/go-telnet"
"github.com/reiver/go-telnet/telsh"
"proxy/canal"
"proxy/config"
"io"
sdb "proxy/Nmysql"
rdb "proxy/Nredis"
)
// Command not found!
func notFoundHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
_, _ = oi.LongWriteString(stdout, "\rCommand not found!")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
// Syn DB
func syncDbHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
//rdb.ClrTariffAndBundle()
_ = sdb.LoadAcctTblFromMysql()
_, _ = oi.LongWriteString(stdout, "\rSync DB, done!")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
// Syn msisdn
func syncMsisdnHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
//rdb.ClrTariffAndBundle()
_ = sdb.LoadOneAcctFromMysql(args[1])
_, _ = oi.LongWriteString(stdout, "\rSync DB, done!")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
func syncDbProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
if len(args) > 0 {
if args[0] == "db" {
return telsh.PromoteHandlerFunc(syncDbHandler)
} else if args[0] == "msisdn" && len(args)>=2 {
return telsh.PromoteHandlerFunc(syncMsisdnHandler, args...)
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
}
// Clr DB
func clearDbHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
rdb.ClrTariffAndBundle()
_, _ = oi.LongWriteString(stdout, "\rClear DB Finish!")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
// Clr Expired rr
func clearRrHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
rdb.ClrExpRes()
_, _ = oi.LongWriteString(stdout, "\rClear Expired RR Finish!")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
func clearDbProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
if len(args) > 0 {
if args[0] == "db" {
return telsh.PromoteHandlerFunc(clearDbHandler)
} else if args[0] == "rr" {
return telsh.PromoteHandlerFunc(clearRrHandler)
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
}
// get ofr
func getOfrHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
rdb.RdbGetTariffByOfrId(args[1])
_, _ = oi.LongWriteString(stdout, "\rGet ofr Finish!")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
// get act
func getActHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
//_, _ = oi.LongWriteString(stdout, "\n\rdebug2, len(args)="+fmt.Sprintf("%d:%v", len(args), args))
rsp, _ := rdb.RdbGetAcctRecordByServiceNbr(args[1])
_, _ = oi.LongWriteString(stdout, "\r"+rsp+"\n\rGet acct Finish!")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
// get rat
func getRatHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
rsp, _ := rdb.RdbGetRrByServiceNbrAndDomain(args[1])
_, _ = oi.LongWriteString(stdout, "\r"+rsp+"\n\rGet Rr Finish!")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
// get state
func getStateHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
var state string
/*if rdb.CheckIfRdbMaster() == true {
state = "Redis: master; state: " + canal.CurState
} else {*/
state = "Redis: master; state: " + canal.CurState
//}
_, _ = oi.LongWriteString(stdout, "\r"+state)
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
func getRecordProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
if len(args) >= 2 {
/*if args[0] == "ofr" {
return telsh.PromoteHandlerFunc(getOfrHandler)
} else */if args[0] == "act" {
return telsh.PromoteHandlerFunc(getActHandler, args...)
} else if args[0] == "rat" {
return telsh.PromoteHandlerFunc(getRatHandler, args...)
} else if args[0] == "state" {
return telsh.PromoteHandlerFunc(getStateHandler, args...)
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
} else if len(args) == 1 {
if args[0] == "state" {
return telsh.PromoteHandlerFunc(getStateHandler)
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
}
// enable bundle notify
func enableVoiceBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
config.SetBundleUsageNtf(1, true)
_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
func enableDataBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
config.SetBundleUsageNtf(2, true)
_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
func enableSmsBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
config.SetBundleUsageNtf(3, true)
_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
func enableParamProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
if len(args) == 1 {
if args[0] == "voc75ntf" {
return telsh.PromoteHandlerFunc(enableVoiceBundleNtfHandler)
} else if args[0] == "dat75ntf" {
return telsh.PromoteHandlerFunc(enableDataBundleNtfHandler)
} else if args[0] == "sms75ntf" {
return telsh.PromoteHandlerFunc(enableSmsBundleNtfHandler)
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
}
// disable bundle notify
func disableVoiceBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
config.SetBundleUsageNtf(1, false)
_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
func disableDataBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
config.SetBundleUsageNtf(2, false)
_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
func disableSmsBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
config.SetBundleUsageNtf(3, false)
_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
_, _ = oi.LongWriteString(stdout, "\n\r")
_, _ = oi.LongWriteString(stdout, "")
return nil
}
func disableParamProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
if len(args) == 1 {
if args[0] == "voc75ntf" {
return telsh.PromoteHandlerFunc(disableVoiceBundleNtfHandler)
} else if args[0] == "dat75ntf" {
return telsh.PromoteHandlerFunc(disableDataBundleNtfHandler)
} else if args[0] == "sms75ntf" {
return telsh.PromoteHandlerFunc(disableSmsBundleNtfHandler)
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
} else {
return telsh.PromoteHandlerFunc(notFoundHandler)
}
}
/* version handler
func versionHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
oi.LongWriteString(stdout, "\rCurrent PCF version:\n\r")
oi.LongWriteString(stdout, "\r" + n.GetPcfVersion())
oi.LongWriteString(stdout, "\n\r")
oi.LongWriteString(stdout, "")
return nil
}
func versionProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
return telsh.PromoteHandlerFunc(versionHandler)
}*/
func Server(addr string) {
shellHandler := telsh.NewShellHandler()
shellHandler.WelcomeMessage = `
__ __ ______ _ _____ ____ __ __ ______
\ \ / /| ____|| | / ____| / __ \ | \/ || ____|
\ \ /\ / / | |__ | | | | | | | || \ / || |__
\ \/ \/ / | __| | | | | | | | || |\/| || __|
\ /\ / | |____ | |____ | |____ | |__| || | | || |____
\/ \/ |______||______| \_____| \____/ |_| |_||______|
\033[2J\033[1;1HAVAILABLE COMMANDS\n" +
========================================================================
| Command | Remark |
========================================================================
| help | Help page. |
| date | Current date. |
| syn db | Syn Mysql DB to Redis DB. |
| clr db | Clear Redis DB. |
| clr rr | Clear Expired RR. |
| get state | Get loading/init state. |
| get act serviceNbr | Get acct info by service number. |
| get rat num:domain | Get RR info by service number and domain. |
| [en|dis]able voc75ntf| Enable[Disable] %75 usage of voice bundle. |
| [en|dis]able dat75ntf| Enable[Disable] %75 usage of data bundle. |
| [en|dis]able sms75ntf| Enable[Disable] %75 usage of sms bundle. |
| q | Quit. |
========================================================================
`
//shellHandler.Prompt = "pcf:~$"
shellHandler.ExitCommandName = "q"
shellHandler.ExitMessage = "Good bye...\r\n"
// Register the "sync db" command.
commandName := "syn"
commandProducer := telsh.ProducerFunc(syncDbProducer)
_ = shellHandler.Register(commandName, commandProducer)
// Register the "clear db" command.
commandName = "clr"
commandProducer = clearDbProducer
_ = shellHandler.Register(commandName, commandProducer)
commandName = "get"
commandProducer = getRecordProducer
_ = shellHandler.Register(commandName, commandProducer)
commandName = "enable"
commandProducer = enableParamProducer
_ = shellHandler.Register(commandName, commandProducer)
commandName = "disable"
commandProducer = disableParamProducer
_ = shellHandler.Register(commandName, commandProducer)
// Register the "version" command.
//commandName = "version"
//commandProducer = telsh.ProducerFunc(versionProducer)
//shellHandler.Register(commandName, commandProducer)
if err := telnet.ListenAndServe(addr, shellHandler); nil != err {
panic(err)
}
}
+194
View File
@@ -0,0 +1,194 @@
package canal
import (
"github.com/go-mysql-org/go-mysql/canal"
"github.com/go-mysql-org/go-mysql/mysql"
"github.com/go-mysql-org/go-mysql/replication"
mdb "proxy/Nmysql"
rds "proxy/Nredis"
"proxy/config"
//"github.com/siddontang/go-log/log"
//"strconv"
"proxy/logger"
)
type MyEventHandler struct {
canal.DummyEventHandler
}
// 监听数据记录
func (h *MyEventHandler) OnRow(e *canal.RowsEvent) error {
logger.CanalLog.Infof("OnRow: %s.%s %s %v", e.Table.Schema, e.Table.Name, e.Action, e.Rows)
/*if !config.Config.CanalServer.Standalone && rds.CheckIfRdbMaster() == false {
logger.CanalLog.Warnf("not stand alone, and change to Slave!")
cnl.Close()
return nil
}*/
c := ParseAndFilterBinLog(e)
updateRedisTable(c)
for columnIndex, curColumn := range e.Table.Columns {
logger.CanalLog.Debugf("row info: %v %v %v", curColumn.Name, columnIndex, e.Rows[len(e.Rows)-1][columnIndex])
}
//cnl.Close()// if slave
return nil
}
// 创建,更改,重命名或者删除表时触发,通常会需要清除与表相关的数据,如缓存。 It will be called before OnDDL.
func (h *MyEventHandler) OnTableChanged(header *replication.EventHeader, schema string, table string) error {
logger.CanalLog.Infof("OnTableChanged: %s %s", schema, table)
return nil
}
// 监听binlog日志的变化文件与记录的位置
func (h *MyEventHandler) OnPosSynced(header *replication.EventHeader, pos mysql.Position, set mysql.GTIDSet, force bool) error {
// if force == true, 立即同步位置
rds.RdbSetBinLogPos(pos.Name, pos.Pos)
logger.CanalLog.Infof("OnPosSynced: Name[%v] Pos[%v], force[%t]", pos.Name, pos.Pos, force)
return nil
}
// 当产生新的binlog日志后触发(在达到内存的使用限制后(默认为1GB),会开启另一个文件,每个新文件的名称后都会有一个增量.)
func (h *MyEventHandler) OnRotate(header *replication.EventHeader, r *replication.RotateEvent) error {
// record := fmt.Sprintf("On Rotate: %v \n", &mysql.Position{Name: string(r.NextLogName), Pos: uint32(r.Position)})
// binlog的记录位置,新binlog的文件名
logger.CanalLog.Infof("On Rotate: Pos[%v] NextLogName[%v] \n", r.Position, r.NextLogName)
return nil
}
// Create alter drop truncate(删除当前表再新建一个一模一样的表结构)
func (h *MyEventHandler) OnDDL(header *replication.EventHeader, nextPos mysql.Position, queryEvent *replication.QueryEvent) error {
// binlog日志的变化文件与记录的位置
logger.CanalLog.Infof("OnDDL: Name[%v] Pos[%v]\n", nextPos.Name, nextPos.Pos)
logger.CanalLog.Infof("%v\n %v\n %v\n %v\n %v\n",
queryEvent.ExecutionTime, // 猜是执行时间,但测试显示0
string(queryEvent.Schema), // 库名
string(queryEvent.Query), // 变更的sql语句
string(queryEvent.StatusVars[:]), //测试显示乱码
queryEvent.SlaveProxyID) // 从库代理ID?
return nil
}
func (h *MyEventHandler) String() string {
return "MyEventHandler"
}
var cnl *canal.Canal
func StartMyCanal(addr string, username string, password string) {
cfg := canal.NewDefaultConfig()
cfg.Addr = addr //"192.168.1.211:3306"
cfg.User = username
cfg.Password = password
// We only care table canal_test in test db
cfg.Dump.TableDB = "boss"
cfg.Dump.Tables = []string{"tb_prd_ofr_detail_inst_551",
"tb_bil_tariff", "tb_prd_ofr", "tb_bil_evt_pricing_strategy", "config_area",
"tb_bil_pricing_area", "ratable_history", "tb_bil_holiday_rel", "tb_bil_holiday"}//, "tb_prd_prd_inst_551"}
cfg.IncludeTableRegex = make([]string, 0, 1)
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_prd_prd_inst_551")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_prd_ofr_detail_inst_551")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_bil_tariff")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_prd_ofr")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_bil_evt_pricing_strategy")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.config_area")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_bil_pricing_area")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.ratable_history")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_bil_holiday_rel")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_bil_holiday")
if config.Config.CronCfg.Enabled && config.Config.CronCfg.NtfSms != "" {
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_sms_info")
}
if config.Config.Rest.Enabled {
cfg.Dump.Tables = append(cfg.Dump.Tables, "tb_sync_mobile")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_sync_mobile")
}
c, err := canal.NewCanal(cfg)
if err != nil {
logger.CanalLog.Errorf("NewCanal, err: %v", err)
return
}
// Register a handler to handle RowsEvent
c.SetEventHandler(&MyEventHandler{})
var pos *mysql.Position
if config.Config.CanalServer.Reinit {
pos = QueryBinLogPos(c)
if pos == nil {
logger.CanalLog.Errorln("fail to get binlog position.")
return
}
logger.CanalLog.Infoln("start to sync mysql DB.")
CurState = "loading"
if config.Config.CanalServer.FlushBeforeInit {
rds.ClrTariffAndBundle()
}
_ = mdb.LoadAcctTblFromMysql()
_ = mdb.LoadAlertSmsFromMysql()
//_ = mdb.LoadCreateAcctFromMysql()
config.Config.CanalServer.Reinit = false
config.SavePcfCfg()
logger.CanalLog.Infoln("finish sync mysql DB...")
CurState = "synchronize"
} else {
ret := rds.RdbGetBinLogPos()
if ret == nil {
logger.CanalLog.Warnln("fail to get redis binlog position, query current position from mysql.")
pos = QueryBinLogPos(c)
if pos == nil {
logger.CanalLog.Errorln("fail to get binlog position.")
return
}
} else {
pos = &mysql.Position{Name: ret.File, Pos: ret.Position}
}
}
// Start canal
cnl = c
logger.CanalLog.Infof("Go run")
err = c.RunFrom(*pos)
if err != nil {
logger.CanalLog.Errorf("RunFrom err: %v", err)
} else {
logger.CanalLog.Warnf("Canal exit!!!!!!")
c.Close()
}
/* 从头开始监听
err = c.Run()
if err != nil {
logger.CanalLog.Infof("Run err: %v", err)
}*/
// mysql-bin.000004, 1027
// startPos := mysql.Position{Name: "mysql-bin.000004", Pos: 1027}
// c.RunFrom(startPos)
}
func QueryBinLogPos(c *canal.Canal) *mysql.Position {
var pos mysql.Position
ret, err := c.Execute("SHOW MASTER STATUS;")
if err != nil {
logger.CanalLog.Errorf("SHOW MASTER STATUS err: %v", err)
return nil
}
pos.Name, err = ret.Resultset.GetStringByName(0, "File")
if err != nil {
logger.CanalLog.Errorf("Get binlog file name err: %v", err)
return nil
}
posTmp, err := ret.Resultset.GetUintByName(0, "Position")
if err != nil {
logger.CanalLog.Errorf("Get binlog position err: %v", err)
return nil
}
pos.Pos = uint32(posTmp)
logger.CanalLog.Infof("Current Position: %v", pos)
rds.RdbSetBinLogPos(pos.Name, pos.Pos)
return &pos
}
+197
View File
@@ -0,0 +1,197 @@
package canal
import (
"github.com/go-mysql-org/go-mysql/canal"
"github.com/go-mysql-org/go-mysql/mysql"
"github.com/go-mysql-org/go-mysql/replication"
mdb "proxy/Nmysql"
rds "proxy/Nredis"
"proxy/config"
//"github.com/siddontang/go-log/log"
//"strconv"
"proxy/logger"
)
type MyEventHandler struct {
canal.DummyEventHandler
}
// 监听数据记录
func (h *MyEventHandler) OnRow(e *canal.RowsEvent) error {
logger.CanalLog.Infof("OnRow: %s.%s %s %v", e.Table.Schema, e.Table.Name, e.Action, e.Rows)
/*if !config.Config.CanalServer.Standalone && rds.CheckIfRdbMaster() == false {
logger.CanalLog.Warnf("not stand alone, and change to Slave!")
cnl.Close()
return nil
}*/
c := ParseAndFilterBinLog(e)
updateRedisTable(c)
for columnIndex, curColumn := range e.Table.Columns {
logger.CanalLog.Debugf("row info: %v %v %v", curColumn.Name, columnIndex, e.Rows[len(e.Rows)-1][columnIndex])
}
//cnl.Close()// if slave
return nil
}
// 创建,更改,重命名或者删除表时触发,通常会需要清除与表相关的数据,如缓存。 It will be called before OnDDL.
func (h *MyEventHandler) OnTableChanged(schema string, table string) error {
//
logger.CanalLog.Infof("OnTableChanged: %s %s", schema, table)
return nil
}
// 监听binlog日志的变化文件与记录的位置
func (h *MyEventHandler) OnPosSynced(pos mysql.Position, set mysql.GTIDSet, force bool) error {// update and save
// if force == true, 立即同步位置
rds.RdbSetBinLogPos(pos.Name, pos.Pos)
logger.CanalLog.Infof("OnPosSynced: Name[%v] Pos[%v], force[%t]", pos.Name, pos.Pos, force)
return nil
}
// 当产生新的binlog日志后触发(在达到内存的使用限制后(默认为1GB),会开启另一个文件,每个新文件的名称后都会有一个增量.)
func (h *MyEventHandler) OnRotate(r *replication.RotateEvent) error {
// record := fmt.Sprintf("On Rotate: %v \n", &mysql.Position{Name: string(r.NextLogName), Pos: uint32(r.Position)})
// binlog的记录位置,新binlog的文件名
logger.CanalLog.Infof("On Rotate: Pos[%v] NextLogName[%v] \n", r.Position, r.NextLogName)
return nil
}
// Create alter drop truncate(删除当前表再新建一个一模一样的表结构)
func (h *MyEventHandler) OnDDL(nextPos mysql.Position, queryEvent *replication.QueryEvent) error {
// binlog日志的变化文件与记录的位置
logger.CanalLog.Infof("OnDDL: Name[%v] Pos[%v]\n", nextPos.Name, nextPos.Pos)
logger.CanalLog.Infof("%v\n %v\n %v\n %v\n %v\n",
queryEvent.ExecutionTime,// 猜是执行时间,但测试显示0
string(queryEvent.Schema),// 库名
string(queryEvent.Query),// 变更的sql语句
string(queryEvent.StatusVars[:]),//测试显示乱码
queryEvent.SlaveProxyID)// 从库代理ID?
return nil
}
func (h *MyEventHandler) String() string {
return "MyEventHandler"
}
var cnl *canal.Canal
func StartMyCanal(addr string, username string, password string) {
cfg := canal.NewDefaultConfig()
cfg.Addr = addr//"192.168.1.211:3306"
cfg.User = username
cfg.Password = password
// We only care table canal_test in test db
cfg.Dump.TableDB = "boss"
cfg.Dump.Tables = []string{"tb_prd_ofr_detail_inst_551",
"tb_bil_tariff", "tb_prd_ofr", "tb_bil_evt_pricing_strategy", "config_area",
"tb_bil_pricing_area", "ratable_history", "tb_bil_holiday_rel", "tb_bil_holiday"}//, "tb_prd_prd_inst_551"}
cfg.IncludeTableRegex = make([]string, 0, 1)
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_prd_prd_inst_551")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_prd_ofr_detail_inst_551")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_bil_tariff")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_prd_ofr")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_bil_evt_pricing_strategy")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.config_area")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_bil_pricing_area")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.ratable_history")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_bil_holiday_rel")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_bil_holiday")
if config.Config.CronCfg.Enabled && config.Config.CronCfg.NtfSms != "" {
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_sms_info")
}
if config.Config.Rest.Enabled {
cfg.Dump.Tables = append(cfg.Dump.Tables, "tb_sync_mobile")
cfg.IncludeTableRegex = append(cfg.IncludeTableRegex, "boss\\.tb_sync_mobile")
}
c, err := canal.NewCanal(cfg)
if err != nil {
logger.CanalLog.Errorf("NewCanal, err: %v", err)
return
}
// Register a handler to handle RowsEvent
c.SetEventHandler(&MyEventHandler{})
var pos *mysql.Position
if config.Config.CanalServer.Reinit {
pos = QueryBinLogPos(c)
if pos == nil {
logger.CanalLog.Errorln("fail to get binlog position.")
return
}
logger.CanalLog.Infoln("start to sync mysql DB.")
CurState = "loading"
if config.Config.CanalServer.FlushBeforeInit {
rds.ClrTariffAndBundle()
}
_ = mdb.LoadAcctTblFromMysql()
_ = mdb.LoadAlertSmsFromMysql()
//_ = mdb.LoadCreateAcctFromMysql()
config.Config.CanalServer.Reinit = false
config.SavePcfCfg()
logger.CanalLog.Infoln("finish sync mysql DB...")
CurState = "synchronize"
} else {
ret := rds.RdbGetBinLogPos()
if ret == nil {
logger.CanalLog.Warnln("fail to get redis binlog position, query current position from mysql.")
pos = QueryBinLogPos(c)
if pos == nil {
logger.CanalLog.Errorln("fail to get binlog position.")
return
}
} else {
pos = &mysql.Position{Name: ret.File, Pos: ret.Position}
}
}
// Start canal
cnl = c
logger.CanalLog.Infof("Go run")
err = c.RunFrom(*pos)
if err != nil {
logger.CanalLog.Errorf("RunFrom err: %v", err)
} else {
logger.CanalLog.Warnf("Canal exit!!!!!!")
c.Close()
}
/* 从头开始监听
err = c.Run()
if err != nil {
logger.CanalLog.Infof("Run err: %v", err)
}*/
// mysql-bin.000004, 1027
// startPos := mysql.Position{Name: "mysql-bin.000004", Pos: 1027}
// c.RunFrom(startPos)
}
func QueryBinLogPos(c *canal.Canal) *mysql.Position {
var pos mysql.Position
ret, err := c.Execute("SHOW MASTER STATUS;")
if err != nil {
logger.CanalLog.Errorf("SHOW MASTER STATUS err: %v", err)
return nil
}
pos.Name, err = ret.Resultset.GetStringByName(0, "File")
if err != nil {
logger.CanalLog.Errorf("Get binlog file name err: %v", err)
return nil
}
posTmp, err := ret.Resultset.GetUintByName(0, "Position")
if err != nil {
logger.CanalLog.Errorf("Get binlog position err: %v", err)
return nil
}
pos.Pos = uint32(posTmp)
logger.CanalLog.Infof("Current Position: %v", pos)
rds.RdbSetBinLogPos(pos.Name, pos.Pos)
return &pos
}
+160
View File
@@ -0,0 +1,160 @@
package canal
import (
//"log"
"os"
"time"
"github.com/golang/protobuf/proto"
"github.com/withlin/canal-go/client"
pbe "github.com/withlin/canal-go/protocol/entry"
"proxy/logger"
)
func ConectCanalServer(ipaddr string) {
// 192.168.199.17 替换成你的canal server的地址
// example 替换成-e canal.destinations=example 你自己定义的名字
connector := client.NewSimpleCanalConnector(ipaddr, 11111, "", "", "example", 60000, 60*60*1000)
err := connector.Connect()
if err != nil {
logger.CanalLog.Errorln(err)
os.Exit(1)
}
// https://github.com/alibaba/canal/wiki/AdminGuide
//mysql 数据解析关注的表,Perl正则表达式.
//
//多个正则之间以逗号(,)分隔,转义符需要双斜杠(\\)
//
//常见例子:
//
// 1. 所有表:.* or .*\\..*
// 2. canal schema下所有表: canal\\..*
// 3. canal下的以canal打头的表:canal\\.canal.*
// 4. canal schema下的一张表:canal\\.test1
// 5. 多个规则组合使用:canal\\..*,mysql.test1,mysql.test2 (逗号分隔)
filter := "canal.instance.filter.regex=boss.tb_prd_prd_inst_551,boss.tb_prd_ofr_detail_inst_551,boss.tb_bil_tariff,boss.tb_prd_ofr,boss.tb_bil_evt_pricing_strategy,boss.config_area,boss.tb_bil_pricing_area,boss.ratable_history,boss.tb_bil_holiday_rel,boss.tb_bil_holiday"
//err = connector.Subscribe(".*\\..*")
err = connector.Subscribe(filter)
if err != nil {
logger.CanalLog.Errorln(err)
os.Exit(1)
}
var counter int= 0
for {
message, err := connector.Get(100, nil, nil)
if err != nil {
logger.CanalLog.Errorln(err)
os.Exit(1)
}
batchId := message.Id
if batchId == -1 || len(message.Entries) <= 0 {
time.Sleep(200 * time.Millisecond)
counter++
if counter == 300 {
logger.CanalLog.Infoln("===Idle===")
counter = 0
}
continue
}
printEntry(message.Entries)
counter = 0
}
}
/*
func updateRedisTable(oneR *RecordChange) {
var synType int
if oneR.EventType == pbe.EventType_INSERT {
synType = 1
} else if oneR.EventType == pbe.EventType_DELETE {
synType = 3
} else {
synType = 2
}
switch oneR.TableName {
case TbAcctInfo:
mdb.UpdateRedisAcctTable(synType, oneR.ChgAcctInfo.PrdInstId, oneR.ChgAcctInfo.ServiceNbr)
case TbOfrDetail:
mdb.UpdateRedisAcctTableOfr(synType, oneR.ChgOfrDetail.OfrDetailInstId)
case TbTariff:
mdb.UpdateRedisTariffTable(synType, oneR.ChgTariff.TariffId)
case TbOfrInfo:
mdb.UpdateRedisTariffTableByOfr(synType, oneR.ChgOfrInfo.OfrId)
case TbPricingStrategy:
mdb.UpdateRedisTariffTableByStrategy(synType, oneR.ChgPricingStrategy.EventPricingStrategyId)
case TbConfigArea:// update prefix table, while update config_area table
mdb.UpdateRedisPrefixTableByConfigArea(synType, oneR.ChgConfigArea.AreaId, oneR.ChgConfigArea.OldAreaCode, oneR.ChgConfigArea.NewAreaCode)
case TbPricingArea:
mdb.UpdateRedisPrefixTable(synType, oneR.ChgPricingArea.NewStrategyId, oneR.ChgPricingArea.NewAreaId)
case TbRr:
if rrId > 0 {
mdb.UpdateRedisRrTable(synType, rrId, ratableVal, usedVal, beginTime, endTime)
} else {
if ofrId > 0 {// ofr: CALC_PRIORITY
mdb.UpdateRdbRrOfrPriority(ofrId, tariffSeq)
} else if strategyId > 0 {// strategy: EVENT_PRIORITY
mdb.UpdateRdbRrStrategyPriority(strategyId, tariffSeq)
}
}
case TbHoliday:
mdb.UpdateRedisHolidayDisTableByTariffId(synType, TariffId, tariffSeq)
case TbBilHoliday:
mdb.UpdateRedisHolidayDisTableByHolidayId(synType, holidayId)
default:
}
}*/
func printEntry(entrys []pbe.Entry) {
for _, entry := range entrys {
if entry.GetEntryType() == pbe.EntryType_TRANSACTIONBEGIN || entry.GetEntryType() == pbe.EntryType_TRANSACTIONEND {
continue
}
rowChange := new(pbe.RowChange)
err := proto.Unmarshal(entry.GetStoreValue(), rowChange)
checkError(err)
if rowChange != nil {
eventType := rowChange.GetEventType()
header := entry.GetHeader()
logger.CanalLog.Infof("================> binlog[%s : %d],name[%s,%s], eventType: %s", header.GetLogfileName(), header.GetLogfileOffset(), header.GetSchemaName(), header.GetTableName(), header.GetEventType())
for _, rowData := range rowChange.GetRowDatas() {
/*oneRecordChg := ParseAndFilterChange(eventType, header.GetTableName(), rowData)
if oneRecordChg == nil {
continue
}
updateRedisTable(oneRecordChg)*/
if eventType == pbe.EventType_DELETE {
printColumn(rowData.GetBeforeColumns())
} else if eventType == pbe.EventType_INSERT {
printColumn(rowData.GetAfterColumns())
} else {
logger.CanalLog.Infoln("-------> before")
printColumn(rowData.GetBeforeColumns())
logger.CanalLog.Infoln("-------> after")
printColumn(rowData.GetAfterColumns())
}
}
}
}
}
func printColumn(columns []*pbe.Column) {
for _, col := range columns {
logger.CanalLog.Infof("%s : %s update= %t", col.GetName(), col.GetValue(), col.GetUpdated())
}
}
func checkError(err error) {
if err != nil {
logger.CanalLog.Errorf("Fatal error: %s", err.Error())
os.Exit(1)
}
}
+28
View File
@@ -0,0 +1,28 @@
package canal
import (
"proxy/logger"
"time"
)
var CurState string= "init"
func CanalFsm(addr string, username string, password string) {
t := time.NewTimer(time.Second * 2)
defer t.Stop()
for {
<-t.C// wait for next tick
//if config.Config.CanalServer.Standalone || (!config.Config.CanalServer.Standalone && rds.CheckIfRdbMaster() == true) {
StartMyCanal(addr, username, password)
logger.CanalLog.Warnf("Exit Canal!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
t.Reset(time.Second * 3)
/*} else {
CurState = "idle"
if config.Config.CanalServer.Reinit {
config.Config.CanalServer.Reinit = false
config.SavePcfCfg()
}
t.Reset(time.Second * 2)
}*/
}
}
+1102
View File
File diff suppressed because it is too large. Load diff
+114
View File
@@ -0,0 +1,114 @@
package canal
import (
"github.com/go-mysql-org/go-mysql/canal"
. "proxy/MsgDef"
mdb "proxy/Nmysql"
"proxy/logger"
)
func updateRedisTable(c *RecordChange) {
if c == nil {
return
}
var synType int
if c.EventType == canal.InsertAction {
synType = 1
} else if c.EventType == canal.DeleteAction {
synType = 3
} else {
synType = 2
}
switch c.TableName {
case TbAcctInfo:
for _, row := range c.ChgAcctInfo {
logger.CanalLog.Infof("entry updateRedisTable: TbAcctInfo, type[%d]", synType)
mdb.UpdateRedisAcctTable(synType, &row)
}
case TbOfrDetail:
for _, row := range c.ChgOfrDetail {
logger.CanalLog.Infof("entry updateRedisTable: TbOfrDetail, type[%d]", synType)
mdb.UpdateRedisAcctTableOfr(synType, &row)
}
case TbTariff:
for _, row := range c.ChgTariff {
logger.CanalLog.Infof("entry updateRedisTable: TbTariff, type[%d]", synType)
mdb.UpdateRedisTariffTable(synType, &row)
}
case TbOfrInfo:
for _, row := range c.ChgOfrInfo {
logger.CanalLog.Infof("entry updateRedisTable: TbOfrInfo, type[%d]", synType)
mdb.UpdateRedisTariffTableByOfr(synType, &row)
}
case TbPricingStrategy:
for _, row := range c.ChgPricingStrategy {
logger.CanalLog.Infof("entry updateRedisTable: TbPricingStrategy, type[%d]", synType)
mdb.UpdateRedisTariffTableByStrategy(synType, &row)
}
case TbConfigArea:// update prefix table, while update config_area table
for _, row := range c.ChgConfigArea {
logger.CanalLog.Infof("entry updateRedisTable: TbConfigArea, type[%d]", synType)
if synType == 3 {
mdb.UpdateRedisPrefixTableByConfigArea(synType, &row)
} else {
mdb.UpdateRedisPrefixTableByConfigArea(synType, &row)
}
}
case TbPricingArea:
for _, row := range c.ChgPricingArea {
logger.CanalLog.Infof("entry updateRedisTable: TbPricingArea, type[%d]", synType)
if synType == 3 {
mdb.UpdateRedisPrefixTable(synType, &row)
} else {
mdb.UpdateRedisPrefixTable(synType, &row)
}
}
case TbRr:
for _, row := range c.ChgRr {
logger.CanalLog.Infof("entry updateRedisTable: TbRr, type[%d]", synType)
//if row.Id > 0 {
if synType == 1 {
mdb.UpdateRedisRrTable(synType, &row)
} else if synType == 3 {
mdb.UpdateRedisRrTable(synType, &row)
} else {
mdb.UpdateRedisRrTable(synType, &row)
}
/*} else {
if ofrId > 0 {// ofr: CALC_PRIORITY
mdb.UpdateRdbRrOfrPriority(ofrId, tariffSeq)
} else if strategyId > 0 {// strategy: EVENT_PRIORITY
mdb.UpdateRdbRrStrategyPriority(strategyId, tariffSeq)
}
}*/
}
case TbHoliday:
for _, row := range c.ChgHoliday {
logger.CanalLog.Infof("entry updateRedisTable: TbHoliday, type[%d]", synType)
if synType == 1 {
mdb.UpdateRedisHolidayDisTableByTariffId(synType, &row)
} else if synType == 3 {
mdb.UpdateRedisHolidayDisTableByTariffId(synType, &row)
} else {
mdb.UpdateRedisHolidayDisTableByTariffId(synType, &row)
}
}
case TbBilHoliday:
for _, row := range c.ChgBilHoliday {
logger.CanalLog.Infof("entry updateRedisTable: TbBilHoliday, type[%d]", synType)
mdb.UpdateRedisHolidayDisTableByHolidayId(synType, &row)
}
case TbSmsInfo:
for _, row := range c.ChgAlertSms {
logger.CanalLog.Infof("entry updateRedisTable: TbSmsInfo, type[%d]", synType)
mdb.UpdateRedisAlertSms(synType, &row)
}
case TbSyncMobile:
/*for _, row := range c.ChgSyncMobile {
logger.CanalLog.Infof("entry updateRedisTable: TbSyncMobile, type[%d]", synType)
mdb.UpdateRedisSyncMobile(synType, &row)
}*/
default:
}
}
+38
View File
@@ -0,0 +1,38 @@
log:
level: info
mysqlDb:
addr: 192.168.1.211:3306
username: boss
password: mysqlboss
redisDb:
netType: unix
addr: /var/run/kvdb.sock
##sentinelAddrs:
## - 192.168.7.90:26379
## - 192.168.4.61:26379
telnetServer:
addr: 192.168.7.90:4100
rest:
enabled: true
httpAddr: 192.168.7.90:8080
emsAddr: 192.168.7.92:4999
locRzIp: 192.168.7.90
locRzPort: 4900
ocsRzIp: 192.168.7.90
ocsRzPort: 4951
enableNotification: true
canalServer:
enabled: true
addr: 192.168.1.211:3306
username: canal
password: canal
reinit: false
flushBeforeInit: true
standalone: true
cronCfg:
enabled: true
clrExp: '0 20 5 1,11,21 * ?'
ntfSms: '*/3 * * * * ?'
provision:
enabled: true
ssEntryIdInCrm: 1049
+141
View File
@@ -0,0 +1,141 @@
package config
import (
"gopkg.in/yaml.v2"
"io/ioutil"
//"os"
//"io/ioutil"
//"encoding/json"
l4g "proxy/logger"//"github.com/sirupsen/logrus"
)
type LogConf struct {
//Output string `yaml:"output"`// file; console
Level string `yaml:"level"`// debug; info; warn; error
//Path string `yaml:"path"`
//MaxAge int `yaml:"maxAge"`// per Hour
//RotationTime int `yaml:"rotationTime"`// per Hour
}
type MysqlDb struct {
Addr string `yaml:"addr"`
Username string `yaml:"username"`
Password string `yaml:"password"`
}
type RedisDb struct {
NetType string `yaml:"netType"`
Addr string `yaml:"addr"`
Password string `yaml:"password,omitempty"`
SentinelAddrs []string `yaml:"sentinelAddrs,omitempty"`
}
type TelnetServer struct {
Addr string `yaml:"addr"`
}
type RestConf struct {
Enabled bool `yaml:"enabled"`
HttpAddr string `yaml:"httpAddr"`
//EmsAddr string `yaml:"emsAddr,omitempty"`
LocRzIp string `yaml:"locRzIp"`
LocRzPort int `yaml:"locRzPort"`
OcsRzIp string `yaml:"ocsRzIp"`
OcsRzPort int `yaml:"ocsRzPort"`
//EnableNotification bool `yaml:"enableNotification"`
}
type CanalServer struct {
Enabled bool `yaml:"enabled"`
Addr string `yaml:"addr"`
Username string `yaml:"username"`
Password string `yaml:"password"`
Reinit bool `yaml:"reinit"`
FlushBeforeInit bool `yaml:"flushBeforeInit"`
//Standalone bool `yaml:"standalone"`
}
type CronCfg struct {
Enabled bool `yaml:"enabled"`
ClrExp string `yaml:"clrExp,omitempty"`
NtfSms string `yaml:"ntfSms,omitempty"`
}
type ProvisionCfg struct {
Enabled bool `yaml:"enabled"`
Interval int `yaml:"interval"`
ReadTimout int `yaml:"readTimout"`
EmsIp string `yaml:"emsIp"`
EmsPort int `yaml:"emsPort"`
Username string `yaml:"username"`
Password string `yaml:"password"`
ConnectHss string `yaml:"connectHss,omitempty"`
ConnectAuc string `yaml:"connectAuc,omitempty"`
ConnectVms string `yaml:"connectVms,omitempty"`
DisconnectHss string `yaml:"disconnectHss,omitempty"`
DisconnectAuc string `yaml:"disconnectAuc,omitempty"`
DisconnectVms string `yaml:"disconnectVms,omitempty"`
SsEntryIdInCrm int `yaml:"ssEntryIdInCrm,omitempty"`
}
type BundleUsageNotify struct {
//Enabled bool `yaml:"enabled"`
Voice75Percent bool `yaml:"voice75Percent"`
Data75Percent bool `yaml:"data75Percent"`
Sms75Percent bool `yaml:"sms75Percent"`
}
type DbConfig struct {
Log *LogConf `yaml:"log,omitempty"`
MysqlDb MysqlDb `yaml:"mysqlDb"`
RedisDb RedisDb `yaml:"redisDb"`
TelnetServer TelnetServer `yaml:"telnetServer"`
Rest RestConf `json:"rest"`
CanalServer CanalServer `yaml:"canalServer"`
CronCfg CronCfg `yaml:"cronCfg"`
Provision ProvisionCfg `yaml:"provision"`
BundleUsageNotify BundleUsageNotify `yaml:"bundleUsageNotify"`
}
var Config = DbConfig{ /*mysql: "192.168.1.151:3306", username: "root", password: "rootaa"*/}
func ReadConfig() error {
if content, err := ioutil.ReadFile("/usr/local/restproxy/etc/config.yaml"); err != nil {
return err
} else {
if yamlErr := yaml.Unmarshal(content, &Config); yamlErr != nil {
return yamlErr
}
}
return nil
}
func SavePcfCfg() {
if content, err := yaml.Marshal(&Config); err != nil {
l4g.CfgLog.Errorf("Marshal failed error %s", err.Error())
return
} else if fileErr := ioutil.WriteFile("/usr/local/restproxy/etc/config.yaml", content, 0644); fileErr != nil {
l4g.CfgLog.Errorf("WriteFile failed error %s", fileErr.Error())
return
}
}
func SetBundleUsageNtf(serviceType int, bEnable bool) {
switch serviceType {
case 1:
Config.BundleUsageNotify.Voice75Percent = bEnable
case 2:
Config.BundleUsageNotify.Data75Percent = bEnable
case 3:
Config.BundleUsageNotify.Sms75Percent = bEnable
default:
}
SavePcfCfg()
}
+46
View File
@@ -0,0 +1,46 @@
package cron
import (
rds "proxy/Nredis"
rest "proxy/Nrestful"
"github.com/robfig/cron"
l4g "proxy/logger"
)
func cronClrExpRes() {// 3.1(+[29]/30/31); 5.1/7.1/10.1/12.1(+31);
rds.ClrExpRes()
}
func cronNtfSms() {
rest.RdbScanAlertSmsRecord()
}
var c *cron.Cron = nil
func CronStart(clrExp, ntfSms string) {
c = cron.New()
// add a func to run in cron time
//err := c.AddFunc("0 59 * * * ?", cron_rentThisMonth)
var err error
if clrExp != "" {
err = c.AddFunc(clrExp, cronClrExpRes)
if err != nil {
l4g.AppLog.Error("Add cron clear expire rr and acct error: %v", err)
}
}
if ntfSms != "" {
err = c.AddFunc(ntfSms, cronNtfSms)
if err != nil {
l4g.AppLog.Error("Add cron send notify sms error: %v", err)
}
}
c.Start()
}
func CronStop() {
c.Stop()
}
+75
View File
@@ -0,0 +1,75 @@
package logger
import (
"os"
"time"
formatter "github.com/antonfisher/nested-logrus-formatter"
"github.com/sirupsen/logrus"
"proxy/util/logger_conf"
"proxy/util/logger_util"
)
var (
log *logrus.Logger
AppLog *logrus.Entry
InitLog *logrus.Entry
CfgLog *logrus.Entry
MysqlLog *logrus.Entry
/*Bdtpolicylog *logrus.Entry
PolicyAuthorizationlog *logrus.Entry
AMpolicylog *logrus.Entry
SMpolicylog *logrus.Entry
Consumerlog *logrus.Entry
UtilLog *logrus.Entry
CallbackLog *logrus.Entry
OamLog *logrus.Entry
CtxLog *logrus.Entry
ConsumerLog *logrus.Entry
GinLog *logrus.Entry
NotifyEventLog *logrus.Entry*/
ProvLog *logrus.Entry
RedisLog *logrus.Entry
RestLog *logrus.Entry
CanalLog *logrus.Entry
)
const (
FieldRemoteAddr string = "remote_addr"
)
func init() {
log = logrus.New()
log.SetReportCaller(true)
log.Formatter = &formatter.Formatter{
TimestampFormat: time.RFC3339,
TrimMessages: true,
NoFieldsSpace: true,
HideKeys: true,
FieldsOrder: []string{"component", "category", FieldRemoteAddr},
}
free5gcLogHook, err := logger_util.NewFileHook(logger_conf.Free5gcLogFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0o666)
if err == nil {
log.Hooks.Add(free5gcLogHook)
}
AppLog = log.WithFields(logrus.Fields{"component": "proxy", "category": "App"})
InitLog = log.WithFields(logrus.Fields{"component": "proxy", "category": "Init"})
CfgLog = log.WithFields(logrus.Fields{"component": "proxy", "category": "Cfg"})
MysqlLog = log.WithFields(logrus.Fields{"component": "proxy", "category": "Mysql"})
RedisLog = log.WithFields(logrus.Fields{"component": "proxy", "category": "Redis"})
RestLog = log.WithFields(logrus.Fields{"component": "proxy", "category": "Rest"})
CanalLog = log.WithFields(logrus.Fields{"component": "proxy", "category": "Canal"})
ProvLog = log.WithFields(logrus.Fields{"component": "proxy", "category": "Prov"})
}
func SetLogLevel(level logrus.Level) {
log.SetLevel(level)
}
func SetReportCaller(set bool) {
log.SetReportCaller(set)
}
+147
View File
@@ -0,0 +1,147 @@
package main
import (
"proxy/canal"
config2 "proxy/config"
"proxy/cron"
"proxy/provision"
_ "time"
l4g "github.com/sirupsen/logrus"
mysql "proxy/Nmysql"
rdb "proxy/Nredis"
rest "proxy/Nrestful"
tn "proxy/TelnetShellServer"
"proxy/logger"
)
/*
func initLog(cfg *rest.LogConf) {
if strings.Compare("file", cfg.Output) != 0 {
l4g.SetOutput(os.Stdout)
} else {
path := cfg.Path// "/var/log/pcf.log"
// log rotate
//`WithLinkName` 为最新的日志建立软连接
//`WithRotationTime` 设置日志分割的时间,隔多久分割一次
//WithMaxAge 和 WithRotationCount二者只能设置一个
// `WithMaxAge` 设置文件清理前的最长保存时间
// `WithRotationCount` 设置文件清理前最多保存的个数
//
// add a new log every 3 hours, with 30 days at most.
writer, _ := rotatelogs.New(
path+".%Y-%m-%d-%H:%M",
rotatelogs.WithLinkName(path),
//rotatelogs.WithMaxAge(time.Duration(cfg.MaxAge)*time.Hour),
//rotatelogs.WithRotationTime(time.Duration(cfg.RotationTime)*time.Hour),
rotatelogs.WithRotationTime(3 * time.Hour),
rotatelogs.WithRotationCount(uint(cfg.MaxAge)),
)
l4g.SetOutput(writer)
}
if strings.Compare("debug", cfg.Level) == 0 {
l4g.SetLevel(l4g.DebugLevel)
} else if strings.Compare("info", cfg.Level) == 0 {
l4g.SetLevel(l4g.InfoLevel)
} else if strings.Compare("warn", cfg.Level) == 0 {
l4g.SetLevel(l4g.WarnLevel)
} else if strings.Compare("error", cfg.Level) == 0 {
l4g.SetLevel(l4g.ErrorLevel)
}
//l4g.SetReportCaller(true)// useless
//l4g.SetFormatter(&l4g.TextFormatter{})
}*/
func check(err error, message string) {
if err != nil {
panic(err)
}
initLog.Debugf("%s", message)
}
// ******************************************************************
var initLog *l4g.Entry
func init() {
initLog = logger.InitLog
}
func setLogLevel(level string) {
if level != "" {
level, err := l4g.ParseLevel(level)
if err != nil {
initLog.Warnf("Log level [%s] is invalid, set to [info] level",
level)
logger.SetLogLevel(l4g.InfoLevel)
} else {
initLog.Infof("Log level is set to [%s] level", level)
logger.SetLogLevel(level)
}
} else {
initLog.Infoln("Log level not set. Default set to [info] level")
logger.SetLogLevel(l4g.InfoLevel)
}
logger.SetReportCaller(true)
}
// *********************************************************************************
//var cfgFile = flag.String("c", "", "selfcare proxy configure file.")
func main() {
// check if billing already running
/*var output, errout string
err, output, errout := rest.Shellout("pidof billing")
if err != nil {
fmt.Printf("Get pid of billing fail, err: %v\n", err)
} else {
ss := strings.Fields(output)
if len(ss) >= 2 {
fmt.Printf("Process billing is already running, pids[%s], exit!\n", output)
os.Exit(0)
} else {
fmt.Printf("First process of billing, stdout[%s], stderr[%s]!\n", output, errout)
}
}*/
//flag.Parse()
// read config
config := &config2.Config
err := config2.ReadConfig()
if err != nil {
initLog.Errorf("open config file error: %s", err)
return
} else {
initLog.Infof("config file: %v", config)
}
//initLog(&config.Log)
setLogLevel(config.Log.Level)
initLog.Infof("selfcare proxy start...\r\nconfig:[%v]", config)
if config.Rest.Enabled {
go rest.Connect_ocs(config.Rest.LocRzIp, config.Rest.OcsRzIp, config.Rest.LocRzPort, config.Rest.OcsRzPort)
go rest.StartHttpServer(config.Rest.HttpAddr)
}
go tn.Server(config.TelnetServer.Addr)
// temp disable======================
go rdb.NewRedisClient(config.RedisDb.NetType, config.RedisDb.Addr, config.RedisDb.Password, config.RedisDb.SentinelAddrs)
go mysql.OpenMysql(config.MysqlDb.Username, config.MysqlDb.Password, config.MysqlDb.Addr)
if config.CanalServer.Enabled {
go canal.CanalFsm(config.CanalServer.Addr, config.CanalServer.Username, config.CanalServer.Password)
}
//
if config.CronCfg.Enabled && (config.CronCfg.ClrExp != "" || config.CronCfg.NtfSms != "") {
cron.CronStart(config.CronCfg.ClrExp, config.CronCfg.NtfSms)
defer cron.CronStop()
}
go provision.ProvisionFsm()
select {}
}
+242
View File
@@ -0,0 +1,242 @@
package provision
import "C"
import (
"fmt"
"github.com/ircop/tclient"
"proxy/MsgDef"
"proxy/Nmysql"
rds "proxy/Nredis"
l4g "proxy/logger"
"strconv"
"strings"
"time"
. "proxy/config"
)
func ProvisionFsm() {
prov := &Config.Provision
if !prov.Enabled {
return
}
interval := prov.Interval
if interval <= 0 {
interval = 8
}
ticker := time.NewTicker(time.Second * time.Duration(interval))
defer ticker.Stop()
for {
<-ticker.C // wait for next tick
CheckNewProvision()
ProvisionBySmcli()
}
}
func TelnetClient() {
client := tclient.New(5, "manager", "manager", "")
err := client.Open("192.168.13.117", 4999)
if err != nil {
panic(err)
}
defer client.Close()
// you can omit this, or do auth stuff manually by calling `ReadUntil` with login/password prompts
/*out, err := client.Login("manager", "manager")
if err != nil {
panic(err)
}
fmt.Printf(out)*/
out, err := client.Cmd("connect hlr -srvip 192.168.13.118 -passwd 123456")
if err != nil {
panic(err)
}
fmt.Printf(out)
out, err = client.Cmd("connect auc -srvip 192.168.13.118 -passwd 123456")
if err != nil {
panic(err)
}
fmt.Printf(out)
out, err = client.Cmd("connect vms -srvip 192.168.4.221 -passwd 123456")
if err != nil {
panic(err)
}
fmt.Printf(out)
// smcli cmd
out, err = client.Cmd("disconnect hlr")
if err != nil {
panic(err)
}
fmt.Printf(out)
out, err = client.Cmd("disconnect vms")
if err != nil {
panic(err)
}
fmt.Printf(out)
//out, err = client.ReadUntil()
}
func CheckNewProvision() {
si, _ := Nmysql.QuerySyncMobileInfo()
if si != nil {
for _, v := range si {
if v.OperType == 2 {// replace imsi
oi, _ := Nmysql.QueryOldImsiInfo(v.ServiceNbr)
if oi != nil {
Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_DISCONNECT_ACCOUNT, Nmysql.NT_HSS, strconv.Itoa(oi.PrdInstId), "delete subscriber -imsi " + v.Imsi)
Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_DISCONNECT_ACCOUNT, Nmysql.NT_AUC, strconv.Itoa(oi.PrdInstId),"delete aucSubscriber -imsi " + v.Imsi)
Nmysql.UpdateSyncMobileState(oi.PreId, 6)
crtCmd := fmt.Sprintf("create subscriber -imsi %s -msisdn %s -eps_user_tpl def_eps -impi %s@ims.mnc010.mcc505.3gppnetwork.org",
v.Imsi, v.ServiceNbr, v.Imsi)
Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_HSS, strconv.Itoa(v.PrdInstId), crtCmd)
if v.Opc == "" {
crtCmd = fmt.Sprintf("create aucSubscriber -imsi %s -ki %s",
v.Imsi, v.Ki)
} else {
crtCmd = fmt.Sprintf("create aucSubscriber -imsi %s -ki %s -opc %s",
v.Imsi, v.Ki, v.Opc)
}
Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_AUC, strconv.Itoa(v.PrdInstId), crtCmd)
Nmysql.UpdateSyncMobileState(v.PreId, 2)
}
} else {
crtCmd := fmt.Sprintf("create subscriber -imsi %s -msisdn %s -eps_user_tpl def_eps -impi %s@ims.mnc010.mcc505.3gppnetwork.org",
v.Imsi, v.ServiceNbr, v.Imsi)
Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_HSS, strconv.Itoa(v.PrdInstId), crtCmd)
if v.Opc == "" {
crtCmd = fmt.Sprintf("create aucSubscriber -imsi %s -ki %s",
v.Imsi, v.Ki)
} else {
crtCmd = fmt.Sprintf("create aucSubscriber -imsi %s -ki %s -opc %s",
v.Imsi, v.Ki, v.Opc)
}
Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_AUC, strconv.Itoa(v.PrdInstId), crtCmd)
if v.VmsFlag > 0 {
crtCmd := fmt.Sprintf("create vmsSubscriber -msisdn %s",
v.ServiceNbr)
Nmysql.AddSmcliCmd2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_VMS, strconv.Itoa(v.PrdInstId), crtCmd)
}
// add ocs success
crtCmd = fmt.Sprintf("create ppsSubscriber -msisdn %s -PRE_ID %d",
v.ServiceNbr, v.PreId)
Nmysql.AddSmcliCmdSucc2Mysql(Nmysql.CT_CREATE_SUB, Nmysql.NT_OCS, strconv.Itoa(v.PrdInstId), crtCmd)
var synMobile = MsgDef.ChgSyncMobile{PreId: v.PreId, OperType: v.OperType, State: 1, ServiceNbr: v.ServiceNbr, CustId: v.CustId, AcctId: v.AcctId,
PrdInstId: v.PrdInstId, MobileType: v.MobileType, BirthDate: v.BirthDate, Balance: v.Balance, BalanceExpDate: v.BalanceExpDate, OfrId: v.OfrId,
Imsi: v.Imsi, Ki: v.Ki, Opc: v.Opc, VmsFlag: v.VmsFlag, ExpDate: v.ExpDate, CugId: v.CugId}
rds.RdbSetCreateAcctRecord(&synMobile)
Nmysql.UpdateSyncMobileState(v.PreId, 2)
}
}
}
}
func ProvisionBySmcli() {
si, _ := Nmysql.QuerySyncCnCmd()
if si != nil {
prv := &Config.Provision
SmcliClient := tclient.New(prv.ReadTimout, prv.Username, prv.Password, "")
err := SmcliClient.Open(prv.EmsIp, prv.EmsPort)
if err != nil {
l4g.ProvLog.Errorf("Smcli Client Open fail: %v", err)
return
}
defer SmcliClient.Close()
var out string
if prv.ConnectHss != "" {
out, err = SmcliClient.Cmd(prv.ConnectHss)
if err != nil {
l4g.ProvLog.Errorf("Smcli Client Cmd[%s] err: %v", prv.ConnectHss, err)
return
}
l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", prv.ConnectHss, out)
if !strings.Contains(out, "success") {// 0000:Command successful
l4g.ProvLog.Warnf("Smcli Cmd[%s] not success", prv.ConnectHss)
return
}
}
if prv.ConnectAuc != "" {
out, err = SmcliClient.Cmd(prv.ConnectAuc)
if err != nil {
l4g.ProvLog.Errorf("Smcli Client Cmd[%s] err: %v", prv.ConnectAuc, err)
goto ReleaseConnnet
}
l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", prv.ConnectAuc, out)
if !strings.Contains(out, "success") {// 0000:Command successful
l4g.ProvLog.Warnf("Smcli Cmd[%s] not success", prv.ConnectAuc)
goto ReleaseConnnet
}
}
if prv.ConnectVms != "" {
out, err = SmcliClient.Cmd(prv.ConnectVms)
if err != nil {
l4g.ProvLog.Errorf("Smcli Client Cmd[%s] err: %v", prv.ConnectVms, err)
goto ReleaseConnHss
}
l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", prv.ConnectVms, out)
if !strings.Contains(out, "success") {// 0000:Command successful
l4g.ProvLog.Warnf("Smcli Cmd[%s] not success", prv.ConnectVms)
goto ReleaseConnHss
}
}
// smcli cmd
for _, v := range si {
if v.Command != "" {
out, err = SmcliClient.Cmd(v.Command)
if err != nil {
l4g.ProvLog.Errorf("Smcli Client Cmd[%s] err: %v", v.Command, err)
Nmysql.UpdateCnCmdResult(v.Id, 2, 2, "timeout")
goto ReleaseConnnet
}
l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", v.Command, out)
if !strings.Contains(out, "success") {// 0000:Command successful
l4g.ProvLog.Warnf("Smcli Cmd[%s] not success", v.Command)
Nmysql.UpdateCnCmdResult(v.Id, 2, 2, out)
goto ReleaseConnnet
} else {
l4g.ProvLog.Infof("Smcli Cmd[%s] success", v.Command)
Nmysql.UpdateCnCmdResult(v.Id, 2, 1, out)
}
}
}
ReleaseConnnet:
if prv.DisconnectVms != "" {
out, err = SmcliClient.Cmd(prv.DisconnectVms)
if err != nil {
l4g.ProvLog.Errorf("Smcli Client Cmd[%s] fail: %v", prv.DisconnectVms, err)
return
}
l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", prv.DisconnectVms, out)
}
ReleaseConnHss:
if prv.DisconnectHss != "" {
out, err = SmcliClient.Cmd(prv.DisconnectHss)
if err != nil {
l4g.ProvLog.Errorf("Smcli Client Cmd[%s] fail: %v", prv.DisconnectHss, err)
return
}
l4g.ProvLog.Infof("Smcli Client Cmd[%s] output: %s", prv.DisconnectHss, out)
}
}
}
+237
View File
@@ -0,0 +1,237 @@
package redis
import (
"context"
"fmt"
rds "github.com/go-redis/redis/v8"
l4g "proxy/logger" //"github.com/sirupsen/logrus"
"strconv"
"strings"
//"strconv"
//. "../MsgDef"
)
var ctx = context.Background()
var rdb *rds.Client
func NewRedisClient(netType, addr string) {
rdb = rds.NewClient(&rds.Options{
Network: netType,// The network type, either tcp or unix. Default is tcp.
Addr: addr,// can be: /var/run/redis/redis-server.sock???
Password: "", // no password set
DB: 0, // use default DB
PoolSize: 5,
})
pong, err := rdb.Ping(ctx).Result()
if err != nil {
l4g.RedisLog.Errorf("%v, err: %v", pong, err)// Output: PONG <nil>
} else {
l4g.RedisLog.Debugf("%v", pong)// Output: PONG <nil>
}
return
}
type PcfUsrData struct {
Msisdn string `redis:"msisdn"`
PccRules string `redis:"pcc_rules"`
}
func MmlAddPcfUser(params []string) (rsp string) {
var imsi, msisdn, pccRules string
for _, val := range params {
if strings.HasPrefix(val, "imsi=") {
imsi = val[len("imsi="):]
} else if strings.HasPrefix(val, "msisdn=") {
msisdn = val[len("msisdn="):]
} else if strings.HasPrefix(val, "pcc_rules=") {
pccRules = val[len("pcc_rules="):]
}
}
err := rdb.HMSet(ctx, "pcfUser:"+imsi, "msisdn", msisdn, "pcc_rules", pccRules).Err()
if err != nil {
rsp = fmt.Sprintf("HMSet pcfUser:%s, err: %v", imsi, err)
}
return rsp
}
func MmlModPcfUser(params []string) (rsp string) {
var imsi, msisdn, pccRules string
for _, val := range params {
if strings.HasPrefix(val, "imsi=") {
imsi = val[len("imsi="):]
} else if strings.HasPrefix(val, "msisdn=") {
msisdn = val[len("msisdn="):]
} else if strings.HasPrefix(val, "pcc_rules=") {
pccRules = val[len("pcc_rules="):]
}
}
err := rdb.HMSet(ctx, "pcfUser:"+imsi, "msisdn", msisdn, "pcc_rules", pccRules).Err()
if err != nil {
rsp = fmt.Sprintf("HMSet pcfUser:%s, err: %v", imsi, err)
}
return rsp
}
func MmlDelPcfUser(params []string) (rsp string) {
var imsi string
for _, val := range params {
if strings.HasPrefix(val, "imsi=") {
imsi = val[len("imsi="):]
}
}
err := rdb.Del(ctx, "pcfUser:"+imsi).Err()
if err != nil {
rsp = fmt.Sprintf("Del pcfUser:%s, err: %v", imsi, err)
}
return rsp
}
func MmlDspPcfUser(params []string) (rsp string) {
var imsi string
for _, val := range params {
if strings.HasPrefix(val, "imsi=") {
imsi = val[len("imsi="):]
}
}
res := rdb.HGetAll(ctx, "pcfUser:"+imsi)
err := res.Err()
if err != nil {
rsp = fmt.Sprintf("HGetAll pcfUser:%s, err: %v", imsi, err)
return rsp
}
// Scan the results into the struct.
var usrData PcfUsrData
if err = res.Scan(&usrData); err != nil {
rsp = fmt.Sprintf("HGetAll Scan pcfUser:%s, err: %v", imsi, err)
} else {
rsp = fmt.Sprintf("pcfUser:imsi=%s, [%v]", imsi, usrData)
}
return rsp
}
func GetPcfUsrDataByImsi(imsi string) (usrData PcfUsrData, err error) {
res := rdb.HGetAll(ctx, "pcfUser:"+imsi)
err = res.Err()
if err != nil {
l4g.RedisLog.Errorf("HGetAll pcfUser:%s, err: %v", imsi, err)
return
}
// Scan the results into the struct.
if err = res.Scan(&usrData); err != nil {
l4g.RedisLog.Errorf("HGetAll Scan pcfUser:%s, err: %v", imsi, err)
return
} else {
return
}
}
func GetPcfUsrPccRulesByImsi(imsi string) (pccRules string, err error) {
res := rdb.HGetAll(ctx, "pcfUser:"+imsi)
err = res.Err()
if err != nil {
l4g.RedisLog.Errorf("HGetAll pcfUser:%s, err: %v", imsi, err)
return "", err
}
// Scan the results into the struct.
var usrData PcfUsrData
if err = res.Scan(&usrData); err != nil {
l4g.RedisLog.Errorf("HGetAll Scan pcfUser:%s, err: %v", imsi, err)
return "", err
} else {
return usrData.PccRules, nil
}
}
func MmlBadPcfUser(params []string) (rsp string) {
var pccRules string
var startImsi, startMsisdn int64
var subNum int64= 0
for _, val := range params {
if strings.HasPrefix(val, "start_imsi=") {
startImsi, _ = strconv.ParseInt(val[len("start_imsi="):], 10, 64)
} else if strings.HasPrefix(val, "start_msisdn=") {
startMsisdn, _ = strconv.ParseInt(val[len("start_msisdn="):], 10, 64)
} else if strings.HasPrefix(val, "pcc_rules=") {
pccRules = val[len("pcc_rules="):]
} else if strings.HasPrefix(val, "sub_num=") {
subNum, _ = strconv.ParseInt(val[len("sub_num="):], 10, 64)
}
}
var i int64= 0
for i=0; i<subNum; i++ {
var imsi, msisdn string
imsi = fmt.Sprintf("imsi=%d", startImsi+i)
msisdn = fmt.Sprintf("msisdn=%d", startMsisdn+i)
mmlParams := []string{imsi, msisdn, pccRules}
MmlAddPcfUser(mmlParams)
}
rsp = "Command OK"
return
}
func MmlBdePcfUser(params []string) (rsp string) {
var startImsi int64= 0
var subNum int64= 0
for _, val := range params {
if strings.HasPrefix(val, "imsi=") {
startImsi, _ = strconv.ParseInt(val[len("start_imsi="):], 10, 64)
} else if strings.HasPrefix(val, "sub_num=") {
subNum, _ = strconv.ParseInt(val[len("sub_num="):], 10, 64)
}
}
var i int64= 0
for i=0; i<subNum; i++ {
var imsi string
imsi = fmt.Sprintf("imsi=%d", startImsi+i)
mmlParams := []string{imsi}
MmlDelPcfUser(mmlParams)
}
rsp = "Command OK"
return
}
func HandleMmlCmdRequest(cmd []string) string {
paramStr := strings.TrimPrefix(cmd[1], "pcfuser:")
params := strings.Split(paramStr, ",")
switch cmd[0] {
case "add":
return MmlAddPcfUser(params)
case "mod":
return MmlModPcfUser(params)
case "del":
return MmlDelPcfUser(params)
case "dsp":
return MmlDspPcfUser(params)
case "bad":
return MmlBadPcfUser(params)
case "bde":
return MmlBdePcfUser(params)
default:
return "Unkown MML CMD"
}
}
+14
View File
@@ -0,0 +1,14 @@
# Toolchain
# Goland project folder
.idea/
# Visual Studio Code
.vscode/
# emacs/vim
GPATH
GRTAGS
GTAGS
TAGS
tags
cscope.*
# mac
.DS_Store
+289
View File
@@ -0,0 +1,289 @@
# This file contains all available configuration options
# with their default values.
# options for analysis running
run:
# default concurrency is a available CPU number
concurrency: 4
# timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 1m
# exit code when at least one issue was found, default is 1
issues-exit-code: 1
# include test files or not, default is true
tests: false
# list of build tags, all linters use it. Default is empty list.
build-tags:
# which dirs to skip: issues from them won't be reported;
# can use regexp here: generated.*, regexp is applied on full path;
# default value is empty list, but default dirs are skipped independently
# from this option's value (see skip-dirs-use-default).
# "/" will be replaced by current OS file path separator to properly work
# on Windows.
skip-dirs:
# default is true. Enables skipping of directories:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
skip-dirs-use-default: true
# which files to skip: they will be analyzed, but issues from them
# won't be reported. Default value is empty list, but there is
# no need to include all autogenerated files, we confidently recognize
# autogenerated files. If it's not please let us know.
# "/" will be replaced by current OS file path separator to properly work
# on Windows.
skip-files:
- "api_.*\\.go$"
- "model_.*\\.go$"
- "routers.go"
- "client.go"
- "configuration.go"
- "nas.go"
# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
# If invoked with -mod=readonly, the go command is disallowed from the implicit
# automatic updating of go.mod described above. Instead, it fails when any changes
# to go.mod are needed. This setting is most useful to check that go.mod does
# not need updates, such as in a continuous integration and testing system.
# If invoked with -mod=vendor, the go command assumes that the vendor
# directory holds the correct copies of dependencies and ignores
# the dependency descriptions in go.mod.
#modules-download-mode: readonly|release|vendor
# Allow multiple parallel golangci-lint instances running.
# If false (default) - golangci-lint acquires file lock on start.
allow-parallel-runners: true
# output configuration options
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
format: colored-line-number
# print lines of code with issue, default is true
print-issued-lines: true
# print linter name in the end of issue text, default is true
print-linter-name: true
# make issues output unique by line, default is true
uniq-by-line: true
# all available settings of specific linters
linters-settings:
errcheck:
# report about not checking of errors in type assertions: `a := b.(MyStruct)`;
# default is false: such cases aren't reported by default.
check-type-assertions: false
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
# default is false: such cases aren't reported by default.
check-blank: true
# [deprecated] comma-separated list of pairs of the form pkg:regex
# the regex is used to ignore names within pkg. (default "fmt:.*").
# see https://github.com/kisielk/errcheck#the-deprecated-method for details
#ignore: fmt:.*,io/ioutil:^Read.*
# path to a file containing a list of functions to exclude from checking
# see https://github.com/kisielk/errcheck#excluding-functions for details
#exclude: /path/to/file.txt
funlen:
lines: 60
statements: 40
gocognit:
# minimal code complexity to report, 30 by default (but we recommend 10-20)
min-complexity: 10
nestif:
# minimal complexity of if statements to report, 5 by default
min-complexity: 4
goconst:
# minimal length of string constant, 3 by default
min-len: 3
# minimal occurrences count to trigger, 3 by default
min-occurrences: 3
gocritic:
# Which checks should be enabled; can't be combined with 'disabled-checks';
# See https://go-critic.github.io/overview#checks-overview
# To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run`
# By default list of stable checks is used.
enabled-checks:
#- rangeValCopy
# Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty
disabled-checks:
- regexpMust
# Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.
# Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags".
enabled-tags:
- performance
disabled-tags:
- experimental
settings: # settings passed to gocritic
captLocal: # must be valid enabled check name
paramsOnly: true
rangeValCopy:
sizeThreshold: 32
gocyclo:
# minimal code complexity to report, 30 by default (but we recommend 10-20)
min-complexity: 10
godox:
# report any comments starting with keywords, this is useful for TODO or FIXME comments that
# might be left in the code accidentally and should be resolved before merging
keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting
#- TODO
- FIXME
- BUG
#- NOTE
#- OPTIMIZE # marks code that should be optimized before merging
#- HACK # marks hack-arounds that should be removed before merging
- XXX # Fatal! Important problem
gofmt:
# simplify code: gofmt with `-s` option, true by default
simplify: true
goimports:
# put imports beginning with prefix after 3rd-party packages;
# it's a comma-separated list of prefixes
local-prefixes: github.com/org/project
golint:
# minimal confidence for issues, default is 0.8
min-confidence: 0.8
gomnd:
settings:
mnd:
# the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.
checks: argument,case,condition,operation,return,assign
gomodguard:
allowed:
modules: # List of allowed modules
# - gopkg.in/yaml.v2
domains: # List of allowed module domains
# - golang.org
blocked:
modules: # List of blocked modules
# - github.com/uudashr/go-module: # Blocked module
# recommendations: # Recommended modules that should be used instead (Optional)
# - golang.org/x/mod
# reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional)
versions: # List of blocked module version constraints
# - github.com/mitchellh/go-homedir: # Blocked module with version constraint
# version: "< 1.1.0" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons
# reason: "testing if blocked version constraint works." # Reason why the version constraint exists. (Optional)
govet:
# report about shadowed variables
check-shadowing: true
# settings per analyzer
settings:
printf: # analyzer name, run `go tool vet help` to see all analyzers
funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
# enable or disable analyzers by name
enable:
- atomicalign
enable-all: false
disable:
- shadow
disable-all: false
depguard:
list-type: blacklist
include-go-root: false
packages:
- github.com/sirupsen/logrus
packages-with-error-message:
# specify an error message to output when a blacklisted package is used
- github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
lll:
# max line length, lines longer will be reported. Default is 120.
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
line-length: 120
# tab width in spaces. Default to 1.
tab-width: 1
maligned:
# print struct with more effective memory layout or not, false by default
suggest-new: true
nakedret:
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
max-func-lines: 30
testpackage:
# regexp pattern to skip files
skip-regexp: (export|internal)_test\.go
unused:
# treat code as a program (not a library) and report unused exported identifiers; default is false.
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
# with golangci-lint call it on a directory with the changed file.
check-exported: false
whitespace:
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
custom:
# Each custom linter should have a unique name.
linters:
enable:
- gofmt
- govet
- errcheck
- staticcheck
- unused
- gosimple
- structcheck
- varcheck
- ineffassign
- deadcode
- typecheck
# Additional
- lll
- godox
# - gomnd
#- maligned
#- nestif
#- goconst
#- gocognit
- nakedret
#disable-all: false
fast: true
issues:
# List of regexps of issue texts to exclude, empty list by default.
# But independently from this option we use default exclude patterns,
# it can be disabled by `exclude-use-default: false`. To list all
# excluded by default patterns execute `golangci-lint run --help`
exclude:
# Excluding configuration per-path, per-linter, per-text and per-source
exclude-rules:
# Exclude some linters from running on tests files.
# Independently from option `exclude` we use default exclude patterns,
# it can be disabled by this option. To list all
# excluded by default patterns execute `golangci-lint run --help`.
# Default value for this option is true.
exclude-use-default: false
# The default value is false. If set to true exclude and exclude-rules
# regular expressions become case sensitive.
exclude-case-sensitive: false
# The list of ids of default excludes to include or disable. By default it's empty.
include:
#- EXC0002 # disable excluding of issues about comments from golint
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
#max-issues-per-linter: 0
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
#max-same-issues: 0
# Show only new issues: if there are unstaged changes or untracked files,
# only those changes are analyzed, else only changes in HEAD~ are analyzed.
# It's a super-useful option for integration of golangci-lint into existing
# large codebase. It's not practical to fix all existing issues at the moment
# of integration: much better don't allow issues in new code.
# Default is false.
new: false
# Show only new issues created after git revision `REV`
new-from-rev: ""
# Show only new issues created in git patch with set file path.
#new-from-patch: path/to/patch/file
severity:
# Default value is empty string.
# Set the default severity for issues. If severity rules are defined and the issues
# do not match or no severity is provided to the rule this will be the default
# severity applied. Severities should match the supported severity names of the
# selected out format.
# - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity
# - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity
# - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
default-severity: error
# The default value is false.
# If set to true severity-rules regular expressions become case sensitive.
case-sensitive: false
# Default value is empty list.
# When a list of severity rules are provided, severity information will be added to lint
# issues. Severity rules have the same filtering capability as exclude rules except you
# are allowed to specify one matcher per severity rule.
# Only affects out formats that support setting severity information.
rules:
- linters:
- gomnd
severity: ignore
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 Communication Service/Software Laboratory, National Chiao Tung University
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+63
View File
@@ -0,0 +1,63 @@
package logger_conf
import (
"log"
"os"
"strconv"
)
//var Free5gcLogDir string = path_util.Free5gcPath("free5gc/log") + "/"
var Free5gcLogDir string = "/var/log/"
//var LibLogDir string = Free5gcLogDir + "lib/"
//var NfLogDir string = Free5gcLogDir + "nf/"
var Free5gcLogFile string = Free5gcLogDir + "selfcareproxy.log"
func init() {//InitLoggerConf(dir, filename string) {//init() {
//Free5gcLogDir = dir
//Free5gcLogFile = dir + filename
/*if err := os.MkdirAll(LibLogDir, 0775); err != nil {
log.Printf("Mkdir %s failed: %+v", LibLogDir, err)
}
if err := os.MkdirAll(NfLogDir, 0775); err != nil {
log.Printf("Mkdir %s failed: %+v", NfLogDir, err)
}*/
// Create log file or if it already exist, check if user can access it
f, fileOpenErr := os.OpenFile(Free5gcLogFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
if fileOpenErr != nil {
// user cannot access it.
log.Printf("Cannot Open %s\n", Free5gcLogFile)
} else {
// user can access it
if err := f.Close(); err != nil {
log.Printf("File %s cannot been closed\n", Free5gcLogFile)
}
}
sudoUID, errUID := strconv.Atoi(os.Getenv("SUDO_UID"))
sudoGID, errGID := strconv.Atoi(os.Getenv("SUDO_GID"))
if errUID == nil && errGID == nil {
// if using sudo to run the program, errUID will be nil and sudoUID will get the uid who run sudo
// else errUID will not be nil and sudoUID will be nil
// If user using sudo to run the program and create log file, log will own by root,
// here we change own to user so user can view and reuse the file
if err := os.Chown(Free5gcLogDir, sudoUID, sudoGID); err != nil {
log.Printf("Dir %s chown to %d:%d error: %v\n", Free5gcLogDir, sudoUID, sudoGID, err)
}
/*if err := os.Chown(LibLogDir, sudoUID, sudoGID); err != nil {
log.Printf("Dir %s chown to %d:%d error: %v\n", LibLogDir, sudoUID, sudoGID, err)
}
if err := os.Chown(NfLogDir, sudoUID, sudoGID); err != nil {
log.Printf("Dir %s chown to %d:%d error: %v\n", NfLogDir, sudoUID, sudoGID, err)
}*/
if fileOpenErr == nil {
if err := os.Chown(Free5gcLogFile, sudoUID, sudoGID); err != nil {
log.Printf("File %s chown to %d:%d error: %v\n", Free5gcLogFile, sudoUID, sudoGID, err)
}
}
}
}
+15
View File
@@ -0,0 +1,15 @@
# Toolchain
# Goland project folder
.idea/
# Visual Studio Code
.vscode/
# emacs/vim
GPATH
GRTAGS
GTAGS
TAGS
tags
cscope.*
# mac
.DS_Store
+289
View File
@@ -0,0 +1,289 @@
# This file contains all available configuration options
# with their default values.
# options for analysis running
run:
# default concurrency is a available CPU number
concurrency: 4
# timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 1m
# exit code when at least one issue was found, default is 1
issues-exit-code: 1
# include test files or not, default is true
tests: false
# list of build tags, all linters use it. Default is empty list.
build-tags:
# which dirs to skip: issues from them won't be reported;
# can use regexp here: generated.*, regexp is applied on full path;
# default value is empty list, but default dirs are skipped independently
# from this option's value (see skip-dirs-use-default).
# "/" will be replaced by current OS file path separator to properly work
# on Windows.
skip-dirs:
# default is true. Enables skipping of directories:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
skip-dirs-use-default: true
# which files to skip: they will be analyzed, but issues from them
# won't be reported. Default value is empty list, but there is
# no need to include all autogenerated files, we confidently recognize
# autogenerated files. If it's not please let us know.
# "/" will be replaced by current OS file path separator to properly work
# on Windows.
skip-files:
- "api_.*\\.go$"
- "model_.*\\.go$"
- "routers.go"
- "client.go"
- "configuration.go"
- "nas.go"
# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
# If invoked with -mod=readonly, the go command is disallowed from the implicit
# automatic updating of go.mod described above. Instead, it fails when any changes
# to go.mod are needed. This setting is most useful to check that go.mod does
# not need updates, such as in a continuous integration and testing system.
# If invoked with -mod=vendor, the go command assumes that the vendor
# directory holds the correct copies of dependencies and ignores
# the dependency descriptions in go.mod.
#modules-download-mode: readonly|release|vendor
# Allow multiple parallel golangci-lint instances running.
# If false (default) - golangci-lint acquires file lock on start.
allow-parallel-runners: true
# output configuration options
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
format: colored-line-number
# print lines of code with issue, default is true
print-issued-lines: true
# print linter name in the end of issue text, default is true
print-linter-name: true
# make issues output unique by line, default is true
uniq-by-line: true
# all available settings of specific linters
linters-settings:
errcheck:
# report about not checking of errors in type assertions: `a := b.(MyStruct)`;
# default is false: such cases aren't reported by default.
check-type-assertions: false
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
# default is false: such cases aren't reported by default.
check-blank: true
# [deprecated] comma-separated list of pairs of the form pkg:regex
# the regex is used to ignore names within pkg. (default "fmt:.*").
# see https://github.com/kisielk/errcheck#the-deprecated-method for details
#ignore: fmt:.*,io/ioutil:^Read.*
# path to a file containing a list of functions to exclude from checking
# see https://github.com/kisielk/errcheck#excluding-functions for details
#exclude: /path/to/file.txt
funlen:
lines: 60
statements: 40
gocognit:
# minimal code complexity to report, 30 by default (but we recommend 10-20)
min-complexity: 10
nestif:
# minimal complexity of if statements to report, 5 by default
min-complexity: 4
goconst:
# minimal length of string constant, 3 by default
min-len: 3
# minimal occurrences count to trigger, 3 by default
min-occurrences: 3
gocritic:
# Which checks should be enabled; can't be combined with 'disabled-checks';
# See https://go-critic.github.io/overview#checks-overview
# To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run`
# By default list of stable checks is used.
enabled-checks:
#- rangeValCopy
# Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty
disabled-checks:
- regexpMust
# Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.
# Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags".
enabled-tags:
- performance
disabled-tags:
- experimental
settings: # settings passed to gocritic
captLocal: # must be valid enabled check name
paramsOnly: true
rangeValCopy:
sizeThreshold: 32
gocyclo:
# minimal code complexity to report, 30 by default (but we recommend 10-20)
min-complexity: 10
godox:
# report any comments starting with keywords, this is useful for TODO or FIXME comments that
# might be left in the code accidentally and should be resolved before merging
keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting
#- TODO
- FIXME
- BUG
#- NOTE
#- OPTIMIZE # marks code that should be optimized before merging
#- HACK # marks hack-arounds that should be removed before merging
- XXX # Fatal! Important problem
gofmt:
# simplify code: gofmt with `-s` option, true by default
simplify: true
goimports:
# put imports beginning with prefix after 3rd-party packages;
# it's a comma-separated list of prefixes
local-prefixes: github.com/org/project
golint:
# minimal confidence for issues, default is 0.8
min-confidence: 0.8
gomnd:
settings:
mnd:
# the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.
checks: argument,case,condition,operation,return,assign
gomodguard:
allowed:
modules: # List of allowed modules
# - gopkg.in/yaml.v2
domains: # List of allowed module domains
# - golang.org
blocked:
modules: # List of blocked modules
# - github.com/uudashr/go-module: # Blocked module
# recommendations: # Recommended modules that should be used instead (Optional)
# - golang.org/x/mod
# reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional)
versions: # List of blocked module version constraints
# - github.com/mitchellh/go-homedir: # Blocked module with version constraint
# version: "< 1.1.0" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons
# reason: "testing if blocked version constraint works." # Reason why the version constraint exists. (Optional)
govet:
# report about shadowed variables
check-shadowing: true
# settings per analyzer
settings:
printf: # analyzer name, run `go tool vet help` to see all analyzers
funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
# enable or disable analyzers by name
enable:
- atomicalign
enable-all: false
disable:
- shadow
disable-all: false
depguard:
list-type: blacklist
include-go-root: false
packages:
- github.com/sirupsen/logrus
packages-with-error-message:
# specify an error message to output when a blacklisted package is used
- github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
lll:
# max line length, lines longer will be reported. Default is 120.
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
line-length: 120
# tab width in spaces. Default to 1.
tab-width: 1
maligned:
# print struct with more effective memory layout or not, false by default
suggest-new: true
nakedret:
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
max-func-lines: 30
testpackage:
# regexp pattern to skip files
skip-regexp: (export|internal)_test\.go
unused:
# treat code as a program (not a library) and report unused exported identifiers; default is false.
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
# with golangci-lint call it on a directory with the changed file.
check-exported: false
whitespace:
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
custom:
# Each custom linter should have a unique name.
linters:
enable:
- gofmt
- govet
- errcheck
- staticcheck
- unused
- gosimple
- structcheck
- varcheck
- ineffassign
- deadcode
- typecheck
# Additional
- lll
- godox
# - gomnd
#- maligned
#- nestif
#- goconst
#- gocognit
- nakedret
#disable-all: false
fast: true
issues:
# List of regexps of issue texts to exclude, empty list by default.
# But independently from this option we use default exclude patterns,
# it can be disabled by `exclude-use-default: false`. To list all
# excluded by default patterns execute `golangci-lint run --help`
exclude:
# Excluding configuration per-path, per-linter, per-text and per-source
exclude-rules:
# Exclude some linters from running on tests files.
# Independently from option `exclude` we use default exclude patterns,
# it can be disabled by this option. To list all
# excluded by default patterns execute `golangci-lint run --help`.
# Default value for this option is true.
exclude-use-default: false
# The default value is false. If set to true exclude and exclude-rules
# regular expressions become case sensitive.
exclude-case-sensitive: false
# The list of ids of default excludes to include or disable. By default it's empty.
include:
#- EXC0002 # disable excluding of issues about comments from golint
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
#max-issues-per-linter: 0
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
#max-same-issues: 0
# Show only new issues: if there are unstaged changes or untracked files,
# only those changes are analyzed, else only changes in HEAD~ are analyzed.
# It's a super-useful option for integration of golangci-lint into existing
# large codebase. It's not practical to fix all existing issues at the moment
# of integration: much better don't allow issues in new code.
# Default is false.
new: false
# Show only new issues created after git revision `REV`
new-from-rev: ""
# Show only new issues created in git patch with set file path.
#new-from-patch: path/to/patch/file
severity:
# Default value is empty string.
# Set the default severity for issues. If severity rules are defined and the issues
# do not match or no severity is provided to the rule this will be the default
# severity applied. Severities should match the supported severity names of the
# selected out format.
# - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity
# - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity
# - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
default-severity: error
# The default value is false.
# If set to true severity-rules regular expressions become case sensitive.
case-sensitive: false
# Default value is empty list.
# When a list of severity rules are provided, severity information will be added to lint
# issues. Severity rules have the same filtering capability as exclude rules except you
# are allowed to specify one matcher per severity rule.
# Only affects out formats that support setting severity information.
rules:
- linters:
- gomnd
severity: ignore
+9
View File
@@ -0,0 +1,9 @@
# Change Log
---
2020-03-xx-xx
---
- Implemented enchacements:
- Fixed bugs:
- Closed issues:
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 Communication Service/Software Laboratory, National Chiao Tung University
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+42
View File
@@ -0,0 +1,42 @@
package logger_util
type Logger struct {
AMF *LogSetting `yaml:"AMF"`
AUSF *LogSetting `yaml:"AUSF"`
N3IWF *LogSetting `yaml:"N3IWF"`
NRF *LogSetting `yaml:"NRF"`
NSSF *LogSetting `yaml:"NSSF"`
PCF *LogSetting `yaml:"PCF"`
SMF *LogSetting `yaml:"SMF"`
UDM *LogSetting `yaml:"UDM"`
UDR *LogSetting `yaml:"UDR"`
NEF *LogSetting `yaml:"NEF"`
WEBUI *LogSetting `yaml:"WEBUI"`
Aper *LogSetting `yaml:"Aper"`
CommonConsumerTest *LogSetting `yaml:"CommonConsumerTest"`
FSM *LogSetting `yaml:"FSM"`
MongoDBLibrary *LogSetting `yaml:"MongoDBLibrary"`
NAS *LogSetting `yaml:"NAS"`
NGAP *LogSetting `yaml:"NGAP"`
OpenApi *LogSetting `yaml:"OpenApi"`
NamfCommunication *LogSetting `yaml:"NamfCommunication"`
NamfEventExposure *LogSetting `yaml:"NamfEventExposure"`
NnssfNSSAIAvailability *LogSetting `yaml:"NnssfNSSAIAvailability"`
NnssfNSSelection *LogSetting `yaml:"NnssfNSSelection"`
NsmfEventExposure *LogSetting `yaml:"NsmfEventExposure"`
NsmfPDUSession *LogSetting `yaml:"NsmfPDUSession"`
NudmEventExposure *LogSetting `yaml:"NudmEventExposure"`
NudmParameterProvision *LogSetting `yaml:"NudmParameterProvision"`
NudmSubscriberDataManagement *LogSetting `yaml:"NudmSubscriberDataManagement"`
NudmUEAuthentication *LogSetting `yaml:"NudmUEAuthentication"`
NudmUEContextManagement *LogSetting `yaml:"NudmUEContextManagement"`
NudrDataRepository *LogSetting `yaml:"NudrDataRepository"`
PathUtil *LogSetting `yaml:"PathUtil"`
PFCP *LogSetting `yaml:"PFCP"`
}
type LogSetting struct {
DebugLevel string `yaml:"debugLevel"`
ReportCaller bool `yaml:"ReportCaller"`
}
+174
View File
@@ -0,0 +1,174 @@
package logger_util
import (
"bytes"
"fmt"
"log"
"os"
"path"
"runtime"
formatter "github.com/antonfisher/nested-logrus-formatter"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
)
var(//const (
maxLogFileSize int64= 1024*1024*128
maxLogFile = 8
)
func SetLoggerSizeAndNum(size, num int) {
maxLogFileSize = 1024*1024*int64(size)
maxLogFile = num
}
type FileHook struct {
file *os.File
flag int
chmod os.FileMode
formatter *formatter.Formatter
}
func renameFiles(file string) {
var oldFileName, newFileName string
var i int
for i = maxLogFile-1; i > 0; i-- {
if i > 1 {
oldFileName = fmt.Sprintf("%s.%d",file, i-1)
} else {
oldFileName = file
}
if _, err := os.Stat(oldFileName); err == nil {
newFileName = fmt.Sprintf("%s.%d", file, i)
os.Rename(oldFileName, newFileName)
}
}
}
func NewFileHook(file string, flag int, chmod os.FileMode) (*FileHook, error) {
plainFormatter := &formatter.Formatter{
TimestampFormat: "2006-01-02 15:04:05.000",
TrimMessages: true,
NoColors: true,
NoFieldsColors: true,
NoFieldsSpace: true,
HideKeys: true,
FieldsOrder: []string{"component", "category", "remote_addr"},
CallerFirst: true,
CustomCallerFormatter: func(f *runtime.Frame) string {
file := path.Base(f.File)
if len(file) > 25 {
file = file[len(file)-25:]
}
return fmt.Sprintf(" %15s:%04d", file, f.Line)
},
}
logFile, err := os.OpenFile(file, flag, chmod)
if err != nil {
fmt.Fprintf(os.Stderr, "unable to write file on filehook %v", err)
return nil, err
}
return &FileHook{logFile, flag, chmod, plainFormatter}, err
}
// Fire event
func (hook *FileHook) Fire(entry *logrus.Entry) error {
var line string
info, err := hook.file.Stat()
if err != nil {
return err
}
if info.Size() > maxLogFileSize {
fileInfo, err := os.Stat(hook.file.Name())
if err != nil {
return err
}
if fileInfo.Size() > maxLogFileSize {
renameFiles(hook.file.Name())
}
hook.file.Close()
if hook.file, err = os.OpenFile(hook.file.Name(), hook.flag, hook.chmod); err != nil {
fmt.Fprintf(os.Stderr, "unable to write file on filehook %v", err)
return err
}
}
if plainformat, err := hook.formatter.Format(entry); err != nil {
log.Printf("Formatter error: %+v", err)
return err
} else {
line = string(plainformat)
}
if _, err := hook.file.WriteString(line); err != nil {
fmt.Fprintf(os.Stderr, "unable to write file on filehook(entry.String)%v", err)
return err
}
return nil
}
func (hook *FileHook) Levels() []logrus.Level {
return []logrus.Level{
logrus.PanicLevel,
logrus.FatalLevel,
logrus.ErrorLevel,
logrus.WarnLevel,
logrus.InfoLevel,
logrus.DebugLevel,
}
}
// CustomResponseWriter
type CustomResponseWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (w CustomResponseWriter) Write(b []byte) (int, error) {
w.body.Write(b)
return w.ResponseWriter.Write(b)
}
func (w CustomResponseWriter) WriteString(s string) (int, error) {
w.body.WriteString(s)
return w.ResponseWriter.WriteString(s)
}
//
//The Middleware will write the Gin logs to logrus.
func ginToLogrus(log *logrus.Entry) gin.HandlerFunc {
return func(c *gin.Context) {
path := c.Request.URL.Path
raw := c.Request.URL.RawQuery
blw := &CustomResponseWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
c.Writer = blw
//
// Process request
c.Next()
clientIP := c.ClientIP()
method := c.Request.Method
statusCode := c.Writer.Status()
errorMessage := c.Errors.ByType(gin.ErrorTypePrivate).String()
if raw != "" {
path = path + "?" + raw
}
log.Infof("| %3d | %15s | %-7s | %s | %s",
statusCode, clientIP, method, path, errorMessage)
}
}
//NewGinWithLogrus - returns an Engine instance with the ginToLogrus and Recovery middleware already attached.
func NewGinWithLogrus(log *logrus.Entry) *gin.Engine {
engine := gin.New()
engine.Use(ginToLogrus(log), gin.Recovery())
return engine
}
@@ -0,0 +1,7 @@
package version
var VERSION = "2020-03-31-01"
func GetVersion() (version string) {
return VERSION
}
+84
View File
@@ -0,0 +1,84 @@
TOPDIR:=.
TGT:=../bin/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/libmjson/src/
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
LIBS += ./pstn_cli/lib/libpstncli.a ./tcp/lib/libtcp.a
LIBS += /usr/lib/x86_64-linux-gnu/libidn.a -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient
LIBS += ./third-lib/libcurl/lib/.libs/libcurl.a -lrt -lcrypto -lssl -lpthread
LIBS += ./third-lib/libevent/.libs/libevent.a ./third-lib/libevent/.libs/libevent_pthreads.a
LIBS += ./third-lib/libmjson/src/.libs/libmjson.a -L/usr/local/lib -lglib-2.0 -lz -lidn2
CFLAGS = -Wall -g -DX86_64 -DTEST_RESTPROXY $(LIBS)
CONFIGURE = ./configure
CC = gcc
$(TGT): lib_all 3rdlib_all $(OBJS)
if [ ! -d ../bin ]; then mkdir ../bin; fi
$(CC) -o $(TGT) $(CFLAGS) $(SRCS) $(INCDIR) $(LIBS)
chmod a+x $(TGT)
$(OBJS): %.o:%.c
$(CC) $(CFLAGS) -c -o $@ $< $(INCDIR)
all: $(TGT)
clean_all: clean lib_clean 3rdlib_clean
lib_all:
$(MAKE) -C ./smcli_client
$(MAKE) -C ./pstn_cli
$(MAKE) -C ./tcp
$(MAKE) -C ./dba
3rdlib_prepare:
if [ ! -d ./third-lib/libevent ]; then \
tar -xvf ../backup/libevent-2.1.11-stable.tar.gz -C ./third-lib/; \
mv ./third-lib/libevent-2.1.11-stable ./third-lib/libevent; \
fi
if [ ! -d ./third-lib/libcurl ]; then \
tar -xvf ../backup/curl-7.52.1.tar.gz -C ./third-lib/; \
mv ./third-lib/curl-7.52.1 ./third-lib/libcurl; \
fi
if [ ! -d ./third-lib/libmjson ]; then \
tar -xvf ../backup/mjson-1.7.0.tar.gz -C ./third-lib/; \
mv ./third-lib/json-1.7.0 ./third-lib/libmjson; \
fi
3rdlib_config: 3rdlib_prepare
cd ./third-lib/libevent && $(CONFIGURE)
cd ./third-lib/libcurl && $(CONFIGURE)
cd ./third-lib/libmjson && $(CONFIGURE)
3rdlib_all:
$(MAKE) -C ./third-lib/libevent
$(MAKE) -C ./third-lib/libcurl
$(MAKE) -C ./third-lib/libmjson
lib_clean:
$(MAKE) -C ./smcli_client clean
$(MAKE) -C ./pstn_cli clean
$(MAKE) -C ./tcp clean
$(MAKE) -C ./dba clean
3rdlib_clean:
$(MAKE) -C ./third-lib/libevent clean
$(MAKE) -C ./third-lib/libcurl clean
$(MAKE) -C ./third-lib/libmjson clean
clean:
rm -rf $(OBJS) $(TGT)
+33
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)
+12
View File
@@ -0,0 +1,12 @@
1)°²×°libmysqlclient
apt-get install libmysqlclient-dev
2)make dba
°²×°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
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
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
+33
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
+33
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
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};
/* 对于query、get-subscriberid来说,都是http-request操作,不用带参数 */
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);
// 设置basic 向服务器提供验证信息
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)
{
/* 对于topup来说,topup需要是http-post操作,且需要带额外参数.*/
/* 注意: 这里param是全局变量,多线程可能出错. 后续要分析下安全性. 2019/06/23 22:58:30 */
static char param[512] = {0};
// 设置问非0表示本次操作为post
curl_easy_setopt(eh, CURLOPT_POST, 1);
// url地址
curl_easy_setopt(eh, CURLOPT_URL,curAdaptor->urlBuf);
// 设置basic 向服务器提供验证信息
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)
{
/* 配置为query/topup流程都要先获取subscriber-id的话, topup的参数格式是这样的: */
/* msisdn=90909093&&pin=39977093792343 */
snprintf(param, sizeof(param), "msisdn=%s&pin=%s",
curAdaptor->msg.topup.msisdn, curAdaptor->msg.topup.pin);
}
else
{
/* 配置为query/topup流程不用先获取subscriber-id,而是直接query/topup到self-http, topup的参数格式是这样的: */
/* 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参数
curl_easy_setopt(eh, CURLOPT_POSTFIELDS, param);
curl_easy_setopt(eh, CURLOPT_POSTFIELDSIZE, strlen(param) );
// 对返回的数据进行操作的函数地址
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, curl_adaptor_resolve_cb);
// 这是write_data的第四个参数值
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);
}
// 打印调试信息
// curl_easy_setopt(eh, CURLOPT_VERBOSE, 1);
// 将响应头信息和相应体一起传给write_data
curl_easy_setopt(eh, CURLOPT_HEADER, 1);
// 设置为非0,响应头信息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)
{
/* 配置为query/topup流程都要先获取subscriber-id. query/topup的时候要将subscriber-id送出去 */
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType].curlFormat, curAdaptor->msg.query.subsid, curAdaptor->msg.query.msisdn);
}
else
{
/* 配置为query/topup流程不用先获取subscriber-id,不需要将subscriber-id送出去 */
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)
{
/* 配置为query/topup流程都要先获取subscriber-id. query/topup的时候要将subscriber-id送出去 */
len += snprintf(curAdaptor->urlBuf + len, RESTFUL_CUL_BUF_MAX - len,
g_tab_url[urlType].curlFormat, curAdaptor->msg.topup.subsid);
}
else
{
/* 配置为query/topup流程不用先获取subscriber-id,不需要将subscriber-id送出去 */
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
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: 查询 */
#define URLFetchWalletBalanceGetsubsid g_rest_proxy_env.cnf.url_fetchwalletbalance_getsubsid
#define URLFetchWalletBalance g_rest_proxy_env.cnf.url_fetchwalletbalance
/* url: 充值卡充值 */
#define URLRechargeGetsubsid g_rest_proxy_env.cnf.url_recharge_getsubsid
#define URLRecharge g_rest_proxy_env.cnf.url_recharge
/* url: 余额转账 */
#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, /* 转账获取sender的subscriberID的url */
URL_TRANS_GetsubsidReceiver, /* 转账获取receiver的subscriberID的url */
URL_TRANS, /* 转账的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]; // 转出的号码
char msisdn_receiver[24]; // 转入的号码
unsigned int money; // 转账金额
char subsid_sender[RESTFUL_SUBSID_LEN]; // 转出账号对应的subscriber-id
char subsid_receiver[RESTFUL_SUBSID_LEN]; // 转入账号对应的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__ */
+65
View File
@@ -0,0 +1,65 @@
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 =
GLIB_PATH = /usr/include/glib-2.0
GLIB_CONFIG_PATH = /usr/lib/x86_64-linux-gnu/glib-2.0/include
SRC_PATH = ./src
INC_PATH = ./src/include
PLT_PATH = ../../../ocs/plat
APP_PATH = ../../../ocs/mss
INC_PATH += -I$(PLT_PATH)/snmp/src -I$(PLT_PATH)/radius/src/include -I$(GLIB_PATH) -I$(GLIB_CONFIG_PATH)
OBJ_ADD =
TEST_OBJ_PATH =
PREPROC_CMD =
POSTPROC_CMD =
# Add MySQL include and library paths
MYSQL_INCLUDE_PATH := /usr/include/mysql
MYSQL_LIB_PATH := /usr/lib/x86_64-linux-gnu
MYSQL_LIBS := -lmysqlclient -lpthread -lz -lm -lrt -ldl
DEBUG_CFLAGS += -I$(MYSQL_INCLUDE_PATH) -I$(INC_PATH)
DEBUG_LINK_CFLAGS += -L$(MYSQL_LIB_PATH) -lmysqlclient -lpthread -lz -lm -lrt -ldl
RELEASE_CFLAGS += -I$(MYSQL_INCLUDE_PATH) -I$(INC_PATH)
RELEASE_LINK_CFLAGS += -L$(MYSQL_LIB_PATH) -lmysqlclient -lpthread -lz -lm -lrt -ldl
##--------------------------------------
##
## 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)
##
##--------------------------------------
MAKE_INCLUDE = ../inc
include ${MAKE_INCLUDE}/Makefile.rules
+345
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
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
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;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+50
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();
}
+62
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"
#include "radius_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);
}
+47
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
+87
View File
@@ -0,0 +1,87 @@
//md5.h
/***********************************************************************/
/** md5.h -- header file for implementation of MD5 **/
/** RSA Data Security, Inc. MD5 Message-Digest Algorithm **/
/** Created: 2/17/90 RLR **/
/** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **/
/** Revised (for MD5): RLR 4/27/91 **/
/** -- G modified to have y&~z instead of y&z **/
/** -- FF, GG, HH modified to add in last register done **/
/** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **/
/** -- distinct additive constant for each step **/
/** -- round 4 added, working mod 7 **/
/***********************************************************************/
/***********************************************************************/
/** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **/
/** **/
/** License to copy and use this software is granted provided that **/
/** it is identified as the "RSA Data Security, Inc. MD5 Message- **/
/** Digest Algorithm" in all material mentioning or referencing this **/
/** software or this function. **/
/** **/
/** License is also granted to make and use derivative works **/
/** provided that such works are identified as "derived from the RSA **/
/** Data Security, Inc. MD5 Message-Digest Algorithm" in all **/
/** material mentioning or referencing the derived work. **/
/** **/
/** RSA Data Security, Inc. makes no representations concerning **/
/** either the merchantability of this software or the suitability **/
/** of this software for any particular purpose. It is provided "as **/
/** is" without express or implied warranty of any kind. **/
/** **/
/** These notices must be retained in any copies of any part of this **/
/** documentation and/or software. **/
/***********************************************************************/
#ifndef _RADIUS_MD5_H
#define _RADIUS_MD5_H
typedef unsigned char BYTE;
/* typedef a 32-bit type */
//typedef unsigned long int UINT4;
typedef unsigned int UINT4;
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
/* Data structure for MD5 (Message-Digest) computation */
typedef struct _MD5_CTX
{
UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
UINT4 buf[4]; /* scratch buffer */
unsigned char in[64]; /* input buffer */
unsigned char digest[16]; /* actual digest after MD5Final call */
} MD5_CTX;
void radius_MD5Init (MD5_CTX *);
void radius_MD5Update (MD5_CTX *,unsigned char *,unsigned int);
void radius_MD5Final (MD5_CTX *);
void radius_MD5Transform(UINT4 *,UINT4 *);
void radius_get_md5_str(char *dest, char *org, int len);
void radius_get_md5_hex(char *dest, char *org, int len);
void radius_get_hmac_md5_hex(BYTE *dest, BYTE *org, int org_len, BYTE *key, int key_len);
#endif
/***********************************************************************/
/** End of md5.h **/
/***********************************************************************/
+201
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;
//}
+188
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);
}
}
}
+58
View File
@@ -0,0 +1,58 @@
##----------------------------------------------------------##
## ##
## Universal Makefile Backup Function ##
## ##
## Created : Wei Liu 07/06/20 ##
## Revision: [Last]Wei Liu 07/07/07 ##
## ##
##----------------------------------------------------------##
##--------------------------------------
##
## Make backup
##
##--------------------------------------
# backup
TIME_STR = ${shell date +%y%m%d_%H%M%S}
VER_STR = $(sed -n '/$(MODULE)_VERSION/'p ./src/include/$(MODULE).h | \
awk -F '[{,}]' $(print $2 $3 $4 ) )
BACK_PATH := ../../../r9_bak
BACK_PATH := $(BACK_PATH)/$(TYPE)/$(MODULE)
BACK_NAME = $(MODULE)_$(VER_STR)_$(TIME_STR).tgz
LS = ls -tl
version:
@echo $(VER_STR)
backfile ?= *
ifeq "$(backfile)" "*"
backfile =$(wildcard $(BACK_PATH)/*.tgz)
CHECK_BACK_FILE =$(backfile)
else
CHECK_BACK_FILE =$(shell find $(BACK_PATH) -name $(backfile))
endif
bk: clean
@$(MKDIR) -p $(BACK_PATH) --mode=0777
@echo Backuping $(MODULE)... $(BACK_PATH)/$(BACK_NAME)
@tar czvf $(BACK_PATH)/$(BACK_NAME) ./src ./ut ./doc ./Makefile
lsbk:
@$(LS) $(BACK_PATH)
rmbk:
ifneq "$(CHECK_BACK_FILE)" ""
@rm -rf $(BACK_PATH)/$(backfile)
@$(LS) $(BACK_PATH)
endif
unzip:
ifneq "$(CHECK_BACK_FILE)" ""
@tar czvf $(BACK_PATH)/$(BACK_NAME) ./src ./ut ./doc ./Makefile
@tar zxvf $(BACK_PATH)/$(backfile)
@ls $(BACK_PATH)
endif
+101
View File
@@ -0,0 +1,101 @@
##----------------------------------------------------------##
## ##
## Universal Makefile Lcov Function ##
## ##
## Created : Wei Liu 07/04/11 ##
## Revision: [Last]Wei Liu 07/07/09 ##
## ##
##----------------------------------------------------------##
##--------------------------------------
##
## COVER define
##
##--------------------------------------
ifeq "$(COVER_NEED)" "yes"
COVER := /usr/bin/lcov
GENHTML := /usr/bin/genhtml
GENDESC := /usr/bin/gendesc
GENPNG := /usr/bin/genpng
##Depending on the presence of the GD.pm perl module, we can use the
##special option '--frames' for genhtml
USE_GENPNG := $(shell $(GENPNG) --help >/dev/null 2>/dev/null; echo $$?)
ifeq ($(USE_GENPNG),0)
FRAMES := --frames
else
FRAMES :=
endif
##COV_SETFLAG := --zerocounters --path . -q --directory .
COV_SETFLAG := --zerocounters -q --directory ../obj
COV_SET := $(COVER) $(COV_SETFLAG)
COVER_REPORT_PATH ?= $(UTDIR)/output
INFO_FILE = $(COVER_REPORT_PATH)/$(MODULE).info
DSP_FILE = $(MODULE)_test_descriptions.txt
COV_OUTSET = --capture --directory ../obj \
--output-file $(INFO_FILE)\
--test-name $(MODULE) -q \
--base-directory ../
COV_HTMLSET= $(INFO_FILE) \
--output-directory $(COVER_REPORT_PATH)\
--title $(MODULE) \
--show-details $(FRAMES) \
--legend -q --num-spaces 4
COV_OUTPUT = $(COVER) $(COV_OUTSET)
COV_DOC_PATH := /usr/local/include/cov
endif
##--------------------------------------
##
## Make Test
##
##--------------------------------------
test:
@echo -e "\n================================Test start======================================\n"
ifeq "$(BUILD)" "exef"
ifeq "$(COVER_NEED)" "yes"
@$(MKDIR) -p $(COVER_REPORT_PATH) --mode=0777
@cp -rf $(COV_DOC_PATH)/lcovrc $(COV_DOC_PATH)/lcov_html_header\
$(COV_DOC_PATH)/lcov_html_foot /etc/
@cp -rf /usr/local/include/cgprof/cgprof /usr/local/bin/cgprof
@$(COV_SET)
$(OUTFILE)
gprof $(OUTFILE) gmon.out -p | cgprof -Tps
@$(COV_OUTPUT)
@LANG=C $(GENHTML) $(COV_HTMLSET)
@echo
@echo -e "||---------------------------------------------------------------"
@echo -e "|| Test cover report generated on the paht $(COVER_REPORT_PATH). "
@echo -e "|| Point a web browser at index.html to see results. "
@echo -e "||---------------------------------------------------------------"
else
@echo "COVER_NEED: $(COVER_NEED)BUILD: $(BUILD) "
$(OUTFILE)
endif
@echo -e "\n================================Test End========================================\n"
else
@echo -e "||---------------------------------------------------------------"
@echo -e "|| This is not exef project! "
@echo -e "||---------------------------------------------------------------"
@echo "This is not exef project!"
endif
cleanlcov:
@$(COV_SET) --reset
retest: cleanlcov test
+28
View File
@@ -0,0 +1,28 @@
##----------------------------------------------------------##
## ##
## Universal Makefile Documentation Function ##
## ##
## Created : Wei Liu 07/06/30 ##
## Revision: [Last]Wei Liu 07/07/07 ##
## ##
##----------------------------------------------------------##
VER_STR ?= 9.0
DOXYGEN_DOC_PATH := /usr/local/include/doc
define PREPARE_DOXYGEN
sed 's/MODULE/$(MODULE)/g' $(1) | sed 's/VER_STR/$(VER_STR)/g' >> ./doc/doxygen.conf
endef
define MAKE_DOC
@echo
@echo -e "Generate documnet of $(MODULE)\t\t\t Please Waiting..."
@$(call PREPARE_DOXYGEN, $(DOXYGEN_DOC_PATH)/doxygen.conf)
@doxygen ./doc/doxygen.conf
@cp -rf $(DOXYGEN_DOC_PATH)/view_chm.bat ./doc/html
@echo
@echo ==================================Doxygen End===================================
endef
+379
View File
@@ -0,0 +1,379 @@
##----------------------------------------------------------##
## ##
## Universal Makefile Indenting fuction ##
## ##
## Created : Wei Liu 07/04/30 ##
## Revision: [Last]Wei Liu 07/07/07 ##
## ##
##----------------------------------------------------------##
##--------------------------------------
##
## Make indenting program flags
##
##--------------------------------------
##-bad或--blank-lines-after-declarations  在声明区段后加上空白行。
BAD_FLAG :=
##-bad
##-bap或--blank-lines-after-procedures  在程序后加上空白行。
BAP_FLAG :=
##-bap
##-bbb或--blank-lines-after-block-comments  在注释区段後加上空白行。
BBB_FLAG :=
##-bbb
##--break-before-boolean-operator bbo 较长的行,在逻辑运算符前分行
BBO_FLAG :=
##-bc或--blank-lines-after-commas  在声明区段中,若出现逗号即换行。
BC_FLAG :=
##-bl或--braces-after-if-line  if(或是else,for等等)与後面执行区段的"{"自成一行。
BL_FLAG := -bl
##-bli<缩排格数>或--brace-indent<缩排格数>  设置{}缩排的格数。
BLI_FLAG := -bli4
##--braces-after-struct-decl-line bls 定义结构,"struct"和"{"分行
BLS_FLAG := -bls
##-br或--braces-on-if-line  if(或是else,for等等)与後面执行跛段的"{"自成一行。
BR_FLAG :=
##-bs或--blank-before-sizeof  在sizeof之後空一格。
BS_FLAG :=
##`-cbin'
##`--case-brace-indentationn'
##Indent braces after a case label N spaces.
CBI_FLAG := -cbi5
##-c<栏数>或--comment-indentation<栏数>  将注释置于程序码右侧指定的栏位。
CW_FLAG := -c33
##-cd<栏数>或--declaration-comment-column<栏数>  将注释置于声明右侧指定的栏位。
CD_FLAG := -cd33
##-cdb或--comment-delimiters-on-blank-lines  注释符号自成一行。
CDB_FLAG :=
##-ce或--cuddle-else  将else置于"}"(if执行区段的结尾)之後。
CE_FLAG :=
##-ci<缩排格数>或--continuation-indentation<缩排格数>  叙述过长而换行时,指定换行後缩排的格数。
CI_FLAG :=
##-ci4
##-cli<缩排格数>或--case-indentation-<缩排格数>  使用case时,switch缩排的格数。
CLI_FLAG := -cli0
##-cp<栏数>或-else-endif-column<栏数>  将注释置于else与elseif叙述右侧定的栏位。
CP_FLAG := -cp33
##-cs或--space-after-cast  在cast之後空一格。
CS_FLAG := -cs
##-d<缩排格数>或-line-comments-indentation<缩排格数>  针对不是放在程序码右侧的注释,设置其缩排格数。
D_FLAG :=
##-d0
##-di<栏数>或--declaration-indentation<栏数>  将声明区段的变量置于指定的栏位。
DI_FLAG :=
##-di4
##-fc1或--format-first-column-comments  针对放在每行最前端的注释,设置其格式。
FC1_FLAG := -fc1
##-fca或--format-all-comments  设置所有注释的格式。
FCA_FLAG :=
##-gnu或--gnu-style  指定使用GNU的格式,此为预设值。
GNU_FLAG :=
##-kr或--k-and-r-style  指定使用Kernighan&Ritchie的格式。
KR_FLAG :=
##-orig或--original  使用Berkeley的格式。
ORG_STYLE :=
##-i<格数>或--indent-level<格数>  设置缩排的格数。
I_FLAG := -i4
##-ip<格数>或--parameter-indentation<格数>  设置参数的缩排格数。
IP_FLAG := -ip4
##--line-length 75 l75 非注释行最长75
LINE_FLAG :=
##`-lcn'
##`--comment-line-lengthn'
##Set maximum line length for comment formatting to n.
LCN_FLAG :=
##`-lps'
##`--leave-preprocessor-space'
##Leave space between `#' and preprocessor directive.
LPS_FLAG :=
##-lp或--continue-at-parentheses  叙述过长而换行,且叙述中包含了括号时,将括号中的每行起始栏位内容垂直对其排列。
LP_FLAG :=
##--break-function-decl-args nbfda 关闭:函数的参数一个一行
NBFDA_FLAG := -nbfda
##-nbad或--no-blank-lines-after-declarations  在声明区段後不要加上空白行。
NBAD_FLAG :=
##-nbap或--no-blank-lines-after-procedures  在程序後不要加上空白行。
NBAP_FLAG :=
##-nbbb或--no-blank-lines-after-block-comments  在注释区段後不要加上空白行。
NBBB_FLAG :=
##-nbc或--no-blank-lines-after-commas  在声明区段中,即使出现逗号,仍旧不要换行。
NBC_FLAG := -nbc
##-ncdb或--no-comment-delimiters-on-blank-lines  注释符号不要自成一行。
NCBD_FLAG := -ncdb
##--cuddle-do-while ncdw "do --- while"的"while"和其前面的"}"另起一行
NCDW_FLAG := -ncdw
##-nce或--dont-cuddle-else  不要将else置于"}"之後。
NCE_FLAG :=
##-nce
##-ncs或--no-space-after-casts  不要在cast之後空一格。
NCS_FLAG :=
##-nfc1或--dont-format-first-column-comments  不要格式化放在每行最前端的注释。
NFC1_FLAG :=
##-nfca或--dont-format-comments  不要格式化任何的注释。
NFCA_FLAG := -nfca
##--honour-newlines hnl Prefer to break long lines at the position of newlines in the input
HNL_FLAG := -hnl
##-nip或--no-parameter-indentation  参数不要缩排。
NIP_FLAG :=
##-nlp或--dont-line-up-parentheses  叙述过长而换行,且叙述中包含了括号时,不用将括号中的每行起始栏位垂直对其排列。
NLP_FLAG :=
##-npcs或--no-space-after-function-call-names  在调用的函数名称之後,不要加上空格。
NPCS_FLAG :=
##-npro或--ignore-profile  不要读取indent的配置文件.indent.pro。
NPRO_FLAG := -npro
##-nprs或--space-after-procedure-calls  在"("后")"前不插入空格 。
NPRS_FLAG := -nprs
##-npsl或--dont-break-procedure-type  程序类型与程序名称放在同一行。
NPSL_FLAG := -npsl
##--space-after-for saf for后面有空格
SAF_FLAG := -saf
##--space-after-if sai if后面有空格
SAI_FLAG := -sai
##--space-after-while saw while后面有空格
SAW_FLAG := -saw
##-nsc或--dont-star-comments  注解左侧不要加上星号(*)。
NSC_FLAG := -nsc
##-nsob或--leave-optional-semicolon  不用处理多馀的空白行。
NSOB_FLAG :=
##-nss或--dont-space-special-semicolon  若for或while区段仅有一行时,在分号前不加上空格。
NSS_FLAG := -nss
##-nv或--no-verbosity  不显示详细的信息。
NV_FLAG := -nv
##`-nut'
##`--no-tabs'
##Use spaces instead of tabs.
NUT_FLAG :=
##-nut
##-pcs或--space-after-procedure-calls  在调用的函数名称与"("之间加上空格。
PCS_FLAG := -pcs
##`-prs'
##`--space-after-parentheses'
##Put a space after every '(' and before every ')'.
PRS_FLAG :=
##`-pin'
##`--paren-indentationn'
##Specify the extra indentation per open parentheses '(' when a statement is broken.
PI_FLAG :=
##-pi4
##-psl或--procnames-start-lines  程序类型置于程序名称的前一行。
PSL_FLAG :=
##-sc或--start-left-side-of-comments  在每行注释左侧加上星号(*)。
SC_FLAG :=
##-sob或--swallow-optional-blank-lines  删除多馀的空白行。
SOB_FLAG := -sob
## -sbin, --struct-brace-indentationn
## Indent braces of a struct, union or enum N spaces.
SBI_FLAGE := -sbi4
##-ss或--space-special-semicolon  若for或swile区段今有一行时,在分号前加上空格。
SS_FLAG := -ss
##-st或--standard-output  将结果显示在标准输出设备。
ST_FLAG :=
##-T  数据类型名称缩排。
T_FLAG := -T
##-ts<格数>或--tab-size<格数>  设置tab的长度。
TS_FLAG := -ts4
##-ts4
##--use-tabs ut 使用tab来缩进
UT_FLAG := -ut
##-ut
##-v或--verbose  执行时显示详细的信息。
V_FLAG := -v
##-version  显示版本信息。
VER_FLAG :=
##未实现的风格:
##1,()与变量间加空格 (以实现)
##2, else 独立成行
##3, 注释缩进
##4,每个函数前加注释段
## indent flags
## -bad -bap -bbb -bbo -bl -bli4 -bls -bs -c33 -cd33 -ce -ci4 -cli0
## -cp33 -cs -d0 -di4 -fc1 -hnl -i4 -ip4 -lp -nbc -ncdb -nbfda -ncdw
## -nfc1 -nfca -npro -npsl -nsc -nv -pcs -saf -sai -saw -sob -ss -T -ts4 -ut
INDENT_FLAGS1 := $(GNU_FLAG) \
$(KR_FLAG) \
$(ORG_STYLE) \
$(BAD_FLAG) \
$(BAP_FLAG) \
$(BBB_FLAG) \
$(BBO_FLAG) \
$(BC_FLAG) \
$(BL_FLAG) \
$(BLI_FLAG) \
$(BLS_FLAG) \
$(BR_FLAG) \
$(BS_FLAG) \
$(CBI_FLAG) \
$(CW_FLAG) \
$(CD_FLAG) \
$(CDB_FLAG) \
$(CE_FLAG) \
$(CI_FLAG) \
$(CLI_FLAG) \
$(CP_FLAG) \
$(CS_FLAG) \
$(D_FLAG) \
$(DI_FLAG) \
$(FC1_FLAG) \
$(FCA_FLAG) \
$(HNL_FLAG) \
$(I_FLAG) \
$(IP_FLAG) \
$(LINE_FLAG ) \
$(LP_FLAG) \
$(NBAD_FLAG) \
$(NBAP_FLAG) \
$(NBBB_FLAG) \
$(NBC_FLAG) \
$(NCBD_FLAG) \
$(NBFDA_FLAG) \
$(NCDW_FLAG) \
$(NCE_FLAG) \
$(NCS_FLAG) \
$(NFC1_FLAG) \
$(NFCA_FLAG) \
$(NIP_FLAG) \
$(NLP_FLAG) \
$(NPCS_FLAG) \
$(NPRO_FLAG) \
$(NPRS_FLAG) \
$(NPSL_FLAG) \
$(NSC_FLAG) \
$(NSOB_FLAG) \
$(NSS_FLAG) \
$(NV_FLAG) \
$(PCS_FLAG) \
$(PI_FLAG) \
$(PSL_FLAG) \
$(PRS_FLAG) \
$(SAF_FLAG) \
$(SAI_FLAG) \
$(SAW_FLAG) \
$(SBI_FLAGE) \
$(SC_FLAG) \
$(SOB_FLAG) \
$(SS_FLAG) \
$(ST_FLAG) \
$(T_FLAG) \
$(TS_FLAG) \
$(UT_FLAG) \
$(V_FLAG) \
$(VER_FLAG) \
$(NUT_FLAG)
INDENT_FLAGS = -kr -i4
##$(warning $(INDENT_FLAGS) $(1))
##--------------------------------------
##
## MAKE_INDENT template
##
##------------------------------------
define INDENT_FILE
indent $(INDENT_FLAGS) $(1)
endef
define MAKE_INDENT
@echo
@echo "[Indent flags ]: $(INDENT_FLAGS)"
@echo ""
$(foreach file,$(1),$(call INDENT_FILE, $(file)))
@echo
@echo ===================================Indent End===================================
endef
+347
View File
@@ -0,0 +1,347 @@
##----------------------------------------------------------##
## ##
## Universal Makefile Rules ##
## ##
##----------------------------------------------------------##
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)
RELEASE_LINK_CFLAGS = -g $(RELS_FLAGS_ADD) -o
DEBUG_CFLAGS += -g -Wall -rdynamic -DDEBUG -I. $(DBUG_FLAGS_ADD)
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))
ifneq (,$(findstring hlr,$(PLT_LIB)))
MODULE_APP_LIB=
##-L../app/ae/src/lib -lpubfunc
endif
ifneq (,$(findstring auceir,$(PLT_LIB)))
MODULE_APP_LIB=
##-L../app/ae/src/lib -lpubfunc -L../usr/lib -la3a8 -ldl -lpopt
endif
##--------------------------------------
##
## 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 ${MAKE_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 ${MAKE_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 ${MAKE_INCLUDE}/Makefile.doxygen
doc:
@chmod 777 $(SRC_FULL_PATH)
@echo ==================================Doxygen START=================================
@echo
$(call MAKE_DOC, $(SRC_FULL_PATH))
##--------------------------------------
##
## backup Makefile.backup
##
##--------------------------------------
include ${MAKE_INCLUDE}/Makefile.backup
##--------------------------------------
##
## cov Makefile.cov
##
##--------------------------------------
include ${MAKE_INCLUDE}/Makefile.cov
##--------------------------------------
##
## usage Makefile.usage
##
##--------------------------------------
include ${MAKE_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:
+288
View File
@@ -0,0 +1,288 @@
##----------------------------------------------------------##
## ##
## Universal Makefile Splint Function ##
## ##
## Created : Wei Liu 07/05/20 ##
## Revision: [Last]Wei Liu 07/07/07 ##
## ##
##----------------------------------------------------------##
##--------------------------------------
##
## Make splinting program flags
##
##--------------------------------------
##是否有提示信息
SFLAG_HINTS := #-hints
##是否用库信息代替头文件
SFLAG_INCLUDE := +single-include
#+never-include
##包含什么库
SFLAG_LIB := +posixlib
##+nolib +nof -warnposix
##+unixlib
##+posixlib
#+nolib +nof -warnposix
##+nof
##+unixlib
##+which_lib
##
SFLAG_DUMP :=
##dump ./include/public.h ./include/pub_base.h ./include/includes.h
SFLAG_LOAD :=
##+load /usr/share/splint/lib/unixstrict.lcd
##load ./include/public.h ./include/pub_base.h ./include/includes.h
SFLAG_DIR :=
##-I/work/r9/plat/public/src/include/splint
##-I/work/r9/plat/public/src/include/splint
##-I /usr/local/work/r9/plat/public/src/include/
##检查模式
SFLAG_TYPE := -strict
##略过的头文件
SFLAG_SYS_HEADERS := +skip_sys_headers
SFLAG_ISO_HEADERS :=
#+skip_iso_headers
SFLAG_POSIX_HEADERS :=
##+skip_posix_headers
##每个头文件只检查一次
SFLAG_SINGLE_INCLUDE := +singleinclude
##系统文件目录
SFLAG_SYS_DIR :=
##+sys-dirs /work/r9/plat/public/src/include/splint
##函数参数有原型
SFLAG_PROTO_PARAMNAME := -protoparamname
##变量名是否为保留名
SFLAG_UNDERSCORE := -isoreserved -isoreservedinternal
## 在"/*"和"*/"中再次使用"/*"和"*/"
SFLAG_NESTCOMMENT := -nestcomment
##允许未说明导出变量、函数和类型
SFLAG_EXPORT_VAR := -exportvar
SFLAG_EXPORT_FCN := -exportfcn
SFLAG_EXPORT_TYPE := -exporttype
SFLAG_EXPORT_CONST := -exportconst
##允许其他类型定义为BOOL型
SFLAG_LIKELY_BOOL := -likelybool
##两种类型相等
SFLAG_CHAR_INT := +charint
SFLAG_BOOL_INT := +boolint
##Report memory transfer errors for initializations to read-only string literals
SFLAG_READONLY_TRANS := -readonlytrans
##A string literal is assigned to a char array that smaller than the string literal needs
SFLAG_STRING_SMALLER := -stringliteralsmaller
##A variable declared outside a macro body starts with the macro-var-prefix
SFLAG_MACRO_PREFIX := -macrovarprefixexclude
##Initializer does not define all elements of a declared array
SFLAG_INITAL_ELEMENT := -initallelements
##类型匹配
SFLAG_PARAM_TYPE := -type
##Report modification errors in functions declared without a modifies clause
SFLAG_MODIFY := -modnomods
##Use of a checked global in a function with no globals list
SFLAG_GLOBAL := -glob-noglobs
##Use of internal state in function with no globals list
SFLAG_INTERNAL_GLOBS := -internal-globs-noglobs
##Implicit checked qualifier on global variables and qualifier file static scope variables with no checking annotation
SFLAG_CHECK_GLOBAL := -imp-checkedstrict-globs -imp-checkedstrict_statics
##Undocumented modification of a checked global variable in a function with no modifies clause
SFLAG_CHECK_GLOBAL_MODIFY := -mod-globs-nomods
##Storage declared with observer may be modified through a call to an unconstrained function
SFLAG_OBSERVER_MODIFY := -mod-observer-uncon
##忽略返回值
SFLAG_IGNORE_RETVAL := -retval
##while,if and for statement is not a block
SFLAG_WHILE_BLOCK := -whileblock
SFLAG_IF_BLOCK := -ifblock
SFLAG_FOR_BLOCK := -forblock
##There is no finals else following an else if construct
SFLAG_ELSEIF_COMPLETE := -elseifcomplete
##允许指针进行数学运算
SFLAG_POINT_ARITH := -ptrarith -nullptrarith
##An unconstrained function is called in a function body where modifications are checked.
SFLAG_UNCONSTRAIN_MODIFY := -mod-uncon-nomods
##NO effect of unconstrained functions
SFLAG_EFFECT_UNCONSTRAIN := -no-effect-uncon
##Type-mismatch in parameter corresponding to format code in a printflike or scanflike function
SFLAG_FORMAT-TYPE := -format-type
##An actual parameter that is passed as a unique formal parameter is aliased by another parameter or global variable
SFLAG_ALIASING := -alias-unique -ret-alias#-may-alias-unique
##Transfer Errors flag
SFLAG_STORAGE_TRANSFER := -onlytrans -temptrans -unqualified-trans -immediatetrans
##Report errors for break statements inside a nested while, for or switch
SFLAG_DEEP_BREAK := -deep-break #-switch-switch-break -loop-loop-break
##Storage has inconsistent states of alternate paths through a branch
SFLAG_INCONSISTENT_BRANCH := -branch-state
##There is a non-empty case in a switch not followed by a break.
##Likely infinite loop is detected
##Likely infinite loop is detected. Loop test or body calls an unconstrained function that may produce an undetected modification
SFLAG_PROBLEMATIC_CTR := -case-break -infloops -infloopsuncon
##An expression may be undefined because a sub-expression contains a call to an unconstrained function (no modifies clause)
##that may modify something that may be modified or used by another sub-expression
SFLAG_UNDEFINED_EVALORDER := -eval-order-uncon
##Only storage transferred to an unqualified global or static reference.
##This may lead to a memory leak, since the new reference is not necessarily released
SFLAG_INITIALIZERS := -only-unq-global-trans
##Primitive operation does not type check strictly
SFLAG_PRIMITIVE_OPERA := -strict-ops -bitwise-signed
##Unused Declarations (未使用的声明)
SFLAG_DECLARARIONS := -field-use -fcnuse -param-use -typeuse -varuse -enummemuse
##Function, variable, iterator or constant declared but never defined (未初始化)
SFLAG_COMPLETE_PRG := -decl-undef
##A declaration is exported but not used outside this module or not appear in a header file
SFLAG_EXPORTS := -export-local -export-header
##把warning输出到文件splint_warn中
SFLAG_WARN_FILE := #+warning-stream splint_warn
##把致命错误输出到文件splint_error中
SFLAG_ERROR_FILE := #+error-stream splint_error
##文件覆盖
SFLAG_STREAM_OVERWRITE := -streamoverwrite
##An abstract type defined in M.h (or specified in M.lcl) is accessible in M.c
SFLAG_ACCESS := -access-module
##Function definition is in old style syntax. Standard prototype syntax is preferred.
SFLAG_ISO_CONFORMANCE := #-old-style
##Use of function that may lead to buffer overflow
SFLAG_BUFFER := -bufferoverflowhigh
##A function is declared without a parameter list prototype
SFLAG_FUNC_NOPARAM := -noparams
##Operand of sizeof operator is a type
SFLAG_SIZEOF_TYPE := -sizeoftype
##Storage derivable from a parameter, return value or global variable is not completely defined
SFLAG_COMP_DEF := -compdef
##Behavior of an expression is unspecified or implementation-dependent
##because sub-expressions contain interfering side effects that may be evaluated in any order
SFLAG_EVAL_ORDER := -eval-order
##try to recover code
SFLAG_TRY_TO_RECOVER := #+trytorecover
##返回一个NULL指针
SFLAG_NULL_RET := -nullret
##A possibly null pointer is reachable from a parameter or global variable that is not declared using a /*@null@*/ annotation
SFLAG_NULL_STATE := -nullstate
##The value of a location that may not be initialized on some execution path is used
SFLAG_USE_BEFORE_DEF := -usedef
##编译时不知道参数类型 Format parameter is not known at compile-time 例如:sprintf(mgcpAsciTempBuf, msg)
SFLAG_FORMAT_CONST := -format-const
##Argument to exit has implementation defined behavior. The only valid arguments to exit are EXIT_SUCCESS, EXIT_FAILURE and 0.
##An error is reported if Splint can determine statically that the argument to exit is not one of these
SFLAG_EXIT_ARG := -exitarg
##An extern declaration is used inside a function body
SFLAG_EXTERN := -nested-extern
SFLAG_OLD_STTLE := -oldstyle
SFLAG_SHIFT_NEG := -shiftnegative
SFLAG_PREPROC := -preproc
##all splint flags
SPLINT_FLAGS := $(SFLAG_LIB) $(SFLAG_TYPE) $(SFLAG_SYS_HEADERS) $(SFLAG_ISO_HEADERS)\
$(SFLAG_POSIX_HEADERS) $(SFLAG_SINGLEINCLUDE) $(SFLAG_WARN)\
$(SFLAG_UNDERSCORE) $(SFLAG_NESTCOMMENT) $(SFLAG_EVAL_ORDER)\
$(SFLAG_PROTO_PARAMNAME) $(SFLAG_EXPORT_VAR) $(SFLAG_EXPORT_FCN)\
$(SFLAG_EXPORT_TYPE) $(SFLAG_LIKELY_BOOL) $(SFLAG_CHAR_INT)\
$(SFLAG_READONLY_TRANS) $(SFLAG_STRING_SMALLER) $(SFLAG_MACRO_PREFIX)\
$(SFLAG_INITAL_ELEMENT) $(SFLAG_PARAM_TYPE) $(SFLAG_GLOBAL)\
$(SFLAG_CHECK_GLOBAL) $(SFLAG_CHECK_GLOBAL_MODIFY) $(SFLAG_IGNORE_RETVAL)\
$(SFLAG_INTERNAL_GLOBS) $(SFLAG_MODIFY) $(SFLAG_BOOL_INT)\
$(SFLAG_WHILE_BLOCK) $(SFLAG_HINTS) $(SFLAG_IF_BLOCK) $(SFLAG_FOR_BLOCK)\
$(SFLAG_POINT_ARITH) $(SFLAG_ELSEIF_COMPLETE) $(SFLAG_UNCONSTRAIN_MODIFY)\
$(SFLAG_EFFECT_UNCONSTRAIN) $(SFLAG_OBSERVER_MODIFY)\
$(SFLAG_FORMAT-TYPE) $(SFLAG_ALIASING) $(SFLAG_STORAGE_TRANSFER)\
$(SFLAG_DEEP_BREAK) $(SFLAG_INCONSISTENT_BRANCH) $(SFLAG_PROBLEMATIC_CTR)\
$(SFLAG_UNDEFINED_EVALORDER) $(SFLAG_INITIALIZERS) $(SFLAG_PRIMITIVE_OPERA)\
$(SFLAG_DECLARARIONS) $(SFLAG_COMPLETE_PRG) $(SFLAG_EXPORTS) $(SFLAG_INCLUDE)\
$(SFLAG_STREAM_OVERWRITE) $(SFLAG_WARN_FILE) $(SFLAG_ERROR_FILE)\
$(SFLAG_ACCESS) $(SFLAG_ISO_CONFORMANCE) $(SFLAG_BUFFER) $(SFLAG_SIZEOF_TYPE)\
$(SFLAG_COMP_DEF) $(SFLAG_FUNC_NOPARAM) $(SFLAG_TRY_TO_RECOVER)\
$(SFLAG_EXPORT_CONST) $(SFLAG_DUMP) $(SFLAG_LOAD) $(SFLAG_NULL_RET)\
$(SFLAG_NULL_STATE) $(SFLAG_USE_BEFORE_DEF) $(SFLAG_FORMAT_CONST)\
$(SFLAG_EXIT_ARG) $(SFLAG_EXTERN) $(SFLAG_OLD_STTLE) $(SFLAG_DIR)\
$(SFLAG_SHIFT_NEG) $(SFLAG_PREPROC)
##--------------------------------------
##
## MAKE_INDENT template
##
##------------------------------------
define SPLINT_FILE
@echo -e "Splinting: $(notdir $(1)) \t\t\t please wait ..."
@nohup splint $(SPLINT_FLAGS) $(1) | sed '$d' | sed '1,2d' |\
sed '/Splint /d' | sed '/Finished /d' |\
sed '/Cannot continue/d'
endef
##@echo $(SPLINT_FLAGS)
define MAKE_SPLINT
@echo
$(foreach file,$(1),$(call SPLINT_FILE, $(file)))
@echo
@echo =======================================End======================================
endef
+36
View File
@@ -0,0 +1,36 @@
##----------------------------------------------------------##
## ##
## Universal Makefile usage ##
## ##
## Created : Wei Liu 07/04/11 ##
## Revision: [Last]Wei Liu 07/07/09 ##
## ##
##----------------------------------------------------------##
##-------------------------------------
##
## Universal Makefile Usage
##
##-------------------------------------
usage:
@echo "usage: [make ] = make all "
@echo "usage: [make all ] "
@echo "usage: [make clean ] "
@echo "usage: [make rebuild ] "
@echo "usage: [make test ] "
@echo "usage: [make indent ] "
@echo "usage: [make splint ] "
@echo "usage: [make prtdebug ] "
@echo "usage: [make dir ] "
@echo "usage: [make config ] = make dir now "
@echo "usage: [make check ] = not supported now "
@echo "usage: [make bk ] "
@echo "usage: [make lsbk ] "
@echo "usage: [make rmbk backfile=*/[filename]] "
@echo "usage: [make unzip backfile=[filename] ] "
@echo "usage: [make version ] "
@echo "usage: [make umakever ] "
+102
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
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
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;
// ÔËÐÐģʽ
#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)
{
/* ³õʼ»¯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
/* ³õʼ»¯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;
}
Loaded 100 of 143 files, more files were not shown because too many files have changed in this diff. Show more