by Hippo2000(2000/12/24)
DBI::ProxyServerの親、RPC::PlServerなのです。Java RMIに対応するようなものだということです。
作者はJochen Wiedmannさんです。それにしても、この方は色々なものを作っています。
Jochen Wiedmannさんにはメールで了解をいただきました。
なお内容等が間違っていたら修正します。ご連絡ください。
RPC::PlServer - PlRPCサーバーを書くためのPerl拡張
# RPC::PlServerのサブクラスを作成する use RPC::PlServer;
package MyServer; $MyServer::VERSION = '0.01'; @MyServer::ISA = qw(RPC::PlServer);
# Run()メソッドを1つの接続を扱うようにオーバーライト
sub Run {
my $self = shift;
my $socket = $self->{'socket'};
}
# MyServerクラスのインスタンスの作成
package main;
my $server = MyServer->new({'localport' => '1234'}, \@ARGV);
# 実際に実行させるポートいバインドする $server->Bind();
PlRPC (Perl RPC) は完全にPerlによってかかれたサーバーとクライントを実装するためのパッケージです。この名前はSunのRPC(Remote Procedure Call)から借りてきましたが、JavaのRMI("Remote Method Interface")と同じぐらいよいものになるかもしれません。というのもPlRPCは非常に簡単なやり方でPerlのOOフレームワークの完全なパワーを与えるからです。
RPC::PlServerはサーバー側で使われるパッケージです、RPC::PlClientがなんのためのものかはお分かりでしょう。両方のパッケージはRPC::PlServer::Commを通信のために共有しています。これらの部分についてはPlRPC::Client(3) と RPC::PlServer::Comm をご覧ください。
PlRPCはクライアントによって実行されるであろうメソッドのセットを定義することにより稼動します。例えばサーバーはメソッド "multply" をクライアントに提供するとします。そうすると関数の呼出しはクライアントでは以下のようになります。
@result = $client->multiply($a, $b);
これはサーバーでは以下のように対応する呼出しに対応づけられます
@result = $server->multiply($a, $b);
引数と結果はサーバーへ、あるいはサーバーから自動的に魔法で転送されます。(この魔法はPerlでの名前を持っています:それはStorableモジュールです。この素晴らしいパッケージについてRaphael Manfrediに感謝します)。簡単でしょ? :-)
RPC::PlServer と RPC::PlClient は抽象的なサーバーとクライアントです: 独自のクラスを派生させる必要があります。
RPC::PlServerはNet::Daemonのオプションと属性をすべて継承しており、さらに以下のものを追加します。
完全にPerlの例外をベースとしているので、RPCパッケージでのエラーの取扱いはとても簡単です。そのため典型的なコードは以下のようになります:
eval {
# ここで何かをします。エラーについて何も注意しません
...
};
if ($@) {
# エラー発生
...
}
my $server = RPC::PlServer(\%options, \@args);
(クラス・メソッド) このコンストラクタはNet::Daemonパッケージからそのまま継承されています。詳しくは Net::Daemon(3) をご覧ください。
$ok = $self->AcceptApplication($app); $ok = $self->AcceptVersion($version); $ok = $self->AcceptUser($user, $password);
RPC::PlServerパッケージはとても細かなアクセス制御スキームを持っています:まず最初にNet::Daemonのホストをベースとしたアクセス制御を継承しています。それはバージョン制御とユーザー認証も加えています。これを実現するために、Net::Daemonからのメソッド Accept は3つのメソッドに分割されています。AcceptApplication, AcceptVersion and AcceptUser のそれぞれは、TRUEまたはFALSEを返します。クライアントはその引数をapplication, version, user そして password. として羽k取ります。クライアントは上記のメソッドすべてがTRUEを返すときだけ受け付けられます。
デフォルトの実装では以下のようになります: $self が $app のサブクラスであれば、AcceptApplicationはTRUEを返します。AcceptVersionは、要求されたバージョンが${$class}::VERSION 以下であればTRUEを返します。ユーザーが接続を許されるかどうかはクライアント構成設定によります。例は 構成設定ファイル をご覧ください。
クライアントに任意のメソッドを呼び出す能力を与えることは、恐ろしいセキュリティホールになりかねません。そのためサーバーはmethods 属性を持っています。これはクラス名をキーに、値はメソッド名をキーとしたハッシュのリファレンスとするハッシュのリファレンスです。つまり以下のようなハッシュだったとします:
$self->{'methods'} = {
'CalcServer' => {
'NewHandle' => 1,
'CallMethod' => 1 },
'Calculator' => {
'new' => 1,
'multiply' => 1,
'add' => 1,
'divide' => 1,
'subtract' => 1 }
};
このときクライアントがオブジェクトを作るためにCalcServerのNewHandle メソッドを使うことができますが、許可されたコンストラクタ Calculator->newを介する場合のみです。一度、Calculatorが作成されると、サーバーはメソッドをmultiply、add、divide、subtractを呼び出すことができます。
サーバーの構成設定ファイル(config file)はNet::Daemonから継承されています。users と cipher 属性をクライアント・リストに追加しています。このため典型的な構成設定ファイルは以下のようになります:
# Load external modules; this is not required unless you use
# the chroot() option.
#require DBD::mysql;
#require DBD::CSV;
# キーの作成
my $myhost_key = Crypt::IDEA->new('83fbd23390ade239');
my $bob_key = Crypt::IDEA->new('be39893df23f98a2');
{
# 'chroot' => '/var/dbiproxy',
'facility' => 'daemon',
'pidfile' => '/var/dbiproxy/dbiproxy.pid',
'user' => 'nobody',
'group' => 'nobody',
'localport' => '1003',
'mode' => 'fork',
# アクセス制御
'clients' => [
# ローカル LAN (192.168.1.*)を受け付ける
{
'mask' => '^192\.168\.1\.\d+$',
'accept' => 1,
'users' => [ 'bob', 'jim' ],
'cipher' => $myhost_key
},
# myhost.company.com を受け付ける
{
'mask' => '^myhost\.company\.com$',
'accept' => 1,
'users' => [ {
'name' => 'bob',
'cipher' => $bob_key
} ]
},
# その他は受け付けない
{
'mask' => '.*',
'accept' => 0
}
]
}
気をつけなければならないこと:192.168.1*のユーザーリストにはスカラー値が入っていますが、myhost.company.comのユーザリストにはハッシュへのリファレンスが入っています;これはユーザーの構成設定はユーザー・ベースの暗号化になっているので、これは必要です。
十分に時間を使ったので、言葉ではなく例を展開しましょう :-)。MD5ダイジェストのためのサーバーという簡単なサーバーを書きましょう。このサーバーは外部パッケージ MD5を使いますが、クライアントにはこのパッケージ MD5 をインストールする必要はありません。ここではサーバーのソースを示します。クライアントの部分はRPC::PlClient manページにあります。 RPC::PlClient(3). をご覧ください。
#!/usr/bin/perl -wT
# -T スィッチに注意してください! これはPerlサーバーには常に推奨されます。
use strict; # つねによい選択です.
require RPC::PlServer;
require MD5;
package MD5_Server; # クライアントはアプリケーション "MD5_Server"を
# 要求する必要があります
$MD5_Server::VERSION = '1.0'; # もしバージョン 1.1を要求するのであれば、
# クライアントは拒絶されます
@MD5_Server::ISA = qw(RPC::PlServer);
eval {
# 以下のサーバーオプションは構成設定フィル(config file)またはコマンドラインで
# 上書きすることができます。
my $server = MD5_Server->new({
'pidfile' => '/var/run/md5serv.pid',
'configfile' => '/etc/md5serv.conf',
'facility' => 'daemon', # Default
'user' => 'nobody',
'group' => 'nobody',
'localport' => 2000,
'logfile' => 0, # Use syslog
'mode' => 'fork', # Recommended for Unix
'methods' => {
'MD5_Server' => {
'ClientObject' => 1,
'CallMethod' => 1,
'NewHandle' => 1
},
'MD5' => {
'new' => 1,
'add' => 1,
'hexdigest' => 1
},
}
});
$server->Bind();
};
いわなければならないことがあります:PlRPCをベースとしたサーバーは潜在的にセキュリティに問題があります! 私はセキュリティ問題を避けるために全力を尽くしてきましたが、何かを落としているかもしれません。セキュリティは設計の結果1つですが、設計の結果だけではありません。(よく知られている問題ですが...)
以下の設計原則を強くお勧めします:
(原文のまま)
The PlRPC-modules are
Copyright (C) 1998, Jochen Wiedmann
Am Eisteich 9
72555 Metzingen
Germany
Phone: +49 7123 14887
Email: joe@ispsoft.de
All rights reserved.
You may distribute this package under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file.
RPC::PlClient(3), RPC::PlServer::Comm(3), Net::Daemon(3), Net::Daemon::Log(3), Storable(3), Sys::Syslog(3), Win32::EventLog(3)
アプリケーションの例として DBI::ProxyServer(3) をご覧ください。
ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。