package org.apache.haox.transport.udp; import org.apache.haox.event.Event; import org.apache.haox.event.EventType; import org.apache.haox.transport.Transport; import org.apache.haox.transport.TransportHandler; import org.apache.haox.transport.event.TransportEvent; import org.apache.haox.transport.event.TransportEventType; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.util.HashMap; import java.util.Map; public class UdpTransportHandler extends TransportHandler { protected Map<InetSocketAddress, UdpTransport> transports = new HashMap<InetSocketAddress, UdpTransport>(); @Override public EventType[] getInterestedEvents() { return new EventType[] { UdpEventType.CHANNEL_READABLE, TransportEventType.TRANSPORT_WRITABLE, TransportEventType.TRANSPORT_READABLE, TransportEventType.NEW_TRANSPORT }; } @Override protected void doHandle(Event event) throws Exception { EventType eventType = event.getEventType(); if (eventType == UdpEventType.CHANNEL_READABLE) { UdpChannelEvent ce = (UdpChannelEvent) event; DatagramChannel channel = ce.getChannel(); doRead(channel); } else if (eventType == TransportEventType.TRANSPORT_READABLE) { TransportEvent te = (TransportEvent) event; Transport transport = te.getTransport(); transport.onReadable(); } else if (eventType == TransportEventType.TRANSPORT_WRITABLE) { TransportEvent te = (TransportEvent) event; Transport transport = te.getTransport(); transport.onWriteable(); } else if (eventType == TransportEventType.NEW_TRANSPORT) { TransportEvent te = (TransportEvent) event; Transport transport = te.getTransport(); if (transport instanceof UdpTransport) { InetSocketAddress remoteAddress = transport.getRemoteAddress(); if (! transports.containsKey(remoteAddress)) { transports.put(remoteAddress, (UdpTransport) transport); } } } } private void doRead(DatagramChannel channel) throws IOException { ByteBuffer recvBuffer = ByteBuffer.allocate(65536); // to optimize InetSocketAddress fromAddress = (InetSocketAddress) channel.receive(recvBuffer); if (fromAddress != null) { recvBuffer.flip(); UdpTransport transport = transports.get(fromAddress); if (transport == null) { // should be from acceptor transport = new UdpTransport(channel, fromAddress); transport.setDispatcher(getDispatcher()); dispatch(TransportEvent.createNewTransportEvent(transport)); } transport.onRecvData(recvBuffer); } } @Override public void helpHandleSelectionKey(SelectionKey selectionKey) throws IOException { DatagramChannel channel = (DatagramChannel) selectionKey.channel(); if (selectionKey.isReadable()) { dispatch(UdpChannelEvent.makeReadableChannelEvent(channel)); } else if (selectionKey.isWritable()) { dispatch(UdpChannelEvent.makeWritableChannelEvent(channel)); } // Udp channel is always writable, so not usable selectionKey.interestOps(SelectionKey.OP_READ); } }