java - سش تعريف ملقم لم يتلق-مصافحة الجمود



sockets ssh (1)

أراهن التعليمات البرمجية التالية يخلق مشكلة:

String ident = new IdentificationStringParser(buffer, loggerFactory).parseIdentificationString();
if (ident.isEmpty()) {
    return ident;
}

إذا كان إيدنتيفيكاتيون سترينغبارسر.) إرجاع سلسلة فارغة، فإنه سيتم إرجاعها إلى طريقة المتصل. ستستمر طريقة المتصل في استدعاء while ((serverID = readIdentification(buf)).isEmpty()) حيث أن السلسلة فارغة دائما. الطريقة الوحيدة لكسر الحلقة ستكون إذا int b = connInfo.in.read(); إلى int b = connInfo.in.read(); ريتورنس -1 ... ولكن إذا كان الخادم يحتفظ بإرسال البيانات (أو إعادة إرسال البيانات) لا يتم استيفاء هذا الشرط مطلقا.

إذا كان هذا هو الحال وأود أن أضيف نوعا من طريقة اصطناعية للكشف عن هذا مثل:

private String readIdentification(Buffer.PlainBuffer buffer, AtomicInteger numberOfAttempts)
        throws IOException {
    String ident = new IdentificationStringParser(buffer, loggerFactory).parseIdentificationString();

    numberOfAttempts.incrementAndGet();


    if (ident.isEmpty() && numberOfAttempts.intValue() < 1000) { // 1000 
        return ident;
    } else if (numberOfAttempts.intValue() >= 1000) {
        throw new TransportException("To many attempts to read the server ident").

    }

    if (!ident.startsWith("SSH-2.0-") && !ident.startsWith("SSH-1.99-"))
        throw new TransportException(DisconnectReason.PROTOCOL_VERSION_NOT_SUPPORTED,
                                     "Server does not support SSHv2, identified as: " + ident);

    return ident;
}

وبهذه الطريقة سوف تؤكد على الأقل أن هذه هي الحالة ويمكن أن تحفر المزيد لماذا .parseIdentificationString () ترجع سلسلة فارغة.

نحن نواجه بعض المشاكل في محاولة لتنفيذ تجمع من سفتبكونكتيونس لطلبنا.

نحن نستخدم حاليا سشج (سميزز) ومكتبة النقل، ومواجهة قضية نحن ببساطة لا يمكن محاكاة في بيئة التنمية لدينا (ولكن يبقى الخطأ تظهر بشكل عشوائي في الإنتاج، وأحيانا بعد ثلاثة أيام، وأحيانا بعد 10 دقيقة فقط).

المشكلة، عند محاولة إرسال ملف عبر سفتب، يتم تأمين مؤشر الترابط في أسلوب init من فئة TransportImpl سشميزز:

   @Override
    public void init(String remoteHost, int remotePort, InputStream in, OutputStream out)
            throws TransportException {
        connInfo = new ConnInfo(remoteHost, remotePort, in, out);

    try {

        if (config.isWaitForServerIdentBeforeSendingClientIdent()) {
            receiveServerIdent();
            sendClientIdent();
        } else {
            sendClientIdent();
            receiveServerIdent();
        }


        log.info("Server identity string: {}", serverID);

    } catch (IOException e) {
        throw new TransportException(e);
    }

    reader.start();
}

إسويتفورسرفيردنتبيفوريسندينغكلينتيدنت هو فالس بالنسبة لنا، لذلك أولا وقبل كل عميل (نحن) إرسال الهوية لدينا، كما يظهر في السجلات:

" سلسلة هوية العميل: بلابلا "

ثم يتحول إلى receiveServerIdent :

    private void receiveServerIdent() throws IOException 
{
        final Buffer.PlainBuffer buf = new Buffer.PlainBuffer();
        while ((serverID = readIdentification(buf)).isEmpty()) {
            int b = connInfo.in.read();
            if (b == -1)
                throw new TransportException("Server closed connection during identification exchange");
            buf.putByte((byte) b);
        }
    }

الخيط لا يحصل على السيطرة مرة أخرى، كما الخادم لا يرد أبدا مع هويتها. يبدو أن رمز عالق في هذا بينما حلقة. يتم إهمال مهلة، أو استثناءات سش، عميلي يبقى فقط في انتظار إلى الأبد، ويحصل على موضوع مسدود.

هذا هو الأسلوب readIdentification :

private String readIdentification(Buffer.PlainBuffer buffer)
        throws IOException {
    String ident = new IdentificationStringParser(buffer, loggerFactory).parseIdentificationString();
    if (ident.isEmpty()) {
        return ident;
    }

    if (!ident.startsWith("SSH-2.0-") && !ident.startsWith("SSH-1.99-"))
        throw new TransportException(DisconnectReason.PROTOCOL_VERSION_NOT_SUPPORTED,
                                     "Server does not support SSHv2, identified as: " + ident);

    return ident;
}

يبدو أن المدخلات كونكتيونينفو في المدخل أبدا يحصل على البيانات للقراءة، كما لو كان الخادم إغلاق الاتصال (حتى لو، كما قيل في وقت سابق، لا يتم طرح أي استثناء).

لقد حاولت محاكاة هذا الخطأ عن طريق تشبع المفاوضات، وإغلاق مآخذ أثناء الاتصال، وذلك باستخدام كونتراك لقتل الاتصالات المنشأة في حين يجري المصافحة، ولكن مع عدم وجود الحظ على الإطلاق، لذلك أي مساعدة سيكون موضع تقدير كبير.

:)





deadlock