1use rand::{Rng, OsRng};
2use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt};
3use std::io::Cursor;
4use std::iter;
5use std::convert;
6use std::string::FromUtf8Error;
7use std::fmt;
8use crypto::{aessafe, blockmodes};
9use crypto::symmetriccipher::{Encryptor, Decryptor, SymmetricCipherError};
10use crypto::buffer::{RefReadBuffer, RefWriteBuffer, BufferResult};
11
12const STX: u8 = 0x7Fu8;
13const STEX: u8 = 0x7Eu8;
14const MAX_SLAVE_ID: u8 = 0x7Du8;
15
16pub type SlaveID = u8;
17pub type Data = Vec<u8>;
18pub type DataSlice = [u8];
19pub type CRC = [u8; 2];
20pub type ECount = u32;
21pub type Generator = u64;
22pub type Modulus = u64;
23pub type InterKey = u64;
24pub type Key = [u8; 16];
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27#[allow(dead_code)]
28pub enum Command {
29 Reset,
31 HostProtocolVersion,
32 GetSerialNumber,
33 Sync,
34 Disable,
35 Enable,
36 GetFirmwareVersion,
37 GetDatasetVersion,
38 PayoutAmount,
40 GetDenominationLevel,
41 HaltPayout,
42 GetDenominationRoute,
43 GetMinimumPayout,
44 SetCoinMechInhibits,
45 PayoutByDenomination,
46 SetGenerator,
47 RequestKeyExchange,
48 GetBuildRevision,
49 GetHopperOptions,
50 CashboxPayoutOperationData,
51 EventAck,
52 SetFixedEncryptionKey,
53 SetupRequest,
54 Poll,
55 GetAllLevels,
56 SetDenominationLevel,
57 CommunicationPassThrough,
58 SetDenominatinoRoute,
59 FloatAmount,
60 EmptyAll,
61 FloatByDenomination,
62 SetCoinMechGlobalInhibit,
63 SetModulus,
64 SetBaudRate,
65 SetHopperOptions,
66 SmartEmpty,
67 PollWithAck,
68 CoinMechOptions,
69 ResetFixedEncryptionKey,
70 SetCashboxPayoutLimit,
71 SetInhibits,
73 DisplayOn,
74 DisplayOff,
75 Reject,
76 UintData,
77 ChannelValueData,
78 ChannelSecurityData,
79 LastRejectCode,
80 Hold,
81 GetCounters,
82 ResetCounters,
83 Unknown(u8),
84}
85
86impl Command {
87 #[allow(dead_code)]
88 pub fn from_u8(n: u8) -> Command {
89 match n {
90 0x01 => Command::Reset,
91 0x06 => Command::HostProtocolVersion,
92 0x0C => Command::GetSerialNumber,
93 0x11 => Command::Sync,
94 0x09 => Command::Disable,
95 0x0A => Command::Enable,
96 0x20 => Command::GetFirmwareVersion,
97 0x21 => Command::GetDatasetVersion,
98 0x33 => Command::PayoutAmount,
99 0x35 => Command::GetDenominationLevel,
100 0x38 => Command::HaltPayout,
101 0x3C => Command::GetDenominationRoute,
102 0x3E => Command::GetMinimumPayout,
103 0x40 => Command::SetCoinMechInhibits,
104 0x46 => Command::PayoutByDenomination,
105 0x4A => Command::SetGenerator,
106 0x4C => Command::RequestKeyExchange,
107 0x4F => Command::GetBuildRevision,
108 0x51 => Command::GetHopperOptions,
109 0x53 => Command::CashboxPayoutOperationData,
110 0x57 => Command::EventAck,
111 0x60 => Command::SetFixedEncryptionKey,
112 0x05 => Command::SetupRequest,
113 0x07 => Command::Poll,
114 0x22 => Command::GetAllLevels,
115 0x34 => Command::SetDenominationLevel,
116 0x37 => Command::CommunicationPassThrough,
117 0x3B => Command::SetDenominatinoRoute,
118 0x3D => Command::FloatAmount,
119 0x3F => Command::EmptyAll,
120 0x44 => Command::FloatByDenomination,
121 0x49 => Command::SetCoinMechGlobalInhibit,
122 0x4B => Command::SetModulus,
123 0x4D => Command::SetBaudRate,
124 0x50 => Command::SetHopperOptions,
125 0x52 => Command::SmartEmpty,
126 0x56 => Command::PollWithAck,
127 0x5A => Command::CoinMechOptions,
128 0x61 => Command::ResetFixedEncryptionKey,
129 0x4E => Command::SetCashboxPayoutLimit,
130 0x02 => Command::SetInhibits,
131 0x03 => Command::DisplayOn,
132 0x04 => Command::DisplayOff,
133 0x08 => Command::Reject,
134 0x0D => Command::UintData,
135 0x0E => Command::ChannelValueData,
136 0x0F => Command::ChannelSecurityData,
137 0x17 => Command::LastRejectCode,
138 0x18 => Command::Hold,
139 0x58 => Command::GetCounters,
140 0x59 => Command::ResetCounters,
141 _ => Command::Unknown(n),
142 }
143 }
144
145 #[allow(dead_code)]
146 pub fn to_u8(&self) -> u8 {
147 match *self {
148 Command::Reset => 0x01,
149 Command::HostProtocolVersion => 0x06,
150 Command::GetSerialNumber => 0x0C,
151 Command::Sync => 0x11,
152 Command::Disable => 0x09,
153 Command::Enable => 0x0A,
154 Command::GetFirmwareVersion => 0x20,
155 Command::GetDatasetVersion => 0x21,
156 Command::PayoutAmount => 0x33,
157 Command::GetDenominationLevel => 0x35,
158 Command::HaltPayout => 0x38,
159 Command::GetDenominationRoute => 0x3C,
160 Command::GetMinimumPayout => 0x3E,
161 Command::SetCoinMechInhibits => 0x40,
162 Command::PayoutByDenomination => 0x46,
163 Command::SetGenerator => 0x4A,
164 Command::RequestKeyExchange => 0x4C,
165 Command::GetBuildRevision => 0x4F,
166 Command::GetHopperOptions => 0x51,
167 Command::CashboxPayoutOperationData => 0x53,
168 Command::EventAck => 0x57,
169 Command::SetFixedEncryptionKey => 0x60,
170 Command::SetupRequest => 0x05,
171 Command::Poll => 0x07,
172 Command::GetAllLevels => 0x22,
173 Command::SetDenominationLevel => 0x34,
174 Command::CommunicationPassThrough => 0x37,
175 Command::SetDenominatinoRoute => 0x3B,
176 Command::FloatAmount => 0x3D,
177 Command::EmptyAll => 0x3F,
178 Command::FloatByDenomination => 0x44,
179 Command::SetCoinMechGlobalInhibit => 0x49,
180 Command::SetModulus => 0x4B,
181 Command::SetBaudRate => 0x4D,
182 Command::SetHopperOptions => 0x50,
183 Command::SmartEmpty => 0x52,
184 Command::PollWithAck => 0x56,
185 Command::CoinMechOptions => 0x5A,
186 Command::ResetFixedEncryptionKey => 0x61,
187 Command::SetCashboxPayoutLimit => 0x4E,
188 Command::SetInhibits => 0x02,
189 Command::DisplayOn => 0x03,
190 Command::DisplayOff => 0x04,
191 Command::Reject => 0x08,
192 Command::UintData => 0x0D,
193 Command::ChannelValueData => 0x0E,
194 Command::ChannelSecurityData => 0x0F,
195 Command::LastRejectCode => 0x17,
196 Command::Hold => 0x18,
197 Command::GetCounters => 0x58,
198 Command::ResetCounters => 0x59,
199 Command::Unknown(n) => n,
200 }
201 }
202}
203
204#[derive(Debug, Clone, Copy, PartialEq, Eq)]
205#[allow(dead_code)]
206pub enum Response {
207 Ok,
208 CommandNotKnown,
209 WrongNumberOfParameters,
210 ParameterOutOfRange,
211 CommandCannotBeProcessed,
212 SoftwareError,
213 Fail,
214 KeyNotSet,
215 Unknown(u8),
216}
217
218impl Response {
219 #[allow(dead_code)]
220 pub fn from_u8(n: u8) -> Response {
221 match n {
222 0xF0 => Response::Ok,
223 0xF2 => Response::CommandNotKnown,
224 0xF3 => Response::WrongNumberOfParameters,
225 0xF4 => Response::ParameterOutOfRange,
226 0xF5 => Response::CommandCannotBeProcessed,
227 0xF6 => Response::SoftwareError,
228 0xF8 => Response::Fail,
229 0xFA => Response::KeyNotSet,
230 _ => Response::Unknown(n),
231 }
232 }
233
234 #[allow(dead_code)]
235 pub fn to_u8(&self) -> u8 {
236 match *self {
237 Response::Ok => 0xF0,
238 Response::CommandNotKnown => 0xF2,
239 Response::WrongNumberOfParameters => 0xF3,
240 Response::ParameterOutOfRange => 0xF4,
241 Response::CommandCannotBeProcessed => 0xF5,
242 Response::SoftwareError => 0xF6,
243 Response::Fail => 0xF8,
244 Response::KeyNotSet => 0xFA,
245 Response::Unknown(n) => n,
246 }
247 }
248}
249
250
251#[derive(Debug, Clone)]
252#[allow(dead_code)]
253pub enum ErrorType {
254 NotAResponse,
255 PartialMessage,
256 CRCError,
257 EncryptedCRCError,
258 SlaveIdError,
259 NoResponse,
260 UnknownResponse,
261 KeyNotSet,
262 UTF8Error,
263 KeyExchangeError,
264 CryptoError(SymmetricCipherError),
265 EncryptionCounterError,
266 NotOkResponse(Payload),
267 ParseError,
268}
269
270impl convert::From<SymmetricCipherError> for ErrorType {
271 fn from(e: SymmetricCipherError) -> ErrorType {
272 ErrorType::CryptoError(e)
273 }
274}
275
276impl convert::From<FromUtf8Error> for ErrorType {
277 fn from(_: FromUtf8Error) -> ErrorType {
278 ErrorType::UTF8Error
279 }
280}
281
282#[derive(Debug, Clone, Copy, PartialEq, Eq)]
283#[allow(dead_code)]
284pub enum Code {
285 CommandCode(Command),
286 ResponseCode(Response),
287}
288
289#[derive(Debug, Clone, PartialEq, Eq)]
290#[allow(dead_code)]
291pub struct CoinValue {
292 pub value: u32,
293 pub country_code: String,
294}
295
296impl CoinValue {
297 pub fn decode(data: &mut Vec<u8>) -> Result<CoinValue, ErrorType> {
298 let value_vec: Vec<u8> = data.drain(0..4 as usize).collect();
299 let country_code_vec: Vec<u8> = data.drain(0..3 as usize).collect();
300
301 let country_code = String::from_utf8(country_code_vec)?;
302
303 let val = vec_to_u32(&value_vec)?;
304
305 Ok(CoinValue {
306 value: val,
307 country_code: country_code,
308 })
309 }
310
311 pub fn decode_list(data: &mut Vec<u8>) -> Result<Vec<CoinValue>, ErrorType> {
312 let num = data.remove(0);
313 let mut coin_values = Vec::<CoinValue>::new();
314 for _ in 0..num {
315 coin_values.push(CoinValue::decode(data)?);
316 }
317 Ok(coin_values)
318 }
319
320 pub fn encode(&self) -> Vec<u8> {
321 let mut data = vec![];
322 let mut value_vec = u32_to_vec(self.value);
323 data.append(&mut value_vec);
324 data.extend_from_slice(self.country_code.as_bytes());
325
326 data
327 }
328
329 pub fn encode_list(list: &Vec<CoinValue>) -> Vec<u8> {
330 let mut data = vec![list.len() as u8];
331
332 for elem in list {
333 let mut elem_data = elem.encode();
334 data.append(&mut elem_data);
335 }
336 data
337 }
338}
339
340impl fmt::Display for CoinValue {
341 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
342 write!(f, "{} {}", self.value, self.country_code)
343 }
344}
345
346#[derive(Debug, Clone, PartialEq, Eq)]
347#[allow(dead_code)]
348pub struct CoinNumValue {
349 pub num: u16,
350 pub value: u32,
351 pub country_code: String,
352}
353
354impl CoinNumValue {
355 pub fn decode(data: &mut Vec<u8>) -> Result<CoinNumValue, ErrorType> {
356 let num_vec: Vec<u8> = data.drain(0..2 as usize).collect();
357 let value_vec: Vec<u8> = data.drain(0..4 as usize).collect();
358 let country_code_vec: Vec<u8> = data.drain(0..3 as usize).collect();
359
360 let country_code = String::from_utf8(country_code_vec)?;
361
362 let num = vec_to_u16(&num_vec)?;
363 let val = vec_to_u32(&value_vec)?;
364
365 Ok(CoinNumValue {
366 num: num,
367 value: val,
368 country_code: country_code,
369 })
370 }
371
372 pub fn decode_list(data: &mut Vec<u8>) -> Result<Vec<CoinNumValue>, ErrorType> {
373 let num = data.remove(0);
374 let mut coin_num_values = Vec::<CoinNumValue>::new();
375 for _ in 0..num {
376 coin_num_values.push(CoinNumValue::decode(data)?);
377 }
378 Ok(coin_num_values)
379 }
380
381 pub fn encode(&self) -> Vec<u8> {
382 let mut data = vec![];
383 let mut num_vec = u16_to_vec(self.num);
384 data.append(&mut num_vec);
385 let mut value_vec = u32_to_vec(self.value);
386 data.append(&mut value_vec);
387 data.extend_from_slice(self.country_code.as_bytes());
388
389 data
390 }
391
392 pub fn encode_list(list: &Vec<CoinNumValue>) -> Vec<u8> {
393 let mut data = vec![list.len() as u8];
394
395 for elem in list {
396 let mut elem_data = elem.encode();
397 data.append(&mut elem_data);
398 }
399 data
400 }
401}
402
403impl fmt::Display for CoinNumValue {
404 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
405 write!(f, "{} {}: {}", self.value, self.country_code, self.num)
406 }
407}
408
409#[derive(Debug, Clone, PartialEq, Eq)]
410#[allow(dead_code)]
411pub struct IncompleteCoinValue {
412 pub value: u32,
413 pub value_requested: u32,
414 pub country_code: String,
415}
416
417impl IncompleteCoinValue {
418 pub fn decode(data: &mut Vec<u8>) -> Result<IncompleteCoinValue, ErrorType> {
419 let value_vec: Vec<u8> = data.drain(0..4 as usize).collect();
420 let value_requested_vec: Vec<u8> = data.drain(0..4 as usize).collect();
421 let country_code_vec: Vec<u8> = data.drain(0..3 as usize).collect();
422
423 let country_code = String::from_utf8(country_code_vec)?;
424
425 let val = vec_to_u32(&value_vec)?;
426 let val_req = vec_to_u32(&value_requested_vec)?;
427
428 Ok(IncompleteCoinValue {
429 value: val,
430 value_requested: val_req,
431 country_code: country_code,
432 })
433 }
434
435 pub fn decode_list(data: &mut Vec<u8>) -> Result<Vec<IncompleteCoinValue>, ErrorType> {
436 let num = data.remove(0);
437 let mut coin_values = Vec::<IncompleteCoinValue>::new();
438 for _ in 0..num {
439 coin_values.push(IncompleteCoinValue::decode(data)?);
440 }
441 Ok(coin_values)
442 }
443
444 pub fn encode(&self) -> Vec<u8> {
445 let mut data = vec![];
446 let mut value_vec = u32_to_vec(self.value);
447 data.append(&mut value_vec);
448 let mut value_vec_req = u32_to_vec(self.value_requested);
449 data.append(&mut value_vec_req);
450 data.extend_from_slice(self.country_code.as_bytes());
451
452 data
453 }
454
455 pub fn encode_list(list: &Vec<IncompleteCoinValue>) -> Vec<u8> {
456 let mut data = vec![list.len() as u8];
457
458 for elem in list {
459 let mut elem_data = elem.encode();
460 data.append(&mut elem_data);
461 }
462 data
463 }
464}
465
466
467
468#[derive(Debug, Clone, PartialEq, Eq)]
469#[allow(dead_code)]
470pub struct CashboxPayoutData {
471 pub known: Vec<CoinNumValue>,
472 pub unknown: u32,
473}
474
475impl CashboxPayoutData {
476 pub fn decode(data: &mut Vec<u8>) -> Result<CashboxPayoutData, ErrorType> {
477 let known = CoinNumValue::decode_list(data)?;
478 let unknown_vec: Vec<u8> = data.drain(0..4 as usize).collect();
479 let unknown = vec_to_u32(&unknown_vec)?;
480
481 Ok(CashboxPayoutData {
482 known: known,
483 unknown: unknown,
484 })
485 }
486
487 pub fn encode(&self) -> Vec<u8> {
488 let mut data = vec![];
489 let mut known = CoinNumValue::encode_list(&self.known);
490 data.append(&mut known);
491
492 let mut unknown_vec = u32_to_vec(self.unknown);
493 data.append(&mut unknown_vec);
494
495 data
496 }
497}
498
499
500
501#[derive(Debug)]
502#[derive(Clone)]
503#[allow(dead_code)]
504pub enum DeviceType {
505 BillValidator,
506 SmartHopper,
507}
508
509#[derive(Debug, Clone, PartialEq, Eq)]
510#[allow(dead_code)]
511pub enum FraudAttemptData {
512 BillValidatorData { channel: u8 },
513 SmartHopperData { dispensed: Vec<CoinValue> },
514}
515
516#[derive(Debug, Clone, PartialEq, Eq)]
517#[allow(dead_code)]
518pub enum PollEvent {
519 SlaveReset,
520 Disabled,
521 FraudAttempt { data: FraudAttemptData },
522 Initialising,
523 Dispensing { dispensed: Vec<CoinValue> },
524 Dispensed { dispensed: Vec<CoinValue> },
525 CoinsLow,
526 HopperJammed { dispensed: Vec<CoinValue> },
527 Halted { dispensed: Vec<CoinValue> },
528 Floating { floated: Vec<CoinValue> },
529 Floated { floated: Vec<CoinValue> },
530 Timeout { dispensed: Vec<CoinValue> },
531 IncompletePayout { dispensed: Vec<IncompleteCoinValue> },
532 IncompleteFloat { floated: Vec<IncompleteCoinValue> },
533 CashboxPaid { dispensed: Vec<CoinValue> },
534 CoinCredit { credit: CoinValue },
535 CoinMechJammed,
536 CoinMechReturnActive,
537 Emptying,
538 Emptied,
539 SmartEmptying { dispensed: Vec<CoinValue> },
540 SmartEmptied { dispensed: Vec<CoinValue> },
541 CalibrationFailed { error_code: u8 },
542 CoinMechError { error_code: u8 },
543 AttachedCoinMechDisabled,
544 AttachedCoinMechEnabled,
545 Read { channel: u8 },
546 NoteCredit { channel: u8 },
547 Rejecting,
548 Rejected,
549 Stacking,
550 Stacked,
551 SafeJam,
552 UnsafeJam,
553 StackerFull,
554 NoteClearedFromFront { channel: u8 },
555 NoteClearedIntoCashbox { channel: u8 },
556 ChannelDisable,
557 TicketInBezel,
558 PrintedToCashbox,
559 Unknown(u8),
560}
561
562impl PollEvent {
563 #[allow(dead_code)]
564 pub fn parse_first(data: &mut Vec<u8>, device_type: &DeviceType) -> Result<Option<PollEvent>, ErrorType> {
565
566 if data.len() == 0 {
569 return Ok(None);
570 }
571 let code = data.remove(0);
572 match code {
573 0xF1 => Ok(Some(PollEvent::SlaveReset)),
574 0xE8 => Ok(Some(PollEvent::Disabled)),
575 0xE6 => {
576 match device_type {
577 &DeviceType::BillValidator => {
578 let channel = data.remove(0);
579 Ok(Some(PollEvent::FraudAttempt { data: FraudAttemptData::BillValidatorData { channel: channel } }))
580 }
581 &DeviceType::SmartHopper => {
582 let coin_values = CoinValue::decode_list(data)?;
583 Ok(Some(PollEvent::FraudAttempt { data: FraudAttemptData::SmartHopperData { dispensed: coin_values } }))
584 }
585 }
586 }
587 0xB6 => Ok(Some(PollEvent::Initialising)),
588 0xDA => {
589 let coin_values = CoinValue::decode_list(data)?;
590 Ok(Some(PollEvent::Dispensing { dispensed: coin_values }))
591 }
592 0xD2 => {
593 let coin_values = CoinValue::decode_list(data)?;
594 Ok(Some(PollEvent::Dispensed { dispensed: coin_values }))
595 }
596 0xD3 => Ok(Some(PollEvent::CoinsLow)),
597 0xD5 => {
598 let coin_values = CoinValue::decode_list(data)?;
599 Ok(Some(PollEvent::HopperJammed { dispensed: coin_values }))
600 }
601 0xD6 => {
602 let coin_values = CoinValue::decode_list(data)?;
603 Ok(Some(PollEvent::Halted { dispensed: coin_values }))
604 }
605 0xD7 => {
606 let coin_values = CoinValue::decode_list(data)?;
607 Ok(Some(PollEvent::Floating { floated: coin_values }))
608 }
609 0xD8 => {
610 let coin_values = CoinValue::decode_list(data)?;
611 Ok(Some(PollEvent::Floated { floated: coin_values }))
612 }
613 0xD9 => {
614 let coin_values = CoinValue::decode_list(data)?;
615 Ok(Some(PollEvent::Timeout { dispensed: coin_values }))
616 }
617 0xDC => {
618 let coin_values = IncompleteCoinValue::decode_list(data)?;
619 Ok(Some(PollEvent::IncompletePayout { dispensed: coin_values }))
620 }
621 0xDD => {
622 let coin_values = IncompleteCoinValue::decode_list(data)?;
623 Ok(Some(PollEvent::IncompleteFloat { floated: coin_values }))
624 }
625 0xDE => {
626 let coin_values = CoinValue::decode_list(data)?;
627 Ok(Some(PollEvent::CashboxPaid { dispensed: coin_values }))
628 }
629 0xDF => {
630 let coin_value = CoinValue::decode(data)?;
631 Ok(Some(PollEvent::CoinCredit { credit: coin_value }))
632 }
633 0xC4 => Ok(Some(PollEvent::CoinMechJammed)),
634 0xC5 => Ok(Some(PollEvent::CoinMechReturnActive)),
635 0xC2 => Ok(Some(PollEvent::Emptying)),
636 0xC3 => Ok(Some(PollEvent::Emptied)),
637 0xB3 => {
638 let coin_values = CoinValue::decode_list(data)?;
639 Ok(Some(PollEvent::SmartEmptying { dispensed: coin_values }))
640 }
641 0xB4 => {
642 let coin_values = CoinValue::decode_list(data)?;
643 Ok(Some(PollEvent::SmartEmptied { dispensed: coin_values }))
644 }
645 0x83 => {
646 let error_code = data.remove(0);
647 Ok(Some(PollEvent::CalibrationFailed { error_code: error_code }))
648 }
649 0xB7 => {
650 let error_code = data.remove(0);
651 Ok(Some(PollEvent::CoinMechError { error_code: error_code }))
652 }
653 0xBD => Ok(Some(PollEvent::AttachedCoinMechDisabled)),
654 0xBE => Ok(Some(PollEvent::AttachedCoinMechEnabled)),
655 0xEF => {
656 let channel = data.remove(0);
657 Ok(Some(PollEvent::Read { channel: channel }))
658 }
659 0xEE => {
660 let channel = data.remove(0);
661 Ok(Some(PollEvent::NoteCredit { channel: channel }))
662 }
663 0xED => Ok(Some(PollEvent::Rejecting)),
664 0xEC => Ok(Some(PollEvent::Rejected)),
665 0xCC => Ok(Some(PollEvent::Stacking)),
666 0xEB => Ok(Some(PollEvent::Stacked)),
667 0xEA => Ok(Some(PollEvent::SafeJam)),
668 0xE9 => Ok(Some(PollEvent::UnsafeJam)),
669 0xE7 => Ok(Some(PollEvent::StackerFull)),
670 0xE1 => {
671 let channel = data.remove(0);
672 Ok(Some(PollEvent::NoteClearedFromFront { channel: channel }))
673 }
674 0xE2 => {
675 let channel = data.remove(0);
676 Ok(Some(PollEvent::NoteClearedIntoCashbox { channel: channel }))
677 }
678 0xB5 => Ok(Some(PollEvent::ChannelDisable)),
679 0xAD => Ok(Some(PollEvent::TicketInBezel)),
680 0xAF => Ok(Some(PollEvent::PrintedToCashbox)),
681 _ => Ok(Some(PollEvent::Unknown(code))),
682 }
683 }
684
685 pub fn encode(&self) -> Vec<u8> {
686 match self {
687 &PollEvent::SlaveReset => vec![0xF1],
688 &PollEvent::Disabled => vec![0xE8],
689 &PollEvent::FraudAttempt { ref data } => {
690 match data {
691 &FraudAttemptData::BillValidatorData { channel } => vec![0xE6, channel],
692 &FraudAttemptData::SmartHopperData { dispensed: ref coin_values } => {
693 let mut res = vec![0xE6];
694 let mut encoded = CoinValue::encode_list(coin_values);
695 res.append(&mut encoded);
696 res
697 }
698 }
699 }
700 &PollEvent::Initialising => vec![0xB6],
701 &PollEvent::Dispensing { dispensed: ref coin_values } => {
702 let mut res = vec![0xDA];
703 let mut encoded = CoinValue::encode_list(coin_values);
704 res.append(&mut encoded);
705 res
706 }
707 &PollEvent::Dispensed { dispensed: ref coin_values } => {
708 let mut res = vec![0xD2];
709 let mut encoded = CoinValue::encode_list(coin_values);
710 res.append(&mut encoded);
711 res
712 }
713 &PollEvent::CoinsLow => vec![0xD3],
714 &PollEvent::HopperJammed { dispensed: ref coin_values } => {
715 let mut res = vec![0xD5];
716 let mut encoded = CoinValue::encode_list(coin_values);
717 res.append(&mut encoded);
718 res
719 }
720 &PollEvent::Halted { dispensed: ref coin_values } => {
721 let mut res = vec![0xD6];
722 let mut encoded = CoinValue::encode_list(coin_values);
723 res.append(&mut encoded);
724 res
725 }
726 &PollEvent::Floating { floated: ref coin_values } => {
727 let mut res = vec![0xD7];
728 let mut encoded = CoinValue::encode_list(coin_values);
729 res.append(&mut encoded);
730 res
731 }
732 &PollEvent::Floated { floated: ref coin_values } => {
733 let mut res = vec![0xD8];
734 let mut encoded = CoinValue::encode_list(coin_values);
735 res.append(&mut encoded);
736 res
737 }
738 &PollEvent::Timeout { dispensed: ref coin_values } => {
739 let mut res = vec![0xD9];
740 let mut encoded = CoinValue::encode_list(coin_values);
741 res.append(&mut encoded);
742 res
743 }
744 &PollEvent::IncompletePayout { dispensed: ref coin_values } => {
745 let mut res = vec![0xDC];
746 let mut encoded = IncompleteCoinValue::encode_list(coin_values);
747 res.append(&mut encoded);
748 res
749 }
750 &PollEvent::IncompleteFloat { floated: ref coin_values } => {
751 let mut res = vec![0xDD];
752 let mut encoded = IncompleteCoinValue::encode_list(coin_values);
753 res.append(&mut encoded);
754 res
755 }
756 &PollEvent::CashboxPaid { dispensed: ref coin_values } => {
757 let mut res = vec![0xDE];
758 let mut encoded = CoinValue::encode_list(coin_values);
759 res.append(&mut encoded);
760 res
761 }
762 &PollEvent::CoinCredit { credit: ref coin_value } => {
763 let mut res = vec![0xDF];
764 let mut encoded = coin_value.encode();
765 res.append(&mut encoded);
766 res
767 }
768 &PollEvent::CoinMechJammed => vec![0xC4],
769 &PollEvent::CoinMechReturnActive => vec![0xC5],
770 &PollEvent::Emptying => vec![0xC2],
771 &PollEvent::Emptied => vec![0xC3],
772 &PollEvent::SmartEmptying { dispensed: ref coin_values } => {
773 let mut res = vec![0xB3];
774 let mut encoded = CoinValue::encode_list(coin_values);
775 res.append(&mut encoded);
776 res
777 }
778 &PollEvent::SmartEmptied { dispensed: ref coin_values } => {
779 let mut res = vec![0xB4];
780 let mut encoded = CoinValue::encode_list(coin_values);
781 res.append(&mut encoded);
782 res
783 }
784 &PollEvent::CalibrationFailed { error_code } => vec![0x83, error_code],
785 &PollEvent::CoinMechError { error_code } => vec![0xB7, error_code],
786 &PollEvent::AttachedCoinMechDisabled => vec![0xBD],
787 &PollEvent::AttachedCoinMechEnabled => vec![0xBE],
788 &PollEvent::Read { channel } => vec![0xEF, channel],
789 &PollEvent::NoteCredit { channel } => vec![0xEE, channel],
790 &PollEvent::Rejecting => vec![0xED],
791 &PollEvent::Rejected => vec![0xEC],
792 &PollEvent::Stacking => vec![0xCC],
793 &PollEvent::Stacked => vec![0xEB],
794 &PollEvent::SafeJam => vec![0xEA],
795 &PollEvent::UnsafeJam => vec![0xE9],
796 &PollEvent::StackerFull => vec![0xE7],
797 &PollEvent::NoteClearedFromFront { channel } => vec![0xE1, channel],
798 &PollEvent::NoteClearedIntoCashbox { channel } => vec![0xE2, channel],
799 &PollEvent::ChannelDisable => vec![0xB5],
800 &PollEvent::TicketInBezel => vec![0xAD],
801 &PollEvent::PrintedToCashbox => vec![0xAF],
802 &PollEvent::Unknown(val) => vec![val],
803 }
804 }
805}
806
807#[derive(Debug)]
808#[derive(Clone)]
809#[allow(dead_code)]
810pub enum PayoutError {
811 NotEnoughValue,
812 CannotPayExactAmount,
813 DeviceBusy,
814 DeviceDisabled,
815 Unknown(u8),
816}
817
818impl PayoutError {
819 fn from_u8(n: u8) -> PayoutError {
820 match n {
821 1 => PayoutError::NotEnoughValue,
822 2 => PayoutError::CannotPayExactAmount,
823 3 => PayoutError::DeviceBusy,
824 4 => PayoutError::DeviceDisabled,
825 _ => PayoutError::Unknown(n),
826 }
827 }
828}
829
830pub fn calc_crc(data: &Vec<u8>) -> CRC {
831 let poly = 0x8005;
832 let mut crc = 0xFFFFu16;
833
834 for byte in data {
835 crc ^= (*byte as u16) << 8;
836 for _ in 0..8 {
837 if (crc & 0x8000) != 0 {
838 crc = ((crc << 1) & 0xffff) ^ poly;
839 } else {
840 crc <<= 1;
841 }
842 }
843 }
844 [(crc & 0xff) as u8, (crc >> 8 & 0xff) as u8]
845}
846
847pub fn vec_to_u16(vector: &Vec<u8>) -> Result<u16, ErrorType> {
848 let mut rdr = Cursor::new(vector);
849 match rdr.read_u16::<LittleEndian>() {
850 Ok(data) => Ok(data),
851 Err(_) => Err(ErrorType::ParseError),
852 }
853}
854
855#[allow(dead_code)]
856pub fn u16_to_vec(num: u16) -> Vec<u8> {
857 let mut data = vec![];
858 data.write_u16::<LittleEndian>(num).unwrap();
859 data
860}
861
862pub fn vec_to_u32(vector: &Vec<u8>) -> Result<u32, ErrorType> {
863 let mut rdr = Cursor::new(vector);
864 match rdr.read_u32::<LittleEndian>() {
865 Ok(data) => Ok(data),
866 Err(_) => Err(ErrorType::ParseError),
867 }
868}
869
870pub fn u32_to_vec(num: u32) -> Vec<u8> {
871 let mut data = vec![];
872 data.write_u32::<LittleEndian>(num).unwrap();
873 data
874}
875
876pub fn vec_to_u64(vector: &Vec<u8>) -> Result<u64, ErrorType> {
877 let mut rdr = Cursor::new(vector);
878 match rdr.read_u64::<LittleEndian>() {
879 Ok(data) => Ok(data),
880 Err(_) => Err(ErrorType::ParseError),
881 }
882}
883
884pub fn u64_to_vec(num: u64) -> Vec<u8> {
885 let mut data = vec![];
886 data.write_u64::<LittleEndian>(num).unwrap();
887 data
888}
889
890
891#[derive(Debug, Clone, PartialEq, Eq)]
892#[allow(dead_code)]
893pub struct Payload {
894 pub code: Code,
895 pub data: Data,
896 pub encrypted: bool,
897}
898
899
900impl Payload {
901 pub fn new_u64(code: Code, data_u64: u64, encrypted: bool) -> Payload {
902 Payload {
903 code: code,
904 data: u64_to_vec(data_u64),
905 encrypted: encrypted,
906 }
907 }
908
909 pub fn encode(&self, ecount: ECount, key: Option<Key>) -> Result<Vec<u8>, ErrorType> {
910 let mut temp = Vec::<u8>::new();
911 let code_byte = match &self.code {
912 &Code::CommandCode(ref cmd) => cmd.to_u8(),
913 &Code::ResponseCode(ref resp) => resp.to_u8(),
914 };
915 temp.push(code_byte);
916 temp.append(&mut self.data.clone());
917
918 match self.encrypted {
919 true => {
920 if let None = key {
921 Err(ErrorType::KeyNotSet)
922 } else {
923 Payload::encrypt(&temp, ecount, key.unwrap())
924 }
925 }
926 false => Ok(temp),
927 }
928 }
929
930 pub fn decode(raw: &Vec<u8>, ecount: ECount, key: Option<Key>) -> Result<Payload, ErrorType> {
931 let encrypted = raw[0] == STEX;
932 let mut data = match encrypted {
933 true => {
934 if let None = key {
935 return Err(ErrorType::KeyNotSet);
936 } else {
937 Payload::decrypt(raw, ecount, key.unwrap())?
938 }
939 }
940 false => raw.clone(),
941 };
942 let code_byte = data.remove(0);
943
944 Ok(Payload {
946 code: Code::ResponseCode(Response::from_u8(code_byte)),
947 data: data,
948 encrypted: encrypted,
949 })
950 }
951
952 fn encrypt(raw_payload: &Vec<u8>, ecount: ECount, key: Key) -> Result<Vec<u8>, ErrorType> {
953 let mut to_encode = Vec::<u8>::new();
954 to_encode.push(raw_payload.len() as u8);
955
956 let mut ecount_vec = u32_to_vec(ecount);
957 to_encode.append(&mut ecount_vec);
958
959 to_encode.extend_from_slice(raw_payload);
960 let packing_len = 16 - ((to_encode.len() + 2) % 16);
962 to_encode.extend(iter::repeat(0u8).take(packing_len));
963
964 let ecrc = calc_crc(&to_encode);
966 to_encode.extend_from_slice(&ecrc);
967
968 let enc_len = to_encode.len();
969
970 let aes_enc = aessafe::AesSafe128Encryptor::new(&key[..]);
971 let mut encryptor = blockmodes::EcbEncryptor::new(aes_enc, blockmodes::NoPadding);
972
973 let mut out = Vec::<u8>::with_capacity(enc_len);
974 out.resize(enc_len, 0u8);
975
976 {
977 let mut buff_in = RefReadBuffer::new(&to_encode);
978 let mut buff_out = RefWriteBuffer::new(&mut out);
979
980 match encryptor.encrypt(&mut buff_in, &mut buff_out, true) {
981 Ok(BufferResult::BufferUnderflow) => {}
982 Ok(BufferResult::BufferOverflow) => {
983 panic!("ESSP Encryption buffer overflow"); }
985 Err(err) => return Err(ErrorType::CryptoError(err)),
986 }
987 }
988 out.insert(0, STEX);
992
993 Ok(out)
994 }
995
996 fn decrypt(raw: &Vec<u8>, ecount: ECount, key: Key) -> Result<Vec<u8>, ErrorType> {
997 let mut to_decode = raw.clone();
998
999 to_decode.remove(0);
1001
1002 let dec_len = to_decode.len();
1004
1005 let aes_dec = aessafe::AesSafe128Decryptor::new(&key[..]);
1006 let mut decryptor = blockmodes::EcbDecryptor::new(aes_dec, blockmodes::NoPadding);
1007
1008 let mut out = Vec::<u8>::with_capacity(dec_len);
1009 out.resize(dec_len, 0u8);
1010
1011 {
1012 let mut buff_in = RefReadBuffer::new(&to_decode);
1013 let mut buff_out = RefWriteBuffer::new(&mut out);
1014
1015 match decryptor.decrypt(&mut buff_in, &mut buff_out, true) {
1016 Ok(BufferResult::BufferUnderflow) => {}
1017 Ok(BufferResult::BufferOverflow) => {
1018 panic!("ESSP Decryption buffer overflow!"); }
1020 Err(err) => return Err(ErrorType::CryptoError(err)),
1021 }
1022 }
1023 let crc_2 = out.pop().unwrap();
1026 let crc_1 = out.pop().unwrap();
1027
1028 let received_crc: CRC = [crc_1, crc_2];
1029 let expected_crc = calc_crc(&out);
1030 if received_crc != expected_crc {
1031 return Err(ErrorType::EncryptedCRCError);
1032 }
1033
1034 let payload_len = out.remove(0);
1035 let mut payload = out.split_off(4);
1040 let received_ecount = vec_to_u32(&out)?;
1041
1042 if received_ecount != ecount {
1044 return Err(ErrorType::EncryptionCounterError);
1045 }
1046
1047 let _ = payload.split_off(payload_len as usize);
1049
1050 Ok(payload)
1053 }
1054
1055 pub fn parse_as_u64(&self) -> Result<u64, ErrorType> {
1056 vec_to_u64(&self.data)
1057 }
1058
1059 pub fn parse_as_u32(&self) -> Result<u32, ErrorType> {
1060 vec_to_u32(&self.data)
1061 }
1062
1063 pub fn parse_as_payout_error(&self) -> PayoutError {
1064 PayoutError::from_u8(self.data[0])
1065 }
1066
1067 pub fn parse_as_poll_response(&self, device_type: &DeviceType) -> Result<Vec<PollEvent>, ErrorType> {
1068 let mut event_data = self.data.clone();
1069 let mut events = Vec::<PollEvent>::new();
1070 while event_data.len() > 0 {
1071 let event = PollEvent::parse_first(&mut event_data, &device_type)?;
1072 if let Some(event) = event {
1073 events.push(event);
1074 }
1075 }
1076 Ok(events)
1077 }
1078
1079 pub fn parse_as_coin_values(&self) -> Result<Vec<CoinNumValue>, ErrorType> {
1080 CoinNumValue::decode_list(&mut self.data.clone())
1081 }
1082
1083 pub fn parse_as_cashbox_payout_data(&self) -> Result<CashboxPayoutData, ErrorType> {
1084 CashboxPayoutData::decode(&mut self.data.clone())
1085 }
1086}
1087
1088#[derive(Debug, Clone, PartialEq, Eq)]
1089#[allow(dead_code)]
1090pub struct Message {
1091 pub slave_id: SlaveID,
1092 pub payload: Payload,
1093}
1094
1095impl Message {
1096 fn byte_stuff(data: &Data) -> Data {
1098 let mut temp = Vec::<u8>::new();
1100 temp.push(data[0]);
1101
1102 for byte in data[1..].iter() {
1104 if *byte == STX {
1105 temp.push(STX);
1106 }
1107 temp.push(*byte);
1108 }
1109
1110 temp
1111 }
1112
1113 fn byte_destuff(data: &DataSlice) -> Data {
1114 let mut res = vec![];
1115
1116 let mut previous_byte = 0u8;
1117 for i in 0..data.len() {
1118 if previous_byte == STX && data[i] == STX {
1119 previous_byte = 0u8;
1120 } else {
1121 previous_byte = data[i];
1122 res.push(previous_byte);
1123 }
1124 }
1125
1126 res
1127 }
1128
1129 pub fn encode(&self, seq: bool, ecount: ECount, key: Option<Key>) -> Result<Vec<u8>, ErrorType> {
1130 let mut temp = Vec::<u8>::new();
1131 if seq {
1132 temp.push(self.slave_id + 128u8);
1133 } else {
1134 temp.push(self.slave_id);
1135 }
1136
1137 let mut encoded_payload = self.payload.encode(ecount, key)?;
1138 temp.push(encoded_payload.len() as u8);
1139 temp.append(&mut encoded_payload);
1140
1141 let crc = calc_crc(&temp);
1143 temp.extend_from_slice(&crc);
1144
1145 temp.insert(0, STX);
1147
1148 Ok(Message::byte_stuff(&temp))
1150 }
1151
1152 pub fn decode(buffer: &mut Vec<u8>, seq: bool, ecount: ECount, key: Option<Key>) -> Result<Message, ErrorType> {
1153 if buffer.len() < 3 {
1154 return Err(ErrorType::PartialMessage);
1155 }
1156
1157 while buffer[0] != STX || buffer[1] == STX {
1158 warn!("Message alignment error, clearing buffer until next STX! Bad buffer: {:?}", buffer);
1159
1160 let mut invalid_message: Vec<u8> = vec![];
1161 invalid_message.push(buffer.remove(0));
1162
1163 let stx_pos = buffer.iter().position(|&r| r == STX);
1164 match stx_pos {
1165 Some(pos) => {
1166 invalid_message.extend(buffer.drain(0..pos as usize));
1167 warn!("Clearing {} bytes from buffer: {:?}, remaining buffer: {:?}", pos + 1, invalid_message, buffer);
1168 }
1169 None => {
1170 invalid_message.append(buffer);
1171 buffer.clear();
1172 warn!("Clearing from buffer: {:?}, buffer is empty", invalid_message);
1173 }
1174 }
1175
1176 if buffer.len() < 3 {
1177 return Err(ErrorType::PartialMessage);
1178 }
1179 }
1180
1181 trace!("Result buffer: {:?}", buffer);
1182
1183 let buffer_size: usize = buffer.len();
1184 if buffer_size < 3 {
1185 return Err(ErrorType::PartialMessage);
1186 }
1187
1188 let mut slave_id = buffer[1];
1189 let received_seq;
1190 if slave_id >= 128 {
1191 received_seq = true;
1192 slave_id -= 128;
1193 } else {
1194 received_seq = false;
1195 }
1196
1197 if slave_id > MAX_SLAVE_ID {
1198 debug!("Invalid slave ID received: {:?}", slave_id);
1199 buffer.drain(0..2);
1200 return Err(ErrorType::SlaveIdError);
1201 }
1202
1203 trace!("Decoding buffer: {:?}", buffer);
1204
1205 let payload_size = buffer[2] as usize;
1206 let expected_msg_size = payload_size + 5;
1207
1208 let mut to_read: usize = 0;
1209 let mut destuffed: Vec<u8> = vec![];
1210 let mut destuffed_size = 0;
1211
1212 trace!("Guessing message size: {}", expected_msg_size);
1213
1214 while destuffed_size != expected_msg_size {
1215 to_read = to_read + expected_msg_size - destuffed_size;
1216
1217 if buffer_size < to_read {
1218 trace!("Partial message: {:?} - size: {}, expected: {}", buffer, buffer_size, to_read);
1219 return Err(ErrorType::PartialMessage);
1220 };
1221
1222 trace!("Message to destuff: {:?}", &buffer[0..to_read]);
1223
1224 destuffed = Message::byte_destuff(&buffer[0..to_read]);
1225 destuffed_size = destuffed.len();
1226
1227 let removed = to_read - destuffed_size;
1228 trace!("Byte stuffing removed, got: {:?} - diff: {}", destuffed, removed);
1229 }
1230
1231 buffer.drain(0..to_read);
1233 if received_seq == seq {
1236 }
1240
1241 if !Message::validate_crc(&destuffed) {
1242 error!("CRC error on ESSP message: {:?}", destuffed);
1243 return Err(ErrorType::CRCError);
1244 }
1245
1246 trace!("Received valid ESSP message for slaveID: {:?}, seq {:?} - raw message {:?}", slave_id, received_seq, destuffed);
1247
1248 let raw_payload = destuffed.drain(3..(payload_size + 3)).collect();
1250
1251 let decoded_payload = Payload::decode(&raw_payload, ecount, key)?;
1252
1253 trace!("Decoded: {:?}", decoded_payload);
1254
1255 Ok(Message {
1256 slave_id: slave_id,
1257 payload: decoded_payload,
1258 })
1259 }
1260
1261 pub fn validate_crc(raw: &Vec<u8>) -> bool {
1262 if raw.is_empty() {
1263 error!("Validate CRC called on empty ESSP message!");
1264 return false;
1265 }
1266
1267 let mut data = raw.clone();
1268 data.remove(0);
1270
1271 let crc2 = data.pop().unwrap();
1272 let crc1 = data.pop().unwrap();
1273
1274 [crc1, crc2] == calc_crc(&data)
1275 }
1276}
1277
1278fn mod_pow(num: u64, pow: u64, modulo: u64) -> u64 {
1279 let mut num = num;
1280 let mut pow = pow;
1281 let mut ret = 1;
1282 while pow > 0 {
1283 if pow & 1 == 1 {
1284 ret = (ret * num) % modulo;
1285 }
1286 pow >>= 1;
1287 num = (num * num) % modulo;
1288 }
1289 ret
1290}
1291
1292pub fn calc_inter_key(generator: Generator, modulus: Modulus) -> (InterKey, InterKey) {
1293 let mut os_rng = OsRng::new().unwrap();
1294 let host_rnd = os_rng.next_u64();
1295
1296 let inter_key: InterKey = mod_pow(generator, host_rnd, modulus);
1297
1298 (inter_key, host_rnd)
1299}
1300
1301pub fn calc_key(slave_inter_key: InterKey, host_rnd: InterKey, modulus: Modulus, fix_key: InterKey) -> [u8; 16] {
1302 let negotiated_key = mod_pow(slave_inter_key, host_rnd, modulus);
1303 let mut negotiated_key_vec = u64_to_vec(negotiated_key);
1304 let mut fix_key_vec = u64_to_vec(fix_key);
1305 let mut key_calc = vec![];
1306
1307 key_calc.append(&mut fix_key_vec);
1309 key_calc.append(&mut negotiated_key_vec);
1310
1311 let mut array = [0u8; 16];
1312 for (&x, p) in key_calc.iter().zip(array.iter_mut()) {
1313 *p = x;
1314 }
1315 array
1316}
1317
1318
1319#[cfg(test)]
1320mod tests {
1321 use super::*;
1322
1323 #[test]
1324 fn essp_crc() {
1325 let data = vec![128, 1, 240];
1326 assert_eq!(calc_crc(&data), [35, 128]);
1327 }
1328
1329 #[test]
1330 fn essp_destuff_payload() {
1331 let buffer_original = vec![127, 16, 17, 126, 3, 4, 138, 40, 34, 127, 127, 49, 153, 193, 182, 35, 94, 11, 49, 201, 112];
1332 let buffer_expected = vec![127, 16, 17, 126, 3, 4, 138, 40, 34, 127, 49, 153, 193, 182, 35, 94, 11, 49, 201, 112];
1333 let res = Message::byte_destuff(&buffer_original);
1334 assert_eq!(res, buffer_expected);
1335 }
1336
1337 #[test]
1338 fn essp_destuff_crc1() {
1339 let buffer_original = vec![127, 16, 17, 126, 202, 137, 148, 122, 207, 20, 164, 91, 71, 249, 182, 87, 229, 42, 127, 127, 220];
1340 let buffer_expected = vec![127, 16, 17, 126, 202, 137, 148, 122, 207, 20, 164, 91, 71, 249, 182, 87, 229, 42, 127, 220];
1341 let res = Message::byte_destuff(&buffer_original);
1342 assert_eq!(res, buffer_expected);
1343 }
1344
1345 #[test]
1346 fn essp_destuff_crc2() {
1347 let buffer_original = vec![127, 168, 17, 126, 147, 14, 209, 35, 122, 97, 150, 16, 194, 114, 247, 10, 162, 95, 197, 47, 131, 127, 127];
1348 let buffer_expected = vec![127, 168, 17, 126, 147, 14, 209, 35, 122, 97, 150, 16, 194, 114, 247, 10, 162, 95, 197, 47, 131, 127];
1349 let res = Message::byte_destuff(&buffer_original);
1350 assert_eq!(res, buffer_expected);
1351 }
1352
1353 #[test]
1354 fn essp_double_destuff() {
1355 let buffer_original = vec![127, 16, 18, 126, 3, 4, 138, 40, 34, 127, 127, 127, 127, 49, 153, 193, 182, 35, 94, 11, 49, 201, 112];
1356 let buffer_expected = vec![127, 16, 18, 126, 3, 4, 138, 40, 34, 127, 127, 49, 153, 193, 182, 35, 94, 11, 49, 201, 112];
1357 let res = Message::byte_destuff(&buffer_original);
1358 assert_eq!(res, buffer_expected);
1359 }
1360
1361 #[test]
1362 fn essp_decode_partial() {
1363 let mut buffer = vec![127, 168, 2, 240, 127, 127, 49, 129, 127, 16, 17, 126, 3, 4, 138, 40, 34, 127, 127, 49, 153, 193, 182, 35, 94, 11, 49];
1364
1365 let res = Message::decode(&mut buffer, false, 0, None);
1366 let expected = Message {
1367 slave_id: 40,
1368 payload: Payload {
1369 code: Code::ResponseCode(Response::Ok),
1370 data: vec![127],
1371 encrypted: false,
1372 },
1373 };
1374 assert_eq!(res.unwrap(), expected);
1375
1376 let res = Message::decode(&mut buffer, false, 0, None);
1377 assert!(res.is_err());
1378 match res.unwrap_err() {
1379 ErrorType::PartialMessage => {}
1380 other => panic!("Expected PartialMessage, got: {:?}", other),
1381 }
1382 assert_eq!(buffer.len(), 19);
1383 }
1384
1385 #[test]
1386 fn essp_decode_double_stuffed() {
1387 let mut buffer = vec![127, 168, 2, 240, 127, 127, 49, 129, 127, 168, 5, 240, 100, 127, 127, 127, 127, 200, 174, 30];
1388
1389 let mut res = Message::decode(&mut buffer, false, 0, None);
1391 let expected1 = Message {
1392 slave_id: 40,
1393 payload: Payload {
1394 code: Code::ResponseCode(Response::Ok),
1395 data: vec![127],
1396 encrypted: false,
1397 },
1398 };
1399 assert_eq!(res.unwrap(), expected1);
1400
1401 res = Message::decode(&mut buffer, false, 0, None);
1403 let expected2 = Message {
1404 slave_id: 40,
1405 payload: Payload {
1406 code: Code::ResponseCode(Response::Ok),
1407 data: vec![100, 127, 127, 200],
1408 encrypted: false,
1409 },
1410 };
1411 assert_eq!(res.unwrap(), expected2);
1412 assert!(buffer.is_empty());
1413 }
1414
1415 #[test]
1421 fn essp_decode_unencrypted() {
1422 let mut buffer = vec![127, 168, 9, 240, 199, 63, 16, 0, 0, 0, 0, 0, 254, 238];
1423 let res = Message::decode(&mut buffer, false, 0, None);
1424 assert!(res.is_ok());
1425 let expected = Message {
1426 slave_id: 40,
1427 payload: Payload {
1428 code: Code::ResponseCode(Response::Ok),
1429 data: vec![199, 63, 16, 0, 0, 0, 0, 0],
1430 encrypted: false,
1431 },
1432 };
1433 assert_eq!(res.unwrap(), expected);
1434 assert!(buffer.is_empty());
1435 }
1436
1437 #[test]
1438 fn essp_message_alignment_self_heal() {
1439 let expected = Message {
1440 slave_id: 0,
1441 payload: Payload {
1442 code: Code::ResponseCode(Response::Ok),
1443 data: vec![],
1444 encrypted: false,
1445 },
1446 };
1447
1448 let mut buffer = vec![9, 240, 199, 127, 127, 127, 127, 127, 128, 1, 240, 35, 128];
1449 let mut res = Message::decode(&mut buffer, false, 0, None);
1450 assert_eq!(res.unwrap(), expected);
1451 assert!(buffer.is_empty());
1452
1453 buffer = vec![199, 127, 127, 127, 127, 127, 128, 1, 240, 35, 128];
1454 res = Message::decode(&mut buffer, false, 0, None);
1455 assert_eq!(res.unwrap(), expected);
1456 assert!(buffer.is_empty());
1457
1458 let mut buffer = vec![127, 127, 127, 127, 127, 128, 1, 240, 35, 128];
1459 let res = Message::decode(&mut buffer, false, 0, None);
1460 assert_eq!(res.unwrap(), expected);
1461 assert!(buffer.is_empty());
1462
1463 let mut buffer = vec![127, 127, 127, 127, 128, 1, 240, 35, 128];
1464 let res = Message::decode(&mut buffer, false, 0, None);
1465 assert_eq!(res.unwrap(), expected);
1466 assert!(buffer.is_empty());
1467
1468 let mut buffer = vec![127, 127, 127, 128, 1, 240, 35, 128];
1469 let res = Message::decode(&mut buffer, false, 0, None);
1470 assert_eq!(res.unwrap(), expected);
1471 assert!(buffer.is_empty());
1472
1473 let mut buffer = vec![127, 128, 1, 240, 35, 128];
1474 let res = Message::decode(&mut buffer, false, 0, None);
1475 assert_eq!(res.unwrap(), expected);
1476 assert!(buffer.is_empty());
1477
1478 let mut buffer = vec![127, 128, 1, 240, 35, 128];
1479 let res = Message::decode(&mut buffer, false, 0, None);
1480 assert_eq!(res.unwrap(), expected);
1481 assert!(buffer.is_empty());
1482 }
1483
1484}