org.aotorrent.common.connection.HTTPTrackerConnection.java Source code

Java tutorial

Introduction

Here is the source code for org.aotorrent.common.connection.HTTPTrackerConnection.java

Source

/*
 * 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;
            }
        }
    }
}