Code Monkey home page Code Monkey logo

eslgo's People

Contributors

dependabot[bot] avatar shambles07 avatar winsock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eslgo's Issues

Long running ESL connections unable to send commands

Problem

Bug Report

Connections made with esl.Dial cannot send commands using c.SendCommand after five seconds of life.

This is because we set a global deadline on the connection.

I had a much longer issue written, with some additional data, but my machine inexplicably rebooted...

Content
  1. Subjective Considerations
  2. Quick Workaround
  3. Reproduce

Subjective Considerations #

I am grateful for this package! These are small things that can (maybe) be improved iteratively, and they are only my opinions.

  1. Official context docs - Do not store Contexts inside a struct type; instead, pass a Context explicitly to each function that needs it.
    • We should consider using a new context for each command, and allowing the "parent" caller to choose if a deadline is hit or a context needs canceled.
  2. Exporting some attributes and methods of Conn would be helpful for developers - specifically the newConnection constructor.
    • This package seems really perfect for a structure that enables 3rd party plugins/hooks. I wonder how we could enable that...
  3. Quietly stopping the receiveLoop on a context.Err() with only an internal logger.Warn can make it difficult to track down what's happening when things inevitably go wrong.
    • Should we consider panic? I'm not normally a fan but the entire system is down at this point, right?
    • At a minimum we should log a full error.
    • Is there a possibility we could reinitialize a failed connection? Should we?
    • Do these considerations apply when we remove the context from the Conn struct in favor of passing context around?

Quick Workaround #

Disable the deadline checker/setter here (remove or comment out). Replace with another timeout enforcement method, or just allow the caller to manage their own timeouts.

Reproduce #

/*
 * This code snippet shows a long-running ESL connection that
 * fails to deliver commands after five seconds of life.
 *
 * Note that we are limited by an artificial Go deadline, not
 * any FreeSWITCH limitation.
 */
package main

import (
	"context"
	"log"
	"time"

	"github.com/percipia/eslgo"
	"github.com/percipia/eslgo/command"
)


func main() {
	// Connect to FreeSWITCH
	conn, err := eslgo.Dial("127.0.0.1:8021", "ClueCon", func() {
		log.Println("Inbound Connection Disconnected")
	})
	if err != nil {
		log.Println("Error connecting", err)
		return
	}
	defer conn.ExitAndClose()

	// Create a basic context
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
	defer cancel()

	go func() {
		i := 0
		for {
			log.Printf("sending ping %v\n", i)
			if _, err := conn.SendCommand(ctx, command.API{
				Command:    "echo",
				Arguments:  log.Sprintf("ping %v", i),
				Background: false,
			}); err != nil {
				log.Println(err)
			}
			i++
			time.Sleep(time.Second * 1)
		}
	}()

	time.Sleep(30)
}

Response with content type "text/rude-rejection" freezes opts.Dial function

When FreeSwitch returns a "text/rude-rejection" Response the opts.Dial function keeps waiting a message from channel forever in:
<-connection.responseChannels[TypeAuthRequest]

I created a temporary fix adding a new response and an anonymous go routine before the line of the mentioned above

go func () {
  <-connection.responseChannels[TypeRude]
  connection.ExitAndClose()
}()

// First auth
<-connection.responseChannels[TypeAuthRequest]

Tell me if you want me to make a pull request or to find another cleaner solution (I'm sure there's a better way)

Regards.

Multiple Freeswitch Support

Hey percipia Team,

It will be really helpful if you guys will make built in support for N number of freeswitches.

Allow setting a custom logger

Context

There are some debug log messages printed out by the library. As brought up in a side discussion of #5 we should allow setting a customer logger to allow users of the library to decide how to save/print these messages rather than printing to stdout using GoLang's default logging interface.

Ideas

  • Add in a new options struct for containing these kind of optional settings
  • Keep the original outbound and inbound connection functions signatures the same but add new ones that will take the struct and make the old ones call the new one internally.
  • All internal library logging can be disabled by passing nil for a logger
  • Until Golang 2 add a new interface Logger with the following definition since it seems to be what most third party libraries use
type Logger interface {
	Debug(format string, args ...interface{})
	Info(format string, args ...interface{})
	Warn(format string, args ...interface{})
	Error(format string, args ...interface{})
}

It doesn't exit on wrong password

Hello!

Thanks for the library, @winsock ! It's so useful and helpful!

I've encountered this behavior: when I set an incorrect ESL password the library replies like the following:

$ ~/go/bin/go run ~/main.go

2021/02/16 13:43:36 Failed to auth &{%!e(string=failed to auth Content-Type: []string{"command/reply"}
Reply-Text: []string{"-ERR invalid"}
)}
2021/02/16 13:43:41 No one to handle response Content-Type: []string{"text/disconnect-notice"}
Content-Length: []string{"67"}
Disconnected, goodbye.
See you at ClueCon! http://www.cluecon.com/

and it never exits.

In my opinion, the program must exit after sending "exit" command to FreeSWITCH instance.

Outbound connection write timeout after capturing DTMF digits

Hi, thanks for sharing this neat library with the community.

I've used it to create a small PoC that generates IVR menu dynamically instead of using fixed XML files, but when I got to the part where I needed to capture callers menu response I ran into an issue with the underlying TCP connection:

time="2022-07-14T07:14:32Z" level=info msg="[1] Answer the call"
time="2022-07-14T07:14:32Z" level=info msg="[2] Start DTMF listener"
time="2022-07-14T07:14:32Z" level=info msg="[3] Play IVR menu"
time="2022-07-14T07:14:32Z" level=info msg="[5] Capture DTMF events"
time="2022-07-14T07:14:48Z" level=info msg="Received digit: 2"
time="2022-07-14T07:14:48Z" level=error msg="Error transferring the call!"
time="2022-07-14T07:14:48Z" level=error msg="write tcp 10.22.1.201:8084->10.22.1.200:52490: i/o timeout"

Here is how DTMF digit is captured:

func (ch *CallHandler) captureDTMF(ctx context.Context, conn *eslgo.Conn) (byte, error) {
	digit, err := conn.WaitForDTMF(ctx, ch.uuid)
	if err != nil {
		ch.logger.Error("Error waiting for DTMF signal")
		return 0, err
	}
	ch.logger.Info("Received digit: " + string(digit))

	return digit, nil
}

Timeout happens on the next ESL command I try to executed after receiving the digit. Not sure if it matters, but the next command is this:

func (ch *CallHandler) transferCall(ctx context.Context, conn *eslgo.Conn, digit byte) error {
	_, err := conn.SendCommand(ctx, &call.Execute{UUID: ch.uuid, AppName: "deflect", AppArgs: "sip:eureka@" + ch.outboundDestIp, Sync: true, SyncPri: true})
	if err != nil {
		ch.logger.Error("Error transferring the call!")
		ch.logger.Error(err)
		return err
	}
	return nil
}

The deflect commmand works as expected if I comment out the "capture DTMF digits" logic, which makes me think that capturing the DTMF digit somehow affects the connection.

Any ideas what might be going wrong here or if I'm missing something important?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.