@Override
	protected void announce(AnnounceEvent event) {
		List<Peer> peers = new LinkedList<Peer>();
		
		try {
			boolean received = false;
			for (int rounds = 0; !received && rounds < MAX_ROUNDS; ++rounds) {
				
				int transaction_id = random.nextInt();
				byte[] msg = getRawAnnounceMessage(event, this.connection_id, transaction_id).array();
				DatagramPacket sentPacket = url.makePacket(msg);
				
				try {
					this.socket.send(sentPacket);
				} catch (IOException e) {
					e.printStackTrace();
					continue;
				}
				
				DatagramPacket packet = url.makePacket(new byte[65508]);
				try {
					this.socket.setSoTimeout((int) (15000 * Math.pow(2, rounds)));
					this.socket.receive(packet);
					
					if (packet.getLength() >= 20) {
						ByteBuffer buffer = ByteBuffer.wrap(packet.getData());
						int action = buffer.getInt();
						int received_tid = buffer.getInt();
						
						if (action == ACTION_ID_ANNOUNCE && received_tid == transaction_id) {
							
							int interval = buffer.getInt();
							this.next_allowed_announce = System.currentTimeMillis() + interval * 1000l;
							
							buffer.getInt(); // leechers
							buffer.getInt(); // seeders
							
							int remaining = packet.getLength() - 20;
							
							while (remaining >= 6) {
								byte[] ip = new byte[4];
								buffer.get(ip);
								short port = buffer.getShort();
								
								peers.add(new Peer(InetAddress.getByAddress(ip), port));
								remaining -= 6;
							}
							
							received = true;
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} catch (UnknownHostException ex) {
			ex.printStackTrace();
		}
		
		this.peers = peers.toArray(new Peer[peers.size()]);
	}