1// Copyright 2022 The Pigweed Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); you may not 4// use this file except in compliance with the License. You may obtain a copy of 5// the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12// License for the specific language governing permissions and limitations under 13// the License. 14 15/** Functions for working with pw_rpc packets. */ 16 17import { Message } from 'google-protobuf'; 18import { 19 RpcPacket, 20 PacketType, 21} from 'pigweedjs/protos/pw_rpc/internal/packet_pb'; 22import { Status } from 'pigweedjs/pw_status'; 23import { MessageSerializer } from './descriptors'; 24 25// Channel, Service, Method, CallId 26type idSet = [number, number, number, number]; 27 28export function decode(data: Uint8Array): RpcPacket { 29 return RpcPacket.deserializeBinary(data); 30} 31 32function serializeMessage( 33 message?: Message, 34 serializers?: MessageSerializer, 35): Uint8Array { 36 let payload: Uint8Array; 37 if (typeof message !== 'undefined') { 38 if (serializers) { 39 payload = serializers.serialize(message); 40 } else { 41 payload = (message as any)['serializeBinary'](); 42 } 43 } else { 44 payload = new Uint8Array(0); 45 } 46 return payload; 47} 48 49export function decodePayload( 50 payload: Uint8Array, 51 payloadType: any, 52 serializer?: MessageSerializer, 53): any { 54 if (serializer) { 55 return serializer.deserialize(payload); 56 } 57 return payloadType['deserializeBinary'](payload); 58} 59 60export function forServer(packet: RpcPacket): boolean { 61 return packet.getType() % 2 == 0; 62} 63 64export function encodeClientError( 65 packet: RpcPacket, 66 status: Status, 67): Uint8Array { 68 const errorPacket = new RpcPacket(); 69 errorPacket.setType(PacketType.CLIENT_ERROR); 70 errorPacket.setChannelId(packet.getChannelId()); 71 errorPacket.setMethodId(packet.getMethodId()); 72 errorPacket.setServiceId(packet.getServiceId()); 73 errorPacket.setCallId(packet.getCallId()); 74 errorPacket.setStatus(status); 75 return errorPacket.serializeBinary(); 76} 77 78export function encodeClientStream( 79 ids: idSet, 80 message: Message, 81 customSerializer?: MessageSerializer, 82): Uint8Array { 83 const streamPacket = new RpcPacket(); 84 streamPacket.setType(PacketType.CLIENT_STREAM); 85 streamPacket.setChannelId(ids[0]); 86 streamPacket.setServiceId(ids[1]); 87 streamPacket.setMethodId(ids[2]); 88 streamPacket.setCallId(ids[3]); 89 const msgSerialized = serializeMessage(message, customSerializer); 90 streamPacket.setPayload(msgSerialized); 91 return streamPacket.serializeBinary(); 92} 93 94export function encodeClientStreamEnd(ids: idSet): Uint8Array { 95 const streamEnd = new RpcPacket(); 96 streamEnd.setType(PacketType.CLIENT_REQUEST_COMPLETION); 97 streamEnd.setChannelId(ids[0]); 98 streamEnd.setServiceId(ids[1]); 99 streamEnd.setMethodId(ids[2]); 100 streamEnd.setCallId(ids[3]); 101 return streamEnd.serializeBinary(); 102} 103 104export function encodeRequest( 105 ids: idSet, 106 request?: Message, 107 customSerializer?: MessageSerializer, 108): Uint8Array { 109 const payload = serializeMessage(request, customSerializer); 110 const packet = new RpcPacket(); 111 packet.setType(PacketType.REQUEST); 112 packet.setChannelId(ids[0]); 113 packet.setServiceId(ids[1]); 114 packet.setMethodId(ids[2]); 115 packet.setCallId(ids[3]); 116 packet.setPayload(payload); 117 return packet.serializeBinary(); 118} 119 120export function encodeResponse(ids: idSet, response: Message): Uint8Array { 121 const packet = new RpcPacket(); 122 packet.setType(PacketType.RESPONSE); 123 packet.setChannelId(ids[0]); 124 packet.setServiceId(ids[1]); 125 packet.setMethodId(ids[2]); 126 packet.setCallId(ids[3]); 127 const msgSerialized = (response as any)['serializeBinary'](); 128 packet.setPayload(msgSerialized); 129 return packet.serializeBinary(); 130} 131 132export function encodeCancel(ids: idSet): Uint8Array { 133 const packet = new RpcPacket(); 134 packet.setType(PacketType.CLIENT_ERROR); 135 packet.setStatus(Status.CANCELLED); 136 packet.setChannelId(ids[0]); 137 packet.setServiceId(ids[1]); 138 packet.setMethodId(ids[2]); 139 packet.setCallId(ids[3]); 140 return packet.serializeBinary(); 141} 142