• Nebyly nalezeny žádné výsledky

Hlavní práce71619_kadj02.pdf, 1.6 MB Stáhnout

N/A
N/A
Protected

Academic year: 2022

Podíl "Hlavní práce71619_kadj02.pdf, 1.6 MB Stáhnout"

Copied!
96
0
0

Načítání.... (zobrazit plný text nyní)

Fulltext

(1)

Vysoká škola ekonomická v Praze

Fakulta informatiky a statistiky

Implementace MQTT klienta

DIPLOMOVÁ PRÁCE

Studijní program: Aplikovaná informatika Studijní obor: Informační systémy a technologie

Autor: Bc. Jindřich Kadoun

Vedoucí diplomové práce: Ing. Tomáš Bruckner, Ph.D.

Praha, květen 2021

(2)

Čestné prohlášení

Prohlašuji, že jsem tuto diplomovou práci vypracoval samostatně. Veškeré použité podklady, ze kterých jsem čerpal informace, jsou uvedeny v seznamu použité literatury a citovány v textu podle normy ČSN ISO 690.

V... dne ... Podpis:

(3)

Poděkování

Rád bych poděkoval svému vedoucímu Ing. Tomášovi Brucknerovi, Ph.D. za odborný dohled, vstřícnost a čas věnovaný vedení této diplomové práce.

(4)

4

Abstrakt

Tato práce je zaměřena na implementaci MQTT protokolu do aplikace realizované v programovacím jazyce C obohacený o některé prvky z C++. Hlavním cílem práce je konstrukce modulu ve formě staticky linkované knihovny, která bude zajišťovat podporu pro přijímání a odesílání zpráv skrze MQTT protokol. Úvodní část je věnována teoretickým základům protokolu a programovacího jazyka. Po teoretickém uvedení se práce věnuje analýze stávajícího projektu, do kterého je tato funkcionalita implementována, a konstrukci testovacího projektu pro jednotlivé implementační přírůstky. Tyto přírůstky jsou pak v následující kapitole implementovány, popsány spolu se zdrojovým kódem a nakonec otestovány. Závěr práce pak zhodnocuje výsledky praktické části a shrnuje poznatky získané v průběhu implementace.

Klíčová slova

MQTT, síťový protokol, message broker, C, C++, programování, Wireshark

(5)

5

Abstract

This thesis is focused on the implementation of MQTT protocol in application which is realized in programming language C enriched with some elements of C++ programming language. The main goal of this thesis is construction of module in form of statically linked library which will provide support for receiving and sending messages via the MQTT protocol. Introduction part of this thesis is dedicated to theoretical basics of the protocol and programming language. After this theoretical introduction, the thesis continues by analysing current project which is the implementation subject and constructs test solution for the individual incrementation. Subsequently, features are developed in this incrementation manner and described together with the source code. The conclusion of this thesis then evaluates the results of the practical part and summarizes the knowledge gained during the implementation.

Keywords

MQTT, network protocol, message broker, C, C++, programming, Wireshark

(6)

6

Obsah

Úvod ... 12

Cíle práce ... 13

Hlavní cíl práce ... 13

Dílčí cíle práce ... 13

Struktura práce ...14

Vstupy...14

Řešení ...14

Výstupy ... 15

Použitý postup ... 15

Komentovaná rešerše informačních zdrojů ...16

1 Netstar ... 17

1.1 Popis produktu Netstar ... 17

1.2 Stav produktu Netstar ... 18

2 Analýza projektu Netstar Platform ... 20

2.1 Architektura projektu Netstar Platform ... 20

2.2 Sestavení projektu Netstar Platform ... 22

2.3 Technické specifikace projektu Netstar Platform ... 25

2.3.1 Pointery a reference ... 26

2.3.2 Objekty ... 27

2.3.3 Vlákna ... 29

2.3.4 Messages ... 30

3 MQTT protokol ... 31

3.1 Specifika protokolu MQTT ... 31

3.1.1 Session state ... 31

3.1.2 Quality of Service ... 32

3.1.3 Standard properties ... 33

3.1.4 Topic Names a Topic Filters ... 34

3.2 Kontrolní pakety ... 34

3.2.1 CONNECT paket ... 35

3.2.2 CONACK paket ... 36

3.2.3 PUB paket ... 37

3.2.4 PUBACK paket ... 37

3.2.5 PUBREC paket ... 38

(7)

7

3.2.6 PUBREL paket ... 38

3.2.7 PUBCOMP paket ... 38

3.2.8 SUB paket ... 39

3.2.9 SUBACK paket ... 39

3.2.10 UNSUB paket ... 40

3.2.11 UNSUBACK paket ... 40

3.2.12 PINGREQ paket ... 40

3.2.13 PINGGRESP paket ... 40

3.2.14 DISCONNECT paket... 40

3.2.15 AUTH paket ...41

4 Implementace ... 42

4.1 Prvotní projekt ... 42

4.1.1 Nastavení TCP spojení ... 42

4.1.2 Message broker ... 43

4.2 Navázání a udržení spojení ... 58

4.2.1 Kódování CON paketu ... 58

4.2.2 Kódování příznaků CON paketu ...61

4.2.3 Kódování standardních properties ... 63

4.2.4 Kódování ID klienta ... 65

4.2.5 Kódování uživatelského jména a hesla ... 66

4.2.6 Udržení spojení ... 67

4.2.7 Kódování DISCONNECT paketu ... 69

4.2.8 Závěr a testování ... 69

4.3 Kódování fixního headeru... 72

4.3.1 Kódování Variable Byte Integer... 73

4.4 Odesílání zpráv ... 74

4.4.1 Kódování PUB paketu ... 74

4.4.2 Závěr a testování ... 76

4.5 Přijímání zpráv ... 77

4.5.1 Kódování SUB paketu ... 77

4.5.2 Zpracování příchozích dat ... 78

4.5.3 Závěr a testování ... 80

4.6 Implementace Quality of Service ... 82

4.6.1 Quality of Service úrovně 1 ... 85

4.6.2 Quality of Service úrovně 2 ... 88

(8)

8

4.6.3 Závěr a testování ... 90

5 Diskuse... 92

Závěr ... 93

Dosažení vytyčených cílů ... 93

Využití výsledků diplomové práce ... 93

Závěr ... 94

Použitá literatura ... 95

(9)

9

Seznam obrázků

Obrázek 1 Hardwarová telefonní ústředna 2N ATEUS NetStar IP. (Zdroj: [24]) ... 17

Obrázek 2 Ukázka modulů pro Mqtt. (Zdroj: autor) ... 21

Obrázek 3 Seznam standard properties. (Zdroj: [1])... 33

Obrázek 4 Ukázka obecné definice fixního headeru. (Zdroj: [1])... 34

Obrázek 5 Výpis příkazové řádky pro analýzu MQTT brokera. (Zdroj: autor) ... 44

Obrázek 6 Ukázka klientské vrstvy Mosquitto . (Zdroj: autor) ... 45

Obrázek 7 Výpis z programu Wireshark zachycující poslání jedné zprávy. (Zdroj: autor) . 48 Obrázek 8 Export paketů jako pole v C z programu Wireshark. (Zdroj: autor) ... 49

Obrázek 9 Výpis komunikace mezi naší aplikací a Mosquitto klientem. (Zdroj: autor) ... 52

Obrázek 10 Ukázka endianity. (Zdroj: autor) ... 64

Obrázek 11 Ukázka poslaného CON paketu s detailem na klientský identifikátor. (Zdroj: autor) ... 66

Obrázek 12 Výpis paměťového bloku při kódování CON paketu. (Zdroj: autor) ... 69

Obrázek 13 Aplikace připojené k brokeru spolu s programem Wireshark. (Zdroj: autor) . 70 Obrázek 14 Program Wireshark zachycující síťový provoz spolu s aplikací. (Zdroj: autor) 71 Obrázek 15 Komunikace skrze publikování zpráv. (Zdroj: autor) ... 76

Obrázek 16 Komunikace mezi naší aplikací a Mosquitto klientskou vrstvou. (Zdroj: autor) ... 80

Obrázek 17 Síťový provoz komunikace pro ověření zpracování dat. (Zdroj: autor) ... 81

Obrázek 18 Síťový provoz při Quality of Service 1. (Zdroj: autor) ... 90

Obrázek 19 Síťový provoz při Quality of Service 2. (Zdroj: autor) ... 90

Obrázek 20 Síťový provoz při testu časovače pro opětovné doručení. (Zdroj: autor) ...91

(10)

10

Seznam výpisů programového kódu

Výpis 1 Ukázka definice funkce. (Zdroj: autor) ... 23

Výpis 2 Ukázka assembly kódu. (Zdroj: autor) ... 23

Výpis 3 Ukázka forward deklarace funkce. (Zdroj: autor) ... 24

Výpis 4 Ukázka chybového výstupu linkeru. (Zdroj: autor) ... 24

Výpis 5 Ukázka přiřazení reference do proměnné. (Zdroj: autor) ... 26

Výpis 6 Ukázka dědičnosti. (Zdroj: autor) ... 28

Výpis 7 Ukázka konstrukce interní zprávy. (Zdroj: autor) ... 30

Výpis 8 Nastavení TCP vrstvy. (Zdroj: autor) ... 42

Výpis 9 Konstruktor klientského vlákna. (Zdroj: autor) ... 46

Výpis 10 Zpracování standardního vstupu. (Zdroj: autor) ... 47

Výpis 11 Konstrukce zprávy a následné odeslání přes TCP. (Zdroj: autor) ... 50

Výpis 12 Upravené přeposílání interních zpráv. (Zdroj: autor) ... 53

Výpis 13 Enum popisující typy paketů. (Zdroj: autor) ... 54

Výpis 14 Třídění akcí pro typy paketů. (Zdroj: autor) ... 55

Výpis 15 Definice objektů pro práci s požadavky. (Zdroj: autor) ... 56

Výpis 16 Definice funkce pro kódování a následné poslání MQTT paketu. (Zdroj: autor) . 57 Výpis 17 Funkce odpovědná za kódování MQTT paketu. (Zdroj: autor) ... 57

Výpis 18 Hlavní kódovací funkce pro CON paket. (Zdroj: autor) ... 59

Výpis 19 Definované konstanty a parametry v hlavičkovém souboru. (Zdroj: autor) ... 60

Výpis 20 Definice enumu bitové masky pro příznaky. (Zdroj: autor) ...61

Výpis 21 Funkce pro zakódování příznaků do CON paketu. (Zdroj: autor) ... 62

Výpis 22 Enum popisující vlastnosti a jejich příslušné hodnoty. (Zdroj: autor) ... 63

Výpis 23 Obecná funkce pro kódování properties. (Zdroj: autor) ... 64

Výpis 24 Funkce pro zakódování klientského identifikátoru do CON paketu. (Zdroj: autor) ... 65

Výpis 25 Funkce pro kódování uživatelského jména. (Zdroj: autor) ... 66

Výpis 26 Zdrojový kód přidaný pro nastavení časovače. (Zdroj: autor) ... 67

Výpis 27 Funkce volaná při přerušení TCP spojení. (Zdroj: autor) ... 68

Výpis 28 Funkce pro zakódování PINGREQ paketu. (Zdroj: autor) ... 68

Výpis 29 Funkce sestavující DISCONNECT paket. (Zdroj: autor) ... 69

Výpis 30 Kódování fixního headeru. (Zdroj: autor) ... 72

Výpis 31 Ukázka algoritmu pro kódování variable byte integeru. (Zdroj: [1]) ... 73

Výpis 32 Funkce pro zakódování variable byte integeru. (Zdroj: autor) ... 73

Výpis 33 Funkce pro kódování PUB paketu. (Zdroj: autor) ... 74

Výpis 34 Funkce na přidání příznaků do paketu. (Zdroj: autor) ... 75

Výpis 35 Funkce pro kódování SUB paketu. (Zdroj: autor) ... 77

Výpis 36 Zpracovávání příchozích dat z TCP vrstvy. (Zdroj: autor) ... 78

Výpis 37 Funkce pro kódování PUB paketu. (Zdroj: autor) ... 82

Výpis 38 Funkce pro dekódování identifikátoru. (Zdroj: autor) ... 83

Výpis 39 Definice objektů pro reprezentaci odeslaných zpráv. (Zdroj: autor) ... 84

Výpis 40 Změna odsílání PUB paketu při Quality of Service 1. (Zdroj: autor) ... 85

Výpis 41 Funkce pro alokování prostředků časovače. (Zdroj: autor) ... 86

Výpis 42 Zdrojový kód pro znovu odesílání PUB paketů. (Zdroj: autor) ... 87

Výpis 43 Funkce pro dealokaci prostředků časovače. (Zdroj: autor) ... 87

(11)

11

Výpis 44 Zdrojový kód pro potvrzení odeslání PUB paketu. (Zdroj: autor) ... 88

Výpis 45 Funkce pro kódování paketu PUBREL. (Zdroj: autor) ... 88

Výpis 46 Zdrojový kód pro posílání PUBREC paketu. (Zdroj: autor) ... 89

Výpis 47 Zdrojový kód pro konstrukci PUBREC paketu. (Zdroj: autor) ... 89

Výpis 48 Funkce pro nastavování vstupních hodnot. (Zdroj: autor) ... 90

(12)

12

Úvod

Pro společnosti vyvíjející software byla na začátku devadesátých let pouze limitovaná cesta, jak sestavit fungující aplikaci. Stejně jako všechny ostatní subjekty v informačních technologiích, i tyto byly předmětem rapidní inovace. Modernizace zaběhlého produktu však není triviální úkol, a proto je stále ještě nespočet aplikací sestrojených na principech, které by kdekdo dnes označil za zastaralé. Moderní technologie s sebou přinesly obrovskou flexibilitu a odstranily předchozí bariéry pro nové nadšence. To vše však nepřišlo bez oběti.

Spolu s flexibilitou a rychlostí vývoje ztrácí daná technologie přímou kontrolu nad prováděnými operacemi a kompromisy pro ulehčení programování jsou vykoupené nižším dosahovaným výkonem. Alternativa, kde je aplikace programovaná staršími principy a jazyky, má i dnes své místo na trhu. Toto místo je do jisté míry zaplněno staršími produkty nemožné nebo nevýhodné převádět na úroveň diktující moderní trend. Jedná se majoritně o výpočetně náročné programy obsluhující nejpodstatnější část logiky produktu. Toto jádro je zpravidla doplněno o modernější prvky pro usnadnění údržby sekundárních vlastností.

Pro firmy vyvíjející aplikace, které musí dosahovat extrémní optimalizace a zároveň podporovat starší platformy, není jiné cesty.

Jednou z takových firem je i 2N Telekomunikace, kde vývoj telekomunikačních technologií začínal v době, kdy informační technologie byla žhavou novinkou ve světě. V jejich nynějším portfoliu je aplikace, jejíž část tvoří backend zděděný z předchozích aplikací. Tato část obsluhuje spojení hovorů, zvukové transformace a přehrávání do zařízení. Zmíněná část backendu byla modernizována a několikrát přetvářena i po strukturální stránce, nicméně stojí na základech programovacího jazyka C spolu s prvky C++. Struktura je zcela modularizovaná, a tak nabízí možnost využití již napsaného kódu do nesčetně dalších produktů. Tento backend využívá další aplikační vrstva realizovaná v Javě, která dále posílá data pro zobrazení na frontendu realizovaná JavaScriptovým frameworkem React.

Následující modernizace si klade za úkol zlepšit komunikaci mezi backendovými vrstvami, a to skrze message brokera. Tento broker bude obstarávat výměnu informací v reálném čase a nahradí tak dosavadní neoptimalizovanou komunikaci skrze sdílenou relační databázi.

Vzhledem k podpoře MQTT ze strany Javy a z nutnosti podpory budoucích projektů, které již tento protokol interně používají, byla stanovena nutnost podpory tohoto protokolu na straně C backendu.

(13)

13

Cíle práce

Tato diplomová práce si klade za hlavní cíl vhodně implementovat modul zajišťující klientskou komunikaci s message brokerem skrze MQTT protokol do již stávajícího projektu realizovaného v C/C++. Této implementaci bude předcházet potřebná analýza stávajícího projektu, možnosti modulu a protokolu. Výstupem bude modul, který bude možný nalinkovat jako statickou knihovnu do projektu a používat pro zprostředkování komunikace.

Hlavní cíl práce

Hlavním cílem této práce je analyzovat a vhodně implementovat řešení pro podporu klientské komunikace skrze MQTT protokol do stávajícího projektu realizovaného v C/C++.

Dílčí cíle práce

Pro splnění hlavního cíle byly stanoveny následující dílčí cíle:

• Popsat produkt Netstar

• Analyzovat integrační specifika projektu Netstar Platform

• Analyzovat komunikační protokol MQTT

• Navázat a udržet spojení s message brokerem

• Implementovat odesílání zpráv

• Implementovat přijímání zpráv

• Implementace Quality of Service

(14)

14

Struktura práce

Struktura práce zahrnuje teoretické uvedení do problematiky využívaných technologií a následné zpracování daného úkolu. V první kapitole se věnujeme popisu a představení produktu Netstar. Tento popis zahrnuje stručnou historii produktu včetně jednotlivých inovačních iterací produktu. Kapitola také popisuje současný stav a následné překážky, které je nutno vyřešit právě pomocí implementace podpory komunikačního protokolu.

Následující kapitola analyzuje a zkoumá projekt Netstar Platform po důkladnější a techničtější stránce. Je zde uvedena základní architektura projektu a jeho fungování s ostatními technologickými vrstvami. Analýza také zahrnuje technologická a integrační specifika projektu, které je nutné dodržovat při naplňování určených cílů.

V třetí kapitole se věnujeme analýze MQTT protokolu tak, jak byla definována konsorciem OASIS. Tento teoretický popis prozkoumává interní chování protokolu a požadavky pro korektní implementaci. Také jsou zde probrány kontrolní pakety, jejich vlastnosti, kódování, struktura a význam. Tyto kontrolní pakety spolu s definovaným provozním chováním tvoří podstatu MQTT komunikace, kterou je nutné integrovat do našeho řešení.

Čtvrtá kapitola pak obsahuje samotnou implementaci jednotlivých vlastností klientské vrstvy. Jednotlivé podkapitoly odpovídají dílčím cílům pro naplnění cíle hlavního.

Funkčnost každé přidané vlastnosti je prakticky demonstrována na externích nástrojích či manuálním testováním.

Předposlední, pátá, kapitola diskutuje o zrealizovaném řešení. Představuje celistvý softwarový produkt a prozkoumává možné další zlepšení v budoucnu.

Vstupy

Vstupy této práce jsou MQTT komunikační modul a projekt Netstar Platform. MQTT je síťový komunikační protokol, který je velice jednoduchý po strukturální stránce a velice komunikačně úsporný. Netstar Platform je samotný produkt, do kterého se autor bude snažit naimplementovat podporu komunikace zmíněného síťového protokolu. Produkt je zanalyzován jak po produkční, tak technické stránce.

Řešení

Vyvíjený modul se stane připojitelnou součástí do několika stávajících projektů, které jsou podřízeny interním systémovým mechanikám. Pro správnou integraci modulu je třeba dané interní mechaniky pochopit. Analýza produktu Netstar prozkoumává tyto mechaniky a popisuje současný stav stávajícího projektu spolu s analýzou síťového protokolu MQTT.

Kapitola 4 Implementace pak konstruuje řešení využívající znalosti z předchozí kapitoly pro implementaci a korektní integraci této implementace. Je navržena vhodná architektura pro sestrojování, odesílání a přijímání paketů. Funkčnost každé dílčí funkcionality je znázorněna a poté využita v následujících kapitolách.

(15)

15 Výstupy

Výstup této práce je modul podporující komunikaci přes síťový protokol MQTT napsaný v jazyce C/C++. Tento modul musí správně integrovat praktiky již zavedeného projektu pro správné fungování modulu.

Použitý postup

Pro dosažení cílů této práce byla práce rozdělena do příslušných kapitol, jejichž stručný obsah je předmětem kapitoly Struktura práce. Jednotlivé kapitoly byly sepsány na základě poznatků ze studia referenčních technických dokumentací jejichž předmětem byl síťový protokol MQTT a standardy zaobírajíce se C/C++. Cíle této práce bude autor naplňovat v následujících kapitolách a validace bude prováděna skrze message broker třetí strany Mosquitto spolu s analyzačním nástrojem WireShark pro zkoumání síťového toku. Tato validace bude formou manuálního testování modulu, které bude odpovídat jednotkovým testům funkcionalit.

Jako úvodní část je nutné zanalyzovat a popsat produkt Netstar po produkční stránce s nutnou dávkou historického vývoje. Tato část nám zlepší schopnost pochopit technickou specifičnost projektu, která je předmětem další části analýzy. Autor analyzovat a srovnával technická specifika počínaje u architektury projektu. Tato specifika jsou navázána na historii produktu jako takového. Po architektuře autor prozkoumává samotné sestavení projektu a srovnává ho se standardním kompilačním procesem. Poslední část je věnována samotným technologickým specifikám, které bude muset autor dodržovat pro správné integrování modulu do produktu. Každá unikátnost projektu je porovnána s vyšším programovacím jazykem C++.

MQTT síťový protokol je popisován v kapitole následující. Je zde podrobně rozebírána struktura jednotlivých paketů, jejich správné kódování do binárního tvaru. V neposlední řadě jsou pak popisována specifika protokolu, které budeme v nadcházející implementaci muset zohlednit.

Samotná implementace začíná úvodním projektem, který pouze naváže primitivní spojení.

Od tohoto bodu posléze budeme přidávat jednotlivé funkcionality odpovídajícím dílčím cílům. Tyto funkcionality pak manuálně otestujeme nad námi vytvořeným testovacím projektem.

(16)

16

Komentovaná rešerše informačních zdrojů

Cílem této kapitoly je vylistování a okomentování informačních zdrojů zabývající se podobnou problematikou, zejména pak komunikací a notifikací přes MQTT protokol.

Vzhledem k úspornosti protokolu je tato technologie nejvíce používaná v oblasti Internet of Things.

Primárním zdrojem pro tuto práci je MQTT standard předepisující danou formu komunikačního kanálu. [1][2] Tato práce bude následovat strukturu nastíněnou tímto dokumentem a jednotlivé funkcionality budou implementovány na základě jednotlivých kapitol.

Pan Koranga Deepak se v jeho diplomové práci [14] zabývá systémem pro monitorování zařízení přes internet věcí a ke komunikaci s jeho hardwarovými periferiemi používá protokol MQTT pro co možnou největší energetickou úsporu.

Bakalářská práce pana Adama Chyského [15] na téma „Aplikace pro ovládání zařízení v chytré domácnosti vytvořené na platformě RaspberryPi“ využívá jako alternativu k http protokolu protokol MQTT, který je také na aplikační vrstvě referenčního OSI modelu.

Podobně jako předchozí práce je i práce „IoT based Smart Home“ od autora Guneet Singh [16] zaměřená na chytrou domácnost. Senzory domácích spotřebičů pak komunikují s mateřskou platformou přes protokol MQTT.

Na rozdíl od výše vyjmenovaných prací se tato práce zaměřuje na implementování notifikací ve vnitřních vrstvách aplikace, a nikoliv jen na notifikaci externích periférií.

(17)

17

1 Netstar

Cílem této kapitoly je v úvodní části popsat současný stav produktu Netstar a jeho návaznost na projekt Netstar Platform, kde autor rozebírá nejrelevantnější informace pro pochopení podstaty produktu a jeho stručnou historii. Dále je popisován současný stav projektu a jsou zde zmiňovány neoptimální skutečnosti, jež tvoří hlavní důvod potřeby MQTT modulu.

V kapitole technické specifikace projektu jsou zkoumány technická specifika projektu Netstar Platform, které tvoří hlavní jádro aplikace a jsou také největší integrační překážkou.

Jako finální podkapitola je uvedené reálná aplikace Netstar Platform pro ilustrace použití v praxi.

1.1 Popis produktu Netstar

Označení Netstar popisuje ve firemním kontextu 2N hned několik pojmů. Jednak se jedná o označení hardwarové telefonní ústředny s vývojem, který odstartoval na počátku 90. let.

V původní verzi sloužil jako hardwarová komponenta pro spojovaní a přenášení telefonní komunikace převážně pro firemní zákazníky. Další využití bylo přímo u telekomunikačních společností zajišťující telefonní spojení pro širší veřejnost. Po příchodu inovačních pásem a internetu původní analogová ústředna neustála a bylo potřeba adresovat IP telefony a ostatní periferie s digitálním přenosem. Takovouto ústřednu můžete vidět na Obrázku 1, jež ilustruje jednu z mnoha koncových řešení takovéto inovované hardwarové komponenty.

S rozšířením internetu do běžných domácností však byla potřeba produkt přizpůsobit ještě o krok dále.

Jako poslední fáze evoluce projektu Netstar bylo převedení celé logiky do čistě softwarové podoby. Tato podoba by nesloužila jako samo prodejný produkt, ale jako základní část ostatních produktů, umožňující, mimo jiné, IP komunikaci. Takováto softwarová obdoba se začala nazývat Nestar Platform a odkazuje na fakt, že vznikla z původní hardwarové centrály a zároveň, že se jedná pouze o platformu, na které mohou ostatní produkty stavět a přeskočí

Obrázek 1 Hardwarová telefonní ústředna 2N ATEUS NetStar IP. (Zdroj: [24])

(18)

18

tím tak těžkosti spolu svázané s vývojem funkcionality na telefonní komunikaci. Tyto produkty budou ovšem uzavřené v rámci firmy, nicméně nabízí možnosti dlouhodobé údržby a customizace díky projektu Netstar Platform.

1.2 Stav produktu Netstar

Konečné produkty v současné době, ve kterých hraje Nestar Platform významnou roli, existují ve dvou podobách. První z nich je označena jako Axis Audio Manager, či Axis Audio Management software family. Druhý z nich je pojmenován My2N.

My2N je cloudové řešení pro správu chytrých zvonků, dveřníků a interkomů. Nabízí možnosti spárovat s ostatními chytrými zařízeními a umožňuje například otevřít branku při doručování balíků bez nutnosti přítomnosti uživatele. Axis Audio Manager je vyvíjen v úzké spolupráci s mateřskou firmou Axis Communications a nabízí řešení pro správu audio periférií skrze IP protokol. Tento produkt je však rozvětvený na další alternativy. Některé z nich jsou veřejně propagovány, jako například AAM Pro, AAM Edge a AAM Center. Tyto alternativy nabízí různorodou funkcionalitu a škálovatelnost pro různé segmenty zákazníků.

Typický příklad pro tyto produkty by byl školní rozhlas až po multimediální periferie v obchodních centrech. Existují ale i neveřejné produkty, jejichž vývoj je zaplacen z větší části ze strany zákazníka a řeší specifické požadavky.

Tato různorodost však vynutila extrémní flexibilitu produktu, aby mohl odpovědět na všechny požadavky a zároveň mohl být dostatečně udržován. Tato flexibilita je do značné míry uskutečňována modularizací backendu do tzv. modulů, které slouží jako jednotky izolovaných funkcionalit. Je tak možné za pomocí změny parametrů sestavení softwaru vytvořit produkt, který odpovídá na specifickou potřebu zákazníka.

Jako dalším krokem vstříc flexibilitě produktu, byl zakomponován middleware realizovaný v Javě. Tento aplikační middleware zpracovává požadavky od forntendu a backendu běžící jako standartní proces. Avšak byla lokalizována nutnost předávat notifikace mezi oběma stranami v reálném čase. Nynější řešení zahrnuje jako společný bod pro takovéto sídlení informací databázi PostgreSQL, která slouží jako mediátor mezi těmito aplikačními body.

Toto řešení je však daleko od ideálního stavu, protože databáze jako taková je inicializována z C backendu při startu aplikace a zároveň má ve vlastnictví všechny hlavní definice tabulek, views, indexací a procedury. Middleware je pak odkázaný na již předem určenou definici architektury databáze a pouze mění jednotlivé hodnoty, popřípadě sleduje některé změny.

Právě tyto změny nejsou však přenášeny v reálném čase kvůli nasčítané časové režii přes tři technologie – z backendu do databáze a z databáze dotazem do middlewaru.

(19)

19

Je nutné však reagovat na takovéto události daleko rychleji a flexibilněji nežli se pouze periodicky dotazovat. Řešením byl message broker používající MQTT síťový protokol, který se již používá v ostatních částech projektu. Je zde nenulová šance, že by v budoucnu byl potřeba sdílený realtimový komunikační kanál mezi výše zmíněnými částmi, proto je takovéto technicky konzistentní řešení jasnou volbou.

Je zde mnoho možností komerčních nebo opensourových message brokerů, jejichž integrace do multiplatformního prostředí je více či méně složitá. Hlavní zřetel byl však brán na výkon, velikost a složitost údržby. Opensourové řešení jako např. mosquito, které bylo předlohou budoucího řešení, je výkonově vyhovující a zároveň dosti úsporný, co se týče velikosti. Hlavním negativem bylo u tohoto řešení, a obecně u všech takovýchto opensourových řešení, architektura směřovaná na procesy v operačním systému, což významně kolidovalo s naší architekturou snažící se maximálně využít více vláknového programování. Tento problém se tak moc neobjevoval u komerčních řešení, jako např.

Kafka, v závislosti jejich optimalizace, nicméně vzhledem k nutnosti, aby takovéto produkty byly co nejvíce obecné pro zasáhnutí co nejširšího segmentu trhu, jsou bohužel obrovské a velice náročné na výkon.

(20)

20

2 Analýza projektu Netstar Platform

Účel této kapitoly je analyzovat a představit Netstar Platform z hlediska architektury projektu, sestavování výsledného produktu, a hlavně popsat technické náležitosti softwarového řešení. Toto řešení má své unikátní technické specifikace, které byly inspirovány z jazyka C++. Poslední část této kapitoly pak rozebírá a porovnává tyto technické spojitosti mezi obohaceným jazykem Netstar Platform a oficiálním jazykem C++.

2.1 Architektura projektu Netstar Platform

Základním prvkem našeho projektu je modul. Jako modul označujeme projekt v Microsoft Visual Studiu, který splní požadovanou souborovou architekturu a je kompilovaný jako statická knihovna. Takováto knihovna je pak nalinkována k požadované aplikaci a používána skrze definované kořenové rozhraní. Toto rozhraní je v podobě hlavičkového souboru, kde jsou uvedeny exportované funkce umožňující volání z ostatních modulů. Další povinné hlavičkové soubory jsou pro uvedení předkompilovaných hlaviček a pro sdílení lokálních funkcí.

Při sestavování cílového binárního programu máme několik možností. Tyto binární soubory mohou být sestaveny do formy knihoven – buď dynamických nebo statických. Knihovna obecně znamená sestavený program, který je možné využít dalším nezávislým programem.

Výrazně je tak podpořena modularita výsledného programu. Funkcionalita těchto knihoven je, specificky v C++, zveřejněna pomocí hlavičkových souborů. K hlavičkovému souboru je obvykle připojen korespondující předkompilovaný soubor v binární formě. Binární formu volí autoři ze dvou hlavních důvodů. Zrychlují sestavování cílového programu, který tuto knihovnu používá a chrání své intelektuální vlastnictví samotného zdrojového kódu knihovny. Tím, mimo jiné, zabraňují i nechtěným změnám ze strany uživatelů knihovny. [8]

[9]

Statické knihovny, známé také jako archiv, jsou soubory, které se přímo připojí v kompilaci cílového programu. Při kompilaci se veškerá funckionalita archivu nalinkuje na výsledný program a po sestavení je vše jako jeden celek. To má své světlé i stinné stránky. Výhodou je, že program běží vždy se správnou verzí knihovny a předchází se tak problémy s kompatibilitou. Nevýhodou je, že kopie této knihovny se stane víceméně součástí vašeho zdrojového kódu, která logicky vyžaduje i více místa. Tento fakt může vyústit ve zhoršení optimalizace výsledného programu. [8] [9]

Dynamické knihovny, nazývané také jako sdílené knihovny, jsou předkompilované soubory, které se nekompilují spolu s výsledným programem. Místo toho jsou jako samostatné soubory a výsledný program je připojí pouze pokud je to skutečně nutné. Dynamické knihovny jsou obecně více využívané, jelikož umožňují být použity z více míst najednou a šetří tak výslednou paměť. Dalším pozitivem je možnost kdykoliv tento modul změnit bez nutnosti zasahovat do zdrojového kódu cílového programu. [9]

(21)

21

Nejpřímočařejším přístupem pro výsledný program je samostatně spustitelný program.

Tento program má svojí vykonávající rutinu a o jeho spuštění se stará operační systém. Ne každý operační systém však má stejné požadavky, a ne všechna zařízení mají operační systém. Součástí procesu sestavování tohoto souboru jsou specifické parametry pro platformu spuštění. Nejfrekventovanější jsou například bitové verze (64-bit, 32-bit) platformy a optimalizační parametr (debug, release). Tyto parametry jsou buďto již předvyplněny integrovaným vývojovým prostředím či kompilátorem samotným.[8]

Hlavním prvkem je soubor se zdrojovým kódem, který nese název modulu s doplňkem

„main“. Tento soubor má právě jednu veřejnou metodu, jež se volá při instancializaci vlákna a jejím úkolem je přiřadit hlavní funkce do virtuální tabulky. Virtuální tabulka je koncept pro vytváření objektů a obsahem jsou pointery na funkce, které mají na starost inicializaci a ukončení vlákna spolu s dedikovanou funkcí pro zpracovávání interních zpráv. Takto vytvořené vlákno je spuštěno s vlastními prostředky a sdílí prostředky kernelovského modulu. Vlákna mohou být různého typu, jež závisí na potenciál dopadu na systém.

Například pro modul zpracovávající čtení a zápis do souboru je umožněno systém zbrzdit a počkat na předání dostatečných práv k danému souboru.

Na obrázku 2 můžeme vidět souborovou strukturu finálních modulů pro Mqtt. Tyto moduly jsou rozděleny na Api modul, který není instanciovaný jako vlákno, ale pouze jako kernelovským prostředek. Tento modul umožňuje snadný a přehledný způsob pro komunikaci s ostatními vlákny. Samotná logika je umístěna v modulu Mod.

Moduly dodržují již zmíněnou souborovou strukturu, kde hlavička označena XXXRoot.h je seznam veřejných funkcí, objektů a proměnných. Naopak XXXLoc.h je používána pouze napříč modulem. Takovéto rozdělení do určité míry napodobuje zapouzdřování public a private objektů z C++. Mimo těchto souborů jsou pak důležité zmínit XXXPch.c pro předkompilované hlavičky sloužící pouze při optimalizačních úkonech sestavení programu.

XML soubor v každém modulu slouží pro automatizované generování proměnných

používaných v komunikaci napříč moduly. O toto generování se stará před kompilační fáze sestavování softwarového produktu.

Obrázek 2 Ukázka modulů pro Mqtt. (Zdroj: autor)

(22)

22

2.2 Sestavení projektu Netstar Platform

Průběh sestavení programu se skládá z několika kroků, které jsou z části nestandartními.

Účel těchto nestandartních částí je předpřipravit software na části standartní. Jmenovitě pak se jedná o generaci předdefinovaných proměnných, struktur a objektů pomocí tzv.

DefsGenu a dále kompilací subprogramu Utils, který má za úkol pomáhat při samotné kompilaci projektů. Na konci tohoto procesu očekáváme spustitelný soubor aplikace s definovanými funkcionalitami modulů v něm zakomponovaných.

Jako kompilace se často nesprávně označuje celý proces sestavení binárního souboru.

Nicméně, kdybychom chtěli být přesní, jedná se pouze o část procesu překladu zdrojového kódu čitelný pro lidi, do tzv. strojového kódu čitelného pro stroje. Tato fáze sestavení má několik dílčích kroků, které se však liší v závislosti na použitém kompilátoru. Výsledkem kompilace je tzv. object file pro každý jednotlivý soubor zdrojového kódu. Na rozdíl od jiných programovacích jazyků, které například spoléhají na JIT kompilaci, C++ nebere příliš velkou zřetel na strukturu či počet kompilovaných souborů. [7]

ISO/IEC 14882:2011 definuje 9 základních fází při překladu zdrojového kódu. Tyto fáze se však dají popsat stručněji podle funkce. Jako první jsou syntaktické kroky. Namapování všech literálů ze zdrojového kódu, který je také dekódován do základního setu znaků. Tento set obsahuje 96 znaků potřebné pro překlad. Další fáze obsahují syntaktickou kontrolu, manipulaci s netisknutelnými znaky, nahrazení komentářů a dosazení maker definovaných uživatelem. [10]

Dále následuje zpracování preprocesorem. Preprocesor má za úkol vyhodnotit a dosadit veškeré preprocesorové direktivy ve zdrojovém kódu. Tyto direktivy začínají znakem „#“.

Nejčastější použití je dosazování externích zdrojových kódů a kondiční direktivy (např.

#ifdef). Pro každý jednotlivý vnořený soubor jsou rekurzivně vykonávány výše zmíněné fáze.

[10]

Po těchto před přípravných změnách, kterými prošel každý soubor v našem kompilovaném cíli, je na řadě samotný překlad do strojového kódu. Strojový kód jako takový již obsahuje pouze konstantní data a instrukce v binární formě. Někdy je však nutné vidět, a hlavně přečíst tento strojový kód – například pro optimalizační úlohy. K pomoci a ukázce, jak takovýto strojový kód vypadá, máme jazyk assembly. Assembly je symbolický a abstrahovaný popis strojového kódu. Tento jazyk má symbolické instrukce, které víceméně plní stejnou funkci, ale každý procesor je implementuje jinak. Dosazení do přesné instrukční sady provádí tzv. assembler.

(23)

23 Zde jednoduchá funkce pro vynásobení dvou čísel:

int Mutltiply(int a, int b) {

Log("Multiply");

return a * b;

}

Výpis 1 Ukázka definice funkce. (Zdroj: autor)

se přeloží jako následující strojový kód. Call instrukce například volá externí funkci Log, která je adresována na YAPBDPBD. Samotné násobení čísel probíhá instrukcí imul, která bere operační registr eax, do kterého si v kroku před tím nakopírovala obsah proměnné a, a násobí jím obsah proměnné b.

; Line 9

push OFFSET ??_C@_08EOBDLMOI@Multiply@

call ?Log@@YAPBDPBD@Z ; Log

add esp, 4

; Line 10

mov eax, DWORD PTR _a$[ebp]

imul eax, DWORD PTR _b$[ebp]

Výpis 2 Ukázka assembly kódu. (Zdroj: autor)

Při kompilaci se používá kompilátor MSVC od společnosti Microsoft. Po kroku kompilace jsme ponecháni ve stavu, kde jsou k dispozici pouze dílčí statické knihovny v čistě binárním stavu, nicméně v tomto procesu je ještě jeden dílčí krok. Finální krok pro vyprodukování binárního souboru je nazývaný linkování. Jak již název napovídá, v tomto kroku se spojují jednotlivé object soubory, které byly jako výstup předchozí kompilace. Kompilace samostatná bere každý C++ soubor velice striktně a odděleně. Až v čase linkování se začínají vyhodnocovat jednotlivé symboly a hledají se příslušné definice funkcí. V tomto kroku se také dosazují v našem zdrojovém kódu knihovny třetích stran či standardní knihovny.

Samozřejmě jsou zde před rezervované názvy pro jednotlivé vitální funkce pro běh programu, které nelze použít. Nejčastější chyby jsou buď chybějící externí symboly nebo čirý opak, čímž je víceznačnost symbolu. Při sestavování se tak můžeme setkat se dvěma různými typy chybových hlášek – z kompilačního kroku a linkování. Zdrojový kód, který může být validní pro kompilaci však nemusí projít linkovacím krokem. [20]

(24)

24

Jako například již jednou uvedená funkce spolu s tzv. forward deklarací funkce Log:

const char* Log(const char*);

int Mutltiply(int a, int b) {

Log("Multiply");

return a * b;

}

Výpis 3 Ukázka forward deklarace funkce. (Zdroj: autor)

Projde kompilací, nicméně v případě, že neposkytnu soubor s definicí funkce Log linker vrátí chybovou hlášku při snaze sestavit výsledný spustitelný soubor:

error LNK2001: unresolved external symbol "char const * __cdecl Log(char const *)"

(?Log@@YAPBDPBD@Z)

Výpis 4 Ukázka chybového výstupu linkeru. (Zdroj: autor)

V tomto stavu již máme spustitelnou aplikaci, která má požadované funcionality, avšak nezbytně to neimplikuje, že efekty aplikace uvidíme okamžitě. Je nutné je backendovou službu napojit na další články jako middleware popř. frontend.

(25)

25

2.3 Technické specifikace projektu Netstar Platform

Pro pochopení současného stavu projektu Netstar je nutné pochopit historie jazyku C/C++

a produktu Netstaru jako takového. Původní produkt byla hardwarová podoba, kde software byl psán na nízko úrovňovém jazyku. Tato forma umožňovala rychlý a jednoduchý provoz.

A tento přístup a důraz na rychlost a efektivitu byl zachován dodnes i po převedení produktu do softwarové podoby. Spolu s tímto faktem se ale nezměnila ani nízká úroveň jazyka, který začal zaostávat z pohledu dostupných programových prostředků.

Historie programovacího jazyku C++ sahá až do roku 1979, kdy Bjarne Stroustrup pracoval na jeho někdejší disertační práci. Při vypracovávání této práce měl Stroustrup možnost setkat se s programovacím jazykem zvaným Simula. Simula byl primárně navržený pro simulace a je obecně označovaný jako první programovací jazyk, který používal paradigma objektového programování. Stroustrup byl unesen tímto, v té době, inovativním směrem programování, avšak psaní samotného zdrojového kódu bylo příliš pomalé pro praktickou aplikaci. Nedlouho poté začal vyvíjet svůj vlastní programovací jazyk, který nazval „C with Classes“. Bylo to rozšíření již existujícího jazyka C o objekty. Programovací jazyk C byl poměrně známý a uznávaný pro jeho spolehlivou rychlost a zároveň přenositelnost, nicméně Stroustrup přidal tomuto jazyku třídy, základní dědění, inline funkce a typování silného typu. [11]

Základním stavebním kamenem každého programovacího jazyka jsou příkazy na ovlivnění chodu programu. Do určité míry je možné každý program zredukovat na podmíněné větvení, cykly a konstantní data. C++ není výjimkou a tyto funkcionality nabízí od velice nízko úrovňových alternativ (goto) až po novější a sofistikovanější (range for). Tyto základní kameny se dají rámcově dělit na větvící, iterativní a skokové spolu s dalšími méně používanými příklady. Chod programu můžeme ovlivňovat i jinými úkony od podmínek až nekonečné cyklování určité části programu. Logika programu sama o sobě není až tak dobře využitelná. Druhou nezbytnou komponentu, kterou doplňuje tuto část, jsou data a manipulace s nimi. C a C++ jazyk jsou staticky typované jazyky a jako takové nabízejí základní množinu primitivních a derivovaných datových typů. Pro efektvní práci s těmito datovými typy byly vytvořeny kontejnery. Specializované datové struktury, do kterých je možné takové to proměnné vložit a posléze rychle vybrat, hledat, smazat a aktualizovat.

[12][21]

(26)

26

Ovšem v původním jazyku C nebyly takovéto datové struktury. Byly vytvořeny dodatečné knihovny mající svou vlastní implementaci, avšak tyto knihovny byl výtvor až subjektů třetích stran a nebyly k dispozici od samotného počátku. A kvůli všem těmto důvodům se Netstar Platform rozhodl jít svojí cestou. Je zde k dispozici několik datových struktur, které do jité míry kopírují C++, ale nejsou stejně intuitivní. K dispozici v tuto chvíli jsou obecné mapy, hash mapy, spojové seznamy různých typů a stromové struktury. Mimo tyto existují v projektu i další, které jsou však velice specializované a rámcově jsou kombinací některých z již vyjmenovaných datových struktur. Specifičnost struktur v Netstaru je evidentní již od samotné inicializace a konstruování těchnto struktur. Při inicializaci je nutné dodat jednak místo alokované pro objekt samotný, ale i getovou a komparační funkci. Pokud budeme hledět na tento přístup můžeme udělat snadnou paralelu k uživateli definovaným strukturám z jiných vyšších programovacích jazyků. Je zde ještě jeden element, jež každý objekt, který chce být přidán do této struktury, musí obsahovat. Speciální pointerovou proměnnou, na která samotná struktura bude ukazovat a přes kterou bude tento objekt dostávat.

2.3.1 Pointery a reference

Mezi nejkontroverznější prvky jazyka C++ se rozhodně řadí pointery a reference. Tyto dva datové typy jsou nedílnou součástí a také důvod značné neoblíbenosti jazyka celkově. Dnes je již velice raritní vidět programovací jazyk, který tyto koncepty zapracovává do svého základu. Ironicky všechny ostatní vyšší programovací jazyky, které tuto funkcionalitu mají odstíněnou vrstvou abstrakce je používají úplně stejným způsobem. Specificky tyto dva datové typy dávají tomuto programovacímu jazyku, jak obrovskou moc nad výpočtem, tak bohužel dělá celý proces učení pro nováčky daleko složitější. [22]

Celý princip pointerů je pouze o možnosti se dotazovat na danou proměnou či funkci přes její adresu v paměti. Každá alokovaná paměť dostane určitý blok a adresu virtuální paměti od operačního systému. Existují způsoby, jak alokovat takovou paměť mimo přidělený region, ale vzdáváme se možnosti používat reference na tyto proměnné. Pointer je datový typ, který má v sobě uloženou adresu jiné proměnné. Na samotnou proměnnou pak můžeme přistupovat přes tuto adresu. Adresu proměnné dokážeme získat přes operátor „&“. Bohužel samotná proměnná o datovém typu pointer má také svoji adresu. A toto vnořování lze uskutečnit nekonečně mnohokrát. To zapříčiňuje neoblíbenost a dle mnohých nepřehlednost práce s ukazateli a referencemi. [13]

int a = 20; // deklarace primitivní proměnné int* p; // deklarace proměnné typu pointer

p = &a; // přiřazovací příkaz pro uložení reference do pointeru

Výpis 5 Ukázka přiřazení reference do proměnné. (Zdroj: autor)

V moderním C++ jsou přítomny takzvané smartpointery neboli chytré ukazatele. Ty mají do jisté míry ulehčovat práci a pochopení těchto neoblíbených datových typů. Navíc ale poskytují velice užitečnou funkcionalitu spojenou se samostatným hlídáním životnosti proměnné, která je velice inspirována tzv. garbage collectory. Mimo to nabízí velmi dobré

(27)

27

synchronizační nástroje při multi vláknovém programování a dělá tyto pointery nepostradatelnými nástroji moderního C++ vývojáře. [13]

Projekt Netstar Platform samozřejmě v obrovské míře využívá možnosti pointerových proměnných a reference, nicméně je zde i implementován smartpointer pro často využívané typy napříč moduly. Takovéto proměnné jsou zpravidla umístěna v kernelovském modulu.

Vytváření a následná destrukce alokované paměti pro potřebná data je prováděna pouze skrze řídící vlákna obsluhující ostatní moduly. Jako nejčetnější příklad by bylo vhodné uvést interní message, která je podrobněji rozebírána dále v této kapitole. Po zažádání jádra o vytvoření takovéhoto objektu je nám dán k dispozici pointer, jehož datový segment můžeme upravovat. Jako finální krok každé zprávy je odeslání, avšak objekt nám přišel s již pevně daným počtem, kolikrát tuto zprávu můžeme poslat. Jakmile se tato proměnná dostane na nulu, je tím vyčerpána její životnost a následně automaticky zničena kernelovským modulem. Adresní vlákno zprávy je zodpovědné za to, překopírovat veškerá relevantní data v aktivním scopu aplikace a posléze zahodit pointer zprávy. Obecné smartpointery využívají podobné mechaniky a tento čítač nazývají reference counter. Tento counter však drží počet aktivních referencí, které objekty mají mezi celou aplikaci a pakliže je counter dekrementován na nulu, je i tento objekt uvolněn.

2.3.2 Objekty

Hlavním cílem C++ bylo obohatit předchozí jazyk C o objekty. To je uskutečněné pomocí implementace tříd, které působí jako hlavní zdroj objektů. Třídy samostatně představují pouze šablonu, podle které se samotná instance objektu vytvoří. Tuto šablonu tvoří data a jednotlivé členské funkce. Pro dodržení základního pilíře objektového programování – enkapsulace – je nutné pro členské data a funkce použít modifikátory přístupu. Tyto modifikátory nastavují viditelnost jednotlivých parametrů ostatním objektům. Doporučuje se defenzivní přístup k těmto oprávněním, proto jsou všechny datové prvky označené jako privátní není-li explicitně řečeno jinak. [13]

Vytváření objektů v C++ se provádí pomocí volání konstruktoru jako v ostatních vyšších programovacích jazycích, nicméně z důvodu nutnosti přímé operace a správě paměti je zde odlišnost v podobě destruktoru. Tato speciální třída, která začíná znakem tilda, je zodpovědná za uvolnění přidělené paměti na konci jeho životního cyklu. Pro jednodušší objekty je možné použít implicitní konstruktory a destruktory poskytované kompilátorem, avšak tento přístup bude velice neefektivní u složitějších objektů. Speciálním typem je pak copy konstruktor, který má na starosti správné překopírování objektu do odlišné instance.

Jako každý datový typ i třída má svoji adresu a to znamená, že můžeme vytvořit pointer na třídu, což bohužel pouze přidává na komplikovanosti již tak náročných pointerů. [23]

(28)

28

Obecně řečeno třídy ani objekty nejsou součástí C jazyka, jelikož C není objektově orientovaný jazyk. Nicméně je důležité si uvědomit fakt, že C je přímá podmnožina jazyku C++, a tak z definice, by bylo možné takové vlastnosti zkonstruovat i v tomto nižším jazyku.

Projekt Netstar Platform je přesně touto variantou. Kernelovský modul zorchestruje implicitní chování C++ jazyka co se týče správy objektů. Objekt je popsán svými vlastnostmi a jednou z nich je dědičnost.

struct parent { int a;

};

struct child {

struct parent base;

int b;

};

int main() {

struct child derived;

derived.b = 1;

derived.base.a = 2;

}

Výpis 6 Ukázka dědičnosti. (Zdroj: autor)

V ukázce zdrojového kódu lze vidět, jak takovéto dědičnosti dosáhnout v případě struktur.

Pro paměťovou optimalizaci je však podmínkou, aby mateřský objekt byl uveden na prvním místě. Proměnná base nám pak slouží jako reference pro nadřazený objekt a klíčové slovo

„super“ v ostatních vyšších programovacích jazycích je obdoba této reference. Tento příklad je pravděpodobně nejjednodušší a v projektu nalezneme pokročilejší elementy čerpající z disassembly C++ (rozloženého jazyka C++ v nižších programovacích formách).

Majoritně nejpočetnější objektem v Netstar Platform je tzv. Common Data Resource Interface 3. Tento objekt je přítomen u velké část business logiky a je používán na specializovanou komunikaci mezi moduly. CDRI3 má svoji základní strukturu funkci Init na inicializování objektu, funkci Exit pro ukončení a dealokovaní prostředků objektu a funkci pro zpracovávání zpráv. Toto zpracovávání je jedním z nejdůležitějších kroků v softwarové logice, jelikož je to jediné místo, kde je umožněn datový přenos mezi moduly.

(29)

29 2.3.3 Vlákna

Více vláknové programování je v dnešní době standardním optimalizačním přístupem a je hojně využíván na všech úrovních softwaru. Vždy tomu tak nebylo. Možnosti souběžného zpracovávání běžícího softwaru přišlo až s rozšířeností více jaderných procesorů, které tuto funkci podporovali. Není tedy asi překvapení pro nikoho fakt, že na tuto skutečnost jazyk C nebyl vůbec přizpůsoben. Co však je méně známý fakt, že i vyšší programovací jazyk C++ v prvních verzích neměl žádnou podporu vláken. Až od verze C++11 byla tato funkcionalita dodána a další verze 14 a 17 dále zlepšovali tuto funkcionalitu. Posléze byla tato funkcionalita dodána i do jazyka C skrze tzv. POSSIX thready. Tyto thready jsou založeny na otevřeném standardu POSSIX pro unixové operační systémy. V dnešních verzích Windows již najdete adaptaci winApi pro tyto vlákna, takže je lze označit za multiplatformní standard. [25]

Oproti vláknům a jejich prostředkům v C++ je v projektu Netstar Platform pouze zlomek funkcionality. Synchronizační prostředky – mutexy - jsou omezeny pouze na pevné zámky pro jednotlivé vlákna, bez žádných vymožeností postupného uvolňování. Vlákna v kontextu Netstar také mají tři kategorie, které specifikují jejich vlastnosti. Jedná se o kooperativní, preemptivní a platformní skupiny. Platformní vlákna jsou typem, který má největší vytíženost a je zde i nejvyšší risk hazardu či zamrznutí. Obecně jsou to vlákna, která nějakým podstatným způsobem přijímají nebo odesílají větší množství dat. Takováto vlákna pak musí mít speciální možnost tvrdého exitu při žádosti ze strany operačního systému. Další skupinou vláken je preemptivní. Tyto vlákna mají toleranci v řádech několik milisekund odezvy a typickým příklad by bylo čtení/zapisování do jednoduchého textového souboru.

Kooperativní vlákna jsou pak nejbezpečnější a musí garantovat, že nikterak nezpomalí nebo nezablokují celkový chod programu.

(30)

30 2.3.4 Messages

Posledním technickým specifikem projektu Netstar Platform jsou interní zprávy. Tyto zprávy nejsou žádnou obdobou existujícího prvku z C++. Jsou čistě unikátní pro tento projekt. Jak bylo výše zmíněno, každý modul musí splňovat předdefinovanou souborovou strukturu v níž se nachází i xml soubor, který obsahuje definice interfaců zpráv pro generátor. Tento soubor definuje parametry pro interní komunikaci a ladění. Generátor před samotnou kompilací projektu přečte parametry a vygeneruje své hlavičkové soubory, které připojí do všech ostatních modulů. Dle firemní politiky je přísně zakázáno, aby moduly mezi sebou sdílely data jinak než přes interní zprávy. Interní zprávy jsou binární stream mezi jednotlivými instancemi modulů a jsou moderovány právě kernelovským modulem.

Tyto zprávy obsahují data, která se přidávají do spojového seznamu zprávy jako tzv.

informační elementy, zkráceně „IE“.

struct MESSAGE * pM = MessAlloc(1000);

pM->Group = MESS_GROUP_MQTT;

pM->Id = MQTT_MESS_PUB_RECEIVED;

IE_Append(&pM, &msgID, IE_SUB_ID, sizeof(int));

MessPost(pM, CdriGetHandle(&pQ->Base.Base));

Výpis 7 Ukázka konstrukce interní zprávy. (Zdroj: autor)

Tyto informační elementy musí být definovány v xml souboru umístěný v modulu. Tyto zprávy mají vlastní škálovatelnost a umí se tak přizpůsobit extrémním podmínkám platformy. Jsou také velice robustní a doručovací systém klade velký důraz na správné logování všech akcí. To obrovským způsobem zjednodušuje debugging rozsáhlého projektu.

Ne všechny moduly jsou si však v tomto projektu rovny. Zejména pak kernelovský modul, který je kompilovaný jako první a obstarává všechna systémová volání. V každé výsledné aplikaci musí být tento modul přítomný. Jeho částí jsou i specializované moduly, která však nemají svá vlastní vlákna a místo toho mají určitou množinu, jejíž velikost závisí na výkonnosti systému. Do této skupiny patří i modul Cdri, který pro naše účely zprostředkovává komunikaci přes TCP protokol.

(31)

31

3 MQTT protokol

Cílem kapitoly je popis nutného teoretického základu fungování a prvků MQTT protokolu.

V úvodu kapitoly je brán zřetel na funkcionalitu a provozní chování dle reference MQTT protokolu. V druhé části jsou pak rozebírány jednotlivé stavební prvky komunikace – kontrolní pakety. Pro správné datové zakódování paketů a následné správné chování aplikace je nezbytné, aby byl tento teoretický základ dokonale adaptován v procesu implementace.

3.1 Specifika protokolu MQTT

MQTT je zkratka pro MQ Telemtery transport, dříve také Message Queuing Telemetry Transport. Jedná se o otevřený OASIS standard, který popisuje jednoduchý a přenosově nenáročný síťový protokol založen na posílání zpráv do centralizovaného bodu. Tento centralizovaný bod se nazývá broker a celý systém používá komunikace podle návrhového vzoru publisher – subscriber. Přenos informací probíhá pomocí TCP a staví se tak až na svrchní aplikační vrstvu referenčního modelu OSI. Díky jeho úsporným vlastnostem je tento protokol používán v podobě notifikací mezi aplikacemi, např. Facebook Messenger, nebo pro komunikaci v síti Internet of Things. [3]

Provozní chování MQTT nastiňuje vztahy mezi elementy protokolu. Prezentuje, co musí vývojář, který chce tento protokol adaptovat, splnit a poskytuje další užitečné doporučení při adaptaci protokolu. [1]

3.1.1 Session state

Session je obecné označení pro úspěšné navázání spojení. Toto spojení má svá specifika komunikované na počátku komunikace probíhající skrze pakety CON, CONACK a DISCONNECT. Po stránce významu je pak paket CON nejdůležitějším, jelikož nese unikátní identifikátor pro spojení. Takovýto identifikátor je povinen server uložit a umožnit klientovi opakované připojení v případě, že neuběhl interval dohodnutý v CON paketu. Po uběhnutí takovéhoto intervalu je pak session smazána. [1]

(32)

32 3.1.2 Quality of Service

Jedna z nejdůležitějších vlastností komunikace přes protokol MQTT je Quality of Service.

Jedná se o vyjednanou úroveň kvality komunikace mezi klientem a serverem. V protokolu jsou rozlišovány tři úrovně komunikace:

• Úroveň nula – garance na doručení zprávy není, někdy označována jako odešli a zapomeň

• Úroveň jedna – garance na doručení zprávy alespoň jednou

• Úroveň dvě – nejvyšší stupeň kvality, garance na doručení zprávy je právě jedna Tyto úrovně se liší počtem a typem paketů, které je nutno poslat. Další fakt je, že tato kvalita je definována pouze mezi klientem a brokerem. Nepřesahává tak tato kvalita až na koncového klienta. Je možné tak poslat zprávu s dohodnutou kvalitou na úrovni dvě, nicméně klient, který tento kanál odebírá, může takto odebírat v rámci úrovně 0.

Kvalita komunikace na úrovni nula je přímo závislá na kvalitě TCP spojení, nad kterém MQTT komunikace běží. Oproti tomu, úroveň dva již má povinný potvrzovací paket na každou publikovanou zprávu. Tímto potvrzovacím paketem je však potvrzena pouze jedna strana komunikace, a proto se může stát, že při nedoručení potvrzovací zprávy klient bude stále odesílat tu samou zprávu. Tento problém řeší nejvyšší a zároveň nejpomalejší stupeň MQTT komunikace. Druhý stupeň potvrzuje obě strany komunikace, a to přes tři dedikované pakety, jejichž účelem je postupně potvrdit zpracování zpráv od všech zainteresovaných stran. [4]

(33)

33 3.1.3 Standard properties

Set standardních properties umožňuje paketu nést podrobnější informace. Není součástí všech paketů, a i v případech, kdy je přítomen, je zde podkategorie, která označuje dovolenou vlastnost pro daný paket. Těchto vlastností je možno přidat určité množství a každá kategorie má své specifika pro opakování. [1]

Obrázek 3 Seznam standard properties. (Zdroj: [1])

(34)

34 3.1.4 Topic Names a Topic Filters

Pro určení požadovaného kanálu k odebírání či zaslání zprávy se v MQTT používá řetězec zvaný topic. Tento topic je strukturovaný podobně jako cesta k souborům ve filesystému a to tak, že jeho separátor jednotlivých úrovní je znak lomítka (“/” U+002F). Tyto lomítka pak jednotlivé úrovně hierarchicky řetězec uspořádávají do stromové struktury. V řetězci pro topic se mohou objevovat také další znaky, ale výrazně záleží, zda se jedná o Topic name či Topic filter. Topic name je použit u procesu publikování zpráv, a proto nesmí být řetězec vyložen několika způsoby. U odebírání však toto pravidlo neplatí. Chceme-li odebírat více kanálů najednou můžeme toho docílit chytrým sestavením Topic filtru využívající Wildcards. Wildcards se rozlišují na dvě skupiny – jedno a víceúrovňové. Jednoúrovňové jsou definované jako znaménko plus (“+” U+002B) a poskytují zástupný znak na jednu úroveň stromu. Znak mřížky (“#” U+0023) uvozuje víceúrovňové zástupné znaky. Je povoleno libovolné množství kombinací těchto znaků v jednom řetězci. [1]

3.2 Kontrolní pakety

Kontrolní paket je označení pro základní stavební prvky komunikace přes protokol MQTT.

Je nezbytné pochopit tyto prvky, jejich vztahy mezi nimi a strukturu. Bez takovéto znalosti není možné zprostředkovat jakoukoliv komunikaci. Každý kontrolní paket je rozdělen do tří základních částí:

• fixní header

• variabilní header

• payload

Fixní header je pevně daný, co se týče struktury, nicméně nikoli, co se týče délky. Obsahuje identifikaci paketu s jeho následnou délkou kódovaný jako Variable byte integer. Tato datová reprezentace délky je flexibilně dlouhá. Fixní header je jediná povinná složka každého paketu, proto jej nebudeme zahrnovat do kapitol zkoumající strukturu jednotlivých paketů.

Obrázek 4 Ukázka obecné definice fixního headeru. (Zdroj: [1])

Variabilní header a payload jsou další části, ze kterého se paket skládá, nicméně jejich přítomnost a struktura je specifická a záleží na typu paketu. V některých není přítomen ani jeden, jako například u PINGREQ paketu, který se skládá pouze z fixního headeru.

Struktuře těchto dvou částí se tedy musíme zabývat odděleně u každého paketu zvlášť.

Tato sekce si dává za úkol seznámit čtenáře s kontrolními pakety protokolu MQTT, jejich významu a struktuře. [5]

(35)

35 3.2.1 CONNECT paket

První ze skupiny kontrolních paketů a zároveň první v pořadí při inicializaci spojení je paket Connection request s označením CON. Tento paket musí být poslán jako první forma komunikace ze strany klienta směrem k definovanému serveru či brokeru. V průběhu síťové komunikace může klient poslat pouze jediný CON packet, který server musí zpracovat a odeslat odpověď – buď ve formě CONACK potvrzující správně vyjednaného spojení či některé z možností chybové odpovědi. Chybové odpovědi jsou množina možných reakcí serveru na nesprávný CON packet. Tyto možnosti zahrnují mimo jiné packet s reason kódem či uzavření TCP spojení. Využívané možnosti se liší podle implementace serveru. V případě, že klient pošle druhý CON packet v průběhu již navázaného spojení, je takováto akce považovaná za chybu a server v tomto případě musí uzavřít síťové spojení s klientem. [17]

Po fixním headeru, který je i zde přítomen, následuje variabilní header, jehož struktura je složena z polí protocol name, protocol level, connect flags, keep alive intervalu a standardní skupiny properties.

První pole ve variabilním headeru slouží pro určení jména protokolu. Toto pole je právě 6 bytu dlouhé a obsahuje délku kódovanou na prvních dvou bytech, přičemž první byte je označován jako most significant bit neboli nejvýznamnější bit pro hodnotu délky protokolu a analogicky další byte je least significant bit délky. Následující čtyři byty obsahuje řetězec MQTT, který musí být dle UTF-8 kódování. Toto pole je statické a dle konsorcia OASIS nebylo a nebude v budoucnosti nikdy měněné. Toto pole slouží pro servery, které podporují více než jeden komunikační protokol, firewally a analyzátory paketů pro určení MQTT provozu. V případě, že server nepodporuje takovýto protokol musí zavřít síťový kanál s klientem. Pole protocol version je jeden byte dlouhé a určuje verzi MQTT, která se bude pro nadcházející spojení využívat. V době psaní tohoto dokumentu jsou dostupné pouze dvě verze. Třetí pole je opět dlouhé jen jeden byte a obsahuje několik parametrů vlastností připojení a indikuje přítomnost některých polí v payload. Tyto příznaky jsou příznaky pro uživatelské jméno a heslo, will retain, will qos, will flag a clean start řazené od nejvyššího bitu po nejmenší. První, nulový, bit je rezervovaný a musí být nastavený na nulu. V opačném případě je paket neplatný a označený jako malformed. [1][2]

Předposlední pole variabilního headeru je určení intervalu pro vypršení session. Keep alive je kódovaný neznaménkový celočíselný typ na dva byty, kde první je most significant bit a druhý least significant bit. Tato číselná hodnota určuje počet sekund od posledního přijatého kontrolního paketu od klienta, při kterém je udržován komunikační kanál. Je klientova odpovědnost dodržovat takto stanovený interval a při nedodržení jednoho a půl násobku takto stanoveného intervalu musí server zavřít síťové spojení s klientem. V případě, že je v paketu CONACK uveden keep alive, je nucen klient dodržovat tuto hodnotu namísto navrhované v CON paketu. V případě nuly není ani jedné straně nucený žádný interval pro obnovování komunikačního kanálu. Pro udržení spojení v situaci, kdy není žádný provoz přes komunikační kanál, musí klient posílat paket PINGREQ pro znovuobnovení odpočtu intervalu. Vzhledem ke dvou bytové podobě intervalu je maximální hodnota 65 535 neboli 18 hodin 12 minut a 15 sekund. Větší interval není v tomto protokolu podporován. Následné pole je nepovinné a jedná se o standardní list Properties. Je zde několik specifikovaných vlastností s informativním charakterem, nicméně nejdůležitější jsou definovány kódy 0x21

Odkazy

Související dokumenty

- Existence rizika (neurčitost, jakou hodnotu bude mít nemovitost na konci sledovaného období). Hlavní rozdíl mezi diskontní a kapitalizační mírou spočívá v tom,

[r]

[r]

This option runs an F-test to compare the variances of the two samples. It also constructs confidence intervals or bounds for each standard deviation and for the ratio of

Proseminář z Matematické analýzy, ZS 2021 – 2022 Teoretické

b) její determinant je roven 0, ale žádné dva její prvky nejsou stejné.. 2. řádu

Címje zpusobena absence animacních programu ve vetšine zarízení ve Špindlerove Mlýne a zda -lije skutecne animace rozhodující konkurencní výhodou pro volbu daného strediska

• Přidání sítě na R27 proběhne jako obvykle s tím rozdílem, že po přijetí UPDATE paketu na R26 (a šíření informací o síti k R25) odešle R26 na multicast rozhraní