11import { Reader } from '@jsonjoy.com/buffers/lib/Reader' ;
22import { RpcMsgType , RpcReplyStat , RpcAcceptStat , RpcRejectStat , RPC_VERSION } from './constants' ;
33import { RpcDecodingError } from './errors' ;
4- import { RpcOpaqueAuth , RpcCallBody , RpcAcceptedReply , RpcRejectedReply , RpcMessage , RpcMismatchInfo } from './messages' ;
4+ import {
5+ RpcOpaqueAuth ,
6+ RpcCallMessage ,
7+ RpcAcceptedReplyMessage ,
8+ RpcRejectedReplyMessage ,
9+ RpcMessage ,
10+ RpcMismatchInfo ,
11+ } from './messages' ;
512
613export class RpcMessageDecoder {
714 public decodeMessage ( reader : Reader ) : RpcMessage | undefined {
@@ -15,43 +22,88 @@ export class RpcMessageDecoder {
1522 const msgType = reader . u32 ( ) ;
1623 let message : RpcMessage | undefined ;
1724 if ( msgType === RpcMsgType . CALL ) {
18- const callBody = this . readCallBody ( reader ) ;
19- if ( ! callBody ) {
25+ if ( reader . size ( ) < 20 ) {
2026 reader . x = startPos ;
2127 return undefined ;
2228 }
23- const params = reader . size ( ) > 0 ? reader . buf ( reader . size ( ) ) : undefined ;
24- callBody . params = params ;
25- message = new RpcMessage ( xid , callBody ) ;
29+ const rpcvers = reader . u32 ( ) ;
30+ if ( rpcvers !== RPC_VERSION ) {
31+ throw new RpcDecodingError ( `Unsupported RPC version: ${ rpcvers } ` ) ;
32+ }
33+ const prog = reader . u32 ( ) ;
34+ const vers = reader . u32 ( ) ;
35+ const proc = reader . u32 ( ) ;
36+ const cred = this . readOpaqueAuth ( reader ) ;
37+ if ( ! cred ) {
38+ reader . x = startPos ;
39+ return undefined ;
40+ }
41+ const verf = this . readOpaqueAuth ( reader ) ;
42+ if ( ! verf ) {
43+ reader . x = startPos ;
44+ return undefined ;
45+ }
46+ const params = reader . size ( ) > 0 ? reader . cut ( reader . size ( ) ) : undefined ;
47+ message = new RpcCallMessage ( xid , rpcvers , prog , vers , proc , cred , verf , params ) ;
2648 } else if ( msgType === RpcMsgType . REPLY ) {
2749 if ( reader . size ( ) < 4 ) {
2850 reader . x = startPos ;
2951 return undefined ;
3052 }
3153 const replyStat = reader . u32 ( ) ;
3254 if ( replyStat === RpcReplyStat . MSG_ACCEPTED ) {
33- const reply = this . readAcceptedReply ( reader ) ;
34- if ( ! reply ) {
55+ const verf = this . readOpaqueAuth ( reader ) ;
56+ if ( ! verf ) {
3557 reader . x = startPos ;
3658 return undefined ;
3759 }
38- const results = reader . size ( ) > 0 ? reader . buf ( reader . size ( ) ) : undefined ;
39- reply . results = results ;
40- message = new RpcMessage ( xid , reply ) ;
60+ if ( reader . size ( ) < 4 ) {
61+ reader . x = startPos ;
62+ return undefined ;
63+ }
64+ const acceptStat = reader . u32 ( ) ;
65+ let mismatchInfo : RpcMismatchInfo | undefined ;
66+ if ( acceptStat === RpcAcceptStat . PROG_MISMATCH ) {
67+ if ( reader . size ( ) < 8 ) {
68+ reader . x = startPos ;
69+ return undefined ;
70+ }
71+ const low = reader . u32 ( ) ;
72+ const high = reader . u32 ( ) ;
73+ mismatchInfo = new RpcMismatchInfo ( low , high ) ;
74+ }
75+ const results = reader . size ( ) > 0 ? reader . cut ( reader . size ( ) ) : undefined ;
76+ message = new RpcAcceptedReplyMessage ( xid , verf , acceptStat , mismatchInfo , results ) ;
4177 } else if ( replyStat === RpcReplyStat . MSG_DENIED ) {
42- const reply = this . readRejectedReply ( reader ) ;
43- if ( ! reply ) {
78+ if ( reader . size ( ) < 4 ) {
4479 reader . x = startPos ;
4580 return undefined ;
4681 }
47- message = new RpcMessage ( xid , reply ) ;
82+ const rejectStat = reader . u32 ( ) ;
83+ let mismatchInfo : RpcMismatchInfo | undefined ;
84+ let authStat : number | undefined ;
85+ if ( rejectStat === RpcRejectStat . RPC_MISMATCH ) {
86+ if ( reader . size ( ) < 8 ) {
87+ reader . x = startPos ;
88+ return undefined ;
89+ }
90+ const low = reader . u32 ( ) ;
91+ const high = reader . u32 ( ) ;
92+ mismatchInfo = new RpcMismatchInfo ( low , high ) ;
93+ } else if ( rejectStat === RpcRejectStat . AUTH_ERROR ) {
94+ if ( reader . size ( ) < 4 ) {
95+ reader . x = startPos ;
96+ return undefined ;
97+ }
98+ authStat = reader . u32 ( ) ;
99+ }
100+ message = new RpcRejectedReplyMessage ( xid , rejectStat , mismatchInfo , authStat ) ;
48101 } else {
49102 throw new RpcDecodingError ( 'Invalid reply_stat' ) ;
50103 }
51104 } else {
52105 throw new RpcDecodingError ( 'Invalid msg_type' ) ;
53106 }
54- reader . consume ( ) ;
55107 return message ;
56108 } catch ( err ) {
57109 if ( err instanceof RangeError ) {
@@ -62,55 +114,7 @@ export class RpcMessageDecoder {
62114 }
63115 }
64116
65- private readCallBody ( reader : StreamingReader ) : RpcCallBody | undefined {
66- if ( reader . size ( ) < 20 ) return undefined ;
67- const rpcvers = reader . u32 ( ) ;
68- if ( rpcvers !== RPC_VERSION ) {
69- throw new RpcDecodingError ( `Unsupported RPC version: ${ rpcvers } ` ) ;
70- }
71- const prog = reader . u32 ( ) ;
72- const vers = reader . u32 ( ) ;
73- const proc = reader . u32 ( ) ;
74- const cred = this . readOpaqueAuth ( reader ) ;
75- if ( ! cred ) return undefined ;
76- const verf = this . readOpaqueAuth ( reader ) ;
77- if ( ! verf ) return undefined ;
78- return new RpcCallBody ( rpcvers , prog , vers , proc , cred , verf ) ;
79- }
80-
81- private readAcceptedReply ( reader : StreamingReader ) : RpcAcceptedReply | undefined {
82- const verf = this . readOpaqueAuth ( reader ) ;
83- if ( ! verf ) return undefined ;
84- if ( reader . size ( ) < 4 ) return undefined ;
85- const acceptStat = reader . u32 ( ) ;
86- let mismatchInfo : RpcMismatchInfo | undefined ;
87- if ( acceptStat === RpcAcceptStat . PROG_MISMATCH ) {
88- if ( reader . size ( ) < 8 ) return undefined ;
89- const low = reader . u32 ( ) ;
90- const high = reader . u32 ( ) ;
91- mismatchInfo = new RpcMismatchInfo ( low , high ) ;
92- }
93- return new RpcAcceptedReply ( verf , acceptStat , mismatchInfo , undefined ) ;
94- }
95-
96- private readRejectedReply ( reader : StreamingReader ) : RpcRejectedReply | undefined {
97- if ( reader . size ( ) < 4 ) return undefined ;
98- const rejectStat = reader . u32 ( ) ;
99- let mismatchInfo : RpcMismatchInfo | undefined ;
100- let authStat : number | undefined ;
101- if ( rejectStat === RpcRejectStat . RPC_MISMATCH ) {
102- if ( reader . size ( ) < 8 ) return undefined ;
103- const low = reader . u32 ( ) ;
104- const high = reader . u32 ( ) ;
105- mismatchInfo = new RpcMismatchInfo ( low , high ) ;
106- } else if ( rejectStat === RpcRejectStat . AUTH_ERROR ) {
107- if ( reader . size ( ) < 4 ) return undefined ;
108- authStat = reader . u32 ( ) ;
109- }
110- return new RpcRejectedReply ( rejectStat , mismatchInfo , authStat ) ;
111- }
112-
113- private readOpaqueAuth ( reader : StreamingReader ) : RpcOpaqueAuth | undefined {
117+ private readOpaqueAuth ( reader : Reader ) : RpcOpaqueAuth | undefined {
114118 if ( reader . size ( ) < 8 ) return undefined ;
115119 const flavor = reader . u32 ( ) ;
116120 const length = reader . u32 ( ) ;
0 commit comments