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

org.red5.server.net.remoting.codec.RemotingProtocolEncoder Maven / Gradle / Ivy

Go to download

Ant Media Server supports RTMP, RTSP, MP4, HLS, WebRTC, Adaptive Streaming, etc.

There is a newer version: 2.10.0
Show newest version
/*
 * RED5 Open Source Media Server - https://github.com/Red5/
 * 
 * Copyright 2006-2016 by respective authors (see below). All rights reserved.
 * 
 * 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 org.red5.server.net.remoting.codec;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.mina.core.buffer.IoBuffer;
import org.red5.compatibility.flex.messaging.messages.AbstractMessage;
import org.red5.compatibility.flex.messaging.messages.ErrorMessage;
import org.red5.io.amf.Output;
import org.red5.io.object.Serializer;
import org.red5.server.api.IConnection.Encoding;
import org.red5.server.api.Red5;
import org.red5.server.api.remoting.IRemotingConnection;
import org.red5.server.api.remoting.IRemotingHeader;
import org.red5.server.exception.ClientDetailsException;
import org.red5.server.net.remoting.FlexMessagingService;
import org.red5.server.net.remoting.message.RemotingCall;
import org.red5.server.net.remoting.message.RemotingPacket;
import org.red5.server.net.rtmp.status.StatusCodes;
import org.red5.server.net.rtmp.status.StatusObject;
import org.red5.server.service.ServiceNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Remoting protocol encoder.
 */
public class RemotingProtocolEncoder {

    protected static Logger log = LoggerFactory.getLogger(RemotingProtocolEncoder.class);

    /**
     * Encodes the given buffer.
     * 
     * @param message
     *            message
     * @return buffer
     * @throws Exception
     *             on exception
     */
    public IoBuffer encode(Object message) throws Exception {
        RemotingPacket resp = (RemotingPacket) message;
        IoBuffer buf = IoBuffer.allocate(1024);
        buf.setAutoExpand(true);
        Output output;
        if (resp.getEncoding() == Encoding.AMF0) {
            buf.putShort((short) 0); // encoded using AMF0
        } else {
            buf.putShort((short) 3); // encoded using AMF3
        }

        IRemotingConnection conn = (IRemotingConnection) Red5.getConnectionLocal();
        Collection headers = conn.getHeaders();
        buf.putShort((short) headers.size()); // write the header count
        if (resp.getEncoding() == Encoding.AMF0) {
            output = new Output(buf);
        } else {
            output = new org.red5.io.amf3.Output(buf);
        }
        for (IRemotingHeader header : headers) {
            Output.putString(buf, IRemotingHeader.PERSISTENT_HEADER);
            output.writeBoolean(false);
            Map param = new HashMap();
            param.put("name", header.getName());
            param.put("mustUnderstand", header.getMustUnderstand() ? Boolean.TRUE : Boolean.FALSE);
            param.put("data", header.getValue());
            Serializer.serialize(output, param);
        }
        headers.clear();

        buf.putShort((short) resp.getCalls().size()); // write the number of bodies
        for (RemotingCall call : resp.getCalls()) {
            log.debug("Call");
            Output.putString(buf, call.getClientResponse());
            if (!call.isMessaging) {
                Output.putString(buf, "null");
            } else {
                Output.putString(buf, "");
            }
            buf.putInt(-1);
            log.info("result: {}", call.getResult());
            if (call.isAMF3) {
                output = new org.red5.io.amf3.Output(buf);
            } else {
                output = new Output(buf);
            }
            Object result = call.getClientResult();
            if (!call.isSuccess()) {
                if (call.isMessaging && !(result instanceof ErrorMessage)) {
                    // Generate proper error result for the Flex messaging client
                    AbstractMessage request = (AbstractMessage) call.getArguments()[0];
                    if (result instanceof ServiceNotFoundException) {
                        ServiceNotFoundException ex = (ServiceNotFoundException) result;
                        result = FlexMessagingService.returnError(request, "serviceNotAvailable", "Flex messaging not activated", ex.getMessage());
                    } else if (result instanceof Throwable) {
                        result = FlexMessagingService.returnError(request, "Server.Invoke.Error", ((Throwable) result).getMessage(), (Throwable) result);
                    } else {
                        result = FlexMessagingService.returnError(request, "Server.Invoke.Error", result.toString(), "");
                    }
                } else if (!call.isMessaging) {
                    // Generate proper error object to return
                    result = generateErrorResult(StatusCodes.NC_CALL_FAILED, call.getException());
                }
            }
            Serializer.serialize(output, result);
        }
        buf.flip();
        if (log.isDebugEnabled()) {
            log.debug(">>{}", buf.getHexDump());
        }
        return buf;

    }

    /**
     * Generate error object to return for given exception.
     * 
     * @param code
     *            call
     * @param error
     *            error
     * @return status object
     */
    protected StatusObject generateErrorResult(String code, Throwable error) {
        // Construct error object to return
        String message = "";
        while (error != null && error.getCause() != null) {
            error = error.getCause();
        }
        if (error != null && error.getMessage() != null) {
            message = error.getMessage();
        }
        StatusObject status = new StatusObject(code, "error", message);
        if (error instanceof ClientDetailsException) {
            // Return exception details to client
            status.setApplication(((ClientDetailsException) error).getParameters());
            if (((ClientDetailsException) error).includeStacktrace()) {
                List stack = new ArrayList();
                for (StackTraceElement element : error.getStackTrace()) {
                    stack.add(element.toString());
                }
                status.setAdditional("stacktrace", stack);
            }
        } else if (error != null) {
            status.setApplication(error.getClass().getCanonicalName());
        }
        return status;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy