Trivial P2P in newLISP
;
; 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))