File Coverage

blib/lib/Net/APNs/Extended.pm
Criterion Covered Total %
statement 66 70 94.2
branch 22 28 78.5
condition 22 27 81.4
subroutine 12 12 100.0
pod 4 4 100.0
total 126 141 89.3


line stmt bran cond sub pod time code
1             package Net::APNs::Extended;
2              
3 7     7   189049 use strict;
  7         12  
  7         237  
4 7     7   26 use warnings;
  7         10  
  7         158  
5 7     7   129 use 5.008_001;
  7         22  
  7         316  
6             our $VERSION = '0.11';
7              
8 7     7   3333 use parent qw(Exporter Net::APNs::Extended::Base);
  7         2148  
  7         32  
9 7     7   369 use Carp qw(croak);
  7         16  
  7         462  
10              
11             use constant {
12 7         5534 NO_ERRORS => 0,
13             PROCESSING_ERROR => 1,
14             MISSING_DEVICE_TOKEN => 2,
15             MISSING_TOPIC => 3,
16             MISSING_PAYLOAD => 4,
17             INVALID_TOKEN_SIZE => 5,
18             INVALID_TOPIC_SIZE => 6,
19             INVALID_PAYLOAD_SIZE => 7,
20             INVALID_TOKEN => 8,
21             SHUTDOWN => 10,
22             UNKNOWN_ERROR => 255,
23 7     7   32 };
  7         11  
24              
25             our @EXPORT_OK = qw{
26             NO_ERRORS
27             PROCESSING_ERROR
28             MISSING_DEVICE_TOKEN
29             MISSING_TOPIC
30             MISSING_PAYLOAD
31             INVALID_TOKEN_SIZE
32             INVALID_TOPIC_SIZE
33             INVALID_PAYLOAD_SIZE
34             INVALID_TOKEN
35             SHUTDOWN
36             UNKNOWN_ERROR
37             };
38             our %EXPORT_TAGS = (constants => \@EXPORT_OK);
39              
40             __PACKAGE__->mk_accessors(qw[
41             max_payload_size
42             command
43             ]);
44              
45             my %default = (
46             host_production => 'gateway.push.apple.com',
47             host_sandbox => 'gateway.sandbox.push.apple.com',
48             is_sandbox => 0,
49             port => 2195,
50             max_payload_size => 256,
51             command => 1,
52             );
53              
54             sub new {
55 5     5 1 942 my ($class, %args) = @_;
56 5         71 $class->SUPER::new(%default, %args);
57             }
58              
59             sub send {
60 4     4 1 5777 my ($self, $device_token, $payload, $extra) = @_;
61 4 100 100     323 croak 'Usage: $apns->send($device_token, \%payload [, \%extra ])'
62             unless defined $device_token && ref $payload eq 'HASH';
63              
64 2   100     5 $extra ||= {};
65 2   100     6 $extra->{identifier} ||= 0;
66 2   100     6 $extra->{expiry} ||= 0;
67 2   50     4 my $data = $self->_create_send_data($device_token, $payload, $extra) || return 0;
68 2 50       2793 return $self->_send($data) ? 1 : 0;
69             }
70              
71             sub send_multi {
72 5     5 1 6764 my ($self, $datum) = @_;
73 5 100       198 croak 'Usage: $apns->send_multi(\@datum)' unless ref $datum eq 'ARRAY';
74              
75 4         4 my $data;
76 4         5 my $i = 0;
77 4         7 for my $stuff (@$datum) {
78 6 100       183 croak 'Net::APNs::Extended: send data must be ARRAYREF' unless ref $stuff eq 'ARRAY';
79 5         7 my ($device_token, $payload, $extra) = @$stuff;
80 5 100 66     124 croak 'Net::APNs::Extended: send data require $device_token and \%payload'
81             unless defined $device_token && ref $payload eq 'HASH';
82 4   100     11 $extra ||= {};
83 4   100     9 $extra->{identifier} ||= $i++;
84 4   100     11 $extra->{expiry} ||= 0;
85 4         8 $data .= $self->_create_send_data($device_token, $payload, $extra);
86             }
87 2 50       31 return $self->_send($data) ? 1 : 0;
88             }
89              
90             sub retrieve_error {
91 2     2 1 3180 my $self = shift;
92 2         5 my $data = $self->_read;
93 2 50       34 return unless defined $data;
94              
95 2         9 my ($command, $status, $identifier) = unpack 'C C L', $data;
96 2         5 my $error = {
97             command => $command,
98             status => $status,
99             identifier => $identifier,
100             };
101              
102 2         5 $self->disconnect;
103 2         20 return $error;
104             }
105             *retrive_error = *retrieve_error;
106              
107             sub _create_send_data {
108 7     7   23129 my ($self, $device_token, $payload, $extra) = @_;
109 7         15 my $chunk;
110              
111 7 100       207 croak 'aps parameter must be HASHREF' unless ref $payload->{aps} eq 'HASH';
112              
113             # numify
114 6 100       25 $payload->{aps}{badge} += 0 if exists $payload->{aps}{badge};
115              
116             # trim alert body
117 6         33 my $json = $self->json->encode($payload);
118 6         248 while (bytes::length($json) > $self->{max_payload_size}) {
119 851 100 66     27554 if (ref $payload->{aps}{alert} eq 'HASH' && exists $payload->{aps}{alert}{body}) {
    50          
120 429         704 $payload->{aps}{alert}{body} = $self->_trim_alert_body($payload->{aps}{alert}{body}, $payload);
121             }
122             elsif (exists $payload->{aps}{alert}) {
123 422         842 $payload->{aps}{alert} = $self->_trim_alert_body($payload->{aps}{alert}, $payload);
124             }
125             else {
126 0         0 $self->_trim_alert_body(undef, $payload);
127             }
128 851         1760 $json = $self->json->encode($payload);
129             }
130              
131 6         1097 my $command = $self->command;
132 6 100       36 if ($command == 0) {
    50          
133 1         8 $chunk = CORE::pack('C n/a* n/a*', $command, $device_token, $json);
134             }
135             elsif ($command == 1) {
136 5         50 $chunk = CORE::pack('C L N n/a* n/a*',
137             $command, $extra->{identifier}, $extra->{expiry}, $device_token, $json,
138             );
139             }
140             else {
141 0         0 croak "command($command) not support. shuled be 0 or 1";
142             }
143              
144 6         22 return $chunk;
145             }
146              
147             sub _trim_alert_body {
148 851     851   1033 my ($self, $body, $payload) = @_;
149 851 50 33     4024 if (!defined $body || length $body == 0) {
150 0         0 my $json = $self->json->encode($payload);
151 0         0 croak sprintf "over the payload size (current:%d > max:%d) : %s",
152             bytes::length($json), $self->{max_payload_size}, $json;
153             }
154 851         1835 substr($body, -1, 1) = '';
155 851         2232 return $body;
156             }
157              
158             1;
159             __END__