Twilio .sendDigits() not working with WebRTC client out-bound call - javascript

I am creating a Twilio WebRTC soft phone which is almost complete. I need the agent to be able to enter any of 10-digit DTMF touch-tones manually in the course of an out-bound call. I am using the .sendDigits() function but it does not produce a touch-tone in a call. All of my other functions work, but I am a bit stuck...
<script type="text/javascript">
Twilio.Device.setup("<?php echo $token; ?>");
Twilio.Device.ready(function (device) {
$("#log").text("Client '<?php echo $clientName ?>' is ready");
});
Twilio.Device.error(function (error) {
$("#log").text("Error: " + error.message);
});
Twilio.Device.connect(function (conn) {
$("#log").text("Successfully established call");
});
Twilio.Device.disconnect(function (conn) {
$("#log").text("Call ended");
});
var connection;
Twilio.Device.incoming(function(conn) {
connection = conn;
$("#number").val(conn.parameters.From);
var ss= "Incomging Call:\n"+conn.parameters.From;
$("#log").text("Incoming connection from " + conn.parameters.From);
//enable the accept button
$(".accept").prop('disabled', false);
});
function accept() {
connection.accept();
}
function call() {
// get the phone number to connect the call to
params = {"PhoneNumber": $("#number").val()};
Twilio.Device.connect(params);
}
function hangup() {
Twilio.Device.disconnectAll();
}
function senddigits() {
if (connection!=null)
connection.sendDigits("1");
}
</script>
I call the function with a simple button...
<button onclick="senddigits();">1</button>
My code is based on this solution, and the Twilio.connection documentation.

I was able to find the problem. I just needed to add connection = conn; in the connect function...
Twilio.Device.connect(function (conn) {
$("#log").text("Successfully established call");
connection = conn;
});

Related

Ratchet PHP: count online users

I'm using Ratchet PHP for a chat.
I need to be able to display how many users are online.
So in my Chat.php file:
public function onOpen(ConnectionInterface $conn)
{
$count = $this->clients->count() + 1;
print_r($count);
$conn->countClient = $count;
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
}
Since this function is called every time a new connection is made.. I chose to make my count there but... correct me if I'm wrong ;)
print_r($count);
Give give me 1... even if I have multiple users connected.
But I also struggle with the JS part:
<script>
function connect() {
var conn = new WebSocket('ws://localhost:8080?token={{ user.user_id }}');
// OPEN THE CONNECTION
conn.onopen = function (e) {
console.log("Connection established!", );
};
}
</script>
How can I pass the value count (attach to the conn object in my PHP function) ?
Thanks for any advice or help

Why not one method to connect and send in websocket?

I am new websocket and refering to the below Spring Websocket tutorial and it is working fine in my system. I am also using stomp.js and sockjs-0.3.4.js.
https://spring.io/guides/gs/messaging-stomp-websocket/
If the html and javascript has two distinct methods like below, it works.
function connect() {
var socket = new SockJS('/app/hello');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/greetings', function(greeting) {
//showGreeting(greeting);
showGreeting(JSON.parse(greeting.body).content);
});
});
}
function sendName() {
var name = document.getElementById('name').value;
stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));
}
If I write a single javascript function as given below, it does not work and get the error as Uncaught Error: INVALID_STATE_ERR.
function startAndSend() {
connect();
sendName();
}
I want to know why it is not working. It may be dumb question, please help me in this regard. I provide below the complete html file. Is it always necessary to write html button for connect and send information to websocket as given in the Spring Websocket example ? Is it not possible to onClick of a button, it will connect and send information to websocket ? It seems to be a peculiar for me, I need your help.
<!DOCTYPE html>
<html>
<head>
<title>Hello WebSocket</title>
<script src="sockjs-0.3.4.js"></script>
<script src="stomp.js"></script>
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
document.getElementById('response').innerHTML = '';
}
function connect() {
var socket = new SockJS('/app/hello');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/greetings', function(greeting) {
//showGreeting(greeting);
showGreeting(JSON.parse(greeting.body).content);
});
});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function sendName() {
var name = document.getElementById('name').value;
stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));
}
function showGreeting(message) {
var response = document.getElementById('response');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
console.log(message);
p.appendChild(document.createTextNode(message));
response.appendChild(p);
}
//Does not work
function startAndSend() {
connect();
sendName();
}
</script>
</head>
<body>
<noscript>
<h2 style="color: #ff0000">Seems your browser doesn't support
Javascript! Websocket relies on Javascript being enabled. Please
enable Javascript and reload this page!</h2>
</noscript>
<div>
Stomp Over Websocket using Spring
<div>
<button id="connect" onclick="connect();">Connect</button>
<button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
<button id="check" onclick="startAndSend();">StartAndSend</button>
</div>
<div id="conversationDiv">
<label>What is your name?</label><input type="text" id="name" />
<button id="sendName" onclick="sendName();">Send</button>
<p id="response"></p>
</div>
</div>
</body>
</html>
That is because stompClient.connect() method is asynchronous and when you call sendName() right after connect() connection is not established yet.
You are supposed to call sendName() in stompClient.connect() callback to be sure that connection is established by the time sendName() invokes.
For example:
function connect() {
var socket = new SockJS('/app/hello');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
sendName();
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/greetings', function(greeting) {
//showGreeting(greeting);
showGreeting(JSON.parse(greeting.body).content);
});
});
}
Without being familiar with Stomp (so just a wild guess): The actual stompClient.connect call takes a callback as the second argument. This indicates that this runs asynchronous. Your attempt at using the connection then fails because it is executed before the connection has actually been established. Try what happens when you put the call into the callback of the connect function.

Ratchet Websockets - Detect disconnected clients

I'm designing a chatroom in ratchet websockets to be as responsive as possible.
It knows when a user leaves the page, and everything like that.
But if a user/client for example loses its connection with the server, the issue is the client cant let the server know it has disconnected, because it has already disconnected and cant send the server a message. So how do I track when a chat client has lost their internet connection and is no longer online?
Two possible solutions I can think of:
server polls the clients once every 15 mins to half hour to check to see who is online. Clients who do not respond get disconnected. Is this possible to do without interrupting everything else going on in php? if so how? and where do I put the code? I saw something about addPeriodicTimer() from LoopInterface but im not sure if that would do the job or where the function would fit into my code.
Also does it call sleep() function because that would not be good. I still want other tasks happening in the background while this function is on a timer (if possible in php)
onClose() method in php
Can this detect when a user has really disconnected in every circumstance? If so, when this event fires off, how can I find out which user was disconnected? it only passes a ConnectionInterface and no message.
Sorry, im still new to the ratchet library and still trying to work out how to achieve this task.
my code for server.php:
<?php
require($_SERVER['DOCUMENT_ROOT'].'/var/www/html/vendor/autoload.php');
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
$server = IoServer::factory(new HttpServer(new WsServer(new Chat)), 8080);
$server->run();
?>
code for app.js
// JavaScript Document
var chat = document.getElementById("chatwindow");
var msg = document.getElementById("messagebox");
var refInterval = 0;
var timeup = false;
var awaytimer;
var socket = new WebSocket("ws://52.39.48.172:8080");
var openn = false;
function addMessage(msg){
"use strict";
chat.innerHTML += "<p>" + msg + "</p>";
}
msg.addEventListener('keypress', function(evt){
"use strict";
if(evt.charCode != 13)
return;
evt.preventDefault();
if(msg.value == "" || !openn)
return;
socket.send(JSON.stringify({
msg: msg.value,
uname: nme,
uid: id,
tag: "[msgsend]"
}));
msg.value = "";
});
socket.onopen = function(evt) {
openn = true;
socket.send(JSON.stringify({
uname: nme,
uid: id,
tag: "[connected]"
}));
};
socket.onmessage = function(evt) {
var data = JSON.parse(evt.data);
if(data.tag == "[connected]")
{
addMessage(data.uname + " has connected...");
}
else if(data.tag == "[bye]")
{
addMessage(data.uname + " has left the room...");
if(data.uname == nme)
socket.close();
}
else if(data.tag == "[msgsend]")
{
addMessage(data.uname + ": " + data.msg);
}
};
window.onfocus = refPage;
function refPage()
{
if(timeup == true)
{
if(refInterval == 1)
{
refInterval = 0;
location.reload();
}
}
else
{
clearTimeout(awaytimer);
}
timeup = false;
}
window.onblur = timelyExit;
function timelyExit()
{
refInterval = 1;
// change this to trigger some kind of inactivity timer
awaytimer = setTimeout(function(){socket.send(JSON.stringify({
uname: nme,
uid: id,
tag: "[bye]"
})); timeup=true; }, 900000);
}
window.onoffline = window.onunload = window.onbeforeunload = confirmExit;
function confirmExit()
{
socket.send(JSON.stringify({
uname: nme,
uid: id,
tag: "[bye]"
}));
socket.close();
}
socket.onclose = function() {
openn = false;
//cant send server this message because already closed.
/*
socket.send(JSON.stringify({
uname: nme,
uid: id,
tag: "[bye]"
}));
*/
socket.close();
};
Code for chat.php
<?php
error_reporting(E_ALL ^ E_NOTICE);
session_id($_GET['sessid']);
if(!session_id)
session_start();
$userid = $_SESSION["userid"];
$username = $_SESSION["username"];
$isadmin = $_SESSION["isadmin"];
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface
{
protected $clients;
public function __construct()
{
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn)
{
$this->clients->attach($conn);
}
public function onClose(ConnectionInterface $conn)
{
$this->clients->detach($conn);
}
public function onMessage(ConnectionInterface $conn, $msg)
{
$msgjson = json_decode($msg);
$tag = $msgjson->tag;
if($tag == "[msgsend]")
{
foreach($this->clients as $client)
{
$client->send($msg);
}
}
else if($tag == "[bye]")
{
foreach($this->clients as $client)
{
$client->send($msg);
}
onClose($conn);
}
else if($tag == "[connected]")
{
//store client information
//send out messages
foreach($this->clients as $client)
{
$client->send($msg);
}
}
}
public function onError(ConnectionInterface $conn, Exception $e)
{
echo "Error: " . $e->getMessage();
$conn -> close();
}
}
?>
Edit: just tested and confirmed onClose() method doesnt fire when internet connection is terminated.
is there a way i can still go about the first solution?
This best solution for detecting disconnected clients would be event based and does not poll the clients at all. This approach would be your second solution, and also models itself nicely around the asynchronous nature of WebSocket message passing.
It is however possible as you state that some naughty clients in certain cases may not notify the socket server of their disconnection and leave it 'hanging', so to speak. In this case, I would suggest to not try to implement the polling trigger within the Socket Server itself and instead initiate the polling via a separate, server-side client that is triggered via cron or other task scheduler and instructs the socket server to initiate a request to poll all connected clients.
For more information on constructing server-side clients, see this question of mine for which I was also able to find some solutions.
In order to determine who sent the disconnect message, I would suggest going away from using just SplObjectStorage inside of the Ratchet\MessageComponentInterface implementation you have and instead wrap a simple array inside of another class, so something like this:
class MyClientList
{
protected $clients = [];
public function addClient(Connection $conn)
{
$this->clients[$conn->resourceId] = [
'connection' => $conn,
];
return $this;
}
public function removeClient(Connection $conn)
{
if(isset($this->clients[$conn->resourceId])) {
unset($this->clients[$conn->resourceId]);
}
return $this;
}
public function registerClient(ConnectionInterface $conn, array $userData)
{
if(isset($this->clients[$conn->resourceId])) {
$this->clients[$conn->resourceId] = array_merge(
$this->clients[$conn->resourceId],
$userData
);
}
return $this;
}
public function getClientData(ConnectionInterface $conn)
{
return isset($this->clients[$conn->resourceId]) ?
$this->clients[$conn->resourceId] :
null
;
}
}
At some point shortly after a user first connects, your client should send a socket message to the server and instruct the server to now register the identity of the client with additional information (in your case you are attempting to identify a uname and uid properties). By indexing against the connection id, you should be able to use this implementation to divine the identity of all messages originating from clients after they have sent in the initial registration message.

Can not connect web socket with javascript

I want to connect to my web socket that put on amazone instance with some ip. I can connect my web socket with some ip and port with google rest client app and its working very well.
Screen Shot :
But if i want to connect this with java script it can not connect. This is working fine before 2-3 month. i have not change and thing but its not working now.
If i want to connect with firefox it produce an error.
Here is my code :-
function init() {
var host = "ws://XX.XX.XXX.XXX:XXXX"; // SET THIS TO YOUR SERVER
try {
var socket = new WebSocket(host);
// alert('WebSocket - status ' + socket.readyState);
log('WebSocket - status ' + socket.readyState);
socket.onopen = function (msg) {
alert('open');
alert("Welcome - status " + this.readyState);
log("Welcome - status " + this.readyState);
if (this.readyState != 1)
{
reconnect();
}
};
socket.onmessage = function (msg) {
// alert("Received: " + msg.data);
log("Received: " + msg.data);
};
socket.onclose = function (msg) {
// alert("Disconnected - status " + this.readyState);
log("Disconnected - status " + this.readyState);
};
} catch (ex) {
alert(ex);
log(ex);
}
$("msg").focus();
}
This is alerting status 0 and error show in console :-
Firefox can't establish a connection to the server at ws://XX.XX.XXX.XXX:XXXX.
var socket = new WebSocket(host);
I'd try your code and for me is working just fine, I'd test it with this webpage: https://www.websocket.org/echo.html , maybe could be helpful for testing purposes. But also i found this question: websocket-rails, websocket handshake error , maybe also help.
However i'd just change the host in your code to this:"ws://echo.websocket.org", and everything works without problems.
Hope you find a solution and that this info was of any help. Here's your code that i used for the test:
function init() {
var host = "ws://echo.websocket.org";
try {
var socket = new WebSocket(host);
alert('WebSocket - status ' + socket.readyState);
socket.onopen = function (msg) {
alert('open');
alert("Welcome - status " + this.readyState);
if (this.readyState != 1)
{
reconnect();
}
};
socket.onmessage = function (msg) {
alert("Received: " + msg.data);
};
socket.onclose = function (msg) {
alert("Disconnected - status " + this.readyState);
};
} catch (ex) {
alert(ex);
}
$("msg").focus();
}
*Sorry for my bad english.

I need the route data in a node client between client to correct connected user

I am trying to build a gnuchess web api and bind it to a graphical web interface. Trought a websocket the users will connect and when connecting the server-websocket will launch a "gnuchess" as subprocess. Then I would like to communicate with the gnuchess's stdin/stdout and send the stream to the user. But as the code is today it only starts new gnuchess's but I could only write to one of them (with all connected clients I could do that)
I have this code node-code:
var http = require("http");
var ws = require("./");
var fs = require("fs");
var process = require('child_process');
theglobal = "";
var ls = "";
// Web server
http.createServer(function (req, res) {
fs.createReadStream("index.html").pipe(res)
}).listen(8080);
// Socket stuff
var server = ws.createServer(function (connection) {
connection.on("text", function (str) {
var tmp_cmd = str.split(" ")[0];
var tmp_string = str.substr(str.indexOf(" ") + 1);
console.log(tmp_cmd)
console.log(tmp_string)
if (tmp_cmd == "move") {
ls.stdin.write(tmp_string + "\n");
connection.sendText(str);
}
if (str == "start") {
connection.sendText(str);
ls = process.spawn('/usr/games/gnuchess');
ls.stdout.on('data', function (chunk) {
broadcast(chunk)
});
}
})
});
server.listen(8081);
// Functions
// This broadcasts to all clients connected
function broadcast(str) {
server.connections.forEach(function (connection) {
connection.sendText(str)
})
}
HTML:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Chat example</title>
<script>
var connection
window.addEventListener("load", function () {
var nickname = prompt("Choose a nickname")
if (nickname) {
connection = new WebSocket("ws://"+window.location.hostname+":8081")
connection.onopen = function () {
console.log("Connection opened")
connection.send(nickname)
document.getElementById("form").onsubmit = function (event) {
var msg = document.getElementById("msg")
if (msg.value)
connection.send(msg.value)
msg.value = ""
event.preventDefault()
}
}
connection.onclose = function () {
console.log("Connection closed")
}
connection.onerror = function () {
console.error("Connection error")
}
connection.onmessage = function (event) {
var div = document.createElement("div")
div.textContent = event.data
document.body.appendChild(div)
}
}
})
</script>
</head>
<body>
<form id="form">
Message: <input size="50" id="msg"> <input type="submit" value="Submit">
</form>
</body>
</html>
But what happens is that it starts a new gnuchess for every user who connects (it should be like that) but the data routes to the first openeded gnuchess.
Could solve the problem by using a IRC bot and IRC server and use different channel for each game (#gnuchess_user1, #gnuchess_user2, etc..) But I think it's easier actually to solve it by making a method or own object for each user and route it in the websocket.
You should look at socket.io, it has built in support for rooms:
io.on('connection', function(socket){
socket.join('some room');
});
Which means you can broadcast to all sockets connected to that room. You don't have to spawn separate processes for these (it will be devastating for your performance..)
io.to('some room').emit('some event');
http://socket.io

Categories