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 }