steamkit/base/gc/
client_msg_gc.rs1use crate::base::gc::msg_base_gc::IClientGCMsg;
4use crate::base::gc::packet_base_gc::IPacketGCMsg;
5use crate::base::generated::steam_language_internal::{
6 IGCSerializableHeader, IGCSerializableMessage, MsgGCHdr, MsgGCHdrProtoBuf, SteamSerializable,
7 SteamSerializableDeserialize,
8};
9use crate::base::msg_base::{MsgBase, Reader};
10use crate::error::SteamError;
11use crate::types::job_id::JobID;
12use steamkit_protos::gc::CMsgProtoBufHeader;
13
14pub struct ClientGCMsgProtobuf<TBody>
16where
17 TBody: prost::Message + Default,
18{
19 pub header: MsgGCHdrProtoBuf,
21 pub body: TBody,
23 pub payload: MsgBase,
25}
26
27impl<TBody> ClientGCMsgProtobuf<TBody>
28where
29 TBody: prost::Message + Default,
30{
31 pub fn new(e_msg: u32) -> Self {
33 Self::with_payload_reserve(e_msg, 0)
34 }
35
36 pub fn with_payload_reserve(e_msg: u32, payload_reserve: usize) -> Self {
38 let mut header = MsgGCHdrProtoBuf::default();
39 header.set_gc_emsg(e_msg);
40 ClientGCMsgProtobuf {
41 header,
42 body: TBody::default(),
43 payload: MsgBase::new(payload_reserve),
44 }
45 }
46
47 pub fn reply(e_msg: u32, reply_to: &dyn IClientGCMsg) -> Self {
49 let mut msg = Self::new(e_msg);
50 msg.set_target_job_id(reply_to.source_job_id());
51 msg
52 }
53
54 pub fn from_packet(msg: &dyn IPacketGCMsg) -> Result<Self, SteamError> {
56 if !msg.is_proto() {
57 return Err(SteamError::InvalidArgument(
58 "ClientGCMsgProtobuf used for non-proto message!".to_string(),
59 ));
60 }
61 let mut result = Self::new(msg.msg_type());
62 result.deserialize(msg.get_data())?;
63 Ok(result)
64 }
65
66 pub fn body(&self) -> &TBody {
68 &self.body
69 }
70
71 pub fn body_mut(&mut self) -> &mut TBody {
73 &mut self.body
74 }
75
76 pub fn header(&self) -> &MsgGCHdrProtoBuf {
78 &self.header
79 }
80
81 pub fn header_mut(&mut self) -> &mut MsgGCHdrProtoBuf {
83 &mut self.header
84 }
85
86 pub fn proto_header(&self) -> &CMsgProtoBufHeader {
88 &self.header.proto
89 }
90
91 pub fn proto_header_mut(&mut self) -> &mut CMsgProtoBufHeader {
93 &mut self.header.proto
94 }
95
96 pub fn payload(&self) -> &MsgBase {
98 &self.payload
99 }
100
101 pub fn payload_mut(&mut self) -> &mut MsgBase {
103 &mut self.payload
104 }
105}
106
107impl<TBody> IClientGCMsg for ClientGCMsgProtobuf<TBody>
108where
109 TBody: prost::Message + Default,
110{
111 fn is_proto(&self) -> bool {
112 true
113 }
114
115 fn msg_type(&self) -> u32 {
116 self.header.msg
117 }
118
119 fn target_job_id(&self) -> JobID {
120 JobID::from_value(self.header.proto.job_id_target.unwrap_or(u64::MAX))
121 }
122
123 fn set_target_job_id(&mut self, id: JobID) {
124 self.header.proto.job_id_target = Some(id.value());
125 }
126
127 fn source_job_id(&self) -> JobID {
128 JobID::from_value(self.header.proto.job_id_source.unwrap_or(u64::MAX))
129 }
130
131 fn set_source_job_id(&mut self, id: JobID) {
132 self.header.proto.job_id_source = Some(id.value());
133 }
134
135 fn serialize(&self) -> Vec<u8> {
136 let mut out = Vec::new();
137 self.header.write(&mut out);
138 out.extend_from_slice(&self.body.encode_to_vec());
139 out.extend_from_slice(&self.payload.payload);
140 out
141 }
142
143 fn deserialize(&mut self, data: &[u8]) -> Result<(), SteamError> {
144 let mut reader = Reader::new(data);
145 let header = MsgGCHdrProtoBuf::read(&mut reader)?;
146
147 let remaining = reader.remaining();
148 let body_bytes = reader.read_up_to(remaining);
149 let body = TBody::decode(body_bytes.as_slice())?;
150
151 let mut payload = MsgBase::new(0);
152 if !body_bytes.is_empty() {
153 payload.write_bytes(&body_bytes);
154 payload.seek(0);
155 }
156
157 self.header = header;
158 self.body = body;
159 self.payload = payload;
160 Ok(())
161 }
162}
163
164pub struct ClientGCMsg<TBody>
166where
167 TBody: SteamSerializableDeserialize + IGCSerializableMessage,
168{
169 pub header: MsgGCHdr,
171 pub body: TBody,
173 pub payload: MsgBase,
175 pub msg_type: u32,
177}
178
179impl<TBody> ClientGCMsg<TBody>
180where
181 TBody: SteamSerializableDeserialize + IGCSerializableMessage,
182{
183 pub fn new(payload_reserve: usize) -> Self {
185 let body = TBody::default();
186 let msg_type = body.get_gc_emsg();
187 ClientGCMsg {
188 header: MsgGCHdr::default(),
189 body,
190 payload: MsgBase::new(payload_reserve),
191 msg_type,
192 }
193 }
194
195 pub fn reply(reply_to: &dyn IClientGCMsg) -> Self {
197 let mut msg = Self::new(0);
198 msg.set_target_job_id(reply_to.source_job_id());
199 msg
200 }
201
202 pub fn from_packet(msg: &dyn IPacketGCMsg) -> Result<Self, SteamError> {
204 if msg.is_proto() {
205 return Err(SteamError::InvalidArgument(
206 "ClientGCMsg used for proto message!".to_string(),
207 ));
208 }
209 let mut result = Self::new(0);
210 result.deserialize(msg.get_data())?;
211 Ok(result)
212 }
213
214 pub fn body(&self) -> &TBody {
216 &self.body
217 }
218
219 pub fn body_mut(&mut self) -> &mut TBody {
221 &mut self.body
222 }
223
224 pub fn header(&self) -> &MsgGCHdr {
226 &self.header
227 }
228
229 pub fn header_mut(&mut self) -> &mut MsgGCHdr {
231 &mut self.header
232 }
233
234 pub fn payload(&self) -> &MsgBase {
236 &self.payload
237 }
238
239 pub fn payload_mut(&mut self) -> &mut MsgBase {
241 &mut self.payload
242 }
243}
244
245impl<TBody> IClientGCMsg for ClientGCMsg<TBody>
246where
247 TBody: SteamSerializableDeserialize + IGCSerializableMessage,
248{
249 fn is_proto(&self) -> bool {
250 false
251 }
252
253 fn msg_type(&self) -> u32 {
254 self.msg_type
255 }
256
257 fn target_job_id(&self) -> JobID {
258 JobID::from_value(self.header.target_job_id)
259 }
260
261 fn set_target_job_id(&mut self, id: JobID) {
262 self.header.target_job_id = id.value();
263 }
264
265 fn source_job_id(&self) -> JobID {
266 JobID::from_value(self.header.source_job_id)
267 }
268
269 fn set_source_job_id(&mut self, id: JobID) {
270 self.header.source_job_id = id.value();
271 }
272
273 fn serialize(&self) -> Vec<u8> {
274 let mut out = Vec::new();
275 self.header.write(&mut out);
276 self.body.write(&mut out);
277 out.extend_from_slice(&self.payload.payload);
278 out
279 }
280
281 fn deserialize(&mut self, data: &[u8]) -> Result<(), SteamError> {
282 let mut reader = Reader::new(data);
283 let header = MsgGCHdr::read(&mut reader)?;
284 let body = TBody::read(&mut reader)?;
285
286 let remaining = reader.remaining();
287 let rest = reader.read_up_to(remaining);
288 let mut payload = MsgBase::new(0);
289 if !rest.is_empty() {
290 payload.write_bytes(&rest);
291 payload.seek(0);
292 }
293
294 self.header = header;
295 self.body = body;
296 self.payload = payload;
297 Ok(())
298 }
299}