fix: adjustment directory structure

This commit is contained in:
zhangsz
2025-03-25 09:46:16 +08:00
parent e9b29a109d
commit 63ec6e5b14
167 changed files with 374 additions and 21127 deletions

8
proxy/.idea/.gitignore generated vendored Normal file
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
proxy/.idea/encodings.xml generated Normal file
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
proxy/.idea/misc.xml generated Normal file
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
proxy/.idea/modules.xml generated Normal file
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
proxy/.idea/selfcare_proxy_go.iml generated Normal file
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
proxy/.idea/vcs.xml generated Normal file
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
proxy/.project Normal file
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
proxy/Makefile Normal file
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
proxy/MsgDef/canal.go Normal file
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
}

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
proxy/Nmysql/alert_sms.go Normal file
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
}

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
proxy/Nmysql/map.go Normal file
View File

@@ -0,0 +1,4 @@
package Nmysql
type void struct{}
var member void

1311
proxy/Nmysql/mysql_db.go Normal file

File diff suppressed because it is too large Load Diff

175
proxy/Nmysql/provision.go Normal file
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
proxy/Nmysql/smcli_cmd.go Normal file
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"}

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
proxy/Nmysql/user_status.go Normal file
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
proxy/Nredis/acctount.go Normal file
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
proxy/Nredis/alert_sms.go Normal file
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
proxy/Nredis/bundleclr.go Normal file
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()
}

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
}
}

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
proxy/Nredis/holiday.go Normal file
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
}
}

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
proxy/Nredis/rds_client.go Normal file
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
}

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
}

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
}
}

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
}
}

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
}

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
proxy/Nrestful/rest_msg.go Normal file
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
}

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)
//
}

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
}
}

View File

@@ -0,0 +1,5 @@
package Nrestful
import (
)

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
proxy/Readme.txt Normal file
View File

@@ -0,0 +1,80 @@
Ubuntu18.04
1.<2E><>װredis-server
#apt-get install redis-server
#vim /etc/redis/redis.conf
1)<29><><EFBFBD><EFBFBD>master
bind 192.168.7.90
protected-mode no
unixsocket /var/run/redis/redis-server.sock
unixsocketperm 700
2)<29><><EFBFBD><EFBFBD>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.<2E><>װ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.<2E><>װsctp
sudo apt install lksctp-tools
sudo apt install libsctp-dev
Ubuntu20.04<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ
diam/diam_adaptor<6F><72>makefile<6C>ļ<EFBFBD><C4BC><EFBFBD>CFLAGS<47><53> -DOLD_SCTP_SOCKET_API
3.<2E><>װlibhiredis
sudo apt install libhiredis-dev
<EFBFBD><EFBFBD>װglib
#sudo apt-get install libglib2.0-dev ## 20.04
<EFBFBD><EFBFBD>װidn
#sudo apt -y install idn
<EFBFBD><EFBFBD>װ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<72><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#apt-get install libidn11-dev
4.<2E><>װmysqldump
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>mysqldump,Ȼ<><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>װ<EFBFBD><D7B0>Ҫ<EFBFBD>İ汾
#apt install mysql-client-5.7 ## 18.04
#apt install mysql-client libmysqlclient-dev ## mysql-server 20.04
5.<2E><>װcanal
#dpkg -i canal-1.0.1.amd64.deb
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>canal<EFBFBD><EFBFBD>
#vim /usr/local/etc/canal/config.yaml
log:
output: file
level: info #log<6F><67><EFBFBD><EFBFBD>
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: # <20><>sentinel addr
# - 192.168.7.90:26379
# - 192.168.4.61:26379
telnetServer:
addr: 192.168.7.90:4100
canalServer:
reinit: true # <20><><EFBFBD><EFBFBD>ʱ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB>ͬ<EFBFBD><CDAC>mysql<71><6C>redis
standalone: false # <20>Ƿ񵥻<C7B7><F1B5A5BB><EFBFBD><EFBFBD>У<EFBFBD>trueʱ<65><CAB1><EFBFBD><EFBFBD>ʵʱͬ<CAB1><CDAC>mysql<71><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>falseʱֻ<CAB1>б<EFBFBD><D0B1><EFBFBD>redis<69><73>masterʱ<72><CAB1>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>canal<61><6C>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>
6.<2E><>װocs

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
proxy/canal/canal.go Normal file
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
proxy/canal/canal.go.bak Normal file
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
proxy/canal/client.go Normal file
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
proxy/canal/client_fsm.go Normal file
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
proxy/canal/msg.go Normal file

File diff suppressed because it is too large Load Diff

114
proxy/canal/sync_redis.go Normal file
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
proxy/conf/config.yaml Normal file
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
proxy/config/config.go Normal file
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
proxy/cron/cron.go Normal file
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()
}

176
proxy/go.sum Normal file
View File

@@ -0,0 +1,176 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/antonfisher/nested-logrus-formatter v1.3.1 h1:NFJIr+pzwv5QLHTPyKz9UMEoHck02Q9L0FP13b/xSbQ=
github.com/antonfisher/nested-logrus-formatter v1.3.1/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-mysql-org/go-mysql v1.11.0 h1:Y0ooXu2UtbjsgpfjFBXZEvidEl1q8n0ESxej0zZ78Zc=
github.com/go-mysql-org/go-mysql v1.11.0/go.mod h1:y/7aggbs+Io8rPVerIjTe1+nMgt8q5tBIxIc+qQnE0k=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-sql-driver/mysql v1.9.1 h1:FrjNGn/BsJQjVRuSa8CBrM5BWA9BWoXXat3KrtSb/iI=
github.com/go-sql-driver/mysql v1.9.1/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/ircop/tclient v0.0.0-20180908074649-f30684f28b0f h1:p7j1sjVHXwjJpr8fYjzInUGTmK9rYXgcQPiXjpawl/c=
github.com/ircop/tclient v0.0.0-20180908074649-f30684f28b0f/go.mod h1:d111ZaRuwWWPIw3+gL48/SD8Pj9P6qBS5scMGWFt6/I=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pingcap/errors v0.11.5-0.20240311024730-e056997136bb h1:3pSi4EDG6hg0orE1ndHkXvX6Qdq2cZn8gAPir8ymKZk=
github.com/pingcap/errors v0.11.5-0.20240311024730-e056997136bb/go.mod h1:X2r9ueLEUZgtx2cIogM0v4Zj5uvvzhuuiu7Pn8HzMPg=
github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 h1:tdMsjOqUR7YXHoBitzdebTvOjs/swniBTOLy5XiMtuE=
github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86/go.mod h1:exzhVYca3WRtd6gclGNErRWb1qEgff3LYta0LvRmON4=
github.com/pingcap/log v1.1.1-0.20230317032135-a0d097d16e22 h1:2SOzvGvE8beiC1Y4g9Onkvu6UmuBBOeWRGQEjJaT/JY=
github.com/pingcap/log v1.1.1-0.20230317032135-a0d097d16e22/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4=
github.com/pingcap/tidb/pkg/parser v0.0.0-20241118164214-4f047be191be h1:t5EkCmZpxLCig5GQA0AZG47aqsuL5GTsJeeUD+Qfies=
github.com/pingcap/tidb/pkg/parser v0.0.0-20241118164214-4f047be191be/go.mod h1:Hju1TEWZvrctQKbztTRwXH7rd41Yq0Pgmq4PrEKcq7o=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/reiver/go-oi v1.0.0 h1:nvECWD7LF+vOs8leNGV/ww+F2iZKf3EYjYZ527turzM=
github.com/reiver/go-oi v1.0.0/go.mod h1:RrDBct90BAhoDTxB1fenZwfykqeGvhI6LsNfStJoEkI=
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e h1:quuzZLi72kkJjl+f5AQ93FMcadG19WkS7MO6TXFOSas=
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e/go.mod h1:+5vNVvEWwEIx86DB9Ke/+a5wBI464eDRo3eF0LcfpWg=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/siddontang/go-log v0.0.0-20180807004314-8d05993dda07 h1:oI+RNwuC9jF2g2lP0u0cVEEZrc/AYBCuFdvwrLWM/6Q=
github.com/siddontang/go-log v0.0.0-20180807004314-8d05993dda07/go.mod h1:yFdBgwXP24JziuRl2NMUahT7nGLNOKi1SIiFxMttVD4=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/withlin/canal-go v1.1.2 h1:ugAjPPXB1g6sePQLei/l7eaZ57ioJSo87/+z4++H2hY=
github.com/withlin/canal-go v1.1.2/go.mod h1:VlapEcKekyXd7luA6QzflxbisrYzSLAjpRqzLcgr+zk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

75
proxy/logger/logger.go Normal file
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
proxy/main.go Normal file
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 {}
}

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
proxy/redis/client.go Normal file
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
proxy/util/logger_conf/.gitignore vendored Normal file
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

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

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.

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
proxy/util/logger_util/.gitignore vendored Normal file
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

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

View File

@@ -0,0 +1,9 @@
# Change Log
---
2020-03-xx-xx
---
- Implemented enchacements:
- Fixed bugs:
- Closed issues:

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.

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"`
}

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
}

View File

@@ -0,0 +1,7 @@
package version
var VERSION = "2020-03-31-01"
func GetVersion() (version string) {
return VERSION
}