You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

377 lines
11 KiB
Go

package simphone
import (
"bytes"
"fmt"
"os"
"strings"
"sync"
"time"
"github.com/google/uuid"
"gitlab.com/ics_cinnamon/voicegateway/icsconf"
"gitlab.com/ics_cinnamon/voicegateway/icserror"
"gitlab.com/ics_cinnamon/voicegateway/icslog"
"gitlab.com/ics_cinnamon/voicegateway/icsmediaconv"
"gitlab.com/ics_cinnamon/voicegateway/icsnet"
"gitlab.com/ics_cinnamon/voicegateway/icssvc"
"gitlab.com/ics_cinnamon/voicegateway/sim/icspacketgen"
"gitlab.com/ics_cinnamon/voicegateway/sim/simprocnew"
)
type SimPhone struct {
isCaller bool
ID int
CallID string
PayloadType int
SSRC uint32
Seq uint16
Timestamp uint32
TSIPPort int
SIPPort int
RTPTxPort int
RTPCBTxPort int
TRTPTxPort int
lsaddr *icsnet.IcsNetAddr //local sip addr
laddr *icsnet.IcsNetAddr //local rtp addr
rsaddr *icsnet.IcsNetAddr //remote sip addr
raddr *icsnet.IcsNetAddr //remote rtp addr
localRTPUDP *icsnet.IcsUDPNet
sentTime int
sendRTPStatus bool
expTime time.Time
mediaStart int
wgMedia sync.WaitGroup
rtptimer *time.Timer
}
func NewSimPhone(id int) *SimPhone {
s := &SimPhone{}
simconf := icsconf.GetSimConfig()
s.ID = id
if strings.Compare("YES", strings.ToUpper(simconf.IsCaller)) == 0 {
s.CallID = uuid.New().String()
s.isCaller = true
//fmt.Println("Call ID -", s.CallID)
}
s.SSRC = icspacketgen.GenSSRC()
s.Seq = 1
s.PayloadType = icsmediaconv.ICS_PT_ALAW
s.SIPPort = simconf.SimPhoneConfig.SIPPort
s.TSIPPort = simconf.TargetPhoneConfig.TSIPPort
s.TRTPTxPort = simconf.TargetPhoneConfig.TRTPPort + (s.ID * 2) //targetRTPTxPort
s.RTPTxPort = simconf.SimPhoneConfig.RTPPort + (s.ID * 2) //localRTPTxPort
la1 := icsnet.NewNetAddrWithIPPort(simconf.SimPhoneConfig.MYIP, s.SIPPort)
s.lsaddr = &la1
la2 := icsnet.NewNetAddrWithIPPort(simconf.SimPhoneConfig.MYIP, s.RTPTxPort)
s.laddr = &la2
s.sentTime = 0
s.sendRTPStatus = false
s.wgMedia = sync.WaitGroup{}
return s
}
func (s *SimPhone) SetRemoteAddr(saddr *icsnet.IcsNetAddr, addr *icsnet.IcsNetAddr) { //sip addr, rtp addr
s.rsaddr = saddr
s.raddr = addr
}
func (s *SimPhone) Run() *icserror.IcsError {
svc := icssvc.GetServiceStatus()
l := icslog.GetIcsLog()
l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Phone[%d] Started! SIP addr: %v, RTP addr: %v\n",
s.ID, s.lsaddr, s.laddr)
l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "%s\n", s.String())
simconf := icsconf.GetSimConfig()
//make rtp event timer
s.rtptimer = time.NewTimer(time.Millisecond)
rtpReadTimer := time.NewTicker(time.Second)
wgRTPListen := sync.WaitGroup{}
//create rtp liesten goroutine
s.localRTPUDP = icsnet.NewUDP(s.laddr, nil)
lerr := s.localRTPUDP.Listen()
if lerr == nil {
wgRTPListen.Add(1)
go func() {
fmt.Println("############### start rtp", s.laddr)
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Start RTP Listen[%v]\n", s.laddr)
totalRlen := 0
for s.mediaStart != 2 || !svc.GetExit() || !svc.GetStop() {
_, _, rlen, rtperr := s.localRTPUDP.ReadRTP()
if rtperr == nil {
s.expTime = time.Now()
totalRlen += rlen
} else {
fmt.Printf("\nTotal Recved RTP Length[%d]\n", totalRlen)
fmt.Println("##### id : ", s.ID)
break
}
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Stoped[%d] RTP Listen[%v] Total Recved RTP length %d\n", s.mediaStart, s.laddr, totalRlen)
wgRTPListen.Done()
}()
} else {
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to listen RTP[%v] - %v\n", s.laddr, lerr)
return nil
}
///////////////////////////
//CALLER SIDE
l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "CALLER SIDE")
id := fmt.Sprintf("%d", s.ID+7000)
toid := fmt.Sprintf("%d", s.ID+21016)
fmt.Println("############################################################################## id : ", id)
fmt.Println("############################################################################## id : ", toid)
fmt.Println("############################################################################## id : ", s.TRTPTxPort)
ra := icsnet.NewNetAddrWithIPPort(simconf.GetSimTargetIP(), s.TSIPPort)
s.rsaddr = &ra
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "SIP address [%v] [%v]", s.lsaddr, s.rsaddr)
localSIPUDP := icsnet.NewUDP(s.lsaddr, s.rsaddr)
serr := localSIPUDP.Connect(s.lsaddr, s.rsaddr)
if serr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to Connect [%v]->[%v]", s.lsaddr, s.rsaddr)
return serr
}
/////////////////////
// send regi sip
fmt.Println("###################### regi")
if simconf.RegiCount != 0 {
regiCount := 0
for {
buf, rlen, err := simprocnew.NewReadSIP(s.ID, s.CallID, simconf.SimPhoneConfig.MYIP, s.TSIPPort, ra, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP)
if err != nil {
fmt.Println(err)
}
n := bytes.Index(buf[:rlen], []byte{32})
if string(buf[:n]) == "REGISTER" {
regiSip := simprocnew.NewSIPSignal("REGI", s.ID, id, toid, ra, s.CallID, simconf.SimPhoneConfig.MYIP, s.TSIPPort, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP, buf, rlen)
if regiSip != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Send Invite error [%s]", regiSip)
return regiSip
}
regiCount += 1
}
if regiCount == simconf.RegiCount {
break
}
}
}
// time.Sleep(time.Second * 2)
////////////////////
// get call flow //
///////////////////
// ra = icsnet.NewNetAddrWithIPPort(simconf.GetSimTargetIP(), s.TRTPTxPort)
// l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Start sending RTP[%s:%d]", ra.IPv4String, ra.Port)
// s.raddr = &ra
// s.localRTPUDP.SetRemoteAddr(s.raddr)
simScenarioConf := icsconf.GetSimScenarioConfig()
// var stopByeTimer *time.Ticker
for _, ord := range simScenarioConf.SipOrder.Order {
fmt.Println("######################################################## : ", strings.ToUpper(ord))
switch strings.ToUpper(ord) {
// case "WAIT": // set send bye time
// stopByeTimer = time.NewTicker(time.Second * time.Duration(simScenarioConf.SipOrder.StopTime))
case "BYE":
go func() {
// if stopByeTimer != nil {
// <-stopByeTimer.C
// }
sendSip := simprocnew.NewSIPSignal("BYE", s.ID, id, toid, ra, s.CallID, simconf.SimPhoneConfig.MYIP, s.TRTPTxPort, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP, nil, 0)
if sendSip != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Send bye error [%s]", sendSip)
return
}
}()
case "ACK":
sendSip := simprocnew.NewSIPSignal(strings.ToUpper(ord), s.ID, id, toid, ra, s.CallID, simconf.SimPhoneConfig.MYIP, s.TRTPTxPort, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP, nil, 0)
if sendSip != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Send SIP error (except BYE) [%s]", sendSip)
return sendSip
} else {
go func() {
buf, rlen, err := simprocnew.NewReadSIP(s.ID, s.CallID, simconf.SimPhoneConfig.MYIP, s.TRTPTxPort, ra, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP)
if err != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv BYE - %v", err)
return
} else {
fmt.Println(string(buf[:rlen]))
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Receved BYE Message : %s", string(buf[:rlen]))
// stopByeTimer.Stop()
sendSip := simprocnew.NewSIPSignal("BYE200", s.ID, id, toid, ra, s.CallID, simconf.SimPhoneConfig.MYIP, s.TRTPTxPort, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP, nil, 0)
if sendSip != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Send bye error [%s]", sendSip)
return
} else {
// s.mediaStart = 1
// s.wgMedia.Wait()
}
}
}()
}
case "TTS":
go s.ExpireReadRTP(rtpReadTimer)
for {
if s.sendRTPStatus {
break
}
}
case "STT":
// send rtp
ra = icsnet.NewNetAddrWithIPPort(simconf.GetSimTargetIP(), s.TRTPTxPort)
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Start sending RTP[%s:%d]", ra.IPv4String, ra.Port)
s.raddr = &ra
s.localRTPUDP.SetRemoteAddr(s.raddr)
s.wgMedia.Add(1)
go s.RunMedia(s.raddr.Port, s.PayloadType)
// s.mediaStart = 1
s.wgMedia.Wait()
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sending RTP Done!")
s.mediaStart = 2
case "DTMF":
default:
sendSip := simprocnew.NewSIPSignal(strings.ToUpper(ord), s.ID, id, toid, ra, s.CallID, simconf.SimPhoneConfig.MYIP, s.TRTPTxPort, s.laddr, s.rsaddr, s.lsaddr, localSIPUDP, nil, 0)
if sendSip != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Send SIP error (except BYE) [%s]", sendSip)
return sendSip
}
}
}
s.localRTPUDP.Close()
wgRTPListen.Wait()
s.rtptimer.Stop()
return nil
}
func (s *SimPhone) RunMedia(port int, pt int) {
fmt.Println("#### RunMedia")
defer func() {
s.wgMedia.Done()
}()
l := icslog.GetIcsLog()
simconf := icsconf.GetSimConfig()
var voiceFileName string
if strings.Compare(simconf.IsCaller, "yes") == 0 {
voiceFileName = "./voice/9012-RX-1649749470147018876.raw"
} else {
voiceFileName = "./voice/9012-RX-1649749470147018876.raw"
}
fp, err := os.Open(voiceFileName)
if err != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to Voice file-%v", err)
if s.isCaller {
s.wgMedia.Done()
}
return
}
defer fp.Close()
fs, err := os.Stat(voiceFileName)
if err != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to Voice file-%v", err)
if s.isCaller {
s.wgMedia.Done()
}
return
}
fileLen := fs.Size()
voiceIdx := 0
voiceBuf := make([]byte, fileLen)
flen, err := fp.Read(voiceBuf)
if flen <= 0 || err != nil {
l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to Voice file-%v", err)
if s.isCaller {
s.wgMedia.Done()
}
return
}
ra := icsnet.NewNetAddrWithIPPort(simconf.GetSimTargetIP(), s.TRTPTxPort)
s.localRTPUDP.SetRemoteAddr(&ra)
before := time.Now()
for {
<-s.rtptimer.C
s.rtptimer.Reset(time.Millisecond)
if s.mediaStart == 0 {
time.Sleep(time.Millisecond * 2)
// continue
} else if s.mediaStart == 2 {
break
}
now := time.Now()
var delta time.Duration = (time.Millisecond * 20) - now.Sub(before)
if delta < 0 {
time.Sleep((time.Millisecond * 20) + delta)
} else {
time.Sleep((time.Millisecond * 20) - delta)
}
before = now
r := icspacketgen.NewRTP()
rtppacket := r.MakeRTPData(uint8(pt), &s.Seq, &s.Timestamp, s.SSRC, voiceBuf[voiceIdx:voiceIdx+160])
voiceIdx += 160
if int64(voiceIdx+160) >= fileLen {
voiceIdx = len(voiceBuf) - 1
rtppacket = r.MakeRTPData(uint8(pt), &s.Seq, &s.Timestamp, s.SSRC, voiceBuf[voiceIdx:])
break
}
wlen, werr := s.localRTPUDP.WriteRTP(rtppacket)
if werr != nil {
l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to write RTP packet %d-%s{%v}", wlen, werr.GetMessage(), werr.GetError())
if s.isCaller {
s.wgMedia.Done()
}
return
}
}
l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Voice data length %d-%d", voiceIdx, s.sentTime)
s.sendRTPStatus = false
}
func (s *SimPhone) String() string {
return fmt.Sprintf("ID: %d\nCall ID: %s\nPayload Type: %d\nSIP Port: %d\nTRTPTxPort: %d",
s.ID, s.CallID, s.PayloadType, s.SIPPort, s.TRTPTxPort)
}
func (s *SimPhone) ExpireReadRTP(t *time.Ticker) {
// s.sendRTPStatus = false
s.expTime = time.Now()
for t := range t.C {
// if s.sendRTPStatus {
// s.sendRTPStatus = false
// } else
if time.Now().Sub(s.expTime) >= time.Second {
fmt.Println(t)
s.sendRTPStatus = true
break
} else if s.sendRTPStatus {
continue
}
}
}