File Coverage

blib/lib/Net/EPP/Protocol.pm
Criterion Covered Total %
statement 13 36 36.1
branch 0 10 0.0
condition n/a
subroutine 5 8 62.5
pod 0 3 0.0
total 18 57 31.5


line stmt bran cond sub pod time code
1             # Copyright (c) 2016 CentralNic Ltd. All rights reserved. This program is
2             # free software; you can redistribute it and/or modify it under the same
3             # terms as Perl itself.
4             package Net::EPP::Protocol;
5 1     1   4 use bytes;
  1         1  
  1         5  
6 1     1   98 use Carp;
  1         1  
  1         53  
7 1     1   3 use vars qw($THRESHOLD);
  1         1  
  1         27  
8 1     1   3 use strict;
  1         1  
  1         31  
9              
10             =pod
11              
12             =head1 NAME
13              
14             Net::EPP::Protocol - Low-level functions useful for both EPP clients and
15             servers.
16              
17             =head1 SYNOPSIS
18              
19             #!/usr/bin/perl
20             use Net::EPP::Protocol;
21             use IO::Socket;
22             use strict;
23              
24             # create a socket:
25              
26             my $socket = IO::Socket::INET->new( ... );
27              
28             # send a frame down the socket:
29              
30             Net::EPP::Protocol->send_frame($socket, $xml);
31              
32             # get a frame from the socket:
33              
34             my $xml = Net::EPP::Protocol->get_frame($socket);
35              
36             =head1 DESCRIPTION
37              
38             EPP is the Extensible Provisioning Protocol. EPP (defined in RFC 4930)
39             is an application layer client-server protocol for the provisioning and
40             management of objects stored in a shared central repository. Specified
41             in XML, the protocol defines generic object management operations and an
42             extensible framework that maps protocol operations to objects. As of
43             writing, its only well-developed application is the provisioning of
44             Internet domain names, hosts, and related contact details.
45              
46             This module implements functions that are common to both EPP clients and
47             servers that implement the TCP transport as defined in RFC 4934. The
48             main consumer of this module is currently L.
49              
50             =head1 VARIABLES
51              
52             =head2 $Net::EPP::Protocol::THRESHOLD
53              
54             At least one EPP server implementation sends an unframed plain text error
55             message when a client connects from an unauthorised address. As a result, when
56             the first four bytes of the message are unpacked, the client tries to read and
57             allocate a very large amount of memory.
58              
59             If the apparent frame length received from a server exceeds the value of
60             C<$Net::EPP::Protocol::THRESHOLD>, the C method will croak.
61              
62             The default value is 1GB.
63              
64             =cut
65              
66             BEGIN {
67 1     1   217 our $THRESHOLD = 1000000000;
68             }
69              
70             =pod
71              
72             =head1 METHODS
73              
74             my $xml = Net::EPP::Protocol->get_frame($socket);
75              
76             This method reads a frame from the socket and returns a scalar
77             containing the XML. C<$socket> must be an L or one of its
78             subclasses (ie C).
79              
80             If the transmission fails for whatever reason, this method will
81             C, so be sure to enclose it in an C.
82              
83             =cut
84              
85             sub get_frame {
86 0     0 0   my ($class, $fh) = @_;
87              
88 0           my $hdr;
89 0 0         if (!defined($fh->read($hdr, 4))) {
90 0           croak("Got a bad frame length from peer - connection closed?");
91              
92             } else {
93 0           my $length = (unpack('N', $hdr) - 4);
94 0 0         if ($length < 0) {
    0          
    0          
95 0           croak("Got a bad frame length from peer - connection closed?");
96              
97             } elsif (0 == $length) {
98 0           croak('Frame length is zero');
99              
100             } elsif ($length > $THRESHOLD) {
101 0           croak("Frame length is $length which exceeds $THRESHOLD");
102              
103             } else {
104 0           my $xml = '';
105 0           my $buffer;
106 0           while (length($xml) < $length) {
107 0           $buffer = '';
108 0           $fh->read($buffer, ($length - length($xml)));
109 0 0         last if (length($buffer) == 0); # in case the socket has closed
110 0           $xml .= $buffer;
111             }
112              
113 0           return $xml;
114              
115             }
116             }
117             }
118              
119             =pod
120              
121             Net::EPP::Protocol->send_frame($socket, $xml);
122              
123             This method prepares an RFC 4934 compliant EPP frame and transmits it to
124             the remote peer. C<$socket> must be an L or one of its
125             subclasses (ie C).
126              
127             If the transmission fails for whatever reason, this method will
128             C, so be sure to enclose it in an C. Otherwise, it will
129             return a true value.
130              
131             =cut
132              
133             sub send_frame {
134 0     0 0   my ($class, $fh, $xml) = @_;
135 0           $fh->print($class->prep_frame($xml));
136 0           $fh->flush;
137 0           return 1;
138             }
139              
140             =pod
141              
142             my $frame = Net::EPP::Protocol->prep_frame($xml);
143              
144             This method returns the XML frame in "wire format" with the protocol
145             header prepended to it. The return value can be printed directly to an
146             open socket, for example:
147              
148             print STDOUT Net::EPP::Protocol->prep_frame($frame->toString);
149              
150             =cut
151              
152             sub prep_frame {
153 0     0 0   my ($class, $xml) = @_;
154 0           return pack('N', length($xml) + 4).$xml;
155             }
156              
157             =pod
158              
159             =head1 AUTHOR
160              
161             CentralNic Ltd (L).
162              
163             =head1 COPYRIGHT
164              
165             This module is (c) 2016 CentralNic Ltd. This module is free software; you can
166             redistribute it and/or modify it under the same terms as Perl itself.
167              
168             =head1 SEE ALSO
169              
170             =over
171              
172             =item * L
173              
174             =item * RFCs 4930 and RFC 4934, available from L.
175              
176             =item * The CentralNic EPP site at L.
177              
178             =back
179              
180             =cut
181              
182             1;