naledi / client / networking.lisp
;;;; Naledi ya Africa ("Star of Africa") is an ncurses-based survival game
;;;; set in Africa.
;;;; This file is responsible for connecting to the server.
;;;; (c) 2018 Daniel Vedder, MIT license

(in-package :naledi-ya-africa)

(let ((naledi-server NIL))	
	(defun connect-server (&optional (ip *host*) (port *port*))
		"Connect to the specified server"
		;;FIXME I need to catch some exceptions here...
		(setf naledi-server (usocket:socket-connect ip port))
		(if naledi-server
			(notify "Connected to server ~A:~A" ip port)
			(notify "Connection to server ~A:~A failed." ip port)))

	(defun current-server () naledi-server) ;XXX remove after development?
	(defun query-server (&rest request)
		"Send a request string to the server and return the answer"
		;; If one argument is :ignore-errors, error strings are passed up
		;; to the caller. Otherwise, they cause a crash.
		;;TODO the client should handle errors gracefully!
		(unless naledi-server ;XXX do this with exceptions
			(return-from query-server "You are not connected to a server!"))
		(let* ((servstr (usocket:socket-stream naledi-server))
				  (ig-errors (find ':ignore-errors request))
				  (req (string-from-list
						   (remove-if #'(lambda (s) (eq s ':ignore-errors))
			(logf 4 "CLIENT: sending request ~S" request)
			(format servstr "~A~%" req)
			(finish-output servstr)
			(usocket:wait-for-input naledi-server)
			(let ((reply (read servstr nil)))
				(logf 4 "CLIENT: received reply.")
				(when (search "ERROR" reply)
					(if ig-errors (logf 1 reply) (error reply)))
	(defun disconnect ()
		"Disconnect from the server"
		(when naledi-server
			(usocket:socket-close naledi-server)
			(setf naledi-server NIL)
			(notify "Disconnected from server."))))