Advertisement
Guest User

Untitled

a guest
Aug 11th, 2017
404
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 5.07 KB | None | 0 0
  1. (ql:quickload "usocket")
  2.  
  3. ;; declare our chat parameters with default values
  4. ;; we'll resolve hostnames later so address can be ip4 or a hostname
  5. (defparameter *server-address* "192.168.1.0")
  6. (defparameter *port* "22")
  7. (defparameter *username* "u0")
  8.  
  9. ;; switches default to false
  10. (defparameter *server* nil)
  11.  
  12. (defparameter *params* '(*server-address*
  13.                     *port*
  14.                     *username*
  15.                     *server*))
  16.  
  17. (defun debug-print (func str)
  18.   (format t "~s:~s~%" func str)
  19.   (finish-output))
  20.  
  21. ;; evaluate command line arguments (argv)
  22. (defun eval-arg (cur-arg prev-arg test test2 internal-param)
  23.   (when (or (string= prev-arg test) (string= prev-arg test2))
  24.     (setf (symbol-value internal-param) cur-arg)))
  25.  
  26. ;; evaluate command line switches (argv)
  27. (defun eval-switch (cur-arg test test2 internal-param)
  28.   (when (or (string= cur-arg test) (string= cur-arg test2))
  29.     (setf (symbol-value internal-param) t)))
  30.  
  31. (defun eval-args (args)
  32.   ;; set chat parameters based on command line input
  33.   (let ((prev-arg ""))
  34.     (loop
  35.       for cur-arg in args
  36.       do (progn
  37.            ;(format t "cur-arg: ~s~%" cur-arg)
  38.            (eval-arg cur-arg prev-arg "--server-address" "-a" '*server-address*)
  39.            (eval-arg cur-arg prev-arg "--port" "-p" '*port*)
  40.            (eval-arg cur-arg prev-arg "--username" "-u" '*username*)
  41.            (eval-switch cur-arg "--server" "-s" '*server*)
  42.            (format t "prev-arg: ~a, cur-arg: ~a~%" prev-arg cur-arg)
  43.            (setf prev-arg cur-arg)))))
  44.  
  45. ;; iterate through a list of symbols printing both the name and value
  46. (defun print-params (params)
  47.   (loop
  48.     for i in params do
  49.     (format t "~a: ~a~%" i (symbol-value i))))
  50.  
  51. ;; send data to the server, automatically handle string conversion to a buffer
  52. (defun send-data (socket input)
  53.   (let ((buffer (make-array (list-length input)
  54.                             :element-type '(unsigned-byte 8)
  55.                             :initial-element 0))
  56.         (input-length (list-length input)))
  57.     (setf buffer (map '(vector (unsigned-byte 8)) #'char-code input))
  58.     (usocket::socket-send socket buffer input-length)))
  59.  
  60. ;; loop to gather user input to send
  61. (defun input-data (socket username)
  62.   (loop
  63.     (let ((input "") (prepend (concatenate 'string username ": ")))
  64.       (setf input (read))
  65.       (if (string= input "(exit-chat)")
  66.           (return))
  67.       ;; attach username to message
  68.       (setf input (concatenate 'string prepend input (list #\newline)))
  69.       (send-data socket input))))
  70.  
  71. ;; handle received buffer and print to
  72. (defun handle-received-data (buffer)
  73.   (let ((output ""))
  74.     (setf output (map 'string #'code-char buffer))
  75.     (print output)))
  76.  
  77. ;; thread function to handle all incoming data
  78. (defun receive-thread (socket)
  79.   (debug-print "receive-thread" "1")
  80.   (block receiver-nested-loop
  81.          (debug-print "receive-thread" "2")
  82.          (loop
  83.            (let ((ready-socket (usocket::wait-for-input socket)))
  84.              (debug-print "receive-thread" "3")
  85.              (let ((return-buffer (usocket::socket-receive ready-socket nil nil)))
  86.                  (debug-print "receive-thread" "4")
  87.                  (if (not (eq return-buffer :eof))
  88.                      (handle-received-data return-buffer)
  89.                      (return-from receiver-nested-loop)))))))
  90.  
  91. ;; handle the chat communication
  92. (defun handle-connection (socket username)
  93.   (unwind-protect
  94.     (block run-server-block
  95.            (debug-print "handle-connection" "1")
  96.            (sb-thread:make-thread (lambda ()
  97.                                     (progn
  98.                                       (receive-thread socket))))
  99.            (input-data socket username))
  100.     (usocket::socket-close socket)))
  101.  
  102. ;; create a server and set it to listen
  103. (defun create-server (host port username)
  104.   (debug-print "create-server" "1")
  105.   (let ((socket (usocket::socket-listen host port :element-type '(unsigned-byte 8))))
  106.     (handle-connection socket username)))
  107.  
  108. ;; create a client and attempt to connect to a server
  109. (defun create-client (host port username)
  110.   (debug-print "create-client" "1")
  111.   (let ((socket (usocket::socket-connect host port :element-type '(unsigned-byte 8))))
  112.     (handle-connection socket username)))
  113.  
  114. ;; our main function
  115. (defun main ()
  116.   (handler-case
  117.     (progn
  118.       ;; print out the passed argv arguments for sanity
  119.       ;(format t "~s~%" *posix-argv*)
  120.  
  121.       (eval-args *posix-argv*)
  122.  
  123.       (print-params *params*)
  124.       (format t "~d~%" (parse-integer *port*))
  125.  
  126.       (if *server*
  127.           (progn
  128.             (debug-print "main" "entering create-server")
  129.             (create-server *server-address* (parse-integer *port*) *username*))
  130.           (progn
  131.             (debug-print "main" "entering create-client")
  132.             (create-client *server-address* (parse-integer *port*) *username*)))
  133.       (format t "past main functions")
  134.       (sb-ext:exit))
  135.     (sb-sys:interactive-interrupt (e)
  136.                                   (format t "Exiting chat: ~a~%" e)
  137.                                  (sb-ext:exit))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement