M2M: S-UDP protocol: examples

Verze z 8. 8. 2021, 16:36, kterou vytvořil Adamn (diskuse | příspěvky)
(rozdíl) ← Starší verze | zobrazit aktuální verzi (rozdíl) | Novější verze → (rozdíl)

SUDP PROTOKOL - příklady

Jsou zde tři příklady, kdy náš program vytvořil SUDP příkaz, a poslal jej UDP protokolem do zařízení SDS.

Tyto tři pakety jsou zde rozebrány podle popisu SUDP protokolu.

Ptáte se

Dotaz:

Kde se v těchto příkladech vzali právě ty konkrétní hodnoty a čísla ?

Odpověď:

Některé jsou pevně dané popisem protokolu SUDP, některé jsou zcela náhodné (random) tak jak to SUPD protokol vyžaduje (opět viz popis), některé jsou odvozeny od stavu (např. aktuální čas) no a nakonec - některé jsou jednoduše zvolené ručně mnou, aby tady vůbec nějaký příklad byl.

Dotaz:

Jak spočítám kolik je hodnota 'R' ?

Odpověď:

Viz popis protokolu, a pokud to stále není jasné, tak viz vzoreček v následujících příkladech (vyjádřete si R ze vzorečku kde se počítá PL, matematika 4. třídy ZŠ).



Příklad č. 1 - ODESLÁNÍ "NOP" PAKETU

Náš program vytvořil platný "NOP" paket. Tento paket zde rozebereme, ať máte k dispozici praktický skutečný příklad.

Hodnoty jsou tedy zvoleny, a my se na ně podíváme. Váš program je mnohdy bude volit jinak, ale pořád to musí odpovídat intencím zadání protokolu SUDP, jinak to SDS odmítne.

Takže:

Máme vzorový SUDP paket, který posíláme do SDS. Tento paket si zde rozebereme.

Každý SUDP paket se skládá ze: HLAVIČKY a PAYLOADu. Tyto dvě časti jsou v paketu vloženy těsně za sebou.

Hlavička SUDP paketu je rozepsána zde:

SDS_header[0]  = 83 dec     (konstanta)
SDS_header[1]  = 68 dec     (konstanta)
SDS_header[2]  = 83 dec     (konstanta)
version        = 32 dec     (konstanta)
PL             = 2 dec      (určeno výpočtem)
enc_flag       = 16 dec     (konstanta)
rsvd           = 0 dec      (konstanta)
CK1            = 115 dec    (určeno výpočtem)
user_corid     = 2 dec      (zvoleno vámi)
ctr_block[0]   = 1 dec      (zvoleno vámi)
ctr_block[1]   = 0 dec      (zvoleno vámi)
ctr_block[2]   = 0 dec      (zvoleno vámi)
ctr_block[3]   = 0 dec      (zvoleno vámi)

Celá bajtová reprezentace SUDP Hlavičky je tedy taková:

53445320021000730200000001000000000000000000000000000000

Payload SUDP paketu je rozepsán zde:

random         = 6 dec              (náhodné číslo)
ck2            = 31 dec             (určeno výpočtem)
XR_MTU         = 1328 dec           (obvykle určeno systémem)
crc32          = 2039090611 dec     (určeno výpočtem)
ic.uptime      = 827 dec            (stavová hodnota)
ic.time        = 1528904578 dec     (stavová hodnota)
ic.sds_device  = 2979004417 dec     (určeno vámi podle cílového SDS)
ic.master_cmd  = 0 dec              (zvoleno vámi)
ic.sub_cmd     = 0 dec              (zvoleno vámi) 
ic.XL          = 0 dec              (zvoleno vámi - délka aplikačních dat)
ic.payload     =                    (vaše aplikační data - zde nejsou takže prázdno) 
ic.randompay   = 0xC6 0x7F 0x1A 0x3E 0xE3 0x67 0x2C 0x2C   (náhodná čísla o počtu R)

Všimněte si, že v tomto paketu nejsou neseny vlastní aplikační data (XL je nula), a je zde tedy pouze vidět "randompay" což je doplnění náhodných čísel (ať tam nejsou jen nuly) do bloku pro zarovnání délky na násobek 16.

Výpočet je:

PL = ( XL + R + 24 ) / 16
 2 = ( 0  + 8 + 24 ) / 16

Takže tedy náš kompletní PAYLOAD před šifrováním (tj. plain-text), tedy to co následně dáváme jako celý blok do funkce XTEA-ENC, je takovýto:

061F3005B30D8A793B030000823B215B010090B100000000C67F1A3EE3672C2C

Teď se provede šifrování PAYLOAD bloku.

Vstupy do XTEA-ENC jsou:

XTEA-ENC: CounterBlock (POZOR, tisknuto jako čísla formátu UINT32 v reprezentaci Little Endian):

[0] = 0x00000001 [1] = 0x00000000 

XTEA-ENC: EncKey (POZOR, tisknuto jako čísla formátu UINT32 v reprezentaci Little Endian):

[0] = 0x0002FFFF [1] = 0x1E002A00 [2] = 0x0F473332 [3] = 0x34303833 

Takže, kompletní PAYLOAD po šifrování s výše uvedenými parametry vypadá takto:

1C920F27D85A966CD6DA8D80686A51CFF7FA8F8BFC371DE0CEA8FEE612B9C884

Tímto si můžete ověřit, že vaše implementace XTEA-ENC pracuje stejně jako ta v SDS.

Celý paket je tedy sloučením SUDP Hlavičky a šifrovaného SUDP payloadu:

534453200210007302000000010000000000000000000000000000001C920F27D85A966CD6DA8D80686A51CFF7FA8F8BFC371DE0CEA8FEE612B9C884120000000000000000000000000000000000000000000000

Hotovo, tato data tvoří surový UDP paket, který je zaslán do SDS zařízení.

A zařízení SDS odpoví surovým UDP paketem takto:

534453200210009F02000000C103000000000000000000000000000094D1D2C7095D09AA4171F0C0D2B8790EBD7F688364CC2ABB7F52EA185DF69B1812000000000000000000000000000000358B7B722F4C8DFA



Příklad č. 2 - ODESLÁNÍ "GET GENERAL STATUS" PAKETU

Náš program vytvořil platný "GET GENERAL STATUS" paket. Tento paket zde rozebereme, ať máte k dispozici praktický skutečný příklad.

Hodnoty jsou tedy zvoleny, a my se na ně podíváme. Váš program je mnohdy bude volit jinak, ale pořád to musí odpovídat intencím zadání protokolu SUDP, jinak to SDS odmítne.

Takže:

Máme vzorový SUDP paket, který posíláme do SDS. Tento paket si zde rozebereme.

Každý SUDP paket se skládá ze: HLAVIČKY a PAYLOADu. Tyto dvě části jsou v paketu vloženy těsně za sebou.

Hlavička SUDP paketu je rozepsána zde:

SDS_header[0]  = 83 dec
SDS_header[1]  = 68 dec
SDS_header[2]  = 83 dec
version        = 32 dec
PL             = 2 dec
enc_flag       = 16 dec
rsvd           = 0 dec
CK1            = 216 dec
user_corid     = 3 dec
ctr_block[0]   = 5 dec
ctr_block[1]   = 0 dec
ctr_block[2]   = 0 dec
ctr_block[3]   = 0 dec

Celá bajtová reprezentace SUDP Hlavičky je tedy taková:

53445320021000D80300000005000000000000000000000000000000

Payload SUDP paketu je rozepsán zde:

random         = 5 dec
ck2            = 36 dec
XR_MTU         = 1328 dec
crc32          = 2653010472 dec
ic.uptime      = 10452 dec
ic.time        = 1528905210 dec
ic.sds_device  = 2979004417 dec
ic.master_cmd  = 1 dec
ic.sub_cmd     = 0 dec
ic.XL          = 0 dec
ic.payload     = 
ic.randompay   = 0x87 0x99 0xA4 0x15 0x23 0xDE 0xB0 0x6C 

Všimněte si, že v tomto paketu nejsou neseny vlastní aplikační data (XL je nula), a je zde tedy pouze vidět "randompay" což je doplnění náhodných čísel (ať tam nejsou jen nuly) do bloku pro zarovnání délky na násobek 16.

Výpočet je:

PL = ( XL + R + 24 ) / 16
 2 = ( 0  + 8 + 24 ) / 16

Takže tedy náš kompletní PAYLOAD před šifrováním (tj. plain-text), tedy to co následně dáváme jako celý blok do funkce XTEA-ENC, je takovýto:

0524300528BA219ED4280000FA3D215B010090B1010000008799A41523DEB06C

Teď se provede šifrování PAYLOAD bloku.

Vstupy do XTEA-ENC jsou:

XTEA-ENC: CounterBlock (POZOR, tisknuto jako čísla formátu UINT32 v reprezentaci Little Endian):

[0] = 0x00000005 [1] = 0x00000000 

XTEA-ENC: EncKey (POZOR, tisknuto jako čísla formátu UINT32 v reprezentaci Little Endian):

[0] = 0x0002FFFF [1] = 0x1E002A00 [2] = 0x0F473332 [3] = 0x34303833 

Takže, kompletní PAYLOAD po šifrování s výše uvedenými parametry vypadá takto:

3F978ED56E61218EE88A67AEC92378E76FB9B3BBE3FE6009FFA509FD80E6500F

Tímto si můžete ověřit, že vaše implementace XTEA-ENC pracuje stejně jako ta v SDS.

Celý paket je tedy sloučením SUDP Hlavičky a šifrovaného SUDP payloadu:

53445320021000D803000000050000000000000000000000000000003F978ED56E61218EE88A67AEC92378E76FB9B3BBE3FE6009FFA509FD80E6500FAE0000000000000000000000000000000000000000000000

Hotovo, tato data tvoří surový UDP paket, který je zaslán do SDS zařízení.

A zařízení SDS odpoví surovým UDP paketem například takto:

534453201D10003A03000000C90300000000000000000000000000006F7CB8670960B64EEA040F1E49C61B2540A463E73F4DCEE9D58DD83DF748DB76C62A212AD2FFBFF9717C9F6B76C54B84978BAE11F838658743B4679D9F89255950CCBEAACB9FBF1E097EA916A393A0F883072FDE2D66BCA40B9E85A51FF2A7EB54D87D8AEC71D1AB76BD7B17FF79BC871D207D5C8BB10CCE624B5AABF1D4F19A3622299055076B414723D47971A5053E3BDCAB37960068DBA0225362224C0E40E950586D54943396CCCE9A4A6EB8247BF5FA50F680A1309D3AFA7D9D227A9D2141249A962949468A240EF8E6A66036437C32B2BFF60BB6EBCEB93B35D79FB24288EB7CB985AFB91D50CDCCDCC7C240FE4235F6BAD4746A0E344107A4DD6E1C0319E533ED4BDE6D8CF04B270A0A68D860082671EF0FF52BEE99593EB25754E5FE6AAD437CD5ECD81913D049EBFAFBDE9659C1C2C6D05CF2ABB71586658404766C6F623CD4D7AF04A64D9CF9709010238732D60EE6D1A545884C5E2CDB3476C8836C4AB1AF401C9B4DBB69FF2F40BC0EA7DF84456FCEB46C3CC82E09DF27EEC7B224B9042B2EB16833FD8571160F2BC55ECEA39BC8D28679A2463D3425DCFBCE607E314B9BCDCC0B9750750FADCF280374511CF56315D90441F0ACBD977310739A5FCC7E1F9148E6684C4DB53E0DE92B3B37FFF51C94691C0BC24246A460DEC9A972967453D57101A6



Příklad č. 3 - ODESLÁNÍ "FC-SET" PAKETU (master command 8, sub command 1)

Třetí vzorový odeslaný paket je rozebrán zde.

Tento paket už nese aplikační data (v našem případě zápis FC-SET do indexu 1234 typem TEXT o délce 5).

Každý SUDP paket se skládá ze: HLAVIČKY a PAYLOADu. Tyto dvě části jsou v paketu vloženy těsně za sebou.

Hlavička SUDP paketu je rozepsána zde:

SDS_header[0]  = 83 dec
SDS_header[1]  = 68 dec
SDS_header[2]  = 83 dec
version        = 32 dec
PL             = 3 dec
enc_flag       = 16 dec
rsvd           = 0 dec
CK1            = 122 dec
user_corid     = 4 dec
ctr_block[0]   = 9 dec
ctr_block[1]   = 0 dec
ctr_block[2]   = 0 dec
ctr_block[3]   = 0 dec

Celá bajtová reprezentace SUDP Hlavičky je tedy taková:

534453200310007A0400000009000000000000000000000000000000

Payload SUDP paketu je rozepsán zde:

random         = 230 dec
ck2            = 42 dec
XR_MTU         = 1328 dec
crc32          = 1754788747 dec
ic.uptime      = 267277 dec
ic.time        = 1528905467 dec
ic.sds_device  = 2979004417 dec
ic.master_cmd  = 8 dec
ic.sub_cmd     = 1 dec
ic.XL          = 9 dec
ic.payload     = 0xD2 0x04 0x05 0x40 0x31 0x32 0x33 0x34 0x35 
ic.randompay   = 0x0A 0x56 0x8B 0x82 0x5F 0xB0 0x46 0x96 0x6E 0x8B 0xB2
0xF4 0x18 0xFE 0x6F 

Délka 'ic.payload' je právě 'ic.XL' bajtů, a délka 'ic.randompay' je právě 'R' bajtů.

Výpočet je:

PL = ( XL + R  + 24 ) / 16
 3 = ( 9  + 15 + 24 ) / 16

Pro jistotu je zde i pohled na výpočet R:

15 = 3*16 - 9 - 24

Takže tedy náš kompletní PAYLOAD před šifrováním (tj. plain-text), tedy to co následně dáváme jako celý blok do funkce XTEA-ENC, je takovýto:

E62A30058BF397680D140400FB3E215B010090B108010900D204054031323334350A568B825FB046966E8BB2F418FE6F

Teď se provede šifrování PAYLOAD bloku.

Vstupy do XTEA-ENC jsou:

XTEA-ENC: CounterBlock (POZOR, tisknuto jako čísla formátu UINT32 v reprezentaci Little Endian):

[0] = 0x00000009 [1] = 0x00000000 

XTEA-ENC: EncKey (POZOR, tisknuto jako čísla formátu UINT32 v reprezentaci Little Endian):

[0] = 0x0002FFFF [1] = 0x1E002A00 [2] = 0x0F473332 [3] = 0x34303833 

Takže, kompletní PAYLOAD po šifrování s výše uvedenými parametry vypadá takto:

06A8503904AECC372D9968D7D1332B917898EB5DFECF361D28D131B53AFD2622CC6E4E7405A5FAD6456D9CEDFA7AA42A

Tímto si můžete ověřit, že vaše implementace XTEA-ENC pracuje stějně jako ta v SDS.

Celý paket je tedy sloučením SUDP Hlavičky a šifrovaného SUDP payloadu:

534453200310007A040000000900000000000000000000000000000006A8503904AECC372D9968D7D1332B917898EB5DFECF361D28D131B53AFD2622CC6E4E7405A5FAD6456D9CEDFA7AA42A210000000000000000000000000000000000000000000000

Hotovo, tato data tvoří surový UDP paket, který je zaslán do SDS zařízení.

A zařízení SDS odpoví surovým UDP paketem například takto:

53445320031000EF0400000003040000000000000000000000000000E55553636B788B2A8B2B92AC67E7F8D1EEE9EC9E7AB5800BE87C598B2F0743AD6449CDEC60D3AEC1DC47398E375372E52100000000000000003B5FAB2C7DF1B212F0F62D497F5310


Vzorové výpočty CRC32

Pro ověření funkce vaší implementace výpočtu CRC32 jsou zde ukázány tři příklady toho, jak se to pro S-UDP počítá.

Algoritmus výpočtu pracuje vždy s 32bit krokem. Na začátku je crc32 nastaveno na 0xFFFFFFFF a pak se postupně přepočítává, vždys 32bit slovo za slovem.

Polynom je 0x04C11DB7.

Vyzkoušet si to můžete online, např. na stránce: https://crccalc.com/?crc=00000915+&method=hex - výsledky jsou v řádku označeném jako "CRC-32/MPEG-2".

Příklad číslo 1:

complete plaintext payload: 1A1F30051315E2A13A03000006FAAB5B010090B100000000E6D5BF5CAAACC71F

crc32: start, output=0xFFFFFFFF
crc32: input=0000033A output=0x4E5739EE
crc32: input=5BABFA06 output=0xB0493723
crc32: input=B1900001 output=0xC21BA6F9
crc32: input=00000000 output=0x3641804E
crc32: input=5CBFD5E6 output=0xD9F37F11
crc32: input=1FC7ACAA output=0xA1E21513
crc32: DONE, final hex-output=0xA1E21513 / dec-output=2715948307

Všimněte si kritické vlastnosti výpočtu crc32 z původního payloadu - jak jsou jednotlivé bajty přerovnány. Je to dáno tím, že procesor je v režimu LITTLE ENDIAN, tedy že má "LSB na kraji vlevo a MSB na kraji vpravo". Pěkně to jde vidět hned na prvním řádku výpočtu:

přímá bajtová reprezentace plaintext payload v RAM - (hex): . . . 3A030000 . . .

crc32: input = 0000033A (hex)

Protože crc32 výpočet se provádí vždy nad celým 32bit slovem, musí se správně dané slovo z paměti přečíst. Jinak řečeno: výpočet crc32 se nekrmí po bajtech, ale po celých 32bit slovech, a tento výpočet pracuje nad hodnotami, nikoliv nad bajtovou reprezentací.

Příklad číslo 2:

complete plaintext payload: 5A243005F712DC60DD3A010056FAAB5B010090B10100000040BD21F282B1929F

crc32: start, output=0xFFFFFFFF
crc32: input=00013ADD output=0xFCC2CCAE
crc32: input=5BABFA56 output=0x683AFE3A
crc32: input=B1900001 output=0x1C8E2FE4
crc32: input=00000001 output=0xDB03731A
crc32: input=F221BD40 output=0x0C83B853
crc32: input=9F92B182 output=0x60DC12F7
crc32: DONE, final hex-output=0x60DC12F7 / dec-output=1625035511

Příklad číslo 3:

crc32: start, output=0xFFFFFFFF
crc32: input=00000915 output=0xC481EFEE
crc32: input=5BABF5F3 output=0xC5CCC0E4
crc32: input=B1900001 output=0xC3BB7150
crc32: input=00000001 output=0x0E1C2392
crc32: input=3573A2F1 output=0x33E32AB1
crc32: input=F6E5E9B8 output=0x40568BE0
crc32: DONE, final hex-output=0x40568BE0 / dec-output=1079413728

Příklad číslo 4:

crc32: start, output=0xFFFFFFFF
crc32: input=000104E0 output=0x4651762C
crc32: input=5BABF633 output=0xE922DAA8
crc32: input=B1900001 output=0x3C523379
crc32: input=00000102 output=0xAB0DEA5F
crc32: input=6106EAC7 output=0x3DBC5A0C
crc32: input=1338A018 output=0xBE4F22AB
crc32: DONE, final hex-output=0xBE4F22AB / dec-output=3192857259

Příklad číslo 5:

crc32: start, output=0xFFFFFFFF
crc32: input=000176C5 output=0x18F1F4D1
crc32: input=5BABF650 output=0x1A8E95EB
crc32: input=B1900001 output=0x2DCD4583
crc32: input=00080104 output=0x5C75899C
crc32: input=00040008 output=0x1EB0AB7A
crc32: input=00000008 output=0xB7621ED3
crc32: DONE, final hex-output=0xB7621ED3 / dec-output=3076660947


Vzorový kód pro výpočet crc32

Kód v jazyce C:

 // Nibble lookup table for 0x04C11DB7 polynomial
 const uint32_t CrcTable[16] = 
  {  
    0x00000000,0x04C11DB7,0x09823B6E,0x0D4326D9,0x130476DC,0x17C56B6B,0x1A864DB2,0x1E475005, 
    0x2608EDB8,0x22C9F00F,0x2F8AD6D6,0x2B4BCB61,0x350C9B64,0x31CD86D3,0x3C8EA00A,0x384FBDBD
  };
 
 uint32_t Crc32Fast(uint32_t Crc; const uint32_t Data)
 {
  Crc = Crc ^ Data; // Apply all 32-bits
 
  // Process 32-bits, 4 at a time, or 8 rounds
 
  Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // Assumes 32-bit reg, masking index to 4-bits
  Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // 0x04C11DB7 Polynomial
  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
 
  return Crc;
 }

Jak lze vidět, funkce se krmí po 32bit slovech.

 volatile uint32_t crc32;
 volatile uint32_t * dword_data;
 
 // odkud bereme data (položky v rámci bloku "ic" viz příklady výše)
 dword_data = (uint32_t *)&sudp.header.ic;
 
 // vypocet crc32 zacina zde 
 crc32 = 0xFFFFFFFF; 
 for (i = 0; i < ((sudp_packet.header.PL*16-8)/4), i++)
 {
   crc32 = Crc32Fast(crc32, dword_data[i]);
 }
 
 // hotovo...
 printf("output crc32 is : 0x%08x \n", crc32);

Toto byl celý příklad, jak lze vidět, je to jednoduchá záležitost.


Konec stránky

Potřebujete více příkladů ? získejte si data sami pomocí našeho EXE (vzorový komunikační program), které je volně k dispozici.