@@ -21,71 +21,122 @@ use crate::{
21
21
error:: Error ,
22
22
interaction_model:: {
23
23
core:: OpCode ,
24
- messages:: msg:: { self , SubscribeReq , SubscribeResp } ,
24
+ messages:: {
25
+ msg:: { self , SubscribeReq , SubscribeResp } ,
26
+ GenericPath ,
27
+ } ,
25
28
} ,
26
- tlv:: { TLVWriter , TagType , ToTLV } ,
29
+ tlv:: { self , get_root_node_struct , FromTLV , TLVWriter , TagType , ToTLV } ,
27
30
transport:: proto_demux:: ResponseRequired ,
28
31
} ;
29
32
30
- use super :: { DataModel , Transaction } ;
33
+ use super :: { read :: ResumeReadReq , DataModel , Transaction } ;
31
34
32
35
static SUBS_ID : AtomicU32 = AtomicU32 :: new ( 1 ) ;
33
36
34
- impl DataModel {
35
- pub fn handle_subscribe_req (
36
- & self ,
37
- req : & SubscribeReq ,
37
+ #[ derive( PartialEq ) ]
38
+ enum SubsState {
39
+ Confirming ,
40
+ Confirmed ,
41
+ }
42
+
43
+ pub struct SubsCtx {
44
+ state : SubsState ,
45
+ id : u32 ,
46
+ resume_read_req : Option < ResumeReadReq > ,
47
+ }
48
+
49
+ impl SubsCtx {
50
+ pub fn new (
51
+ rx_buf : & [ u8 ] ,
38
52
trans : & mut Transaction ,
39
53
tw : & mut TLVWriter ,
40
- ) -> Result < SubsCtx , Error > {
41
- let ctx = SubsCtx {
54
+ dm : & DataModel ,
55
+ ) -> Result < Self , Error > {
56
+ let root = get_root_node_struct ( rx_buf) ?;
57
+ let req = SubscribeReq :: from_tlv ( & root) ?;
58
+
59
+ let mut ctx = SubsCtx {
42
60
state : SubsState :: Confirming ,
43
61
// TODO
44
62
id : SUBS_ID . fetch_add ( 1 , Ordering :: SeqCst ) ,
63
+ resume_read_req : None ,
45
64
} ;
46
65
47
- let read_req = req. to_read_req ( ) ;
48
- tw. start_struct ( TagType :: Anonymous ) ?;
49
- tw. u32 (
50
- TagType :: Context ( msg:: ReportDataTag :: SubscriptionId as u8 ) ,
51
- ctx. id ,
52
- ) ?;
53
66
let mut resume_from = None ;
54
- self . handle_read_attr_array ( & read_req, trans, tw, & mut resume_from) ?;
55
- tw. end_container ( ) ?;
56
-
67
+ ctx. do_read ( & req, trans, tw, dm, & mut resume_from) ?;
68
+ if resume_from. is_some ( ) {
69
+ // This is a multi-hop read transaction, remember this read request
70
+ ctx. resume_read_req = Some ( ResumeReadReq :: new ( rx_buf, & resume_from) ?) ;
71
+ }
57
72
Ok ( ctx)
58
73
}
59
74
60
- pub fn handle_subscription_confirm (
61
- & self ,
75
+ pub fn handle_status_report (
76
+ & mut self ,
62
77
trans : & mut Transaction ,
63
78
tw : & mut TLVWriter ,
64
- ctx : & mut SubsCtx ,
79
+ dm : & DataModel ,
65
80
) -> Result < ( OpCode , ResponseRequired ) , Error > {
66
- if ctx . state != SubsState :: Confirming {
81
+ if self . state != SubsState :: Confirming {
67
82
// Not relevant for us
68
83
trans. complete ( ) ;
69
84
return Err ( Error :: Invalid ) ;
70
85
}
71
- ctx. state = SubsState :: Confirmed ;
86
+
87
+ // Is there a previous resume read pending
88
+ if self . resume_read_req . is_some ( ) {
89
+ let mut resume_read_req = self . resume_read_req . take ( ) . unwrap ( ) ;
90
+ if let Some ( packet) = resume_read_req. pending_req . as_mut ( ) {
91
+ let rx_buf = packet. get_parsebuf ( ) ?. as_borrow_slice ( ) ;
92
+ let root = tlv:: get_root_node ( rx_buf) ?;
93
+ let req = SubscribeReq :: from_tlv ( & root) ?;
94
+
95
+ self . do_read ( & req, trans, tw, dm, & mut resume_read_req. resume_from ) ?;
96
+ if resume_read_req. resume_from . is_some ( ) {
97
+ // More chunks are pending, setup resume_read_req again
98
+ self . resume_read_req = Some ( resume_read_req) ;
99
+ }
100
+
101
+ return Ok ( ( OpCode :: ReportData , ResponseRequired :: Yes ) ) ;
102
+ }
103
+ }
104
+
105
+ // We are here implies that the read is now complete
106
+ self . confirm_subscription ( trans, tw)
107
+ }
108
+
109
+ fn confirm_subscription (
110
+ & mut self ,
111
+ trans : & mut Transaction ,
112
+ tw : & mut TLVWriter ,
113
+ ) -> Result < ( OpCode , ResponseRequired ) , Error > {
114
+ self . state = SubsState :: Confirmed ;
72
115
73
116
// TODO
74
- let resp = SubscribeResp :: new ( ctx . id , 40 ) ;
117
+ let resp = SubscribeResp :: new ( self . id , 40 ) ;
75
118
resp. to_tlv ( tw, TagType :: Anonymous ) ?;
76
119
trans. complete ( ) ;
77
120
Ok ( ( OpCode :: SubscriptResponse , ResponseRequired :: Yes ) )
78
121
}
79
- }
80
122
81
- #[ derive( PartialEq , Clone , Copy ) ]
82
- enum SubsState {
83
- Confirming ,
84
- Confirmed ,
85
- }
123
+ fn do_read (
124
+ & mut self ,
125
+ req : & SubscribeReq ,
126
+ trans : & mut Transaction ,
127
+ tw : & mut TLVWriter ,
128
+ dm : & DataModel ,
129
+ resume_from : & mut Option < GenericPath > ,
130
+ ) -> Result < ( ) , Error > {
131
+ let read_req = req. to_read_req ( ) ;
132
+ tw. start_struct ( TagType :: Anonymous ) ?;
133
+ tw. u32 (
134
+ TagType :: Context ( msg:: ReportDataTag :: SubscriptionId as u8 ) ,
135
+ self . id ,
136
+ ) ?;
137
+ dm. handle_read_attr_array ( & read_req, trans, tw, resume_from) ?;
138
+ tw. end_container ( ) ?;
86
139
87
- #[ derive( Clone , Copy ) ]
88
- pub struct SubsCtx {
89
- state : SubsState ,
90
- id : u32 ,
140
+ Ok ( ( ) )
141
+ }
91
142
}
0 commit comments