package icssessionmanager

import (
	"io/ioutil"
	"fmt"
	// "net"
	"math/rand"
	"runtime/debug"
	"strconv"
	"strings"
	"time"

	"github.com/google/uuid"
	"gitlab.com/ics_cinnamon/voicegateway/icscbtimer"
	"gitlab.com/ics_cinnamon/voicegateway/icsconf"
	"gitlab.com/ics_cinnamon/voicegateway/icsdtmf"
	"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/icspacketparser"
	"gitlab.com/ics_cinnamon/voicegateway/icsrtp"
	"gitlab.com/ics_cinnamon/voicegateway/icssvc"
	"gitlab.com/ics_cinnamon/voicegateway/recorddata"
	"gitlab.com/ics_cinnamon/voicegateway/recorddata/writecallsignal"
	"gitlab.com/ics_cinnamon/voicegateway/sipasm"
)

func (s *IcsSession) SetRegisterStatus(status int) int {
	s.registerStatus = status

	return s.registerStatus
}

func (s IcsSession) GetRegisterStatus() int {
	return s.registerStatus
}

func (s *IcsSession) SetAgentStatus(status int) int {
	s.agentStatus = status

	return s.agentStatus
}

func (s IcsSession) GetAgentStatus() int {
	return s.agentStatus
}

//response register
func (s *IcsSession) ProcRegister(sip *icspacketparser.SIP) *icserror.IcsError {
	l := icslog.GetIcsLog()

	//check expires header value
	expires := sip.Headers["EXPIRES"][0]
	if len(expires) == 0 {
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Invalid SIP - No Expires header")
		return nil
	}
	expN, cerr := strconv.Atoi(expires)
	if cerr != nil {
		return icserror.ICSERRStrConv
	}

	//remove register
	if expN == 0 {
		//stop callback timer
		s.RegisterCallBackTimer.Stop()

		//make response
		resSIP := sipasm.NewSIPResponse(sip, 200)
		resSIP.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR, "")

		//send response
		wlen, werr := (*s.sipNeter).WriteSIP([]byte(resSIP.String()))
		if werr != nil {
			l.Print(icslog.LOG_LEVEL_FATAL, -1, werr.GetMessage())
			return icserror.ICSERRNETWriteError
		}
		l.Printf(icslog.LOG_LEVEL_INFO, -1, "Sent Data(%d) [%s]->[%s]>\n%s",
			wlen,
			(*s.sipNeter).LocalAddr().String(),
			(*s.sipNeter).RemoteAddr().String(),
			resSIP.String())
	}

	return nil
}

//register callback timer function
func (s *IcsSession) RequestRegisterCB(t *icscbtimer.IcsCBTimer) {
	l := icslog.GetIcsLog()

	for s.GetRegisterStatus() == STATUS_REGISTER_NOT_READY {
		time.Sleep(time.Millisecond)
	}

	conf := icsconf.GetIcsConfig()
	ip := conf.InfoConfig.ServerIP
	port := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport

	regifunc := func(t *time.Time) {
		regiMethod := fmt.Sprintf("sip:%s;transport=%s", ip, transport)
		reqRegi := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_REGISTER, regiMethod)

		via := fmt.Sprintf("SIP/2.0/UDP %s;rport;branch=%s", ip, sipasm.GenerateBranch())
		maxforwards := "70"
		from := fmt.Sprintf("<sip:%s@%s>;tag=%s", s.AgentName, ip, sipasm.GenerateTag())

		s.uri = fmt.Sprintf("sip:%s@%s", s.AgentName, ip)
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set URI [%s]", s.uri)

		to := fmt.Sprintf("<sip:%s@%s>", s.AgentName, ip)
		postfix := fmt.Sprintf("@%s", ip)
		var callid string
		if len(s.callID) != 0 {
			callid = s.callID
			//if len(s.regiCallID) != 0 {
			//callid = s.regiCallID
		} else {
			callid = sipasm.GenerateCallID(postfix)
		}
		cseq := fmt.Sprintf("%d REGISTER", s.Cseq)
		s.Cseq++
		contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, port, transport)
		expires := fmt.Sprintf("%d", conf.AgentConfig[s.ID].RegisterConfig.RegisterExpire)
		userAgent := conf.InfoConfig.Product
		allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
		supported := "timer,path,replaces"
		contentLength := "0"

		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, via)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, from)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, to)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, callid)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, cseq)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_EXPIRES, expires)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, contentLength)
		reqRegi.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

		s.callID = callid
		//s.regiCallID = callid
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID,
			"Session Allocated[%d] Call ID: %s==========================",
			s.goroutineID, s.callID)

		wlen, werr := (*s.sipNeter).WriteSIP([]byte(reqRegi.String()))
		if werr != nil {
			l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
			return
		}
		s.SetRegisterStatus(STATUS_REGISTER_REQUEST)
		s.SetSessionMethodWithType(ICS_SIP_AUTOMATA_REGISTER)

		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
			wlen,
			(*s.sipNeter).LocalAddr().String(),
			(*s.sipNeter).RemoteAddr().String(),
			reqRegi.String())

		//fmt.Println(reqRegi)
		//fmt.Println(wlen)
	}
	regifunc(nil)

	for t1 := range t.GetTick() {
		//fmt.Println(s.ID, t1)
		regifunc(&t1)
	}

}

func (s *IcsSession) RequestInviteCB(inviteto string, t *icscbtimer.IcsCBTimer) {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	inviteFunc := func() {
		status := s.GetAgentStatus()
		if status == STATUS_AGENT_READY {
			ip := conf.InfoConfig.ServerIP
			port := conf.SIPConfig.Port
			mediaPort := conf.AgentConfig[s.ID].MediaConfig.Port
			proxy := conf.SIPConfig.SIPProxy
			transport := conf.SIPConfig.Transport
			format := conf.AgentConfig[s.ID].MediaConfig.Format

			inviteMethod := fmt.Sprintf("sip:%s@%s;transport=%s", inviteto, proxy, transport)
			reqInvite := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_INVITE, inviteMethod)

			via := fmt.Sprintf("SIP/2.0/UDP %s;rport;branch=%s", ip, sipasm.GenerateBranch())
			maxforwards := "70"
			from := fmt.Sprintf("<sip:%s@%s:5090>;tag=%s", s.AgentName, ip, sipasm.GenerateTag())

			s.uri = fmt.Sprintf("sip:%s@%s", s.AgentName, ip)
			l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set URI [%s]", s.uri)

			to := fmt.Sprintf("<sip:%s@%s;user=phone>", "01025670081", ip)
			//to := fmt.Sprintf("<sip:%s@%s>", s.AgentName, ip)
			postfix := fmt.Sprintf("@%s", ip)
			var callid string
			if len(s.callID) != 0 {
				callid = s.callID
				//if len(s.regiCallID) != 0 {
				//callid = s.regiCallID
			} else {
				callid = sipasm.GenerateCallID(postfix)
			}
			cseq := fmt.Sprintf("%d INVITE", s.Cseq)
			s.Cseq++
			contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, port, transport)
			//expires := fmt.Sprintf("%d", conf.AgentConfig[s.ID].RegisterConfig.RegisterExpire)
			userAgent := conf.InfoConfig.Product
			allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
			supported := "timer,path,replaces"

			formats := strings.Split(format, " ")
			reqInvite.SDP = sipasm.NewSDPMessage(ip, mediaPort, formats[:], 0)
			sdpLength := fmt.Sprintf("%d", len(reqInvite.SDP.String()))

			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, via)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, from)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, to)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, callid)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, cseq)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
			//reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_EXPIRES, expires)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_TYPE, "application/sdp")
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, sdpLength)
			reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

			wlen, werr := (*s.sipNeter).WriteSIP([]byte(reqInvite.String()))
			if werr != nil {
				l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
				return
			}

			s.callID = callid

			s.SetAgentStatus(STATUS_AGENT_CALLING)

			l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
				wlen,
				(*s.sipNeter).LocalAddr().String(),
				(*s.sipNeter).RemoteAddr().String(),
				reqInvite.String())
		}
	}
	inviteFunc()

	for t1 := range t.GetTick() {
		fmt.Println(s.ID, t1)
		t.Stop()
	}
}

func (s *IcsSession) RequestInvite(inviteto string) {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	inviteFunc := func() {
		ip := conf.InfoConfig.ServerIP
		// port := conf.SIPConfig.Port
		mediaPort := conf.AgentConfig[s.ID].MediaConfig.Port
		// proxy := conf.SIPConfig.SIPProxy
		transport := conf.SIPConfig.Transport
		format := conf.AgentConfig[s.ID].MediaConfig.Format

		//sim
		inviteMethod := fmt.Sprintf("sip:%s@172.31.29.47;transport=%s", s.AgentName, transport) // nlb(DNS)를 한번 갔다온 ip를 넣어줘야함.
		s.uri = fmt.Sprintf("sip:%s@%s", s.AgentName, ip)
		to := fmt.Sprintf("<sip:%s@%s;user=phone>", s.AgentName, ip)
		from := fmt.Sprintf("<sip:%s@%s>;tag=%s", inviteto, ip, sipasm.GenerateTag())
		if conf.Representative.Value {
			inviteMethod = fmt.Sprintf("sip:%s@%s;transport=%s", "AISB", ip, transport)
			s.uri = fmt.Sprintf("sip:%s@%s", "AISB", ip)
			to = fmt.Sprintf("<sip:%s@%s;user=phone>", "AISB", ip)
			agentName := s.AgentName
			agentSplit := agentName[len(agentName)-2:len(agentName)]
			telNo := fmt.Sprintf("010243427%s", agentSplit)
			from = fmt.Sprintf("<sip:%s@%s>;tag=%s", telNo, ip, sipasm.GenerateTag())
		}
		reqInvite := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_INVITE, inviteMethod)

		via := fmt.Sprintf("SIP/2.0/UDP %s:5090;branch=%s", ip, sipasm.GenerateBranch())
		maxforwards := "70"

		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set URI [%s]", s.uri)

		// postfix := "192.168.0.83"
		var callid string
		s.m.Lock()
		s.callID = uuid.New().String()
		s.m.Unlock()
		callid = s.callID
		// if len(s.callID) != 0 {
		// 	callid = s.callID
		// 	//if len(s.regiCallID) != 0 {
		// 	//callid = s.regiCallID
		// } else {
		// 	callid = sipasm.GenerateCallID(postfix)
		// }
		cseq := fmt.Sprintf("%d INVITE", s.Cseq)
		s.Cseq++
		// contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, port, transport)
		contact := fmt.Sprintf("<sip:%s@%s:5060>", inviteto, ip)
		//expires := fmt.Sprintf("%d", conf.AgentConfig[s.ID].RegisterConfig.RegisterExpire)
		// userAgent := conf.InfoConfig.Product
		userAgent := "M800B/v.7.20A.204.759"
		allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
		supported := "em,100rel,timer,replaces,path,resource-priority,sdp-anat"

		formats := strings.Split(format, " ")
		// reqInvite.SDP = sipasm.NewSDPMessage(ip, mediaPort, formats[:], 0)
		reqInvite.SDP = sipasm.NewSDPMessage(ip, mediaPort, formats[:], 0)
		sdpLength := fmt.Sprintf("%d", len(reqInvite.SDP.String()))

		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, via)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, from)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, to)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, callid)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, cseq)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_XAICALL, s.referto)
		//reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_EXPIRES, expires)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_TYPE, "application/sdp")
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, sdpLength)
		reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

		wlen, werr := (*s.sipNeter).WriteSIP([]byte(reqInvite.String()))
		if werr != nil {
			l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
			return
		}

		// s.callID = callid
		// s.callID = uuid.New().String()

		if conf.Representative.Value {
			s.SetAgentStatus(STATUS_AGENT_READY)
		} else {
			s.SetAgentStatus(STATUS_AGENT_CALLING)
		}
		

		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
			wlen,
			(*s.sipNeter).LocalAddr().String(),
			(*s.sipNeter).RemoteAddr().String(),
			reqInvite.String())
	}
	inviteFunc()
}

// pass invite for sim
func (s *IcsSession) PassInvite(sip *icspacketparser.SIP) *icserror.IcsError {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	// TODO - send bye
	defer func() {
		if err := recover(); err != nil {
			l.Printf(icslog.LOG_LEVEL_WARN, s.ID, "%s \n%s",
				icserror.ICSERRNETNotConnectError.GetMessage(), debug.Stack())
		}
	}()

	ip := conf.InfoConfig.ServerIP
	port := conf.SIPConfig.Port

	// fmt.Println("sip.Media ", sip.Media)
	mediaPort, _ := strconv.Atoi(sip.Media)

	proxy := conf.SIPConfig.SIPProxy
	transport := conf.SIPConfig.Transport
	format := conf.AgentConfig[s.ID].MediaConfig.Format

	inviteMethod := fmt.Sprintf("sip:%s@%s;transport=%s", "AISB", proxy, transport)
	reqInvite := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_INVITE, inviteMethod)

	via := fmt.Sprintf("SIP/2.0/UDP %s;rport;branch=%s", ip, sipasm.GenerateBranch())
	maxforwards := "70"
	agentName := s.AgentName
	agentSplit := agentName[len(agentName)-2:len(agentName)]
	telNo := fmt.Sprintf("010243427%s", agentSplit)
	from := fmt.Sprintf("<sip:%s@%s:5090>;tag=%s", telNo, ip, sipasm.GenerateTag())

	s.uri = fmt.Sprintf("sip:%s@%s", s.AgentName, ip)
	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set URI [%s]", s.uri)

	s.referto = sip.XAICall
	to := fmt.Sprintf("<sip:%s@%s;user=phone>", "AISB", ip)
	//to := fmt.Sprintf("<sip:%s@%s>", s.AgentName, ip)
	// postfix := fmt.Sprintf("@%s", ip)
	var callid string
	callid = uuid.New().String()
	// if len(s.callID) != 0 {
	// 	callid = s.callID
	// 	//if len(s.regiCallID) != 0 {
	// 	//callid = s.regiCallID
	// } else {
	// 	callid = sipasm.GenerateCallID(postfix)
	// }
	s.m.Lock()
	s.callID = callid
	s.m.Unlock()
	cseq := fmt.Sprintf("%d INVITE", s.Cseq)
	s.Cseq++
	contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", "AISB", ip, port, transport)
	//expires := fmt.Sprintf("%d", conf.AgentConfig[s.ID].RegisterConfig.RegisterExpire)
	userAgent := conf.InfoConfig.Product
	allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
	supported := "timer,path,replaces"

	formats := strings.Split(format, " ")
	reqInvite.SDP = sipasm.NewSDPMessage(ip, mediaPort, formats[:], 0)
	sdpLength := fmt.Sprintf("%d", len(reqInvite.SDP.String()))
	// fmt.Println("###### X-AICALL ", sip.XAICall)
	// refer := strings.Split(sip.XAICall, "@")[0]

	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, via)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, from)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, to)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, callid)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, cseq)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_XAICALL, sip.XAICall)
	//reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_EXPIRES, expires)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_TYPE, "application/sdp")
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, sdpLength)
	reqInvite.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Send INVITE! [%s] -> [%s] \r\n %+v\r\n", 
	(*s.sipNeter).LocalAddr().String(),
	(*s.sipNeter).RemoteAddr().String(),
	reqInvite)

	// sendINVITE := fmt.Sprintf("%+v",sip)
	_, werr := (*s.sipNeter).WriteSIP([]byte(reqInvite.String()))
	if werr != nil {
		l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
		s.SetAgentStatus(STATUS_AGENT_READY)
		return werr
	}
	// fmt.Println(wlen)

	s.InviteSIP = nil
	s1 := icspacketparser.NewSIP()
	err := s1.SipParser([]byte(reqInvite.String()))
	if err != nil {
		// fmt.Printf("########### ererererrererer  %s \r\n %+v\r\n", reqInvite.String(), s.InviteSIP)	
	} else {
		s.InviteSIP = &s1
		// fmt.Printf("########### %+v\r\n",s1)
		// fmt.Printf("########### %s, \r\n %+v\r\n",reqInvite.String(), s.InviteSIP)
	}
	
	// s.RemoveSession()
	return nil
}

//response invite
func (s *IcsSession) ProcInvite(sip *icspacketparser.SIP) *icserror.IcsError {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	// TODO - send bye
	defer func() {
		if err := recover(); err != nil {
			l.Printf(icslog.LOG_LEVEL_WARN, s.ID, "%s \n%s",
				icserror.ICSERRNETNotConnectError.GetMessage(), debug.Stack())

		}
	}()
	s.referto = sip.XAICall

	name1 := strings.SplitN(sip.To, "@", 2)
	name2 := strings.SplitN(name1[0], ":", 2)
	ac := FindAgentConfig(name2[1])
	if ac == nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not found Agent Name - %s",
			icserror.ICSERRUnkown.GetMessage())
		s.ResError(sip, 400)
		return icserror.ICSERRUnkown
	}
	s.SetAgentConfig(ac)
	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Found Agent config - %+v", ac)

	ai := FindAgentInfo(name2[1])
	if ai == nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not found Agent Name - %s",
			icserror.ICSERRUnkown.GetMessage())
		s.ResError(sip, 400)
		return icserror.ICSERRUnkown
	}
	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Found Agent Info - %+v", ai)
	s.SetAgentInfo(ai)

	ip := conf.InfoConfig.ServerIP
	sipPort := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport
	format := s.AgentConf.MediaConfig.Format
	mediaPort := s.AgentConf.MediaConfig.Port

	ierr := s.Init()
	if ierr != nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Session Init Error - %d",
			ierr.GetMessage())
		s.ResError(sip, 500)
		return ierr
	}

	status := s.GetAgentStatus()
	if status == STATUS_AGENT_READY || status == STATUS_AGENT_CALLING {
		//reset rx cnt
		s.rxCnt = 0

		//get remote rtp addr in SDP
		//fmt.Println("invite > method type", sip.Method, sip.Content)
		rport, perr := s.findSDPMediaAudioPort(sip)
		if perr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not found Audio Port [%d] - %s",
				rport, perr.GetMessage())
			s.ResError(sip, 500)
			return perr
		}
		sdpConnectInfo := strings.Split(sip.Content.Connection, " ")
		remoteIP := sdpConnectInfo[len(sdpConnectInfo)-1]
		remoteAddrs := fmt.Sprintf("%s:%d", remoteIP, rport)
		remoteAddr := icsnet.NewNetAddrWithIPAddr(remoteAddrs)
		//connect to remote RTP
		s.rtpMediaNeter.SetRemoteAddr(&remoteAddr)
		
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set media remote address - %s(%s)", remoteAddr, s.rtpMediaNeter.RemoteAddr())
		/*
			cerr := s.rtpMediaNeter.Connect(nil, &remoteAddr)
			if cerr != nil {
				fmt.Println("CONNECTION FAIL!!!", cerr)
			}
		*/

		/*
			//send 100 trying
			s.SetAgentStatus(STATUS_AGENT_CALLING)
			res100 := sipasm.NewSIPResponse(sip, 100)
			res100.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, conf.InfoConfig.Product)
			res100.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, "0")
			res100.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)
			//fmt.Println(res100)

			wlen, werr := (*s.sipNeter).WriteSIP([]byte(res100.String()))
			if werr != nil {
				l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
				s.SetAgentStatus(STATUS_AGENT_READY)
				return werr
			}
			l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
				wlen,
				(*s.sipNeter).LocalAddr().String(),
				(*s.sipNeter).RemoteAddr().String(),
				res100.String())
		*/
		//send 200 ok
		res200 := sipasm.NewSIPResponse(sip, 200)
		formats := strings.Split(format, " ")
		s.invitePayloads = formats
		m := *sip.Content.Media
		mLen := len(m)
		var sendrecv int
		for iter1 := 0; iter1 < mLen; iter1++ {
			for iter2 := 0; iter2 < mLen; iter2++ {
				if strings.Contains(m[iter1].Attributes[iter2], "sendrecv") {
					sendrecv = 0
					break
				} else if strings.Contains(m[iter1].Attributes[iter2], "sendonly") {
					sendrecv = 2
					break
				} else if strings.Contains(m[iter1].Attributes[iter2], "recvonly") {
					sendrecv = 1
					break
				}
			}
		}
		res200.SDP = sipasm.NewSDPMessage(ip, mediaPort, formats[:1], sendrecv)

		//set payload
		payload, err := s.compareSDPMediaPayload(sip)
		if err != nil {
			l.Print(icslog.LOG_LEVEL_ERROR, s.ID, "Not found payload type")
			//TODO: should response error sip message
			s.ResError(sip, 500)
			return err
		}
		s.payloadType = icspacketparser.PayloadType(payload)
		//create media decoder
		var cerr *icserror.IcsError
		/*
			s.TxConverter, cerr = icsmediaconv.NewConverter(s.ID, s.payloadType, false)
			if cerr != nil {
				l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to New Tx Converter-%v", cerr)
				return cerr
			} else {
				l.Print(icslog.LOG_LEVEL_INFO, s.ID, "New Tx Converter(Decoder)")
			}
		*/
		s.RxConverter, cerr = icsmediaconv.NewConverter(s.ID, s.payloadType, true)
		if cerr != nil {
			//s.isFoundPayload = false
			l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to New Rx Converter-%v", cerr)
			s.ResError(sip, 415)
			return cerr
		} else {
			l.Print(icslog.LOG_LEVEL_INFO, s.ID, "New Rx Converter(Decoder)")
		}

		//fmt.Printf("%v\n", res200.SDP.String())
		//fmt.Println(res200)

		//s.callID = sip.CallID
		/////////////////////////////////////////////
		//set call signal addr
		csraddr := icsnet.NewNetAddrWithIPPort(s.AgentInfo.IP, s.AgentInfo.Port)
		//csladdr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.MyAddr.ServerIP, conf.VoiceAgentConfig.MyAddr.ServerPort)
		/*
			csraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentInfo[s.ID].IP, conf.VoiceAgentConfig.AgentInfo[s.ID].Port)
			csladdr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.MyAddr.ServerIP, conf.VoiceAgentConfig.MyAddr.ServerPort)
		*/

		//set Voice addr
		vraddr := icsnet.NewNetAddrWithIPPort(s.AgentInfo.IP, s.AgentInfo.VoicePort)
		//vraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentInfo[s.ID].IP, conf.VoiceAgentConfig.AgentInfo[s.ID].VoicePort)

		s.VoiceNeter = icsnet.NewUDP(nil, &vraddr)
		//s.VoiceNeter = icsnet.NewUDP(&vladdr, &vraddr)
		conerr := s.VoiceNeter.Connect(nil, nil)
		if conerr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Error init Voice Neter[%s->%s]-%v", s.VoiceNeter.LocalAddr().String(), vraddr.String(), conerr.GetError())
			s.ResError(sip, 500)
			return conerr
		}
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Voice(UDP) Connected to VoiceAgent[%s->%s]", s.VoiceNeter.LocalAddr().String(), vraddr.String())

		////////////////////////////////////////
		//send call signal data to VoiceAgent
		// defer func() {
		// 	if err := recover(); err != nil {
		// 		l.Printf(icslog.LOG_LEVEL_WARN, s.ID, "%s [%s]\n%s",
		// 			icserror.ICSERRNETNotConnectError.GetMessage(), csraddr, debug.Stack())
		// 	}
		// }()
		var inout string = "O"
		s.SetDirection(true)
		if s.GetDirection() {
			inout = "I"
		}
		callsignal := writecallsignal.NewCallSignalData()
		s.StartTimeStamp = time.Now().UnixNano()
		s.ChannelID = conf.GetChannelID()
		s.ServerID = conf.GetServerID()
		//TODO : agent conf
		//station := conf.AgentConfig[s.ID].Name
		s.Station = s.AgentInfo.Name
		// fmt.Println("s.Station = s.AgentInfo.Name>>>>>", s.Station)
		///////////
		cust1 := strings.SplitN(sip.From, "@", 2)
		cust2 := strings.SplitN(cust1[0], ":", 2)
		s.CustID = cust2[1]
		//////////
		callsignal.SetData(s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, 0, "S", inout)
		t, _, werr := icsnet.SendCallSignal(nil, &csraddr, callsignal.GetData())
		if werr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send Call-Start signal to VoiceAgent(%s)", werr.GetError())
			if t != nil {
				s.ResError(sip, 502)
				t.Close()
			}
			s.ResError(sip, 502)
			// Before not return => not stop call process
			return werr
		} else {
			l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Call-Start signal to VoiceAgent - channelid: %s, serverid: %d, station: %s, Custom: %s, starttimestamp: %d, START, inout: %s\n",
				s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, inout)
		}
		//t, wlen, werr := icsnet.SendCallSignal(nil, &csraddr, callsignal.GetData())
		//t, wlen, werr := icsnet.SendCallSignal(&csladdr, &csraddr, callsignal.GetData())
		/*
			if werr == nil {
				defer t.Close()
				l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Call-Start signal to VoiceAgent(%d)", wlen)
				///////////////////////////////////
				// recv TTS data
				//recv tts header
				ttsHeader, rlen, rerr := t.Read(36)
				if rerr != nil {
					l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv TTS header(%d,%s)", rlen, rerr.GetError())
					//return rerr
				}
				ttscmd := binary.LittleEndian.Uint32(ttsHeader[0:])
				ttsrc := binary.LittleEndian.Uint32(ttsHeader[4:])
				ttspl := binary.LittleEndian.Uint64(ttsHeader[8:])
				agentname := string(ttsHeader[16:])
				//remove null terminator
				n := bytes.Index([]byte(agentname), []byte{0})
				agentName := string([]byte(agentname)[:n])
				l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS header(%d) AgentName: %s, Command: %d result code: %d, payload length: %d",
					rlen, agentName, ttscmd, ttsrc, ttspl)
				//recv tts data
				tts, rlen, rerr := t.Read(int(ttspl))
				if rerr != nil {
					l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to recv TTS(%d,%s)", rlen, rerr.GetError())
					//return rerr
				}
				s.m.Lock()
				s.tts = make([]byte, int(ttspl))
				copy(s.tts, tts)
				s.m.Unlock()
				//s.tts = tts
				l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Recved TTS data. Length: %d", len(s.tts))
			} else {
				l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send Call-Start signal to VoiceAgent(%s)", werr.GetError())
				if t != nil {
					t.Close()
				}
				//return rerr
			}
		*/

		/*
			//////////////////////
			//RTP start
			l.Print(icslog.LOG_LEVEL_INFO, s.ID, "Started RTP sender Callback")
			s.txCnt = 0
			s.callStartTime = time.Now()
			s.RTPSenderCallBackTimer.Start()
		*/

		//set sip resp header
		contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, sipPort, transport)
		sdpLength := fmt.Sprintf("%d", len(res200.SDP.String()))
		supported := "timer, path, replaces, sdp-anat"

		res200.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, conf.InfoConfig.Product)
		res200.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
		res200.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
		res200.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_TYPE, "application/sdp")
		res200.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, sdpLength)
		res200.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)
		wlen, werr := (*s.sipNeter).WriteSIP([]byte(res200.String()))
		if werr != nil {
			l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
			s.SetAgentStatus(STATUS_AGENT_READY)
			return werr
		}

		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
			wlen,
			(*s.sipNeter).LocalAddr().String(),
			(*s.sipNeter).RemoteAddr().String(),
			res200.String())
		s.txCnt = 0
		s.callStartTime = time.Now()
		s.SetAgentStatus(STATUS_AGENT_BUSY)

		/*////
		time.Sleep(3000 * time.Millisecond)
		s.RequestRefer(sip)
		*/
	} else if status == STATUS_AGENT_BUSY {
		if strings.Contains(strings.ToUpper(sip.Supported), "SDP-ANAT") {
			//send 486 busy
			res486 := sipasm.NewSIPResponse(sip, 486)
			contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, sipPort, transport)
			res486.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, conf.InfoConfig.Product)
			res486.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
			res486.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

			wlen, werr := (*s.sipNeter).WriteSIP([]byte(res486.String()))
			if werr != nil {
				l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
				s.SetAgentStatus(STATUS_AGENT_READY)
				return werr
			}

			//s.SetAgentStatus(STATUS_AGENT_BUSY)

			l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
				wlen,
				(*s.sipNeter).LocalAddr().String(),
				(*s.sipNeter).RemoteAddr().String(),
				res486.String())
		} else {
			//send 486 busy
			res486 := sipasm.NewSIPResponse(sip, 486)
			contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, sipPort, transport)
			res486.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, conf.InfoConfig.Product)
			res486.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
			res486.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

			wlen, werr := (*s.sipNeter).WriteSIP([]byte(res486.String()))
			if werr != nil {
				l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
				s.SetAgentStatus(STATUS_AGENT_READY)
				return werr
			}

			//s.SetAgentStatus(STATUS_AGENT_BUSY)

			l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
				wlen,
				(*s.sipNeter).LocalAddr().String(),
				(*s.sipNeter).RemoteAddr().String(),
				res486.String())
			//remove session
			//s.RemoveSession()
		}
		//TODO:re-Invite
	} else {
		//TODO: send error response

	}

	return nil
}

//response invite
func (s *IcsSession) ProcACKInvite(sip *icspacketparser.SIP) *icserror.IcsError {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()
	// s.InviteSIP = sip

	///////////////////////////////////////////
	///////////////////////////////////////////
	// set agentinfo
	name1 := strings.SplitN(sip.To, "@", 2)
	name2 := strings.SplitN(name1[0], ":", 2)
	ac := FindAgentConfig(name2[1])
	s.m.Lock()
	s.callID = sip.CallID
	s.m.Unlock()
	if ac == nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not found Agent Name - %s",
			icserror.ICSERRUnkown.GetMessage())
		s.ResError(sip, 400)
		return icserror.ICSERRUnkown
	}
	s.SetAgentConfig(ac)
	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Found Agent config - %+v", ac)

	ai := FindAgentInfo(name2[1])
	if ai == nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not found Agent Name - %s",
			icserror.ICSERRUnkown.GetMessage())
		s.ResError(sip, 400)
		return icserror.ICSERRUnkown
	}
	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Found Agent Info - %+v", ai)
	s.SetAgentInfo(ai)

	ierr := s.Init()
	if ierr != nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Session Init Error - %d",
			ierr.GetMessage())
		s.ResError(sip, 500)
		return ierr
	}

	ip := conf.InfoConfig.ServerIP
	//mediaPort := conf.AgentConfig[s.ID].MediaConfig.Port
	sipPort := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport
	format := conf.AgentConfig[s.ID].MediaConfig.Format

	if conf.Representative.Value {// 대표번호일때 강제로 콜링으로 변환
		s.SetAgentStatus(STATUS_AGENT_CALLING)
	}
	status := s.GetAgentStatus()
	// fmt.Println("BOT STATUS ", status == STATUS_AGENT_CALLING)
	if status == STATUS_AGENT_CALLING {
		ackMethod := fmt.Sprintf("sip:01025670081@%s;transport=%s", "192.168.0.222:5090", transport)

		reqAck := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_ACK, ackMethod)

		//via := fmt.Sprintf("SIP/2.0/UDP %s;rport;branch=%s", ip, sipasm.GenerateBranch())
		maxforwards := "70"
		//from := fmt.Sprintf("<sip:%s@%s:5090>;tag=%s", s.AgentName, ip, sipasm.GenerateTag())

		s.uri = fmt.Sprintf("sip:%s@%s", s.AgentName, ip)
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set URI [%s]", s.uri)

		//to := fmt.Sprintf("<sip:%s@%s;user=phone>", "01025670081", "192.168.0.221")
		//to := fmt.Sprintf("<sip:%s@%s;user=phone>", "01025670081", ip)
		//to := fmt.Sprintf("<sip:%s@%s>", s.AgentName, ip)
		//cseq := fmt.Sprintf("%d INVITE", s.Cseq)
		contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, sipPort, transport)
		userAgent := conf.InfoConfig.Product
		allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
		supported := "timer,path,replaces"

		if sip.Source == "200" {
			//get remote rtp addr in SDP
			//fmt.Println("invite > method type", sip.Method, sip.Content)
			rport, perr := s.findSDPMediaAudioPort(sip)
			if perr != nil {
				return perr
			}
			sdpConnectInfo := strings.Split(sip.Content.Connection, " ")
			remoteIP := sdpConnectInfo[len(sdpConnectInfo)-1]
			remoteAddrs := fmt.Sprintf("%s:%d", remoteIP, rport)
			//fmt.Println("remote RTP addr:", remoteAddrs)
			remoteAddr := icsnet.NewNetAddrWithIPAddr(remoteAddrs)
			//connect to remote RTP
			s.rtpMediaNeter.SetRemoteAddr(&remoteAddr)

			//set payload
			formats := strings.Split(format, " ")
			s.invitePayloads = formats
			payload, err := s.compareSDPMediaPayload(sip)
			if err != nil {
				l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Not found payload type - %s", err.GetError().Error())
				l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Not found payload type - %s", sip.Content)
				//TODO: should response error sip message
				return err
			}
			s.payloadType = icspacketparser.PayloadType(payload)
			var cerr *icserror.IcsError
			s.RxConverter, cerr = icsmediaconv.NewConverter(s.ID, s.payloadType, true)
			if cerr != nil {
				//s.isFoundPayload = false
				l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to New Rx Converter-%v", cerr)
				s.ResError(sip, 415)
				return cerr
			} else {
				l.Print(icslog.LOG_LEVEL_INFO, s.ID, "New Rx Converter(Decoder)")
			}
		}

		for _, viav := range sip.Via {
			reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, viav)
		}
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, sip.From)
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, sip.To)
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, sip.CallID)
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, sip.Cseq)
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent)
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow)
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, "0")
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

		// wlen, werr := (*s.sipNeter).WriteSIP([]byte(reqAck.String()))
		wlen, werr := (*s.sipNeter).WriteSIPTo([]byte(reqAck.String()), s.remoteSIPAddr)
		if werr != nil {
			l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
			s.SetAgentStatus(STATUS_AGENT_READY)
			return werr
		}

		if sip.Source == "200" {
			//RTP start
			s.txCnt = 0
			s.callStartTime = time.Now()
			// s.RTPSenderCallBackTimer.Start()

			s.SetAgentStatus(STATUS_AGENT_BUSY)
			s.RTPSenderCallBackTimer.Start()
		}

		///////////////////////////////////////////
		///////////////////////////////////////////
		// set agentinfo
		// name1 := strings.SplitN(sip.To, "@", 2)
		// name2 := strings.SplitN(name1[0], ":", 2)
		// ac := FindAgentConfig(name2[1])
		// if ac == nil {
		// 	l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not found Agent Name - %s",
		// 		icserror.ICSERRUnkown.GetMessage())
		// 	s.ResError(sip, 400)
		// 	return icserror.ICSERRUnkown
		// }
		// s.SetAgentConfig(ac)
		// l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Found Agent config - %+v", ac)

		// ai := FindAgentInfo(name2[1])
		// if ai == nil {
		// 	l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not found Agent Name - %s",
		// 		icserror.ICSERRUnkown.GetMessage())
		// 	s.ResError(sip, 400)
		// 	return icserror.ICSERRUnkown
		// }
		// l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Found Agent Info - %+v", ai)
		// s.SetAgentInfo(ai)

		// ierr := s.Init()
		// if ierr != nil {
		// 	l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Session Init Error - %d",
		// 		ierr.GetMessage())
		// 	s.ResError(sip, 500)
		// 	return ierr
		// }

		//set payload
		// payload, err := s.compareSDPMediaPayload(sip)
		// if err != nil {
		// 	l.Print(icslog.LOG_LEVEL_ERROR, s.ID, "Not found payload type")
		// 	//TODO: should response error sip message
		// 	s.ResError(sip, 500)
		// 	return err
		// }
		// s.payloadType = icspacketparser.PayloadType(payload)

		// set audio port
		// rport, perr := s.findSDPMediaAudioPort(sip)
		// if perr != nil {
		// 	l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not found Audio Port [%d] - %s",
		// 		rport, perr.GetMessage())
		// }
		// sdpConnectInfo := strings.Split(sip.Content.Connection, " ")
		// remoteIP := sdpConnectInfo[len(sdpConnectInfo)-1]
		// remoteAddrs := fmt.Sprintf("%s:%d", remoteIP, rport)
		// remoteAddr := icsnet.NewNetAddrWithIPAddr(remoteAddrs)
		// //connect to remote RTP
		// s.rtpMediaNeter.SetRemoteAddr(&remoteAddr)
		// l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set media remote address - %s(%s)", remoteAddr, s.rtpMediaNeter.RemoteAddr())


		///////////////////////////////////////////
		///////////////////////////////////////////
		// send call signal
		// var inout string = "O"
		// s.SetDirection(true)
		// if s.GetDirection() {
		// 	inout = "I"
		// }
		// csraddr := icsnet.NewNetAddrWithIPPort(s.AgentInfo.IP, s.AgentInfo.Port)
		// callsignal := writecallsignal.NewCallSignalData()
		// s.StartTimeStamp = time.Now().UnixNano()
		// s.ChannelID = conf.GetChannelID()
		// s.ServerID = conf.GetServerID()
		// //TODO : agent conf
		// //station := conf.AgentConfig[s.ID].Name
		// s.Station = s.AgentInfo.Name
		// fmt.Println("s.Station = s.AgentInfo.Name>>>>>", s.Station)
		// ///////////
		// cust1 := strings.SplitN(sip.From, "@", 2)
		// cust2 := strings.SplitN(cust1[0], ":", 2)
		// s.CustID = cust2[1]
		// //////////
		// callsignal.SetData(s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, 0, "S", inout)
		// t, _, werr := icsnet.SendCallSignal(nil, &csraddr, callsignal.GetData())
		// if werr != nil {
		// 	fmt.Println("Failed to send Call-Start ", werr.GetError())
		// 	l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send Call-Start signal to VoiceAgent(%s)", werr.GetError())
		// 	if t != nil {
		// 		s.ResError(sip, 502)
		// 		t.Close()
		// 	}
		// 	s.ResError(sip, 502)
		// 	// Before not return => not stop call process
		// 	return werr
		// } else {
		// 	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Call-Start signal to VoiceAgent - channelid: %s, serverid: %d, station: %s, Custom: %s, starttimestamp: %d, START, inout: %s\n",
		// 		s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, inout)
		// }
		// fmt.Println("Send Call Signal to 83 VAB")
		// l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Send Call Signal to 83 VAB")
		///////////////////////////////////////////
		///////////////////////////////////////////

		// fmt.Println(s)
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
			wlen,
			(*s.sipNeter).LocalAddr().String(),
			(*s.sipNeter).RemoteAddr().String(),
			reqAck.String())

	}

	return nil
}

//for cancel method
func (s *IcsSession) ProcInvite487(sip *icspacketparser.SIP) *icserror.IcsError {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()
	ip := conf.InfoConfig.ServerIP
	//mediaPort := conf.AgentConfig[s.ID].MediaConfig.Port
	sipPort := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport
	//format := conf.AgentConfig[s.ID].MediaConfig.Format

	//status := s.GetAgentStatus()
	//send 487 Request Terminiated
	res487 := sipasm.NewSIPResponse(sip, 487)
	contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, sipPort, transport)
	res487.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, conf.InfoConfig.Product)
	res487.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
	res487.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

	wlen, werr := (*s.sipNeter).WriteSIP([]byte(res487.String()))
	if werr != nil {
		l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
		s.SetAgentStatus(STATUS_AGENT_READY)
		return werr
	}

	//s.SetAgentStatus(STATUS_AGENT_BUSY)

	s.callEndTime = time.Now()

	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
		wlen,
		(*s.sipNeter).LocalAddr().String(),
		(*s.sipNeter).RemoteAddr().String(),
		res487.String())

	s.SetAgentStatus(STATUS_AGENT_READY)

	return nil
}

func (s *IcsSession) ProcCancel(sip *icspacketparser.SIP) *icserror.IcsError {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()
	ip := conf.InfoConfig.ServerIP
	//mediaPort := conf.AgentConfig[s.ID].MediaConfig.Port
	sipPort := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport
	//format := conf.AgentConfig[s.ID].MediaConfig.Format

	//status := s.GetAgentStatus()
	//send 200 ok
	res200 := sipasm.NewSIPResponse(sip, 200)
	contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, sipPort, transport)
	res200.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, conf.InfoConfig.Product)
	res200.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
	res200.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

	wlen, werr := (*s.sipNeter).WriteSIP([]byte(res200.String()))
	if werr != nil {
		l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
		s.SetAgentStatus(STATUS_AGENT_READY)
		return werr
	}

	//s.SetAgentStatus(STATUS_AGENT_BUSY)

	s.callEndTime = time.Now()

	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
		wlen,
		(*s.sipNeter).LocalAddr().String(),
		(*s.sipNeter).RemoteAddr().String(),
		res200.String())

	s.SetAgentStatus(STATUS_AGENT_CANCELING)

	return nil
}

func (s *IcsSession) ProcBye(sip *icspacketparser.SIP) *icserror.IcsError {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()
	ip := conf.InfoConfig.ServerIP
	//mediaPort := conf.AgentConfig[s.ID].MediaConfig.Port
	sipPort := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport
	//format := conf.AgentConfig[s.ID].MediaConfig.Format

	////////////////////////////////////////
	//send call signal-end to VoiceAgent
	/////////////////////////////////////////////
	//set call signal addr
	// fmt.Println(s)
	// csraddr := icsnet.NewNetAddrWithIPPort(s.AgentInfo.IP, s.AgentInfo.Port)
	//csladdr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.MyAddr.ServerIP, conf.VoiceAgentConfig.MyAddr.ServerPort)
	/*
		csraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentInfo[s.ID].IP, conf.VoiceAgentConfig.AgentInfo[s.ID].Port)
		csladdr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.MyAddr.ServerIP, conf.VoiceAgentConfig.MyAddr.ServerPort)
	*/

	defer func() {
		if err := recover(); err != nil {
			l.Printf(icslog.LOG_LEVEL_WARN, s.ID, "%s %s\n%s",
				icserror.ICSERRNETNotConnectError.GetMessage(), "", debug.Stack())
		}
	}()
	var inout string = "O"
	s.SetDirection(true)
	if s.GetDirection() {
		inout = "I"
	}
	callsignal := writecallsignal.NewCallSignalData()
	s.StartTimeStamp = time.Now().UnixNano()
	s.EndTimeStamp = time.Now().UnixNano()
	s.ChannelID = conf.GetChannelID()
	s.ServerID = conf.GetServerID()
	station := conf.AgentConfig[s.ID].Name
	s.Station = station
	///////////
	cust1 := strings.SplitN(sip.From, "@", 2)
	cust2 := strings.SplitN(cust1[0], ":", 2)
	s.CustID = cust2[1]
	//////////
	l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, ">>>>>channelid: %s, serverid: %d, station: %s, Custom: %s, starttimestamp: %d, START, inout: %s\n",
		s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, inout)
	callsignal.SetData(s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, s.EndTimeStamp, "E", inout)
	// t, wlen, werr := icsnet.SendCallSignal(nil, &csraddr, callsignal.GetData())
	//t, wlen, werr := icsnet.SendCallSignal(&csladdr, &csraddr, callsignal.GetData())
	// if werr != nil {
	// 	l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send Call-End signal to VoiceAgent(%s)", werr.GetError())
	// } else {
	// 	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Call-End signal to VoiceAgent(%d)", wlen)
	// 	defer t.Close()
	// }
	//close voiceneter(voice connection to voice agent)
	if s.VoiceNeter != nil {
		s.VoiceNeter.Close()
	}
	////////////////////////////////////////

	//status := s.GetAgentStatus()
	//send 200 ok
	res200 := sipasm.NewSIPResponse(sip, 200)
	contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, sipPort, transport)
	res200.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, conf.InfoConfig.Product)
	res200.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
	res200.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

	// wlen, werr := (*s.sipNeter).WriteSIP([]byte(res200.String()))
	wlen, werr := (*s.sipNeter).WriteSIPTo([]byte(res200.String()), s.remoteSIPAddr)
	if werr != nil {
		l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
		s.SetAgentStatus(STATUS_AGENT_READY)
		return werr
	}

	//s.SetAgentStatus(STATUS_AGENT_BUSY)

	s.callEndTime = time.Now()

	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
		wlen,
		(*s.sipNeter).LocalAddr().String(),
		(*s.sipNeter).RemoteAddr().String(),
		res200.String())

	s.SetAgentStatus(STATUS_AGENT_READY)

	s.AgentConf = nil
	s.AgentInfo = nil

	return nil
}

// SIM
func (s *IcsSession) SendRequestInvite() {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	// fmt.Println("######### sim loop count!! ", conf.SimLoopCount)
	// fmt.Printf("Send Call Start Sip(%s) count %d!!!!!!!", s.AgentName, s.simLoopCount)
	if s.simLoopCount < conf.SimLoopCount {
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Send Call Start Sip(%s) count %d!!!!!!!\r\n", s.AgentName, s.simLoopCount)
		time.Sleep(time.Second*1)
		s.RequestInvite("01024342788")
		s.simLoopCount += 1
	} else {
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Send Call Start Sip(%s) END %d !!!!!!!\r\n", s.AgentName, s.simLoopCount)		
	}
}

func (s *IcsSession) ProcSIP20Bye(sip *icspacketparser.SIP) *icserror.IcsError {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()
	// conf := icsconf.GetIcsConfig()
	//ip := conf.InfoConfig.ServerIP
	//mediaPort := conf.AgentConfig[s.ID].MediaConfig.Port
	//sipPort := conf.SIPConfig.Port
	//transport := conf.SIPConfig.Transport
	//format := conf.AgentConfig[s.ID].MediaConfig.Format

	l.Print(icslog.LOG_LEVEL_INFO, s.ID, "SIP2.0 BYE")
	s.RemoveSession()
	// ////////////////////////////////////////
	// //send call signal-end to VoiceAgent
	// /////////////////////////////////////////////
	// //set call signal addr
	// csraddr := icsnet.NewNetAddrWithIPPort(s.AgentInfo.IP, s.AgentInfo.Port)
	// //csladdr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.MyAddr.ServerIP, conf.VoiceAgentConfig.MyAddr.ServerPort)
	// /*
	// 	csraddr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.AgentInfo[s.ID].IP, conf.VoiceAgentConfig.AgentInfo[s.ID].Port)
	// 	csladdr := icsnet.NewNetAddrWithIPPort(conf.VoiceAgentConfig.MyAddr.ServerIP, conf.VoiceAgentConfig.MyAddr.ServerPort)
	// */

	// defer func() {
	// 	if err := recover(); err != nil {
	// 		l.Printf(icslog.LOG_LEVEL_WARN, s.ID, "%s %s\n%s",
	// 			icserror.ICSERRNETNotConnectError.GetMessage(), csraddr, debug.Stack())
	// 	}
	// }()
	// var inout string = "O"
	// s.SetDirection(true)
	// if s.GetDirection() {
	// 	inout = "I"
	// }
	// callsignal := writecallsignal.NewCallSignalData()
	// s.StartTimeStamp = time.Now().UnixNano()
	// s.EndTimeStamp = time.Now().UnixNano()
	// s.ChannelID = conf.GetChannelID()
	// s.ServerID = conf.GetServerID()
	// station := conf.AgentConfig[s.ID].Name
	// s.Station = station
	// ///////////
	// cust1 := strings.SplitN(sip.From, "@", 2)
	// cust2 := strings.SplitN(cust1[0], ":", 2)
	// s.CustID = cust2[1]
	// //////////
	// l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, ">>>>>channelid: %s, serverid: %d, station: %s, Custom: %s, starttimestamp: %d, START, inout: %s\n",
	// 	s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, inout)
	// callsignal.SetData(s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, s.EndTimeStamp, "E", inout)
	// t, wlen, werr := icsnet.SendCallSignal(nil, &csraddr, callsignal.GetData())
	// //t, wlen, werr := icsnet.SendCallSignal(&csladdr, &csraddr, callsignal.GetData())
	// defer t.Close()
	// if werr != nil {
	// 	l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send Call-End signal to VoiceAgent(%s)", werr.GetError())
	// } else {
	// 	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Call-End signal to VoiceAgent(%d)", wlen)
	// }
	// //close voiceneter(voice connection to voice agent)
	// if s.VoiceNeter != nil {
	// 	s.VoiceNeter.Close()
	// }

	// s.RemoveSession()
	// fmt.Println("######### sim loop count!! ", conf.SimLoopCount)
	// fmt.Printf("Send Call Start Sip(%s) count %d!!!!!!!", s.AgentName, s.simLoopCount)
	if s.simLoopCount < conf.SimLoopCount {
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Send Call Start Sip(%s) count %d!!!!!!!\r\n", s.AgentName, s.simLoopCount)
		s.RequestInvite("01024342788")
		s.simLoopCount += 1
	} else {
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Send Call Start Sip(%s) END!!!!!!!\r\n", s.AgentName, s.simLoopCount)		
	}

	return nil
}

//rtp sender callback timer function
func (s *IcsSession) SendRTPCB(t *icscbtimer.IcsCBTimer) {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()
	//format := conf.AgentConfig[s.ID].MediaConfig.Format

	defer func() {
		if err := recover(); err != nil {
			l.Printf(icslog.LOG_LEVEL_WARN, s.ID, "%s\n%s",
				icserror.ICSERRNETNotConnectError.GetMessage(), debug.Stack())
		}
	}()

	l.Print(icslog.LOG_LEVEL_INFO, s.ID, "Started Callback SendRTPCB")
	//fmt.Printf(">>>>>neter: %d %+v\n", s.ID, s.rtpMediaNeter)
	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "RTP Payload : %d [%p], Destination: %+v",
		s.payloadType,
		&s.rtpMediaNeter,
		s.rtpMediaNeter)

	//init rtp info of session
	//ssrc
	seed := rand.NewSource(time.Now().UnixNano())
	r1 := rand.New(seed)
	s.rtpSSRC = uint32(r1.Intn(999999999))
	//seq
	seed = rand.NewSource(time.Now().UnixNano())
	r1 = rand.New(seed)
	s.rtpSeq = uint16(r1.Intn(9999))
	//timestamp
	s.rtpTS = uint32(time.Now().Unix())

	//s.TX
	// iter := 0
	// totalSentLen := 0
	// offset := 0
	// psize := icspacketparser.RTPPayloadInfo[s.payloadType].PSize
	// ts := s.rtpTS
	// seq := s.rtpSeq


	// voiceFilePath := "/home/leejj9612/sim/voice/9001-RX-1648533187911907029.pcm"
	voiceFilePath := "/home/icsvsim/voice/Sample.pcm"
	readPcmData, ferr := ioutil.ReadFile(voiceFilePath)
	if ferr != nil {
		// fmt.Println("Read Voice File error ", ferr)
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "############ VoiceFile Read ERROR")
		return
	}
	// l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "############ readPcmData %d", readPcmData)
	

	s.m.Lock()
	// pcmDataLen := len(s.tts)
	pcmDataLen := len(readPcmData)
	pcmData := make([]byte, pcmDataLen)
	copy(pcmData, readPcmData[44:]) //cut off wave header
	// fmt.Printf("@@@@@ Read Data len: %d\r\n@@@@@ data: %+v\r\n@@@@@ copyData: %+v \r\n\r\n", pcmDataLen, readPcmData, pcmData)
	//pcmData := s.tts[44:] //cut off wave header
	//fmt.Println("pcmData len>>>", pcmDataLen, len(s.tts))
	s.m.Unlock()

	var cerr *icserror.IcsError
	s.TxConverter, cerr = icsmediaconv.NewConverter(s.ID, s.payloadType, false)
	if cerr != nil {
		l.Printf(icslog.LOG_LEVEL_FATAL, s.ID, "Failed to New Tx Converter-%v", cerr)
		return
	} else {
		l.Print(icslog.LOG_LEVEL_INFO, s.ID, "New Tx Converter(Encoder)")
	}
	//defer s.TxConverter.Close()

	// l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "@@@@@@@@@@@@@@@@@ pcmDataLen : %d, loop Count: %d \r\n", pcmDataLen, conf.CallEndInfo.Loop)
	// fmt.Printf("@@@@@@@@@@@@@@@@@ pcmDataLen : %d, loop Count: %d \r\n", pcmDataLen, conf.CallEndInfo.Loop)
	//fmt.Println(">>>", s.payloadType, icspacketparser.RTPPayloadInfo[s.payloadType].PSize)
	var rtp *icsrtp.RTP
	if conf.CallEndInfo.Value {
		for lc := 0; lc < conf.CallEndInfo.Loop; lc++ {
			// fmt.Printf("@@@@@@@@@@@@@@@@@@@@@@ %d ", lc)
			iter := 0
			totalSentLen := 0
			offset := 0
			psize := icspacketparser.RTPPayloadInfo[s.payloadType].PSize
			ts := s.rtpTS
			seq := s.rtpSeq
			// l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "@@@@@@@@@@@@@@@@@ writRTP ERROR offset: %+v, psize: %+v, ts: %+v\r\n", offset, psize, ts)
			for t1 := range t.GetTick() {
				if pcmDataLen < offset+psize {
					//fmt.Println("BREAK!", pcmDataLen, offset+psize*2)
					break
				}
				/*
				 uplus에서 샘플 음성으로 pcma를 사용(이미 인코딩 되있는 음성파일이라 읽어서 160씩 보내주면됨)
			     	- 인코딩 할 필요 없는 파일이라 인코딩 제거
					- pcma여서 160으로 고정해서 전송(다른 경우는 추후 진행)
				*/
				payload := pcmData[offset : offset+psize]
				//payload, convErr := s.TxConverter.Encode(s.tts[offset : offset+icspacketparser.RTPPayloadInfo[s.payloadType].PSize])
				// if convErr != nil {
				// 	l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Encoding Error - %s", convErr.GetError())
				// 	return
				// }

				//fmt.Printf("1048@@@@ %+v\n", s.rtpMediaNeter)
				/*
					wflen, wferr := ttsfile1.Write(payload)
					if wferr != nil {
						fmt.Println("file.write error", wferr, wflen)
						os.Exit(1)
					}
					ttsfile1.Sync()
				*/

				if iter == 0 {
					if offset+psize >= pcmDataLen {
						//if offset+psize >= alawDataLen {
						offset = 0
					}
					rtp = icsrtp.NewRTP(1, //set mark bit
						int(s.payloadType),
						int(seq),
						int(ts),
						int(s.rtpSSRC),
						payload)
					//alawData[offset:offset+icspacketparser.RTPPayloadInfo[s.payloadType].PSize])
					totalSentLen += icspacketparser.RTPPayloadInfo[s.payloadType].PSize
					offset += psize
					//offset += icspacketparser.RTPPayloadInfo[s.payloadType].PSize
				} else {
					if offset+psize >= pcmDataLen {
						//if offset+psize >= alawDataLen {
						offset = 0
					}
					rtp = icsrtp.NewRTP(0,
						int(s.payloadType),
						int(seq),
						int(ts),
						int(s.rtpSSRC),
						payload)
					//alawData[offset:offset+icspacketparser.RTPPayloadInfo[s.payloadType].PSize])
					totalSentLen += icspacketparser.RTPPayloadInfo[s.payloadType].PSize
					offset += psize
					//offset += icspacketparser.RTPPayloadInfo[s.payloadType].PSize
				}
				iter++
				ts += uint32(psize)
				seq++
				s.txCnt++

				//fmt.Printf("1095@@@@ %+v\n", s.rtpMediaNeter)
				wlen, werr := s.rtpMediaNeter.WriteRTP(rtp.Byte())
				if werr != nil {
					// l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "@@@@@@@@@@@@@@@@@ writRTP ERROR t1: %+v, wlen: %+v, werr: %+v\r\n", t1, wlen, werr)
					fmt.Println(t1, wlen, werr)
				}
				//fmt.Printf("wlen: %d\r", totalSentLen)
				//l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent RTP(%d) to %s", wlen, s.rtpMediaNeter.RemoteAddr().String())

			}
			// fmt.Printf("Sent RTP(%d) to [%s] [%s]\r\n", totalSentLen, s.rtpMediaNeter.RemoteAddr().String(), s.AgentName )
			// l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent RTP(%d) to %s", totalSentLen, s.rtpMediaNeter.RemoteAddr().String())
			time.Sleep(time.Second)
		}
		s.RequestBYE(s.InviteSIP)
	} else {
		for {
			iter := 0
			totalSentLen := 0
			offset := 0
			psize := icspacketparser.RTPPayloadInfo[s.payloadType].PSize
			ts := s.rtpTS
			seq := s.rtpSeq
			for t1 := range t.GetTick() {
				if pcmDataLen < offset+psize*2 {
					//fmt.Println("BREAK!", pcmDataLen, offset+psize*2)
					break
				}
				payload, convErr := s.TxConverter.Encode(pcmData[offset : offset+psize*2])
				//payload, convErr := s.TxConverter.Encode(s.tts[offset : offset+icspacketparser.RTPPayloadInfo[s.payloadType].PSize])
				if convErr != nil {
					l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Encoding Error - %s", convErr.GetError())
					return
				}

				//fmt.Printf("1048@@@@ %+v\n", s.rtpMediaNeter)
				/*
					wflen, wferr := ttsfile1.Write(payload)
					if wferr != nil {
						fmt.Println("file.write error", wferr, wflen)
						os.Exit(1)
					}
					ttsfile1.Sync()
				*/

				if iter == 0 {
					if offset+psize >= pcmDataLen {
						//if offset+psize >= alawDataLen {
						offset = 0
					}
					rtp = icsrtp.NewRTP(1, //set mark bit
						int(s.payloadType),
						int(seq),
						int(ts),
						int(s.rtpSSRC),
						payload)
					//alawData[offset:offset+icspacketparser.RTPPayloadInfo[s.payloadType].PSize])
					totalSentLen += icspacketparser.RTPPayloadInfo[s.payloadType].PSize
					offset += psize * 2
					//offset += icspacketparser.RTPPayloadInfo[s.payloadType].PSize
				} else {
					if offset+psize >= pcmDataLen {
						//if offset+psize >= alawDataLen {
						offset = 0
					}
					rtp = icsrtp.NewRTP(0,
						int(s.payloadType),
						int(seq),
						int(ts),
						int(s.rtpSSRC),
						payload)
					//alawData[offset:offset+icspacketparser.RTPPayloadInfo[s.payloadType].PSize])
					totalSentLen += icspacketparser.RTPPayloadInfo[s.payloadType].PSize
					offset += psize * 2
					//offset += icspacketparser.RTPPayloadInfo[s.payloadType].PSize
				}
				iter++
				ts += uint32(psize)
				seq++
				s.txCnt++

				//fmt.Printf("1095@@@@ %+v\n", s.rtpMediaNeter)
				wlen, werr := s.rtpMediaNeter.WriteRTP(rtp.Byte())
				if werr != nil {
					fmt.Println(t1, wlen, werr)
				}
				//fmt.Printf("wlen: %d\r", totalSentLen)
				//l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent RTP(%d) to %s", wlen, s.rtpMediaNeter.RemoteAddr().String())

			}
			// fmt.Printf("Sent RTP(%d) to [%s] [%s]\r\n", totalSentLen, s.rtpMediaNeter.RemoteAddr().String(), s.AgentName )
			// l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent RTP(%d) to %s", totalSentLen, s.rtpMediaNeter.RemoteAddr().String())
			time.Sleep(time.Second)
			// s.RequestBYE(s.InviteSIP)
		}
	}
}

func (s *IcsSession) ReadRTP() {
	l := icslog.GetIcsLog()
	svc := icssvc.GetServiceStatus()
	conf := icsconf.GetIcsConfig()

	/*
		n := time.Now()
		filename := fmt.Sprintf("./%daaabbb%d-2.pcm", s.ID, n.Nanosecond())
		ttsfile, ferr := os.OpenFile(filename, os.O_CREATE|os.O_RDWR|os.O_APPEND|os.O_TRUNC|os.O_SYNC, os.FileMode(0644))
		if ferr != nil {
			fmt.Println(ferr)
			os.Exit(1)
		}
		//ttsfile.Write(tts)
		defer ttsfile.Close()
	*/

	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started ReadRTP - %s", s.rtpMediaNeter.LocalAddr())

	s.readTimer = *time.NewTicker(time.Second)
	// s.ExpTimer = icscbtimer.NewCBTimer(time.Second, s.ExpiredRTP)
	// s.ExpTimer.Start()
	// go s.ExpiredRTP(s.readTimer)
	for !svc.GetExit() || !svc.GetStop() {
		//fmt.Println(">>>", s.ID, s.rtpMediaNeter.LocalAddr().String())

		if s.rtpMediaNeter == nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "######### media neter nil!!!")
			break
		}

		data, _, rlen, rerr := s.rtpMediaNeter.ReadRTP()
		//data, raddr, rlen, rerr := s.rtpMediaNeter.ReadRTP()
		if rerr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "%s-%s", rerr.GetMessage(), rerr.GetError())
			break
		}
		//l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Recved RTP from %s - %d", raddr.String(), rlen)

		//parsing rtp
		rtp := icspacketparser.NewRTP()
		if err := rtp.RTPParser(data[:rlen]); err != nil {
			l.Print(icslog.LOG_LEVEL_ERROR, s.ID, err.GetMessage())
			continue
		}
		RPT := rtp.GetPayloadType()

		if RPT == icspacketparser.PayloadType(101) { //rfc2833
			///////////////
			//dtmf
			dtmf, derr := icsdtmf.DTMF(s.dtmf, rtp, nil)
			if derr == icserror.ICSERRDTMFOK {
				if s.BotStatus == recorddata.DTMF_COMMAND {
					l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "DTMF : %s", dtmf)
					s.RTPSenderCallBackTimer.Stop()
				}
				//fmt.Printf("DTMF : %s\n", dtmf)

				csraddr := icsnet.NewNetAddrWithIPPort(s.AgentInfo.IP, s.AgentInfo.Port)
				/*
					var inout string = "O"
					s.SetDirection(true)
					if s.GetDirection() {
						inout = "I"
					}
				*/
				callsignal := writecallsignal.NewCallSignalData()
				s.StartTimeStamp = time.Now().UnixNano()
				s.ChannelID = conf.GetChannelID()
				s.ServerID = conf.GetServerID()
				//TODO : agent conf
				//station := conf.AgentConfig[s.ID].Name
				s.Station = s.AgentInfo.Name
				callsignal.SetData(s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, 0, "D", dtmf)
				t, _, werr := icsnet.SendCallSignal(nil, &csraddr, callsignal.GetData())
				if werr != nil {
					l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send Call-Start signal to VoiceAgent(%s)", werr.GetError())
					if t != nil {
						t.Close()
					}
				} else {
					l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent DTMF signal to VoiceAgent - channelid: %s, serverid: %d, station: %s, Custom: %s, starttimestamp: %d, DTMF: %s\n",
						s.ChannelID, s.ServerID, s.Station, s.CustID, s.StartTimeStamp, dtmf)
				}

			} else if derr == icserror.ICSERRDTMFFail {
				l.Printf(icslog.LOG_LEVEL_WARN, s.ID, "DTMF error - %s", derr.GetError())
			}
		} else if RPT == icspacketparser.PayloadType(8) { //rfc2833{
			// fmt.Println("Recev 21 TTS!!!")
			s.expRead = time.Now()
			s.expCheck = false
		} else {
			//rtp decoding
			pcm, cerr := s.RxConverter.Decode(rtp.Payload)
			if cerr != nil {
				l.Print(icslog.LOG_LEVEL_ERROR, s.ID, cerr.GetMessage())
				continue
			}
			//fmt.Println("payload len", len(rtp.Payload), rtp.PayloadLen, len(pcm))
			//ttsfile.Write(pcm)

			///////////////
			//dtmf
			dtmf, derr := icsdtmf.DTMF(s.dtmf, rtp, pcm)
			if derr == nil {
				if s.BotStatus == recorddata.DTMF_COMMAND {
					l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "DTMF : %s", dtmf)
					s.RTPSenderCallBackTimer.Stop()
				}
				continue
			} /*else if derr == icserror.ICSERRDTMFFail {
				l.Printf(icslog.LOG_LEVEL_WARN, s.ID, "DTMF error - %s", derr.GetError())
			}*/

			//send voice data to voice agent
			if s.rxSeq == -1 {
				s.rxSeq = int(rtp.Seq)
			}

			voicedata := recorddata.NewVoiceData()
			voicedata.SetData(s.ServerID, s.Station, int32(rtp.Seq-uint16(s.rxSeq)), s.StartTimeStamp, "0", RPT, pcm)
			_, werr := s.VoiceNeter.Write(voicedata.GetData())
			//_, werr := s.VoiceNeter.WriteRTP(pcm)
			if werr != nil {
				l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Voice writing error(%d) - %s", werr.GetCode(), werr.GetError())
				break
				// continue
			}
			s.rxCnt++
		}
	}
}

// func (s *IcsSession)ExpiredRTP(t *icscbtimer.IcsCBTimer) {
func (s *IcsSession)ExpiredRTP(t time.Ticker) {
	s.mychannel = make(chan bool)
	// fmt.Println("### timer start")
	// valCheckTimer := time.NewTicker(time.Second)
	s.expRead = time.Now()
	for {
		select {
		case <-s.mychannel:
			return
		case tm := <- t.C:
			if s.expCheck {
				fmt.Println("agent : ", s.AgentName , " ", tm)
			} else if !s.expCheck {
				if time.Now().Sub(s.expRead) > time.Second {
					// fmt.Printf("### session expired %s\n", s.AgentName)
					s.RTPSenderCallBackTimer.Start()
					s.expCheck = true
				}
			}
		}
		// if s.expCheck {
		// 	fmt.Println(t)
		// } else if !s.expCheck {
		// 	if time.Now().Sub(s.expRead) > time.Second {
		// 		fmt.Println("### session expired")
		// 		s.RTPSenderCallBackTimer.Start()
		// 		s.expCheck = true
		// 	}
		// }
	}
}

func (s *IcsSession) ReadRTCP() {
	l := icslog.GetIcsLog()
	svc := icssvc.GetServiceStatus()

	for !svc.GetExit() || !svc.GetStop() {
		//fmt.Println("###", s.ID, s.rtcpMediaNeter.LocalAddr().String())

		if s.rtcpMediaNeter == nil {
			break
		}

		data, raddr, rlen, rerr := s.rtcpMediaNeter.ReadRTP()
		if rerr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "%s-%s", rerr.GetMessage(), rerr.GetError())
			break
		}

		rtp := icspacketparser.NewRTP()
		if err := rtp.RTPParser(data[:rlen]); err != nil {
			l.Print(icslog.LOG_LEVEL_ERROR, s.ID, err.GetMessage())
		}

		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Recved RTCP from %s - %d", raddr.String(), rlen)
	}
}

/*
//rtp recver callback timer function
func (s *IcsSession) RecverRTPCB() icsnet.RT
*/

//options callback timer function
func (s *IcsSession) RequestOptionsCB(t *icscbtimer.IcsCBTimer) {
	l := icslog.GetIcsLog()

	conf := icsconf.GetIcsConfig()
	ip := conf.InfoConfig.ServerIP
	port := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport

	optfunc := func(t *time.Time) {
		optMethod := fmt.Sprintf("sip:%s;transport=%s", ip, transport)
		reqOpt := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_OPTIONS, optMethod)

		via := fmt.Sprintf("SIP/2.0/UDP %s;rport;branch=%s", ip, sipasm.GenerateBranch())
		maxforwards := "70"
		from := fmt.Sprintf("<sip:%s@%s>;tag=%s", s.AgentName, ip, sipasm.GenerateTag())

		s.uri = fmt.Sprintf("sip:%s@%s", s.AgentName, ip)
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set URI [%s]", s.uri)

		to := fmt.Sprintf("<sip:%s@%s>", s.AgentName, ip)
		postfix := fmt.Sprintf("@%s", ip)
		callid := sipasm.GenerateCallID(postfix)
		cseq := fmt.Sprintf("%d OPTIONS", s.Cseq)
		s.Cseq++
		contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, port, transport)
		userAgent := conf.InfoConfig.Product
		allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
		supported := "timer,path,replaces"
		contentLength := "0"

		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, via)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, from)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, to)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, callid)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, cseq)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, contentLength)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

		wlen, werr := (*s.sipNeter).WriteSIP([]byte(reqOpt.String()))
		if werr != nil {
			l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
			return
		}

		l.Printf(icslog.LOG_LEVEL_DEBUG, s.ID, "Sent Data(%d) [%s]->[%s]> OPTIONS [%s]",
			wlen,
			(*s.sipNeter).LocalAddr().String(),
			(*s.sipNeter).RemoteAddr().String(),
			callid)
	}
	optfunc(nil)

	for t1 := range t.GetTick() {
		//fmt.Println(s.ID, t1)
		optfunc(&t1)
	}

}

//refer callback timer function
func (s *IcsSession) RequestRefer(referto string, sip *icspacketparser.SIP) {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()
	ip := conf.InfoConfig.ServerIP
	port := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport

	optfunc := func() {
		optMethod := fmt.Sprintf("sip:%s;transport=%s", ip, transport)
		reqOpt := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_REFER, optMethod)

		via := fmt.Sprintf("SIP/2.0/UDP %s;rport;branch=%s", ip, sipasm.GenerateBranch())
		maxforwards := "70"
		from := strings.SplitN(sip.From, ": ", 2)[0]

		s.uri = fmt.Sprintf("sip:%s@%s", s.AgentName, ip)
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set URI [%s]", s.uri)

		to := fmt.Sprintf("<sip:%s@%s>", s.AgentName, ip)
		callid := sip.GetCallID()
		cseq := fmt.Sprintf("%d REFER", s.Cseq)
		s.Cseq++
		referto := fmt.Sprintf("<sip:%s>", s.referto)
		contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, port, transport)
		userAgent := conf.InfoConfig.Product
		allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
		supported := "timer,path,replaces"
		contentLength := "0"

		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, via)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, from)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, to)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, callid)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, cseq)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_REFER_TO, referto)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, contentLength)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

		wlen, werr := (*s.sipNeter).WriteSIP([]byte(reqOpt.String()))
		if werr != nil {
			l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
			return
		}

		l.Printf(icslog.LOG_LEVEL_DEBUG, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
			wlen,
			(*s.sipNeter).LocalAddr().String(),
			(*s.sipNeter).RemoteAddr().String(),
			reqOpt.String())
	}
	optfunc()
}

// refer notify 200ok
func (s *IcsSession) ProcReferNotify200ok(sip *icspacketparser.SIP) {

	l := icslog.GetIcsLog()

	optfunc := func() {
		res200 := sipasm.NewSIPResponse(sip, 200)
		res200.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)
		wlen, werr := (*s.sipNeter).WriteSIP([]byte(res200.String()))
		if werr != nil {
			l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
			s.SetAgentStatus(STATUS_AGENT_READY)
			return
		}
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
			wlen,
			(*s.sipNeter).LocalAddr().String(),
			(*s.sipNeter).RemoteAddr().String(),
			res200.String())
		s.txCnt = 0
		s.callStartTime = time.Now()
		s.SetAgentStatus(STATUS_AGENT_READY)
	}
	optfunc()
}

func (s *IcsSession) RequestBYESIM() {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()
	ip := conf.InfoConfig.ServerIP
	port := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport
	// contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, port, transport)
	// fmt.Println(">>>contact", inviteSIP.Contact)
	// contactName1 := strings.SplitN(inviteSIP.Contact, "sip:", 2)
	// contactName := strings.SplitN(contactName1[1], "@", 2)

	optfunc := func() {
		optMethod := fmt.Sprintf("sip:%s@%s;transport=%s", "AISB", conf.SIPConfig.SIPProxy, transport)
		reqOpt := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_BYE, optMethod)

		via := fmt.Sprintf("SIP/2.0/UDP %s:%d;branch=%s", ip, port, sipasm.GenerateBranch())
		maxforwards := "70"
		// from := strings.SplitN(s.CustID, ": ", 2)
		from := s.AgentName
		// from := fmt.Sprintf("<sip:%s@%s>;tag=%s", s.AgentName, ip, sipasm.GenerateTag())

		s.uri = fmt.Sprintf("sip:%s@%s", s.AgentName, ip)
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set URI [%s]", s.uri)

		// to := strings.SplitN(, ": ", 2)
		to := s.CustID
		//to := fmt.Sprintf("<sip:%s@%s>", s.AgentName, ip)
		callid := s.callID
		cseq := fmt.Sprintf("%d BYE", s.Cseq)
		s.Cseq++
		//referto := fmt.Sprintf("<sip:01025670081@192.168.0.221>")
		contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, port, transport)
		userAgent := conf.InfoConfig.Product
		allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
		supported := "timer,path,replaces"
		contentLength := "0"

		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, via)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, to[0])
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, from[0])
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, callid)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, cseq)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
		//reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_REFER_TO, referto)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, contentLength)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

		wlen, werr := (*s.sipNeter).WriteSIP([]byte(reqOpt.String()))
		if werr != nil {
			l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
			return
		}

		//l.Printf(icslog.LOG_LEVEL_WARN, s.ID, "BYE CALL STACK\n%s", debug.Stack())

		l.Printf(icslog.LOG_LEVEL_DEBUG, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
			wlen,
			(*s.sipNeter).LocalAddr().String(),
			(*s.sipNeter).RemoteAddr().String(),
			reqOpt.String())
	}
	optfunc()
}

//request bye
func (s *IcsSession) RequestBYE(inviteSIP *icspacketparser.SIP) {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()
	// fmt.Printf("inviteSIP %+v\r\n", inviteSIP)
	ip := conf.InfoConfig.ServerIP
	port := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport
	// fmt.Println(">>>contact", inviteSIP.Contact)
	// contactName1 := strings.SplitN(inviteSIP.Contact, "sip:", 2)
	// contactName := strings.SplitN(contactName1[1], "@", 2)

	optfunc := func() {
		optMethod := fmt.Sprintf("sip:%s@%s;transport=%s", "AISB", conf.SIPConfig.SIPProxy, transport)
		reqOpt := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_BYE, optMethod)

		via := fmt.Sprintf("SIP/2.0/UDP %s:%d;branch=%s", ip, port, sipasm.GenerateBranch())
		maxforwards := "70"
		from := fmt.Sprintf("<sip:%s@%s:5090>;tag=%s", "AISB", ip, sipasm.GenerateTag())
		// from := strings.SplitN(inviteSIP.From, ": ", 2)
		//from := fmt.Sprintf("<sip:%s@%s>;tag=%s", s.AgentName, ip, sipasm.GenerateTag())

		s.uri = fmt.Sprintf("sip:%s@%s", "AISB", ip)
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set URI [%s]", s.uri)

		to := fmt.Sprintf("<sip:%s@%s;user=phone>", "01024342788", ip)
		if s.InviteSIP != nil {
			from = s.InviteSIP.From
			to = s.InviteSIP.To
		}
		// to := strings.SplitN(inviteSIP.To, ": ", 2)
		//to := fmt.Sprintf("<sip:%s@%s>", s.AgentName, ip)
		callid := inviteSIP.GetCallID()
		cseq := fmt.Sprintf("%d BYE", s.Cseq)
		s.Cseq++
		//referto := fmt.Sprintf("<sip:01025670081@192.168.0.221>")
		contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", "AISB", ip, port, transport)
		userAgent := conf.InfoConfig.Product
		allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
		supported := "timer,path,replaces"
		contentLength := "0"

		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, via)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, to)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, from)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, callid)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, cseq)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
		//reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_REFER_TO, referto)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, contentLength)
		reqOpt.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

		// wlen, werr := (*s.sipNeter).WriteSIP([]byte(reqOpt.String()))
		wlen, werr := (*s.sipNeter).WriteSIPTo([]byte(reqOpt.String()), s.remoteSIPAddr)
		if werr != nil {
			l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
			return
		}

		//l.Printf(icslog.LOG_LEVEL_WARN, s.ID, "BYE CALL STACK\n%s", debug.Stack())

		l.Printf(icslog.LOG_LEVEL_DEBUG, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
			wlen,
			(*s.sipNeter).LocalAddr().String(),
			(*s.sipNeter).RemoteAddr().String(),
			reqOpt.String())
	}
	optfunc()
}

func (s *IcsSession) Res486Ack(sip *icspacketparser.SIP) *icserror.IcsError {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	ip := conf.InfoConfig.ServerIP
	//mediaPort := conf.AgentConfig[s.ID].MediaConfig.Port
	sipPort := conf.SIPConfig.Port
	transport := conf.SIPConfig.Transport

	ackMethod := fmt.Sprintf("sip:01025670081@%s;transport=%s", "192.168.0.222:5090", transport)

	reqAck := sipasm.NewSIPMessage(sipasm.ICSSIP_METHOD_ACK, ackMethod)

	//via := fmt.Sprintf("SIP/2.0/UDP %s;rport;branch=%s", ip, sipasm.GenerateBranch())
	maxforwards := "70"
	//from := fmt.Sprintf("<sip:%s@%s:5090>;tag=%s", s.AgentName, ip, sipasm.GenerateTag())

	s.uri = fmt.Sprintf("sip:%s@%s", s.AgentName, ip)
	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Set URI [%s]", s.uri)

	//to := fmt.Sprintf("<sip:%s@%s;user=phone>", "01025670081", "192.168.0.221")
	//to := fmt.Sprintf("<sip:%s@%s;user=phone>", "01025670081", ip)
	//to := fmt.Sprintf("<sip:%s@%s>", s.AgentName, ip)
	//cseq := fmt.Sprintf("%d INVITE", s.Cseq)
	contact := fmt.Sprintf("<sip:%s@%s:%d;transport=%s>", s.AgentName, ip, sipPort, transport)
	userAgent := conf.InfoConfig.Product
	allow := "REGISTER,OPTIONS,INVITE,ACK,CANCEL,BYE,NOTIFY,PRACK,REFER,INFO,SUBSCRIBE,UPDATE"
	supported := "timer,path,replaces"

	for _, viav := range sip.Via {
		reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_VIA, viav)
	}
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_MAX_FORWARDS, maxforwards)
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_FROM, sip.From)
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_TO, sip.To)
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CALL_ID, sip.CallID)
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CSEQ, sip.Cseq)
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTACT, contact)
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_USER_AGENT, userAgent)
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_ALLOW, allow)
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_SUPPORTED, supported)
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_CONTENT_LENGTH, "0")
	reqAck.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)

	// wlen, werr := (*s.sipNeter).WriteSIPTo([]byte(reqAck.String()), s.remoteSIPAddr)
	wlen, werr := (*s.sipNeter).WriteSIP([]byte(reqAck.String()))
	if werr != nil {
		l.Print(icslog.LOG_LEVEL_FATAL, s.ID, werr.GetMessage())
		s.SetAgentStatus(STATUS_AGENT_READY)
		return werr
	}
	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
                          wlen,
                          (*s.sipNeter).LocalAddr().String(),
                          (*s.sipNeter).RemoteAddr().String(),
                          reqAck.String())

	return nil
}

func (s *IcsSession) ResError(sip *icspacketparser.SIP, errNum int) {
	var resError *sipasm.SIPMessage
	l := icslog.GetIcsLog()
	switch errNum { // 4xx : client error, 5xx~ : server error
	case 400:
		resError = sipasm.NewSIPResponse(sip, 400) // Bad requeset : request could not be understood by the server
	case 415:
		resError = sipasm.NewSIPResponse(sip, 415) // Unsupported Media Type
	case 488:
		resError = sipasm.NewSIPResponse(sip, 488) // Not Acceptable Here : Codec error
	case 500:
		resError = sipasm.NewSIPResponse(sip, 500) // Internal Server error : server encountered an unexpected condition
	case 502:
		resError = sipasm.NewSIPResponse(sip, 502) // Bad Gateway : The server, while acting as a gateway or proxy, received an invalid response from the upstream server
	}
	resError.AddSIPHeader(sipasm.ICSSIP_HEADER_TERMINATOR)
	wlen, werr := (*s.sipNeter).WriteSIP([]byte(resError.String()))
	if werr != nil {
		l.Print(icslog.LOG_LEVEL_ERROR, s.ID, werr.GetMessage())
		s.SetAgentStatus(STATUS_AGENT_READY)
	}
	l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Sent Data(%d) [%s]->[%s]>\n%s",
		wlen,
		(*s.sipNeter).LocalAddr().String(),
		(*s.sipNeter).RemoteAddr().String(),
		resError.String())
}
