#!/usr/bin/perl

=head1 NAME

CSSJ::Driver - CSSJドライバ

=head2 依存モジュール

use strict;
use Exporter;
use Symbol;
use Socket;
use File::Temp;

=head2 概要

ドライバの窓口となる関数群です。

=head2 作者

$Date: 2006/03/30 08:55:03 $ MIYABE Tatsuhiko

=cut
package CSSJ::Driver;
require CSSJ::CTIP;
use CSSJ::Session;

require Exporter;
@ISA	= qw(Exporter);
@EXPORT_OK	= qw(create_driver_for);

use strict;
use Socket;

=head1 create_driver_for

C<create_driver_for HOST PORT [ENCODING]>

指定されたホスト・ポートに接続するためのドライバを返します。

=head2 パラメータ

=over

=item HOST 接続先ホスト

=item PORT 接続先ポート

=item ENCODING 文字のやりとりに使うキャラクタ・エンコーディング名

=back

=head2 戻り値

B<CSSJ::Driver>

=cut
sub create_driver_for ($$;$) {
  my $host = shift;
  my $port = shift;
  my $encoding = shift || "ISO-8859-1";
  
  return new CSSJ::Driver($host, $port, $encoding);
}

=head1 CSSJ::Driver

C<new CSSJ::Driver HOST PORT ENCODING>

ドライバのコンストラクタです。

ドライバの作成は通常CSSJ::Driver::create_driver_forで行うため、
ユーザーがコンストラクタを直接呼び出す必要はありません。

=head2 パラメータ

=over

=item HOST 接続先ホスト

=item PORT 接続先ポート

=item ENCODING 文字のやりとりに使うキャラクタ・エンコーディング名

=back

=cut
sub new {
  my $class = shift;
  my $self = {
    'host' => $_[0],
    'port' => $_[1],
    'encoding' => $_[2]
  };
  
  bless $self, $class;
  return $self;
}

=head1 CSSJ::Driver->create_session

C<create_session USER PASSWORD>

セッションを作成します。

=head2 パラメータ

=over

=item USER ユーザーID

=item PASSWORD パスワード

=back

=head2 戻り値

B<CSSJ::Session,エラーの場合はundef>

=cut
sub create_session ($$$) {
  my $self = shift;
  my ($user,$password) = @_;
  
  my $address = inet_aton($self->{host});
  my $port_address = sockaddr_in($self->{port}, $address);
  my $protocol = getprotobyname('tcp');
  
  socket(FP, PF_INET, SOCK_STREAM, $protocol) or return undef;
  connect(FP, $port_address) or return undef;
  CSSJ::CTIP::connect(FP, $self->{encoding}) or return undef;
  CSSJ::CTIP::req_property(FP, 'ctip.auth', 'PLAIN:'.$user.chr(0x0A).$password) or return undef;
  my %response = CSSJ::CTIP::res_next(FP);
  if(! %response) { return undef; }
  $response{type} == CSSJ::CTIP::RES_ERROR or (warn('Bad response') and return undef);
  $response{error} == 'OK' or (warn('Authentication failed') and return undef);
  return new CSSJ::Session(*FP);
}

