Stuck messages in ZeroMQ - network-programming

I'm having a strange problem with ZeroMQ, in which some messages get stuck, and just get unstuck when new messages arrive. It's like the new messages push the stuck messages on the door (terrible comparison, i know).
My code is quite simple:
rep.php
$context = new ZMQContext;
$receiver = new ZMQSocket($context, ZMQ::SOCKET_PULL);
$receiver->connect("tcp://localhost:8022");
$receiver2 = new ZMQSocket($context, ZMQ::SOCKET_PULL);
$receiver2->connect("tcp://localhost:8024");
for (;;) {
echo $receiver->recv() . PHP_EOL;
echo $receiver2->recv() . PHP_EOL;
}
cnt.php and cnt2.php (same code, different ports)
$context = new ZMQContext;
$work = new ZMQSocket($context, ZMQ::SOCKET_PUSH);
$work->bind('tcp://*:8022');
$work->send('Hello World');
cnt.php sends to 8022 and cnt2.php to 8024. They get executed from time to time and send messages to rep.php. However, some messages get stuck. If i sent 4 messages from cnt.php, nothing is received, but when i send 1 from cnt2.php, i get 5 messages at once. Any ideas?

I am no PHP expert here but guessing the syntax and functionality. Please correct me if I am wrong
echo $receiver->recv() . ' - ' . $receiver2->recv();
recv() should be a blocking call.
$receiver->recv() blocks until some message is received.
But echo does not echo the message immediately
You are again blocked on $receiver2->recv()
Only when you send message from the other file does echo work because it is waiting on $receiver2->recv()
Since you want to process the socket recv() independently, you should use polling or event based asynchronous I/O.
[Attempted solution]
$poll = new ZMQPoll();
$poll->add($receiver, ZMQ::POLL_IN);
$poll->add($receiver2, ZMQ::POLL_IN);
$readable = $writeable = array();
while(true) {
$events = $poll->poll($readable, $writeable);
foreach($readable as $socket) {
$message = $socket->recv();
echo $message, PHP_EOL;
}
}
Adapted from : http://zguide.zeromq.org/php:rrbroker

Related

Twilio Not doing anything when receiving SMS

I'm creating a sample application that will post alerts to the website in the event of a hurricane or service outage. I'm not using Laravel.
I set the URL of the page in my account settings. The first time I sent a message I received a HTTP error that it had timed out without being given a reponse. I edited the XML and tried again.
I'm not getting anything in the database and I'm not getting the response. I also wrote a sample page that posts a value to see if it would work and it did. It posted it into the database and showed correctly formatted XML.
<?php
$response = 'This number cannot handle automated replies...';
$twiml1 = '<response><sms>';
$twiml2 = '</sms></response>';
require_once '../settings/db.php';
if (isset($_POST['body'])) {
$body = strip_tags($_POST['body']);
$sql = "INSERT INTO alerts (message) VALUES ('$body')";
$result = $db->query($sql);
if ($result) {
$response = 'Thanks. Your message was posted on the website.';
} else {
$response = 'There was a query error.';
}
}
header('Content-type: application/xml');
echo $twiml1;
echo $response;
echo $twiml2;
Twilio developer evangelist here.
Parameters that are sent via webhooks from Twilio are case sensitive and start with a capital letter. The text for an incoming message is sent as the Body parameter so checking for $_POST['body'] won't work.
I'd update your conditional to:
if (isset($_POST['Body'])) {
$body = strip_tags($_POST['Body']);
// The rest
}
Also, just to note, the <Sms> element has been deprecated. I'd use the <Message> element instead. The tags are case sensitive too, so I'd update the TwiML section to this:
$twiml1 = '<Response><Message>';
$twiml2 = '</Message></Response>';
Let me know if that helps at all.

Twilio blacklist rule fatal error

I am using twilio to send bulk sms messages. Let's say some customer decided that they don't want to receive messages anymore so they reply with "stop" and that will add them to the black list. I am hard coding the phone numbers because I am still testing on my own cell phones. I noticed that when I do not remove the numbers on the black list from my code, I am getting an error message and my script stops at that point.
In the future, I will probably be using numbers stored in a database or a file. In that case, how do I overcome this problem if it happened. Basically what I want to do is: If a number is in the black list, move on to the next number and avoid that error using an exception or something.
The error message and code is below.
Thanks,
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Send SMS</title>
<?php
/* Send an SMS using Twilio. You can run this file 3 different ways:
*
* 1. Save it as sendnotifications.php and at the command line, run
* php sendnotifications.php
*
* 2. Upload it to a web host and load mywebhost.com/sendnotifications.php
* in a web browser.
*
* 3. Download a local server like WAMP, MAMP or XAMPP. Point the web root
* directory to the folder containing this file, and load
* localhost:8888/sendnotifications.php in a web browser.
*/
// Step 1: Get the Twilio-PHP library from twilio.com/docs/libraries/php,
// following the instructions to install it with Composer.
//require_once "vendor/autoload.php";
require __DIR__ . '/twilio-php-master/Twilio/autoload.php';
use Twilio\Rest\Client;
// Step 2: set our AccountSid and AuthToken from https://twilio.com/console
$AccountSid = "something";
$AuthToken = "something";
// Step 3: instantiate a new Twilio Rest Client
$client = new Client($AccountSid, $AuthToken);
// Step 4: make an array of people we know, to send them a message.
// Feel free to change/add your own phone number and name here.
$people = array(
"+17570123456" => "Chris",
"+17571234568" => "Hussam"
);
// Step 5: Loop over all our friends. $number is a phone number above, and
// $name is the name next to it
foreach ($people as $number => $name) {
$sms = $client->account->messages->create(
// the number we are sending to - Any phone number
$number,
array(
// Step 6: Change the 'From' number below to be a valid Twilio number
// that you've purchased
'from' => "+184444444444",
// the sms body
'body' => "Hey $name, this is Hussam. Testing Twilio SMS API!"
)
);
// Display a confirmation message on the screen
echo "Sent message to $name.\n";
}
?>
( ! ) Fatal error: Uncaught exception 'Twilio\Exceptions\RestException' with message '[HTTP 400] Unable to create record: The message From/To pair violates a blacklist rule.' in C:\wamp64\www\Twilio\twilio-php-master\Twilio\Version.php on line 86 ( ! ) Twilio\Exceptions\RestException: [HTTP 400] Unable to create record: The message From/To pair violates a blacklist rule. in C:\wamp64\www\Twilio\twilio-php-master\Twilio\Version.php on line 86 Call Stack
Time Memory Function Location 1 0.0000 239280 {main}( ) ...\send.php:0 2 0.0156 799016 Twilio\Rest\Api\V2010\Account\MessageList->create( ) ...\send.php:56 3 0.0156 814688 Twilio\Version->create( ) ...\MessageList.php:63
Twilio developer evangelist here.
You need to catch the exception that is thrown from the request to send a message to the blacklisted number. You can do so with try and catch like this:
foreach ($people as $number => $name) {
try {
$sms = $client->account->messages->create(
$number,
array(
'from' => "+18443949780",
'body' => "Hey $name, this is Hussam. Testing Twilio SMS API!"
)
);
echo "Sent message to $name.\n";
} catch (\Twilio\Exceptions\RestException $e) {
echo "Couldn't send message to $number\n";
}
}
When you hook this up to a database, you'll want to use the catch to update a field to mark the number as blocked so that you don't try to send to it again.
Let me know if that helps at all.
This worked for me with Laravel 5. Notice the use of \Twilio\Exceptions\RestException.
try {
$sms = $client->account->messages->create(
$number,
array(
'from' => "+16136543180",
'body' => "Hey $name, Are you still mad at us about your cat!"
)
);
echo "Sent message to $name.\n";
} catch (\Twilio\Exceptions\RestException $e) {
if ($e->getCode() == 20404) {
//this will be false condition
dd('False Result 404');
} else {
//some other exception code
dd($e->getMessage());
}
}

Issues using ratchetphp/Pawl websocket client

My question is specific to using slack rtm on ratchetphp/Pawl. I have below code which connects fine but dies eventually.
<?php
require_once "response.php";
//first make authenticated call to rtm.start
use \Curl\Curl;
$curl = new Curl();
$rtmStartUrl = "https://slack.com/api/rtm.start?token=xx-xx-xx-xx-xx&pretty=1";
$curl->get($rtmStartUrl);
$wsUrl = $curl->response->url;
$loop = React\EventLoop\Factory::create();
$connector = new Ratchet\Client\Connector($loop);
$connector($wsUrl)
->then(function(Ratchet\Client\WebSocket $conn) {
$conn->on('message', function(\Ratchet\RFC6455\Messaging\MessageInterface $msg) use ($conn) {
echo "Received: {$msg}\n";
// $conn->close();
});
$conn->on('close', function($code = null, $reason = null) {
echo "Connection closed ({$code} - {$reason})\n";
});
$conn->send('Hello World!');
}, function(\Exception $e) use ($loop) {
echo "Could not connect: {$e->getMessage()}\n";
$loop->stop();
});
$loop->run();
Upon running, the output is:
root#ip-172-31-45-75:/var/www/html/slack# php pawl.php
Received: {"type":"hello"}
Received: {"type":"reconnect_url","url":"wss://mpmulti-qpau.slack-msgs.com/websocket/jDkgDysXfZspRj10zqdcrshHK6PhPLItYx2HEkdXy47RPCAJwKgI_NLq0bhS4uMjIT7iRtOoCDUJffcxcr7YdiqMbITUZYqnTmT39Et5a8JeuPLFfCUUzan4MCz34p0jcfAKaQW9G9HpIWrYH4CTqyICZuhgWHnzo8K7dO2zXFc="}
Received: {}
Connection closed (1006 - Underlying connection closed)
root#ip-172-31-45-75:/var/www/html/slack#
The websocket is part of slack rtm api (https://api.slack.com/rtm). It seems like when reading on empty websocket, the connection is closed. I think it might be like we listen to slack events (https://api.slack.com/events) sent over websocket for working to avoid disconnect.
Currently, this does not work because of disconnection error.
Hello World! is not a valid message for this API, so Slack is closing the connection when it receives that message. Try sending something valid (or nothing at all).

Where during my expect script is is it timing out?

Within my expect script expect_after to catch the timeout coming from BadPromptPassword, however how do I return that this was the place that my expect script timed out? I've played with expect_out and it doesnt give me what I need... Any help appreciated. Thanks
spawn telnet 172.27.228.239
expect {
timeout { puts "Timed out waiting for response from telnet ('172.27.228.230',)."; exit 1}
"Password:" { send "lab\r"; }
"\[>#\]"
};
send "en\r"
expect_after {
timeout {
puts "a default timeout clause for all subsequent expect commands ";
exit 1
}
}
expect "#>"
send "admin"
expect "BadPromptPassword:"
send "lab\r"
close
wait
Here's a quick hack
expect_after {
timeout {
puts "timed-out expecting $pattern";
exit 1
}
}
set pattern "#>"
expect $pattern
send "admin"
set pattern "BadPromptPassword:"
expect $pattern
send "lab\r"

error "not a valid Socket resource" implementing the phpwebsocket library

I'm trying to work with the phpwebsocket library at http://code.google.com/p/phpwebsocket/
I'm using the version r8 of the server.php file. For testing I just tried with the client.html file, also provided by the website.
When the server is started I get this:
Server Started : 2011-08-29 22:11:23
Master socket : Resource id #4
Listening on : www.midomain.com port 12345
But when I load the client.html file in the browser, the server shows the following errors:
Notice: Undefined variable: key1 in /home/mink500/public_html/test/server.php on line 143
Notice: Undefined variable: key2 in /home/mink500/public_html/test/server.php on line 143
Warning: socket_select(): 5 is not a valid Socket resource in /home/mink500/public_html/test/server.php on line 15
There are two variables that are not defined, and the function socket_select() returns the error "5 is not a valid Socket resource"
In the browser I get the "Disconnected" message as soon as the file is loaded.
I tried to make the server work locally using XAMPP (Apache and PHP) but I got the same errors. I also tried to change ports and follow the instructions in this issue:
http://code.google.com/p/phpwebsocket/issues/detail?id=33
But I still get the error "5 is not a valid Socket resource"
I remember that refreshing the page several times I got it running a few months ago, but now it's impossible. Besides, I need it to work all the time, not just after I refresh the page like 20 times.
I also tried with the websocket.class.php file, but this time I get an error on the client side. The browser now returns "Error during WebSocket handshake: 'Sec-WebSocket-Accept' header is missing".
So, I can't make it work with old or new files, with remote or local server, with magic or a ouija board!
Any idea?
Thanks
Starting with the newest phpwebsocket client.html and server.php files I replaced both the getheaders() and dohandshake() functions with the code below works for me in newest Chrome. However it currently does not write to the browser nor stay alive after one uer comment in the chat box.
function dohandshake($user, $buffer) {
$key = null;
console("\nRequesting handshake...");
console($buffer);
console("Handshaking...");
preg_match("#Sec-WebSocket-Key: (.*?)\r\n#", $buffer, $match) && $key = $match[1];
$key .= "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
$key = sha1($key);
$key = pack('H*', $key);
$key = base64_encode($key);
$upgrade =
"HTTP/1.1 101 Switching Protocols\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"Sec-WebSocket-Accept: {$key}\r\n\r\n";
socket_write($user->socket, $upgrade . chr(0), strlen($upgrade . chr(0)));
$user->handshake = true;
console($upgrade);
console("Done handshaking...");
return true;
}
function getheaders($header) {
$retVal = array();
$fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $header));
foreach ($fields as $field) {
if (preg_match('/([^:]+): (.+)/m', $field, $match)) {
$match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1])));
if (isset($retVal[$match[1]])) {
$retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
} else {
$retVal[$match[1]] = trim($match[2]);
}
}
}
if (preg_match("/GET (.*) HTTP/", $header, $match)) {
$retVal['GET'] = $match[1];
}
return $retVal;
}

Resources