File Coverage

blib/lib/Net/Time.pm
Criterion Covered Total %
statement 45 46 97.8
branch 13 18 72.2
condition 6 9 66.6
subroutine 11 11 100.0
pod 2 2 100.0
total 77 86 89.5


line stmt bran cond sub pod time code
1             # Net::Time.pm
2             #
3             # Copyright (C) 1995-2004 Graham Barr. All rights reserved.
4             # Copyright (C) 2014, 2020 Steve Hay. All rights reserved.
5             # This module is free software; you can redistribute it and/or modify it under
6             # the same terms as Perl itself, i.e. under the terms of either the GNU General
7             # Public License or the Artistic License, as specified in the F file.
8              
9             package Net::Time;
10              
11 2     2   1047 use 5.008001;
  2         9  
12              
13 2     2   11 use strict;
  2         4  
  2         41  
14 2     2   10 use warnings;
  2         4  
  2         46  
15              
16 2     2   10 use Carp;
  2         5  
  2         106  
17 2     2   11 use Exporter;
  2         4  
  2         78  
18 2     2   581 use IO::Select;
  2         1790  
  2         75  
19 2     2   11 use IO::Socket;
  2         13  
  2         37  
20 2     2   976 use Net::Config;
  2         12  
  2         1051  
21              
22             our @ISA = qw(Exporter);
23             our @EXPORT_OK = qw(inet_time inet_daytime);
24              
25             our $VERSION = "3.13";
26              
27             our $TIMEOUT = 120;
28              
29             sub _socket {
30 5     5   2709 my ($pname, $pnum, $host, $proto, $timeout) = @_;
31              
32 5   100     21 $proto ||= 'udp';
33              
34 5   66     1057 my $port = (getservbyname($pname, $proto))[2] || $pnum;
35              
36 5 50       26 my $hosts = defined $host ? [$host] : $NetConfig{$pname . '_hosts'};
37              
38 5         9 my $me;
39              
40 5         10 foreach my $addr (@$hosts) {
41 5 100       28 $me = IO::Socket::INET->new(
42             PeerAddr => $addr,
43             PeerPort => $port,
44             Proto => $proto
45             )
46             and last;
47             }
48              
49 5 100       61 return unless $me;
50              
51 4 100       18 $me->send("\n")
52             if $proto eq 'udp';
53              
54 4 100       28 $timeout = $TIMEOUT
55             unless defined $timeout;
56              
57 4 50       12 IO::Select->new($me)->can_read($timeout)
58             ? $me
59             : undef;
60             }
61              
62              
63             sub inet_time {
64 1   50 1 1 2 my $s = _socket('time', 37, @_) || return;
65 1         17 my $buf = '';
66 1         2 my $offset = 0 | 0;
67              
68             return
69 1 50       6 unless defined $s->recv($buf, length(pack("N", 0)));
70              
71             # unpack, we | 0 to ensure we have an unsigned
72 1         19 my $time = (unpack("N", $buf))[0] | 0;
73              
74             # the time protocol return time in seconds since 1900, convert
75             # it to a the required format
76              
77 1 50       4 if ($^O eq "MacOS") {
78              
79             # MacOS return seconds since 1904, 1900 was not a leap year.
80 0         0 $offset = (4 * 31536000) | 0;
81             }
82             else {
83              
84             # otherwise return seconds since 1972, there were 17 leap years between
85             # 1900 and 1972
86 1         2 $offset = (70 * 31536000 + 17 * 86400) | 0;
87             }
88              
89 1         5 $time - $offset;
90             }
91              
92              
93             sub inet_daytime {
94 1   50 1 1 1772 my $s = _socket('daytime', 13, @_) || return;
95 1         20 my $buf = '';
96              
97 1 50       4 defined($s->recv($buf, 1024))
98             ? $buf
99             : undef;
100             }
101              
102             1;
103              
104             __END__