290 lines
14 KiB
Go
290 lines
14 KiB
Go
package cdr
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
|
|
"be.ems/lib/dborm"
|
|
"be.ems/lib/global"
|
|
"be.ems/lib/log"
|
|
"be.ems/lib/services"
|
|
"be.ems/restagent/config"
|
|
wsService "be.ems/src/modules/ws/service"
|
|
)
|
|
|
|
var (
|
|
UriIMSCDREvent = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrEvent"
|
|
UriIMSCDRFile = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrFile"
|
|
UriSMFCDREvent = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/smf/objectType/cdrEvent"
|
|
UriSMFCDRFile = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/smf/objectType/cdrFile"
|
|
|
|
CustomUriIMSCDREvent = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrEvent"
|
|
CustomUriIMSCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrFile"
|
|
CustomUriSMFCDREvent = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrEvent"
|
|
CustomUriSMFCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrFile"
|
|
)
|
|
|
|
// SMF CDR
|
|
type CdrSubscriptionID struct {
|
|
SubscriptionIDType string `json:"subscriptionIDType"`
|
|
SubscriptionIDData string `json:"subscriptionIDData"`
|
|
}
|
|
|
|
type CdrNetWorkFuctionInfomation struct {
|
|
NetworkFunctionality string `json:"networkFunctionality"`
|
|
NetworkFunctionName string `json:"networkFunctionName,omitempty"`
|
|
NetworkFunctionIPv4Address string `json:"networkFunctionIPv4Address,omitempty"`
|
|
NetworkFunctionIPv6Address string `json:"networkFunctionIPv6Address,omitempty"`
|
|
}
|
|
|
|
type SMFTrigger string
|
|
|
|
const (
|
|
TimeThresholdReached SMFTrigger = "timeThresholdReached"
|
|
VolumeThresholdReached SMFTrigger = "volumeThresholdReached"
|
|
UnitThresholdReached SMFTrigger = "unitThresholdReached"
|
|
TimeQuotaExhausted SMFTrigger = "timeQuotaExhausted"
|
|
VolumeQuotaExhausted SMFTrigger = "volumeQuotaExhausted"
|
|
UnitQuotaExhausted SMFTrigger = "unitQuotaExhausted"
|
|
ExpiryOfQuotaValidityTime SMFTrigger = "expiryOfQuotaValidityTime"
|
|
ExpiryOfQuotaHoldingTime SMFTrigger = "expiryOfQuotaHoldingTime"
|
|
EndOfPDUSession SMFTrigger = "endOfPDUSession"
|
|
)
|
|
|
|
type CdrSMFTrigger struct {
|
|
SMFTrigger SMFTrigger `json:"sMFTrigger"`
|
|
}
|
|
|
|
type CdrQuotaManagementIndicator string
|
|
|
|
// List of QuotaManagementIndicator
|
|
const (
|
|
Cdr_QMI_ONLINE_CHARGING CdrQuotaManagementIndicator = "ONLINE_CHARGING"
|
|
Cdr_QMI_OFFLINE_CHARGING CdrQuotaManagementIndicator = "OFFLINE_CHARGING"
|
|
Cdr_QMI_QUOTA_MANAGEMENT_SUSPENDED CdrQuotaManagementIndicator = "QUOTA_MANAGEMENT_SUSPENDED"
|
|
)
|
|
|
|
type CdrUsedUnitContainer struct {
|
|
ServiceIdentifier *int32 `json:"serviceIdentifier,omitempty"`
|
|
QuotaManagementIndicatorExt CdrQuotaManagementIndicator `json:"quotaManagementIndicatorExt,omitempty"`
|
|
Triggers []SMFTrigger `json:"triggers,omitempty"`
|
|
TriggerTimestamp *time.Time `json:"triggerTimestamp,omitempty"`
|
|
Time *uint32 `json:"time,omitempty"`
|
|
DataTotalVolume *uint64 `json:"dataTotalVolume,omitempty"`
|
|
DataVolumeUplink *uint64 `json:"dataVolumeUplink,omitempty"`
|
|
DataVolumeDownlink *uint64 `json:"dataVolumeDownlink,omitempty"`
|
|
ServiceSpecificUnits *uint64 `json:"serviceSpecificUnits,omitempty"`
|
|
EventTimeStamp *time.Time `json:"eventTimeStamp,omitempty"`
|
|
LocalSequenceNumber int32 `json:"localSequenceNumber"`
|
|
//PDUContainerInformation *PduContainerInformation `json:"pDUContainerInformation,omitempty"`
|
|
//NSPAContainerInformation *NspaContainerInformation `json:"nSPAContainerInformation,omitempty"`
|
|
}
|
|
|
|
type CdrMultipleUnitUsage struct {
|
|
RatingGroup uint32 `json:"ratingGroup" yaml:"ratingGroup" bson:"ratingGroup" mapstructure:"RatingGroup"`
|
|
UsedUnitContainer []CdrUsedUnitContainer `json:"usedUnitContainer,omitempty" yaml:"usedUnitContainer" bson:"usedUnitContainer" mapstructure:"UsedUnitContainer"`
|
|
//UPFID string `json:"uPFID,omitempty" yaml:"uPFID" bson:"uPFID" mapstructure:"UPFID"`
|
|
}
|
|
|
|
type CdrSubscriberEquipmentNumber struct {
|
|
SubscriberEquipmentNumberType string `json:"subscriberEquipmentNumberType"`
|
|
SubscriberEquipmentNumberData string `json:"subscriberEquipmentNumberData"`
|
|
}
|
|
|
|
type CdrNetworkSliceInstanceID struct {
|
|
SST int32 `json:"sST"`
|
|
|
|
SD string `json:"sD,omitempty"`
|
|
}
|
|
|
|
type CdrPduAddress struct {
|
|
PDUIPv4Address string `json:"pDUIPv4Address,omitempty"`
|
|
PDUIPv6AddresswithPrefix string `json:"pDUIPv6AddresswithPrefix,omitempty"`
|
|
IPV4dynamicAddressFlag bool `json:"iPV4dynamicAddressFlag,omitempty"`
|
|
IPV6dynamicPrefixFlag bool `json:"iPv6dynamicPrefixFlag,omitempty"`
|
|
}
|
|
|
|
type CdrArp struct {
|
|
PriorityLevel int32 `json:"priorityLevel"`
|
|
PreemptionCapability string `json:"preemptionCapability"`
|
|
PreemptionVulnerability string `json:"preemptionVulnerability"`
|
|
}
|
|
|
|
type CdrAuthorizedQosInformation struct {
|
|
FiveQi int `json:"fiveQi"`
|
|
ARP *CdrArp `json:"aRP,omitempty"`
|
|
PriorityLevel *int32 `json:"priorityLevel,omitempty"`
|
|
AverWindow *int32 `json:"averWindow,omitempty"`
|
|
MaxDataBurstVol *int32 `json:"maxDataBurstVol,omitempty"`
|
|
}
|
|
|
|
type CdrSubscribedDefaultQos struct {
|
|
FiveQi int32 `json:"fiveQi,omitempty"`
|
|
ARP CdrArp `json:"aRP,omitempty"`
|
|
PriorityLevel *int32 `json:"priorityLevel,omitempty"`
|
|
}
|
|
|
|
type CdrSessionAmbr struct {
|
|
Uplink string `json:"uplink"`
|
|
|
|
Downlink string `json:"downlink"`
|
|
}
|
|
|
|
type CdrPDUSessionChargingInformation struct {
|
|
PDUSessionChargingID int32 `json:"pDUSessionChargingID"`
|
|
UserIdentifier string `json:"userIdentifier,omitempty"` // isdn
|
|
UserEquipmentInfo *CdrSubscriberEquipmentNumber `json:"userEquipmentInfo,omitempty"` // imei/imeisv
|
|
//UserLocationInfomation *UserLocation `json:"userLocationinfo,omitempty"`
|
|
UserRoamerInOut string `json:"userRoamerInOut,omitempty"`
|
|
PDUSessionId int32 `json:"pDUSessionId"`
|
|
NetworkSliceInstanceID *CdrNetworkSliceInstanceID `json:"networkSliceInstanceID,omitempty"`
|
|
//PDUType PduSessionType `json:"pDUType,omitempty"`
|
|
SSCMode string `json:"sSCMode,omitempty"`
|
|
DNNID string `json:"dNNID"`
|
|
SUPIPLMNIdentifier string `json:"sUPIPLMNIdentifier,omitempty"`
|
|
//ServingNetworkFunctionID *ServingNetworkFunctionId `json:"servingNetworkFunctionID,omitempty"`
|
|
//RATType RatType `json:"rATType,omitempty"`
|
|
DataNetworkNameIdentifier string `json:"dataNetworkNameIdentifier,omitempty"`
|
|
PDUAddress CdrPduAddress `json:"pDUAddress,omitempty"`
|
|
AuthorizedQoSInformation *CdrAuthorizedQosInformation `json:"authorizedQoSInformation,omitempty"`
|
|
UETimeZone string `json:"uETimeZone,omitempty"`
|
|
PDUSessionstartTime *time.Time `json:"pDUSessionstartTime,omitempty"`
|
|
PDUSessionstopTime *time.Time `json:"pDUSessionstopTime,omitempty"`
|
|
Diagnostics *int `json:"diagnostics,omitempty"`
|
|
ChargingCharacteristics string `json:"chargingCharacteristics,omitempty"`
|
|
ChChSelectionMode string `json:"chChSelectionMode,omitempty"`
|
|
ThreeGPPPSDataOffStatus string `json:"threeGPPPSDataOffStatus,omitempty"`
|
|
//RANSecondaryRATUsageReport *RanSecondaryRatUsageReport `json:"rANSecondaryRATUsageReport,omitempty"`
|
|
SubscribedQoSInformation *CdrSubscribedDefaultQos `json:"subscribedQoSInformation,omitempty"`
|
|
AuthorizedSessionAMBR *CdrSessionAmbr `json:"authorizedSessionAMBR,omitempty"`
|
|
SubscribedSessionAMBR *CdrSessionAmbr `json:"subscribedSessionAMBR,omitempty"`
|
|
ServingCNPLMNID string `json:"servingCNPLMNID,omitempty"`
|
|
DnnSelectionMode string `json:"dnnSelectionMode,omitempty"`
|
|
HomeProvidedChargingID int32 `json:"homeProvidedChargingID,omitempty"`
|
|
|
|
//MAPDUNon3GPPUserLocationInfo *UserLocation `json:"mAPDUNon3GPPUserLocationInfo,omitempty" yaml:"mAPDUNon3GPPUserLocationInfo" bson:"mAPDUNon3GPPUserLocationInfo" mapstructure:"MAPDUNon3GPPUserLocationInfo"`
|
|
//PresenceReportingAreaInformation map[string]PresenceInfo `json:"presenceReportingAreaInformation,omitempty" yaml:"presenceReportingAreaInformation" bson:"presenceReportingAreaInformation" mapstructure:"PresenceReportingAreaInformation"`
|
|
}
|
|
|
|
type CauseForRecordClosing string
|
|
|
|
const (
|
|
NormalRelease CauseForRecordClosing = "normalRelease"
|
|
PartialRecord CauseForRecordClosing = "partialRecord"
|
|
AbnormalRelease CauseForRecordClosing = "abnormalRelease"
|
|
CAMELInitCallRelease CauseForRecordClosing = "cAMELInitCallRelease"
|
|
VolumeLimit CauseForRecordClosing = "volumeLimit"
|
|
TimeLimit CauseForRecordClosing = "timeLimit"
|
|
ServingNodeChange CauseForRecordClosing = "servingNodeChange"
|
|
MaxChangeCond CauseForRecordClosing = "maxChangeCond"
|
|
ManagementIntervention CauseForRecordClosing = "managementIntervention"
|
|
IntraSGSNIntersystemChange CauseForRecordClosing = "intraSGSNIntersystemChange"
|
|
RATChange CauseForRecordClosing = "rATChange"
|
|
MSTimeZoneChange CauseForRecordClosing = "mSTimeZoneChange"
|
|
SGSNPLMNIDChange CauseForRecordClosing = "sGSNPLMNIDChange "
|
|
SGWChange CauseForRecordClosing = "sGWChange"
|
|
APNAMBRChange CauseForRecordClosing = "aPNAMBRChange"
|
|
)
|
|
|
|
type ChargingRecord struct {
|
|
RecordType string `json:"recordType"`
|
|
ChargingID int `json:"chargingID"`
|
|
RecordingNetworkFunctionID string `json:"recordingNetworkFunctionID"` // UUID
|
|
SubscriberIdentifier CdrSubscriptionID `json:"subscriberIdentifier,omitempty"`
|
|
NFunctionConsumerInformation CdrNetWorkFuctionInfomation `json:"nFunctionConsumerInformation"`
|
|
Triggers []CdrSMFTrigger `json:"triggers,omitempty"`
|
|
ListOfMultipleUnitUsage []CdrMultipleUnitUsage `json:"listOfMultipleUnitUsage,omitempty"`
|
|
RecordOpeningTime string `json:"recordOpeningTime"`
|
|
Duration int `json:"duration"`
|
|
RecordSequenceNumber int `json:"recordSequenceNumber,omitempty"`
|
|
CauseForRecClosing CauseForRecordClosing `json:"causeForRecClosing"`
|
|
Diagnostics *int `json:"diagnostics,omitempty"`
|
|
LocalRecordSequenceNumber int `json:"localRecordSequenceNumber,omitempty"`
|
|
PDUSessionChargingInformation CdrPDUSessionChargingInformation `json:"pDUSessionChargingInformation,omitempty"`
|
|
InvocationTimestamp string `json:"invocationTimestamp,omitempty"`
|
|
}
|
|
|
|
type CDREvent struct {
|
|
NeType string `json:"neType" xorm:"ne_type"`
|
|
NeName string `json:"neName" xorm:"ne_name"`
|
|
RmUID string `json:"rmUID" xorm:"rm_uid"`
|
|
Timestamp int `json:"timestamp" xorm:"timestamp"`
|
|
CDR map[string]any `json:"CDR" xorm:"cdr_json"`
|
|
}
|
|
|
|
func PostCDREventFromIMS(w http.ResponseWriter, r *http.Request) {
|
|
log.Info("PostCDREventFromIMS processing... ")
|
|
|
|
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
|
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
|
if err != nil {
|
|
log.Error("Faile to io.ReadAll: ", err)
|
|
services.ResponseNotFound404UriNotExist(w, r)
|
|
return
|
|
}
|
|
|
|
cdrEvent := new(CDREvent)
|
|
err = json.Unmarshal(body, &cdrEvent)
|
|
if cdrEvent.NeType == "" || err != nil {
|
|
log.Error("Failed to Unmarshal cdrEvent:", err)
|
|
services.ResponseInternalServerError500ProcessError(w, err)
|
|
return
|
|
}
|
|
log.Trace("cdrEvent:", cdrEvent)
|
|
|
|
affected, err := dborm.XormInsertTableOne("cdr_event_ims", cdrEvent)
|
|
if err != nil && affected <= 0 {
|
|
log.Error("Failed to insert cdr_event_ims:", err)
|
|
services.ResponseInternalServerError500ProcessError(w, err)
|
|
return
|
|
}
|
|
|
|
// 推送到ws订阅组
|
|
if v, ok := cdrEvent.CDR["recordType"]; ok {
|
|
if v == "MOC" || v == "MTSM" {
|
|
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_IMS_CDR, cdrEvent)
|
|
}
|
|
}
|
|
|
|
services.ResponseStatusOK204NoContent(w)
|
|
}
|
|
|
|
func PostCDREventFromSMF(w http.ResponseWriter, r *http.Request) {
|
|
log.Info("PostCDREventFromSMF processing... ")
|
|
|
|
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
|
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
|
if err != nil {
|
|
log.Error("Faile to io.ReadAll: ", err)
|
|
services.ResponseNotFound404UriNotExist(w, r)
|
|
return
|
|
}
|
|
|
|
cdrEvent := new(CDREvent)
|
|
err = json.Unmarshal(body, &cdrEvent)
|
|
if cdrEvent.NeType == "" || err != nil {
|
|
log.Error("Failed to Unmarshal cdrEvent:", err)
|
|
services.ResponseInternalServerError500ProcessError(w, err)
|
|
return
|
|
}
|
|
log.Trace("cdrEvent:", cdrEvent)
|
|
|
|
affected, err := dborm.XormInsertTableOne("cdr_event_smf", cdrEvent)
|
|
if err != nil && affected <= 0 {
|
|
log.Error("Failed to insert cdr_event_smf:", err)
|
|
services.ResponseInternalServerError500ProcessError(w, err)
|
|
return
|
|
}
|
|
|
|
// 推送到ws订阅组
|
|
// if v, ok := cdrEvent.CDR["recordType"]; ok {
|
|
// if v == "MOC" || v == "MTSM" {
|
|
// wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_IMS_CDR, cdrEvent)
|
|
// }
|
|
// }
|
|
|
|
services.ResponseStatusOK204NoContent(w)
|
|
}
|