2011-12-14 19:21:19 +00:00
|
|
|
#lang racket/base
|
|
|
|
|
|
|
|
;; Simple imperative UDP server harness.
|
|
|
|
|
2011-12-15 17:22:59 +00:00
|
|
|
(require racket/match)
|
2011-12-14 19:21:19 +00:00
|
|
|
(require racket/udp)
|
|
|
|
(require "dump-bytes.rkt")
|
|
|
|
|
|
|
|
(provide (struct-out udp-packet)
|
|
|
|
start-udp-service)
|
|
|
|
|
|
|
|
;; A UdpPacket is a (udp-packet Bytes String Uint16), and represents
|
|
|
|
;; either a received UDP packet and the source of the packet, or a UDP
|
|
|
|
;; packet ready to be sent along with the address to which it should
|
|
|
|
;; be sent.
|
|
|
|
(struct udp-packet (body host port) #:transparent)
|
|
|
|
|
2011-12-15 17:18:14 +00:00
|
|
|
;; TODO: Should packet-classifier be permitted to examine (or possibly
|
|
|
|
;; even transform!) the ServerState?
|
|
|
|
|
2011-12-14 19:21:19 +00:00
|
|
|
;; Starts a generic request/reply UDP server on the given port.
|
|
|
|
(define (start-udp-service
|
|
|
|
port-number ;; Uint16
|
2011-12-15 17:18:14 +00:00
|
|
|
packet-classifier ;; UdpPacket -> Maybe<ClassifiedPacket>
|
2011-12-15 17:22:59 +00:00
|
|
|
bad-packet-handler ;; UdpPacket ServerState -> ListOf<ClassifiedPacket> ServerState
|
|
|
|
good-packet-handler ;; ClassifiedPacket ServerState -> ListOf<ClassifiedPacket> ServerState
|
|
|
|
packet-encoder ;; ClassifiedPacket -> UdpPacket
|
2011-12-14 19:21:19 +00:00
|
|
|
initial-state ;; ServerState
|
|
|
|
#:packet-size-limit
|
|
|
|
[packet-size-limit 65536])
|
|
|
|
(define s (udp-open-socket #f #f)) ;; the server socket
|
|
|
|
(udp-bind! s #f port-number) ;; bind it to the port we were given
|
|
|
|
|
|
|
|
(define (read-and-process-request old-state)
|
|
|
|
(define buffer (make-bytes packet-size-limit))
|
|
|
|
(define-values (packet-length source-hostname source-port)
|
|
|
|
(udp-receive! s buffer))
|
|
|
|
(define packet (subbytes buffer 0 packet-length))
|
|
|
|
|
|
|
|
(printf "----------------------------------------~n~v~n" packet)
|
|
|
|
(dump-bytes! buffer packet-length)
|
|
|
|
(flush-output)
|
|
|
|
|
2011-12-15 17:18:14 +00:00
|
|
|
(define packet-and-source (udp-packet packet source-hostname source-port))
|
|
|
|
(define classified-packet (packet-classifier packet-and-source))
|
|
|
|
|
2011-12-14 19:21:19 +00:00
|
|
|
(define-values (reply-packets new-state)
|
2011-12-15 17:18:14 +00:00
|
|
|
(cond
|
|
|
|
((eq? classified-packet #f) (bad-packet-handler packet-and-source old-state))
|
|
|
|
(else (good-packet-handler classified-packet old-state))))
|
2011-12-14 19:21:19 +00:00
|
|
|
|
|
|
|
(for-each (lambda (p)
|
2011-12-15 17:22:59 +00:00
|
|
|
(match-define (udp-packet body host port) (packet-encoder p))
|
|
|
|
(udp-send-to s host port body))
|
2011-12-14 19:21:19 +00:00
|
|
|
reply-packets)
|
|
|
|
new-state)
|
|
|
|
|
2011-12-14 20:15:36 +00:00
|
|
|
(let service-loop ((state initial-state))
|
|
|
|
(service-loop (read-and-process-request state))))
|