Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get SSL Broken pipe error when try to make push notification

We develop an iPhone app, and have push notification for development and ad hoc version working properly. But when we try to send push notification to real user devices in our database, we got SSL connection reset, then Broken pipe error. We think maybe there are too many devices in our database (more than 70000), so it is failed to send all messages at the same time. So we try to send messages to 1000 devices once, but still got this "Broken pipe" error for around 100 messages. And we are not sure whether the messages have been send. Any suggestion?

like image 574
emagic Avatar asked Apr 12 '10 23:04

emagic


3 Answers

We have solved this problem. It is broken due to invalid tokens in our database table.And apple apns service will disconnect us if there is an invalid token. Since the connection is broken, it will have "Broken Pipe" error when you try to send messages again. Basic solution is to find whether writing to pipe is successful, if not, just disconnect and reconnect again after some delay.

like image 132
emagic Avatar answered Sep 29 '22 21:09

emagic


emagic is correct, one reason for the "broken pipe" error can occur from invalid tokens. There are a few other reasons it can occur too. The following is from Apple Technical Note TN2265:

The most common problem is an invalid device token. If the token came from the sandbox environment, such as when you are testing a development build in house, you can't send it to the production push service. Each push environment will issue a different token for the same device or computer. If you do send a device token to the wrong environment, the push service will see that as an invalid token and discard the notification.

An invalid device token can also mean that the user has deleted your app from their device or computer. You should check the feedback service at least once a day for device tokens that are no longer valid.

Other possible issues might be sending a payload longer than 256 bytes, your payload might not be formatted correctly, or perhaps your JSON dictionary has incorrect syntax.

An occasional disconnect while your provider is idle is nothing to be concerned about; just re-establish the connection and carry on. If one of the push servers is down, the load balancing mechanism will transparently direct your new connection to another server assuming you connect by hostname and not by static IP address.

like image 34
Mongo Avatar answered Sep 29 '22 21:09

Mongo


Extending on emagic's answer, this is my php code snipplet:

private $fp;

private function connect(){ 
    $apnsHost      = 'gateway.push.apple.com'; 
    $apnsCert      = 'certs/cert.pem';
    $apnsPort      = 2195;
    $pass          = "blah";
    $streamContext = stream_context_create();

    stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
    stream_context_set_option($streamContext, 'ssl', 'passphrase', $pass);
    $this->fp = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $streamContext);
    if (!$this->fp) return("Failed to connect: $err $errstr<br>");
    echo 'Connected to APNS<hr />'; 
  }

private function send(){
  $this->connect();
  foreach($pushes as $push) {
    $payload['aps'] = array('alert' => $push->text, 'badge' => 0, 'sound' => 'default');
    $payload2 = json_encode($payload);
    $msg = chr(0) . pack('n', 32) . pack('H*', $push->token) . pack('n', strlen($payload2)) . $payload2;
    try {
      $result = fwrite($this->fp, $msg, strlen($msg));
    } 
    catch (\Exception $e) {
      fclose($this->fp);
      echo('Error sending payload: ' . $e->getMessage());
      sleep(5);
      $this->connect();
    }
  }
}
like image 44
JoeGalind Avatar answered Sep 29 '22 23:09

JoeGalind