originate.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package ami
  2. import (
  3. "errors"
  4. "fmt"
  5. "log"
  6. "strconv"
  7. "sync"
  8. "time"
  9. "git.ali33.ru/fcg-xvii/go-tools/json"
  10. )
  11. func (s *Client) Originate(req *OriginateRequest) (*Originate, error) {
  12. if s.state != StateAuth {
  13. return nil, errors.New("AMI IS NOT AUTH")
  14. }
  15. req.uuid = time.Now().UnixNano()
  16. timeout := RequestTimeoutDefault
  17. if req.Timeout > timeout {
  18. timeout = req.Timeout + time.Millisecond*500
  19. }
  20. resp, check := s.Request(req.Request(), timeout)
  21. if !check {
  22. return nil, errors.New("Originate request timeout")
  23. }
  24. if resp.IsError() {
  25. return nil, fmt.Errorf("Originate error: %v", resp.ErrorMessage())
  26. }
  27. res := initOriginate(req, s)
  28. return res, nil
  29. }
  30. //////////////////////////////////////////////////////////////////
  31. type OriginateRequest struct {
  32. Channel string
  33. Context string
  34. Exten string
  35. Priority string
  36. Timeout time.Duration
  37. CallerID string
  38. Variable json.Map
  39. Account string
  40. Application string
  41. Data string
  42. uuid int64
  43. }
  44. func (s *OriginateRequest) Request() (res Request) {
  45. res = InitRequest("Originate")
  46. res.SetParam("Channel", s.Channel)
  47. res.SetParam("Context", s.Context)
  48. res.SetParam("Exten", s.Exten)
  49. if s.Timeout > 0 {
  50. res.SetParam("Timeout", fmt.Sprintf("%v", int(s.Timeout/time.Millisecond)))
  51. }
  52. res.SetParam("Priority", s.Priority)
  53. res.SetParam("CallerID", s.CallerID)
  54. res.SetParam("Account", s.Account)
  55. res.SetParam("Application", s.Application)
  56. res.SetParam("Data", s.Data)
  57. res.SetParam("Async", "true")
  58. res.SetParam("ChannelID", fmt.Sprint(s.uuid))
  59. res.SetVariables(s.Variable)
  60. return res
  61. }
  62. /////////////////////////////////////////////////////////////////
  63. func initOriginate(req *OriginateRequest, client *Client) *Originate {
  64. res := &Originate{
  65. OriginateRequest: req,
  66. eventChan: client.registerEventListener(req.uuid),
  67. locker: new(sync.RWMutex),
  68. client: client,
  69. }
  70. go res.listenEvents()
  71. return res
  72. }
  73. type Originate struct {
  74. *OriginateRequest
  75. eventChan <-chan Event
  76. userEventChan chan Event
  77. locker *sync.RWMutex
  78. finished bool
  79. err error
  80. client *Client
  81. responseReason byte
  82. hangupCause byte
  83. }
  84. func (s *Originate) listenEvents() {
  85. for {
  86. e, ok := <-s.eventChan
  87. if !ok {
  88. s.finished = true
  89. close(s.userEventChan)
  90. return
  91. }
  92. s.locker.RLock()
  93. if s.userEventChan != nil {
  94. s.userEventChan <- e
  95. }
  96. s.locker.RUnlock()
  97. switch e.Name() {
  98. case "OriginateResponse":
  99. if reason, check := e.ActionData["Reason"]; check {
  100. reasonVal, _ := strconv.ParseInt(reason, 10, 32)
  101. s.responseReason = byte(reasonVal)
  102. }
  103. log.Println("RREASON", s.responseReason)
  104. //if s.responseReason != 4 {
  105. //s.client.removeEventListener(s.uuid)
  106. //}
  107. case "Hangup":
  108. if cause, check := e.ActionData["Cause"]; check {
  109. causeVal, _ := strconv.ParseInt(cause, 10, 32)
  110. s.hangupCause = byte(causeVal)
  111. }
  112. }
  113. }
  114. }
  115. func (s *Originate) IsFinished() bool {
  116. return s.finished
  117. }
  118. func (s *Originate) Events() (res <-chan Event) {
  119. s.locker.Lock()
  120. if s.userEventChan == nil {
  121. s.userEventChan = make(chan Event)
  122. }
  123. res = s.userEventChan
  124. s.locker.Unlock()
  125. return
  126. }