/** * SAMOA - PROTOCOL FRAMEWORK * Copyright (C) 2005 Olivier Rütti (EPFL) (olivier.rutti@a3.epfl.ch) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package seqSamoa.protocols.udp; import java.io.IOException; import java.io.OutputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.util.LinkedList; import seqSamoa.Message; import seqSamoa.ProtocolModule; import seqSamoa.ProtocolStack; import seqSamoa.Service; import seqSamoa.ServiceCallOrResponse; import seqSamoa.exceptions.AlreadyExistingProtocolModuleException; import seqSamoa.services.udp.UDP; import seqSamoa.services.udp.UDPCallParameters; import framework.libraries.DefaultSerialization; /** * This class implement a Protocol that allow to send Object through UDP * * The service implemented is udp (described in util/Services.java) */ public class ProtocolUDP extends ProtocolModule implements Runnable { // Service provided private UDP udp; // Max length for a datagram packet private static final int MAX_PACKET_LENGTH = 1024 * 30; // UDP socket to send/receive private DatagramSocket dsock = null; // True if the thread is running private boolean open = true; // A thread to listen on the UDP socket private Thread thread; // The Executer // It send a message with udp protected Service<UDPCallParameters, Object>.Executer udpExecuter; /** * Constructor. <br> * * @param name * Name of the layer * @param port * The port to listen */ public ProtocolUDP(String name, ProtocolStack stack, UDP udp) throws AlreadyExistingProtocolModuleException { // Initialises the microprotocol super(name, stack); this.udp = udp; // Initialize the Executer LinkedList<ServiceCallOrResponse> initiatedUdp = new LinkedList<ServiceCallOrResponse>(); udpExecuter = this.udp.new Executer(this, initiatedUdp) { public void evaluate(UDPCallParameters params, Message dmessage) { synchronized (this.parent) { try { // Writes and sends the object byte[] b = DefaultSerialization.marshall(dmessage); if (b.length > MAX_PACKET_LENGTH) { throw new RuntimeException("ProtocolUDP : Trying" + " to send a packet too" + " long." + dmessage); } DatagramPacket pack = new DatagramPacket(b, b.length, params.pid.ip, params.pid.port); dsock.send(pack); } catch (IOException e) { throw new RuntimeException("ProtocolUDP: udpExecuter: " + "IOException: " + e.getMessage()); } } } }; // Creates a new datagram socket. try { dsock = new DatagramSocket(stack.getPID().port); } catch (IOException ex) { throw new RuntimeException( "ProtocolUDP : IOException : Failed to create a datagram socket."); } } /** * Overload the close function of Protocol */ synchronized public void close() { open = false; super.close(); } synchronized public void dump(OutputStream stream) { } /** * Enable reception of message in starting a dedicated thread */ synchronized public void startListener() { thread = new Thread(this); thread.setDaemon(true); thread.start(); } /** * Thread that will listen to the network and detect reception of UDP * messages */ public void run() { try { while (open) { // Creates a new bytes array byte[] b = new byte[MAX_PACKET_LENGTH]; // Creates a UDP packet for receiving a packet. // Max size: MAX_PACKET_LENGTH DatagramPacket pack = new DatagramPacket(b, b.length); // Reads a packet. dsock.receive(pack); // Reads the object Message message = (Message) DefaultSerialization .unmarshall(b); if (open) udp.externalResponse(null, message); } // while (open) dsock.close(); } catch (IOException ex) { throw new RuntimeException("MicroUDP : run : IOException"); } catch (ClassNotFoundException e) { throw new RuntimeException( "MicroUDP : run : ClassNotFoundException : Class read from the socket was not found"); } } }