diago
diago copied to clipboard
Hold/Unhold call
There are no Hold/Unhold functions in the current Diago release. I suggest adding functions based on RFC6337.
My version of the functions is below. For the unhold function, I had trouble restoring the IP address from the c header of the original SDP request. Maybe you can suggest a better way to get the IP address in SDP.
func (d *DialogClientSession) Hold(ctx context.Context, dig sipgo.DigestAuth) error {
c := d.UA.Client
newsdp := d.DialogMedia.Media().MediaSession()
newsdp.Mode = sdp.ModeSendonly
newsdp.ExternalIP = net.ParseIP("0.0.0.0")
req := sip.NewRequest(sip.INVITE, d.InviteRequest.Contact().Address)
req.AppendHeader(d.InviteRequest.Contact())
req.AppendHeader(sip.NewHeader("Content-Type", "application/sdp"))
req.SetBody(newsdp.LocalSDP())
res, err := d.Do(ctx, req)
if err != nil {
return err
}
var resDig *sip.Response
if res.StatusCode == sip.StatusProxyAuthRequired {
resDig, err = c.DoDigestAuth(ctx, req, res, dig)
if err != nil {
return err
}
}
err = d.ReadRequest(req, nil)
if err != nil {
return err
}
if !resDig.IsSuccess() {
return sipgo.ErrDialogResponse{
Res: resDig,
}
}
return d.Ack(ctx)
}
func (d *DialogClientSession) UnHold(ctx context.Context, dig sipgo.DigestAuth) error {
//restore original IP from c-field in initial SDP
inreq := d.InviteRequest.Body()
sd := sdp.SessionDescription{}
if err := sdp.Unmarshal(inreq, &sd); err != nil {
return err
}
cinfo, err := sd.ConnectionInformation()
if err != nil {
return err
}
c := d.UA.Client
newsdp := d.DialogMedia.Media().MediaSession()
newsdp.Mode = sdp.ModeSendrecv
newsdp.ExternalIP = cinfo.IP
req := sip.NewRequest(sip.INVITE, d.InviteRequest.Contact().Address)
req.AppendHeader(d.InviteRequest.Contact())
req.AppendHeader(sip.NewHeader("Content-Type", "application/sdp"))
req.SetBody(newsdp.LocalSDP())
res, err := d.Do(ctx, req)
if err != nil {
return err
}
var resDig *sip.Response
if res.StatusCode == sip.StatusProxyAuthRequired {
resDig, err = c.DoDigestAuth(ctx, req, res, dig)
if err != nil {
return err
}
}
err = d.ReadRequest(req, nil)
if err != nil {
return err
}
if !resDig.IsSuccess() {
return sipgo.ErrDialogResponse{
Res: resDig,
}
}
return d.Ack(ctx)
}
Bigger one. But I am glad to see that you can do this without changing lib?
I will keep eye on to add this. Above solution you may have some races, but not to now discuss this, feature is definetely on my roadmap to add.