API Docs
Library API tries to be well documented through comments. For more reference visit GO DOC
Here we explain some of main built in concepts and usage.
Dialog Sessions
diago can act as UAS(User Agent Server) and UAC(User Agent Client), and adds bridging capability to build B2BUA services.
It intentionally distincts dialog received (Acting as server) and dialog created (Acting as client):
DialogServerSession
when receving incoming dialog (SIP INVITE) and setups session (media)DialogClientSession
when it creates outgoing dialog (SIP INVITE) and setups session (media)
For best understanding here some docs with short code reference.
Setup
Diago needs instance to be created NewDiago
or in other words instance represents single UserAgent.
With this instance you can serve multiple incoming dialogs or dial destinations in parallel.
ua, _ := sipgo.NewUA()
dg := diago.NewDiago(ua)
Customize SIP Transport
Diago allows you to customize transport listeners with WithTransport
Below example makes diago only listen for TCP
SIP.
transportTCP := diago.Transport{
Transport: "tcp",
BindHost: "127.0.0.1",
BindPort: 5060,
}
dg := diago.NewDiago(ua,
diago.WithTransport(transportTCP),
)
Transport support: UDP, TCP, TLS, WS, WSS
For more configuration checkout GO Docs
Incoming call
Calling Serve
allows to serve every new call. Here you can build
you routing by accessing dialog. Some of helpers are added
ToUser
- destination callerIDFromUser
- from callerIDTransport
- transport of SIP message
See example below.
dg.Serve(ctx, func(inDialog *diago.DialogServerSession) {
// - Do your call routing.
switch inDialog.ToUser() {
case "answer":
case "123456"
}
// inDialog is scope limited, exiting this routine will Close dialog.
// Use Context to hold dialog in routine
<-inDialog.Context().Done()
})
NOTE: Dialog created is scoped (Like HTTP request serving). Once dialog exists, it is cleaned up, so no further action is needed.
Outgoing call
Invite
sends SIP INVITE and waits for answer. After succesfull answer you can apply many other actions for dialog.
dialog, err := dg.Invite(ctx, recipient sip.Uri, opts diago.InviteOptions)
if err != nil {
// Handle err. Special ErrDialogResponse is returned if non 200 is received
}
defer dialog.Close() // Closing outgoing dialog is needed
// Do something
// Hangup
dialog.Hangup()
Answering call
func Answer(inDialog *diago.DialogServerSession) {
inDialog.Progress() // Progress -> 100 Trying
inDialog.Ringing() // Ringing -> 180 Response
if err := inDialog.Answer(); err != nil {
fmt.Println("Failed to answer", err)
return
}
ctx := inDialog.Context()
select {
case <-ctx.Done():
case <-time.After(1 * time.Minute):
}
}
Media handling
Every session comes with 2 streams (Audio for now). In diago case it is referenced as reader/writer.
AudioReader
reads incoming streamAudioWriter
writes outgoing stream
Normally you mostly deal with writing audio so Playback is created for easier dealing with audio streams.
NOTE: Diago does not automatically reads audio stream in background. This can happen with explicit call or bridging.
Playback
Playing audio file is done with audio playback. Library provides prebuilt playback functionality
Playback can:
- Play File (wav/PCM)
- Play any stream (no encoders)
Either outgoing or incoming after leg is answered you can create playback
pb, err := dialog.PlaybackCreate()
if err != nil {
fmt.Println("Failed to create playback", err)
return
}
if err := pb.Play(playfile, "audio/wav"); err != nil {
fmt.Println("Playing failed", err)
}
}
Playback with control
If you need to control your playback like Mute
Unmute
or just to Stop
current playback, then you can use AudioPlaybackControl
pb, err := dialog.PlaybackControlCreate()
if err != nil {
fmt.Println("Failed to create playback", err)
return
}
go pb.Play(playfile, "audio/wav") // Note needs error handling
pb.Mute(true) // Mute/Unmute audio
pb.Stop() // Stop playing audio. This will make Play exit
}
Bridge
Bridge allows bridging your Dialog Sessions. If dialogs are answered and have media sessions you can bridge them.
bridge := diago.NewBridge()
bridge.AddDialogSession(d1)
bridge.AddDialogSession(d2)
For now bridge is only doing proxy of RTP and it does not allow Transcoding.
Transcoding is generally something you do not want in running system so bridge will return error in case codecs are missmatch.