PageRenderTime 71ms CodeModel.GetById 16ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/protocols/ss7/m3ua/impl/src/main/java/org/mobicents/protocols/ss7/m3ua/impl/sg/RemAspFactory.java

http://mobicents.googlecode.com/
Java | 471 lines | 304 code | 80 blank | 87 comment | 51 complexity | 848982ae4e382a11c1cf92022b58ffa3 MD5 | raw file
  1/*
  2 * JBoss, Home of Professional Open Source
  3 * Copyright 2011, Red Hat, Inc. and individual contributors
  4 * by the @authors tag. See the copyright.txt in the distribution for a
  5 * full listing of individual contributors.
  6 *
  7 * This is free software; you can redistribute it and/or modify it
  8 * under the terms of the GNU Lesser General Public License as
  9 * published by the Free Software Foundation; either version 2.1 of
 10 * the License, or (at your option) any later version.
 11 *
 12 * This software is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 15 * Lesser General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU Lesser General Public
 18 * License along with this software; if not, write to the Free
 19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 21 */
 22
 23package org.mobicents.protocols.ss7.m3ua.impl.sg;
 24
 25import javolution.util.FastList;
 26import javolution.xml.XMLFormat;
 27import javolution.xml.stream.XMLStreamException;
 28
 29import org.apache.log4j.Logger;
 30import org.mobicents.protocols.ss7.m3ua.M3UAProvider;
 31import org.mobicents.protocols.ss7.m3ua.impl.As;
 32import org.mobicents.protocols.ss7.m3ua.impl.Asp;
 33import org.mobicents.protocols.ss7.m3ua.impl.AspFactory;
 34import org.mobicents.protocols.ss7.m3ua.impl.AspState;
 35import org.mobicents.protocols.ss7.m3ua.impl.M3UAManagement;
 36import org.mobicents.protocols.ss7.m3ua.impl.TransitionState;
 37import org.mobicents.protocols.ss7.m3ua.impl.fsm.FSM;
 38import org.mobicents.protocols.ss7.m3ua.impl.fsm.UnknownTransitionException;
 39import org.mobicents.protocols.ss7.m3ua.message.M3UAMessage;
 40import org.mobicents.protocols.ss7.m3ua.message.MessageClass;
 41import org.mobicents.protocols.ss7.m3ua.message.MessageType;
 42import org.mobicents.protocols.ss7.m3ua.message.aspsm.ASPDown;
 43import org.mobicents.protocols.ss7.m3ua.message.aspsm.ASPDownAck;
 44import org.mobicents.protocols.ss7.m3ua.message.aspsm.ASPUp;
 45import org.mobicents.protocols.ss7.m3ua.message.aspsm.ASPUpAck;
 46import org.mobicents.protocols.ss7.m3ua.message.asptm.ASPActive;
 47import org.mobicents.protocols.ss7.m3ua.message.asptm.ASPActiveAck;
 48import org.mobicents.protocols.ss7.m3ua.message.asptm.ASPInactive;
 49import org.mobicents.protocols.ss7.m3ua.message.asptm.ASPInactiveAck;
 50import org.mobicents.protocols.ss7.m3ua.message.transfer.PayloadData;
 51import org.mobicents.protocols.ss7.m3ua.parameter.ASPIdentifier;
 52import org.mobicents.protocols.ss7.m3ua.parameter.ErrorCode;
 53import org.mobicents.protocols.ss7.m3ua.parameter.RoutingContext;
 54import org.mobicents.protocols.ss7.m3ua.parameter.TrafficModeType;
 55
 56/**
 57 * 
 58 * @author amit bhayani
 59 * 
 60 */
 61public class RemAspFactory extends AspFactory {
 62
 63	private static Logger logger = Logger.getLogger(RemAspFactory.class);
 64	
 65	public RemAspFactory(){
 66		super();
 67	}
 68
 69	public RemAspFactory(String name, String ip, int port, M3UAProvider provider, M3UAManagement m3uaManagement) {
 70		super(name, ip, port, provider, m3uaManagement);
 71	}
 72
 73	@Override
 74	public Asp createAsp() {
 75		RemAspImpl remAsp = new RemAspImpl(this.name, this.m3UAProvider, this);
 76		this.aspList.add(remAsp);
 77		return remAsp;
 78	}
 79
 80	@Override
 81	public void read(M3UAMessage message) {
 82
 83		switch (message.getMessageClass()) {
 84
 85		case MessageClass.MANAGEMENT:
 86			switch (message.getMessageType()) {
 87			case MessageType.ERROR:
 88			case MessageType.NOTIFY:
 89			}
 90			break;
 91
 92		case MessageClass.TRANSFER_MESSAGES:
 93			switch (message.getMessageType()) {
 94			case MessageType.PAYLOAD:
 95				PayloadData payload = (PayloadData) message;
 96				this.handlePayload(payload);
 97				break;
 98			default:
 99				break;
100			}
101			break;
102
103		case MessageClass.SIGNALING_NETWORK_MANAGEMENT:
104			logger.warn(String.format("Received %s. Handling of SSNM message is not yet implemented", message));
105			break;
106
107		case MessageClass.ASP_STATE_MAINTENANCE:
108			switch (message.getMessageType()) {
109			case MessageType.ASP_UP:
110				ASPUp aspUp = (ASPUp) message;
111				this.handleAspUp(aspUp);
112				break;
113			case MessageType.ASP_DOWN:
114				// The SGP MUST send an ASP Down Ack message in response to a
115				// received ASP Down message from the ASP even if the ASP is
116				// already marked as ASP-DOWN at the SGP.
117				ASPDown aspDown = (ASPDown) message;
118				this.handleAspDown(aspDown);
119				break;
120			case MessageType.HEARTBEAT:
121				break;
122			default:
123				break;
124			}
125
126			break;
127
128		case MessageClass.ASP_TRAFFIC_MAINTENANCE:
129			// ASPTM should be given to only respective ASP's
130			switch (message.getMessageType()) {
131			case MessageType.ASP_ACTIVE:
132				ASPActive aspActive = (ASPActive) message;
133				this.handleAspActive(aspActive);
134				break;
135			case MessageType.ASP_INACTIVE:
136				ASPInactive aspInactive = (ASPInactive) message;
137				this.handleAspInactive(aspInactive);
138				break;
139			default:
140				break;
141			}
142
143			break;
144
145		case MessageClass.ROUTING_KEY_MANAGEMENT:
146			break;
147
148		default:
149
150			break;
151
152		}
153	}
154
155	private void handlePayload(PayloadData payload) {
156		// Payload is always for single AS
157		long rc = payload.getRoutingContext().getRoutingContexts()[0];
158		Asp asp = this.getAsp(rc);
159
160		if (asp == null) {
161			logger.error(String.format("received PayloadData for RoutingContext=%d. But no ASP found. Message=%s", rc,
162					payload));
163			return;
164		}
165
166		if (asp.getState() == AspState.ACTIVE) {
167			asp.getAs().received(payload);
168		} else {
169			logger.error(String.format("Received PayloadData for RoutingContext=%d. But ASP State=%s. Message=%s", rc,
170					asp.getState(), payload));
171		}
172
173	}
174
175	private void handleAspDown(ASPDown aspDown) {
176		ASPDownAck aspDwnAck = (ASPDownAck) this.m3UAProvider.getMessageFactory().createMessage(
177				MessageClass.ASP_STATE_MAINTENANCE, MessageType.ASP_DOWN_ACK);
178		this.write(aspDwnAck);
179
180		// ASPSM should be given to all ASP's
181		for (FastList.Node<Asp> n = aspList.head(), end = aspList.tail(); (n = n.getNext()) != end;) {
182			Asp asp = n.getValue();
183
184			try {
185				// Signal ASP about state change
186				asp.getFSM().setAttribute(FSM.ATTRIBUTE_MESSAGE, aspDown);
187				asp.getFSM().signal(TransitionState.ASP_DOWN);
188
189				// Signal corresponding AS about ASP's state transition
190				asp.getAs().aspStateChange(asp, TransitionState.ASP_DOWN);
191			} catch (UnknownTransitionException e) {
192				logger.error(e.getMessage(), e);
193			}
194
195		}
196	}
197
198	private void handleAspUp(ASPUp aspUp) {
199		ASPUpAck aspUpAck = (ASPUpAck) this.m3UAProvider.getMessageFactory().createMessage(
200				MessageClass.ASP_STATE_MAINTENANCE, MessageType.ASP_UP_ACK);
201
202		ASPIdentifier aspId = aspUp.getASPIdentifier();
203		if (aspId != null) {
204			aspUpAck.setASPIdentifier(aspId);
205		}
206
207		this.write(aspUpAck);
208
209		// If an ASP Up message is received and, internally, the remote ASP is
210		// in the ASP-ACTIVE state, an ASP Up Ack message is returned, as well
211		// as an Error message ("Unexpected Message"). In addition, the remote
212		// ASP state is changed to ASP-INACTIVE in all relevant Application
213		// Servers, and all registered Routing Keys are considered deregistered.
214
215		for (FastList.Node<Asp> n = aspList.head(), end = aspList.tail(); (n = n.getNext()) != end;) {
216			Asp asp = n.getValue();
217
218			// Set the ASPIdentifier for each ASP
219			asp.setASPIdentifier(aspUp.getASPIdentifier());
220
221			if (asp.getState() == AspState.ACTIVE) {
222				// Check if ASP is in ACTIVE, its error state
223				this.sendError(ErrorCode.Unexpected_Message, asp.getAs().getRoutingContext());
224				// break;
225			}
226
227			try {
228				// Signal ASP about state change
229				asp.getFSM().setAttribute(FSM.ATTRIBUTE_MESSAGE, aspUp);
230				asp.getFSM().signal(TransitionState.ASP_UP);
231
232				// Signal corresponding AS about ASP's state transition
233				asp.getAs().aspStateChange(asp, TransitionState.ASP_UP);
234			} catch (UnknownTransitionException e) {
235				logger.error(e.getMessage(), e);
236			}
237		}
238	}
239
240	private void handleAspInactive(ASPInactive aspInactive) {
241		long[] rcs = null;
242		RoutingContext rcObj = aspInactive.getRoutingContext();
243		if (rcObj == null) {
244
245			if (this.aspList.isEmpty()) {
246				// If the received ASP Inactive message does not contain
247				// an RC parameter and the RK is not defined (by either
248				// static configuration or dynamic registration), the
249				// SGP/IPSP MUST respond with an ERROR message with the
250				// Error Code "No configured AS for ASP".
251				this.sendError(ErrorCode.No_Configured_AS_for_ASP, null);
252				return;
253			}
254
255			// Send ASP Inactive to all ASP's
256			rcs = new long[this.aspList.size()];
257			for (int count = 0; count < rcs.length; count++) {
258				rcs[count] = this.aspList.get(count).getAs().getRoutingContext().getRoutingContexts()[0];
259			}
260		} else {
261			rcs = rcObj.getRoutingContexts();
262		}
263
264		for (long routCntx : rcs) {
265			RemAspImpl remAsp = this.getAsp(routCntx);
266
267			// RemAsp is null means Remote AS is null
268			if (remAsp == null) {
269				// If the received ASP Inactive message contains an RC parameter
270				// that is not defined (by either static configuration or
271				// dynamic registration), the SGP/IPSP MUST respond with an
272				// ERROR message with the Error Code "Invalid Routing Context".
273				RoutingContext rc1 = this.m3UAProvider.getParameterFactory().createRoutingContext(
274						new long[] { routCntx });
275				this.sendError(ErrorCode.Invalid_Routing_Context, rc1);
276			}
277
278			As appServer = remAsp.getAs();
279
280			ASPInactiveAck aspInactAck = (ASPInactiveAck) this.m3UAProvider.getMessageFactory().createMessage(
281					MessageClass.ASP_TRAFFIC_MAINTENANCE, MessageType.ASP_INACTIVE_ACK);
282			aspInactAck.setRoutingContext(appServer.getRoutingContext());
283
284			this.write(aspInactAck);
285
286			try {
287				remAsp.getFSM().setAttribute(FSM.ATTRIBUTE_MESSAGE, aspInactive);
288				remAsp.getFSM().signal(TransitionState.ASP_INACTIVE);
289
290				// Signal AS to transition
291				appServer.aspStateChange(remAsp, TransitionState.ASP_INACTIVE);
292			} catch (UnknownTransitionException e) {
293				logger.error(e.getMessage(), e);
294			}
295
296		}
297	}
298
299	private void handleAspActive(ASPActive aspActive) {
300
301		RoutingContext rcObj = aspActive.getRoutingContext();
302		long[] rcs = null;
303		if (rcObj == null) {
304
305			if (this.aspList.isEmpty()) {
306				// If the RC parameter is not included in the ASP Active
307				// message and there are no RKs defined, the peer node
308				// SHOULD respond with and ERROR message with the Error
309				// Code "Invalid Routing Context".
310				this.sendError(ErrorCode.Invalid_Routing_Context, null);
311				// TODO : Shouldn't the ErrorCode be
312				// ErrorCode.No_Configured_AS_for_ASP?
313				return;
314			}
315
316			// Send ASP Active to all ASP's
317			rcs = new long[this.aspList.size()];
318			for (int count = 0; count < rcs.length; count++) {
319				rcs[count] = this.aspList.get(count).getAs().getRoutingContext().getRoutingContexts()[0];
320			}
321		} else {
322			rcs = rcObj.getRoutingContexts();
323		}
324
325		TrafficModeType trfModType = aspActive.getTrafficModeType();
326
327		for (long routCntx : rcs) {
328			RemAspImpl remAsp = this.getAsp(routCntx);
329
330			// RemAsp is null means Remote AS is null
331			if (remAsp == null) {
332				// If the RC parameter is included in the ASP Active message
333				// and a corresponding RK has not been previously defined
334				// (by either static configuration or dynamic registration),
335				// the peer MUST respond with an ERROR message with the
336				// Error Code "No configured AS for ASP".
337				RoutingContext rc1 = this.m3UAProvider.getParameterFactory().createRoutingContext(
338						new long[] { routCntx });
339				this.sendError(ErrorCode.No_Configured_AS_for_ASP, rc1);
340				// TODO : Shouldn't is be ErrorCode.Invalid_Routing_Context ?
341				continue;
342
343			}
344
345			As appServer = remAsp.getAs();
346
347			if (appServer.getTrafficModeType() != null) {
348				// AppServer has Traffic Mode Type defined check if it
349				// matches with sent ASP ACTIVE Message
350				if (trfModType != null && appServer.getTrafficModeType().getMode() != trfModType.getMode()) {
351
352					// Traffic Mode Type mismatch. Send Error.
353					// TODO should send error or drop message?
354					this.sendError(ErrorCode.Unsupported_Traffic_Mode_Type, appServer.getRoutingContext());
355					continue;
356				}
357
358				// message doesn't have Traffic Mode Type
359
360			} else {
361
362				// AppServer Traffic Mode Type is optionally configured via
363				// management config. If not select the first available in
364				// AspUp message
365
366				if (trfModType == null) {
367					// Asp UP didn't specify the Traffic Mode either. use
368					// default which is loadshare
369					appServer.setDefaultTrafficModeType();
370				} else {
371					// Set the Traffic Mode Type passed in ASP ACTIVE
372					appServer.setTrafficModeType(trfModType);
373				}
374			}
375
376			ASPActiveAck aspActAck = (ASPActiveAck) this.m3UAProvider.getMessageFactory().createMessage(
377					MessageClass.ASP_TRAFFIC_MAINTENANCE, MessageType.ASP_ACTIVE_ACK);
378			aspActAck.setTrafficModeType(appServer.getTrafficModeType());
379			aspActAck.setRoutingContext(appServer.getRoutingContext());
380
381			this.write(aspActAck);
382
383			try {
384				remAsp.getFSM().setAttribute(FSM.ATTRIBUTE_MESSAGE, aspActive);
385				remAsp.getFSM().signal(TransitionState.ASP_ACTIVE);
386
387				// Signal AS to transition
388				appServer.aspStateChange(remAsp, TransitionState.ASP_ACTIVE);
389			} catch (UnknownTransitionException e) {
390				logger.error(e.getMessage(), e);
391			}
392		}
393	}
394
395	private RemAspImpl getAsp(long rc) {
396		for (FastList.Node<Asp> n = aspList.head(), end = aspList.tail(); (n = n.getNext()) != end;) {
397			Asp asp = n.getValue();
398			if (asp.getAs().getRoutingContext().getRoutingContexts()[0] == rc) {
399				return (RemAspImpl) asp;
400			}
401		}
402		return null;
403	}
404
405	private void sendError(int iErrCode, RoutingContext rc) {
406		// Send Error
407		org.mobicents.protocols.ss7.m3ua.message.mgmt.Error error = (org.mobicents.protocols.ss7.m3ua.message.mgmt.Error) this.m3UAProvider
408				.getMessageFactory().createMessage(MessageClass.MANAGEMENT, MessageType.ERROR);
409
410		ErrorCode errCode = this.m3UAProvider.getParameterFactory().createErrorCode(iErrCode);
411		error.setErrorCode(errCode);
412		error.setRoutingContext(rc);
413		this.write(error);
414	}
415
416	@Override
417	public void start() {
418		this.started = true;
419	}
420
421	@Override
422	public void stop() {
423		this.started = false;
424	}
425
426	public void onCommStateChange(CommunicationState state) {
427		switch (state) {
428		case UP:
429			signalAspFsm(TransitionState.COMM_UP);
430			break;
431		case SHUTDOWN:
432			signalAspFsm(TransitionState.COMM_DOWN);
433			break;
434		case LOST:
435			signalAspFsm(TransitionState.COMM_DOWN);
436			break;
437		}
438	}
439
440	private void signalAspFsm(String asptransition) {
441		for (FastList.Node<Asp> n = aspList.head(), end = aspList.tail(); (n = n.getNext()) != end;) {
442			Asp asp = n.getValue();
443			try {
444				asp.getFSM().signal(asptransition);
445			} catch (UnknownTransitionException e) {
446				// This should never happen
447				logger.error(e.getMessage(), e);
448			}
449		}
450	}
451
452	/**
453	 * XML Serialization/Deserialization
454	 */
455	protected static final XMLFormat<RemAspFactory> REM_ASP_FACTORY_XML = new XMLFormat<RemAspFactory>(
456			RemAspFactory.class) {
457
458		@Override
459		public void read(javolution.xml.XMLFormat.InputElement xml, RemAspFactory remAspFactory)
460				throws XMLStreamException {
461			ASP_FACTORY_XML.read(xml, remAspFactory);
462		}
463
464		@Override
465		public void write(RemAspFactory remAspFactory, javolution.xml.XMLFormat.OutputElement xml)
466				throws XMLStreamException {
467			ASP_FACTORY_XML.write(remAspFactory, xml);
468		}
469	};
470
471}