Sygnalizacyjne ABC

Poniższy artykuł oparty jest na wspaniałej pozycji książkowej “System Sygnalizacji nr 7 G. Danielewicz, W.Kabaciński”. Gorąco zachęcam do lektury!!:)

Sterowanie

W wiekszości przypadków jeżeli coś działa dłużej niż okres potrzebny na zaparzenie herbaty to znaczy, że coś nim steruje. Podobnie jest w telekomunukacji, wszystko co dzieje sie w sieci wynika i jest oparte na przesyłaniu i wymianie informacji sterujących pomiędzu jej elementami. Siec telekomunikacyjna jest przykladem sieci zorientowanej polaczeniowo, tzn takiej w ktorej zanim dojdzie do wymiany danych, zarówno w fazie zestawiania jak i rozlaczania połaczenia, realizowana jest wymiana informacji sterujących. Proces za pomocą, którego przekazywane są informacje sterujące nazywamy sygnalizacja.

W telekomunikacji podstawowym zastosowaniem sygnalizacji jest zestawienie połaczenia pomiedzy dwoma abonentami. Nomenklatura nazywa abonenta inicjującego połacznie jako ‘abonenta wywołującego’ a abonenta do którego kierowanie jest połaczenie abonentem wywoływanym. Podobnie w przypadku central (punktów przyłaczenia do sieci) do których dołaczeni są abonenci, centrala wywołująca i wywoływaną. Nawiązanie połaczenia wymaga sygnalizacji pomiedzy:

  • abonentem wywołującym a cetrala wywołującą
  • abonentem wywoływanym a centralą wywoływaną
  • miedzy centrala wywołujacą i wywoływana bezpośrednio lub poprzez inne centrale

Funkcje i rodzaje sygnalizacji

Funkcje i rodzaje sygnalizacji zmieniały się na przestrzeni czasu wraz z rozwojem i ewolucja technologiczną. Niegdyś abonent chcąc nawiązać połaczenie podnosił sluchawke telefoniczną i krecił metalową korbką. To indukowało prąd, który powodował zapelenie się malej lampki w centrali ‘manualnej’ obsługiwanej przez grupę procesorów płci pięknej. Taka pani podłączała swoją sluchawkaę do drugiego konca przewodu i rozpoczynała “obsługę zgłoszenia w centrali”. Dowiadywała się od delikwenta gdzie chce się dodzwonić, po czym odłaczała swoją słuchawkę i za pomocą krótkiego drutu łaczyła dwa odpowiednie przewody.

Z pośród wielu różnych kryteriów za pomocą, których moglibyśmy sklasyfikować sygnalizacje dwa bezwątpienia najważniejsze to funkcje jakie realizuje w danym kontekscie oraz obszar ich zastosowania.

Funkcje

Sygnalizacja spełni trzy zasadnicze funckje:

  • adresową – jest odpowiedzialna za przekazywanie w sieci informacji adresowych dotyczących abonenta wywoływanego. Informacje adresowe zawierają wskazany przez abonenta wywołujacego identyfikator abonenta wywoływanego. Najcześciej identyfikator ten jest podstawą do kierowania sygnalizacji pomiedzy kolejnymi elementami w sieci.
  • nadzorczą – jest odpowiedzialna za kontrolowanie stanu łacza, wykrywa zmiany i przekazuje informacje z nimi związane
  • zarządzającą – jest odpowiedzialna za przesyłanie informacji służacej do zarządzania łączami

Obszar funkcjonowania

Z zależności od obaszaru funkcjonowania syganlizację dzieli się na:

  • abonencką – obejmuje wymianę informacji sterujących pomiędzy centralą i abonentem
  • międzycentrolową – obejmuje wymianę informacji sterujących pomiędzy centralami biorącymi udział w połaczeniu
  • wewnątrz centralowa – jest to wymiana informacji pomiędzy wewnętrznymi komponentami centrali

Zarówno sygnalizacja abonencka jak i między centralowa są objęte przez procesy standaryzacyjne na poziomie międzynarodowym i krajowym, natomiast sygnalizacja wewnątrz centralowa jest niezależnym rozwiązanie danego producenta.

Typy sygnalizacji

Biorąc pod uwagę inne aspekty sygnalizacji związane z jej własciwościami fizycznymi można dokonać ponownej klasyfikacji za pomocą dwóch kryteriów, rodzaju syganału oraz zależności pomiedzy informacjami sterujacymi a danymi.

Rodzaj sygnału

W zależności od tego kryterium możemy wyróżnić dwa rodzaje sygnałów analogowe i cyfrowe.

Sygnały analogowe do przesyłania informacji wykorzystują sygnał analogowy, który może być prądem stałym lub przemiennym o określonej czestotliowśći lub złożonym z większej liczby sygnałów o danych częstotliwościach. W przypadku sygnalizacji prądem stałym informacja może być przesyłana w postaci obecności lub braku prądu oraz poprzez kierunek jego przepływu. W przypadku sygnalizacji prądem przemiennym informacje mogą być przekazywane za pomocą obecności lub braku sygnału oraz jako jego częstotliwość lub kombinacja zbioru częstotliwości. Jeśli częstotliwość sygnalizacji mieści sie w pasmie sygnału danych to jest to tak zwana sygnalizacja w pasmie jeśli nie to poza pasmem.

W przypadku gdy sygnalizacja przyjmuje postać cyfrową jest ona przesyłana w postaci ciągów bitów. O systemach w których informacje przesyłane są w postaci cyfrowej mówimy systemy transmisji cyfrowej. W takich systemach dane transmitowane są w  określonej szczelinie czasowej, w której w zależności od szybkości łacza umieszczane są paczki bitów. Taka przydzieloną szczelinę nazywamy kanałem. Jeśli w ramach takiej szczeliny określona liczba bitów zarezerwowana jest dla informacji sygnalizacyjnych to mamy do czynienia z sygnalizacją w szczelinie natomiast jesli na potrzebę sygnalizacji rezerowana jest niezależna szczelina to mowimy o sygnalizacji poza szczeliną.

Media

Kluczowym aspektem sygnalizacji jest powiązanie pomiędzy przesyłanymi informacjami sygnalizacyjnymi a mediami czyli danymi.  Przesyłanie informacji sygnalizacyjnych może być skojarzone z łaczem danych lub nie. W zależności od charakterystyki skojarzenia sygnalizację dzielimy na skojarzona z kanałem lub we wspólnym kanale. W sygnalizacji skojarzonej z kanałem dla każdego kanału przydzielane są zasoby transmisyjne do przesyłania informacji sterujących związanych wyłacznie z tym łaczem. W sygnalizacji ze wspólnym kanałem zasoby dla informacji sygnalizacyjnych są współdzielone przez wiele kanałów danych. W przypadku gdy mamy do czynienia z całkowitym oddzieleniem sygnalizacji od danych mowimy, że sieć jest podzialona na dwie niezależne warstwy sterująca i transportu danych.

CD..?

W kolejnych postach dokładniej opisze poszczególne formy sygnalizacji ze względu na obszar funckjonowania.

You May Also Like

GWT Hosted mode on 64bit linux

GWT for linux is build against 32bit architecture. It contains some SWT/GTK 32bit modules. So if you try to run it with 64bit java it failsException in thread "main" java.lang.UnsatisfiedLinkError: /opt/tools/sdk/gwt/gwt-linux-1.5.3/libswt-pi-gtk-3235....

Using WsLite in practice

TL;DR

There is a example working GitHub project which covers unit testing and request/response logging when using WsLite.

Why Groovy WsLite ?

I’m a huge fan of Groovy WsLite project for calling SOAP web services. Yes, in a real world you have to deal with those - big companies have huge amount of “legacy” code and are crazy about homogeneous architecture - only SOAP, Java, Oracle, AIX…

But I also never been comfortable with XFire/CXF approach of web service client code generation. I wrote a bit about other posibilites in this post. With JAXB you can also experience some freaky classloading errors - as Tomek described on his blog. In a large commercial project the “the less code the better” principle is significant. And the code generated from XSD could look kinda ugly - especially more complicated structures like sequences, choices, anys etc.

Using WsLite with native Groovy concepts like XmlSlurper could be a great choice. But since it’s a dynamic approach you have to be really careful - write good unit tests and log requests. Below are my few hints for using WsLite in practice.

Unit testing

Suppose you have some invocation of WsLite SOAPClient (original WsLite example):

def getMothersDay(long _year) {
    def response = client.send(SOAPAction: action) {
       body {
           GetMothersDay('xmlns':'http://www.27seconds.com/Holidays/US/Dates/') {
              year(_year)
           }
       }
    }
    response.GetMothersDayResponse.GetMothersDayResult.text()
}

How can the unit test like? My suggestion is to mock SOAPClient and write a simple helper to test that builded XML is correct. Example using great SpockFramework:

void setup() {
   client = Mock(SOAPClient)
   service.client = client
}

def "should pass year to GetMothersDay and return date"() {
  given:
      def year = 2013
  when:
      def date = service.getMothersDay(year)
  then:
      1 * client.send(_, _) >> { Map params, Closure requestBuilder ->
            Document doc = buildAndParseXml(requestBuilder)
            assertXpathEvaluatesTo("$year", '//ns:GetMothersDay/ns:year', doc)
            return mockResponse(Responses.mothersDay)
      }
      date == "2013-05-12T00:00:00"
}

This uses a real cool feature of Spock - even when you mock the invocation with “any mark” (_), you are able to get actual arguments. So we can build XML that would be passed to SOAPClient's send method and check that specific XPaths are correct:

void setup() {
    engine = XMLUnit.newXpathEngine()
    engine.setNamespaceContext(new SimpleNamespaceContext(namespaces()))
}

protected Document buildAndParseXml(Closure xmlBuilder) {
    def writer = new StringWriter()
    def builder = new MarkupBuilder(writer)
    builder.xml(xmlBuilder)
    return XMLUnit.buildControlDocument(writer.toString())
}

protected void assertXpathEvaluatesTo(String expectedValue,
                                      String xpathExpression, Document doc) throws XpathException {
    Assert.assertEquals(expectedValue,
            engine.evaluate(xpathExpression, doc))
}

protected Map namespaces() {
    return [ns: 'http://www.27seconds.com/Holidays/US/Dates/']
}

The XMLUnit library is used just for XpathEngine, but it is much more powerful for comparing XML documents. The NamespaceContext is needed to use correct prefixes (e.g. ns:GetMothersDay) in your Xpath expressions.

Finally - the mock returns SOAPResponse instance filled with envelope parsed from some constant XML:

protected SOAPResponse mockResponse(String resp) {
    def envelope = new XmlSlurper().parseText(resp)
    new SOAPResponse(envelope: envelope)
}

Request and response logging

The WsLite itself doesn’t use any logging framework. We usually handle it by adding own sendWithLogging method:

private SOAPResponse sendWithLogging(String action, Closure cl) {
    SOAPResponse response = client.send(SOAPAction: action, cl)
    log(response?.httpRequest, response?.httpResponse)
    return response
}

private void log(HTTPRequest request, HTTPResponse response) {
    log.debug("HTTPRequest $request with content:\n${request?.contentAsString}")
    log.debug("HTTPResponse $response with content:\n${response?.contentAsString}")
}

This logs the actual request and response send through SOAPClient. But it logs only when invocation is successful and errors are much more interesting… So here goes withExceptionHandler method:

private SOAPResponse withExceptionHandler(Closure cl) {
    try {
        cl.call()
    } catch (SOAPFaultException soapEx) {
        log(soapEx.httpRequest, soapEx.httpResponse)
        def message = soapEx.hasFault() ? soapEx.fault.text() : soapEx.message
        throw new InfrastructureException(message)
    } catch (HTTPClientException httpEx) {
        log(httpEx.request, httpEx.response)
        throw new InfrastructureException(httpEx.message)
    }
}
def send(String action, Closure cl) {
    withExceptionHandler {
        sendWithLogging(action, cl)
    }
}

XmlSlurper gotchas

Working with XML document with XmlSlurper is generally great fun, but is some cases could introduce some problems. A trivial example is parsing an id with a number to Long value:

def id = Long.valueOf(edit.'@id' as String)

The Attribute class (which edit.'@id' evaluates to) can be converted to String using as operator, but converting to Long requires using valueOf.

The second example is a bit more complicated. Consider following XML fragment:

<edit id="3">
   <params>
      <param value="label1" name="label"/>
      <param value="2" name="param2"/>
   </params>
   <value>123</value>
</edit>
<edit id="6">
   <params>
      <param value="label2" name="label"/>
      <param value="2" name="param2"/>
   </params>
   <value>456</value>
</edit>

We want to find id of edit whose label is label1. The simplest solution seems to be:

def param = doc.edit.params.param.find { it['@value'] == 'label1' }
def edit = params.parent().parent()

But it doesn’t work! The parent method returns multiple edits, not only the one that is parent of given param

Here’s the correct solution:

doc.edit.find { edit ->
    edit.params.param.find { it['@value'] == 'label1' }
}

Example

The example working project covering those hints could be found on GitHub.