package com.limegroup.gnutella;
import java.net.InetSocketAddress;
import java.util.concurrent.Executor;
import org.limewire.listener.EventBroadcaster;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import com.limegroup.gnutella.connection.RoutedConnection;
import com.limegroup.gnutella.messages.Message;
/**
* Dispatches messages to the MessageRouter.
*/
@Singleton
public class MessageDispatcher {
private final Executor DISPATCH;
private final MessageRouter messageRouter;
private final EventBroadcaster<MessageSentEvent> messageSentEventBroadcaster;
@Inject
public MessageDispatcher(MessageRouter messageRouter, @Named("messageExecutor") Executor dispatch,
EventBroadcaster<MessageSentEvent> messageSentEventBroadcaster) {
this.messageRouter = messageRouter;
this.DISPATCH = dispatch;
this.messageSentEventBroadcaster = messageSentEventBroadcaster;
}
/** Dispatches a runnable, to allow arbitrary runnables to be processed on the message thread. */
public void dispatch(Runnable r) {
DISPATCH.execute(r);
}
/**
* Dispatches a UDP message.
*/
public void dispatchUDP(Message m, InetSocketAddress addr) {
DISPATCH.execute(new UDPDispatch(messageRouter, m, addr));
}
/**
* Dispatches a Multicast message.
*/
public void dispatchMulticast(Message m, InetSocketAddress addr) {
DISPATCH.execute(new MulticastDispatch(messageRouter, m, addr));
}
/**
* Dispatches a TCP message.
*/
public void dispatchTCP(Message m, RoutedConnection conn) {
DISPATCH.execute(new TCPDispatch(messageRouter, m, conn));
}
/**
* Dispatches the event that <code>message</code> was sent to <code>routedConnection</code>.
*/
public void dispatchTCPMessageSent(Message message, RoutedConnection routedConnection) {
messageSentEventBroadcaster.broadcast(new MessageSentEvent(routedConnection, message));
}
private static abstract class Dispatch implements Runnable {
protected final MessageRouter messageRouter;
protected final Message m;
Dispatch(MessageRouter messageRouter, Message m) {
this.messageRouter = messageRouter;
this.m = m;
}
public void run() {
dispatch();
}
protected abstract void dispatch();
}
private static class UDPDispatch extends Dispatch {
private final InetSocketAddress addr;
UDPDispatch(MessageRouter messageRouter,
Message m,
InetSocketAddress addr) {
super(messageRouter, m);
this.addr = addr;
}
@Override
protected void dispatch() {
messageRouter.handleUDPMessage(m, addr);
}
}
private static class MulticastDispatch extends Dispatch {
private final InetSocketAddress addr;
MulticastDispatch(MessageRouter messageRouter,
Message m,
InetSocketAddress addr) {
super(messageRouter, m);
this.addr = addr;
}
@Override
protected void dispatch() {
messageRouter.handleMulticastMessage(m, addr);
}
}
private static class TCPDispatch extends Dispatch {
private final RoutedConnection conn;
TCPDispatch(MessageRouter messageRouter,
Message m,
RoutedConnection conn) {
super(messageRouter, m);
this.conn = conn;
}
@Override
protected void dispatch() {
messageRouter.handleMessage(m, conn);
}
}
}