簡體   English   中英

Java Nio socketchannel在Safari和TLS1.2的IOS中讀取早期的EOS

[英]Java nio socketchannel read early eos in safari and IOS with TLS1.2

我有一個非常奇怪的問題,我在最近幾天一直在工作。

我在服務器端編寫了一個代理應用程序。 代理所做的全部工作就是管理來自不同應用程序(WebApplications,IOSApps,Android Apps等)的TLS / nonTLS請求和響應,並將流量代理到服務器上的應用程序。

我遇到的問題是,當我通過Safari和通過https(TLSv1.2)訪問使用我的代理的WebApplication時,我的代理沒有隨機響應。 我進行了大量調試,此問題是由我的連接讀取功能引起的。 超時是非常隨機的,在我的測試中,我平均有10個請求中有8個超時。

這是代碼:

public int read(ByteBuffer dst) throws IOException {

    if (!dst.hasRemaining()) {
        return 0;
    }
    if (peerAppData.hasRemaining()) {
        peerAppData.flip();
        return ByteBufferUtils.transferByteBuffer(peerAppData, dst);
    }
    peerNetData.compact();

    int bytesRead = socketChannel.read(peerNetData);

    if (bytesRead > 0) {
        peerNetData.flip();
        while (peerNetData.hasRemaining()) {
            peerAppData.compact();
            SSLEngineResult result = null;
            try {
                result = sslInfo.sslEngine.unwrap(peerNetData, peerAppData);
            } catch (SSLException e) {
                System.out.println(e.getMessage());
                e.printStackTrace();
                // throw e;
            }
            switch (result.getStatus()) {
            case OK:
                peerAppData.flip();
                return ByteBufferUtils.transferByteBuffer(peerAppData, dst);
            case BUFFER_UNDERFLOW:
                peerAppData.flip();
                return ByteBufferUtils.transferByteBuffer(peerAppData, dst);
            case BUFFER_OVERFLOW:
                peerAppData = enlargeApplicationBuffer(peerAppData);
                break;
            case CLOSED:
                closeConnection();
                dst.clear();
                return -1;
            default:
                System.out.println("Invalid SSL status: " + result.getStatus());
                throw new IllegalStateException("Invalid SSL status: " + result.getStatus());
            }
        }
    } else if (bytesRead < 0) {
        handleEndOfStream();
    }
    ByteBufferUtils.transferByteBuffer(peerAppData, dst);
    return bytesRead;
}

此代碼適用於Chrome,Opera和Android。 但是在Safari和IOS上,對SocketChannel的第二次讀取會隨機返回-1。 這導致連接被關閉。 這就解釋了為什么我在Safari / IOS端超時。

我有一段有效的代碼,但是我不能使用它,因為這不允許我代理諸如文件上傳之類的數據流。 並且這不能正確處理SSLEngineResult。

public int read(ByteBuffer dst) throws IOException {

    int bytesRead = 1;
    int totalBytesRead = 0;

    peerNetData.clear();

    while (bytesRead > 0) {
        bytesRead = socketChannel.read(peerNetData);

        if (bytesRead > 0) {
            totalBytesRead = totalBytesRead + bytesRead;
        }
    }

    peerNetData.flip();

    if (totalBytesRead < 0) {
        return bytesRead;
    }

    while (peerNetData.hasRemaining()) {
        SSLEngineResult result = sslInfo.sslEngine.unwrap(peerNetData, dst);
        if (result.getStatus() != SSLEngineResult.Status.OK) {
            return -1;
        }
    }

    peerNetData.compact();

    return totalBytesRead;
}

我真的不知道為什么這些代碼僅在野生動物園瀏覽器或任何IOS設備的請求下失敗。

你們中有人遇到過同樣的問題嗎?

在此先感謝您,如果我錯過了什么,請告訴我!

如果代理的上游read()返回-1,則上游對等方將關閉連接,並且您應該對下游對等方執行相同的操作,而不是使其超時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM