home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Mirror.pm < prev    next >
Encoding:
Perl POD Document  |  2002-12-23  |  5.6 KB  |  386 lines

  1. package Geo::Mirror;
  2.  
  3. use strict;
  4. use vars qw($VERSION);
  5. use Geo::IP;
  6.  
  7. use POSIX;
  8.  
  9. $VERSION = '0.10';
  10.  
  11. use constant PI => 3.14159265358979323846;
  12.  
  13. our (%lat, %lon);
  14.  
  15. while (<DATA>) {
  16.   my ($country, $lat, $lon) = split(':');
  17.  
  18.   $lat{$country} = $lat;
  19.   $lon{$country} = $lon;
  20. }
  21.  
  22. sub new {
  23.   my ($class, %h) = @_;
  24.   my $self = \%h;
  25.   bless $self, $class;
  26.   $self->_init;
  27.   return $self;
  28. }
  29.  
  30. sub _init {
  31.   my $self = shift;
  32.   my $mirror_file = $self->{mirror_file};
  33.   open MIRROR, "$mirror_file";
  34.   while(<MIRROR>) {
  35.     my ($url, $country) = split(' ');
  36.     push @{$self->{mirror}->{$country}}, $url;
  37.   }
  38.   close MIRROR;
  39. }
  40.  
  41. sub _random_mirror {
  42.   my ($self, $country) = @_;
  43.  
  44.   my $num = scalar(@{$self->{mirror}->{$country}});
  45.  
  46.   return unless $num;
  47.  
  48.   return $self->{mirror}->{$country}->[int(rand()*$num)];
  49. }
  50.  
  51. sub find_mirror_by_country {
  52.   my ($self, $country) = @_;
  53.  
  54.   if (exists $self->{mirror}->{$country}) {
  55.     return $self->_random_mirror($country);
  56.   } elsif (exists $self->{nearby_cache}->{$country}) {
  57.     return $self->_random_mirror($self->{nearby_cache}->{$country});
  58.   } else {
  59.     my $new_country = $self->_find_nearby_country($country);
  60.     $self->{nearby_cache}->{$country} = $new_country;
  61.     return $self->_random_mirror($new_country);
  62.   }
  63. }
  64.  
  65. sub find_mirror_by_addr {
  66.   my ($self, $addr) = @_;
  67.  
  68.   unless($self->{gi}) {
  69.     if ($self->{database_file}) {
  70.       $self->{gi} = Geo::IP->open($self->{database_file}, GEOIP_STANDARD);
  71.     } else {
  72.       $self->{gi} = Geo::IP->new(GEOIP_STANDARD);
  73.     }
  74.   }
  75.  
  76.   # default to US if country not found
  77.   my $country = lc($self->{gi}->country_code_by_addr($addr)) || 'us';
  78.   $country = 'us' if $country eq '--';
  79.   return $self->find_mirror_by_country($country);
  80. }
  81.  
  82. sub _find_nearby_country {
  83.   my ($self, $country) = @_;
  84.  
  85.   my @candidate_countries = keys %{$self->{mirror}};
  86.   my $closest_country;
  87.   my $closest_distance = 1_000_000_000;
  88.  
  89.   for (@candidate_countries) {
  90.     my $distance = $self->_calculate_distance($country, $_);
  91.     if ($distance < $closest_distance) {
  92.       $closest_country = $_;
  93.       $closest_distance = $distance;
  94.     }
  95.   }
  96.   return $closest_country;
  97. }
  98.  
  99. sub _calculate_distance {
  100.   my ($self, $country1, $country2) = @_;
  101.  
  102.   my $lat_1 = $lat{$country1};
  103.   my $lat_2 = $lat{$country2};
  104.   my $lon_1 = $lon{$country1};
  105.   my $lon_2 = $lon{$country2};
  106.  
  107.   # Convert all the degrees to radians
  108.   $lat_1 *= PI/180;
  109.   $lon_1 *= PI/180;
  110.   $lat_2 *= PI/180;
  111.   $lon_2 *= PI/180;
  112.  
  113.   # Find the deltas
  114.   my $delta_lat = $lat_2 - $lat_1;
  115.   my $delta_lon = $lon_2 - $lon_1;
  116.  
  117.   # Find the Great Circle distance
  118.   my $temp = sin($delta_lat/2.0)**2 + cos($lat_1) * cos($lat_2) * sin($delta_lon/2.0)**2;
  119.   return atan2(sqrt($temp),sqrt(1-$temp));
  120. }
  121.  
  122. 1;
  123.  
  124. =head1 NAME
  125.  
  126. Geo::Mirror - Find closest Mirror
  127.  
  128. =head1 SYNOPSIS
  129.  
  130.   use Geo::Mirror;
  131.  
  132.   my $gm = Geo::Mirror->new(mirror_file => '/path/to/mirrors.txt');
  133.  
  134.   my $mirror = $gm->closest_mirror_by_country('us');
  135.   my $mirror = $gm->closest_mirror_by_addr('65.15.30.247');
  136.  
  137. =head1 DESCRIPTION
  138.  
  139. This module finds the closest mirror for an IP address.  It uses L<Geo::IP>
  140. to identify the country that the IP address originated from.  If
  141. the country is not represented in the mirror list, then it finds the
  142. closest country using a latitude/longitude table.
  143.  
  144. =head1 AUTHOR
  145.  
  146. Copyright (c) 2002, T.J. Mather, tjmather@tjmather.com, New York, NY, USA
  147.  
  148. All rights reserved.  This package is free software; you can redistribute it
  149. and/or modify it under the same terms as Perl itself.
  150.  
  151. =cut
  152.  
  153. __DATA__
  154. af:33:65
  155. al:41:20
  156. dz:28:3
  157. as:-14:-170
  158. ad:42:1
  159. ao:-12:18
  160. ai:18:-63
  161. aq:-90:0
  162. ag:17:-61
  163. ar:-34:-64
  164. am:40:45
  165. aw:12:-69
  166. au:-27:133
  167. at:47:13
  168. az:40:47
  169. bs:24:-76
  170. bh:26:50
  171. bd:24:90
  172. bb:13:-59
  173. by:53:28
  174. be:50:4
  175. bz:17:-88
  176. bj:9:2
  177. bm:32:-64
  178. bt:27:90
  179. bo:-17:-65
  180. ba:44:18
  181. bw:-22:24
  182. bv:-54:3
  183. br:-10:-55
  184. io:-6:71
  185. vg:18:-64
  186. bg:43:25
  187. bf:13:-2
  188. bi:-3:30
  189. kh:13:105
  190. cm:6:12
  191. ca:60:-95
  192. cv:16:-24
  193. ky:19:-80
  194. cf:7:21
  195. td:15:19
  196. cl:-30:-71
  197. cn:35:105
  198. cx:-10:105
  199. cc:-12:96
  200. co:4:-72
  201. km:-12:44
  202. cd:0:25
  203. cg:-1:15
  204. ck:-21:-159
  205. cr:10:-84
  206. ci:8:-5
  207. hr:45:15
  208. cu:21:-80
  209. cy:35:33
  210. cz:49:15
  211. dk:56:10
  212. dj:11:43
  213. dm:15:-61
  214. do:19:-70
  215. ec:-2:-77
  216. eg:27:30
  217. sv:13:-88
  218. gq:2:10
  219. er:15:39
  220. ee:59:26
  221. et:8:38
  222. fk:-51:-59
  223. fo:62:-7
  224. fj:-18:175
  225. fi:64:26
  226. fr:46:2
  227. gf:4:-53
  228. pf:-15:-140
  229. ga:-1:11
  230. gm:13:-16
  231. ge:42:43
  232. de:51:9
  233. eu:48:10
  234. gh:8:-2
  235. gi:36:-5
  236. gr:39:22
  237. gl:72:-40
  238. gd:12:-61
  239. gp:16:-61
  240. gu:13:144
  241. gt:15:-90
  242. gn:11:-10
  243. gw:12:-15
  244. gy:5:-59
  245. ht:19:-72
  246. hm:-53:72
  247. va:41:12
  248. hn:15:-86
  249. hk:22:114
  250. hu:47:20
  251. is:65:-18
  252. in:20:77
  253. id:-5:120
  254. ir:32:53
  255. iq:33:44
  256. ie:53:-8
  257. il:31:34
  258. it:42:12
  259. jm:18:-77
  260. sj:71:-8
  261. jp:36:138
  262. jo:31:36
  263. ke:1:38
  264. ki:1:173
  265. kp:40:127
  266. kr:37:127
  267. kw:29:45
  268. kg:41:75
  269. lv:57:25
  270. lb:33:35
  271. ls:-29:28
  272. lr:6:-9
  273. ly:25:17
  274. li:47:9
  275. lt:56:24
  276. lu:49:6
  277. mo:22:113
  278. mk:41:22
  279. mg:-20:47
  280. mw:-13:34
  281. my:2:112
  282. mv:3:73
  283. ml:17:-4
  284. mt:35:14
  285. mh:9:168
  286. mq:14:-61
  287. mr:20:-12
  288. mu:-20:57
  289. yt:-12:45
  290. mx:23:-102
  291. fm:6:158
  292. mc:43:7
  293. mn:46:105
  294. ms:16:-62
  295. ma:32:-5
  296. mz:-18:35
  297. na:-22:17
  298. nr:-0:166
  299. np:28:84
  300. nl:52:5
  301. an:12:-68
  302. nc:-21:165
  303. nz:-41:174
  304. ni:13:-85
  305. ne:16:8
  306. ng:10:8
  307. nu:-19:-169
  308. nf:-29:167
  309. mp:15:145
  310. no:62:10
  311. om:21:57
  312. pk:30:70
  313. pw:7:134
  314. pa:9:-80
  315. pg:-6:147
  316. py:-23:-58
  317. pe:-10:-76
  318. ph:13:122
  319. pn:-25:-130
  320. pl:52:20
  321. pt:39:-8
  322. pr:18:-66
  323. qa:25:51
  324. re:-21:55
  325. ro:46:25
  326. ru:60:100
  327. rw:-2:30
  328. sh:-15:-5
  329. kn:17:-62
  330. lc:13:-60
  331. pm:46:-56
  332. vc:13:-61
  333. ws:-13:-172
  334. sm:43:12
  335. st:1:7
  336. sa:25:45
  337. sn:14:-14
  338. sc:-4:55
  339. sl:8:-11
  340. sg:1:103
  341. sk:48:19
  342. si:46:15
  343. sb:-8:159
  344. so:10:49
  345. za:-29:24
  346. gs:-54:-37
  347. es:40:-4
  348. lk:7:81
  349. sd:15:30
  350. sr:4:-56
  351. sj:78:20
  352. sz:-26:31
  353. se:62:15
  354. ch:47:8
  355. sy:35:38
  356. tj:39:71
  357. tz:-6:35
  358. th:15:100
  359. tg:8:1
  360. tk:-9:-172
  361. to:-20:-175
  362. tt:11:-61
  363. tn:34:9
  364. tr:39:35
  365. tm:40:60
  366. tc:21:-71
  367. tv:-8:178
  368. ug:1:32
  369. ua:49:32
  370. ae:24:54
  371. gb:54:-2
  372. us:38:-97
  373. uy:-33:-56
  374. uz:41:64
  375. vu:-16:167
  376. ve:8:-66
  377. vn:16:106
  378. vi:18:-64
  379. wf:-13:-176
  380. eh:24:-13
  381. ye:15:48
  382. yu:44:21
  383. zm:-15:30
  384. zw:-20:30
  385. tw:23:121
  386.