| P2P-pDonkey documentation | Contained in the P2P-pDonkey distribution. |
P2P::pDonkey::Met - Perl extension for handling *.met files of eDonkey peer2peer protocol.
use P2P::pDonkey::Met ':server';
my $servers;
my $p = readServerMet($ARGV[0]);
if ($p) {
printServerMet($p);
} else {
print "$ARGV[0] is not in server.met format\n";
}
...
use P2P::pDonkey::Met ':part';
foreach my $f (@ARGV) {
my $p = readPartMet($f);
if ($p) {
printPartMet($p);
} else {
print "$f is not in part.met format\n";
}
}
...
use P2P::pDonkey::Met ':known';
my $p = readKnownMet($ARGV[0]);
if ($p) {
printKnownMet($p);
} else {
print "$ARGV[0] is not in known.met format\n";
}
...
use P2P::pDonkey::Met ':pref';
my $p = readPrefMet($ARGV[0]);
if ($p) {
printPrefMet($p);
} else {
print "$ARGV[0] is not in pref.met format\n";
}
The module provides functions for reading, printing and writing *.met files of eDonkey peer2peer protocol.
P2P::pDonkey::Met provides the subroutines for four types of met files:
server.met, ...part.met, known.met, pref.met.
Functions are tagged with ':server'.
Returns reference to unpacked server description structure.
Returns packed string for description $$p.
Prints server description to STDOUT.
Returns reference to new server description structure.
Returns reference to list of server descriptions.
Returns packed string for list of descriptions @$l.
Prints items of list @$l to STDOUT.
Returns reference to hash of server descriptions. Keys are idAddr($ip, $port).
Returns packed string for hash of descriptions %$h.
Prints values of hash %$h to STDOUT.
Returns reference to hash of server descriptions.
Returns packed string in server.met file format.
Alias to printServerDescListU($buffer, $offset).
Reads file and unpacks data with unpackServerMet() function.
Packs %$h with packServerMet() function and writes to file.
Functions are tagged with ':part'.
Returns reference to file information structure.
Returns packed string in part.met format.
Prints file information to STDOUT.
Reads file and unpacks data with unpackPartMet() function.
Packs $$p with packPartMet() function and writes to file.
Functions are tagged with ':known'.
Returns reference to list of file information structures.
Returns packed string in known.met format.
Prints elements of list @$l to STDOUT.
Reads file and unpacks data with unpackKnownMet() function.
Packs @$p with packKnownMet() function and writes to file.
Functions are tagged with ':pref'.
Returns reference to hash:
IP => $ip
Port => $port
Hash => $hash
Meta => $meta
Pref => $pref
Returns packed string in pref.met format.
Print file information to STDOUT.
Reads file and unpacks data with unpackPrefMet() function.
Packs $$p with packPrefMet() function and writes to file.
None by default.
Alexey Klimkin, <klimkin@mail.ru>
perl, P2P::pDonkey::Meta.
eDonkey home:
<http://www.edonkey2000.com/>
Basic protocol information:
<http://hitech.dk/donkeyprotocol.html>
<http://www.schrevel.com/edonkey/>
Client stuff:
<http://www.emule-project.net/>
<http://www.nongnu.org/mldonkey/>
Server stuff:
<http://www.thedonkeynetwork.com/>
| P2P-pDonkey documentation | Contained in the P2P-pDonkey distribution. |
# P2P::pDonkey::Met.pm # # Copyright (c) 2003-2004 Alexey klimkin <klimkin at cpan.org>. # All rights reserved. # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. # package P2P::pDonkey::Met; use 5.006; use strict; use warnings; require Exporter; our $VERSION = '0.05'; our @ISA = qw(Exporter); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. # This allows declaration use P2P::pDonkey ':all'; # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK # will save memory. our %EXPORT_TAGS = ( 'all' => [ qw( MT_KNOWNMET MT_PARTMET MT_SERVERMET unpackServerDesc packServerDesc printServerDesc makeServerDesc unpackServerDescList packServerDescList printServerDescList unpackServerDescListU packServerDescListU printServerDescListU unpackServerMet packServerMet printServerMet readServerMet writeServerMet unpackPartMet packPartMet printPartMet readPartMet writePartMet unpackKnownMet packKnownMet printKnownMet readKnownMet writeKnownMet unpackPrefMet packPrefMet printPrefMet readPrefMet writePrefMet readFile writeFile ) ], 'server' => [ qw( unpackServerDesc packServerDesc printServerDesc makeServerDesc unpackServerDescList packServerDescList printServerDescList unpackServerDescListU packServerDescListU printServerDescListU unpackServerMet packServerMet printServerMet readServerMet writeServerMet ) ], 'part' => [ qw( unpackPartMet packPartMet printPartMet readPartMet writePartMet ) ], 'known' => [ qw( unpackKnownMet packKnownMet printKnownMet readKnownMet writeKnownMet ) ], 'pref' => [ qw( unpackPrefMet packPrefMet printPrefMet readPrefMet writePrefMet ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( ); use Carp; use Data::Hexdumper; use P2P::pDonkey::Meta ':all'; use P2P::pDonkey::Util qw( ip2addr ); my $debug = 0; # Preloaded methods go here. use constant MT_SERVERMET => 0x0e; use constant MT_PARTMET => 0xe1; use constant MT_KNOWNMET => 0x0e; sub readFile { my ($fname, $tag) = @_; my ($handle, $buf); my $rs = $/; undef $/; open($handle, "<$fname") or warn "Can't open '$fname': $!\n" and $/ = $rs and return; binmode($handle); if ($tag) { if (read($handle, $buf, 1) != 1 || unpack('C',$buf) != $tag) { warn "File '$fname' without tag!\n"; close($handle); $/ = $rs; return; } $buf .= <$handle>; } else { $buf = <$handle>; } close($handle); $/ = $rs; return \$buf; }; sub writeFile($$) { my ($fname, $buf) = @_; my $handle; open($handle, ">$fname") or warn "Can't open `$fname': $!\n" and return; binmode($handle); print $handle $$buf; close($handle); return 1; }; # ----------------------------------------------------------------------------- # server.met sub unpackServerDesc { my ($ip, $port, $meta); ($ip, $port) = &unpackAddr or return; $meta = &unpackMetaListU or return; # Hash is for compatibility with Info structure return {Hash => '01234567012345670123456701234567', IP => $ip, Port => $port, Meta => $meta}; } sub packServerDesc { my ($d) = @_; return packAddr($d) . packMetaListU($d->{Meta}); } sub printServerDesc { my ($d) = @_; printAddr($d); print "\n"; printMetaListU($d->{Meta}); } sub makeServerDesc { my ($ip, $port, $name, $desc, $nusers, $nfiles, $preference) = @_; defined($ip) && defined($port) or confess "Specify ip and port of server!"; $name or $name = ''; $desc or $desc = ''; $preference or $preference = 0; my %meta; tie %meta, "Tie::IxHash"; $meta{Name} = makeMeta(TT_NAME, $name); $meta{Description} = makeMeta(TT_DESCRIPTION, $desc); $meta{IP} = makeMeta(TT_IP, $ip); $meta{Port} = makeMeta(TT_PORT, $port); $meta{users} = makeMeta(TT_UNDEFINED, $nusers, "users", VT_INTEGER) if defined $nusers; $meta{files} = makeMeta(TT_UNDEFINED, $nfiles, "files", VT_INTEGER) if defined $nfiles; $meta{Preference} = makeMeta(TT_PREFERENCE, $preference); return {Hash => '01234567012345670123456701234567', IP => $ip, Port => $port, Meta => \%meta}; } sub unpackServerDescList { my ($n, @l, $d); defined($n = &unpackD) or return; @l = (); while ($n--) { $d = &unpackServerDesc or return; push @l, $d; } return \@l; } sub packServerDescList { my ($l) = @_; my ($res); $res = packD(scalar @$l); foreach my $d (@$l) { $res .= packServerDesc($d); } return $res; } sub printServerDescList { foreach my $d (@{$_[0]}) { printServerDesc($d); } } sub unpackServerDescListU { my ($n, %l, $d); tie %l, "Tie::IxHash"; defined($n = &unpackD) or return; %l = (); while ($n--) { $d = &unpackServerDesc or return; $l{idAddr($d)} = $d; } return \%l; } sub packServerDescListU { my ($res, $d); my $n = 0; $res = ''; while ((undef, $d) = each %{$_[0]}) { $res .= packServerDesc($d); $n++; } return packD($n) . $res; } sub printServerDescListU { my $d; while ((undef, $d) = each %{$_[0]}) { printServerDesc($d); } } sub unpackServerMet { &unpackB == MT_SERVERMET or return; return &unpackServerDescListU; } sub packServerMet { return packB(MT_SERVERMET) . &packServerDescListU; } sub printServerMet { &printServerDescListU; } # parse server.met file && create hash sub readServerMet { my ($fname) = @_; my ($off, $buf, $res); $buf = readFile($fname, MT_SERVERMET) or return; $off = 0; $res = unpackServerMet($$buf, $off); if ($res && $off != length $$buf) { warn "Unhandled bytes at the end:\n", hexdump(data=>$$buf, start_position=>$off); } return $res; } sub writeServerMet { my ($fname, $servers) = @_; my $buf = packServerMet($servers); return writeFile($fname, \$buf); } # ----------------------------------------------------------------------------- # .part.met sub unpackPartMet { my $v = &unpackB; $v == MT_PARTMET or return; return &unpackFileInfo; } sub packPartMet { return packB(MT_PARTMET) . &packFileInfo; } sub printPartMet { &printInfo; } sub readPartMet { my ($fname) = @_; my ($off, $buf, $res); $buf = readFile($fname, MT_PARTMET) or return; $off = 0; $res = unpackPartMet($$buf, $off); $res->{Path} = $fname; if ($res && $off != length $$buf) { warn "Unhandled bytes at the end:\n", hexdump(data=>$$buf, start_position=>$off); } return $res; } sub writePartMet { my ($fname, $p) = @_; my $buf = packPartMet($p); return writeFile($fname, \$buf); } # ----------------------------------------------------------------------------- # known.met sub unpackKnownMet { &unpackB == MT_KNOWNMET or return; return &unpackFileInfoList; } sub packKnownMet { return packB(MT_KNOWNMET) . &packFileInfoList; } sub printKnownMet { &printInfoList; } sub readKnownMet { my ($fname) = @_; my ($off, $buf, $res); $buf = readFile($fname, MT_KNOWNMET) or return; $off = 0; $res = unpackKnownMet($$buf, $off); if ($res && $off != length $$buf) { warn "Unhandled bytes at the end:\n", hexdump(data=>$$buf, start_position=>$off); } return $res; } sub writeKnownMet { my ($fname, $p) = @_; my $buf = packKnownMet($p); return writeFile($fname, \$buf); } # ----------------------------------------------------------------------------- # pref.met sub unpackPrefMet { my ($ip, $port, $hash, $meta, $pref, $name, $m); ($ip, $port) = &unpackAddr or return; $hash = &unpackHash or return; $meta = &unpackMetaListU or return; $pref = &unpackMetaListU or return; return {IP => $ip, Port => $port, Hash => $hash, Meta => $meta, Pref => $pref}; } sub packPrefMet { my ($p) = @_; return packAddr($p) . packHash($p->{Hash}) . packMetaListU($p->{Meta}) . packMetaListU($p->{Pref}); } sub printPrefMet { my ($d) = @_; print "Address: "; printAddr($d); print "\n"; print "Hash: $d->{Hash}\n"; print "Meta:\n"; printMetaListU($d->{Meta}); print "Preferencies:\n"; printMetaListU($d->{Pref}); } sub readPrefMet { my ($fname) = @_; my ($off, $buf, $res); $buf = readFile($fname) or return; $off = 0; $res = unpackPrefMet($$buf, $off); if ($res && $off != length $$buf) { warn "Unhandled bytes at the end:\n", hexdump(data=>$$buf, start_position=>$off); } return $res; } sub writePrefMet { my ($fname, $p) = @_; my $buf = packPrefMet($p); return writeFile($fname, \$buf); } 1; __END__