Java tutorial
/* * Copyright 2014 Napolov Dmitry * * 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.aotorrent.common.connection; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.channel.*; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.*; import org.aotorrent.common.TorrentEngine; import org.aotorrent.common.protocol.tracker.HTTPTrackerRequest; import org.aotorrent.common.protocol.tracker.HTTPTrackerResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.InetAddress; import java.net.URISyntaxException; import java.util.Date; /** * @author dmitry 13.08.14 8:23 */ public class HTTPTrackerConnection extends AbstractTrackerConnection { private static final Logger LOGGER = LoggerFactory.getLogger(HTTPTrackerConnection.class); private static final boolean COMPACT = true; private static final boolean NO_PEER_ID = true; private static final int NUM_WANT = 50; public HTTPTrackerConnection(TorrentEngine torrentEngine, String url, byte[] infoHash, byte[] peerId, InetAddress localIp, int localPort, EventLoopGroup group) throws URISyntaxException { super(torrentEngine, url, infoHash, peerId, localIp, localPort, group); } @Override protected void obtainPeers() { try { Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { final ChannelPipeline p = ch.pipeline(); p.addLast("codec-http", new HttpClientCodec()); p.addLast("aggregator", new HttpObjectAggregator(65536)); p.addLast("handler", new TrackerConnectionHandler()); } }); Channel ch = b.connect(address).sync().channel(); HTTPTrackerRequest trackerRequest = new HTTPTrackerRequest(uri, infoHash, peerId, localAddress.getPort(), 0, 0, 0, COMPACT, NO_PEER_ID, NUM_WANT, trackerId); HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, trackerRequest.createRequest()); final StringBuilder host = new StringBuilder().append(uri.getHost()); if (uri.getPort() > 0 && uri.getPort() != 80) { host.append(":").append(uri.getPort()); } request.headers().set(HttpHeaders.Names.HOST, host.toString()); request.headers().set(HttpHeaders.Names.USER_AGENT, "AOTorrent/0.1"); request.headers().set(HttpHeaders.Names.ACCEPT, "*/*"); request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE); ch.writeAndFlush(request); ch.closeFuture().sync(); } catch (InterruptedException e) { LOGGER.error("Tracker connection interrupted"); } } private class TrackerConnectionHandler extends SimpleChannelInboundHandler<FullHttpResponse> { @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse response) throws Exception { if (response.getStatus().code() != 200) { LOGGER.error("Tracker responded {} code", response.getStatus().code()); nextRequest = new Date(System.currentTimeMillis() + (300 * 1000)); ctx.close(); return; } try { ByteBuf content = response.content(); final HTTPTrackerResponse httpTrackerResponse = new HTTPTrackerResponse(content); LOGGER.debug("Got peers from tracker" + httpTrackerResponse.getPeers()); torrentEngine.appendPeers(httpTrackerResponse.getPeers()); trackerId = httpTrackerResponse.getTrackerId(); nextRequest = new Date(System.currentTimeMillis() + (httpTrackerResponse.getInterval() * 1000)); ctx.close(); } catch (Exception e) { nextRequest = new Date(System.currentTimeMillis() + (300 * 1000)); throw e; } } } }