2009-05-28 11 views
2

私は、SSLで使用されるチャンネルからクリーンなデータを取得し、暗号化されたデータを書き込むことができるヘルパーモジュールを実装しました。これは関連するインターフェースです(私はそのクラスSSLEngineとclose

public abstract class DataProvider { 
    // Notify the bytes read from the net 
    public abstract void readFromNet(ByteBuffer b); 
    // Gets the bytes to write into the net 
    public abstract void writeToNet(ByteBuffer b); 
    // Add a message to send 
    public abstract boolean addMessage(byte[] data); 
    // Obtains the application data received 
    public abstract byte[] getReceivedApplicationData(); 
    // True if there is something to actually send over the wire 
    public abstract boolean dataToSend(); 
    // True if we should close the channel 
    public abstract boolean shouldClose(); 
    // Notify our intention to shut down the connection 
    public abstract void shutDown(SelectionKey sk); 
    // Set the interest op set for the channel 
    public abstract void setInterestOps(SelectionKey sk); 
} 

私はSSLのためにその抽象基底クラスの実装をしました:));ので、「データプロバイダは、インターフェイスでなければなりません」と私に言っていません。 実装のテスト中に、私は2つの関数を書いています。1つはSocketChannelでメッセージを受け取り、データを送信するSSLSocketは接続を閉じ、もう1つはSocketChannelでメッセージを送信して閉じます。私はこれらの手順を発行してきた場合でも、 さて、問題はのSSLSocketがデータを受信するために使用されるということです近くにはありません:

  1. engine.closeOutbound()
  2. engine.wrap()
  3. channel.write(データ)(はい、私は(ラップで得られたすべてのデータを送信したと確信している)
  4. インバウンドは、close_notify

を読み取るためのチャネルの選択の問題があることですセレクタが4番目のステップでスタックされています。

他のテスト(SSLSocketは接続を閉じます)には問題ありません。私のようにshouldCloseを実装しました

注:

return engine.isOutboundDone() && engine.isInboundDone(); 

ので、私はこれが正しい場合(私は知らない私は近くを初期化してきた場合でも、閉じるために、着信は、close_notifyを必要とします:最後のアサートが侵害され

Socket toRead = socket.accept(); 
toRead.setSoTimeout(0); 
InputStream is = toRead.getInputStream(); 
ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
String read = ""; 
byte[] barray = new byte[1024]; 
while (read.length() < toSend.length() * 2) { 
    int bytesRead = is.read(barray); 
    bos.write(barray, 0, bytesRead); 
    read = new String(bos.toByteArray()); 
} 
assertEquals(toSend + toSend, read); 
assertTrue(toRead.isClosed()); 

:最終的に私は、これはコードの私のSSLSocket側である

return engine.isOutboundDone()でそれを変更することができます。

最初は、toReadに関連付けられた「バックグラウンド」スレッドがないため、受信したメッセージを読み込み/書き込みして、受信したclose_notifyを消費し、最後にソケットを閉じる必要がありますそれでも助けにならない。

+0

GrizzlyやApache MINAのようなフレームワークを使用することをお勧めします。異なるプログラミングパラダイムを混在させています。 –

+2

私は一緒に混合しているそれらの異なるプログラミングのパラダイムは何ですか? – akappa

答えて

1

私は最初のアサートの前にis.close();を追加することをお勧めします。

私が提案したこの小さなコードは、ソケットを閉じないことに注意してください。それはInputStreamを閉じることになっています。

+0

ソケットを閉じることができません:SSLのnotify_endを受信しました。 – akappa

+0

SocketのInputStreamを閉じると、チャンネルが閉じます。 SSLSocketのドキュメントはその情報を「上書き」しないので、その効果は同じであると仮定します。 SSLクローズを正しい方法で実装したかどうかをテストしたいという事実を考えれば、SSLSocketを閉じることはできません。なぜなら、ssl_closeの受信時に "それ自身のために"クローズしたいからです。私はなぜそれが起こらないのだろうと思っています:これは本当に私の質問です。 – akappa

3

非常に遅い回答ですが、すでにclose_notifyを送信している場合は、RFC 2246を参照してください。ただし、取得する必要があります。あなたはclose_notifyでどのくらい正確に選択しているかは言わない。

NBあなたのコードは意味をなさない。ソケットは、を閉じると閉じられます。 isClosed()はソケットであり、接続ではありません。