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 }