반응형

Legacy Notification Format


 APNs 로 연결하기 위한 새로운 개발은 최신의 형식을 사용해야만 하는데요, APNs Provider API 에서 설명했던 것 처럼요.

이 형식들은 priority 를 포함하지 않습니다; 10 의 priority 가 가정되어 있습니다.

Legacy Notification Format


Figure B-1 Legacy notification format



 레거시 형식에서 첫 번째 byte 는 0(zero)으로 된 명령어값? 입니다. 다른 속성들은 개선된 형식과 같습니다. B-1 목록은 레거시 알림 형식을 사용해서 바이너리 인터페이스를 통하여 APNs 로의 원격 알림을 보내는 기능의 한 예를 보여줍니다.


Listing B-1 바이너리 인터페이스를 통해 레거시 형식으로 알림을 보내기.


static bool sendPayload(SSL *sslPtr, char *deviceTokenBinary, char *payloadBuff, size_t payloadLength)
{
    bool rtn = false;
    if (sslPtr && deviceTokenBinary && payloadBuff && payloadLength)
    {
        uint8_t command = 0; /* command number */
        char binaryMessageBuff[sizeof(uint8_t) + sizeof(uint16_t) +
            DEVICE_BINARY_SIZE + sizeof(uint16_t) + MAXPAYLOAD_SIZE];
        /* message format is, |COMMAND|TOKENLEN|TOKEN|PAYLOADLEN|PAYLOAD| */
        char *binaryMessagePt = binaryMessageBuff;
        uint16_t networkOrderTokenLength = htons(DEVICE_BINARY_SIZE);
        uint16_t networkOrderPayloadLength = htons(payloadLength);

        /* command */
        *binaryMessagePt++ = command;

       /* token length network order */
        memcpy(binaryMessagePt, &networkOrderTokenLength, sizeof(uint16_t));
        binaryMessagePt += sizeof(uint16_t);

        /* device token */
        memcpy(binaryMessagePt, deviceTokenBinary, DEVICE_BINARY_SIZE);
        binaryMessagePt += DEVICE_BINARY_SIZE;
        /* payload length network order */
        memcpy(binaryMessagePt, &networkOrderPayloadLength, sizeof(uint16_t));
        binaryMessagePt += sizeof(uint16_t);

        /* payload */
        memcpy(binaryMessagePt, payloadBuff, payloadLength);
        binaryMessagePt += payloadLength;
        if (SSL_write(sslPtr, binaryMessageBuff, (binaryMessagePt - binaryMessageBuff)) > 0)
            rtn = true;
    }
    return rtn; 

} 


Enhanced Notification Format


개선된 형식은 레거시 형식보다 몇가지 발전된 것들이 있습니다:

  • Error response : 레거시 형식처럼, 만약 여러분이 잘못된(malformed) 알림 패킷을 전달한다면, - 예를 들어, 페이로드는 약정한(정해진) 제한을 초과할 것입니다 - APNs  그 연결로 전달하여 응답할 것 입니다. 왜 그 알림이 거부되었는지 어떠한 암시도 주어지지 않습니다. 개선된 형식에는 provider tag 로 임의적인 식별자로 알림을 줍니다. 만약 에러가 발생하면, APNs는 그 식별자와 관련된 에러 코드로 패킷을 반환합니다. 이 응답은 provider 가 위치를 찾아내고 잘못된 알림을 올바르게 할 수 있게 합니다.
  • Notification expiration : APNs 는 store-and-forward 방식을 사용하는데 가장 최근 알림을 단말기의 앱으로 보내기 위해 유지 합니다. 만약 단말기가 전달 시점에 오프라인이라면, APNs 는 단말기가 다음 온라인 상태일 때 알림을 전달합니다. 레거시 형식과 같이, 알림은 알림의 적절성과 상관없이 전달되어 집니다. 다른 말로, 알림은 시간이 지남에 따라 “stale” 하게 될 수 있습니다. 개선된 형식은 expiry 값을 포함하는데 이것은 알림의 유효한 기간을 나타냅니다. APNs 는 expiry 기간이 지났을 때 store-and-forward 안에 있는 알림을 제거 합니다.

Figure B-2 알림 패킷들에 대한 형식을 그렸습니다.



알림 형식의 첫 바이트는 1이라는 명령어 값 입니다. 다른 필드들에 대한 설명은 아래와 같습니다: 
  • Identifier - 알림을 식별 할 수 있는 임의적인 값 입니다. 만약 APNs 가 알림을 해석할 수 없으면 에러-응답 패킷안에 같은 식별자가 반환됩니다.
  • Expiry - 초단위로 고정된 UNIX epoch 날짜 표현인데(UTC) 알림이 더 이상 유효하지 않을 때 제거 될 수 있습니다. 만료 값은 network byte order(big endian)을 사용합니다. 만약 expiry 값이 0이 아니라면, APNs는 적어도 한 번 더 알림을 전달하려고 시도할 것 입니다. 요청에 대해 0으로 명히하는 것은 APNs 가 알림 전체를 저장하지 않겠다는 것 입니다.
  • Token length - 네트워크 순서(big endian)의 디바이스 토큰 길이.
  • Device token - 바이너리 형식의 디바이스 토큰.
  • Payload length - 네트워크 순서(big endian)의 페이로드 길이.  페이로드는 256 bytes 를 초과해서는 안 되고 null 로 끝나서는 안 됩니다.

    • 초기에는 256 bytes 였으나, 현재 iOS 버전은 2KB(2048 bytes) 까지 지원하고 있다.(iOS8 이후부터...)
  • Payload - 알림 페이로드.


Listing B-2 바이너리 인터페이스를 통해 개선된 형식으로 알림 보내기.

static bool sendPayload(SSL *sslPtr, char *deviceTokenBinary, char *payloadBuff, size_t payloadLength)
{
  bool rtn = false;
  if (sslPtr && deviceTokenBinary && payloadBuff && payloadLength)
  {
      uint8_t command = 1; /* command number */
      char binaryMessageBuff[sizeof(uint8_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint16_t) +
          DEVICE_BINARY_SIZE + sizeof(uint16_t) + MAXPAYLOAD_SIZE];
      /* message format is, |COMMAND|ID|EXPIRY|TOKENLEN|TOKEN|PAYLOADLEN|PAYLOAD| */
      char *binaryMessagePt = binaryMessageBuff;
      uint32_t whicheverOrderIWantToGetBackInAErrorResponse_ID = 1234;
      uint32_t networkOrderExpiryEpochUTC = htonl(time(NULL)+86400); // expire message if not delivered in 1 day
      uint16_t networkOrderTokenLength = htons(DEVICE_BINARY_SIZE);
      uint16_t networkOrderPayloadLength = htons(payloadLength);

      /* command */
      *binaryMessagePt++ = command;

     /* provider preference ordered ID */
     memcpy(binaryMessagePt, &whicheverOrderIWantToGetBackInAErrorResponse_ID, sizeof(uint32_t));
     binaryMessagePt += sizeof(uint32_t);

     /* expiry date network order */
     memcpy(binaryMessagePt, &networkOrderExpiryEpochUTC, sizeof(uint32_t));
     binaryMessagePt += sizeof(uint32_t);

     /* token length network order */
      memcpy(binaryMessagePt, &networkOrderTokenLength, sizeof(uint16_t));
      binaryMessagePt += sizeof(uint16_t);

      /* device token */
      memcpy(binaryMessagePt, deviceTokenBinary, DEVICE_BINARY_SIZE);
      binaryMessagePt += DEVICE_BINARY_SIZE;

      /* payload length network order */
      memcpy(binaryMessagePt, &networkOrderPayloadLength, sizeof(uint16_t));
      binaryMessagePt += sizeof(uint16_t);

      /* payload */
      memcpy(binaryMessagePt, payloadBuff, payloadLength);
      binaryMessagePt += payloadLength;
      if (SSL_write(sslPtr, binaryMessageBuff, (binaryMessagePt - binaryMessageBuff)) > 0)
          rtn = true;
  }
  return rtn; 

} 


반응형

+ Recent posts