Top Banner
Univerzita Hradec Králové Fakulta informatiky a managementu Katedra informatiky a kvantitativních metod Android aplikace pro základní konfiguraci a monitoring routerů MikroTik Bakalářská práce Autor: Matěj Daníček Studijní obor: Aplikovaná informatika Vedoucí práce: doc. Ing. Filip Malý, Ph.D. Hradec Králové duben 2015
65

Univerzita Hradec Králové Fakulta informatiky a ...

Oct 15, 2021

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
a monitoring router MikroTik
Hradec Králové duben 2015
Prohlašuji, e jsem bakaláskou práci zpracoval samostatn a s pouitím
uvedené literatury.
Podkování:
Dkuji vedoucímu bakaláské práce doc. Ing. Filipu Malému, Ph.D za metodické
vedení, rady a vstícnost pi zpracování této práce. Dále také rodin za trplivost a
podporu, bez ní by práce nemohla vzniknout.
Anotace
Obsahem této bakaláské práce je popis tvorby a souástí Android aplikace pro
základní konfiguraci a monitoring router MikroTik pomocí RouterOS API, jeho
úelem je poskytovat rozhraní práv pro aplikace takovéhoto typu. Ve své teoretické
ásti se práce zabývá jak popisem základních komponent a zpsob vývoje aplikací na
platform Android, tak samotným RouterOS, strukturou konfigurace, API a zpsobem,
jakým lze pomocí nj komunikovat se zaízením. Vytváená aplikace není zamýšlena
jako plnohodnotné nahrazení oficiálních nástroj pro konfiguraci (jako nap. aplikace
Winbox), avšak má být nástrojem pro rychlé kontroly stavu zaízení i menší zmny
konfigurace a pípadným základem pro budoucí vývoj a rozšiování funkcionality.
Klíová slova: Android, Java, MikroTik, RouterOS, MikroTik API, Winbox
Annotation
of MikroTik Routers
This Bachelor Thesis focuses on the components and development process of an
Android application that would provide users with tools for basic monitoring and
configuring of MikroTik routers using the RouterOS API which is intended to provide
an interface for applications similar to this one. In its theoretical part, the thesis
describes core components and methods that are used in Android application
development as well as RouterOS itself, its configuration, API and ways of its usage.
The application itself is not intended to be a full substitute for official configuration
tools (such as the Winbox application). The goal is to provide a tool for performing
quick status checks and minor configuration changes as well as a foundation for
possible future development and adding other functions.
Key words: Android, Java, MikroTik, RouterOS, MikroTik API, Winbox
Obsah
1. Úvod............................................................................................................................................................. 1
3.3.3. Píkaz „listen“...................................................................................................................... 18
4. Vývoj aplikace........................................................................................................................................ 20
4.1. Komunikaní modul................................................................................................................... 20
4.1.4. TLS pipojení....................................................................................................................... 23
4.2. Správce spojení............................................................................................................................ 23
4.3. Obnovování spojení.................................................................................................................... 24
4.3.3. Runí obnova spojení....................................................................................................... 26
4.4.2. Element <list>..................................................................................................................... 28
4.4.3. Element <propertyTab>.................................................................................................. 28
4.4.4. Element <property>......................................................................................................... 29
4.4.5. Element <scan>.................................................................................................................. 30
4.6.1. Tída ListController.......................................................................................................... 36
4.6.2. Tída AddController......................................................................................................... 37
4.6.3. Tída DetailController..................................................................................................... 38
4.6.4. Tída ScanController........................................................................................................ 38
4.6.5. Zobrazovací rozhraní....................................................................................................... 38
4.8.3. Obnovení do posledního stavu..................................................................................... 46
4.10.3. Obnovení do posledního stavu..................................................................................50
1. Úvod
Cílem této práce je vytvoit aplikaci, která by umoovala základní konfiguraci
a monitoring router se systémem RouterOS (tedy router od spolenosti MikroTik)
z mobilních zaízení i tablet se systémem Android a popsat vzniklé problémy
a postupy, které budou pi vývoji vyuity.
Zaízení MikroTik poskytují levné, snadno konfigurovatelné, avšak dostaten
robustní ešení pro síové pouití. Jejich konfigurace z osobních poíta je provádna
nap. pomocí oficiální aplikace Winbox s pehledným grafickým uivatelským
rozhraním. Pokud však správce sít nemá k osobnímu poítai pístup a je nutné co
nejrychleji zjistit a pop. odstranit závadu na síov infrastruktue, aplikace pro
mobilní zaízení je vhodným ešením.
Vzhledem ke své dominanci na trhu mobilních zaízení (podle serveru Business
Insider [1] více ne 80 % svtových mobilních uivatel pouívá zaízení s nkterou
z verzí operaního systému Android) byla vybrána práv tato platforma.
Pro správce sít i síového technika je také nutná evidence zaízení (tak, aby nemusel
pokadé zadávat adresu a pihlašovací údaje), rychlé zjištní zda je zaízení „online“
a monost zaízení jednoduše restartovat.
1
2. Android API
V této kapitole jsou popsány základní obecné principy vývoje Android aplikací, jejich
základní struktura a zpsob vytváení uivatelského rozhraní. Konkrétnjší postupy
vyuité pi vývoji aplikace budou popsány v píslušné ásti kapitoly 4 – Vývoj
aplikace.
„Aktivita je komponenta aplikace umoující zobrazení obrazovky, se kterou me
uivatel interagovat za úelem provedení poadovaných akcí.“[2] Aplikace zpravidla
obsahuje více aktivit, mezi kterými je mono pecházet a posílat výsledky. Z jedné
aktivity je moné spustit aktivitu jinou, „(...) v ten moment je pvodní aktivita
zastavena, avšak systém si ji a její stav uchová v zásobníku. Pi otevení nové aktivity je
tato vloena do zásobníku, zobrazena a je na ní umístno zaostení (focus). Zásobník
vyuívá princip „last in, first out“ (tedy „poslední dovnit, první ven“) tzn., e pokud
uivatel skonil svou práci v aktivit a stiskl tlaítko „zpt“, je tato ze zásobníku
odstranna a zniena (destroy) a pedchozí aktivita je obnovena (resume).“ [2]
2.1.1. ivotní cyklus
Jak uvádí dokumentace na serveru developer.android.com [2], aktivita me být ve 3
hlavních stavech:
Resumed (pokraující) nebo také running (bící) – stav, ve kterém je aktivita
v popedí a je na ní zaosteno.
Paused (perušená) – jiná aktivita je v popedí, ale je ásten prhledná nebo
nezabírá celou obrazovku. Perušená aktivita není ukonená, avšak v pípad
akutního nedostatku pamti me být tato aktivita systémem ukonena.
Stopped (zastavená) – aktivita je celá pekryta jinou aktivitou a pro uivatele tedy
není viditelná. Me být systémem ukonena pokud je nutné uvolnit pam.
„Pokud je aktivita perušena i zastavena, systém me uvolnit pam jejím
odstranním. A to bu zavoláním metody finish() nebo jednoduše ukonením jejího
2
procesu.“[2] Proto také není doporuováno pouívání aplikací (tzv. „task killers“),
které automaticky ukonují aplikace na pozadí. Jak poznamenává nap. Whitson [3],
automatické ukonování je nejenom neúinné pro zrychlení zaízení a prodlouení
výdre baterie, ale dokonce kontraproduktivní, nebo aplikace a jejich aktivity musí
být vytvoené znovu, co je oproti udrování v pamti daleko náronjší a pomalejší.
Rizikem je také nestabilita systému, pípadn nedostupnosti nkterých funkcí.
O pechodu mezi stavy je aktivita informována pomocí volání metod uvedených na
obr. 1. Tyto metody lze pepsat tak, aby provádly konkrétn to, co je pro danou
aktivitu v dané chvíli poteba. Pro správnou funknost je však nutné vdy zavolat
metodu základní tídy (pomocí volání super.jmenoMetody). Mezi nejdleitjší
z tchto metod patí mj. onCreate a onPause. Typickými innostmi v tchto metodách
jsou podle developer.android.com [2] nap.:
onCreate – Tato metoda je volána pi vytváení aktivity. Jejím obsahem by mlo být
definování prvk, které nebudou bhem ivotního cyklu aktivity mnny (tedy nap.
prvky grafického uivatelského rozhraní, navázání dat na seznamy atp.).
onPause – Volána pedtím, ne je aktivita pekryta jiným objektem. V této metod by
mlo docházet mj. k uloení i aktualizaci perzistentních dat, zastavení animací i
jiných operací nároných na CPU a uvolnní prostedk, které mohou být vyuívány
jinou aktivitou i aplikací (tedy nap. fotoaparát [4]). Pro plynulý a rychlý pechod
mezi aktivitami by tyto innosti nemly být asov nároné, nebo následná aktivita je
zobrazena a po dokonení této metody.
3
2.2. Fragment
„Fragment pedstavuje innost i ást uivatelského rozhraní v aktivit. V jedné aktivit
mete kombinovat více fragment a vytvoit tak více-panelové uivatelské rozhraní
a znovu vyuívat fragmenty ve více aktivitách.“[5]
4
Obr. 1: ivotní cyklus aktivity. Zdroj: [2]
Fragmenty tedy lze vyuívat jako urité podásti aktivit. Mají vlastní ivotní cyklus,
který je sice vázán na ivotní cyklus zastešující aktivity (pokud je napíklad aktivita
uvádna do stavu paused, jsou všechny fragmenty v ní uvedeny do stejného stavu), ale
umouje pracovat i s jednotlivými fragmenty (pidávat, odebírat apod.).[5]
2.3. Manifest aplikace
„Kadá aplikace musí mít ve svém koenovém adresái umístn soubor
AndroidManifest.xml (pojmenování souboru je striktní a nemnné). Manifest poskytuje
systému Android informace nutné pro spuštní aplikaního kódu.“[6] Mezi tyto
informace patí mj.: [6]
Jméno JAVA balíku aplikace, které slouí jako jednoznaný identifikátor dané
aplikace. Pro správné identifikování verzí musí zstat stejné po celou dobu ivota
aplikace. Obvykle bývá voleno jako reverzní jméno domény, tedy nap.
com.company.project
které implementují dané komponenty.
„Povolení, která aplikaci musí být udlena, aby mohla pistupovat k chránným ástem
API a mohla spolupracovat s ostatními aplikacemi.“[6]
Minimální verze API, kterou aplikace vyaduje.
Knihovny, se kterými aplikace vyaduje propojení.
Verze aplikace (celé íslo) a jméno verze (volný etzec znak).
2.4. Perzistentní uloení dat
„Android poskytuje nkolik moností pro uloení trvalých aplikaních dat.“[7] Výbr
monosti závisí na konkrétních potebách dané aplikace. Mezi kritéria výbru patí
mj. „privátnost“ dat (zda data mají být pístupná pouze aplikaci i zda k nim mají mít
pístup i jiné aplikace a uivatel), velikost dat, struktura dat (zda budou ukládány
nap. pouze seznamy hodnot nebo je zapotebí uchovávat sloitjší relace mezi daty).
Monosti uloení jsou následující: [7]
5
Shared Preferences (sdílené hodnoty) – Tato monost umouje trvale uloit páry
klí–data, kde data mohou být primitivní datové typy jako boolean – pravdivostní
hodnota, float – íslo s plovoucí desetinou árkou, integer – celé íslo, long i etzec
znak. Sdílených hodnot ve spojení s tídou PreferenceActivity se vyuívá pro uloení
uivatelského nastavení.[8]
Interní a externí úloišt – Nabízí monost pro uloení soubor. V interním úloišti
(tedy v interní pamti telefonu) je moné zvolit, zda bude soubor pístupný všem
aplikacím i pouze té, která ho vytvoila. Pouití úloišt externího (tedy pídavné
pamové karty i pevné pamti telefonu) znamená umonní pístupu k souboru
uivateli i ostatním aplikacím. Pokud ukládaná data budou patit uivateli (nap.
fotografie, videa, nahrané zvuky atp.), je vhodné je umístit do nkteré ze sdílených
sloek v koenovém adresái externího úloišt (tedy nap. /Music, /Pictures,
/Ringtones atp.).
SQL databáze – „Android poskytuje plnou podporu databází SQLite. Jakákoliv
vytvoená databáze je pístupná všem tídám dané aplikace, ale ne aplikacím jiným.“[7]
Pro uchovávání sloitji strukturovaných dat je nevhodnjší SQLite databáze, která se
vyznauje svojí jednoduchostí a malou velikostí.[9]
2.5. Resources
V Android aplikacích je vyuíváno konceptu Resources, tedy externalizace zdroj jako
jsou obrázky, etzce, zvuky a rozvrení zobrazení. Toto umouje spravovat pomocná
data oddlen od zdrojového kódu a také naítat jejich rzné verze podle parametr
zaízení, na kterém je aktuáln spouštna. Lze tak jednoduše provádt jazykovou
lokalizaci i modifikovat rozloení zobrazení pro zaízení s rozdílným rozlišením
a velikostí displaye. Tato data jsou v projektu umístna v adresái /res a jeho
podadresáích, rozdlených a pojmenovaných podle dat v nich umístných
a parametr zaízení, pi kterých mají být pouity.[10]
Mezi nejdleitjší souásti tohoto adresáe patí definice zobrazovaných etzc (v
souboru strings.xml) a definice prvk zobrazování (v adresái /res/layout).
6
Pístup k obsahu adresáe /res je v kódu provádn pomocí volání nkteré z mnoství
metod, které API nabízí. Tmto metodám je v parametru pedáván celoíselný
identifikátor daného Resource objektu, který je získán pomocí tídy R resp. jejich
statických vnitních tíd a konstant. Tato tída je dynamicky vytváena pi sestavování
aplikace.[11] Ve výsledku je nap. získání hodnoty etzce s chybovou zprávou
provádno pomocí následující metody:
Strukturu uivatelského rozhraní lze vytváet dvma zpsoby. Prvním je nadefinování
prvk v XML souboru umístném v podadresái /res/layout a vyuití metody
LayoutInflater.inflate, která na základ celoíselného identifikátoru XML souboru
vytváí a vrací instanci tídy View.[12]
Druhou moností je vytváení prvk programov pímo ze zdrojového kódu. K tomu
je vyuito tídy ViewGroup, tedy zobrazovacího prvku, který me hierarchicky
zastešovat další, dceinné prvky (instance tídy View i jejích potomk). Tato tída
poskytuje mnoství metod pro práci se zastešovanými prvky, mezi n patí nap.
mnohonásobn petíená metoda addView, dále pak getChildAt i removeView.[13]
Tento zpsob je vhodné pouít v pípad, kdy prvky nejsou statické (tedy pedem
známé a nemnné), ale jsou vytváeny dynamicky na základ aktuálního stavu
aplikace.
7
nejpouívanjší a nejpohodlnjší je vyuití oficiální aplikace Winbox, která má
pomrn pehledné a intuitivní grafické rozhraní. Další moností je vyuití SSH i
Telnet klienta a komunikaci prostednictvím konzole, tedy bez grafického rozhraní.
Poínaje verzí 3.0 je uivatelm umonno vytváet vlastní software pro konfiguraci
a správu zaízení s RouterOS pomocí API, tedy rozhraní pro komunikaci aplikací se
zaízením.[14] Tohoto API vyuívají mj. rzné dohledové i „provisioningové“ systémy
jako nap. ISPadmin.[15]
3.1. Balíky a struktura píkazového stromu
„RouterOS nabízí velké mnoství funkcí a vzhledem k tomu, e kadá instalace vyaduje
specifickou mnoinu tchto funkcí, je moné pidávat a odebírat urité skupiny tchto
funkcí pomocí systému balík. Ve výsledku tedy uivatel me ovlivovat podporované
8
Obr. 2: Grafické uivatelské rozhraní aplikace Winbox. Zdroj: [16]
funkce a velikost instalace.“[17] Kadé zaízení tak me podporovat jinou
funkcionalitu a mít jinou strukturu píkazového stromu.
3.1.1. Píkazový strom
Pro snadnjší orientaci jsou píkazy umístny ve stromové struktue. Jméno dané
úrovn odpovídá konfiguraním informacím v ní dostupným.[18] Tedy napíklad „/ip
route“ pro pístup k IPv4 smrovacím cestám (routes) i „/interface vlan“ pro virtuální
LAN rozhraní (VLAN).
Vtšina úrovní menu pedstavuje tabulku (seznam) poloek a jejich atribut (jejich
výpis i navrácení se provádí píkazem „print“). Nad tmito tabulkami je moné
provádt píkazy jako „add“ (pidání poloky), „remove“ (odebrání poloky), „set“
(nastavení hodnoty daných atribut poloky).
Nkteré úrovn neumoují poloky pidávat i odebírat, ale pouze mnit parametry.
Obecn to jsou nap. fyzicky nepidatelné poloky (mj. ethernetová rozhraní) i rzné
seznamy klient (nap. aktivní uivatelé i bezdrátov pipojená zaízení).
Úrovn, ve kterých je uchováváno globální nastavení platné pro více poloek i pro
celé zaízení mají v tabulce pouze jednu neodebratelnou poloku, které je však mono
píkazem „set“ nastavovat hodnoty atribut. Píkladem me být úrove „/ip dhcp-
server config“ a atribut „store-leases-disk“, který udává, jak asto budou zapjení IP
adres ukládány na disk, resp. flash pam.[19]
3.1.2. Funkní balíky
Balíky funkcí je moné získat z webových stránek MikroTik, poté je nahrát do
zaízení a aktivovat, deaktivovat, odstranit, aktualizovat apod. Všechny tyto píkazy
jsou dostupné z úrovn „/system packages“. Dostupný je také píkaz „print“ pro výpis
balík, podle kterého je moné urit strukturu píkazového stromu.[17]
V tabulce 1 jsou uvedeny nejdleitjší dostupné balíky a jejich funkce.
9
ipv6 podpora IPv6 adresování
routing dynamické smrovací protokoly
system základní smrování, IPv4, telnet, API, firewall, SNMP, VLAN, aj.
wireless podpora bezdrátových rozhraní
advanced-tools rozšíené ping nástroje, netwatch (sledování zaízení v síti), IP sken, wake-on-LAN
Tab. 1: Pehled nejdleitjších funkních balík. Zdroj: [17] (upraveno)
3.2. API slova a vty
„Komunikace s routerem probíhá pomocí odesílání vt routeru a pijímání jedné i více
vt jako odpovdí. Vta je sekvence slov ukonená slovem s nulovou délkou. Slovo je ást
vty zakódovaná specifickým zpsobem – zakódovaná délka a data(…) Kadá vta
odeslaná routeru pomocí API by mla obsahovat píkaz jako první slovo, následovaný
dalšími slovy v libovolném poadí, konec vty je tvoen slovem s nulovou délkou. Po
obdrení celé vty (píkazové slovo, pípadná další slova a slovo s nulovou délkou)
routerem je tato zpracována, poté je vytvoena a vrácena odpov.“[14]
3.2.1. Struktura API slova
Kadé slovo ve vt musí být uritým zpsobem zakódováno. V první ásti je uvedena
délka slova, v druhé pak samotný jeho obsah. Délka slova znaí poet byt obsahu,
které budou odeslány.[14]
0x80 a 0x3FFF 2 délka | 0x8000
0x4000 a 0x1FFFFF 3 délka | 0xC00000
0x200000 a 0xFFFFFFF 4 délka | 0xE0000000
více ne 0xFFFFFFF 5 0xF0 a délka ve 4 bytech
Tab. 2: Kódování délky slova. Zdroj: [14] (upraveno)
10
V tabulce 2 je uveden zpsob, kterým jsou kódovány jednotlivé délky slov. V pípad,
e je délka menší ne 0x80 tedy maximáln 0x7F (127 v desítkovém zápisu) byt je
tato délka zakódována v jednom bytu, kde nejvýznamnjší bit má hodnotu 0 a ostatní
urují samotnou hodnotu v rozmezí 0-127. Práv nulový nejvýznamnjší byt uruje,
e délka slova je zakódována práv v jednom bytu.
Pokud je délka slova v rozmezí 0x80 a 0xFFFFFFF, je k ní za pomoci bitového soutu
(bitového OR) pipotena píslušná maska. Díky této operaci urují nejvýznamnjší
bity nejvýznamnjšího bytu celkový poet byt, ve kterých je délka slova zakódována.
Napíklad pokud mají dva nejvýznamnjší bity nejvýznamnjšího bytu hodnoty 1 a 0,
znamená to, e celá délka slova je zakódována ve 2 bytech. Analogicky hodnoty 1,1,0
znaí zakódování délky ve 3 bytech a hodnoty 1,1,1,0 ve 4.
Pokud je délka slova vtší ne 0xFFFFFFF, je hodnota nejvýznamnjšího bytu
nastavena na 0xF0 a další 4 byty (tedy 32bit) nesou informaci o samotné hodnot.
Nejvýznamnjší byte obsahující 0xF0 tedy znaí, e následující 4 byty obsahují
velikost slova.
Tento zpsob kódování umouje zasílat informaci o délce slova v minimálním
nutném potu byt. Není tedy zapotebí, aby první 4 byty byly pevn vyhrazeny pro
délku slova v pípad, e tato délka má malou hodnotu a nkolik z tchto 4 byt by
mlo nulovou hodnotu.
Za zakódovanou délkou slova následuje slovo jako takové. Slovo me být nkolika
typ: píkazové, atributové, API atributové, filtrovací (dotazovací neboli „query
word“) i slovo odpovdi.[14]
3.2.2. Píkazové slovo
Píkazové slovo je zpravidla první slovo v odesílané vt a zaíná lomítkem. Píkazy
mají velice podobnou strukturu jako ty, pouívané v píkazovém ádku (CLI), avšak
jednotlivé úrovn píkazového stromu nejsou oddleny mezerou, ale lomítkem. Také
nkteré CLI píkazy i parametry API nepodporuje, avšak me podporovat jiné
s podobnou funkcionalitou. Píkladem me být filtrovací parametr „where“ pro
píkaz „print“ a jeho nahrazení filtrovacími slovy (query words).[14]
11
/ip/address/getall
/user/active/listen
/interface/vlan/remove
3.2.3. Atributové slovo
Píkazová slova za sebou mohou mít seznam atributových slov. Atributové slovo se
skládá z následujících ástí: [14]
1. Zakódovaná délka slova (tak jako v kadém typu slova)
2. Znak „=“ jakoto prefix obsahu
3. Jméno atributu
=address=10.0.0.1
=interface=wlan1
3.2.4. API atributové slovo (tag)
API atributové slovo je strukturou podobné bnému atributovému slovu s rozdílem
ve znaku prefixu obsahu. U API atribut se nejedná o rovnítko, ale o teku. API
atributové slovo tedy vdy zaíná tekou. V souasnosti je jediným API atributem
„tag“, který umouje pi posílání vty routeru tuto vtu oznait etzcem znak.
Tento etzec je poté vrácen v kadé odpovdi, kterou router odesílá na základ
pijaté vty.[14]
V následující ukázce [14] je vypnuto rozhraní „ether1“ pomocí vty s tagem 3.
/interface/set =disabled=yes =.id=ether1 .tag=3
12
!done .tag=3
Toto „tagování“ umouje mít v aplikaci pesný pehled k jakému píkazu patí
obdrená odpov a které ásti aplikace má být pedána ke zpracování.
3.2.5. Filtrovací slovo (query word)
V kombinaci s píkazem „print“ (tedy dotaz na všechny poloky) je moné seznam
výsledk k navrácení filtrovat pomocí tzv. „query slov“. Tato funkce byla pidána ve
verzi 3.21. Filtrovací slovo zaíná otazníkem a jeho pouití má svá jasn daná pravidla.
Poadí takovýchto slov je podstatné, nebo jsou vyhodnocovány postupn. Dotaz jako
celek je vyhodnocen pro kadou poloku, která má být vrácena v odpovdi. Pokud
poloka odpovídá kritériím, je zpracována a vrácena, pokud ne (v zásobníku
pravdivostních hodnot pro výsledky jednotlivých výraz se vyskytuje alespo jedna
nepravda) je ignorována.[14]
Filtrovací výraz (slovo) Popis
?atribut vloí „pravda“ pokud poloka má atribut s daným názvem, jinak „nepravda“
?-atribut vloí „pravda“ pokud poloka nemá atribut s daným názvem, jinak „nepravda“
?=atribut=hodnota ?atribut=hodnota
vloí „pravda“ pokud má poloka daný atribut roven dané hodnot, jinak „nepravda“
?<atribut=hodnota vloí „pravda“ pokud hodnota daného atributu menší ne zadaná hodnota, jinak „nepravda“
?>atribut=hodnota vloí „pravda“ pokud hodnota daného atributu vtší ne zadaná hodnota, jinak „nepravda“
?#operace provádí operace s hodnotami v zásobníku
Tab. 3: Pehled filtrovacích výraz. Zdroj: [14] (upraveno)
S hodnotami v zásobníku lze pracovat pomocí operací, které se adí do etzce
a následn jsou s prefixem „?#“ vloeny do slova a odeslány. Tyto operace jsou
v etzci vyhodnocovány postupn zleva doprava.
13
Pokud se v etzci nachází íslo následované znakem (krom „.“), je hodnota s tímto
zásobníkovým indexem zkopírována a vloena na vrchol zásobníku. Pokud je íslo
následované „.“, je toto íslo ignorováno, nebo „.“ vkládá kopii hodnoty na vrcholu
zásobníku. V pípad, e je íslo na konci etzce, jsou veškeré hodnoty v zásobníku
nahrazeny hodnotou na tomto indexu.[14]
Znak „!“ odstraní vrchní hodnotu ze zásobníku a vloí její negaci. Znaky „&“ a „|“
odeberou dv hodnoty z vrcholu zásobníku a vloí jejich logický souin (AND) resp.
logický souet (OR).[14]
Následující vta vrátí všechna rozhraní, která nejsou typu „wlan“ i „bridge“.
/interface/print ?type=wlan ?#! ?type=bridge ?#! ?#&
Stejného výsledku je mono dosáhnout kompaktnjší vtou:
/interface/print ?type=wlan ?type=bridge ?#|!
Tento zpsob filtrování pro píkaz „print“ nahrazuje konzolový parametr „where“,
který není v API dostupný.
3.2.6. Slovo odpovdi
Odpovdní slova jsou posílána routerem v odpovdi na celé vty poslané klientem.
První slovo v odpovdi vdy zaíná znakem „!“. V pípad, e není spojení ukoneno
generuje kadá odeslaná vta minimáln jednu odpov.[14]
První slovo udává o jaký typ odpovdi se jedná. V tabulce 4 je uveden jejich pehled.
14
!done poslední (ukonovací) odpov na danou vtu
!re odpov obsahující data
!trap odpov pi chybových a výjimených stavech
Tab. 4: Typy odpovdí. Zdroj dat: [14]
V pípad, e pi vyhodnocování pijaté vty nastane chyba, je vrácena chybová
odpov (zaínající slovem „!trap“) jejím obsahem je atribut „message“ (obsahující
zprávu o chyb) a pípadn také atribut „category“ (tedy druh chyby, ke které došlo).
Pehled chybových kategorií je uveden v tabulce 5.
Kód Kategorie
1 chyba hodnoty argumentu
2 provádní píkazu perušeno
4 obecná chyba
5 API chyba
6 TTY chyba
7 hodnota generovaná :return píkazem
Tab. 5: Chybové kategorie.[14]
Pokud je tedy routeru odeslána nap. vta pidávající IP adresu neexistujícímu
rozhraní, router vrací následující chybovou vtu: [14]
!trap =category=1 =message=input does not match any value of interface
3.3. API píkazy
Píkazy pouívané v API úzce korespondují s píkazy dostupnými v konzoli, avšak
mají svá specifika. Tato kapitola se zabývá nejdleitjšími píkazy a jejich pouitím.
15
3.3.1. Píkaz „login“
Pro komunikaci pomocí API je nutné nejdív provést pihlášení. To je iniciováno
klientem pomocí odeslání vty, jejím obsahem je pouze píkazové slovo „/login“, na
které router bn odpovídá „!done“ vtou s atributem „ret“, tedy napíklad: [14]
!done =ret=ebddd18303a54111e2dea05a92ab46b4
Hodnotou atributu „ret“ je etzec hexadecimálních znak. Tento etzec je spolen
s pihlašovacím heslem uivatele „zahashován“ a v následné vt, která obsahuje
i uivatelské jméno, odeslán. Tato vta pak me vypadat následovn: [14]
/login =name=admin =response=001ea726ed53ae38520c8334f82d44c9f2
Oficiální manuálové stránky neobsahují informaci, jakým zpsobem má být heslo
a pijatý etzec zpracován a odeslán, avšak uvedené píklady API klient (nap. v Jav
[20] i C# [21]) sestavují hodnotu atributu „response“ následujícím zpsobem: na
zaátek jsou vloeny dv nuly a zbývající ást je tvoena MD5 hashí uivatelského
hesla a etzce obdreného od routeru v pedchozím kroku. Pesnji je hash tvoena
ze tech ástí v tomto poadí:
1. Nulový znak (tedy ve výsledku nulový byte)
2. Uivatelské heslo
3. etzec atributu „ret“ obdrený od routeru resp. jeho úprava, kde je kadá
dvojice obdrených znak pevedena na jeden byte. Tedy nap. dvojice 4A je
pevedena na byte s hodnotou 74, dvojice 6E na byte s hodnotou 110 atp.
Router si po odeslání odpovdi na první „/login“ píkaz sám vytvoí MD5 hash
z pihlašovacích údaj a odeslaného etzce. Tento etzec porovná s etzcem
pijatým od uivatele a pokud jsou totoné, vrátí jednoslovnou vtu obsahující „!done“.
V pípad e hashe totoné nejsou, router ješt ped dokonovací „!done“ vtou vrátí
vtu chybovou, která obsahuje zprávu, e pihlášení nebylo moné.[22]
Vzhledem k tomu, e heslo není nikdy penášeno v prosté textové podob, zamezuje
tento zpsob pihlašování jeho odposlechnutí bhem penosu.
16
3.3.2. Píkaz „getall“ („print“)
Od RouterOS verze 3.21 je píkaz „getall“ aliasem pro píkaz „print“, jsou tedy
navzájem zamnitelné. Tyto API píkazy vrací seznam poloek v daném kontextu
píkazového stromu a jsou pouitelné všude tam, kde je dostupný konzolový píkaz
„print“. Na rozdíl od konzolové verze píkazu se poloky, které mají být vráceny
nemohou filtrovat pomocí parametru „where“, ale za pomoci filtrovacích (query) slov.
Dalším rozdílem je vracení vnitního identifikátoru poloky seznamu pomocí atributu
„.id“. Tento identifikátor je pouíván pi práci s danou polokou, kterou jednoznan
v zaízení identifikuje. Zárove je v API moné filtrovat, které atributy budou u kadé
poloky vráceny pomocí píkazového atributu „.proplist“, jeho hodnotou je etzec
árkou oddlených jmen atribut, které mají být v odpovdi vráceny. Pouívání tchto
atributových seznam je doporuováno z výkonnostních dvod, protoe není-li tento
píkazový atribut uveden, je pistupováno ke všem atributm dané poloky, a to
i k tm, které mají dlouhou pístupovou dobu (jako napíklad obsahy soubor i
výkonnostní poítadla).[14]
Píkladem pouití píkazu „print“ me být vypsání všech IPv4 adres a hodnot jejich
atribut „.id“ (vnitní identifikátor poloky), „address“ (IPv4 adresa a délka prefixu),
„network“ (adresa sít) a „interface“ (jméno rozhraní, ke kterému je daná IP adresa
piazena) pomocí následující vty:
/ip/adress/print =.proplist=.id,address,network,interface
Odpov routeru se skládá z „!re“ vty pro kadou vrácenou poloku a poslední
ukonovací „!done“ vty:
!re .tag=1 =.id=*1 =address=192.168.2.2/24 =network=192.168.2.0 =interface=bridge1 ...další !re odpovdi pro všechny zbývající IPv4 adresy
!done
17
3.3.3. Píkaz „listen“
„Píkaz „listen“ je dostupný tam, kde je dostupný konzolový píkaz „print“, ale ne všude
má oekávaný efekt (nemusí tedy fungovat). Vta „!re“ je vrácena pokadé, kdy se
v dané poloce nco zmní. Pokud je poloka odstranna nebo zmizí jakýmkoliv jiným
zpsobem, vrácená vta obsahuje hodnotu „.dead=yes“. Tento píkaz se neukonuje
automaticky. K jeho ukonení je vyuíván „/cancel“ píkaz.“[14]
Jedná se tedy o monitorovací píkaz, který vrací odpov pokadé, kdy se v dané
poloce zmní hodnota nkterého z atribut. Pokud je daná poloka odstranna nebo
zmizí (nap. dojde k odpojení bezdrátového klienta), odeslaná odpov obsahuje
atribut „.dead“ s hodnotou „yes“. Toto alespo uvádí manuál, avšak nap. pro IPv4
adresy ve verzi systému 6.23 bylo zjištno, e je pro tento atribut vracena hodnota
„true“. S touto nekonzistencí je nutno pi vývoji poítat a ovovat ob hodnoty.
Na verzi 6.23 bylo také odzkoušeno, e píkaz „/listen“ lze kombinovat s atributem
„.proplist“. Poté jsou v odpovdi vráceny pouze atributy uvedené v tomto seznamu,
mezi kterými musí být i atribut „.dead“ pro pípad odstranní poloky. V dokumentaci
není tato monost uvedena a nelze zaruit její funknost ve všech verzích systému.
3.3.4. Ukonení píkaz („cancel“)
Ukonit zpracovávané píkazy je moné pomocí vty s píkazovým slovem „/cancel“.
Nepovinným píkazovým atributem je v takovéto vt „tag“ s hodnotou tagu píkazu,
jeho zpracovávání má být ukoneno. V pípad, e tento atribut není uveden, jsou
ukoneny všechny práv probíhající píkazy. Ukonení píkazu obvykle znamená
navrácení chybové „!trap“ a dokonovací „!done“ odpovdi.[14]
Pi pouívání ukonovacích píkaz je nutné správn rozlišovat atribut „=tag“ (tag
píkazu k ukonení) a API atribut „.tag“ (tag samotného ukonovacího píkazu).
V následující ukázce je ukonen píkaz s tagem 2, piem ukonovací píkaz jako
takový je odeslán s tagem 4.
/cancel =tag=2 .tag=4
18
4. Vývoj aplikace
V této kapitole bude popsán vývoj samotné aplikace, její struktura a nejdleitjší
souásti. Pi vývoji byl kladen draz na modularitu, tedy odstínní jednotlivých
souástí aplikace podle jejich funkcí tak, aby byla zajištna co moná nejvtší
znovupouitelnost a upravitelnost. Mezi tyto moduly patí nap. komunikaní modul
pro kódování a dekódování komunikace se zaízením, modul pro zpracovávání
pijatých odpovdí (jejich pevod na modelové tídy) a pedání zobrazovacímu
modulu, který zajišuje zobrazení informací uivateli pomocí aktivit, fragment
a pohled (views). Za další (pomocné) moduly lze povaovat modul pro pevod XML
souboru s píkazovým stromem na modelové tídy i modul pro import seznamu
router z .wbx souboru (vytváený aplikací Winbox).
4.1. Komunikaní modul
V prvotních fázích vývoje aplikace byly pro komunikaci s routerem vyuity tídy
zveejnné na stránkách MikroTik dokumentace.[20] Tyto se ovšem ukázaly jako
nevhodné kvli své málo objektov-orientované struktue a celkov neuspoádanému
kódu. Gideon LeGrange zveejnil na serveru github.com svojí implementaci
komunikaních tíd.[23] Zveejnny byly pod licencí Apache 2.0, která umouje
volné pouívání, úpravu a šíení díla (za pedpokladu, e je k dílu piloena kopie této
licence).[24] Tyto tídy poskytují snadno pouitelné metody pro vytvoení spojení
k routeru, pihlášení uivatele a jak synchronní, tak asynchronní vykonávání píkaz.
Proto byly pvodní tídy komunikaního modulu nahrazeny práv tmito od Gideona
LeGrange.
Hlavní tídou zajišující komunikaci se zaízením je ApiConnectionImpl, která je
potomkem abstraktní tídy ApiConnection. Ta pedepisuje metody, které její potomek
implementuje. Mezi n patí i statická metoda connect s parametry: String host (pro
adresu routeru) a celoíselnou hodnotou portu, na kterém má být spojení navázáno.
Tato metoda navrací novou instanci tídy ApiConnection (i nkterého z potomk).
Ve tíd ApiConnectionImpl je v tle této metody volána nad vracenou instancí metoda
19
píkaz, tení obdrených odpovdí a celkovou pipravenost tídy pro komunikaci, jak
se naznaeno v následující ukázce:
private Socket sock = null; private DataOutputStream out = null; private DataInputStream in = null; private boolean connected = false; private BlockingQueue<Command> outQueue; private Writer writer; private Reader reader; private Processor processor; /** * Start the API. Connect to the MikroTik * @author Gideon LeGrange */ private void open(String host, int port, boolean secure) throws
ApiConnectionException { try {
sock = openSSLSocket(ia, port); } else {
} in = new DataInputStream(sock.getInputStream()); out = new DataOutputStream(sock.getOutputStream()); connected = true; outQueue = new LinkedBlockingQueue<Command>(); writer = new Writer(); writer.setDaemon(true); writer.start(); reader = new Reader(); reader.setDaemon(true); reader.start(); processor = new Processor(); processor.setDaemon(true); processor.start();
} catch (UnknownHostException ex) { connected = false; throw new ApiConnectionException(String.format("Unknown host '%s'", host),
ex); } catch (IOException ex) {
%d : %s", host, port, ex.getMessage()), ex); }
}
Vnitní tídy Reader a Processor umoují vícevláknové zpracovávání obdrených
odpovdí resp. jejich pevod na tídy Response a její potomky. Tída Reader zajišuje
pevod pijatých odpovdí na etzce znak za pomocí statické metody decode
20
pomocné tídy Util a tyto poté vkládá do fronty LinkedBlockingQueue, odkud jsou
vyzvedány tídou Processor voláním metody take a zpracovávány do modelových tíd
odpovdí (obsahujících odpovídají obdrené hodnoty).
4.1.2. Odesílání píkaz a píjem odpovdí
Tída ApiConnectionImpl vyuívá znakování (tagging) píkaz pro správné urení,
které ásti aplikace (resp. instanci tídy implementující rozhraní ResultListener) má
být vrácena odpov na daný dotaz. Pro získání korektní hodnoty tagu je pouita
privátní synchronizovaná metoda nextTag, která navrací hodnotu globálního
celoíselného poítadla ve form hexadecimálního etzce.
V pamti je také udrována mapa (pesnji instance tídy ConcurrentHashMap), ve
které jsou klíi etzcové hodnoty tag a hodnotou je reference na rozhraní
ResultListener. Do této mapy je pi odesílání píkazu vloen záznam s daným tagem
a píslušnou instancí tídy implementující dané rozhraní, tak aby po obdrení
odpovdi bylo známo, pro který objekt je urena.
V této implementaci je umonno odesílat píkazy jak synchronn tak asynchronn.
Tedy pozastavit vlákno odesílající píkaz dokud není obdrena celá odpov nebo
pouze píkaz odeslat, vlákno nepozastavovat a urit instanci tídy implementující
rozhraní definující metody, které budou volány pi obdrení odpovdi.
4.1.3. Odesílání píkaz z nevolajícího vlákna
V pvodní implementaci Gideona LeGrange byly píkazy odesílány (resp. byty
zapisovány do odchozího proudu) ve vlákn, které volalo metodu execute. V pípad
této aplikace se jedná o její hlavní vlákno. V situaci, kdy je k dispozici dostaten
rychlé internetové pipojení nepedstavuje tento pístup vtší problém. Pokud je ale
pipojení pomalé, me docházet k zablokování volajícího vlákna (a tedy blokování
uivatelského rozhraní), nebo potvrzení o pijetí paket nejsou pijímána dostaten
rychle.
K odstranní tohoto problému byla do tídy ApiConnectionImpl pidána vnitní tída
Writer, která je potomkem tídy Thread. Ve své metod run se cyklicky snaí získat
píkaz k odeslání z fronty outQueue (do které je objekt píkazu vloen v metod
21
execute) a ten poté za pomoci metody Util.write zapsat do proudu. Tato úprava také
pinesla nutnost zmny propagace výjimek, které nastaly pi odesílání. Místo, aby byly
výjimky vyhazovány pímo metodou execute, je nyní nalezen ResultListener pro
píslušný píkaz a na nm volána metoda error, ve které je pedána odpovídající
výjimka.
4.1.4. TLS pipojení
Tídy od Gideona LeGrange také poskytují metody metody pro pipojení k routeru
pomocí zabezpeeného TLS spojení za vyuití Diffieho-Hellmanovy výmny klí.
Toto spojení se ovšem nedaí vytvoit, nebo MikroTik zaízení spojení uzavírá
v poátení fázi. Podle autora tíd pipojení se jedná o problém nekompatibility
implementace TLS pipojení v Jav a MikroTiku. Jediný pípad, kdy se mu podailo
spojení vytvoit bylo za uití Javy verze 8 a vytvoení spojení bez certifikát za
pomoci DH výmny klí.[23] Aplikace tedy podporuje pouze standardní pipojení
bez vyuití TLS.
4.2. Správce spojení
Všechny ásti aplikace které komunikují s routerem musí mít pístup k instanci tídy
ApiConnection, která pedstavuje spojení se zaízením. Není vhodné, aby kadá ást
aplikace vytváela spojení nové, a je tedy nutné zajistit pedávání jedné instance.
V systému Android probíhá komunikace mezi jednotlivými aktivitami (resp. jejich
spouštní) pomocí Intent objekt, ke kterým lze pipojit objekty pomocí tzv. „extras
Bundle“ – mapování objekt na etzcové klíe.[25] Tyto pipojované objekty ovšem
mohou být pouze nkterého ze základních typ (String, int, long, boolean atp.) nebo
musí implementovat rozhraní Serializable i Parcelable.[26] Tento pístup tedy není
pro tuto situaci pouitelný a byla místo nj zvolena jedna z doporuovaných alternativ
[27], a to konkrétn návrhový vzor singleton.
Tímto návrhovým vzorem je docíleno, e v celé aplikaci existuje pouze jedna instance
dané tídy a odkaz na ní je moné získat pomocí veejné, synchronizované statické
metody, pi jejím prvním volání je tato instance vytvoena za pomoci privátního
konstruktoru. Tento princip znázoruje následující ukázka.
22
private ConnectionManager() { }
instance = new ConnectionManager(); } return instance;
} //další metody tídy ConnectionManager
Tída ConnectionManager si uchovává odkaz na instanci pipojení, který je iniciován
pi volání metody createConnection, otevírající nové spojení. Odkaz na aktivní spojení
je mono získat pomocí volání metody getConnection. Tato metoda oví, zda
uchovávaná reference není prázdná (null) a v pípad, e je, metoda vyhazuje výjimku
ConnectionNulledException, jinak vrací práv instanci spojení.
Tato tída si také udruje referenci na Router, ke kterému bylo jako poslední
vytvoeno pipojení. Této reference je vyuito v poskytované metod reconnect, která
se pokusí o obnovení spojení k tomuto routeru.
4.3. Obnovování spojení
Problémem mobilních zaízení je velká náchylnost ke ztrát internetového pipojení,
a u pi pijmutí hovoru (pokud uivatel vyuívá mobilní datové pipojení), pesunu
do dosahu veejné Wi-Fi sít (pokud má uivatel zapnuto automatické pepínání
z mobilních dat na Wi-Fi v dosahu) i prostém oslabení síly signálu a zmny reimu
sít.
V pípad, e je pipojení (by i na malou chvíli) ztraceno, nelze spojení ádným
zpsobem obnovit. Musí být k routeru vytvoeno spojení nové a znovu provedeno
pihlášení. V následujících podkapitolách jsou uvedena nkterá moná ešení tohoto
problému.
23
4.3.1. Automatická obnova pi chyb odesílání
V pípad, e pi odesílání píkazu dojde k IOException „broken pipe“ (tedy ztrát
spojení), je podle tagu píslušného píkazu nalezen ResponseReceiver, který oekává
jeho odpovdi a je na nm zavolána metoda error, kde je jako argument pedána nová
ApiConnectionException (výjimka znaící chybu spojení). Instancí ResponseReceiver je
zpravidla anonymní vnitní tída v metod nkterého z kontroler. V kontroleru by
pi obdrení této výjimky došlo k zavolaní metody disconnected na píslušné
zobrazovací instanci (tuto metodu by bylo nutno pidat do definice ViewInterface
a následn i implementovat v píslušných tídách). V implementaci této metody by
poté byl spuštn AsyncTask, který by se pokusil o vytvoení nového pipojení.
V pípad úspchu by byl vytvoen nový kontroler, který by u disponoval aktivním
spojením, se kterým by mohl pracovat.
Problémem tohoto pístupu je pípad, kdy pi pokusu o obnovu spojení stále ješt
není internetové pipojení dostupné a tento pokus sele. ešením by mohlo být pokus
nkolikrát s asovým odstupem opakovat, to by ovšem mohlo trvat pomrn dlouho
a pro uivatele být nevhodné. Další nevýhodou by byla pomrn vysoká
implementaní sloitost.
Bylo zvaováno pedchozí ešení rozšíit pop. nahradit pomocí tídy
BroadcastReceiver, která umouje odchytávat zasílané Intent objekty a pracovat
s nimi. V manifestu aplikace je moné registrovat uritý BroadcastReceiver jako
píjemce uritých typ zpráv. V tomto pípad byly odchytávány zprávy o zmn stavu
sít pomocí následující definice v manifestu aplikace: [28]
<application <!-- vynechané elementy --> <receiver
</intent-filter> </receiver> <!-- vynechané elementy --> />
Ve tíd NetworkChangeReceiver (potomek tídy BroadcastReceiver) v balíku .helpers
byla pepsána metoda onReceive a v ní vdy oven stav spojení. Pi testování na
emulovaném zaízení vše probíhalo dle oekávání a zprávy o zmn stavu sít byly
pijímány korektn a tém okamit po té, co ke zmn došlo. Problém nastal pi
testování na fyzickém zaízení Huawei Ascend G300 s Android verze 4.4.4
(CyanogenMod v11), kde byly totoné zprávy o zmn stavu sít zasílány nkolikrát.
Podle diskuze na serveru stackoverflow.com [29] se jedná o problém specifický pro
nkterá zaízení. ešením tohoto neoekávaného chování je udrování poslední
pijaté zmny a její porovnání s práv pijímanou. V pípad, e hodnoty stavu jsou
totoné, jedná se o vícenásobné odeslání a zmna ve stavu sít ve skutenosti
nenastala.
Nejvtším problémem se ale ukázala prodleva mezi zmnou stavu sít a pijetím
zprávy. V nkterých pípadech se jednalo a o desítky sekund. Za tuto dobu se mohl
stav aplikace zmnit a obnovení spojení ji není nutné, i je dokonce neádoucí, nebo
uivatel se k routeru pipojil run. Z tchto dvod bylo toto ešení zamítnuto.
4.3.3. Runí obnova spojení
Jako nejvhodnjší ešení se ukázala runí obnova spojení iniciovaná uivatelem.
V pípad, e dojde ke ztrát spojení pi vykonávání píkazu, je o tom uivatel
informován chybovou zprávou a v menu všech patiných aktivit je mu snadno
dostupná poloka pro znovupipojení, to je vykonáno v pozadí pomocí AsyncTask
a o výsledku je uivatel informován pomocí Toast zprávy. V pípad úspchu je
pípadn vykonána akce pro znovu natení zobrazovaných hodnot. Pokus o obnovu
spojení me krom absence pipojení selhat z dvodu, e proces aplikace byl
ukonen (nebo byl nap. dlouho v pozadí a systém poteboval uvolnit prostedky)
a vytvoen znovu. To znamená, e byla vytvoena i nová instance singleton správce
pipojení a tím ztracen odkaz na Router, ke kterému má být vytvoeno spojení. To lze
vyešit perzistentním ukládáním informací o routeru napíklad ve sdílených
preferencích (SharedPreferences), avšak není to nezbytn nutné, nebo pokud byla
aplikace tak dlouho v pozadí, e její proces byl ukonen, je pravdpodobné, e uivatel
nebude chtít pokraovat tam, kde skonil, kdy z aplikace odcházel a postaí
zobrazení hlavní aktivity se seznamem router.
25
Tento pístup byl nakonec zvolen, jeliko umouje uivateli mít pesn pod
kontrolou vytváení spojení k routeru. Nedochází ke snahám o pipojení na pozadí
a k zbytenému vyuívání prostedk. Zárove pro uivatele není obnova spojení
nijak výrazn obtující.
4.4. XML znázornní píkazového stromu
Na rozdíl od konzole, API neposkytuje píkazovou nápovdu pomocí píkazu „?“, která
by vracela dostupné píkazy v dané úrovni pop. jména atribut dané poloky. Akoliv
na tuto API funkcionalitu byl vznesen poadavek [30], podle reakce zamstnance
podpory MikroTik má tato funkcionalita nízkou prioritu.[31]
Je tedy nutné dopedu znát strukturu píkazového stromu, atributy jednotlivých
poloek a jejich typ (zda se jedná nap. o volný etzec, celoíselnou hodnotu, výbr
z pedem známých hodnot, odkaz na jinou poloku i pravdivostní hodnotu). Pro
úely perzistentního uloení této struktury se nabízely dv monosti: relaní databáze
i znakovací soubor XML. Z dvodu snadnjší itelnosti a upravitelnosti byl zvolen
pístup vyuívající XML, ovšem není vyloueno, e v budoucnu se relaní databáze
ukáe jako vhodnjší díky snadnjší práci s vazbami mezi jednotlivými prvky.
4.4.1. Elementy <branch> a <tabsBranch>
Tyto elementy znázorují vtv píkazového stromu a umoují navigaci v menu. Mají
dva atributy a to sice name (zobrazované, uivatelsky pívtivé jméno) a command
(jak bude daná vtev reprezentována v samotném píkazu). Hodnota atributu
command je zpravidla uvozena lomítkem nebo konený píkaz (resp. jeho ást
znaící kontext, tedy v jaké vtvi má být vykonán) je skládán prostým spojením
hodnot command všech rodiovských element.
Rozdíl mezi tmito elementy spoívá ve zpsobu jejich zobrazování. Zatímco
u <branch> mohou být potomky elementy <list> i <scan> (v libovolném potu
a kombinaci), kde kadý z nich je zobrazován jako samostatná poloka menu, tak
v pípad elementu <tabsBranch> mohou být potomky pouze elementy <list>, které
ovšem nejsou zobrazovány jako poloky menu, ale jako jednotlivé záloky (tabs)
26
v zobrazovacím okn (aktivit). Tento zpsob se snaí co nejvrnji imitovat
uivatelské rozhraní aplikace Winbox tak, jak na nj jsou uivatelé zvyklí.
4.4.2. Element <list>
Tento element reprezentuje úrove stromu, ve které je dostupný píkaz „print“. Jedná
se tedy o seznam poloek, nad kterými je mono volat další píkazy. Stejn jako
elementy <branch> a <tabsBranch> disponuje atributy name a command. K nim ješt
pibyly pravdivostní argumenty reprezentující dostupné píkazy nad jednotlivými
polokami. Jsou jimi:
• addable – zda má uivatel monost pidat novou poloku
• commentable – zda jsou u poloek evidovány komentáe a lze je upravovat
• disablable – zda je moné poloku aktivovat/deaktivovat ani by musela být
pidána/odebrána
V tomto elementu mohou být potomky elementy <property> (reprezentace atributu
pro poloku daného typu), <propertyTab> (reprezentace záloky atribut) i <scan>
(reprezentace dostupnosti píkazu skenovacího typu).
4.4.3. Element <propertyTab>
V pípad, e poloka daného kontextu má mnoho atribut, je pro pehlednost
vhodné tyto rozdlit do záloek (tab). Je tomu stejn i u desktopové aplikace Winbox.
K tomu slouí tento element a jeho atribut name, jeho hodnota je poté piazena
objektu Property (resp. jeho poli propertyTabName) a identifikuje, ke které záloce má
být daný atribut piazen, musí být tedy v daném kontextu jedinená. V pípad, e je
element <property> pímým potomkem elementu <list>, je tato hodnota pi parsování
nastavena na atribut name nadazeného listu. Potomky tohoto elementu mohou být
pouze elementy <property>.
4.4.4. Element <property>
Tento element reprezentuje atribut poloky daného kontextu. Nap. v kontextu
/ip/address to jsou mj. address, interface, netmask, network. Opt disponuje atributy
name a command (který v tomto pípad reprezentuje jméno daného atributu tak, jak
27
ho oekává a odesílá MikroTik zaízení). Dalším atributem je type, pro oznaení typu
atributu, jeho pípustné hodnoty jsou uvedeny v tabulce 6.
Hodnota Význam
hodnoty získané z aktuální konfigurace zaízení (tedy nap.
jména rozhraní pro atribut interface u IP adresy)
listStatic výbr jedné hodnoty ze statického seznamu pedem známých
hodnot
hodnoty pedem známy a uivatel vybere, které z nich mají
být souástí výsledného etzce
etzcových hodnot
celoíselných hodnot
ze statického, pedem známého seznamu
Tab. 6: Pehled typ atribut a jejich význam
Pro všechny typy krom string, multipleString, int, multipleInt a bool je také nutný
atribut listItems, který definuje z jakých poloek lze vybírat. Pro typy s dynamickým
seznamem (tedy u kterých, je poteba nejdíve zjistit aktuální hodnoty konfigurace) je
hodnota ve formátu: [statickáPoloka1,statickáPoloka2,...]kontext.jmenoAtributu
(nap.: „all,none,/interface/wireless.name“ pro seznam jmen všech bezdrátových
rozhraní a statické monosti „all“ a „none“). V ostatních pípadech se jedná o etzec
árkami oddlených hodnot.
Dalšími atributy elementu <property> jsou pravdivostní atributy showInTable (ten
uruje, zda má být hodnota zobrazena v pehledové tabulce všech poloek daného
kontextu), showInDetail (urující, zda má být v detailu poloky zobrazeno pole
s hodnotou daného atributu) a editable (zda má být hodnota tohoto atributu
uivatelem upravitelná).
V pípad typ string a multipleString lze také nadefinovat atributy regex
a validationError pro informování uivatele o chybn zadané hodnot. Regex vyjaduje
regulární výraz odpovídající validní hodnot a validationError chybu, která má být
uivateli zobrazena v pípad, e zadaná hodnota neodpovídá danému regulárnímu
výrazu. Vzhledem k astému opakování stejných validaních kritérií (nap. IP i MAC
adresa) byl pro zmenšení objemu dat i celkové zjednodušení a zpehlednní XML
souboru zaveden element <validationPair>, který zastešuje validaní kritéria a na
který se lze odkazovat pomocí hodnoty atributu id. Není tedy nutné pokadé opakovat
(v nkterých pípadech znan dlouhý) regulární výraz. Píklad uití tohoto elementu
je uveden v následující ukázce:
<root> <validationPairs>
<validationPair id="time" regex="^((\d+)(w|h|m|s))+$|^((\d+:){2}\d+)$" validationError="expected e.g.: 1w2d3h4s or 1:20:30"/>
</validationPairs> <!-- vynechané elementy -->
</root>
4.4.5. Element <scan>
Element <scan> reprezentuje píkaz skenovacího typu. Tedy takový, ve kterém je
odeslán píkaz a router vrací odpovdi dokud není jeho vykonávání klientskou
aplikací (uivatelem) ukoneno pop. dokud nevyprší poítadlo. Píkladem me být
píkaz ping i frekvenní skenování u bezdrátových rozhraní.
Tento element me být umístn buto do elementu <branch> (v takovém pípad
bude zobrazen jako poloka menu a není svázán s ádnou existující polokou
konfigurace) nebo do elementu <list> (pokud je píkaz svázán s nkterou z poloek
29
daného kontextu). V pípad, e je píkaz potomkem elementu <list>, je nutné
specifikovat jméno atributu poloky, podle kterého je identifikována konkrétní
poloka, nad kterou je píkaz vyvolán (zpravidla je to vnitní identifikátor „.id“). Tato
specifikace je provedena pomocí XML atributu itemIdPropertyName.
Dalším XML atributem je pravdivostní addOnly, který uruje, zda se vracené poloky
pouze pidávají (jako je tomu u píkazu ping) nebo zda me být navrácena poloka,
odpovídající nkteré díve pijaté s novými hodnotami, které mají nahradit ty staré
(nap. skenování bezdrátových sítí). Vzhledem k tomu, e u takto vracených poloek
není pidáván jednoznaný identifikátor (jako „.id“ u poloek konfigurace) je nutné
specifikovat XML atribut returnItemIdPropertyName, oznaující, který navracený
atribut má být jako takovýto identifikátor pouit.
Potomky tohoto elementu mohou být elementy <property> (pro reprezentaci
vstupních parametr daného píkazu) a <returnProperty> (tedy navracený atribut),
u kterého není nutné sledovat typ, nebo uivatel toto pole nemá monost mnit
a jedná se vdy o etzec znak. Proto má pouze dva XML atributy, a to sice name
a command se stejným významem jako element <property>.
4.5. Model píkazového stromu
Elementy XML jsou pomocnou tídou XMLParser parsovány (pevádny) na instance
modelových tíd. Struktura, hierarchie a vazby tchto tíd jsou znázornny na obr. 3,
který obsahuje zjednodušený diagram, ve kterém byly pro pehlednost vynechány get
a set metody.
4.5.1. Tídy píkazového stromu
Tída Branch pedstavuje pedka pro jednotlivé typy píkazových vtví, kterým
poskytuje pole name a command (vetn jejich veejných get a set metod).
Tída MenuBranch znázoruje naviganí vtev, tedy takovou, která pouze tvoí
strukturu píkazového stromu. Tato tída si udruje seznam dceiných vtví a také
odkaz na vtev, která je jí nadazená. Této tíd odpovídá XML element <branch>.
Dceiná tída TabsBranch odpovídá svému XML protjšku, tedy elementu
<tabsBranch>. Jedná se o tídu zastešující seznam ListBranch tíd (tedy tíd
pedstavujících vtve, ve kterých je dostupný píkaz print), kde pro kadou z nich má
být vytvoena záloka (tab) s tabulkou.
31
Tída ListBranch si uchovává mj. seznam atribut (tíd Property), které jsou dostupné
pro poloky daného kontextu. Zárove disponuje seznamem názv tab, do kterých
mají být pi zobrazení detailu rozazena pole s hodnotami jednotlivých atribut.
Dalším atributem je seznam vtví s píkazy skenovacího typu, které jsou nad
polokami dostupné.
identifikují poloku, nad kterou je píkaz vykonán a navrácenou poloku. Posledním
atributem je boolean addOnly, který znaí, zda mají být pijaté poloky pouze
pidávány i pípadn i upravovány jejich díve pijaté hodnoty.
Tída Property pedstavuje atribut poloky daného kontextu. Mezi její atributy patí:
• String name – uivatelsky pívtivé jméno atributu
• String command – píkazové jméno atributu, tedy takové, se kterým pracuje
MikroTik zaízení
zobrazena v pehledové tabulce resp. detailu dané poloky
• boolean editable – zda má být daný atribut uivatelem upravitelný
• String propertyTabName – jméno záloky detailu, do které má být tento atribut
zaazen
• String listItems – etzec vyjadující moné hodnoty v pípad výbrového
typu, jeho formát je piblíen ve výše zmínné kapitole 4.4.4 Element
<property>
a pípadná chybová zpráva pro uivatele
4.5.2. Rozhraní Parcelable
Vtšina z tchto tíd musí být pedávána mezi aktivitami i ukládána pi jejich
ukonování (pro pípad nutnosti jejich obnovení). K tomu je vyuíván objekt Bundle
a jeho mapování objekt pomocí etzcových klí. Tyto objekty ovšem musí být
32
primitivního typu nebo musí implementovat rozhraní Serializable i Parcelable. Tyto
rozhraní ve výsledku umoují „zploštní“ objektu (tedy jeho pevod na proud byt)
a následné vytvoení kopie na základ jeho zploštlé formy. Rozhraní Parcelable je
souástí Android API a oproti Serializable nevyuívá reflexi pro správné zploštní a je
tedy mén výkonnostn nároné. Jeho nevýhodou je nutnost implementovat metodu
writeToParcel (která objekt pevádí na instanci tídy Parcel, do které jsou vkládány
hodnoty jednotlivých atribut tídy) a konstruktor s jediným parametrem typu Parcel,
který zajišuje vytvoení instance na základ hodnot v nm obsaených.[32]
Ob rozhraní vyadují, aby všechny atributy dané tídy byly opt primitivního typu, i
typu, který implementuje dané rozhraní. Jednotlivé tídy jsou zpracovávány postupn,
nezávisle na sob. V pípad, e jednotlivé tídy na sebe udrují kruhové reference,
nelze tento pístup pouít, nebo dojde k zacyklení volání metod. Mj. z tohoto dvodu
tídy MenuBranch a Branch ádné z tchto rozhraní neimplementují.
Pi výbru mezi Parcelable a Serializable byla dána pednost výkonnosti na úkor
znovupouitelnosti. V pípad, e by tyto modelové tídy mly být pouity v jiné
aplikaci, která by nebyla urena pro platformu Android, odstranit z tchto tíd
implementaci rozhraní pop. jí nahradit jinou nepedstavuje významnou zát.
4.6. Tídy kontroler a zobrazovací rozhraní
Pro odstínní zobrazovací vrstvy od vrstvy komunikaní byla zavedena mezivrstva
„kontroler“, tedy tíd, které poskytují metody pro odesílání píkaz routeru
a zpracovávají pijaté odpovdi na modelové tídy. Tato architektura ve spojení
s vyuitím rozhraní zvyšuje pehlednost kódu, odstínní tíd a umouje snadnjší
úpravu i nahrazení tíd zajišujících tvorbu uivatelského rozhraní. Další výhodou je
monost znovupouití tchto tíd i v jiné aplikaci a na jiné platform s pouhou
úpravou tíd implementujících zobrazovací rozhraní. Diagram na obr. 4 znázoruje
strukturu a metody rozhraní zobrazovací vrstvy a tíd kontroler.
33
Tídy kontroler a zobrazovací rozhraní si navzájem odpovídají. Tídy kontroler si
udrují referenci na tídu implementující píslušné zobrazovací rozhraní. Jejich
metody nemají návratovou hodnotu, protoe jsou vykonávány asynchronn, resp. na
základ volání metody kontroleru je routeru odeslán píkaz, po jeho vykonání je
volána píslušná metoda zobrazovacího rozhraní.
34
Obr. 4: Diagram rozhraní zobrazovací vrstvy a tíd kontroler
Akoliv komunikaní modul poskytuje monost odesílání píkaz synchronn, obecn
není vhodné (a v Android verze Honeycomb a vyšší dokonce dovolené [33]), aby
aplikace vytváela i pracovala (ekala na odpov) se síovými spojeními ve svém
hlavním (UI) vlákn, nebo tyto operace mohou být asov nároné a tedy zpsobit
„zamrznutí“ uivatelského rozhraní (Android po 5 vteinách, kdy aplikace neodpovídá
zobrazuje „Application not responding“ – ANR dialog, ve kterém nabízí uivateli její
ukonení [34]). Z tohoto dvodu není vyuíváno synchronních dotaz, nebo ty by
stejn musely být volány z nových vláken pop. pomocných AsyncTask tíd.
Tídy kontroler získávají v konstruktoru pístup k instanci pipojení pomocí
singleton tídy ConnectionManager a její metody getConnection. V této fázi u musí být
spojení vytvoeno, nebo kontroler není asociován s tídou Router a nemá tedy
pehled, nad jakým routerem jsou píkazy vykonávány. Dále je v konstruktoru vdy
pedávána instance implementující píslušné zobrazovací rozhraní (nad kterou budou
volány metody pro zobrazování výsledku), odpovídající typ píkazové vtve a pop.
hodnota identifikátoru poloky.
4.6.1. Tída ListController
instance implementující zobrazovací rozhraní, nad kterou budou volány píslušné
zobrazovací metody) a ListBranch (tedy píkazovou vtví, nad kterou mají být
vykonávány API píkazy). Ve svém konstruktoru si tída pipraví na základ jmen
atribut dané vtve etzec proplist (urující, které atributy mají být vráceny) a také
spojovou mapu propertyCommandToValue (ve které jsou klíi píkazová jména
atribut a všechny hodnoty jsou nastaveny na „null“), její klon je nastaven všem
parsovaným instancím tídy ListItem a následn jsou jednotlivé hodnoty nastaveny
podle pijaté odpovdi.
Tída dále poskytuje metody pro odeslání dotaz spojených s pehledovým
seznamem (tabulkou) poloek. Jsou jimi:
• getAll() – Pro odeslání dotazu na všechny poloky vtve. Obdrené výsledky
jsou pomocí metody parseToListItem pevádny na instance tídy ListItem,
35
které jsou po pijetí dokonovací vty odeslány v seznamu jako argument
metody showTable zobrazovací tíd.
• listen() – Pro odeslání „listen“ píkazu pro sledování zmn v polokách. Pi
kadém pijetí výsledku je opt vyuita metoda parseToListItem a výsledek
pedán jako parametr metody updateRow zobrazovací tíd.
• stopListening() – Pro odeslání píkazu „cancel“ s odpovídajícím tagem, který
ruší sledování zmn.
s daným identifikátorem. Výsledek tohoto píkazu (stejn jako následujících
dvou) není nutné explicitn zobrazovat, nebo tuto zmnu zachytí a zobrazí
píkaz „listen“.
• toggleEnabled(String itemID, boolean enabled) – Pro odeslání píkazu „set“,
který nastavuje hodnotu atributu enabled (tedy zda je poloka aktivní i ne)
u poloky s daným identifikátorem.
4.6.2. Tída AddController
Další kontrolerovou tídou je AddController, která poskytuje metodu pro získání
dostupných hodnot atribut getProperties. Kód této metody je vykonáván v novém
vlákn, nebo dostupné hodnoty jsou pro jednoduchost získ&a