/* * Copyright (C) 2000 - 2008 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://www.openbluedragon.org/ */ /* * CFMULTICAST * * Sends and receives messages on a multicast network * * Listen for messages: * <cfmulticast action="listen" address="224.1.1.1" port="5600" * cfc="cfc" cfcfunction="testMethod"> * the CFC function must define the argument 'data' to receive the * message itself. 'data' will be a structure with various meta * data inside it to show destination. * * Send a CFML structure * <cfmulticast action="send" address="224.1.1.1" port="5600" * cfmldata="#cgi#"> * * Send a text message * <cfmulticast action="send" address="224.1.1.1" port="5600" * textdata="this is a test"> * * Status * <cfmulticast action="status" address="224.1.1.1" port="5600"> * returns back an structure called 'cfmulticast' that has various * counters in it * * Stop Listening on a given multicast address * <cfmulticast action="stop" address="224.1.1.1" port="5600"> * * * Notes: * - address attribute is a multicast address 224.0.0.0+ * * - Bind address is configured in the bluedragon.xml * server.cfmulticast.bindaddress * defaults to all interfaces if not present * * - Individual messages can't be greater than 64KB in size * * - Log file tracks incoming and outgoing messages; multicast.log * * - Works across .NET and J2EE; can interchange messages */ package com.naryx.tagfusion.cfm.tag.net; import java.io.File; import java.io.Serializable; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; import com.nary.io.FileUtils; import com.nary.util.LogFile; import com.naryx.tagfusion.cfm.engine.cfEngine; import com.naryx.tagfusion.cfm.engine.cfNumberData; import com.naryx.tagfusion.cfm.engine.cfSession; import com.naryx.tagfusion.cfm.engine.cfStructData; import com.naryx.tagfusion.cfm.engine.cfmBadFileException; import com.naryx.tagfusion.cfm.engine.cfmRunTimeException; import com.naryx.tagfusion.cfm.tag.cfTag; import com.naryx.tagfusion.cfm.tag.cfTagReturnType; import com.naryx.tagfusion.cfm.tag.awt.MultiCastManager; import com.naryx.tagfusion.cfm.wddx.cfWDDX; import com.naryx.tagfusion.xmlConfig.xmlCFML; public class cfMULTICAST extends cfTag implements Serializable { static final long serialVersionUID = 1; static private Map<String, MultiCastManager> MulticastManagers = new HashMap<String, MultiCastManager>(); static private String bindAddress; public static void init(xmlCFML configFile) { LogFile.open("MultiCast", new File(cfEngine.thisPlatform.getFileIO().getTempDirectory(), "multicast.log").toString()); bindAddress = configFile.getString("server.cfmulticast.bindaddress", "0.0.0.0" ); // default value is loopback IP address } // ---------------------------------- public void defaultParameters(String _tag) throws cfmBadFileException { defaultAttribute("ACTION", "SEND"); defaultAttribute("ADDRESS", "224.1.1.1"); defaultAttribute("PORT", "14141"); parseTagHeader(_tag); // -- Make sure the parameters are available for listening if (!containsAttribute("ACTION")) throw newBadFileException("Missing Attribute", "CFMULTICAST requires the ACTION attribute"); } // ---------------------------------- public cfTagReturnType render(cfSession _Session) throws cfmRunTimeException { try { String ACTION = getDynamic(_Session, "ACTION").getString().toUpperCase(); String address = getDynamic(_Session, "ADDRESS").getString(); int port = getDynamic(_Session, "PORT").getInt(); MultiCastManager manager = getManager(_Session, address, port); if (ACTION.equals("SEND")) { String data = ""; if (containsAttribute("CFMLDATA")){ data = cfWDDX.cfml2Wddx( getDynamic(_Session, "CFMLDATA")); }else if (containsAttribute("TEXTDATA")){ data = getDynamic(_Session, "TEXTDATA").getString(); } else throw newRunTimeException("Specify either CFMLDATA or TEXTDATA to send"); //-- Check the size of the data packet if (data.length() > 64000) throw newRunTimeException("Data Size must be less than 64KB. Packet=" + data.length() + " bytes"); manager.broadcastData(data); } else if (ACTION.equals("LISTEN")) { if (!containsAttribute("CFC") || !containsAttribute("CFCFUNCTION")) throw newRunTimeException("Specify both CFC and CFCFUNCTION attributes"); String cfc = getDynamic(_Session, "CFC").getString(); String cfcmethod = getDynamic(_Session, "CFCFUNCTION").getString(); String webServerRoot = FileUtils.getRealPath( _Session.REQ, "/" ); manager.registerReceiver(cfc, cfcmethod, webServerRoot); } else if (ACTION.equals("STOP")) { manager.stopReceiving(); } else if (ACTION.equals("STATUS")) { cfStructData mess = new cfStructData(); mess.setData("messages_in", new cfNumberData(manager.getMessagesRxd())); mess.setData("messages_out", new cfNumberData(manager.getMessagesTxd())); mess.setData("bytes_in", new cfNumberData(manager.getBytesRxd())); mess.setData("bytes_out", new cfNumberData(manager.getBytesTxd())); _Session.setData("cfmulticast", mess); } } catch (SecurityException secExc) { throw newRunTimeException("CFMULTICAST is not supported when the SecurityPermission UnmanagedCode attribute is not set. ("+secExc+")"); } return cfTagReturnType.NORMAL; } private synchronized MultiCastManager getManager( cfSession _session, String address, int port ) throws cfmRunTimeException{ MultiCastManager manager = MulticastManagers.get( address + ":" + port ); if ( manager == null ){ try { manager = new MultiCastManager( bindAddress, address, port ); } catch (UnknownHostException e) { throw newRunTimeException( "Failed to open multicast address " + address ); } MulticastManagers.put( address + ":" + port, manager ); } return manager; } }