2005 年 12 月 31 日 23 時 10 分

仮開通


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


いよいよ今年も最後になった。今日中に開通できるか。

PASV コマンドを引き金として、UPnPNT で登録する。
前作ったループの中身を書き換えてみよう。
TcpConsole も使って行単位の送受信を行う。

    TcpConsole *client, *server;
    bool pasvReceived = false;

ループの中身はこんな感じに変更。

    if (index == 0) { // client

        const char *command = client->Read();
        if (command == NULL) break; // disconnected

        // PASV 要求の検出
        if (IsEqualFtpCommand(command, "PASV")) {
            pasvReceived = true;
        }

    } else { // server

        const char *command = server->Read();
        if (command == NULL) break; // disconnected

        // PASV にサーバが成功コード 2xx を返したか。
        if (pasvReceived && command[0] == '2') {

            // PASV の応答を読み取り待機アドレスを得る。
            sockaddr_in dtpAddr;
            if (ParsePasvAddress(command, &dtpAddr)) {

                // UPnPNAT オブジェクトを利用して登録。
                sockaddr_in mappedAddr;
                RegisterPortMapping(dtpAddr, &mappedAddr);

                // 登録した外部アドレスで返答する
                u_short port = ntohs(mappedAddr.sin_port);
                char buffer[256];
                sprintf(buffer,
                  "227 Entering Passive Mode"
                  " (%d,%d,%d,%d,%d,%d)",
                  (int)mappedAddr.sin_addr.S_un.S_un_b.s_b1,
                  (int)mappedAddr.sin_addr.S_un.S_un_b.s_b2,
                  (int)mappedAddr.sin_addr.S_un.S_un_b.s_b3,
                  (int)mappedAddr.sin_addr.S_un.S_un_b.s_b4,
                  (int)(port >> 8),
                  (int)(port & 0xff);

                client->Write(buffer);

            } else {

                // 解析できない場合はそのまま転送。
                client->Write(command);
            }

        } else {

            // その他の応答行はそのまま転送。
            client->Write(command);
        }

        pasvReceived = false;

    }

さて、テスト。

# telnet <server> <port>
<=P 220 Microsoft FTP Service
C=> USER <user>
<=P 331 Password required for <user>.
C=> PASS <password>
<=P 230 User <user> logged in.
C=> PASV
<=P 227 Entering Passive Mode (222,x,x,x,7,23).

ここでもう一つ telnet を立ち上げる。
# telnet 222.x.x.x 1815

メインの方で
C=> LIST
P<= 150 Opening ASCII mode data connection for /bin/ls.
P<= 226 Transfer complete.

OK。サブの方にファイル一覧が表示された。
どうやらうまく動いているようだ。
ただ、繰り返すとルータの NAT エントリを使い尽くすので、
クリーンアップする方法を考えないといけない。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.