PageRenderTime 57ms CodeModel.GetById 17ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 0ms

/protocols/ss7/m3ua/impl/src/main/java/org/mobicents/protocols/ss7/m3ua/impl/M3UAManagement.java

http://mobicents.googlecode.com/
Java | 659 lines | 430 code | 126 blank | 103 comment | 94 complexity | 42ebf0f39ab4ee71257acdca8dad0ef1 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;
 24
 25import java.io.File;
 26import java.io.FileInputStream;
 27import java.io.FileNotFoundException;
 28import java.io.FileOutputStream;
 29import java.io.IOException;
 30import java.util.concurrent.Executors;
 31import java.util.concurrent.ScheduledExecutorService;
 32import java.util.concurrent.TimeUnit;
 33
 34import javolution.text.TextBuilder;
 35import javolution.util.FastList;
 36import javolution.util.FastMap;
 37import javolution.xml.XMLObjectReader;
 38import javolution.xml.XMLObjectWriter;
 39import javolution.xml.stream.XMLStreamException;
 40
 41import org.apache.log4j.Logger;
 42import org.mobicents.protocols.api.Association;
 43import org.mobicents.protocols.api.Management;
 44import org.mobicents.protocols.ss7.m3ua.ExchangeType;
 45import org.mobicents.protocols.ss7.m3ua.Functionality;
 46import org.mobicents.protocols.ss7.m3ua.IPSPType;
 47import org.mobicents.protocols.ss7.m3ua.impl.fsm.FSM;
 48import org.mobicents.protocols.ss7.m3ua.impl.message.MessageFactoryImpl;
 49import org.mobicents.protocols.ss7.m3ua.impl.oam.M3UAOAMMessages;
 50import org.mobicents.protocols.ss7.m3ua.impl.parameter.ParameterFactoryImpl;
 51import org.mobicents.protocols.ss7.m3ua.impl.scheduler.M3UAScheduler;
 52import org.mobicents.protocols.ss7.m3ua.message.MessageClass;
 53import org.mobicents.protocols.ss7.m3ua.message.MessageFactory;
 54import org.mobicents.protocols.ss7.m3ua.message.MessageType;
 55import org.mobicents.protocols.ss7.m3ua.message.transfer.PayloadData;
 56import org.mobicents.protocols.ss7.m3ua.parameter.NetworkAppearance;
 57import org.mobicents.protocols.ss7.m3ua.parameter.ParameterFactory;
 58import org.mobicents.protocols.ss7.m3ua.parameter.ProtocolData;
 59import org.mobicents.protocols.ss7.m3ua.parameter.RoutingContext;
 60import org.mobicents.protocols.ss7.m3ua.parameter.TrafficModeType;
 61import org.mobicents.protocols.ss7.mtp.Mtp3PausePrimitive;
 62import org.mobicents.protocols.ss7.mtp.Mtp3ResumePrimitive;
 63import org.mobicents.protocols.ss7.mtp.Mtp3StatusPrimitive;
 64import org.mobicents.protocols.ss7.mtp.Mtp3TransferPrimitive;
 65import org.mobicents.protocols.ss7.mtp.Mtp3UserPartBaseImpl;
 66
 67/**
 68 * @author amit bhayani
 69 * 
 70 */
 71public class M3UAManagement extends Mtp3UserPartBaseImpl {
 72	private static final Logger logger = Logger.getLogger(M3UAManagement.class);
 73	private static final String AS_LIST = "asList";
 74	private static final String ASP_FACTORY_LIST = "aspFactoryList";
 75	private static final String DPC_VS_AS_LIST = "route";
 76
 77	private static final String M3UA_PERSIST_DIR_KEY = "m3ua.persist.dir";
 78	private static final String USER_DIR_KEY = "user.dir";
 79	private static final String PERSIST_FILE_NAME = "m3ua.xml";
 80
 81	private static final M3UAXMLBinding binding = new M3UAXMLBinding();
 82	private static final String TAB_INDENT = "\t";
 83	private static final String CLASS_ATTRIBUTE = "type";
 84
 85	protected FastList<As> appServers = new FastList<As>();
 86	protected FastList<AspFactory> aspfactories = new FastList<AspFactory>();
 87
 88	protected M3UAScheduler m3uaScheduler = new M3UAScheduler();
 89
 90	private final TextBuilder persistFile = TextBuilder.newInstance();
 91
 92	private final String name;
 93
 94	private String persistDir = null;
 95
 96	protected ParameterFactory parameterFactory = new ParameterFactoryImpl();
 97	protected MessageFactory messageFactory = new MessageFactoryImpl();
 98
 99	protected Management transportManagement = null;
100
101	private ScheduledExecutorService fsmTicker;
102
103	protected int maxAsForRoute = 4;
104
105	private M3UARouteManagement routeManagement = null;
106
107	public M3UAManagement(String name) {
108		this.name = name;
109		binding.setClassAttribute(CLASS_ATTRIBUTE);
110		binding.setAlias(AspFactory.class, "aspFactory");
111		binding.setAlias(As.class, "as");
112		binding.setAlias(Asp.class, "asp");
113
114		this.routeManagement = new M3UARouteManagement(this);
115
116	}
117
118	public String getName() {
119		return name;
120	}
121
122	public String getPersistDir() {
123		return persistDir;
124	}
125
126	public void setPersistDir(String persistDir) {
127		this.persistDir = persistDir;
128	}
129
130	public int getMaxAsForRoute() {
131		return maxAsForRoute;
132	}
133
134	public void setMaxAsForRoute(int maxAsForRoute) {
135		this.maxAsForRoute = maxAsForRoute;
136	}
137
138	public Management getTransportManagement() {
139		return transportManagement;
140	}
141
142	public void setTransportManagement(Management transportManagement) {
143		this.transportManagement = transportManagement;
144	}
145
146	public void start() throws Exception {
147
148		if (this.transportManagement == null) {
149			throw new NullPointerException("TransportManagement is null");
150		}
151
152		if (maxAsForRoute < 1 || maxAsForRoute > 4) {
153			throw new Exception("Max AS for a route can be minimum 1 or maximum 4");
154		}
155
156		super.start();
157
158		this.persistFile.clear();
159
160		if (persistDir != null) {
161			this.persistFile.append(persistDir).append(File.separator).append(this.name).append("_")
162					.append(PERSIST_FILE_NAME);
163		} else {
164			persistFile.append(System.getProperty(M3UA_PERSIST_DIR_KEY, System.getProperty(USER_DIR_KEY)))
165					.append(File.separator).append(this.name).append("_").append(PERSIST_FILE_NAME);
166		}
167
168		logger.info(String.format("M3UA configuration file path %s", persistFile.toString()));
169
170		binding.setM3uaManagement(this);
171
172		try {
173			this.load();
174		} catch (FileNotFoundException e) {
175			logger.warn(String.format("Failed to load the SS7 configuration file. \n%s", e.getMessage()));
176		}
177		
178		this.routeManagement.reset();
179
180		fsmTicker = Executors.newSingleThreadScheduledExecutor();
181		fsmTicker.scheduleAtFixedRate(m3uaScheduler, 500, 500, TimeUnit.MILLISECONDS);
182
183		logger.info("Started M3UAManagement");
184	}
185
186	public void stop() throws Exception {
187		super.stop();
188
189		this.store();
190		fsmTicker.shutdown();
191	}
192
193	public FastList<As> getAppServers() {
194		return appServers;
195	}
196
197	public FastList<AspFactory> getAspfactories() {
198		return aspfactories;
199	}
200
201	public FastMap<String, As[]> getRoute() {
202		return this.routeManagement.route;
203	}
204
205	protected As getAs(String asName) {
206		for (FastList.Node<As> n = appServers.head(), end = appServers.tail(); (n = n.getNext()) != end;) {
207			As as = n.getValue();
208			if (as.getName().equals(asName)) {
209				return as;
210			}
211		}
212		return null;
213	}
214
215	/**
216	 * <p>
217	 * Create new {@link As}
218	 * </p>
219	 * <p>
220	 * Command is m3ua as create <as-name> <AS | SGW | IPSP> mode <SE | DE>
221	 * ipspType < client | server > rc <routing-context> traffic-mode <traffic
222	 * mode>
223	 * </p>
224	 * <p>
225	 * where mode is optional, by default SE. ipspType should be specified if
226	 * type is IPSP. rc is optional and traffi-mode is also optional, default is
227	 * Loadshare
228	 * </p>
229	 * 
230	 * @param args
231	 * @return
232	 * @throws Exception
233	 */
234	public As createAs(String asName, Functionality functionality, ExchangeType exchangeType, IPSPType ipspType,
235			RoutingContext rc, TrafficModeType trafficMode, NetworkAppearance na) throws Exception {
236
237		As as = this.getAs(asName);
238		if (as != null) {
239			throw new Exception(String.format(M3UAOAMMessages.CREATE_AS_FAIL_NAME_EXIST, asName));
240		}
241
242		// TODO check if RC is already taken?
243
244		if (exchangeType == null) {
245			exchangeType = ExchangeType.SE;
246		}
247
248		if (functionality == Functionality.IPSP && ipspType == null) {
249			ipspType = IPSPType.CLIENT;
250		}
251
252		as = new As(asName, rc, trafficMode, functionality, exchangeType, ipspType, na);
253		as.setM3UAManagement(this);
254		FSM localFSM = as.getLocalFSM();
255		this.m3uaScheduler.execute(localFSM);
256
257		FSM peerFSM = as.getPeerFSM();
258		this.m3uaScheduler.execute(peerFSM);
259
260		appServers.add(as);
261
262		this.store();
263
264		return as;
265	}
266
267	public As destroyAs(String asName) throws Exception {
268		As as = this.getAs(asName);
269		if (as == null) {
270			throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_NO_AS, asName));
271		}
272
273		if (as.getAspList().size() != 0) {
274			throw new Exception(String.format(
275					"As=%s still has ASP's assigned. Unassign Asp's before destroying this As", asName));
276		}
277
278		for (FastMap.Entry<String, As[]> e = this.routeManagement.route.head(), end = this.routeManagement.route.tail(); (e = e
279				.getNext()) != end;) {
280			As[] asList = e.getValue();
281			for (int count = 0; count < asList.length; count++) {
282				As asTemp = asList[count];
283				if (asTemp != null && asTemp.equals(as)) {
284					throw new Exception(String.format("As=%s used in route=%s. Remove from route", asName, e.getKey()));
285				}
286			}
287		}
288
289		FSM asLocalFSM = as.getLocalFSM();
290		if (asLocalFSM != null) {
291			asLocalFSM.cancel();
292		}
293
294		FSM asPeerFSM = as.getPeerFSM();
295		if (asPeerFSM != null) {
296			asPeerFSM.cancel();
297		}
298
299		appServers.remove(as);
300
301		this.store();
302
303		return as;
304	}
305
306	/**
307	 * Create new {@link AspFactory}
308	 * 
309	 * @param args
310	 * @return
311	 * @throws Exception
312	 */
313	public AspFactory createAspFactory(String aspName, String associationName) throws Exception {
314		AspFactory factory = this.getAspFactory(aspName);
315
316		if (factory != null) {
317			throw new Exception(String.format(M3UAOAMMessages.CREATE_ASP_FAIL_NAME_EXIST, aspName));
318		}
319
320		Association association = this.transportManagement.getAssociation(associationName);
321		if (association == null) {
322			throw new Exception(String.format("No Association found for name=%s", associationName));
323		}
324
325		if (association.isStarted()) {
326			throw new Exception(String.format("Association=%s is started", associationName));
327		}
328
329		if (association.getAssociationListener() != null) {
330			throw new Exception(String.format("Association=%s is already associated", associationName));
331		}
332
333		factory = new AspFactory(aspName);
334		factory.setAssociation(association);
335		factory.setTransportManagement(this.transportManagement);
336
337		aspfactories.add(factory);
338
339		this.store();
340
341		return factory;
342	}
343
344	public AspFactory destroyAspFactory(String aspName) throws Exception {
345		AspFactory aspFactroy = this.getAspFactory(aspName);
346		if (aspFactroy == null) {
347			throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_NO_ASP, aspName));
348		}
349
350		if (aspFactroy.getAspList().size() != 0) {
351			throw new Exception("Asp are still assigned to As. Unassign all");
352		}
353		aspFactroy.unsetAssociation();
354		this.aspfactories.remove(aspFactroy);
355		this.store();
356
357		return aspFactroy;
358	}
359
360	/**
361	 * Associate {@link Asp} to {@link As}
362	 * 
363	 * @param asName
364	 * @param aspName
365	 * @return
366	 * @throws Exception
367	 */
368	public Asp assignAspToAs(String asName, String aspName) throws Exception {
369		// check ASP and AS exist with given name
370		As as = this.getAs(asName);
371
372		if (as == null) {
373			throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_NO_AS, asName));
374		}
375
376		AspFactory aspFactroy = this.getAspFactory(aspName);
377
378		if (aspFactroy == null) {
379			throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_NO_ASP, aspName));
380		}
381
382		// If ASP already assigned to AS we don't want to re-assign
383		for (FastList.Node<Asp> n = as.getAspList().head(), end = as.getAspList().tail(); (n = n.getNext()) != end;) {
384			Asp asp = n.getValue();
385			if (asp.getName().equals(aspName)) {
386				throw new Exception(String.format(
387						"Cannot assign ASP=%s to AS=%s. This ASP is already assigned to this AS", aspName, asName));
388			}
389		}
390
391		FastList<Asp> asps = aspFactroy.getAspList();
392
393		// Checks for RoutingContext. We know that for null RC there will always
394		// be a single ASP assigned to AS and ASP cannot be shared
395		if (as.getRoutingContext() == null) {
396			// If AS has Null RC, this should be the first assignment of ASP to
397			// AS
398			if (asps.size() != 0) {
399				throw new Exception(String.format(
400						"Cannot assign ASP=% to AS=%. This ASP is already assigned to other AS.", aspName, asName));
401			}
402		} else if (asps.size() > 0) {
403			// RoutingContext is not null, make sure there is no ASP that is
404			// assigned to AS with null RC
405			Asp asp = asps.get(0);
406			if (asp != null && asp.getAs().getRoutingContext() == null) {
407				throw new Exception(
408						String.format(
409								"Cannot assign ASP=% to AS=%. This ASP is already assigned to other AS which has null RoutingContext.",
410								aspName, asName));
411			}
412		}
413
414		if (aspFactroy.getFunctionality() != null && aspFactroy.getFunctionality() != as.getFunctionality()) {
415			throw new Exception(String.format(
416					"Cannot assign ASP=% to AS=%. This ASP is already assigned to other AS of type=%s", aspName,
417					asName, aspFactroy.getFunctionality()));
418		}
419
420		if (aspFactroy.getExchangeType() != null && aspFactroy.getExchangeType() != as.getExchangeType()) {
421			throw new Exception(String.format(
422					"Cannot assign ASP=% to AS=%. This ASP is already assigned to other AS of ExchangeType=%s",
423					aspName, asName, aspFactroy.getExchangeType()));
424		}
425
426		if (aspFactroy.getIpspType() != null && aspFactroy.getIpspType() != as.getIpspType()) {
427			throw new Exception(String.format(
428					"Cannot assign ASP=% to AS=%. This ASP is already assigned to other AS of which has IPSP type=%s",
429					aspName, asName, aspFactroy.getIpspType()));
430		}
431
432		aspFactroy.setExchangeType(as.getExchangeType());
433		aspFactroy.setFunctionality(as.getFunctionality());
434		aspFactroy.setIpspType(as.getIpspType());
435
436		Asp asp = aspFactroy.createAsp();
437		FSM aspLocalFSM = asp.getLocalFSM();
438		m3uaScheduler.execute(aspLocalFSM);
439
440		FSM aspPeerFSM = asp.getPeerFSM();
441		m3uaScheduler.execute(aspPeerFSM);
442		as.addAppServerProcess(asp);
443
444		this.store();
445
446		return asp;
447	}
448
449	public Asp unassignAspFromAs(String asName, String aspName) throws Exception {
450		// check ASP and AS exist with given name
451		As as = this.getAs(asName);
452
453		if (as == null) {
454			throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_NO_AS, asName));
455		}
456
457		Asp asp = as.removeAppServerProcess(aspName);
458		asp.getAspFactory().destroyAsp(asp);
459		this.store();
460		return asp;
461	}
462
463	/**
464	 * This method should be called by management to start the ASP
465	 * 
466	 * @param aspName
467	 *            The name of the ASP to be started
468	 * @throws Exception
469	 */
470	public void startAsp(String aspName) throws Exception {
471		AspFactory aspFactory = this.getAspFactory(aspName);
472
473		if (aspFactory == null) {
474			throw new Exception(String.format("No ASP found by name=%s", aspName));
475		}
476
477		if (aspFactory.getStatus()) {
478			throw new Exception(String.format("ASP name=%s already started", aspName));
479		}
480
481		if (aspFactory.getAspList().size() == 0) {
482			throw new Exception(String.format("ASP name=%s not assigned to any AS yet", aspName));
483		}
484
485		aspFactory.start();
486		this.store();
487	}
488
489	/**
490	 * This method should be called by management to stop the ASP
491	 * 
492	 * @param aspName
493	 *            The name of the ASP to be stopped
494	 * @throws Exception
495	 */
496	public void stopAsp(String aspName) throws Exception {
497		AspFactory aspFactory = this.getAspFactory(aspName);
498
499		if (aspFactory == null) {
500			throw new Exception(String.format("No ASP found by name=%s", aspName));
501		}
502
503		if (!aspFactory.getStatus()) {
504			throw new Exception(String.format("ASP name=%s already stopped", aspName));
505		}
506
507		aspFactory.stop();
508		this.store();
509	}
510
511	public void addRoute(int dpc, int opc, int si, String asName) throws Exception {
512		this.routeManagement.addRoute(dpc, opc, si, asName);
513	}
514
515	public void removeRoute(int dpc, int opc, int si, String asName) throws Exception {
516		this.routeManagement.removeRoute(dpc, opc, si, asName);
517	}
518
519	public void sendTransferMessageToLocalUser(Mtp3TransferPrimitive msg, int seqControl) {
520		super.sendTransferMessageToLocalUser(msg, seqControl);
521	}
522
523	public void sendPauseMessageToLocalUser(Mtp3PausePrimitive msg) {
524		super.sendPauseMessageToLocalUser(msg);
525	}
526
527	public void sendResumeMessageToLocalUser(Mtp3ResumePrimitive msg) {
528		super.sendResumeMessageToLocalUser(msg);
529	}
530
531	public void sendStatusMessageToLocalUser(Mtp3StatusPrimitive msg) {
532		super.sendStatusMessageToLocalUser(msg);
533	}
534
535	private AspFactory getAspFactory(String aspName) {
536		for (FastList.Node<AspFactory> n = aspfactories.head(), end = aspfactories.tail(); (n = n.getNext()) != end;) {
537			AspFactory aspFactory = n.getValue();
538			if (aspFactory.getName().equals(aspName)) {
539				return aspFactory;
540			}
541		}
542		return null;
543	}
544
545	/**
546	 * Persist
547	 */
548	public void store() {
549
550		// TODO : Should we keep reference to Objects rather than recreating
551		// everytime?
552		try {
553			XMLObjectWriter writer = XMLObjectWriter.newInstance(new FileOutputStream(persistFile.toString()));
554			writer.setBinding(binding);
555			// Enables cross-references.
556			// writer.setReferenceResolver(new XMLReferenceResolver());
557			writer.setIndentation(TAB_INDENT);
558			writer.write(aspfactories, ASP_FACTORY_LIST, FastList.class);
559			writer.write(appServers, AS_LIST, FastList.class);
560			writer.write(this.routeManagement.route, DPC_VS_AS_LIST, RouteMap.class);
561
562			writer.close();
563		} catch (Exception e) {
564			logger.error("Error while persisting the Rule state in file", e);
565		}
566	}
567
568	/**
569	 * Load and create LinkSets and Link from persisted file
570	 * 
571	 * @throws Exception
572	 */
573	public void load() throws FileNotFoundException {
574
575		XMLObjectReader reader = null;
576		try {
577			reader = XMLObjectReader.newInstance(new FileInputStream(persistFile.toString()));
578
579			reader.setBinding(binding);
580			aspfactories = reader.read(ASP_FACTORY_LIST, FastList.class);
581			appServers = reader.read(AS_LIST, FastList.class);
582			this.routeManagement.route = reader.read(DPC_VS_AS_LIST, RouteMap.class);
583
584			// Create Asp's and assign to each of the AS. Schedule the FSM's
585			for (FastList.Node<As> n = appServers.head(), end = appServers.tail(); (n = n.getNext()) != end;) {
586				As as = n.getValue();
587				as.setM3UAManagement(this);
588				FSM asLocalFSM = as.getLocalFSM();
589				m3uaScheduler.execute(asLocalFSM);
590
591				FSM asPeerFSM = as.getPeerFSM();
592				m3uaScheduler.execute(asPeerFSM);
593
594				// All the Asp's for this As added in temp list
595				FastList<Asp> tempAsp = new FastList<Asp>();
596				tempAsp.addAll(as.getAspList());
597
598				// Claer Asp's from this As
599				as.getAspList().clear();
600
601				for (FastList.Node<Asp> n1 = tempAsp.head(), end1 = tempAsp.tail(); (n1 = n1.getNext()) != end1;) {
602					Asp asp = n1.getValue();
603
604					try {
605						// Now let the Asp's be created from respective
606						// AspFactory and added to As
607						this.assignAspToAs(as.getName(), asp.getName());
608					} catch (Exception e) {
609						logger.error("Error while assigning Asp to As on loading from xml file", e);
610					}
611				}
612			}
613
614			// Set the transportManagement
615			for (FastList.Node<AspFactory> n = aspfactories.head(), end = aspfactories.tail(); (n = n.getNext()) != end;) {
616				AspFactory factory = n.getValue();
617				factory.setTransportManagement(this.transportManagement);
618				try {
619					factory.setAssociation(this.transportManagement.getAssociation(factory.associationName));
620				} catch (Exception e1) {
621					logger.error(String.format(
622							"Error setting Assciation=%s for the AspFactory=%s while loading from XML",
623							factory.associationName, factory.getName()), e1);
624				}
625
626				if (factory.getStatus()) {
627					try {
628						factory.start();
629					} catch (Exception e) {
630						logger.error(
631								String.format("Error starting the AspFactory=%s while loading from XML",
632										factory.getName()), e);
633					}
634				}
635			}
636
637		} catch (XMLStreamException ex) {
638			// this.logger.info(
639			// "Error while re-creating Linksets from persisted file", ex);
640		}
641	}
642
643	@Override
644	public void sendMessage(Mtp3TransferPrimitive mtp3TransferPrimitive) throws IOException {
645		ProtocolData data = this.parameterFactory.createProtocolData(mtp3TransferPrimitive);
646		PayloadData payload = (PayloadData) messageFactory.createMessage(MessageClass.TRANSFER_MESSAGES,
647				MessageType.PAYLOAD);
648		payload.setData(data);
649
650		As as = this.routeManagement.getAsForRoute(data.getDpc(), data.getOpc(), data.getSI(), data.getSLS());
651		if (as == null) {
652			logger.error(String.format("Tx : No AS found for routing message %s", payload));
653			return;
654		}
655		payload.setNetworkAppearance(as.getNetworkAppearance());
656		payload.setRoutingContext(as.getRoutingContext());
657		as.write(payload);
658	}
659}