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