line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mirror::JSON; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
93924
|
use 5.006; |
|
3
|
|
|
|
|
13
|
|
|
3
|
|
|
|
|
172
|
|
4
|
3
|
|
|
3
|
|
18
|
use strict; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
176
|
|
5
|
3
|
|
|
3
|
|
2177
|
use Mirror::URI (); |
|
3
|
|
|
|
|
10
|
|
|
3
|
|
|
|
|
71
|
|
6
|
3
|
|
|
3
|
|
12767
|
use JSON (); |
|
3
|
|
|
|
|
70820
|
|
|
3
|
|
|
|
|
152
|
|
7
|
|
|
|
|
|
|
|
8
|
3
|
|
|
3
|
|
27
|
use vars qw{$VERSION @ISA}; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
324
|
|
9
|
|
|
|
|
|
|
BEGIN { |
10
|
3
|
|
|
3
|
|
8
|
$VERSION = '0.90'; |
11
|
3
|
|
|
|
|
693
|
@ISA = 'Mirror::URI'; |
12
|
|
|
|
|
|
|
} |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
##################################################################### |
19
|
|
|
|
|
|
|
# Implementation-Specific Methods |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
sub filename { |
22
|
2
|
|
|
2
|
0
|
10
|
return 'mirror.json'; |
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub parse { |
26
|
2
|
|
|
2
|
0
|
4
|
my $class = shift; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# Make sure we actually have a YAML document |
29
|
2
|
50
|
|
|
|
19
|
unless ( $_[0] =~ /^{/ ) { |
30
|
0
|
|
|
|
|
0
|
return undef; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# Parse the file |
34
|
2
|
|
|
|
|
19
|
my $docs = JSON::from_json($_[0]); |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# We only care about the first document |
37
|
2
|
50
|
|
|
|
273
|
unless ( defined $docs ) { |
38
|
0
|
|
|
|
|
0
|
Carp::croak("Illegal JSON document"); |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
2
|
|
|
|
|
10
|
return $docs; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
1; |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=pod |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=head1 NAME |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
Mirror::JSON - Mirror Configuration and Auto-Discovery |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=head1 DESCRIPTION |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
A C file is used to allow a repository client to reliably and |
55
|
|
|
|
|
|
|
robustly locate, identify, validate and age a repository. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
It contains a timestamp for when the repository was last updated, the URI |
58
|
|
|
|
|
|
|
for the master repository, and a list of all the current mirrors at the |
59
|
|
|
|
|
|
|
time the repository was last updated. |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
B contains all the functionality requires to both create |
62
|
|
|
|
|
|
|
and read the F files, and the logic to select one or more |
63
|
|
|
|
|
|
|
mirrors entirely automatically. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
It currently scales cleanly for a dozen or so mirrors, but may be slow |
66
|
|
|
|
|
|
|
when used with very large repositories with a hundred or more mirrors. |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=head2 Methodology |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
A variety of simple individual mechanisms are combined to provide a |
71
|
|
|
|
|
|
|
completely robust discovery and validation system. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
B |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
The F file should exist in a standard location, typically at |
76
|
|
|
|
|
|
|
the root of the repository. The file is very small (no more than a few |
77
|
|
|
|
|
|
|
kilobytes at most) so the overhead of fetching one (or several) of them |
78
|
|
|
|
|
|
|
is negligable. |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
The file is pulled via FTP or HTTP. Once pulled, the first three |
81
|
|
|
|
|
|
|
characters are examined to validate it is a JSON file and not a |
82
|
|
|
|
|
|
|
login page for a "captured hotspot" such as at hotels and airports. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
B |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Because the F file is small (in simple cases only one or two |
87
|
|
|
|
|
|
|
packets) the download time can be used to measure the responsiveness of |
88
|
|
|
|
|
|
|
that mirror. |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
By pulling the files from several mirrors, the comparative download |
91
|
|
|
|
|
|
|
times can be used as part of the process of selecting the fastest mirror. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
B |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
The mirror.json file contains a timestamp that records the last update time |
96
|
|
|
|
|
|
|
for the repository. This timestamp should be updated every repository |
97
|
|
|
|
|
|
|
update cycle, even if there are no actual changes to the repository. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
Once a F file has been fetched correctly, the timestamp can |
100
|
|
|
|
|
|
|
then be used to verify the age of the mirror. Whereas a perfectly up to |
101
|
|
|
|
|
|
|
date mirror will show an age of less than an hour (assuming that the |
102
|
|
|
|
|
|
|
repository master updates every hour) a repository that has stopped |
103
|
|
|
|
|
|
|
updating will show an age that is greater than the longest mirror rate |
104
|
|
|
|
|
|
|
plus the update cycle time. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
Thus, any mirror that as "gone stale" can be filter out of the potential |
107
|
|
|
|
|
|
|
mirrors to use. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
For portability, the timestamp is recording in ISO format Zulu time. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
B |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
The F file contains a link to the master repository. |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
If the L client has an out-of-date current state at some |
116
|
|
|
|
|
|
|
point, it will use the master repository URI in the current state to |
117
|
|
|
|
|
|
|
pull a fresh F from the master repository. |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
This solves the most-simple case, but other cases require a little |
120
|
|
|
|
|
|
|
more complexity (which we'll address later). |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
B |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
The F file contains a simple list of all mirror URIs. |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
Apart from filtering the list to try and find the best mirror to use, |
127
|
|
|
|
|
|
|
the mirror list allows the B client to have backup |
128
|
|
|
|
|
|
|
options for locating the master repository if it moves, or the |
129
|
|
|
|
|
|
|
bootstrap F file has gotten old. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
If the client can't find the master repository (because it has moved) |
132
|
|
|
|
|
|
|
the client will scan the list of mirrors to try to find the location |
133
|
|
|
|
|
|
|
of the updated repository. |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
B |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
To bootstrap the client, it should come with a default bootstrap |
138
|
|
|
|
|
|
|
F file built into it. When the client starts up for the |
139
|
|
|
|
|
|
|
first time, it will attempt to fetch an updated mirror.json from the |
140
|
|
|
|
|
|
|
master repository, and if that doesn't exist will pull from the |
141
|
|
|
|
|
|
|
default list of mirrors until it can find more than one up to date |
142
|
|
|
|
|
|
|
mirror that agrees on the real location of the master server. |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
B |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
On top of the straight forward mirror discovery functionality, the |
147
|
|
|
|
|
|
|
client algorithm contains additional logic to deal with either a |
148
|
|
|
|
|
|
|
mirror or the master server goes bad. While likely not 100% secure |
149
|
|
|
|
|
|
|
it heads off several attack scenarios to prevent anyone trying them, |
150
|
|
|
|
|
|
|
and provides as much as can be expected without resorting to cryto |
151
|
|
|
|
|
|
|
and certificates. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head1 SUPPORT |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
Bugs should be reported via the CPAN bug tracker at |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
L |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
For other issues, or commercial enhancement or support, contact the author. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=head1 AUTHOR |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
Adam Kennedy Eadamk@cpan.orgE |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head1 SEE ALSO |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
L, L, L |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=head1 COPYRIGHT |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Copyright 2007 - 2009 Adam Kennedy. |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
This program is free software; you can redistribute |
174
|
|
|
|
|
|
|
it and/or modify it under the same terms as Perl itself. |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
The full text of the license can be found in the |
177
|
|
|
|
|
|
|
LICENSE file included with this module. |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=cut |