private void Download(ByteBuffer packet) throws IOException {
		// NO HEADER
		
		// allow only 1 download at a time, clear old threads
		for (ServerFwding f : peer_threads){
			if (f.isAlive())
				f.interrupt();
		}
		peer_threads.clear();
		
		//parse the req
		if (packet.capacity() < 4)
			throw new RuntimeException(
					"download request invalid");
		
		int buf_id = packet.getInt(0);
		
		Map<ClientObj, Integer> clients_with_file = new HashMap<ClientObj, Integer>();
		for (ClientObj c : clients){
			if (c.hasFile(buf_id) && c.getId() != client.getId())
				clients_with_file.put(c, 0);
		}
		
		// ask each client to prepare a port
		for (ClientObj c : clients_with_file.keySet()) {
			//open connection with clients listener
			Socket peerConnection = c.getListenerSocket();
			OutputStream out_c = new BufferedOutputStream(peerConnection.getOutputStream());
			
			//construct packet
			//(for connect to a peer conn s->c) [header | file_id (4) | peer id (4) | port num]
			int peer_server_port = Utility.getValidPort();
			buf = Utility.addHeader(Constants.PREPARE, 12, c.getId());
			buf.putInt(Constants.HEADER_LEN, buf_id);
			buf.putInt(Constants.HEADER_LEN + 4, client.getId());
			buf.putInt(Constants.HEADER_LEN + 8, peer_server_port);
			byte[] sendData = buf.array();
			
			// send response
			out_c.write(sendData);
			out_c.flush();
			System.out.println(client.getAddress() + 
					": sent peer client data (with server port " +peer_server_port+").");
			
			try {
				int client_server_port = Utility.getValidPort();
				ServerFwding peer_thread = new ServerFwding(
						client_server_port, c.getId(), peer_server_port, buf_id);
				peer_thread.start();
				
				// send peer info to client, await connection on thread
				buf = Utility.addHeader(Constants.DOWNLOAD_REQ, 8, client.getId());
				buf.putInt(Constants.HEADER_LEN, client_server_port);
				buf.putInt(Constants.HEADER_LEN + 4, c.getId());
				sendData = buf.array();
				out.write(sendData);
				out.flush();
				System.out.println(client.getAddress() + 
						": sent client peer data (with server port " +client_server_port+").");
				peer_threads.add(peer_thread);
			} catch (IOException e){
				// couldn't connect to peer, skip it
				System.err.println(client.getAddress()+ 
						": Failed to set up P2p connection " + e.getMessage());
			} catch (RuntimeException e){
				// couldn't connect to peer, skip it
				System.err.println(client.getAddress()+ 
						": Failed to set uo P2p connection " + e.getMessage());
			}
		}
		
		// send last to client
		buf = Utility.addHeader(Constants.DOWNLOAD_REQ, 8, client.getId());
		buf.putInt(Constants.HEADER_LEN, 0);
		buf.putInt(Constants.HEADER_LEN + 4, 0);
		out.write(buf.array());
		out.flush();
		
		System.out.println(client.getAddress() + 
				": Correctly processed download req for " + buf_id);
	}