private boolean decodeHandshake()

in GaiaXAndroidClientToStudio/src/main/java/com/alibaba/gaiax/studio/third/socket/java_websocket/WebSocketImpl.java [242:379]


    private boolean decodeHandshake(ByteBuffer socketBufferNew) {
        ByteBuffer socketBuffer;
        if (tmpHandshakeBytes.capacity() == 0) {
            socketBuffer = socketBufferNew;
        } else {
            if (tmpHandshakeBytes.remaining() < socketBufferNew.remaining()) {
                ByteBuffer buf = ByteBuffer.allocate(tmpHandshakeBytes.capacity() + socketBufferNew.remaining());
                tmpHandshakeBytes.flip();
                buf.put(tmpHandshakeBytes);
                tmpHandshakeBytes = buf;
            }

            tmpHandshakeBytes.put(socketBufferNew);
            tmpHandshakeBytes.flip();
            socketBuffer = tmpHandshakeBytes;
        }
        socketBuffer.mark();
        try {
            HandshakeState handshakestate;
            try {
                if (role == Role.SERVER) {
                    if (draft == null) {
                        for (Draft d : knownDrafts) {
                            d = d.copyInstance();
                            try {
                                d.setParseMode(role);
                                socketBuffer.reset();
                                Handshakedata tmphandshake = d.translateHandshake(socketBuffer);
                                if (!(tmphandshake instanceof ClientHandshake)) {
                                    Log.e("GaiaX.Socket", "Closing due to wrong handshake");
                                    closeConnectionDueToWrongHandshake(new InvalidDataException(CloseFrame.PROTOCOL_ERROR, "wrong http function"));
                                    return false;
                                }
                                ClientHandshake handshake = (ClientHandshake) tmphandshake;
                                handshakestate = d.acceptHandshakeAsServer(handshake);
                                if (handshakestate == HandshakeState.MATCHED) {
                                    resourceDescriptor = handshake.getResourceDescriptor();
                                    ServerHandshakeBuilder response;
                                    try {
                                        response = wsl.onWebsocketHandshakeReceivedAsServer(this, d, handshake);
                                    } catch (InvalidDataException e) {
                                        Log.e("GaiaX.Socket", "Closing due to wrong handshake. Possible handshake rejection", e);
                                        closeConnectionDueToWrongHandshake(e);
                                        return false;
                                    } catch (RuntimeException e) {
                                        Log.e("GaiaX.Socket", "Closing due to internal server error", e);
                                        wsl.onWebsocketError(this, e);
                                        closeConnectionDueToInternalServerError(e);
                                        return false;
                                    }
                                    write(d.createHandshake(d.postProcessHandshakeResponseAsServer(handshake, response)));
                                    draft = d;
                                    open(handshake);
                                    return true;
                                }
                            } catch (InvalidHandshakeException e) {
                                // go on with an other draft
                            }
                        }
                        if (draft == null) {
                            Log.e("GaiaX.Socket", "Closing due to protocol error: no draft matches");
                            closeConnectionDueToWrongHandshake(new InvalidDataException(CloseFrame.PROTOCOL_ERROR, "no draft matches"));
                        }
                        return false;
                    } else {
                        // special case for multiple step handshakes
                        Handshakedata tmphandshake = draft.translateHandshake(socketBuffer);
                        if (!(tmphandshake instanceof ClientHandshake)) {
                            Log.e("GaiaX.Socket", "Closing due to protocol error: wrong http function");
                            flushAndClose(CloseFrame.PROTOCOL_ERROR, "wrong http function", false);
                            return false;
                        }
                        ClientHandshake handshake = (ClientHandshake) tmphandshake;
                        handshakestate = draft.acceptHandshakeAsServer(handshake);

                        if (handshakestate == HandshakeState.MATCHED) {
                            open(handshake);
                            return true;
                        } else {
                            Log.e("GaiaX.Socket", "Closing due to protocol error: the handshake did finally not match");
                            close(CloseFrame.PROTOCOL_ERROR, "the handshake did finally not match");
                        }
                        return false;
                    }
                } else if (role == Role.CLIENT) {
                    draft.setParseMode(role);
                    Handshakedata tmphandshake = draft.translateHandshake(socketBuffer);
                    if (!(tmphandshake instanceof ServerHandshake)) {
                        Log.e("GaiaX.Socket", "Closing due to protocol error: wrong http function");
                        flushAndClose(CloseFrame.PROTOCOL_ERROR, "wrong http function", false);
                        return false;
                    }
                    ServerHandshake handshake = (ServerHandshake) tmphandshake;
                    handshakestate = draft.acceptHandshakeAsClient(handshakerequest, handshake);
                    if (handshakestate == HandshakeState.MATCHED) {
                        try {
                            wsl.onWebsocketHandshakeReceivedAsClient(this, handshakerequest, handshake);
                        } catch (InvalidDataException e) {
                            Log.e("GaiaX.Socket", "Closing due to invalid data exception. Possible handshake rejection", e);
                            flushAndClose(e.getCloseCode(), e.getMessage(), false);
                            return false;
                        } catch (RuntimeException e) {
                            Log.e("GaiaX.Socket", "Closing since client was never connected", e);
                            wsl.onWebsocketError(this, e);
                            flushAndClose(CloseFrame.NEVER_CONNECTED, e.getMessage(), false);
                            return false;
                        }
                        open(handshake);
                        return true;
                    } else {
                        Log.e("GaiaX.Socket", "Closing due to protocol error: draft {} refuses handshake");
                        close(CloseFrame.PROTOCOL_ERROR, "draft " + draft + " refuses handshake");
                    }
                }
            } catch (InvalidHandshakeException e) {
                Log.e("GaiaX.Socket", "Closing due to invalid handshake", e);
                close(e);
            }
        } catch (IncompleteHandshakeException e) {
            if (tmpHandshakeBytes.capacity() == 0) {
                socketBuffer.reset();
                int newsize = e.getPreferredSize();
                if (newsize == 0) {
                    newsize = socketBuffer.capacity() + 16;
                } else {
                    assert (e.getPreferredSize() >= socketBuffer.remaining());
                }
                tmpHandshakeBytes = ByteBuffer.allocate(newsize);

                tmpHandshakeBytes.put(socketBufferNew);
                // tmpHandshakeBytes.flip();
            } else {
                tmpHandshakeBytes.position(tmpHandshakeBytes.limit());
                tmpHandshakeBytes.limit(tmpHandshakeBytes.capacity());
            }
        }
        return false;
    }