Ai
1 Star 1 Fork 0

ZJOOPS/gosip

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
message.go 12.63 KB
一键复制 编辑 原始数据 按行查看 历史
zhangjun 提交于 2022-07-25 15:23 +08:00 . -fix 修复invite ack的bug
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
package sip
import (
"bytes"
"strings"
"sync"
uuid "github.com/satori/go.uuid"
"gitee.com/zhjun2512/gosip/log"
)
// A representation of a SIP method.
// This is syntactic sugar around the string type, so make sure to use
// the Equals method rather than built-in equality, or you'll fall foul of case differences.
// If you're defining your own Method, uppercase is preferred but not compulsory.
type RequestMethod string
// StatusCode - response status code: 1xx - 6xx
type StatusCode uint16
// Determine if the given method equals some other given method.
// This is syntactic sugar for case insensitive equality checking.
func (method *RequestMethod) Equals(other *RequestMethod) bool {
if method != nil && other != nil {
return strings.EqualFold(string(*method), string(*other))
} else {
return method == other
}
}
// It's nicer to avoid using raw strings to represent methods, so the following standard
// method names are defined here as constants for convenience.
const (
INVITE RequestMethod = "INVITE"
ACK RequestMethod = "ACK"
CANCEL RequestMethod = "CANCEL"
BYE RequestMethod = "BYE"
REGISTER RequestMethod = "REGISTER"
OPTIONS RequestMethod = "OPTIONS"
SUBSCRIBE RequestMethod = "SUBSCRIBE"
NOTIFY RequestMethod = "NOTIFY"
REFER RequestMethod = "REFER"
INFO RequestMethod = "INFO"
MESSAGE RequestMethod = "MESSAGE"
PRACK RequestMethod = "PRACK"
UPDATE RequestMethod = "UPDATE"
PUBLISH RequestMethod = "PUBLISH"
)
type MessageID string
func NextMessageID() MessageID {
return MessageID(uuid.NewV4().String())
}
// Message introduces common SIP message RFC 3261 - 7.
type Message interface {
MessageID() MessageID
Clone() Message
// Start line returns message start line.
StartLine() string
// String returns string representation of SIP message in RFC 3261 form.
String() string
// Short returns short string info about message.
Short() string
// SipVersion returns SIP protocol version.
SipVersion() string
// SetSipVersion sets SIP protocol version.
SetSipVersion(version string)
// Headers returns all message headers.
Headers() []Header
// GetHeaders returns slice of headers of the given type.
GetHeaders(name string) []Header
// AppendHeader appends header to message.
AppendHeader(header Header)
// PrependHeader prepends header to message.
PrependHeader(header Header)
PrependHeaderAfter(header Header, afterName string)
// RemoveHeader removes header from message.
RemoveHeader(name string)
ReplaceHeaders(name string, headers []Header)
// Body returns message body.
Body() string
// SetBody sets message body.
SetBody(body string, setContentLength bool)
/* Helper getters for common headers */
// CallID returns 'Call-ID' header.
CallID() (*CallID, bool)
// Via returns the top 'Via' header field.
Via() (ViaHeader, bool)
// ViaHop returns the first segment of the top 'Via' header.
ViaHop() (*ViaHop, bool)
// From returns 'From' header field.
From() (*FromHeader, bool)
// To returns 'To' header field.
To() (*ToHeader, bool)
// CSeq returns 'CSeq' header field.
CSeq() (*CSeq, bool)
ContentLength() (*ContentLength, bool)
ContentType() (*ContentType, bool)
Contact() (*ContactHeader, bool)
Transport() string
SetTransport(tp string)
Source() string
SetSource(src string)
Destination() string
SetDestination(dest string)
IsCancel() bool
IsAck() bool
Fields() log.Fields
WithFields(fields log.Fields) Message
}
// headers is a struct with methods to work with SIP headers.
type headers struct {
mu sync.RWMutex
// The logical SIP headers attached to this message.
headers map[string][]Header
// The order the headers should be displayed in.
headerOrder []string
}
func newHeaders(hdrs []Header) *headers {
hs := new(headers)
hs.headers = make(map[string][]Header)
hs.headerOrder = make([]string, 0)
for _, header := range hdrs {
hs.AppendHeader(header)
}
return hs
}
func (hs *headers) String() string {
buffer := bytes.Buffer{}
hs.mu.RLock()
// Construct each header in turn and add it to the message.
for typeIdx, name := range hs.headerOrder {
headers := hs.headers[name]
for idx, header := range headers {
buffer.WriteString(header.String())
if typeIdx < len(hs.headerOrder) || idx < len(headers) {
buffer.WriteString("\r\n")
}
}
}
hs.mu.RUnlock()
return buffer.String()
}
// Add the given header.
func (hs *headers) AppendHeader(header Header) {
name := strings.ToLower(header.Name())
hs.mu.Lock()
if _, ok := hs.headers[name]; ok {
hs.headers[name] = append(hs.headers[name], header)
} else {
hs.headers[name] = []Header{header}
hs.headerOrder = append(hs.headerOrder, name)
}
hs.mu.Unlock()
}
// AddFrontHeader adds header to the front of header list
// if there is no header has h's name, add h to the font of all headers
// if there are some headers have h's name, add h to front of the sublist
func (hs *headers) PrependHeader(header Header) {
name := strings.ToLower(header.Name())
hs.mu.Lock()
if hdrs, ok := hs.headers[name]; ok {
hs.headers[name] = append([]Header{header}, hdrs...)
} else {
hs.headers[name] = []Header{header}
newOrder := make([]string, 1, len(hs.headerOrder)+1)
newOrder[0] = name
hs.headerOrder = append(newOrder, hs.headerOrder...)
}
hs.mu.Unlock()
}
func (hs *headers) PrependHeaderAfter(header Header, afterName string) {
headerName := strings.ToLower(header.Name())
afterName = strings.ToLower(afterName)
hs.mu.Lock()
if _, ok := hs.headers[afterName]; ok {
afterIdx := -1
headerIdx := -1
for i, name := range hs.headerOrder {
if name == afterName {
afterIdx = i
}
if name == headerName {
headerIdx = i
}
}
if headerIdx == -1 {
hs.headers[headerName] = []Header{header}
newOrder := make([]string, 0)
newOrder = append(newOrder, hs.headerOrder[:afterIdx+1]...)
newOrder = append(newOrder, headerName)
newOrder = append(newOrder, hs.headerOrder[afterIdx+1:]...)
hs.headerOrder = newOrder
} else {
hs.headers[headerName] = append([]Header{header}, hs.headers[headerName]...)
newOrder := make([]string, 0)
if afterIdx < headerIdx {
newOrder = append(newOrder, hs.headerOrder[:afterIdx+1]...)
newOrder = append(newOrder, headerName)
newOrder = append(newOrder, hs.headerOrder[afterIdx+1:headerIdx]...)
newOrder = append(newOrder, hs.headerOrder[headerIdx+1:]...)
} else {
newOrder = append(newOrder, hs.headerOrder[:headerIdx]...)
newOrder = append(newOrder, hs.headerOrder[headerIdx+1:afterIdx+1]...)
newOrder = append(newOrder, headerName)
newOrder = append(newOrder, hs.headerOrder[afterIdx+1:]...)
}
hs.headerOrder = newOrder
}
hs.mu.Unlock()
} else {
hs.mu.Unlock()
hs.PrependHeader(header)
}
}
func (hs *headers) ReplaceHeaders(name string, headers []Header) {
name = strings.ToLower(name)
hs.mu.Lock()
if _, ok := hs.headers[name]; ok {
hs.headers[name] = headers
}
hs.mu.Unlock()
}
// Gets some headers.
func (hs *headers) Headers() []Header {
hdrs := make([]Header, 0)
hs.mu.RLock()
for _, key := range hs.headerOrder {
hdrs = append(hdrs, hs.headers[key]...)
}
hs.mu.RUnlock()
return hdrs
}
func (hs *headers) GetHeaders(name string) []Header {
name = strings.ToLower(name)
hs.mu.RLock()
defer hs.mu.RUnlock()
if hs.headers == nil {
hs.headers = map[string][]Header{}
hs.headerOrder = []string{}
}
if headers, ok := hs.headers[name]; ok {
return headers
}
return []Header{}
}
func (hs *headers) RemoveHeader(name string) {
name = strings.ToLower(name)
hs.mu.Lock()
delete(hs.headers, name)
// update order slice
for idx, entry := range hs.headerOrder {
if entry == name {
hs.headerOrder = append(hs.headerOrder[:idx], hs.headerOrder[idx+1:]...)
break
}
}
hs.mu.Unlock()
}
// CloneHeaders returns all cloned headers in slice.
func (hs *headers) CloneHeaders() []Header {
return cloneHeaders(hs)
}
func cloneHeaders(msg interface{ Headers() []Header }) []Header {
hdrs := make([]Header, 0)
for _, header := range msg.Headers() {
hdrs = append(hdrs, header.Clone())
}
return hdrs
}
func (hs *headers) CallID() (*CallID, bool) {
hdrs := hs.GetHeaders("Call-ID")
if len(hdrs) == 0 {
return nil, false
}
callId, ok := hdrs[0].(*CallID)
if !ok {
return nil, false
}
return callId, true
}
func (hs *headers) Via() (ViaHeader, bool) {
hdrs := hs.GetHeaders("Via")
if len(hdrs) == 0 {
return nil, false
}
via, ok := (hdrs[0]).(ViaHeader)
if !ok {
return nil, false
}
return via, true
}
func (hs *headers) ViaHop() (*ViaHop, bool) {
via, ok := hs.Via()
if !ok {
return nil, false
}
hops := []*ViaHop(via)
if len(hops) == 0 {
return nil, false
}
return hops[0], true
}
func (hs *headers) From() (*FromHeader, bool) {
hdrs := hs.GetHeaders("From")
if len(hdrs) == 0 {
return nil, false
}
from, ok := hdrs[0].(*FromHeader)
if !ok {
return nil, false
}
return from, true
}
func (hs *headers) To() (*ToHeader, bool) {
hdrs := hs.GetHeaders("To")
if len(hdrs) == 0 {
return nil, false
}
to, ok := hdrs[0].(*ToHeader)
if !ok {
return nil, false
}
return to, true
}
func (hs *headers) CSeq() (*CSeq, bool) {
hdrs := hs.GetHeaders("CSeq")
if len(hdrs) == 0 {
return nil, false
}
cseq, ok := hdrs[0].(*CSeq)
if !ok {
return nil, false
}
return cseq, true
}
func (hs *headers) ContentLength() (*ContentLength, bool) {
hdrs := hs.GetHeaders("Content-Length")
if len(hdrs) == 0 {
return nil, false
}
contentLength, ok := hdrs[0].(*ContentLength)
if !ok {
return nil, false
}
return contentLength, true
}
func (hs *headers) ContentType() (*ContentType, bool) {
hdrs := hs.GetHeaders("Content-Type")
if len(hdrs) == 0 {
return nil, false
}
contentType, ok := hdrs[0].(*ContentType)
if !ok {
return nil, false
}
return contentType, true
}
func (hs *headers) Contact() (*ContactHeader, bool) {
hdrs := hs.GetHeaders("Contact")
if len(hdrs) == 0 {
return nil, false
}
contactHeader, ok := hdrs[0].(*ContactHeader)
if !ok {
return nil, false
}
return contactHeader, true
}
// basic message implementation
type message struct {
// message headers
*headers
mu sync.RWMutex
messID MessageID
sipVersion string
body string
startLine func() string
tp string
src string
dest string
fields log.Fields
}
func (msg *message) MessageID() MessageID {
return msg.messID
}
func (msg *message) StartLine() string {
return msg.startLine()
}
func (msg *message) Fields() log.Fields {
msg.mu.RLock()
defer msg.mu.RUnlock()
return msg.fields.WithFields(log.Fields{
"transport": msg.tp,
"source": msg.src,
"destination": msg.dest,
})
}
func (msg *message) String() string {
var buffer bytes.Buffer
// write message start line
buffer.WriteString(msg.StartLine() + "\r\n")
// Write the headers.
msg.mu.RLock()
buffer.WriteString(msg.headers.String())
msg.mu.RUnlock()
// message body
buffer.WriteString("\r\n" + msg.Body())
return buffer.String()
}
func (msg *message) SipVersion() string {
msg.mu.RLock()
defer msg.mu.RUnlock()
return msg.sipVersion
}
func (msg *message) SetSipVersion(version string) {
msg.mu.Lock()
msg.sipVersion = version
msg.mu.Unlock()
}
func (msg *message) Body() string {
msg.mu.RLock()
defer msg.mu.RUnlock()
return msg.body
}
// SetBody sets message body, calculates it length and add 'Content-Length' header.
func (msg *message) SetBody(body string, setContentLength bool) {
msg.mu.Lock()
msg.body = body
msg.mu.Unlock()
if setContentLength {
hdrs := msg.GetHeaders("Content-Length")
if len(hdrs) == 0 {
length := ContentLength(len(body))
msg.AppendHeader(&length)
} else {
length := ContentLength(len(body))
msg.ReplaceHeaders("Content-Length", []Header{&length})
}
}
}
func (msg *message) Transport() string {
msg.mu.RLock()
defer msg.mu.RUnlock()
return msg.tp
}
func (msg *message) SetTransport(tp string) {
msg.mu.Lock()
msg.tp = strings.ToUpper(tp)
msg.mu.Unlock()
}
func (msg *message) Source() string {
msg.mu.RLock()
defer msg.mu.RUnlock()
return msg.src
}
func (msg *message) SetSource(src string) {
msg.mu.Lock()
msg.src = src
msg.mu.Unlock()
}
func (msg *message) Destination() string {
msg.mu.RLock()
defer msg.mu.RUnlock()
return msg.dest
}
func (msg *message) SetDestination(dest string) {
msg.mu.Lock()
msg.dest = dest
msg.mu.Unlock()
}
// Copy all headers of one type from one message to another.
// Appending to any headers that were already there.
func CopyHeaders(name string, from, to Message) {
name = strings.ToLower(name)
for _, h := range from.GetHeaders(name) {
to.AppendHeader(h.Clone())
}
}
func PrependCopyHeaders(name string, from, to Message) {
name = strings.ToLower(name)
for _, h := range from.GetHeaders(name) {
to.PrependHeader(h.Clone())
}
}
type MessageMapper func(msg Message) Message
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/zhjun2512/gosip.git
git@gitee.com:zhjun2512/gosip.git
zhjun2512
gosip
gosip
v0.0.5

搜索帮助