最近の記事
- 9/1 - 将棋始めました
- 5/16 - サーバー引っ越し
- 4/24 - 優先順位
- 3/17 - vbNullString と 空文字列 ""
- 3/15 - InputBox 関数の戻り値
- 3/13 - 紙と Excel と VBA
- 3/9 - 未だに Visual Basic 6
- 11/14 - ぼて閉鎖
- 11/9 - 関数オブジェクトの呼び出し
- 9/7 - メソッドとしての関数オブジェクト
Entering Passive Mode
いよいよこの日がやってきた。
デバッグで正常に動作することを確認できたので、
サービスの皮を被せてリリースビルドを行う。
開発機にサービスとしてインストールしてテスト、OK!
いよいよ本番稼動機に仕込む。
サービスをインストールした後、UPnP を利用するため、
Windows コンポーネントの追加と削除を開き、
ネットワークサービスの
「インターネットゲートウェイデバイスの検出とクライアントの制御」「UPnP ユーザインタフェース」をインストール。
SSDP Discovery Service サービスを有効にしておく。
ADSL モデムの静的 NAPT でポートを外部に公開。
今日もあまり時間がない……
取り合えずコントロール接続の内容を
デバッグウィンドウに吐き出すように設定
便利な API があるもんだ。
OutputDebugString(command);
そして昨日と同じように接続テスト。
……あれ? 何も流れない?
本職の方が無茶苦茶忙しかったため、
今日はほとんど時間がない。
そんな中、昼休みを利用してテストをしてきました。
AirStation は自宅にないので。
幸い会社のルータも UPnPNT に対応していたので、
ログを吐き出すコードを追加し、
ビルドしてデスクトップ機でデバッグ実行。
デスクトップ機のプロキシポートを
ルータに静的 NAPT 登録して外部に公開し、
AIREDGE カードを利用して外部から接続してみる。
方針も決まったことだし、実装に行こう。
まずはサクっとデータ待機スレッドを実装する。
これは前に作ったコントロール待機スレッドと変わらない。
Socket を作成して Bind, Listen、
auto_ptr<Socket> listener(new Socket(AF_INET, SOCK_STREAM));
listener->Bind(localAddr);
listener->Listen(2);
スレッドとオブジェクト指向の間で悩ましいことがある。
実装上の壁ではないので、大きな悩みではないけれど、
今回は趣味の範囲だし、とことん偏執してみよう。
現在、スレッドはクラスとして実装している。
Thread クラスを継承してスレッドを実装する仕組みだ。
派生クラスは new に引数を渡して作成して実行される。
delete で削除すると、スレッドも強制的に終了される。
Shutdown メソッドで終了の同期を取ることもできる。
今回の場合、listener(L) ソケットを持つスレッドは、
クライアントからの接続を受信すると、
接続を受理して新しいセッション用のソケットを作成し、
新しい session(S) 用のスレッドを作成して実行する。
データ接続をどのように実装するか。
コントロール接続とデータ接続を同時に扱う必要があるので、
素直にスレッド化したほうがよさそうだ。
PASV に対してサーバがポートを開くので、
プロキシも新しいポートを開いて待機する。
クライアントからの接続を処理するために、
データ接続用の待機スレッドを作成しておく。
UPnPNT で登録するのはプロキシのアドレスであり、
クライアントに返信するのはプロキシの外部アドレス。
また、待機スレッドを終了させるときに、
プロキシの外部アドレスを登録解除すると効率が良い。
LinkStation のような FTP 実装に対応するには、
データ接続もプロキシが媒介する必要がある。
さて、もう一度 PASV 対応を考えてみよう。
大文字はグローバル、小文字はプライベート IP/Port
R: リモートホスト(クライアント)
P: プロキシコントロール IP/Port
S: サーバコントロール IP/Port
X: プロキシデータ IP/Port
Y: サーバデータ IP/Port
静: 静的 NAPT ルール
動: 動的 NAPT ルール
調査のつづきをしたが、
前回の推測でほぼ間違いないようだ。
これを回避するためには、
データ接続も、プロキシが媒介する必要がある。
逆に言うと、データセッションを監視できるので、
UPnPNT の登録解除もできるかもしれない。
FTP プロキシの接続のテストをしているうちに、
意外な事実が判明した。
色々なサーバでテストしようと思い、
BUFFALO の LinkStation の FTP 機能を有効にして、
プロキシのテストをしてみた。すると繋がらない。
色々調べてみると、どうやらサーバから見て、
コントロール接続の相手先 IP アドレスと、
データ接続の相手先 IP アドレスが異なる場合、
サーバがデータ接続を拒否するらしい。
いよいよ今年も最後になった。今日中に開通できるか。
PASV コマンドを引き金として、UPnPNT で登録する。
前作ったループの中身を書き換えてみよう。
TcpConsole も使って行単位の送受信を行う。
TcpConsole *client, *server;
bool pasvReceived = false;
ループの中身はこんな感じに変更。