sipgo

package module
v0.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 22, 2023 License: BSD-2-Clause Imports: 11 Imported by: 81

README

SIPGO

Go Report Card License GitHub go.mod Go version

Library for writing fast SIP servers in GO language.
It comes with SIP stack (RFC 3261) optimized for fast parsing.

Fetch lib with:

go get github.com/emiago/sipgo

NOTE: LIB IS IN DEV. API CAN CHANGE

Performance

As example you can find example/proxysip as simple version of statefull proxy. It is used for stress testing with sipp. To find out more about performance check the latest results:
example/proxysip

(Contributions are welcome, I would place your results here)

Examples

Stateful proxy example/proxysip
Dialog example/dialog

Usage

Lib allows you to write easily client or server or to build up stateful proxies, registrar or any sip routing. Writing in GO we are not limited to handle SIP requests/responses in many ways, or to integrate and scale with any external services (databases, caches...).

UAS/UAC build
ua, _ := sipgo.NewUA() // Build user agent
srv, _ := sipgo.NewServer(ua) // Creating server handle
client, _ := sipgo.NewClient(ua) // Creating client handle
srv.OnInvite(inviteHandler)
srv.OnAck(ackHandler)
srv.OnCancel(cancelHandler)
srv.OnBye(byeHandler)

// For registrars
// srv.OnRegister(registerHandler)
go srv.ListenAndServe(ctx, "tcp", "127.0.0.1:5061")
go srv.ListenAndServe(ctx, "ws", "127.0.0.1:5080")
go srv.ListenAndServe(ctx, "udp", "127.0.0.1:5060")
<-ctx.Done()
TLS transports
// TLS
conf :=  sipgo.GenerateTLSConfig(certFile, keyFile, rootPems)
srv.ListenAndServeTLS(ctx, "tcp", "127.0.0.1:5061", conf)

Stateful Proxy build

Proxy is combination client and server handle that creates server/client transaction. They need to share same ua same like uac/uas build. Forwarding request is done via client handle:


srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) {
    req.SetDestination("10.1.2.3") // Change sip.Request destination
    // Start client transaction and relay our request. Add Via and Record-Route header
    clTx, err := client.TransactionRequest(req, sipgo.ClientRequestAddVia, sipgo.ClientRequestAddRecordRoute)
    // Send back response
    res := <-cltx.Responses()
    tx.Respond(res)
})

Checkout /example/proxysip for more how to build simple stateful proxy.

Server Transaction

Server transaction is passed on handler

// Incoming request
srv.OnInvite(func(req *sip.Request, tx sip.ServerTransaction) {
    res := sip.NewResponseFromRequest(req, code, reason, body)
    // Send response
    tx.Respond(res)

    select {
        case m := <-tx.Acks(): // Handle ACK . ACKs on 2xx are send as different request
        case m := <-tx.Cancels(): // Handle Cancel 
        case <-tx.Done():
            // Signal transaction is done. 
            return
    }

    // terminating handler terminates Server transaction automaticaly
})

Server stateless response
srv := sipgo.NewServer()
...
func ackHandler(req *sip.Request, tx sip.ServerTransaction) {
    res := sip.NewResponseFromRequest(req, code, reason, body)
    srv.WriteResponse(res)
}
srv.OnACK(ackHandler)
Client Transaction

NOTE: UA needs server handle and listener on same network before sending request

client, _ := sipgo.NewClient(ua) // Creating client handle

// Request is either from server request handler or created
req.SetDestination("10.1.2.3") // Change sip.Request destination
tx, err := client.TransactionRequest(req) // Send request and get client transaction handle

defer tx.Terminate() // Client Transaction must be terminated for cleanup
...

select {
    case res := <-tx.Responses():
    // Handle responses
    case <-tx.Done():
    // Wait for termination
    return
}

Client stateless request
client, _ := sipgo.NewClient(ua) // Creating client handle
req := sip.NewRequest(method, &recipment, "SIP/2.0")
// Send request and forget
client.WriteRequest(req)
Dialogs (experiment)

ServerDialog is extended type of Server with Dialog support. For now this is in experiment.

srv, err := sipgo.NewServerDialog(ua)
...
srv.OnDialog(func(d sip.Dialog) {
    switch d.State {
	case sip.DialogStateEstablished:
		// 200 response
	case sip.DialogStateConfirmed:
		// ACK send
	case sip.DialogStateEnded:
		// BYE send
	}
})

ClientDialog TODO...

Documentation

More on documentation you can find on Go doc

Supported protocols

  • UDP
  • TCP
  • TLS
  • WS
  • WSS

Tests

Library will be covered with more tests. Focus is more on benchmarking currently.

go test ./...  

Credits

This project was based on gosip by project by @ghetovoice, but started as new project to achieve best/better performance and to improve API. This unfortunately required many design changes, therefore this libraries are not compatible.

Support

If you find this project interesting for support or contributing, you can contact me on mail

For bugs features pls create issue.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClientRequestAddRecordRoute

func ClientRequestAddRecordRoute(c *Client, r *sip.Request) error

ClientRequestAddRecordRoute is option for adding record route header Based on proxy setup https://www.rfc-editor.org/rfc/rfc3261#section-16

func ClientRequestAddVia

func ClientRequestAddVia(c *Client, r *sip.Request) error

ClientRequestAddVia is option for adding via header Based on proxy setup https://www.rfc-editor.org/rfc/rfc3261.html#section-16.6

func ClientRequestDecreaseMaxForward added in v0.7.0

func ClientRequestDecreaseMaxForward(c *Client, r *sip.Request) error

TODO Based on proxy setup https://www.rfc-editor.org/rfc/rfc3261#section-16

func ClientResponseRemoveVia

func ClientResponseRemoveVia(c *Client, r *sip.Response)

ClientResponseRemoveVia is needed when handling client transaction response, where previously used in TransactionRequest with ClientRequestAddVia

func GenerateTLSConfig added in v0.7.0

func GenerateTLSConfig(certFile string, keyFile string, rootPems []byte) (*tls.Config, error)

GenerateTLSConfig creates basic tls.Config that you can pass for ServerTLS It needs rootPems for client side

Types

type Client

type Client struct {
	*UserAgent
	// contains filtered or unexported fields
}

func NewClient

func NewClient(ua *UserAgent, options ...ClientOption) (*Client, error)

func (*Client) TransactionRequest

func (c *Client) TransactionRequest(req *sip.Request, options ...ClientRequestOption) (sip.ClientTransaction, error)

TransactionRequest uses transaction layer to send request

func (*Client) WriteRequest

func (c *Client) WriteRequest(req *sip.Request, options ...ClientRequestOption) error

WriteRequest sends request directly to transport layer

type ClientOption

type ClientOption func(c *Client) error

type ClientRequestOption

type ClientRequestOption func(c *Client, req *sip.Request) error

type RequestHandler

type RequestHandler func(req *sip.Request, tx sip.ServerTransaction)

RequestHandler is a callback that will be called on the incoming request

type Server

type Server struct {
	*UserAgent
	// contains filtered or unexported fields
}

Server is a SIP server

func NewServer

func NewServer(ua *UserAgent, options ...ServerOption) (*Server, error)

NewServer creates new instance of SIP server.

func (*Server) ListenAndServe added in v0.7.0

func (srv *Server) ListenAndServe(ctx context.Context, network string, addr string) error

Serve will fire all listeners. Ctx allows canceling

func (*Server) ListenAndServeTLS added in v0.7.0

func (srv *Server) ListenAndServeTLS(ctx context.Context, network string, addr string, conf *tls.Config) error

Serve will fire all listeners that are secured. Ctx allows canceling

func (*Server) OnAck

func (srv *Server) OnAck(handler RequestHandler)

OnAck registers Ack request handler

func (*Server) OnBye

func (srv *Server) OnBye(handler RequestHandler)

OnBye registers Bye request handler

func (*Server) OnCancel

func (srv *Server) OnCancel(handler RequestHandler)

OnCancel registers Cancel request handler

func (*Server) OnInfo

func (srv *Server) OnInfo(handler RequestHandler)

OnInfo registers Info request handler

func (*Server) OnInvite

func (srv *Server) OnInvite(handler RequestHandler)

OnInvite registers Invite request handler

func (*Server) OnMessage

func (srv *Server) OnMessage(handler RequestHandler)

OnMessage registers Message request handler

func (*Server) OnNotify

func (srv *Server) OnNotify(handler RequestHandler)

OnNotify registers Notify request handler

func (*Server) OnOptions

func (srv *Server) OnOptions(handler RequestHandler)

OnOptions registers Options request handler

func (*Server) OnPrack

func (srv *Server) OnPrack(handler RequestHandler)

OnPrack registers Prack request handler

func (*Server) OnPublish

func (srv *Server) OnPublish(handler RequestHandler)

OnPublish registers Publish request handler

func (*Server) OnRefer

func (srv *Server) OnRefer(handler RequestHandler)

OnRefer registers Refer request handler

func (*Server) OnRegister

func (srv *Server) OnRegister(handler RequestHandler)

OnRegister registers Register request handler

func (*Server) OnRequest

func (srv *Server) OnRequest(method sip.RequestMethod, handler RequestHandler)

OnRequest registers new request callback. Can be used as generic way to add handler

func (*Server) OnSubscribe

func (srv *Server) OnSubscribe(handler RequestHandler)

OnSubscribe registers Subscribe request handler

func (*Server) OnUpdate

func (srv *Server) OnUpdate(handler RequestHandler)

OnUpdate registers Update request handler

func (*Server) ServeRequest

func (srv *Server) ServeRequest(f func(r *sip.Request))

ServeRequest can be used as middleware for preprocessing message

func (*Server) ServeResponse

func (srv *Server) ServeResponse(f func(m *sip.Response))

TODO can this handled better?

func (*Server) TransportLayer

func (srv *Server) TransportLayer() *transport.Layer

Transport is function to get transport layer of server Can be used for modifying

func (*Server) WriteResponse

func (srv *Server) WriteResponse(r *sip.Response) error

WriteResponse will proxy message to transport layer. Use it in stateless mode

type ServerDialog

type ServerDialog struct {
	Server
	// contains filtered or unexported fields
}

ServerDialog is extension of Server to support Dialog handling

func NewServerDialog

func NewServerDialog(ua *UserAgent, options ...ServerOption) (*ServerDialog, error)

func (*ServerDialog) OnDialog

func (s *ServerDialog) OnDialog(f func(d sip.Dialog))

OnDialog allows monitoring new dialogs

func (*ServerDialog) OnDialogChan

func (s *ServerDialog) OnDialogChan(ch chan sip.Dialog)

OnDialogChan same as onDialog but we channel instead callback func

type ServerOption

type ServerOption func(s *Server) error

func WithLogger

func WithLogger(logger zerolog.Logger) ServerOption

func WithUDPDNSResolver

func WithUDPDNSResolver(dns string) ServerOption

type UserAgent

type UserAgent struct {
	// contains filtered or unexported fields
}

func NewUA

func NewUA(options ...UserAgentOption) (*UserAgent, error)

type UserAgentOption

type UserAgentOption func(s *UserAgent) error

func WithDNSResolver

func WithDNSResolver(r *net.Resolver) UserAgentOption

func WithIP

func WithIP(ip string) UserAgentOption

func WithUserAgent

func WithUserAgent(ua string) UserAgentOption

Directories

Path Synopsis
example
dialog command
proxysip command
Originaly forked from github.com/StefanKopieczek/gossip by @StefanKopieczek
Originaly forked from github.com/StefanKopieczek/gossip by @StefanKopieczek
Originally forked from https://github.com/ghettovoice/gosip by @ghetovoice
Originally forked from https://github.com/ghettovoice/gosip by @ghetovoice

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL