All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.predic8.membrane.core.transport.ws.interceptors.WebSocketStompReassembler Maven / Gradle / Ivy

There is a newer version: 5.7.3
Show newest version
/* Copyright 2017 predic8 GmbH, www.predic8.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

package com.predic8.membrane.core.transport.ws.interceptors;

import com.predic8.membrane.annot.MCChildElement;
import com.predic8.membrane.annot.MCElement;
import com.predic8.membrane.core.Router;
import com.predic8.membrane.core.exchange.Exchange;
import com.predic8.membrane.core.http.Body;
import com.predic8.membrane.core.http.Request;
import com.predic8.membrane.core.interceptor.Interceptor;
import com.predic8.membrane.core.interceptor.Outcome;
import com.predic8.membrane.core.transport.ws.WebSocketFrame;
import com.predic8.membrane.core.transport.ws.WebSocketInterceptorInterface;
import com.predic8.membrane.core.transport.ws.WebSocketSender;
import com.predic8.membrane.core.util.EndOfStreamException;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@MCElement(name = "wsStompReassembler")
public class WebSocketStompReassembler implements WebSocketInterceptorInterface {

    List interceptors = new ArrayList<>();

    @Override
    public void init(Router router) throws Exception {
        for (Interceptor i : interceptors)
            i.init(router);
    }

    @Override
    public void handleFrame(WebSocketFrame wsStompFrame, boolean frameTravelsToRight, WebSocketSender sender) throws Exception {
        if (wsStompFrame.getOpcode() != 1) {
            sender.handleFrame(wsStompFrame);
            return;
        }
        Exchange exc = convertToExchange(wsStompFrame);

        // TODO: this changes, as soon as we introduce the STOMPInterceptor
        //if (frameTravelsToRight) {
        if (true) {
            for (Interceptor interceptor : interceptors)
                if (interceptor.handleRequest(exc) != Outcome.CONTINUE)
                    return;

        } else {
            for (int i = interceptors.size(); i >= 0; i--)
                //if (interceptors.get(i).handleResponse(exc) != Outcome.CONTINUE)
                //    return;
                break;
        }

        modifyOriginalFrameWithExchange(wsStompFrame, exc);
        sender.handleFrame(wsStompFrame);
    }

    private ByteArrayOutputStream baos = new ByteArrayOutputStream();

    private void modifyOriginalFrameWithExchange(WebSocketFrame wsStompFrame, Exchange exc) throws IOException {
        baos.reset();
        if (exc.getRequest().getMethod().isEmpty()) {
            // this is a heart-beat
            baos.write('\n');
        } else {
            exc.getRequest().writeSTOMP(baos, true);

            baos.write(0);
        }

        wsStompFrame.setPayload(baos.toByteArray());
    }

    private Exchange convertToExchange(WebSocketFrame wsStompFrame) throws IOException, EndOfStreamException {
        byte[] realPayload = new byte[(int) wsStompFrame.getPayloadLength()];
        System.arraycopy(wsStompFrame.getPayload(), 0, realPayload, 0, (int) wsStompFrame.getPayloadLength());

        if (wsStompFrame.getPayloadLength() == 0)
            throw new IOException("Empty STOMP frame.");

        ByteArrayInputStream bais = new ByteArrayInputStream(wsStompFrame.getPayload(), 0, (int) wsStompFrame.getPayloadLength() - 1);
        Request request = new Request();

        if (isHeartBeat(wsStompFrame)) {
            request.setMethod("");
            request.setBody(new Body(bais));
        } else {
            if (wsStompFrame.getPayload()[(int) wsStompFrame.getPayloadLength() - 1] != 0)
                throw new IOException("STOMP frame is not terminated by \\0.");

            request.read(bais, true);
        }

        Exchange result = new Exchange(null);
        result.setRequest(request);

        if (wsStompFrame.getOriginalExchange() != null)
            result.setProperty(Exchange.WS_ORIGINAL_EXCHANGE, wsStompFrame.getOriginalExchange());

        return result;
    }

    private boolean isHeartBeat(WebSocketFrame frame) {
        return
                (frame.getPayloadLength() == 2 && frame.getPayload()[0] == 0x0D && frame.getPayload()[1] == 0x0A) ||
                        (frame.getPayloadLength() == 1 && frame.getPayload()[0] == 0x0A);
    }

    public List getInterceptors() {
        return interceptors;
    }

    @MCChildElement
    public void setInterceptors(List interceptors) {
        this.interceptors = interceptors;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy