DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Trivial P2P In NewLISP

09.08.2006
| 3366 views |
  • submit to reddit
        ; a trivial P2P file sharing program written in newLISP for demo purpose
;
;  based on ideas from http://www.freedom-to-tinker.com/tinyp2p.html
; and http://ansuz.sooke.bc.ca/software/molester/ and 
; http://ansuz.sooke.bc.ca/software/molester/2005010301.php
;
; command reference
; i/ advertise presence of your node to the peer
; g<filename>/ requests a file 
; f<message> forward to peers
; h/ gets list of all peers
;
; used internally
; e<filename>/ expect a file
; x  sent after receiving a file to make sure
;
; the program below is a toy, not a serious p2p program.
; 
; differences from original mole-ster:
; use of 'x' -- to allow data receipt on receiving side when file is sent
; data is read in 8k chunks at a time.  this is to avoid having to read
; the entire file into a buffer before writing. it allows larger files to be 
; transferred.
;
; more more information refer to the original mole-ster web sites.
;

(context 'P2P)

(constant 'SIGINT 2)
(define (interrupted)
  (println "interruted by user!")
  (exit))

(signal SIGINT interrupted)

(set 'my-address "")
(set 'my-password "")
(set 'peers '())

(define (get-addr addr-and-port)  (regex "(.*):(.*)" addr-and-port)  $1)
(define (get-port addr-and-port)  (regex "(.*):(.*)" addr-and-port)  (integer $2))

(define (op-send dest-addr source-addr filename data)
  (if (set 'socket (net-connect (get-addr dest-addr) (get-port dest-addr)))
      (begin
			(net-send socket (format "%s %s %s/" my-password source-addr filename))
			(net-send socket data )
			(if (!= data "")
				(net-receive socket 'buf 1))
			(close socket))))

(define (P2P:P2P my-password peer-address my-address commands )
  (set 'peers (append peers (list peer-address)))
  (dolist (cmd commands)  (op-send peer-address my-address cmd ""))
  (set 'socket (net-listen  (get-port my-address)))
  (while true 
	 (while  (and (not (net-error)) (not (net-select socket "read" 1000)))
		 (if (net-error) (print (net-error))))
	 (set 'peer-socket (net-accept socket)) (net-receive peer-socket 'buf 1024 "/") 
	 (regex "^([a-zA-Z0-9]*) ([0-9:.]*) ([e-i])([^/]*)(/)" buf) 
	 (set 'peer-password $1) 
	 (set 'peer-address $2) 
	 (set 'peer-command $3) 
	 (set 'requested-filename $4) 
	 (set 'data $6) 
	 (if (= peer-password my-password) 
	     (case peer-command
	       ("e" (begin
	       			(set 'finished false)
	       			(while (not finished)
	       		     	(while (and (not (net-error)) (not (net-select peer-socket "read" 1000)))
	       		     		(if (net-error) (print (net-error))))
			    		(if (!= nil (net-receive peer-socket 'input-data 8192))
			    			(begin
								(append-file  requested-filename input-data)
							(set 'finished true)))
					(net-send socket "x")))
	       ("f"  (dolist (peer peers)   (op-send peer my-address requested-filename data)))
	       ("g" (op-send peer-address my-address (append "e" requested-filename) 
	       			(read-file requested-filename)))
	       ("h" (dolist (peer peers)  (op-send peer-address peer "i" "")))
	       ("i" (append peers peer-address))))
	 (close peer-socket)))

(context 'MAIN)


(P2P:P2P (main-args 2) (main-args 3) (main-args 4)  (slice (main-args) 5 -1))