Sketch of simple 1-in,1-out UDP chassis, with error handling

This commit is contained in:
Tony Garnock-Jones 2011-12-14 14:21:19 -05:00
parent ac1d493528
commit b72b78119f
1 changed files with 56 additions and 0 deletions

56
simple-udp-service.rkt Normal file
View File

@ -0,0 +1,56 @@
#lang racket/base
;; Simple imperative UDP server harness.
(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)
;; Starts a generic request/reply UDP server on the given port.
(define (start-udp-service
port-number ;; Uint16
packet-handler ;; UdpPacket ServerState -> ListOf<UdpPacket> ServerState
initial-state ;; ServerState
#:service-name
[service-name (format "anonymous UDP service on port ~v" port-number)]
#: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 (service-loop state)
(service-loop
(with-handlers ((exn:break? (lambda (e) (raise e)))
(exn? (lambda (e)
(printf "Error in ~a:~n~v~n~n" service-name e)
(flush-output)
state)))
(read-and-process-request state))))
(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)
(define-values (reply-packets new-state)
(packet-handler (udp-packet packet source-hostname source-port) old-state))
(for-each (lambda (p)
(udp-send-to s (udp-packet-host p) (udp-packet-port p) (udp-packet-body p)))
reply-packets)
new-state)
(service-loop initial-state))