Analýza konfiguračného súboru SER.CFG v /usr/local/etc/..
debug=3
{Touto direktívou môžeme buď povolit alebo potlačiť debugové hlášky. Nastavujeme tu aj tzv. debug level, ktorý je štandardne nastavený na 3, čo by malo podať dostatok informácií keď nastane nejaká chyba. Tu vlastne špecifikujeme koľko informácií sa zapíše do syslogu. Maximálny stupeň verbosity je 9. Akonáhle je ale debug level zvýšený zo štandardných 3 tak sa štart aj celkovo operácie trochu spomalia.}
fork=no
{Direktíva fork povie serveru či má SER bežať na popredí alebo na pozadí ako démon. Ak sa plánuje SER spúštať ako systémová služba je nutné zmeniť hodnotu na „yes“. Momentálne spúšťam SER na popredí kvôli debug hláškam a hlbšej analýze.}
log_stderror=yes
{Ak chceme aby nám SER zostal bežať na popredí musíme zmeniť direktívu na „no“.}
listen=testsip.kis.fri.utc.sk
{Direktíva listen určuje na ktorej IP adrese má server čakať SIP traffic. Server musí fyzicky na tejto adrese počúvať. Ak túto direktívu vynecháme bude sa snažiť počúvať na všetkých sieťových rozhraniach. V prípade že tu zadávame IP adresu a nie URL tak môžu nastať v spoločnom použití direktív dns=“no“ a rev_dns=“no“ problémy s vyhodnocovaním R-URI, kde by môže a nastane prípad keď SER pri overovaní či má správu proxovať alebo spracovať ako vlastnú porovná uri sip:smit@testsip.kis.fri.utc.sk a smit@158.193.139.2 a aj keď sú v skutočnosti tieto adresy totožné druhá menovaná by sa pri použití tých to direktív iba preposlala a server by ju nespracoval.}
port=5060
{Táto direktíva slúži na špecifikovanie portu na ktorom bude server počúvať. Default hodnota ak sa direktíva nepoužije je 5060.}
children=4
{Táto direktíva určuje koľko procesov sa má pri štarte serveru vytvoriť. Pre menšie a testovacie systémy sú 4 procesy celkom dostatočné, avšak v produkčnom prostredí je nutné túto hodnotu zvýšiť.}
#dns=no
#rev_dns=no
{Tieto direktívy zabraňujú serveru vo vyhľadávaní jeho adresy v DNS. Týmito príkazmi zabránime chybovým hláškam pri štarte pokiaľ nemáme v DNS záznam.}
fifo="/tmp/ser_fifo"
{Fifo špecifikuje kde sa nachádza SER FIFO. Je to vlastne nejaká obdoba proc filesystému a môže byť použitý na sledovanie aktuálnej činnosti SER serveru. FIFO môže byť použité na vsúvanie (injection) SIP správ priamo SIP proxy externou aplikáciou. Využíva to napr. SERCTL, čo je vlastne program pre správu užívateľov, sledovanie stavu servera alebo napr. reštartovanie CISCO UA telefónov.}
fifo_mode=0777
{Táto direktíva špecifikuje prístupové práva pre súbor ser_fifo v /tmp , nastavovanie je rovnaké ako pri súboroch v UNIX like systémoch, ja osobne odporúčam napr. hodnotu 0666.}
fifo_db_url="mysql://ser:heslo@localhost/ser"
{Táto dorektíva sa taktiež pridáva aby sa potlačili prípadné chybové hlášky pri štarte pri použití podpory MYSQL. Server avšak priamo nevyužíva prístup k fifo_db_url, to využíva iba serctl.}
loadmodule "/usr/local/lib/ser/modules/mysql.so"
loadmodule "/usr/local/lib/ser/modules/sl.so"
loadmodule "/usr/local/lib/ser/modules/tm.so"
loadmodule "/usr/local/lib/ser/modules/rr.so"
loadmodule "/usr/local/lib/ser/modules/maxfwd.so"
loadmodule "/usr/local/lib/ser/modules/usrloc.so"
loadmodule "/usr/local/lib/ser/modules/registrar.so"
loadmodule "/usr/local/lib/ser/modules/auth.so"
loadmodule "/usr/local/lib/ser/modules/auth_db.so"
loadmodule "/usr/local/lib/ser/modules/uri.so"
loadmodule "/usr/local/lib/ser/modules/uri_db.so"
loadmodule "/usr/local/lib/ser/modules/nathelper.so"
loadmodule "/usr/local/lib/ser/modules/textops.so"
loadmodule "/usr/local/lib/ser/modules/acc.so"
loadmodule "/usr/local/lib/ser/modules/msilo.so"
{Tu sa špecifikujú externé moduly, potrebné pre správne fungovanie serveru. SER moduly môžu byť umiestnené kdekoľvek na disku avšak pokiaľ server kompilujeme zo zdrojových kódov tak sú štandardne uložené v /usr/local/lib/ser/modules. Na načítanie modulu je použitá direktíva „loadmodule“.Moduly sú vo formáte .so alias Shared object}
// v tejto časti sa špecifikujú parametre jednotlivých modulov
modparam("auth_db|uri_db|usrloc", "db_url", "mysql://ser:heslo@localhost/ser")
{Modulu auth_db vystavíme parameter db_url ktorý je potrebný na špecifikovanie kde môže SER nájsť MySQL databázu pre autentifikáciu. Taktiež modul uri_db potrebuje prístup k databáze a slúži na rôzne overovanie v rámci autentifikácie, konkrétne pracuje s tabuľkou uri_table ktorá obsahuje zoznam povolených URI pre každého užívateľa. Modul usrloc je zodpovedný za sledovanie umiestnení registrácií SIP klientov. Inými slovami ak sa SIP klient registruje s naším serverom tak SER uloží kontaktnú informáciu inak zvanú aj AOR – Adress of Record do tabuľky. Na túto tabuľku sa potom robí select v prípade že iný SIP klient niekam zavolá. Ak je parameter db_mode nastavený na nulu znamená to že nechceme informácie ukladať perzistentne do databázy ale len do pamäte. Tento príkaz vlastne zaŕňa tri príkazy spojené pomocou „pipe“ ako je známe z linuxu/unixu.}
modparam("auth_db", "calculate_ha1", 1)
{Parameter calculate_ha1 vraví SERu či má použiť zahashované heslá v Mysql tabuľke „subscriber“. V produkčnom systéme by mal byť tento parameter nastavený na nulu aby bolo kryptovanie vypnuté.}
modparam("auth_db", "password_column", "password")
{Modul auth_db má počiatočné defaultné nastavenie pre stĺpec s heslom na „ha1“, avšak schéma ktorú používa SER má heslo v stĺpci „pasword“. Týmto informujeme SER že sa stĺpec zmenil.}
modparam("nathelper", "natping_interval", 30)
{Narozdiel od mediaproxy , rtpproxy nemá vstavanú keep-alive funkciu(pravidelné posielanie paketov klientom ktorí sú za NAT pre zabezpečenie že raz vytvorený dočasný port na NAT serveri zostane otvorený pre SIP správy ako aj RTP stream). Táto funkcia je však zabudovaná do modulu nathelper. Natping_interval je veľmi chúlostivé nastavenie ktoré nariaďuje v akých intervaloch bude SER pingať SIP UA. Väčšina NAT zariadení udržuje spojenie len po dobu minúty alebo dvoch. Tu špecifikujeme interval 30 sekúnd. SER potom klientovi posiela jeden UDP paket o veľkosti 4 bajty každých 30 sekúnd. Toto nastavenie je možné aj pri niektorých typoch klientov, ak by bol prblém v jednosmernom audiu po istom čase tak jedno riešenie je začať používať klientské riešenie keep-alive.}
modparam("nathelper", "ping_nated_only", 1)
{Nathelper môže pingovať všetky UA alebo iba tie ktoré boli označené špeciálnym flagom (značkou). Týmto zaručíme, že sa budú pingovať iba tí klienti čo sú za NAT a u ostatných predpokladáme, že majú verejné adresy.}
modparam("nathelper", "rtpproxy_sock", "unix:/var/run/rtpproxy.sock")
{SER a rtpproxy komunikujú pomocou štandardého unix socketu, ktorého defaultné umiestnenie je práve tu. V prípade že toto umiestnenie zmeníme tak je potom potrebné pri spúštaní rtpproxy špecifikovať parameter –s unix:socketpath, je tiež možné spustiť rtpproxy s –f parametrom aby sa zabránilo forkovaniu a bolo vidieť čo sa odohráva.}
modparam("usrloc", "db_mode", 2)
{Parameter db_mode zmeníme na 2 aby sa použila databáza MySQL pre ukladanie dát ako kontaktné informácie a autentifikácia.}
modparam("registrar", "nat_flag", 6)
{Keď sa SIP klient pokúsi registrovať na našom serveri, tak potrebujeme modulu Registrar povedať že má zaznamenať NAT informácie o UA. Týmto špecifikujeme značku 6, ktorá sa začala používať štandardne ako nat_flag, avšak môžeme tu použiť ľubovoľný integer. Keď sa nastaví nat_flag predtým než zavoláme save() funkciu pre uloženie kontaktných informácií, tak SER uloží aj NAT informácie a nastaví aj značky v databáze v stĺpci flags v tabuľke location. Týmto potom môžeme zavolať lookup(„location“) pri spracovaávní správ a flag 6 bude bude nastavený NAT klientom.}
modparam("rr", "enable_full_lr", 1)
{Modul rr volajúci enable_full_lr slúži pre starších SIP klientov ktorí nesprávne spracúvajú record-route hlavičky. SIP RFC 3261 vraví, že špecifikovanie loose smerovania zahrnutím ;lr do record route hlavičky je korektný spôsob ako povedať ostatným SIP proxy že náš server je loose router. Avšak niektorí starší alebo pokazení SIP klienti nesprávne zahadzovali lr tag pretože nemal priradenú hodnotu ako napr. lr=“true“. Preto špecifikovaním parametra enable_full_lr na 1 SER prepíše všetky ;lr na ;lr=on aby sa odstránil tento problém.}
modparam("acc", "log_level", 1)
{Nasledujúce parametre slúžia pre accounting, čo je uchovávanie rôznych informácií o uskutočnených hovoroch (transakcií) prostredníctvom našeho serveru. Pomocou parametra log_level modulu acc špecifikujeme aký objem informácií bude zapisovaný do syslogu.}
modparam("acc", "log_flag", 1)
{Tento parameter určuje hodnotu integera pomocou ktorého potom v routovacích blokoch označíme transakciu (pomocou setflag(1)) ktorú budeme uchovávať (účtovať). Default hodnota je 1.}
modparam("acc", "log_missed_flag", 2)
{Tu nastavíme či budeme logovať transakcie ktoré ktoré budeme považovať za zmeškaný hovor.}
modparam("acc", "db_url", "mysql://ser:heslo@localhost/ser")
{Týmto posunieme modulu acc parameter db_url ako bolo spravené vyššie, pre prístup k MySQL databáze.}
modparam("acc", "db_flag", 11)
{Tento parameter je špecifický pre každú databázu a určuje aká hodnota má byť použitá pre účtovanie transakcie.}
modparam("acc", "db_missed_flag", 12)
{ Tu nastavíme integer pomocou ktorého označíme transakcie ktoré ktoré budeme považovať za zmeškaný hovor.}}
modparam("acc", "failed_transactions", 1)
{Tu nastavujeme či majú byť účtované aj neúspešné transakcie (status>=300). Default hodnota je 0.}
modparam("msilo", "registrar", "sip:registrar@testsip.kis.fri.utc.sk")
modparam("msilo", "db_url", "mysql://ser:heslo@localhost/ser")
{Tento modul slúži na posielanie IM správ klientom a v prípade nedostupnosti ukladaných do databázy. Tieto správy je možné prehliadať pomocou serwebu.}
{Tu začína hlavný routovací blok kde putujú všetky SIP správy.Z hlavného routovacieho bloku môžem zavolať ďalšie routovacie bloky, testovať správy na isté stavy, odmietnuť správy, posunúť správy ďalej, v podstate môžem SER nakonfigurovať nech robí čokoĺvek so SIP správami, preto je tento systém veľmi flexibilný.}
route {
# —————————————————————–
# Sanity Check Section
# —————————————————————–
{Vykonáme nejaké kontroly}
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483", "Too Many Hops");
break;
};
mf_process_maxfwd_header je bezpečnostná kontrola, ktorá by sa mala vždy vykonať ako prvá. Táto funkcia je obsiahnutá v module mf.so a používa sa na sledovanie kolkokrát prešla SIP správa cez SER (koľkokrát bola správa spravovaná). Chybné konfiguračné súbory môžu poslať správu na zlé miesto a spôsobiť zacyklenie. Taktiež to môžu spôsobiť iné SIP proxy s ktorými SER komunikuje. Základné pravidlo pre tento príkaz je, že ak táto funkcia niekedy vráti „TRUE“ tak sa musí skončiť spracovanie problematickej správy aby sa zabránilo zacykleniu.
Ak sa náhodou takáto situácia vyskytne tak SER potrebuje nejakým spôsobom oboznámiť SIP klienta že nastala chyba. Na to slúži práve funkcia sl_send_reply(). sl_send_reply() sa nachádza v module sl.so a všetko čo robí je, že pošle „stateless“ správu SIP klientovi. Výraz break zastaví spracovanie SIP správy v smerovacom bloku ktorý sa práve vykonáva. Keďže vyvolávam break z hlavného smerovacieho bloku SER úplne ukončí spracovanie tejto správy.
if (msg:len > max_len) {
sl_send_reply("513", "Message Overflow");
break;
};
msg:len je funkcia jadra a vracia dĺžku SIP správy v bajtoch.Taktiež toto ako aj mf_process_maxfwd_header() by malo byť volané na začiatku hlavného smerovacieho bloku. Tento výraz jednoducho otestuje dĺžku SIP správy voči maximálnej dĺžke. Ak je správa väčšia, tak sa prestane spracovávať kvôli riziku pretečenia zásobníka.
Pokiaľ správa prešla úvodnými testami označkujem danú transakciu pre uschovanie kvôli accountingu.
setflag(11);
setflag(12); #zmeskane hovory
# —————————————————————–
# Record Route Section
# —————————————————————–
if (method!="REGISTER") {
record_route();
};
Tu sa pozriem, či je daná správa REGISTER správa. Ak to nie je register správa tak vyvolám record-route aby som zabezpečil, že všetky SIP proxy s ktorými komunikujem ma budú informovať o všetkých zmanách danej transakcie. Týmto si môžem byť istý, že náš SER má šancu spracovať naozaj všetky SIP správy danej konverzácie. Kľúčové slovo ‘method’ je poskytnuté jadrom a umožňuje zistiť aký typ správy sa momentálne spracúva.
Funkcia record_route() jednoducho pridá Record-Route pole do hlavičky aktuálnej SIP správy. Vkladané pole bude vložené pred ktorýkoľvek Record-Route hlavičkový záznam ktorý už môže správa obsahovať. Ďalšie SIP servre alebo klienti použijú tento záznam aby vedeli kam majú poslať odpoveď alebo novú správu v danom SIP dialógu.
Keď sa sa rozhodneme že daný hovor musí byť proxovaný cez náš rtp proxy server, musíme zabezpečiť, že sa daný stream ukončí keď sa daný hovor ukončí (BYE) alebo zruší (CANCEL).
if (method=="BYE" || method=="CANCEL") {
unforce_rtp_proxy();
}
# —————————————————————–
# Loose Route Section
# —————————————————————–
loose_route() testuje či sa má s danou správou spraviť relay alebo nie, to znamená že ak sa s danou správou má spraviť loose route tak sa SER pozrie do správy na top Record Route záznam kde nájde adresu kam má správu preposlať. Vo všetkých ser.cfg by sa mala zavolať funkcia loose_route() až po record_route() funkcii.
Ak test na loose route vráti hodnotu „true“ tak musíme preposlať správu bez ďalšieho spracovania. Aby sa tak stalo tak posuniem správu smerovaciemu bloku 1, čo je v tomto prípade default message handler. Keďže sa vyžaduje zrušenie ďalšieho spracovania tak zavolám break čo ukončí hlavný smerovací blok.
if (loose_route()) {
Naše NAT traverzovanie musí spracovať re-INVITE správy špeciálnym spôsobom aby sa zabránilo „umretiu“ RTP media streamom počas re-INVITE požiadavky. Takže tu sa robí špeciálne re-INVITE NAT spracovanie. Funkcia has_totag() vráti true ak má SIP správa políčko „To“ vo svojej hlavičke. Ak má tak táto správa bude tzv. in-dialog.
force_rtp_proxy() má “l” (lookup) parameter. Ak je špecifikovaný tento parameter tak
rtpproxy bude proxovať tento hovor ak už existuje vytvorená relácia. Jediný dôvod prečo sa to robí je, že rtpproxy vlastne nemôže vedieť že toto je re-INVITE a my chceme zabrániť nepotrebnému proxovaniu hovorov, teda hovorom ktoré to nepotrebujú. Všetky re-INVITE správy budú volať funciu force_rtp_proxy(“l”), ale iba už existujúce proxované relácie budú „re – proxované“.
Nemôžeme vložiť volanie force_rtp_proxy() dovnútra testu nat_uac_test , pretože to zabráni proxovanie ak je re-INVITE zaslaný od UA ktorý nie je NATovaný UA ktorý je za NAT (pretože nat_uac_test() bude false).
Ďalšie veci ktoré sa tu robia: Ak je zistený NAT u UA ktorý poslal INVITE, nastaví sa NAT flag takže vieme že je to NATovaný hovor – (setflag(6)), pridá sa prijatý port navrch „via“ hlavičky (force_rport), a tiež sa prepíše Contact hlavička s verejnou IP adresou klienta (fix_nated_contact).
if (has_totag() && (method=="INVITE" || method=="ACK")) {
if (nat_uac_test("19")) {
setflag(6);
force_rport();
fix_nated_contact();
};
force_rtp_proxy("l");
};
route(1);
break;
};
# —————————————————————–
# Call Type Processing Section
# —————————————————————–
Teraz sme sa dostali do časti konfigurácie kde sa spracovávajú tzv. out-of dialogue
správy. Inými slovami spracúvame buď správy ktoré žačínajú nový dialóg alebo spracúvame SIP správy ktoré nie sú určené pre náš sip proxy (ale my tú správu preposielame čiže proxujeme). Kľúčové slovo ‘uri’ je definované v jadre SERu a je to synomymum k request URI alebo R-URI. Slovo ‘myself’ je tiež definované v jadre a je synonumom pre samotný SIP proxy.
Takže testujeme či je R-URI taká istá ako našeho SIP proxy. Inak povedané ak je tento výraz pravdivý tak sa táto správa nepošle našemu proxy ale niekam inam napr. nejakému SIP telefónu.
V prípade že táto správa už nebude ďalej spracúvaná naším serverom zavoláme smerovací blok pre spracovanie NAT aby sa spustilo rtpproxy predtým než pošleme správu ďalej.
if (uri!=myself) {
route(4);
route(1);
break;
};
Teraz sa explicitne spracujú CANCEL správy. CANCEL správy môžu byť bezpečne spracovanéjednoduchým zavolaním t_relay() pretože SER dokáže automaticky zistiť ku ktorému INVITE tento CANCEL patrí. Čiže tu správu len posuniem do default message handler a ďalšie typy správ tiež svojím špecifickým smerovacím blokom.
if (method=="CANCEL") {
route(1);
break;
} else if (method=="INVITE") {
route(3);
break;
} else if (method=="REGISTER") {
route(2);
break;
};
Lookup(“aliases”) sa pokúša získať aliasy pre Requested URI. Alias je iba iná cesta ako sa odkázať na SIP zariadenie.Funkcia lookup(“aliases”) je vyžadovaná utilitou serctl pre jej správne fungovanie.
lookup("aliases");
if (uri!=myself) {
route(4);
route(1);
break;
};
Lookup(“location”) sa pokúša získať AOR pre Requested URI. Inými slovami, snaží sa zistiť kde sa fyzicky nachádza osoba ktorej voláte. Toto vykonáva prehľadávaním lokačnej tabuľky ktorú napĺňame a updatujeme pomocou funkcie save(). Ak sa nejaké AOR nájde môžeme dokončiť náš hovor, v inom prípade musí SER vrátiť správu s chybou.
if (!lookup("location")) {
sl_send_reply("404", "User Not Found");
break;
};
Ak nie je práve spracúvaná správa typu REGISTER, tak ju iba perpošleme na adresu určenia pomocou default message handler.
route(1);
}
route[1] {
Route[1] je default message handler, a používa sa na preposielanie (relay) správ.
# —————————————————————–
# Default Message Handler
# —————————————————————–
Keď sa jedná o NATovaných klientov musíme korektne spracovať odpovede ktoré sú určené späť klientovi. Tieto odpovede sú dostupné v konfigurácii SERu použitím tzv. reply_route blok. Ser dovoľuje špecifikovať viecero takýchto reply_route blokov, ktoré dokážu spracovať rôzne typy úloh. Tu špecifikujeme že každá reply správa musí prejsť reply_route["1"] blokom, ktorý je definovaný na konci konfiguračného súboru. Aby sa reply_route mohla vyvolať musí sa zavolať prioritne pred t_relay() funkciou.
t_on_reply("1");
t_relay() je funkcia obsiahnutá v module tm.so a je pravdepodobne jedna z najdôležitejších funkcií v konfiguračnom súbore. t_relay() je zodpovedná za poslanie správy k jej príjemcovi a sleduje výskyt hocijakých re-sendov alebo odpovedí. Ak správa nemôže byť poslaná úspešne, potom t_relat() vráti chybovú správu ako vidieť nižšie.
Ak sa niečo „pokazí“ a my sme zavolali force_rtp_proxy (tak, že rtpproxy vytvoril nový proxovaný hovorl), potrebujeme povedať rtp rtpproxy aby ho zrušil použitím unforce_rtp_proxy().
if (!t_relay()) {
if (method=="INVITE" && isflagset(6)) {
unforce_rtp_proxy();
};
sl_reply_error();
};
}
route[2] {
Route[2] spracúva registračné správy. Tu uchovávame dáta o užívateľoch.
# —————————————————————–
# REGISTER Message Handler
# —————————————————————-
Ak sa SIP klient pokúsi registrovať s naším SIP proxy, potrebujeme spôsob ako oznámiť modulu registrar aby uchval NAT informácie o danom UA. Robí sa to použitím flagu 6, ktorý bol náhodne zvolený. Mohol sa použiť aj iný integer ale 6 sa zdá byť všeobecne akceptovaný štandard pre nat_flag. Ak sa nat_flag nastaví predtým než sa zavolá funkcia save() na uloženie kontaktných informácií potom SER taktiež uchová NAT informácie a tiež nastaví stĺpec ‘flags’ v MySQL lokačnej tabuľke. Týmto môžeme neskôr zavolať funkciu lookup(‘location’) keď spracúvam správy a flag 6 bude nastavený na NATovaných klientov.
Aby sa dalo určiť či je SIP klient NATovaný použijeme funkciu nathelperu nat_uac_test(), ktorá berie ako parameter integer. Tento parameter špecifikuje ktorá časť SIP správy sa má preskúmať aby sa určilo či je klient za NAT. Číslo 19 udáva množinu testov a sú to doporučené testy.
POZNÁMKA: Toto sú testy ktoré sa môžu použiť testy použitím nat_uac_test :
1. (16) Je prijatý port (zdrojový port paketu) rozdielny od od portu špecifikovanom na vrchu Via hlavičky ? (Toto sa môže použiť na detekovanie niektorých chybných STUN implementácií).
2. (2) Je prijatá IP adresa (zdrojová IP paketu) rozdielna od IP adresy na vrchu Via hlavičky ?
3. (1) Má pole Contact v hlavičke adresu podľa špecifikácie RFC1918? RFC1918
adresy sú 10.0.0.0/24, 172.16.0.0.0/20, and 192.168.0.0/16.
4. (8) Obsahuje SDP v rámci INVITE alebo OK správy RFC1918 adresu ?
5. (4) Obsahuje najvrchnejší záznam Via adresu podľa RFC1918?
The numbers in paranthesis indicate the number to be used to invoke the test in
nat_uac_test(). Aby sa sputili viaceré testy spočítajú sa dané čísla testov napr. ak v konfiguračnom súbore volám nat_uac_test(“19”) znamená to test #1
(16) + test #2 (2) + test #3 (1) = 19.
if (!search("^Contact:[ ]*\*") && nat_uac_test("19")) {
setflag(6);
fix_nated_register();
force_rport();
};
Keď prijmeme správu REGISTER okamžite sa späť klientovi pošle správa “100 Trying” aby zastavil znovu-posielanie REGISTER správ. Pretože SER je postavený na UDP nie je žiadna garancia, že sa daná správa doručí a preto ak sa nepošle dostatočne rýchlo odpoveď tak UA správu pošle znova.
Odpoveďou ‘100 Trying’ povieme SIP klientovi že spracúvame jeho požiadavku.
Funkcia www_authorize() sa používa na porovnanie užívateľove osobné informácie s tými uloženými v MySQL subscriber tabuľke. Ak sú poskytnuté informácie správne tak táto funkcia vráti true. Ak s REGISTER správou neboli dodané osobné informácie , funkcia vráti false. Prvý parameter špecifikuje doménu v ktorej má užívateľa autentifikovať. My doménu nepoužívame preto je ako parameter prázdny reťazec. Druhý parameter vraví SERu ktorú tabuľku má použiť pre nájdenie používateľove osobné údaje.
Konkrétne tu pošleme späť správu “401 Unauthorized” ktorá povie klientovi aby preposlal požiadavku so zahašovanými osobnými údajmi.
www_challenge() prijíma 2 argumenty. Prvý je doména, kde po zadaní sa pre preposlaní správy objaví, že má poslať informácie pre túto doménu. Druhá hodnota ovplyvňuje zahrnutie qop parametra vo výzve. Je doporučené aby táto hodnota bola 1. Kompletný popis sa dá nájsť v RFC2617. Niektoré IP telefóny nepodporujú qop autentifikáciu.
Funkcia check_to() zabezpečí, že validné používateľské účty nemôžu byť použité neautorizovanými používeteľmi.Nechceme riskovať posielanie osobných informácií ďalším serverom tak odstránime všetky WWW-Authorize alebo Proxy-Authorize hlavičky predtým než správu prepošleme.
Ak sa vykonávanie ser.cfg dostane až sem, tak náš SIP používateľ bol úspešne overený s našou MySQL subscriber tabuľkou, takže použijeme funkciu save(“location”) na pridanie používateľov kontaktný záznam do MySQL lokačnej tabuľky.
sl_send_reply("100", "Trying");
if (!www_authorize("","subscriber")) {
www_challenge("","0");
break;
};
if (!check_to()) {
sl_send_reply("401", "Unauthorized");
break;
};
consume_credentials();
Funkcia save() je zodpovedná za uchovanie informácií o SIP klientovi do lokačnej tebuľky.
if (!save("location")) {
sl_reply_error();
};
m_dump();
}
route[3] {
Route[3] spracováva INVITE správy
# —————————————————————–
# INVITE Message Handler
# —————————————————————–
We use proxy_authorize() to make sure we are not an open relay. Proxy_authorize() will
require INVITE messages to have digest credentials included in the request. If they are
included the function will try to validate them against the subscriber table to make sure
the caller is valid.
Like www_authorize(), proxy_authorize() also takes two arguments. The first is a realm
and the second is the MySQL table in which to look for credentials. In our example this is
the MySQL subscriber table.
.
if (!proxy_authorize("","subscriber")) {
proxy_challenge("","0");
break;
} else if (!check_from()) {
sl_send_reply("403", "Use From=ID");
break;
};
We do not want to risk sending digest credentials to upstream or downstream servers, so
we remove any WWW-Authorize or Proxy-Authorize headers before relaying further
messages.
consume_credentials();
We test to see if the user client is behind NAT, if so, we set the NAT flag (6). This flag is
used further below.
if (nat_uac_test("19")) {
setflag(6);
}
Look up any associated aliases with the dialed number. If there is an aliases and it is not a
locally served domain then just relay the message.
lookup("aliases");
if (uri!=myself) {
route(4);
route(1);
break;
};
Now that all request URI transformations have been done, we can attempt to look for the
correct contact record in the MySQL location table. If an AOR (aka, address of record)
cannot be found then we reply with a 404 error.
if (!lookup("location")) {
sl_send_reply("404", "User Not Found");
break;
};
route(4);
route(1);
}
route[4] {
Route[4] is a convenience route to enable rtpproxy.
If a client is NATed, we must do the following things: Add the received (public) port to the
top-most Via header (force_rport), rewrite the Contact header with the public IP address
and port of the NAT in front of the user client (fix_nated_contact), and set up the
proxying using force_rtp_proxy(). Nathelper will then communicate to rtpproxy, which
will allocate RTP (UDP) ports and the SDP payload of the INVITE will be rewritting (see the
introductory section on NATing for details).
# —————————————————————–
# NAT Traversal Section
# —————————————————————–
if (isflagset(6)) {
force_rport();
fix_nated_contact();
force_rtp_proxy();
};
}
Here we introduce a reply_route. A reply_route is defined just like any other block in ser.
The only difference is that it is called “onreply_route”.
Any message that is passed to this block will be returning to the original sender. You can
think of these messages as the response to the original request that the caller made. The
types of messages that will appear here will have an integer response code, much like
HTTP response codes. Examples here would be 200, 401, 403, and 404.
onreply_route[1] {
We can only call force_rtp_proxy() for SIP messages that have a valid <contact> parameter
in the SDP payload. So here we test to make sure the c= parameter is valid by simply
checking the SDP payload length. We assume that if we have an SDP payload then we will
have a c= parameter and can call force_rtp_proxy ().
if (isflagset(6) && status=~"(180)|(183)|2[0-9][0-9]") {
if (!search("^Content-Length:[ ]*0")) {
force_rtp_proxy();
};
};
Before our reply_route processing is complete we have one more NAT test to try. Here we
make sure the <Contact:> header does not contain an RFC1918 IP address. If it does, then
we replace it with the public IP address and port of the NAT in front of the user client.
if (nat_uac_test("1")) {
fix_nated_contact();
};
}