changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/lib/net/codec/tlv.lisp

changeset 258: 11ef863e0ac0
parent: 099ee89ff63f
child: 386d51cf61ca
author: Richard Westhaver <ellis@rwest.io>
date: Mon, 01 Apr 2024 23:58:17 -0400
permissions: -rw-r--r--
description: keyutils init
1 ;;; lisp/net/codec/tlv.lisp --- TypeLengthValue wire codec
2 
3 ;;
4 
5 ;;; Code:
6 (in-package :net/codec/tlv)
7 
8 (defclass tlv ()
9  ((type :initform 0 :initarg :type :type octet :accessor tlv-type)
10  (length :initform 0 :initarg :length :type (unsigned-byte 16) :accessor tlv-length)
11  (value :initform (make-array 0 :element-type 'octet) :initarg :value :type octet-vector :accessor tlv-value))
12  (:documentation "TypeLengthValue object.
13 
14 TLVs are a common packet format in communication protocols. Objects of
15 this type are assumed to have a 1 byte TYPE, a 2 byte LENGTH, and a
16 VALUE which is an OCTET-VECTOR of length LENGTH."))
17 
18 (defmethod serialize ((obj tlv) (format (eql :bytes)) &key stream)
19  (declare (ignore format))
20  (with-slots (type length value) obj
21  (let* ((end (+ 3 length))
22  (buf (make-array end :element-type 'octet)))
23  (setf (aref buf 0) type)
24  (setf (subseq buf 1 2) (integer-to-octets length 16))
25  (unless (= 0 length)
26  (setf (subseq buf 3 (+ 3 length)) value))
27  (if stream
28  (write buf :stream stream)
29  buf))))
30 
31 (defun make-tlv (type length &optional (value #.(make-array 0 :element-type 'octet)))
32  (make-instance 'tlv :type type :length length :value value))
33 
34 (defmethod serialize ((obj tlv) (format (eql :string)) &key stream (external-format :default))
35  (declare (ignore format stream))
36  (sb-ext:octets-to-string (serialize obj :bytes) :external-format external-format))
37 
38 (defmethod deserialize ((from simple-array) (format (eql :tlv)) &key)
39  (declare (ignore format))
40  (let ((type (aref from 0))
41  (length (octets-to-integer (subseq from 1 3))))
42  (if (= 0 length)
43  (make-tlv type length)
44  (let ((value (subseq from 3 (+ 3 length))))
45  (funcall #'make-tlv type length value)))))
46 
47 (defmethod deserialize ((from stream) (format (eql :tlv)) &key)
48  (let ((type (read-byte from))
49  (l (make-array 2 :element-type 'octet :adjustable t)))
50  (read-sequence l from)
51  (let ((length (octets-to-integer (coerce l 'octet-vector))))
52  (if (= 0 length)
53  (make-tlv type length nil)
54  (let ((value (make-array length :element-type 'octet)))
55  (read-sequence value from)
56  (make-tlv type length value))))))
57 
58 
59 
60 (defmethod serde ((from tlv) (to simple-array))
61  (with-slots (type length value) from
62  (setf (aref to 0) type)
63  (replace to (integer-to-octets length 16) :start1 1 :start2 2)
64  (unless (= 0 length)
65  (replace to value :start1 3 :end1 (+ 3 length)))
66  to))
67 
68 (defmethod serde ((from simple-array) (to tlv))
69  (if (> 3 (length from))
70  (error 'serde-error :message "array length is < 3")
71  (let ((type (aref from 0))
72  (length (octets-to-integer (subseq from 1 2))))
73  (setf (tlv-type to) type
74  (tlv-length to) length
75  (tlv-value to) (subseq from 3 (+ 3 length)))
76  to)))
77 #+nil
78 (describe
79  (deserialize
80  (serialize (make-instance 'tlv) :bytes)
81  :tlv))