;;; -*- mode: lisp; syntax: common-lisp; package: existenz-server; coding: utf-8-unix; -*- (in-package #:existenz-server) #-(or) (progn (defun start-server (&optional (host +ipv6-unspecified+) (port 4000)) (spawn-thread (lambda () (run-server host port)) :name "Existenz Server IO")) (defun run-server (host port) (with-event-base (event-base) (let ((server (make-socket :ipv6 T :type :datagram :local-host host :local-port port :reuse-address T))) (unwind-protect (dispatch-server event-base server) (close server))))) (defun dispatch-server (event-base server) (flet ((read-event (fd event-type errorp) (read-server-event server fd event-type errorp))) (set-io-handler event-base (fd-of server) :read #'read-event) (iterate (iterate (for (values message from) = (recv-nowait distlisp::*current-process*)) (while from) (case message (:exit (abort-thread)))) (event-dispatch event-base :timeout 0.001))))) #+(or) (progn (defun start-server (&optional (host +ipv6-unspecified+) (port 4000)) (multiple-value-bind (left right) (iolib.syscalls:pipe) (make-thread (lambda () (unwind-protect (run-server host port right) (iolib.syscalls:close left) (iolib.syscalls:close right))) :name "EXISTENZ-SERVER-IO") left)) (defun run-server (host port pipe) (with-event-base (event-base) (let ((server (make-socket :ipv6 T :type :datagram :local-host host :local-port port :reuse-address T))) (unwind-protect (dispatch-server event-base server pipe) (close server))))) (defun dispatch-server (event-base server pipe) (flet ((read-event (fd event-type errorp) (read-server-event fd event-type errorp server)) (read-pipe (fd event-type errorp) (declare (ignore fd event-type errorp)) (format T "received signal on pipe~%") (exit-event-loop event-base))) (set-io-handler event-base (fd-of server) :read #'read-event) (set-io-handler event-base pipe :read #'read-pipe) (event-dispatch event-base)))) (defvar *clients* (make-hash-table :test 'eql)) (defun read-server-event (server fd event-type errorp) (declare (ignore fd event-type errorp)) (multiple-value-bind (buffer length host port) (receive-from server :size 500) (format T "received ~A bytes from ~A:~A~%" length host port) (unless (>= length 4) (format T "malformed message, length ~D of 4~%" length) (send-to server #(1 0 0 1) :remote-host host :remote-port port) (return-from read-server-event)) (let ((version (aref buffer 0))) (format T "version ~D~%" version) (let ((sequence-number (+ (ash (aref buffer 1) 8) (aref buffer 2)))) (format T "sequence number ~D~%" sequence-number) (let ((event-type (aref buffer 3))) (format T "event type ~D~%" event-type)))))) #+(or) (defenum event-type :error ; transport error :ping ; hello there :pong ; yes, i heard you :login ; now assign me an identifier :logged-in) ; and this is your session id ;; movement, actions, updates? ;; data via http or bittorrent ;; :ping -> :pong ;; :login -> :error, :logged-in #+(or) (defun handle-event/default-state (buffer) (case event-type (:ping (send-event client :pong)) (T (send-event client :error))))