123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 |
- package layers
- import (
- "bytes"
- "fmt"
- "io"
- "strconv"
- "strings"
- "github.com/google/gopacket"
- )
- type SIPVersion uint8
- const (
- SIPVersion1 SIPVersion = 1
- SIPVersion2 SIPVersion = 2
- )
- func (sv SIPVersion) String() string {
- switch sv {
- default:
-
- return "SIP/2.0"
- case SIPVersion1:
- return "SIP/1.0"
- case SIPVersion2:
- return "SIP/2.0"
- }
- }
- func GetSIPVersion(version string) (SIPVersion, error) {
- switch strings.ToUpper(version) {
- case "SIP/1.0":
- return SIPVersion1, nil
- case "SIP/2.0":
- return SIPVersion2, nil
- default:
- return 0, fmt.Errorf("Unknown SIP version: '%s'", version)
- }
- }
- type SIPMethod uint16
- const (
- SIPMethodInvite SIPMethod = 1
- SIPMethodAck SIPMethod = 2
- SIPMethodBye SIPMethod = 3
- SIPMethodCancel SIPMethod = 4
- SIPMethodOptions SIPMethod = 5
- SIPMethodRegister SIPMethod = 6
- SIPMethodPrack SIPMethod = 7
- SIPMethodSubscribe SIPMethod = 8
- SIPMethodNotify SIPMethod = 9
- SIPMethodPublish SIPMethod = 10
- SIPMethodInfo SIPMethod = 11
- SIPMethodRefer SIPMethod = 12
- SIPMethodMessage SIPMethod = 13
- SIPMethodUpdate SIPMethod = 14
- SIPMethodPing SIPMethod = 15
- )
- func (sm SIPMethod) String() string {
- switch sm {
- default:
- return "Unknown method"
- case SIPMethodInvite:
- return "INVITE"
- case SIPMethodAck:
- return "ACK"
- case SIPMethodBye:
- return "BYE"
- case SIPMethodCancel:
- return "CANCEL"
- case SIPMethodOptions:
- return "OPTIONS"
- case SIPMethodRegister:
- return "REGISTER"
- case SIPMethodPrack:
- return "PRACK"
- case SIPMethodSubscribe:
- return "SUBSCRIBE"
- case SIPMethodNotify:
- return "NOTIFY"
- case SIPMethodPublish:
- return "PUBLISH"
- case SIPMethodInfo:
- return "INFO"
- case SIPMethodRefer:
- return "REFER"
- case SIPMethodMessage:
- return "MESSAGE"
- case SIPMethodUpdate:
- return "UPDATE"
- case SIPMethodPing:
- return "PING"
- }
- }
- func GetSIPMethod(method string) (SIPMethod, error) {
- switch strings.ToUpper(method) {
- case "INVITE":
- return SIPMethodInvite, nil
- case "ACK":
- return SIPMethodAck, nil
- case "BYE":
- return SIPMethodBye, nil
- case "CANCEL":
- return SIPMethodCancel, nil
- case "OPTIONS":
- return SIPMethodOptions, nil
- case "REGISTER":
- return SIPMethodRegister, nil
- case "PRACK":
- return SIPMethodPrack, nil
- case "SUBSCRIBE":
- return SIPMethodSubscribe, nil
- case "NOTIFY":
- return SIPMethodNotify, nil
- case "PUBLISH":
- return SIPMethodPublish, nil
- case "INFO":
- return SIPMethodInfo, nil
- case "REFER":
- return SIPMethodRefer, nil
- case "MESSAGE":
- return SIPMethodMessage, nil
- case "UPDATE":
- return SIPMethodUpdate, nil
- case "PING":
- return SIPMethodPing, nil
- default:
- return 0, fmt.Errorf("Unknown SIP method: '%s'", method)
- }
- }
- var compactSipHeadersCorrespondance = map[string]string{
- "accept-contact": "a",
- "allow-events": "u",
- "call-id": "i",
- "contact": "m",
- "content-encoding": "e",
- "content-length": "l",
- "content-type": "c",
- "event": "o",
- "from": "f",
- "identity": "y",
- "refer-to": "r",
- "referred-by": "b",
- "reject-contact": "j",
- "request-disposition": "d",
- "session-expires": "x",
- "subject": "s",
- "supported": "k",
- "to": "t",
- "via": "v",
- }
- type SIP struct {
- BaseLayer
-
- Version SIPVersion
- Method SIPMethod
- Headers map[string][]string
-
- RequestURI string
-
- IsResponse bool
- ResponseCode int
- ResponseStatus string
-
- cseq int64
- contentLength int64
- lastHeaderParsed string
- }
- func decodeSIP(data []byte, p gopacket.PacketBuilder) error {
- s := NewSIP()
- err := s.DecodeFromBytes(data, p)
- if err != nil {
- return err
- }
- p.AddLayer(s)
- p.SetApplicationLayer(s)
- return nil
- }
- func NewSIP() *SIP {
- s := new(SIP)
- s.Headers = make(map[string][]string)
- return s
- }
- func (s *SIP) LayerType() gopacket.LayerType {
- return LayerTypeSIP
- }
- func (s *SIP) Payload() []byte {
- return s.BaseLayer.Payload
- }
- func (s *SIP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
-
- var countLines int
- var line []byte
- var err error
-
- data = bytes.Trim(data, "\n")
-
-
-
- buffer := bytes.NewBuffer(data)
- for {
-
- line, err = buffer.ReadBytes(byte('\n'))
- if err != nil {
- if err == io.EOF {
- break
- } else {
- return err
- }
- }
-
- line = bytes.Trim(line, "\r\n")
-
-
- if len(line) == 0 {
- s.BaseLayer.Payload = buffer.Bytes()
- break
- }
-
-
- if countLines == 0 {
- err = s.ParseFirstLine(line)
- if err != nil {
- return err
- }
- } else {
- err = s.ParseHeader(line)
- if err != nil {
- return err
- }
- }
- countLines++
- }
- return nil
- }
- func (s *SIP) ParseFirstLine(firstLine []byte) error {
- var err error
-
- splits := strings.SplitN(string(firstLine), " ", 3)
-
- if len(splits) < 3 {
- return fmt.Errorf("invalid first SIP line: '%s'", string(firstLine))
- }
-
- if strings.HasPrefix(splits[0], "SIP") {
-
- s.IsResponse = true
-
- s.Version, err = GetSIPVersion(splits[0])
- if err != nil {
- return err
- }
-
- s.ResponseCode, err = strconv.Atoi(splits[1])
- if err != nil {
- return err
- }
-
- s.ResponseStatus = splits[2]
- } else {
-
-
- s.Method, err = GetSIPMethod(splits[0])
- if err != nil {
- return err
- }
- s.RequestURI = splits[1]
-
- s.Version, err = GetSIPVersion(splits[2])
- if err != nil {
- return err
- }
- }
- return nil
- }
- func (s *SIP) ParseHeader(header []byte) (err error) {
-
- if len(header) == 0 {
- return
- }
-
-
-
- if header[0] == '\t' || header[0] == ' ' {
- header = bytes.TrimSpace(header)
- s.Headers[s.lastHeaderParsed][len(s.Headers[s.lastHeaderParsed])-1] += fmt.Sprintf(" %s", string(header))
- return
- }
-
- index := bytes.Index(header, []byte(":"))
- if index >= 0 {
- headerName := strings.ToLower(string(bytes.Trim(header[:index], " ")))
- headerValue := string(bytes.Trim(header[index+1:], " "))
-
- s.Headers[headerName] = append(s.Headers[headerName], headerValue)
- s.lastHeaderParsed = headerName
-
- err = s.ParseSpecificHeaders(headerName, headerValue)
- if err != nil {
- return err
- }
- }
- return nil
- }
- func (s *SIP) ParseSpecificHeaders(headerName string, headerValue string) (err error) {
- switch headerName {
- case "cseq":
-
-
-
- splits := strings.Split(headerValue, " ")
- if len(splits) > 1 {
-
- s.cseq, err = strconv.ParseInt(splits[0], 10, 64)
- if err != nil {
- return err
- }
-
- if s.IsResponse {
- s.Method, err = GetSIPMethod(splits[1])
- if err != nil {
- return err
- }
- }
- }
- case "content-length":
-
- s.contentLength, err = strconv.ParseInt(headerValue, 10, 64)
- if err != nil {
- return err
- }
- }
- return nil
- }
- func (s *SIP) GetAllHeaders() map[string][]string {
- return s.Headers
- }
- func (s *SIP) GetHeader(headerName string) []string {
- headerName = strings.ToLower(headerName)
- h := make([]string, 0)
- if _, ok := s.Headers[headerName]; ok {
- if len(s.Headers[headerName]) > 0 {
- return s.Headers[headerName]
- } else if len(s.Headers[compactSipHeadersCorrespondance[headerName]]) > 0 {
- return s.Headers[compactSipHeadersCorrespondance[headerName]]
- }
- }
- return h
- }
- func (s *SIP) GetFirstHeader(headerName string) string {
- headerName = strings.ToLower(headerName)
- if _, ok := s.Headers[headerName]; ok {
- if len(s.Headers[headerName]) > 0 {
- return s.Headers[headerName][0]
- } else if len(s.Headers[compactSipHeadersCorrespondance[headerName]]) > 0 {
- return s.Headers[compactSipHeadersCorrespondance[headerName]][0]
- }
- }
- return ""
- }
- func (s *SIP) GetAuthorization() string {
- return s.GetFirstHeader("Authorization")
- }
- func (s *SIP) GetFrom() string {
- return s.GetFirstHeader("From")
- }
- func (s *SIP) GetTo() string {
- return s.GetFirstHeader("To")
- }
- func (s *SIP) GetContact() string {
- return s.GetFirstHeader("Contact")
- }
- func (s *SIP) GetCallID() string {
- return s.GetFirstHeader("Call-ID")
- }
- func (s *SIP) GetUserAgent() string {
- return s.GetFirstHeader("User-Agent")
- }
- func (s *SIP) GetContentLength() int64 {
- return s.contentLength
- }
- func (s *SIP) GetCSeq() int64 {
- return s.cseq
- }
|