123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- package ami
- import (
- "errors"
- "fmt"
- "log"
- "strconv"
- "sync"
- "time"
- "git.ali33.ru/fcg-xvii/go-tools/json"
- )
- func (s *Client) Originate(req *OriginateRequest) (*Originate, error) {
- if s.state != StateAuth {
- return nil, errors.New("AMI IS NOT AUTH")
- }
- req.uuid = time.Now().UnixNano()
- timeout := RequestTimeoutDefault
- if req.Timeout > timeout {
- timeout = req.Timeout + time.Millisecond*500
- }
- res := initOriginate(req, s)
- resp, check := s.Request(req.Request(), timeout)
- if !check {
- s.removeEventListener(req.uuid)
- return nil, errors.New("Originate request timeout")
- }
- if resp.IsError() {
- s.removeEventListener(req.uuid)
- return nil, fmt.Errorf("Originate error: %v", resp.ErrorMessage())
- }
- return res, nil
- }
- //////////////////////////////////////////////////////////////////
- type OriginateRequest struct {
- Channel string
- Context string
- Exten string
- Priority string
- Timeout time.Duration
- CallerID string
- Variable json.Map
- Account string
- Application string
- Data string
- uuid int64
- }
- func (s *OriginateRequest) Request() (res Request) {
- res = InitRequest("Originate")
- res.SetParam("Channel", s.Channel)
- res.SetParam("Context", s.Context)
- res.SetParam("Exten", s.Exten)
- if s.Timeout > 0 {
- res.SetParam("Timeout", fmt.Sprintf("%v", int(s.Timeout/time.Millisecond)))
- }
- res.SetParam("Priority", s.Priority)
- res.SetParam("CallerID", s.CallerID)
- res.SetParam("Account", s.Account)
- res.SetParam("Application", s.Application)
- res.SetParam("Data", s.Data)
- res.SetParam("Async", "true")
- res.SetParam("ChannelID", fmt.Sprint(s.uuid))
- res.SetVariables(s.Variable)
- return res
- }
- /////////////////////////////////////////////////////////////////
- func initOriginate(req *OriginateRequest, client *Client) *Originate {
- res := &Originate{
- OriginateRequest: req,
- eventChan: client.registerEventListener(req.uuid),
- locker: new(sync.RWMutex),
- client: client,
- userEventChan: make(chan Event, 1),
- }
- waiter := make(chan struct{})
- go res.listenEvents(waiter)
- <-waiter
- return res
- }
- type Originate struct {
- *OriginateRequest
- eventChan <-chan Event
- userEventChan chan Event
- locker *sync.RWMutex
- finished bool
- client *Client
- responseReason byte
- hangupCause byte
- }
- func (s *Originate) listenEvents(waiter chan<- struct{}) {
- log.Println("AMI-LISTEN-EVENTS")
- close(waiter)
- defer log.Println("AMI-LISTENER-ORIGINATE-CLOSED")
- for {
- e, ok := <-s.eventChan
- log.Println("E --------------------------->", e, ok)
- if !ok {
- s.finished = true
- close(s.userEventChan)
- return
- }
- s.locker.RLock()
- if s.userEventChan != nil {
- s.userEventChan <- e
- }
- s.locker.RUnlock()
- switch e.Name() {
- case "OriginateResponse":
- if reason, check := e.ActionData["Reason"]; check {
- reasonVal, _ := strconv.ParseInt(reason, 10, 32)
- s.responseReason = byte(reasonVal)
- }
- log.Println("RREASON", s.responseReason)
- if s.responseReason == 0 {
- s.finished = true
- close(s.userEventChan)
- return
- }
- //if s.responseReason != 4 {
- //s.client.removeEventListener(s.uuid)
- //}
- case "Hangup":
- if cause, check := e.ActionData["Cause"]; check {
- causeVal, _ := strconv.ParseInt(cause, 10, 32)
- s.hangupCause = byte(causeVal)
- }
- }
- }
- }
- func (s *Originate) IsFinished() bool {
- return s.finished
- }
- func (s *Originate) Events() (res <-chan Event) {
- return s.userEventChan
- }
|