/* * bitlet - Simple bittorrent library * Copyright (C) 2008 Alessandro Bahgat Shehata, Daniele Castagna * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.bitlet.wetorrent.peer; import java.io.DataInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.URL; import java.net.UnknownHostException; import java.util.Random; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; import java.util.logging.Logger; import org.bitlet.wetorrent.peer.message.Message; import org.bitlet.wetorrent.peer.message.Request; import org.bitlet.wetorrent.util.thread.InterruptableTasksThread; import org.bitlet.wetorrent.util.thread.ThreadTask; /** * * @author Alex */ public class WebSeed implements Peer{ private URL url; private HttpURLConnection connection; private InterruptableTasksThread downloaderThread; private final BlockingQueue<Request> pendingRequests = new LinkedBlockingQueue<Request>();; private final static Request requestEnd = new Request(Integer.MAX_VALUE, 0, 0); private PeersManager peersManager; private byte[] peerId = new byte[20]; private byte[] bitfield; private long downloaded = 0; public WebSeed(URL url, PeersManager peersManager) { this.url = url; this.peersManager = peersManager; bitfield = peersManager.getTorrent().getTorrentDisk().getBitfieldCopy(); for (int i = 0; i < bitfield.length; i++) bitfield[i] |= 0xFF; Random random = new Random(System.currentTimeMillis()); random.nextBytes(peerId); System.arraycopy("-WT-HTTP".getBytes(), 0, peerId, 0, 8); downloaderThread = new InterruptableTasksThread(); downloaderThread.addTask(new HttpRangeDownloader()); } public void requestEnd(){ pendingRequests.add(requestEnd); } public void start() { downloaderThread.start(); } public void interrupt(){ downloaderThread.interrupt(); } public void sendMessage(Message message) { if (message.getType() == Message.REQUEST){ pendingRequests.add((Request)message); } } public void setAmInterested(boolean b) { peersManager.getTorrent().unchoke(this); } public void setIsChoked(boolean b) {} public long getDownloaded() { return downloaded; } public InetAddress getIp() { InetAddress ia = null; try { ia = InetAddress.getByName(url.getHost()); } catch (UnknownHostException ex) { Logger.getLogger(WebSeed.class.getName()).log(Level.SEVERE, null, ex); } return ia; } public int getPort() { return url.getPort(); } public byte[] getPeerId() { return peerId; } public long getLastReceivedMessageMillis() { throw new UnsupportedOperationException("Not supported yet."); } public int getUnfulfilledRequestNumber() { return pendingRequests.size(); } public long getUploaded() { return 0; } public boolean hasPiece(int index) { return true; } public boolean isAmChoked() { return false; } public boolean isSeeder() { return true; } class HttpRangeDownloader implements ThreadTask { public boolean execute() throws Exception { Request nextRequest = pendingRequests.take(); if (nextRequest != requestEnd){ byte[] range = downloadRange(nextRequest); // XXX placeholder byteSink(range); return true; }else return false; } public void interrupt() { try { pendingRequests.put(requestEnd); } catch (InterruptedException ex) { Logger.getLogger(WebSeed.class.getName()).log(Level.SEVERE, null, ex); } } public void exceptionCaught(Exception e) { e.printStackTrace(); } @Deprecated public void exceptionCought(Exception e) { exceptionCaught(e); } private byte[] downloadRange(Request request) throws IOException { byte[] result = new byte[request.getLength()]; // TODO connection should be openend elsewhere connection = (HttpURLConnection) url.openConnection(); connection.setRequestProperty("Connection", "Keep-Alive"); connection.setRequestProperty("Range", "bytes=" + request.getBegin() + "-" + (request.getBegin() + request.getLength() - 1)); System.out.println("Range: bytes=" + request.getBegin() + "-" + (request.getBegin() + request.getLength() - 1)); connection.connect(); int response = connection.getResponseCode(); DataInputStream is = new DataInputStream(connection.getInputStream()); if (response == HttpURLConnection.HTTP_ACCEPTED || response == HttpURLConnection.HTTP_OK || response == HttpURLConnection.HTTP_PARTIAL) { is.readFully(result, 0, request.getLength()); } is.close(); return result; } } // public static void main(String[] args) throws Exception { // final int TOT_SIZE = 22636132; // final int BLOCK_SIZE = 1024; // // URL theUrl = new URL("http://nofatclips.com/02009/01/21/magic/Preproduction.ogv"); // // WebSeed seed = new WebSeed(theUrl); // // HttpURLConnection conn = (HttpURLConnection) theUrl.openConnection(); // // conn.connect(); // InputStream is = conn.getInputStream(); // // FileOutputStream fos = new FileOutputStream("/Users/Alex/Desktop/target.ogv"); // // byte[] buf = new byte[BLOCK_SIZE]; // int len = 0; // int offset = 0; // // while ((len = is.read(buf)) > 0) { // fos.write(buf, 0, len); // offset += len; // // System.out.println("offset: " + offset); // } // // is.close(); // fos.close(); // conn.disconnect(); // } static FileOutputStream fos; static int wrote = 0; private void byteSink(byte[] stuff) throws Exception { fos.write(stuff); wrote += stuff.length; System.out.println("wrote: " + wrote); if (wrote == TOT_SIZE) { fos.close(); } } // static final int TOT_SIZE = 422279; static final int TOT_SIZE = 3576986; /* public static void main(String[] args) throws Exception { final int BLOCK_SIZE = 1 << 19; URL theUrl = new URL("http://nofatclips.com/02009/01/21/magic/Preproduction.ogv"); fos = new FileOutputStream("/Users/casta/Desktop/target.ogv"); // URL theUrl = new URL("http://www.ietf.org/rfc/rfc2616.txt"); // fos = new FileOutputStream("/Users/Alex/Desktop/target.txt"); WebSeed seed = new WebSeed(theUrl); int i = 0; int offset = 0; int length = BLOCK_SIZE; // splittone while (offset < TOT_SIZE) { if (offset + length > TOT_SIZE) length = TOT_SIZE - offset; seed.requestPiece(i, offset, length); offset += length; } seed.requestEnd(); seed.start(); } */ }