Package programming5.net.sockets

Source Code of programming5.net.sockets.UDPReceiver

/*
* UDPReceiver.java
*
* Copyright 2004 Andres Quiroz Hernandez
*
* This file is part of Programming5.
* Programming5 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 3 of the License, or
* (at your option) any later version.
*
* Programming5 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 Programming5.  If not, see <http://www.gnu.org/licenses/>.
*
*/

package programming5.net.sockets;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import programming5.arrays.ArrayOperations;
import programming5.io.Debug;
import programming5.net.AsynchMessageArrivedEvent;
import programming5.net.MessageArrivedEvent;
import programming5.net.Publisher;
import programming5.net.ReceivingThread;

/**
*This class complements the UDPClient class as a constant listener to the socket
*@see programming5.net.sockets.UDPClient
*@author Andres Quiroz Hernandez
*@version 6.19
*/
public class UDPReceiver extends ReceivingThread {
   
    protected DatagramSocket socket;
    protected InetAddress lastAddress = null;
    protected int lastPort = NO_PORT;
    private final int PACKET_SIZE = 65536;
    private boolean listening = true;

    private Map<String, byte[][]> assembly = new HashMap<String, byte[][]>();
    private Map<String, boolean[]> assemblyCounter = new HashMap<String, boolean[]>();
   
    public static final int NO_PORT = -1;
   
    public UDPReceiver(Publisher<MessageArrivedEvent> myReference, DatagramSocket mySocket) {
        super(myReference);
        socket = mySocket;
    }
   
    @Override
    public void run() {
        byte[] buf = new byte[PACKET_SIZE];
        byte[] bytesMessage;
        DatagramPacket p = null;
        while (listening) {
            p = new DatagramPacket(buf, buf.length);
            bytesMessage = null;
            try {
                socket.receive(p);
                String streamID = depacketize(p);
                if (streamID != null) {    // Message is completely received (all packets)
                    lastAddress = p.getAddress();
                    lastPort = p.getPort();
                    Debug.println("Received streamID: " + streamID, "programming5.net.sockets.UDPClient");
                    byte[][] toAssemble = assembly.get(streamID);
                    assembly.remove(streamID);
                    bytesMessage = assemble(toAssemble);
                    ref.fireEvent(new AsynchMessageArrivedEvent(bytesMessage, "//" + lastAddress.getHostAddress() + ":" + Integer.toString(lastPort)));
                }
                buf = new byte[PACKET_SIZE];
            }
            catch (IOException io) {
                if (listening) {
                    System.out.println("UDPReceiver: Error while receiving: " + io.getMessage());
                    listening = false;
                }
            }
        }
    }

    /**
     * @return the last address from which a message was received
     * @deprecated One of two methods to obtain a full address, in between which another message could be
     * received and the address could change; use getReplyAddress instead, which returns a URL
     */
    @Deprecated
    public InetAddress getLastAddress() {
        return lastAddress;
    }

    /**
     * @return the last port from which a message was received
     * @deprecated One of two methods to obtain a full address, in between which another message could be
     * received and the address could change; use getReplyAddress instead, which returns a URL string
     */
    @Deprecated
    public int getLastPort() {
        return lastPort;
    }

    /**
     * @return the last address from which a message was received; if no message was received when called,
     * null will be returned.
     */
    public String getReplyAddress() {
        String ret = null;
        try {
            if (lastAddress != null) {
                ret = new URI("//" + lastAddress.getHostAddress() + ":" + Integer.toString(lastPort)).toString();
            }
        }
        catch (URISyntaxException use) {}
        finally {
            return ret;
        }
    }
   
    protected void end() {
        listening = false;
    }

    private String depacketize(DatagramPacket packet) {
        int packetSize = packet.getLength();
        byte[] bytesMessage;
        String ret = null;
        if (packetSize > 0) {
            InetAddress host = packet.getAddress();
            bytesMessage = packet.getData();
            bytesMessage = ArrayOperations.prefix(bytesMessage, packetSize);
            int separatorIndex = ArrayOperations.seqFind(UDPClient.SEPARATOR.getBytes()[0], bytesMessage);
            if (separatorIndex > 0) {
                String sequenceString = new String(ArrayOperations.subArray(bytesMessage, 0, separatorIndex));
                String[] numbers = sequenceString.split("/");
                String streamID = host.getHostAddress() + "/" + numbers[0];
                byte[][] parts = assembly.get(streamID);
                if (parts == null) {
                    int total = Integer.parseInt(numbers[2]);
                    parts = new byte[total][];
                    assembly.put(streamID, parts);
                    boolean[] counter = new boolean[total];
                    ArrayOperations.initialize(counter, false);
                    assemblyCounter.put(streamID, counter);
                }
                int index = Integer.parseInt(numbers[1]);
                parts[index-1] = ArrayOperations.suffix(bytesMessage, separatorIndex+1);
                boolean[] progress = assemblyCounter.get(streamID);
                progress[index-1] = true;
                if (ArrayOperations.tautology(progress)) {
                    ret = streamID;
                    assemblyCounter.remove(streamID);
                }
            }
            else {
                int start = (separatorIndex == 0) ? 1 : 0;
                byte[][] parts = new byte[1][];
                parts[0] = ArrayOperations.suffix(bytesMessage, start);
                ret = host.getHostAddress();
                assembly.put(ret, parts);
            }
        }
        return ret;
    }

    private byte[] assemble(byte[][] parts) {
        int size = 0;
        for (byte[] part : parts) {
            size += part.length;
        }
        byte[] ret = new byte[size];
        int place = 0;
        for (int i = 0; i < parts.length; i++) {
            for (int j = 0; j < parts[i].length; j++) {
                ret[place++] = parts[i][j];
            }
        }
        return ret;
    }

}
TOP

Related Classes of programming5.net.sockets.UDPReceiver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.