/**
*
*/
package com.limegroup.gnutella.downloader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import junit.framework.Assert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.limewire.concurrent.ManagedThread;
import org.limewire.io.GUID;
import org.limewire.net.SocketsManager;
import org.limewire.service.ErrorService;
import org.limewire.util.DebugRunnable;
import com.limegroup.gnutella.helpers.UrnHelper;
import com.limegroup.gnutella.messages.BadPacketException;
import com.limegroup.gnutella.messages.Message;
import com.limegroup.gnutella.messages.MessageFactory;
import com.limegroup.gnutella.messages.PushRequest;
import com.limegroup.gnutella.messages.Message.Network;
import com.limegroup.gnutella.messages.vendor.HeadPing;
import com.limegroup.gnutella.messages.vendor.HeadPong;
import com.limegroup.gnutella.messages.vendor.HeadPongFactory;
class TestUDPAcceptor implements Runnable {
private static final Log LOG = LogFactory.getLog(TestUDPAcceptor.class);
private int _portC;
private DatagramSocket sock;
private String _fileName;
private TestUploader _uploader;
private GUID _g;
public boolean sentGIV;
private boolean noFile;
public int pings;
private volatile boolean shutdown;
private final SocketsManager socketsManager;
private final MessageFactory messageFactory;
private final HeadPongFactory headPongFactory;
private final Thread runningThread;
TestUDPAcceptor(SocketsManager socketsManager, MessageFactory messageFactory, HeadPongFactory headPongFactory, int port, String testMethod) {
this.socketsManager = socketsManager;
this.messageFactory = messageFactory;
this.headPongFactory = headPongFactory;
noFile = true;
try {
sock = new DatagramSocket(port);
// sock.connect(InetAddress.getLocalHost(),portC);
sock.setSoTimeout(15000);
} catch (IOException bad) {
ErrorService.error(bad);
}
this.runningThread = new ManagedThread(new DebugRunnable(this), "unnamed UDP Acceptor in method: " + testMethod);
runningThread.start();
}
TestUDPAcceptor(SocketsManager socketsManager, MessageFactory messageFactory, HeadPongFactory headPongFactory, int portL, int portC, String filename, TestUploader uploader, GUID g, String testMethod) {
this.socketsManager = socketsManager;
this.messageFactory = messageFactory;
this.headPongFactory = headPongFactory;
_portC = portC;
_fileName = filename;
_uploader = uploader;
_g = g;
try {
sock = new DatagramSocket(portL);
// sock.connect(InetAddress.getLocalHost(),portC);
sock.setSoTimeout(15000);
} catch (IOException bad) {
ErrorService.error(bad, testMethod);
}
this.runningThread = new ManagedThread(new DebugRunnable(this), "push acceptor " + portL + "->" + portC + " in method: " + testMethod);
runningThread.setPriority(Thread.MAX_PRIORITY);
runningThread.start();
}
public void shutdown() {
shutdown = true;
runningThread.interrupt();
}
@Override
public void run() {
DatagramPacket p = new DatagramPacket(new byte[1024], 1024);
Message m = null;
try {
LOG.debug("listening for push request on " + sock.getLocalPort());
while (true) {
sock.receive(p);
ByteArrayInputStream bais = new ByteArrayInputStream(p.getData());
m = messageFactory.read(bais, Network.TCP);
LOG.debug("received " + m.getClass() + " no file? " + noFile);
if (noFile) {
if (m instanceof HeadPing)
handleNoFile(p.getSocketAddress(), new GUID(m.getGUID()));
continue;
} else if (m instanceof HeadPing)
continue;
else
break;
}
Assert.assertTrue(m instanceof PushRequest);
LOG.debug("received a push request");
Socket s = socketsManager.connect(new InetSocketAddress("127.0.0.1", _portC), 500);
OutputStream os = s.getOutputStream();
String GIV = "GIV 0:" + _g.toHexString() + "/" + _fileName + "\n\n";
os.write(GIV.getBytes());
os.flush();
LOG.debug("wrote GIV");
sentGIV = true;
_uploader.setSocket(s);
} catch (BadPacketException bad) {
throw new RuntimeException(bad);
} catch (InterruptedIOException stop){
if (!shutdown) {
throw new RuntimeException(stop);
}
} catch (IOException bad) {
throw new RuntimeException(bad);
} finally {
sock.close();
}
}
private void handleNoFile(SocketAddress from, GUID g) {
HeadPing ping = new HeadPing(g, UrnHelper.SHA1, 0);
HeadPong pong = headPongFactory.create(ping);
Assert.assertFalse(pong.hasFile());
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
pong.write(baos);
DatagramPacket pack = new DatagramPacket(baos.toByteArray(),
baos.toByteArray().length, from);
sock.send(pack);
pings++;
} catch (IOException e) {
throw new RuntimeException(e);
}
LOG.debug("sent a NoFile headPong to " + from);
}
}