www.crossflux.org www.crossflux.org
 
Home Software Publications Forums Contact
Software :: uP2P — micro P2P file sharing application

Version 0.0.1 (02/15/2005), P. Felber.

Download the short concise (6 lines, 436 characters) or the long commented version. This file is released to the public domain. Comments or suggestions are welcome!

#!/bin/sh
# uP2P.sh 0.0.1, 436 characters (excluding comments)
[ $3 ]&&export W=$1 H="$2 $3" K=`mktemp`;Z=/dev/null;e(){ echo "$*";};n(){
nc $* 2>$Z;};x(){ nc -lp ${H#* } -e $1 &>$Z <$Z&};f(){ cat $K|while read h;do
e $W $1 "$2"|n $h;done };case $# in 4)e $W s "$4"|n $H|while read h p f; do
e $W g "$f"|n $h $p>"$f";done;;5)e $H>$K;e $W d $H|n $4 $5>>$K;x $0;;0)x $0
read w c r;[ $W = $w ]&&case $c in s)f l "$r";;g)cat "$r";;a)e $r>>$K;;d)cat $K
f a "$r";;l)ls|grep "$r"|sed "s/^/$H /";;esac;;esac

Description

This shell script was inspired by Prof. Ed Felten's TinyP2P application (as well as Matthew Skala's shorter variant MoleSter) and was developed as a follow-up to a seminar on peer-to-peer (P2P) networks organized at the University of Neuchatel. It sets up a small P2P network by sharing the content of the current directory with other peers. Files added to the directory at runtime are dynamically shared. With trivial modifications (documented in the code), it is also possible to share subdirectories.

This shell script only uses standard Unix tools. Communication is handled using 'netcat' ('nc'), a command-line interface to TCP, installed by default on most Unix systems. It must be compiled to accept the '-e' flag (try 'nc -h' to verify); this is the case, for instance, with bootable Knoppix CDs. The script has been tested on various Linux distributions.

Of course, the goal of this application is NOT to encourage illicit file sharing or facilitate copyright infringement (there exists far better and more scalable solutions), but to demonstrate how simple it is to create a non-trivial file sharing application.

The network is password protected. In order to connect to the network or download a file, one needs to know the password.

As each server knows of every other server, this application is not very scalable. It does, however, work remarkably well for exchanging files among small groups of people.

Usage

To start a server, change to the directory that you would like to share and start the script as follows:

   uP2P.sh password local-ip local-port remote-ip remote-port

where 'password' is the network's password; 'local-ip' and 'local-port' are the IP address and port used by the server for listening to remote requests; 'remote-ip' and 'remote-port' are the IP address and port of some other peer in the network. The first server can be started with any remote address (even its own address) since connections to non-existing endpoints will fail silently. All 5 parameters must be specified.

To start a client, change to the directory that you would like to download files to and start the script as follows:

  uP2P.sh password remote-ip remote-port pattern

where 'password' is the network's password; 'remote-ip' and 'remote-port' are the IP address and port of some server peer in the network; 'pattern' is a filter that specifies the files to download using the 'grep' regular expression syntax. Note that, because of message forwarding, redundant escape characters must be used; for instance, "\." (dot) must be specified as "\\\\.".

To end the script, kill all instances of 'nc'.

Example

Start 4 servers on 4 hosts (or in different directories on the same host):

  uP2P.sh abc 192.168.1.100 9000 192.168.1.100 9000
  uP2P.sh abc 192.168.1.101 9000 192.168.1.100 9000
  uP2P.sh abc 192.168.1.102 9000 192.168.1.101 9000
  uP2P.sh abc 192.168.1.103 9000 192.168.1.101 9000

Download all files containing 'pdf' in their name (here using third server as entry point to the network):

  uP2P.sh abc 192.168.1.102 9000 "pdf"

Limitations

  • There are only few checks and error messages.
  • In theory, there might be some race conditions in rare situations, which might reduce availability or connectivity (this has never been experienced in tests, though).
  • Departures and failures are not handled explicitly: servers keep on forwarding messages to unreachable peers (which silently fails).
  • If there are subdirectories matching the search pattern in the shared directory of a server, an empty file with the same name as the subdirectory will be created by the client. This problem can be solved by slight additions to the script (documented in the code).

The short version has the following additional limitations:

  • Even fewer checks and error messages.
  • The client does not verify if a file already exists locally before downloading it. This may result in unnecessary downloads.

How it works

  • The server forks a new instance each time it processes a request, so that there is always a listener.
  • On startup, a new server sends a 'd' (discover) message to the existing server specified on the command line.
  • When receiving a 'd' message, a server returns its neighbor list to the new peer and forwards an 'a' (advertisement) message to all servers (including itself).
  • When receiving an 'a' message, a server adds the new peer to its neighbor list.
  • On startup, the client sends an 's' (search) request to the existing server specified on the command line.
  • When receiving an 's' message, a server forwards an 'l' (list) message to all servers (including itself).
  • When receiving an 'l' message, a server returns a list of the files that match pattern (each file comes with the host and port of the associated server).
  • Upon receiving the file list from all servers, the client sends 'g' (get) messages to download each file sequentially.