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

Java tutorial

Introduction

Here is the source code for org.aotorrent.common.connection.UDPTrackerConnection.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.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import org.aotorrent.common.TorrentEngine;
import org.aotorrent.common.protocol.tracker.UDPAnnounceReply;
import org.aotorrent.common.protocol.tracker.UDPAnnounceRequest;
import org.aotorrent.common.protocol.tracker.UDPConnectReply;
import org.aotorrent.common.protocol.tracker.UDPConnectRequest;

import java.net.InetAddress;
import java.net.URISyntaxException;
import java.util.Date;

public class UDPTrackerConnection extends AbstractTrackerConnection {

    private int transactionId;

    public UDPTrackerConnection(TorrentEngine torrentEngine, String url, byte[] infoHash, byte[] peerId,
            InetAddress ip, int port) throws URISyntaxException {
        super(torrentEngine, url, infoHash, peerId, ip, port, null);
    }

    @Override
    protected void obtainPeers() {
        try {
            EventLoopGroup group = new NioEventLoopGroup();

            Bootstrap b = new Bootstrap();

            b.group(group).channel(NioDatagramChannel.class).handler(new ChannelInitializer<DatagramChannel>() {
                @Override
                protected void initChannel(DatagramChannel ch) throws Exception {
                    final ChannelPipeline p = ch.pipeline();
                    p.addLast(new TrackerConnectionHandler());
                }
            });

            Channel ch = b.bind(0).sync().channel();

            transactionId = RANDOM.nextInt();
            LOGGER.debug("Sending connect request to " + address);
            ch.writeAndFlush(new DatagramPacket(new UDPConnectRequest(transactionId).toTransmit(), address));

            ch.closeFuture().sync();
        } catch (InterruptedException e) {
            LOGGER.error("Tracker connection interrupted");
        }

    }

    private class TrackerConnectionHandler extends SimpleChannelInboundHandler<DatagramPacket> {

        private long connectionId;

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket datagram) throws Exception {

            final ByteBuf data = datagram.content();

            final int action = data.getInt(0);

            switch (action) {
            case 0:
                final UDPConnectReply connectReply = new UDPConnectReply(data);
                if (connectReply.getTransactionId() != transactionId) {
                    return;
                }
                connectionId = connectReply.getConnectionId();
                LOGGER.debug("Got connect reply with connectionId = " + connectionId
                        + "Sending announce request to " + address);
                sendAnnounceRequest(ctx);
                break;
            case 1:
                final UDPAnnounceReply announceReply = new UDPAnnounceReply(data);
                if (announceReply.getTransactionId() != transactionId) {
                    return;
                }
                nextRequest = new Date(System.currentTimeMillis() + (announceReply.getInterval() * 1000));
                LOGGER.debug("Got peers from tracker" + announceReply.getPeers());
                torrentEngine.appendPeers(announceReply.getPeers());
                ctx.close();
            }
        }

        private void sendAnnounceRequest(ChannelHandlerContext ctx) {
            transactionId = RANDOM.nextInt();
            UDPAnnounceRequest request = new UDPAnnounceRequest(connectionId, transactionId, infoHash, peerId,
                    downloaded, left, uploaded, 2, localAddress.getPort());
            ctx.writeAndFlush(new DatagramPacket(request.toTransmit(), address));
        }
    }
}