originate.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. res := initOriginate(req, s)
  21. resp, check := s.Request(req.Request(), timeout)
  22. if !check {
  23. s.removeEventListener(req.uuid)
  24. return nil, errors.New("Originate request timeout")
  25. }
  26. if resp.IsError() {
  27. s.removeEventListener(req.uuid)
  28. return nil, fmt.Errorf("Originate error: %v", resp.ErrorMessage())
  29. }
  30. return res, nil
  31. }
  32. //////////////////////////////////////////////////////////////////
  33. type OriginateRequest struct {
  34. Channel string
  35. Context string
  36. Exten string
  37. Priority string
  38. Timeout time.Duration
  39. CallerID string
  40. Variable json.Map
  41. Account string
  42. Application string
  43. Data string
  44. uuid int64
  45. }
  46. func (s *OriginateRequest) Request() (res Request) {
  47. res = InitRequest("Originate")
  48. res.SetParam("Channel", s.Channel)
  49. res.SetParam("Context", s.Context)
  50. res.SetParam("Exten", s.Exten)
  51. if s.Timeout > 0 {
  52. res.SetParam("Timeout", fmt.Sprintf("%v", int(s.Timeout/time.Millisecond)))
  53. }
  54. res.SetParam("Priority", s.Priority)
  55. res.SetParam("CallerID", s.CallerID)
  56. res.SetParam("Account", s.Account)
  57. res.SetParam("Application", s.Application)
  58. res.SetParam("Data", s.Data)
  59. res.SetParam("Async", "true")
  60. res.SetParam("ChannelID", fmt.Sprint(s.uuid))
  61. res.SetVariables(s.Variable)
  62. return res
  63. }
  64. /////////////////////////////////////////////////////////////////
  65. func initOriginate(req *OriginateRequest, client *Client) *Originate {
  66. res := &Originate{
  67. OriginateRequest: req,
  68. eventChan: client.registerEventListener(req.uuid),
  69. locker: new(sync.RWMutex),
  70. client: client,
  71. userEventChan: make(chan Event, 1),
  72. }
  73. waiter := make(chan struct{})
  74. go res.listenEvents(waiter)
  75. <-waiter
  76. return res
  77. }
  78. type Originate struct {
  79. *OriginateRequest
  80. eventChan <-chan Event
  81. userEventChan chan Event
  82. locker *sync.RWMutex
  83. finished bool
  84. client *Client
  85. responseReason byte
  86. hangupCause byte
  87. }
  88. func (s *Originate) listenEvents(waiter chan<- struct{}) {
  89. log.Println("AMI-LISTEN-EVENTS")
  90. close(waiter)
  91. defer log.Println("AMI-LISTENER-ORIGINATE-CLOSED")
  92. for {
  93. e, ok := <-s.eventChan
  94. log.Println("E --------------------------->", e, ok)
  95. if !ok {
  96. s.finished = true
  97. close(s.userEventChan)
  98. return
  99. }
  100. s.locker.RLock()
  101. if s.userEventChan != nil {
  102. s.userEventChan <- e
  103. }
  104. s.locker.RUnlock()
  105. switch e.Name() {
  106. case "OriginateResponse":
  107. if reason, check := e.ActionData["Reason"]; check {
  108. reasonVal, _ := strconv.ParseInt(reason, 10, 32)
  109. s.responseReason = byte(reasonVal)
  110. }
  111. log.Println("RREASON", s.responseReason)
  112. if s.responseReason == 0 {
  113. s.finished = true
  114. close(s.userEventChan)
  115. return
  116. }
  117. //if s.responseReason != 4 {
  118. //s.client.removeEventListener(s.uuid)
  119. //}
  120. case "Hangup":
  121. if cause, check := e.ActionData["Cause"]; check {
  122. causeVal, _ := strconv.ParseInt(cause, 10, 32)
  123. s.hangupCause = byte(causeVal)
  124. }
  125. }
  126. }
  127. }
  128. func (s *Originate) IsFinished() bool {
  129. return s.finished
  130. }
  131. func (s *Originate) Events() (res <-chan Event) {
  132. return s.userEventChan
  133. }