response.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. package sip
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strconv"
  6. "strings"
  7. "github.com/ghettovoice/gosip/log"
  8. )
  9. // Response RFC 3261 - 7.2.
  10. type Response interface {
  11. Message
  12. StatusCode() StatusCode
  13. SetStatusCode(code StatusCode)
  14. Reason() string
  15. SetReason(reason string)
  16. // Previous returns previous provisional responses
  17. Previous() []Response
  18. SetPrevious(responses []Response)
  19. /* Common helpers */
  20. IsProvisional() bool
  21. IsSuccess() bool
  22. IsRedirection() bool
  23. IsClientError() bool
  24. IsServerError() bool
  25. IsGlobalError() bool
  26. }
  27. type response struct {
  28. message
  29. status StatusCode
  30. reason string
  31. previous []Response
  32. }
  33. func NewResponse(
  34. messID MessageID,
  35. sipVersion string,
  36. statusCode StatusCode,
  37. reason string,
  38. hdrs []Header,
  39. body string,
  40. fields log.Fields,
  41. ) Response {
  42. res := new(response)
  43. if messID == "" {
  44. res.messID = NextMessageID()
  45. } else {
  46. res.messID = messID
  47. }
  48. res.startLine = res.StartLine
  49. res.sipVersion = sipVersion
  50. res.headers = newHeaders(hdrs)
  51. res.status = statusCode
  52. res.reason = reason
  53. res.body = body
  54. res.fields = fields.WithFields(log.Fields{
  55. "response_id": res.messID,
  56. })
  57. res.previous = make([]Response, 0)
  58. return res
  59. }
  60. func (res *response) Short() string {
  61. if res == nil {
  62. return "<nil>"
  63. }
  64. fields := log.Fields{
  65. "status": res.StatusCode(),
  66. "reason": res.Reason(),
  67. "transport": res.Transport(),
  68. "source": res.Source(),
  69. "destination": res.Destination(),
  70. }
  71. if cseq, ok := res.CSeq(); ok {
  72. fields["method"] = cseq.MethodName
  73. fields["sequence"] = cseq.SeqNo
  74. }
  75. fields = res.Fields().WithFields(fields)
  76. return fmt.Sprintf("sip.Response<%s>", fields)
  77. }
  78. func (res *response) StatusCode() StatusCode {
  79. res.mu.RLock()
  80. defer res.mu.RUnlock()
  81. return res.status
  82. }
  83. func (res *response) SetStatusCode(code StatusCode) {
  84. res.mu.Lock()
  85. res.status = code
  86. res.mu.Unlock()
  87. }
  88. func (res *response) Reason() string {
  89. res.mu.RLock()
  90. defer res.mu.RUnlock()
  91. return res.reason
  92. }
  93. func (res *response) SetReason(reason string) {
  94. res.mu.Lock()
  95. res.reason = reason
  96. res.mu.Unlock()
  97. }
  98. func (res *response) Previous() []Response {
  99. res.mu.RLock()
  100. defer res.mu.RUnlock()
  101. return res.previous
  102. }
  103. func (res *response) SetPrevious(responses []Response) {
  104. res.mu.Lock()
  105. res.previous = responses
  106. res.mu.Unlock()
  107. }
  108. // StartLine returns Response Status Line - RFC 2361 7.2.
  109. func (res *response) StartLine() string {
  110. var buffer bytes.Buffer
  111. // Every SIP response starts with a Status Line - RFC 2361 7.2.
  112. buffer.WriteString(
  113. fmt.Sprintf(
  114. "%s %d %s",
  115. res.SipVersion(),
  116. res.StatusCode(),
  117. res.Reason(),
  118. ),
  119. )
  120. return buffer.String()
  121. }
  122. func (res *response) Clone() Message {
  123. return cloneResponse(res, "", nil)
  124. }
  125. func (res *response) Fields() log.Fields {
  126. return res.fields.WithFields(log.Fields{
  127. "transport": res.Transport(),
  128. "source": res.Source(),
  129. "destination": res.Destination(),
  130. })
  131. }
  132. func (res *response) WithFields(fields log.Fields) Message {
  133. res.mu.Lock()
  134. res.fields = res.fields.WithFields(fields)
  135. res.mu.Unlock()
  136. return res
  137. }
  138. func (res *response) IsProvisional() bool {
  139. return res.StatusCode() < 200
  140. }
  141. func (res *response) IsSuccess() bool {
  142. return res.StatusCode() >= 200 && res.StatusCode() < 300
  143. }
  144. func (res *response) IsRedirection() bool {
  145. return res.StatusCode() >= 300 && res.StatusCode() < 400
  146. }
  147. func (res *response) IsClientError() bool {
  148. return res.StatusCode() >= 400 && res.StatusCode() < 500
  149. }
  150. func (res *response) IsServerError() bool {
  151. return res.StatusCode() >= 500 && res.StatusCode() < 600
  152. }
  153. func (res *response) IsGlobalError() bool {
  154. return res.StatusCode() >= 600
  155. }
  156. func (res *response) IsAck() bool {
  157. if cseq, ok := res.CSeq(); ok {
  158. return cseq.MethodName == ACK
  159. }
  160. return false
  161. }
  162. func (res *response) IsCancel() bool {
  163. if cseq, ok := res.CSeq(); ok {
  164. return cseq.MethodName == CANCEL
  165. }
  166. return false
  167. }
  168. func (res *response) Transport() string {
  169. if tp := res.message.Transport(); tp != "" {
  170. return strings.ToUpper(tp)
  171. }
  172. var tp string
  173. if viaHop, ok := res.ViaHop(); ok && viaHop.Transport != "" {
  174. tp = viaHop.Transport
  175. } else {
  176. tp = DefaultProtocol
  177. }
  178. return tp
  179. }
  180. func (res *response) Destination() string {
  181. if dest := res.message.Destination(); dest != "" {
  182. return dest
  183. }
  184. viaHop, ok := res.ViaHop()
  185. if !ok {
  186. return ""
  187. }
  188. var (
  189. host string
  190. port Port
  191. )
  192. host = viaHop.Host
  193. if viaHop.Port != nil {
  194. port = *viaHop.Port
  195. } else {
  196. port = DefaultPort(res.Transport())
  197. }
  198. if viaHop.Params != nil {
  199. if received, ok := viaHop.Params.Get("received"); ok && received.String() != "" {
  200. host = received.String()
  201. }
  202. if rport, ok := viaHop.Params.Get("rport"); ok && rport != nil && rport.String() != "" {
  203. if p, err := strconv.Atoi(rport.String()); err == nil {
  204. port = Port(uint16(p))
  205. }
  206. }
  207. }
  208. return fmt.Sprintf("%v:%v", host, port)
  209. }
  210. // RFC 3261 - 8.2.6
  211. func NewResponseFromRequest(
  212. resID MessageID,
  213. req Request,
  214. statusCode StatusCode,
  215. reason string,
  216. body string,
  217. ) Response {
  218. res := NewResponse(
  219. resID,
  220. req.SipVersion(),
  221. statusCode,
  222. reason,
  223. []Header{},
  224. "",
  225. req.Fields(),
  226. )
  227. CopyHeaders("Record-Route", req, res)
  228. CopyHeaders("Via", req, res)
  229. CopyHeaders("From", req, res)
  230. CopyHeaders("To", req, res)
  231. CopyHeaders("Call-ID", req, res)
  232. CopyHeaders("CSeq", req, res)
  233. if statusCode == 100 {
  234. CopyHeaders("Timestamp", req, res)
  235. }
  236. res.SetBody(body, true)
  237. res.SetTransport(req.Transport())
  238. res.SetSource(req.Destination())
  239. res.SetDestination(req.Source())
  240. return res
  241. }
  242. func cloneResponse(res Response, id MessageID, fields log.Fields) Response {
  243. newFields := res.Fields()
  244. if fields != nil {
  245. newFields = newFields.WithFields(fields)
  246. }
  247. newRes := NewResponse(
  248. id,
  249. res.SipVersion(),
  250. res.StatusCode(),
  251. res.Reason(),
  252. cloneHeaders(res),
  253. res.Body(),
  254. newFields,
  255. )
  256. newRes.SetPrevious(res.Previous())
  257. newRes.SetTransport(res.Transport())
  258. newRes.SetSource(res.Source())
  259. newRes.SetDestination(res.Destination())
  260. return newRes
  261. }
  262. func CopyResponse(res Response) Response {
  263. return cloneResponse(res, res.MessageID(), nil)
  264. }