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
Embed
Univerzita Hradec Králové Fakulta informatiky a ...
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