package org.yamcs.web.websocket; import java.io.IOException; import org.yamcs.protobuf.Alarms.AlarmData; import org.yamcs.protobuf.Archive.StreamData; import org.yamcs.protobuf.Commanding.CommandHistoryEntry; import org.yamcs.protobuf.Commanding.CommandQueueEvent; import org.yamcs.protobuf.Commanding.CommandQueueInfo; import org.yamcs.protobuf.Pvalue.ParameterData; import org.yamcs.protobuf.Web.WebSocketExtensionData; import org.yamcs.protobuf.Web.WebSocketServerMessage; import org.yamcs.protobuf.Web.WebSocketServerMessage.MessageType; import org.yamcs.protobuf.Web.WebSocketServerMessage.WebSocketReplyData; import org.yamcs.protobuf.Web.WebSocketServerMessage.WebSocketSubscriptionData; import org.yamcs.protobuf.Yamcs.Event; import org.yamcs.protobuf.Yamcs.ProtoDataType; import org.yamcs.protobuf.Yamcs.TimeInfo; import org.yamcs.protobuf.Yamcs.TmPacketData; import org.yamcs.protobuf.YamcsManagement.ClientInfo; import org.yamcs.protobuf.YamcsManagement.LinkEvent; import org.yamcs.protobuf.YamcsManagement.ProcessorInfo; import org.yamcs.protobuf.YamcsManagement.Statistics; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; import io.netty.handler.codec.http.websocketx.WebSocketFrame; import io.protostuff.Schema; public class ProtobufEncoder implements WebSocketEncoder { private ChannelHandlerContext ctx; public ProtobufEncoder(ChannelHandlerContext ctx) { this.ctx = ctx; } @Override public WebSocketFrame encodeException(WebSocketException e) throws IOException { WebSocketServerMessage serverMessage = WebSocketServerMessage.newBuilder() .setType(MessageType.EXCEPTION) .setException(e.toWebSocketExceptionData()) .build(); return toFrame(serverMessage); } @Override public WebSocketFrame encodeReply(WebSocketReplyData reply) throws IOException { WebSocketServerMessage serverMessage = WebSocketServerMessage.newBuilder() .setType(MessageType.REPLY) .setReply(reply) .build(); return toFrame(serverMessage); } @Override public <T> WebSocketFrame encodeData(int sequenceNumber, ProtoDataType dataType, T message, Schema<T> schema) throws IOException { WebSocketSubscriptionData.Builder responseb = WebSocketSubscriptionData.newBuilder(); responseb.setSequenceNumber(sequenceNumber); responseb.setType(dataType); if (dataType == ProtoDataType.CMD_HISTORY) { responseb.setCommand((CommandHistoryEntry) message); } else if (dataType == ProtoDataType.PARAMETER) { responseb.setParameterData((ParameterData) message); } else if (dataType == ProtoDataType.PROCESSOR_INFO) { responseb.setProcessorInfo((ProcessorInfo) message); } else if (dataType == ProtoDataType.CLIENT_INFO) { responseb.setClientInfo((ClientInfo) message); } else if (dataType == ProtoDataType.PROCESSING_STATISTICS) { responseb.setStatistics((Statistics) message); } else if (dataType == ProtoDataType.EVENT) { responseb.setEvent((Event) message); } else if (dataType == ProtoDataType.ALARM_DATA) { responseb.setAlarmData((AlarmData) message); } else if (dataType == ProtoDataType.STREAM_DATA) { responseb.setStreamData((StreamData) message); } else if (dataType == ProtoDataType.LINK_EVENT) { responseb.setLinkEvent((LinkEvent) message); } else if (dataType == ProtoDataType.TIME_INFO) { responseb.setTimeInfo((TimeInfo) message); } else if (dataType == ProtoDataType.EVENT) { responseb.setEvent((Event) message); } else if (dataType == ProtoDataType.COMMAND_QUEUE_INFO) { responseb.setCommandQueueInfo((CommandQueueInfo) message); } else if (dataType == ProtoDataType.COMMAND_QUEUE_EVENT) { responseb.setCommandQueueEvent((CommandQueueEvent) message); } else if (dataType == ProtoDataType.TM_PACKET) { responseb.setTmPacket((TmPacketData) message); } else if (dataType == ProtoDataType.EXTENSION_DATA) { responseb.setExtensionData((WebSocketExtensionData) message); } else { throw new IllegalArgumentException("Unsupported data type " + dataType); } WebSocketServerMessage serverMessage = WebSocketServerMessage.newBuilder() .setType(MessageType.DATA) .setData(responseb) .build(); return toFrame(serverMessage); } private BinaryWebSocketFrame toFrame(WebSocketServerMessage message) throws IOException { // TODO This assumes that the frame is quite small (which it should be, but) ByteBuf buf = ctx.alloc().buffer(); try (ByteBufOutputStream cout = new ByteBufOutputStream(buf)) { message.writeTo(cout); } return new BinaryWebSocketFrame(buf); } }