ApnsPHP icon indicating copy to clipboard operation
ApnsPHP copied to clipboard

Too many bytes written

Open Anarchid opened this issue 11 years ago • 13 comments

I've managed to setup ApnsPHP and get it to work; messages are sent and received as expected.

However, there's this peculiar error:

      array (
        'identifier' => 1,
        'statusCode' => 999,
        'statusMessage' => 'Internal error (112 bytes written instead of 101 bytes)',
      ),

This goes for three times, after the third it gives up:

Wed, 22 Apr 2015 17:11:57 +0200 ApnsPHP[63774]: INFO: Trying ssl://gateway.sandbox.push.apple.com:2195...
Wed, 22 Apr 2015 17:11:58 +0200 ApnsPHP[63774]: INFO: Connected to ssl://gateway.sandbox.push.apple.com:2195.
Wed, 22 Apr 2015 17:11:58 +0200 ApnsPHP[63774]: INFO: Sending messages queue, run #4: 1 message(s) left in queue.
Wed, 22 Apr 2015 17:11:58 +0200 ApnsPHP[63774]: WARNING: Message ID 1 [custom identifier: Message-Badge-3] has 3 errors, removing from queue...

And yet, all three messages are received on the device.

What gives?

Anarchid avatar Apr 22 '15 15:04 Anarchid

Is this reproducible with a particular message or it's a sporadic error?

lucabrunox avatar May 08 '15 13:05 lucabrunox

This was 100% reproducible for me, with every message i tried (though i only tried a few with some shared fields). The most recent looks like this:

ApnsPHP_Message::__set_state(array(
   '_bAutoAdjustLongPayload' => true,
   '_aDeviceTokens' => 
  array (
    0 => 'fffab12acadav12a1337',
  ),
   '_sText' => '21 unread messages',
   '_nBadge' => 21,
   '_sSound' => 'default',
   '_sCategory' => NULL,
   '_bContentAvailable' => NULL,
   '_aCustomProperties' => 
  array (
    'message' => '21 unread messages',
  ),
   '_nExpiryValue' => 30,
   '_mCustomIdentifier' => 'Message-Badge-3',
))

So far i've workarounded it by disabling the check here, but now it seems the message above no longer causes the error. :|

Anarchid avatar May 11 '15 10:05 Anarchid

I think

$nLen = mb_strlen($aMessage['BINARY_NOTIFICATION'], 'latin1');

should be here.

HunTer44x avatar Jun 02 '15 16:06 HunTer44x

I think that too, I wonder if @Anarchid could test that change...

lucabrunox avatar Jun 02 '15 16:06 lucabrunox

Documentation says it should be as defined by RFC 4627. So most likely:

$nLen = mb_strlen($aMessage['BINARY_NOTIFICATION'], 'UTF-8');

Excerpt from rfc:

3.  Encoding

   JSON text SHALL be encoded in Unicode.  The default encoding is
   UTF-8.

   Since the first two characters of a JSON text will always be ASCII
   characters [RFC0020], it is possible to determine whether an octet
   stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
   at the pattern of nulls in the first four octets.

           00 00 00 xx  UTF-32BE
           00 xx 00 xx  UTF-16BE
           xx 00 00 00  UTF-32LE
           xx 00 xx 00  UTF-16LE
           xx xx xx xx  UTF-8

ghispi avatar Jun 11 '15 16:06 ghispi

@ghispi you want to send the raw binary, hence you want the length in bytes not the length in chars.

lucabrunox avatar Jun 11 '15 17:06 lucabrunox

True, got confused by the mb_. So in such case simple strlen should work correctly. Not sure why mb_ with latin1 was suggested.

ghispi avatar Jun 11 '15 17:06 ghispi

Because many use mbstring.func_overload=2 in multi-lingual projects. You can find solution in the user contributed note in PHP Manual about mb_strlen.

HunTer44x avatar Jun 11 '15 18:06 HunTer44x

Ok, but I mean why changing currently used strlen to mb_strlen with such weird setup when strlen does exactly what we need. Documentation implicitly says:

Note:
strlen() returns the number of bytes rather than the number of characters in a string.

ghispi avatar Jun 11 '15 19:06 ghispi

If mbstring.func_overload=2, the strlen() is overloaded to mb_strlen() and return number of chars (not bytes).

HunTer44x avatar Jun 11 '15 19:06 HunTer44x

Ahhh, I never encountered this option but it makes sense. Sorry for the commotion and thanks for explaining.

In such case I'd propose something more flexible which will work if one doesn't have mbstring.

if ((int) ini_get('mbstring.func_overload') & 2) {
    $nLen = mb_strlen($aMessage['BINARY_NOTIFICATION'], 'latin1');
} else {
    $nLen = strlen($aMessage['BINARY_NOTIFICATION']);
}

ghispi avatar Jun 11 '15 19:06 ghispi

There is some bug in php (fixed for php7 alpha) which might cause some of the errors here.

ghispi avatar Jun 12 '15 10:06 ghispi

The issue has disappeared for me for some (quite long) time and then recently resurfaced.

Since i could not simply upgrade to php 7, i've tried @ghispi's patch from https://github.com/immobiliare/ApnsPHP/issues/88#issuecomment-111251202 instead.

It seems to work wonderfully thus far.

Anarchid avatar Oct 14 '16 11:10 Anarchid