• No results found

. Modeling the Weda architectural style

In next sections, the Weda is modeled as a network of timed automata that communicates via message passing (after successfull handshake). This results in compact and intuitively appealing protocol specification. I haven’t found any previous work that models application of some WebSocket subprotocol.

This work is another contribution in area of model checking and WebSockets description.

.. Architecture of the single node model

The model is (as all models) an abstraction of the real implemented protocol in the sense that it leaves out details regarded as unimportant for the verifica-tion task. In our case, an addiverifica-tional challenge in choosing abstracverifica-tion is the need to reduce the state space to search, and hence to reduce time and space consumption during the automatic verification. The goal of this chapter is to make a formal model of this method using UPPAAL and to verify a number of

properties. In the previous chapters we gave an informal description that can be translated to draft RFC document. The protocol is modeled as a network of eight timed automata which can be divided into three groups: a gateway, service and client. Please observe that each group has its own clock if needed – running independently of all other clocks in the system.

Weda model consists of three parts: Server (with Weda gateway), Client and Weda Channel. Modeling an entity such as a Client or Server is a complex and time consuming task. We have decided to keep more abstraction levels to make model a little bit easier to understand and also to decrease the number of reach-able states because of state explosion problem. For example no client proxy or Weda wire layer was modeled at the client group. On the other side, server model is a little bit more complicated to show main tasks to be performed when implementing the style. To make the understanding of the idea behind the implementation easier, the Server model has been divided into four different sub-partitions as follows:

WedaGateway_HostInitialization

WedaGateway_SessionChannelListener

WedaGateway_SessionChannelManager

WedaGateway_SessionChannelWire

Weda channel model is described by WedaChannelInput and WedaChannelOutput timed automata and Client is modeled via WedaGateway_SessionChannelFactory and Client timed automata.



system WedaGateway_HostInitialization, WedaGateway_SessionChannelListener, WedaGateway_SessionChannelManager, WedaGateway_SessionChannelWire,

WedaChannelInput, WedaChannelOutput, WedaGateway_SessionChannelFactory, Client;



Listing 4.1: System definition

.. Weda Gateway Host Initialization

Before the provider and consumer starts communicating with each other, an initialization has to take place. First, the user of API starts the service host which is modeled in initial commited state. Weda gateway gets boot-strapped (i.e. endpoints are configured - ConfigureWedaEndpoints() and Web-Socket server component is started - WebsocketServerStart()). Directly after this srvReady is set and process stay in state Running.



void wedaServerStart() { ConfigureWedaEndpoints();

WebsocketServerStart();

}

ServiceHost_Running ServiceHost_Start

wedaServerStart()

srvReady!

Figure 4.3: Host initialization model.



Listing 4.2: Host initialization local declarations.

.. Weda Gateway SessionChannelListener

WS_ClientConnectionCreated WS_OpenHandshakeValidated WS_TcpConnectionAccepted

Wait NotReady

closedWsConnection[wscon]?

removeFromWsConList()

wsconcnt >= ClientCnt wedaErrServerError[wscon]!

validSubprotocol == true &&

wsconcnt < ClientCnt newWsConnection[wscon]!

addToWsConList()

validSubprotocol == false wedaErrClientError[wscon]!

wsOpenHandshake[wscon]!

wsValidateSubprotocol() wsOpenHandshake[wscon]?

connect[wscon]?

srvReady?

Figure 4.4: Weda Gateway Session Channel Listener model.

The main server’s component that listens for incoming Websocket connections and verifies the incoming subprotocol agreement is called

SessionChannelListener. When the new connection attempt is detected, automat leaves its Waiting state and tries to perform a valid Websocket handshake. The first step is to open a TCP connection. In the descriptive model, we have not explicitly modeled TCP. Instead, the TCP connection is modeled as be-ing open when there is a token present on the channel place. When both sides have opened the TCP connection, the client sends its HTTP upgrade request.

Response with status line “101 Switching Protocols” indicates that the server is changing to the protocol defined in the “Upgrade” header. If subprotocol re-quest is valid and we didn’t exceeded the amount of allowed client count, new Websocket connection is successfully initiated (and client thread started). If subprotocol was not recognized or amount of clients has exceeded the configu-rated limit, automata leaves to Wait state and waits for another valid handshake request.



boolvalidSubprotocol;

void wsValidateSubprotocol(){

validSubprotocol =true;

}

void addToWsConList( ){

wsconcnt++;

}

void removeFromWsConList(){

wsconcnt−−;

}

Listing 4.3: Session Channel Listener’s local declarations.

.. Weda Gateway SessionChannelManager

This model handles Weda channel creation and closing. We have abstracted the EndpointChannelManager component described in informal description into call of the function in this model to achieve readability. In this model, only one channel per WS connection can be created. However informal section de-scribes the details of how to achieve the desired behaviour and model can be extended by this way in the future. Model starts its work on synchronization called newWsConnection. When we have such a tunnel, we then make agreement on WS connection and session channel Id (at this version they can equal, in fu-ture versions this is the place to put EndpointChannelManager into the model).

Server prepares random SessionId and then it sends a notification (unreliable) to the client about the connection properties. By this ACK message we are ex-changing all the information which would otherwise be sent in HTTP header if we were not in Weda system. If Weda channel is opened, it remains waiting for message exchange modeled in another automaton. Channels are destroyed together with Websocket connection. This can be caused by client request or by some exception with impact of aborting the connection. After close, com-ponent will wait for another established WS connection.

WEDA_ChannelOpened

WS_ConnectionClosed

WEDA_ChannelsFaulted

WEDA_ChannelClosed WEDA_ChannelsClosing

WEDA_ChannelsOpened

WEDA_Subprotocol_ChannelAccepted WEDA_ChannelCreated

NotReady

reset()

wedaChannelsOpened[wscon]!

wedaChannelToOneLogicalEndpointOpened[sessionId]!

closedWsConnection[wscon]!

abortChannels[wscon]!

wedaDestroyAllChannels() abortChannels[wscon]!

wedaDestroyAllChannels()

wsConnectionClosed_ReasonOther[wscon]?

wsConnectionClosed_ReasonClientClosing[wscon]?

newWsConnection[wscon]?

wedaCreateChannelToOneLogicalEndpoint()

wedaMsgAck[wscon]!

sendAck(sessionId)

Figure 4.5: Session Channel Manager model.



int sessionId ;

void wsValidateOpenHandshake(){}

void wsValidateSubprotocol(){}

void wedaCreateChannelToOneLogicalEndpoint(){

// RandomizeSessionId sessionId = wscon;

// RegisterChannelToEndpointTo WSConnection

// ( you can have more logical channels on one ws connection−todo in model) channelsOfWsConnection[wscon] = sessionId;

sessioncnt ++;

}

void wedaDestroyAllChannels(){

// unregister

channelsOfWsConnection[wscon] = ;

sessioncnt−−;

}

void sendAck(id_session id ) {

csessid [ wscon] = id ; }

void reset (){

wsconcnt = ;

sessioncnt = ;

}

Listing 4.4: Session Channel Manager’s local declarations.

.. Weda Gateway SessionChannelWire

In order to route messages, we define SessionChannelWire component, responsi-ble for routing wire messages (Weda subprotocol messages). These come from WS connection as UTF-8 encoded frames and asynchronously fire Websocket API’s method DataFrameReceived. This is modeled with binary synchroniza-tion channel from Client automata nextFrame which represents client’s request.

Every frame gets validated if it is valid Weda message. This means for example controlling the flow, Websocket framing issues or incoming id of channel as described in previous work. Valid Weda messages are then enqueued in input buffer of size RcvWindow (used for flow control) and appropriate Weda chan-nel is notified about new message via the incomingWedaMsg synchronization.



int chanid;

boolflowControlErr = false; void validate (){

flowControlErr =false ;

Ready NotReady

WEDA_Wire_RouteToChannelByLogicalEndpoint WEDA_ValidateFrame

WS_DataFrameReceived

e : id_message flowControlErr == false enqueue(e)

abortChannels[wscon]?

flowControlErr == true

wedaErrChannelNotFound!

incomingWedaMsg[chanid]!

nextFrame[wscon]?

wedaChannelsOpened[wscon]?

validate()

Figure 4.6: Session Channel Wire model.

}

void route(){

// lookup weda header for the right route chanid = wscon;

}

// Put an element at the end of the queue void enqueue(id_message message)

{

list [ len++] = message;

route();

}

Listing 4.5: Session Channel Wire’s local declarations.

.. Full-duplex Weda channel

Here we model the channel component responsible for receiving or sending exactly one message at opened session channel. This is done by two timed automata modeling the I/O behavior.

When router notifies the Weda channel about new message in the buffer, au-tomaton tries to dequeue message from input buffer to receive Weda Message.

Message then gets deserialized so the Weda headers are cut leaving the body

MEPDetected NotReady

Ready

WEDA_ResponsePrepared ServiceHost_Proccess

WEDA_RoutingToServiceOperation WEDA_MessageReceived abortChannels[sessionid]?

RequestReply == false

RequestReply == true CorrelateResponse() detectMep()

deserialize()

notifyWedaMsg[sessionid]!

operationFound == true incomingWedaMsg[sessionid]?

dequeue()

wedaChannelToOneLogicalEndpointOpened[sessionid]?

Figure 4.7: WedaChannelInput model

Ready NotReady

WEDA_SendingDataframe abortChannels[sessionid]?

serialize()

notifyWedaMsg[sessionid]?

nextFrameOut[sessionid]!

wedaChannelToOneLogicalEndpointOpened[sessionid]?

Figure 4.8: WedaChannelOutput model.

which should be encoded in format at which the Client and server agreeded on during the handshake (for example SOAP1.2[65]). This payload should be then sent to upper layers to process a desired operation requested by contract.

In model we assumed that the operation was found in upper stack. When Weda layer is entered back, it should assume whether the upper layer has generated some kind of response and detect a desired message exchange pattern[66]. In model we are showing only the request/reply MEP because it is most diffi-cult MEP in full-duplex channel. If one-way message has been identified, the automata can simply return to Ready state waiting for another message. In request/reply scenario, response message generated body must be serialized onto Weda format and attached to header with request correlation informa-tion to allow pipelining of messages through the channel. After that an Output is informed to send the new Weda message on the wire. This is modeled with notifyWedaMsg binary synchronization.

When output channel is notified, it simply serializes the Weda message and sends a dataframe back to the client as modeled with nextFrameOut synchro-nization.

// R: As we want request and reply message to be correlated

// on Weda channel, messaging format MUST uniquely identify message in time // and space. No two messages with a distinct application intent may share // a [ message id] property . A message MAY be retransmitted for any purpose // including communications failure and MAY use the same [message id] property . responseId[sessionid ] = incommingMsgId;

}

// Returns the last message of the buffer queue id_message tail ()

}

list [ i ] = ;

}

void deserialize (){

operationFound = ;

}

Listing 4.6: Input channel local declarations

.. Client-side modeling

Note that the client model is very simplified against the informal descrip-tion. Note also that following models presented describe Weda’s client-server behavior. But when event processing layer is to be added to the system, client side should also use WedaGateway “server’s” components (Listener, Manager, Wire, I/Ochannel,...) bringing us the enterprise service bus integration Weda endpoint at the client side.

.. SessionChannelFactory

SessionChannelFactory represents Weda’s inner client mechanism for creation and disposition of channels at the client side. It is synchronized with Client automaton by openChannel synchronization. When client wants to open Weda channel, Factory tries to connect to the server Weda endpoint and establish Websocket handshake (with SessionChannelListener component). When web-socket connection is ready, then Wedachannel is to be initiated by receiving ACKmessage from the server with information like sessionId of established chan-nel or primary size of RcvWindow to allow flow control. When chanchan-nel opened at the client side, Client automaton gets informed about this by opened uppaal channel.

SessionChannelFactory also stay in ChannelOpened state until the time that client asks to close it or until the connection is closed for other reasons.

.. Client

This automaton is as simple as it represents the client caller of the API. At first it calls Factory’s methods for Weda channel establishment. When channel opened, it generates cntMsg number of messages and sends them onto the server (note the client side WedaChannelInput and WedaChannelOutput is not modeled because of readability of model). At the same time it is asynchronously listen-ing the Weda channel for incomlisten-ing messages from the server. If the message represents the response to the client’s request, these two are paired together and put to the application layer. After cntMsg messages were sent, the client is awaiting all responses from the server even in out-of-order manner allowing true multithreaded environment. When all responses arrive, client invokes the

WEDA_ChannelClosing WEDA_ChannelOpened NotReady

WEDA_ChannelClosed WEDA_ChannelOpening

WS_ConnectionCreated

WS_ChannelCreated

WS_ReceiveOpeningHandshake WS_OpeningTcpConnection

Opening

closedWsConnection[idclient]?

wsConnectionClosed_ReasonClientClosing[idclient]!

close[idclient]?

wedaErrClientError[idclient]?

setClientError()

opened[idclient]!

wedaMsgAck[idclient]?

error == 1 wsOpenHandshake[idclient]?

validateOpeningHandshake() wsOpenHandshake[idclient]!

openChannel[idclient]?

error == 0 connect[idclient]!

Figure 4.9: SessionChannelFactory model.

Close operation to destroy Weda channel. After that it opens a new connec-tion and establishes new channel again in never-ending cycle to allow the best simulation.

Receiving Sending

Opened Opening Closed

nextFrameOut[csessid[idclient]]?

receive() noRequest < cntMsg

nextFrame[idclient]!

send() noRequest >= cntMsg &&

noRequest == noResponse close[idclient]!

reset()

opened[idclient]?

openChannel[idclient]!

Figure 4.10: Client



int turns = ;

int noRequest;

int noResponse;

constint cntMsg = ; // number of send request per turn

void receive (){

noResponse++;

}

void send(){

noRequest++;

}

void reset (){

turns++;

noRequest = ;

noResponse = ;

now = ;

}

Listing 4.7: Client local declarations

.. Global Variables

Each automaton uses of one or more global variables. These variables repre-sent binary or broadcast channels used for parallel composition of a

synchro-nization set. We will list the variables commented in the following listings:



// change this value to model more clients connected to weda server . // Unfortunatelly , verification is not possible , because of state space // explosion problem of UPPAAL.

// Verificate at one client system.

constint ClientCnt = ; //  clientthreads

constint MaxChannels =  ; // logical channel count − this version must = ClientCnt //−don’t change after here.

clock now;

// WEDA SERVER− WS CONNECTIONS AND ITS WEDA CHANNELS typedef int[, ClientCnt−] id_wsconnection;

int channelsOfWsConnection[id_wsconnection];//only one at the moment int wsconcnt = ;// actual count of websocket connections = connected clients broadcast chanwedaChannelsOpened[id_wsconnection],

closedWsConnection[id_wsconnection];

channewWsConnection[id_wsconnection];

chanwsConnectionClosed_ReasonClientClosing[id_wsconnection];

chanwsConnectionClosed_ReasonOther[id_wsconnection];

typedef int[, MaxChannels− ] id_session;

id_session channels;

int sessioncnt = ;

broadcast chanwedaChannelToOneLogicalEndpointOpened[id_session];

chanwedaMsgAck[id_wsconnection];

// MESSAGE

constint RcvWindow = ;// flow control limit

typedef int[, RcvWindow−] id_message;//id of weda message ( in range of RcvWindow) id_message list [ RcvWindow+];//input buffer

int[, RcvWindow] len;// actual message id − buffer freespace indicator

// HOST

// indicates that Weda Gateway finished server initialization phase broadcast chansrvReady;

chansrvClose ;// indicates server shutdown chanwsOpenHandshake[id_wsconnection];

// SUBPROTOCOL

chanincomingWedaMsg[id_session];

channotifyWedaMsg[id_session];

chanwedaErrChannelNotFound, wedaErrOverload[id_session],

wedaErrServerError[ id_wsconnection], wedaErrClientError [ id_wsconnection];

// CLIENT

// indicates that client wants to connect to weda endpoint chanopenChannel[id_wsconnection];

chanconnect[id_wsconnection], opened[id_wsconnection], close[ id_wsconnection];

chantimerOn[id_wsconnection], timerOff[ id_wsconnection];

broadcast chanabortChannels[id_wsconnection];

// indicates wire client request

// ( note that serialization to wire is not modeled for client ) channextFrame[id_wsconnection];

channextFrameOut[id_session]; // indicated message from server to Client int csessid [ id_wsconnection];

id_message responseId[id_session];



Listing 4.8: Weda system’s global declarations

.. Weda model simulation

Simulation of system revealed some mistakes made to the model during mod-eling process. Each run was simulated for a long time runs and has shown particular problems such as deadlocks or client blocking on system with 10 clients for example. These problems were detected and repaired in the model presented in previous section. Example visual output of run from the simula-tor can be viewed in appendix A. Whole model is publicily available on the internet [49].

. Verification

This section presents the results of the verification of the Weda architec-ture style. The UPPAAL model checking system can verify safety, liveness, bounded liveness and reachability properties of a system.

The finite model achieved after the modeling stage is still complex with respect to the memory cost. Thus, a restriction to a small number of processes is required in order to check correctness with UPPAAL.We restricted ourselves up to 50 client processes. Despite that, some properties are difficult to check even for one client as it requires a lot of memory space as well as time such as safety properties. For a safety properties we have created simplified model where one client is connecting to the server only. By UPPAAL’s CTL formula:

A□ (not deadlock)

(4.1) we have confirmed that system is deadlock free.

Now we add an example of not satified property. In asynchronous system we can’t predict that response will return in some meaningfull time by design.

So if we try to verify such property, the result should show that property is not satisfied.

A□ (Client(0).noRequest ! = Client(0).noResponse)

imply (Client(0).TimerRequest < 10000) (4.2)

Following reachability properties has been proved to be satisfied. Next prop-erty checks if client can successfully reconnect and send messages again. It asks if there exists a state where number of turns is greather than zero and channel is again opened.

E♢(Client(0).turns > 0 && Client(0).Opened &&

WedaGateway_SessionChannelWire(0).Ready && Client(0).noRequest > 0) (4.3) Next property checks that the client can open channel succesfully.

E♢ Client(0).Opened

(4.4) Next property checks that the Wire frame can be successfully received.

E♢ WedaChannelInput(0).WEDA_MessageReceived

(4.5) Liveness properties were also verified as being satisfied. The properties are as follows:

A♢ Client(0).noRequest > Client(0).noResponse imply Client(0).Receiving

(4.6) Previous formula verify that every request can obtain its response.

A♢ WedaGateway_SessionChannelFactory(0).WS_OpeningTcpConnection imply

WedaGateway_SessionChannelListener(0).WS_TcpConnectionAccepted (4.7) Previous formula verify that opening the WS connection by client leads to be accepted by the server.

E♢ WedaGateway_SessionChannelWire(0).Ready &&

Client(0).noRequest < Client(0).cntMsg

imply WedaGateway_SessionChannelWire(0).WS_DataFrameReceived (4.8) Previous formula confirms that the system will try to send all messages in the cycle and they are to be received by the Weda server.

. Conclusion

In this chapter we present a framework that can be used to model and verify Weda architecture style in UPPAAL. Whole middleware is modeled by timed

automata to show its behaviour - WedaAPI components, client API invoker and integration with server-side service layer. Model consists of several mod-ules at various levels of abstraction. This approach allows for the system’s sim-ulation and verification before the actual implementation, permitting the early detections of any undesirable behavior. Because the method is susceptible to state space explosion, the model must be abstracted as much as possible, mak-ing a compromise between model complexity and its state space size.

We have proved some of the architecture style properties. For example that the system is deadlock free, client can repeatedly connect and send messages to the server and each request can obtain its response. Or that clients can connect and server can receive Websocket frames and translate them into Weda messages.

In future work client proxy should be modeled in deeper abstraction by adding additional automata, showing how server can asynchronously push messages to client’s public Weda endpoint, which brings event-driven be-haviour of Weda to the model.

This work has contribution to area of model checking and verification as it shows how to model an application of some WebSocket subprotocol, for example with the goal of building new or extending existing message passing architecture style.

. Adapting applications to Weda API

. Overview

With this chapter we explain and provide code examples for many common integration use cases. If you’re looking for more in depth information, online reference [48] should be visited.