| Net-FreeDB2 documentation | Contained in the Net-FreeDB2 distribution. |
Net::FreeDB2::Connection::CDDBP - FreeDB/CDDB concrete connection class using the CDDBP protocol
See Net::FreeDB2.
Net::FreeDB2::Connection::CDDBP is an implementation of the abstract FreeDB/CDDB connection class. It uses the CDDBP protocol to connect to FreeDB/CDDB servers.
Implementation of Net::FreeDB2::Connection::new.
Restriction: proxy_host may not be specified as CDDBP access through proxy is not (yet) implemented.
Throws a Error::Simple exception if a mandatory option is missing and passes exceptions from connect ().
Implementation of Net::FreeDB2::Connection::connect. Stores a signo on response using setSignOnResponse ().
Implementation of Net::FreeDB2::Connection::lscat.
Implementation of Net::FreeDB2::Connection::query.
Implementation of Net::FreeDB2::Connection::read.
Implementation of Net::FreeDB2::Connection::write.
Implementation of Net::FreeDB2::Connection::log.
Implementation of Net::FreeDB2::Connection::motd.
Implementation of Net::FreeDB2::Connection::discid.
Implementation of Net::FreeDB2::Connection::proto.
Implementation of Net::FreeDB2::Connection::sites.
Implementation of Net::FreeDB2::Connection::stat.
Implementation of Net::FreeDB2::Connection::ver.
Implementation of Net::FreeDB2::Connection::update.
Implementation of Net::FreeDB2::Connection::whom.
Set the FreeDB/CDDB sign-on response. VALUE is the value.
Returns the FreeDB/CDDB sign-on response.
Implementation of Net::FreeDB2::Connection::setProxyHost. Throws an exception because proxy_host may not be specified as CDDBP access through proxy is not (yet) implemented.
PRIVATE METHOD. Sends the hello to FreeDB/CDDB server.
PRIVATE METHOD. Sends the quit to FreeDB/CDDB server.
PRIVATE METHOD. Executes command in CMD and waits for a reply. CODE_RX specifies 1) the allowed FreeDB/CDDB codes and 2) the regular expression that determins the termination of the returned output.
PRIVATE METHOD. Makes the a FreeDB/CDDB CDDBP hello string.
FreeDB/CDDB command methods lscat (), query (), read (), write (), log (), motd (), discid (), proto (), sites (), stat (), ver (), update () and whom () throw an Error::Simple exception in cases of connection errors and unexpected situations in the data format.
Net::FreeDB2::Entry, Net::FreeDB2::Match, Net::FreeDB2::Response, Net::FreeDB2::Response::Query and Net::FreeDB2::Response::Read
Not all FreeDB/CDDB commands are implemented (yet).
First development: September 2002
Vincenzo Zocca <Vincenzo@Zocca.com>
Copyright 2002, Vincenzo Zocca.
This file is part of the Net::FreeDB2 module hierarchy for Perl by
Vincenzo Zocca.
The Net::FreeDB2 module hierarchy is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
The Net::FreeDB2 module hierarchy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with the Net::FreeDB2 module hierarchy; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
| Net-FreeDB2 documentation | Contained in the Net-FreeDB2 distribution. |
package Net::FreeDB2::Connection::CDDBP; # Copyright 2002, Vincenzo Zocca. # See LICENSE section for usage and distribution rights. require 5.005_62; use strict; use warnings; use Error qw (:try); require Exporter; use AutoLoader qw(AUTOLOAD); #our @ISA = qw(Net::FreeDB2::Connection Exporter); use base qw(Net::FreeDB2::Connection 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 Net::FreeDB2::Connection::CDDBP ':all'; # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK # will save memory. our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( ); our ( $VERSION ) = '$Revision: 0.8.2.4 $ ' =~ /\$Revision:\s+([^\s]+)/; my $FINAL_EOL_RX = '[\r\n]'; my $FINAL_DOT_RX = '[\r\n]\.[\r\n]'; sub new { # Call constructor of super class my $self = &Net::FreeDB2::Connection::new (@_); # Shift out this class specification shift; # Return object return ($self); } sub _initialize { my $self = shift; # Get options my $opt = shift || {}; # Proxy on CDDBP not yet defined defined ($opt->{proxy_host}) && throw Error::Simple ("ERROR: Net::FreeDB2::Connection::CDDBP::_initialize, CDDBP access through proxy not (yet) implemented."); # Initialize super class return ($self->SUPER::_initialize ($opt)); } sub connect { my $self = shift; # Make socket connection use IO::Socket::INET; my $connection = IO::Socket::INET->new ( PeerAddr => $self->getFreeDBHost (), PeerPort => $self->getFreeDBPort () || 8880, ); defined ($connection) || throw Error::Simple ('ERROR: Net::FreeDB2::Connection::CDDBP::connect, Failed to instanciate an \'IO::Socket::INET\' object.'); # Set the connection $self->setConnection ($connection); # Send command and wait for reply my $content_ref = $self->waitCommandReply (undef, { 200 => $FINAL_EOL_RX, 201 => $FINAL_EOL_RX, 432 => $FINAL_EOL_RX, 433 => $FINAL_EOL_RX, 434 => $FINAL_EOL_RX, }); # Parse the result and store it use Net::FreeDB2::Response::SignOn; $self->setSignOnResponse (Net::FreeDB2::Response::SignOn->new ({ content_ref => $content_ref })); # Send a hello my $res = $self->hello (); # Disconnect and throw exception if error if ($res->hasError ()) { $self->setConnection (); throw Error::Simple ('ERROR: Net::FreeDB2::Connection::CDDBP::connect, handshake failed.'); } } sub lscat { my $self = shift; # Send command and wait for reply my $content_ref = $self->waitCommandReply ('cddb lscat', { 210 => $FINAL_DOT_RX, }); # Parse the result my @content = split (/[\n\r]+/, ${$content_ref}); shift (@content); my @cat = (); foreach my $cat (@content) { last if ($cat eq '.'); push (@cat, $cat); } return (@cat); } sub query { my $self = shift; my $entity = shift; # Send command and wait for reply my $cmd = 'cddb query ' . $entity->mkQuery (); my $content_ref = $self->waitCommandReply ($cmd, { 200 => $FINAL_EOL_RX, 211 => $FINAL_DOT_RX, 202 => $FINAL_EOL_RX, 403 => $FINAL_EOL_RX, 409 => $FINAL_EOL_RX, }); # Parse the result use Net::FreeDB2::Response::Query; return Net::FreeDB2::Response::Query->new ({ content_ref => $content_ref, }); } sub read { my $self = shift; my $match = shift; # Send command and wait for reply my $cmd = 'cddb read ' . $match->getCateg () . ' ' . $match->getDiscid (); my $content_ref = $self->waitCommandReply ($cmd, { 210 => $FINAL_DOT_RX, 401 => $FINAL_EOL_RX, 402 => $FINAL_EOL_RX, 403 => $FINAL_EOL_RX, 409 => $FINAL_EOL_RX, }); # Parse the result use Net::FreeDB2::Response::Read; return Net::FreeDB2::Response::Read->new ({ content_ref => $content_ref, }); } sub write { throw Error::Simple ("ERROR: Net::FreeDB2::Connection::CDDBP::write, to be implemented."); } sub log { throw Error::Simple ("ERROR: Net::FreeDB2::CDDBP::log, to be implemented."); } sub motd { my $self = shift; # Send command and wait for reply my $content_ref = $self->waitCommandReply ('motd', { 210 => $FINAL_DOT_RX, 401 => $FINAL_EOL_RX, }); # Parse the result my @content = split (/[\n\r]+/, ${$content_ref}); my $head = shift (@content); my @motd = (); foreach my $motd (@content) { last if ($motd eq '.'); push (@motd, $motd); } return (@motd); } sub discid { my $self = shift; my $entity = shift; # Send command and wait for reply my $cmd = 'discid ' . $entity->mkQuery (); my $content_ref = $self->waitCommandReply ($cmd, { 200 => $FINAL_EOL_RX, 500 => $FINAL_EOL_RX, }); # Parse the result my @content = split (/[\n\r]+/, ${$content_ref}); my $head = shift (@content); my ($code) = $head =~ /^\s*(\d{3})\s+/; $code == 500 && throw Error::Simple ("ERROR: Net::FreeDB2::Connection::CDDBP::discid, Command Syntax error."); my @head = split (/\s+/, $head); return ($head[4]); } sub proto { throw Error::Simple ("ERROR: Net::FreeDB2::CDDBP::proto, to be implemented."); } sub sites { my $self = shift; # Send command and wait for reply my $content_ref = $self->waitCommandReply ('sites', { 210 => $FINAL_DOT_RX, 401 => $FINAL_EOL_RX, }); # Parse the result use Net::FreeDB2::Response::Sites; return Net::FreeDB2::Response::Sites->new ({ content_ref => $content_ref, }); } sub stat { throw Error::Simple ("ERROR: Net::FreeDB2::CDDBP::stat, to be implemented."); } sub ver { throw Error::Simple ("ERROR: Net::FreeDB2::CDDBP::ver, to be implemented."); } sub update { throw Error::Simple ("ERROR: Net::FreeDB2::CDDBP::update, to be implemented."); } sub whom { throw Error::Simple ("ERROR: Net::FreeDB2::CDDBP::whom, to be implemented."); } sub setSignOnResponse { my $self = shift; # Set FreeDB/CDDB sign-on response $self->{Net_FreeDB2_Connection_CDDBP}{sign_on_response} = shift; } sub getSignOnResponse { my $self = shift; # Return FreeDB/CDDB sign-on response return ($self->{Net_FreeDB2_Connection_CDDBP}{sign_on_response}); } sub hello { my $self = shift; # Send command and wait for reply my $cmd = 'cddb ' . $self->mkHello (); my $content_ref = $self->waitCommandReply ($cmd, { 200 => $FINAL_EOL_RX, 431 => $FINAL_EOL_RX, 402 => $FINAL_EOL_RX, }); # Parse the result and return it use Net::FreeDB2::Response::Hello; return (Net::FreeDB2::Response::Hello->new ({ content_ref => $content_ref })); } sub quit { my $self = shift; # Send command and wait for reply my $content_ref = $self->waitCommandReply ('quit', { 230 => $FINAL_EOL_RX, }); # Disconnect $self->setConnection (); } sub waitCommandReply { my $self = shift; my $cmd = shift; my $rx = shift; # Check if connection is defined defined ($self->getConnection ()) || throw Error::Simple ('ERROR: Net::FreeDB2::Connection::CDDBP::waitCommandReply, no connection available.'); # Set blocking $self->getConnection->blocking (1); # Send command defined ($cmd) && $self->getConnection ()->write ($cmd . "\r\n"); # Wait for code $self->getConnection->read (my $head, 5); $head =~ s/^\s+//; my ($code) = $head =~ /(\d{3})/; exists ($rx->{$code}) || throw Error::Simple ("ERROR: Net::FreeDB2::Connection::CDDBP::waitCommandReply, unknown code '$code' returned."); # Wait for the final DOT or EOL my $content .= $head; $self->getConnection->blocking (0); while (1) { $self->getConnection->read (my $rest, 1024); $content .= $rest; $content =~ /$rx->{$code}/ && last; sleep (1); } # Return the content reference return (\$content); } sub mkHello { my $self = shift; defined ($self->getClientName ()) || throw Error::Simple ('ERROR: Net::FreeDB2::Connection::CDDBP::mkHello, \'client_name\' not set.'); defined ($self->getClientVersion ()) || throw Error::Simple ('ERROR: Net::FreeDB2::Connection::CDDBP::mkHello, \'client_version\' not set.'); defined ($self->getClientHost ()) || throw Error::Simple ('ERROR: Net::FreeDB2::Connection::CDDBP::mkHello, \'client_host\' not set.'); defined ($self->getClientUser ()) || throw Error::Simple ('ERROR: Net::FreeDB2::Connection::CDDBP::mkHello, \'client_user\' not set.'); return ('hello ' . join (' ', $self->getClientUser (), $self->getClientHost (), $self->getClientName (), $self->getClientVersion (), ) ); } 1; __END__ # Below is stub documentation for your module. You better edit it!