source: branches/home/psmith/restructure/src/protocol/yarpc/yarpc-packet-factory.lisp

Last change on this file was 100, checked in by psmith, 18 years ago

Fixed large packet problems: calculated header size correctly; use buffer-pointer to take into account buffer-position on write and moved external format to UTF-8

File size: 6.4 KB
Line 
1#|
2Copyright (c) 2007
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions
7are met:
81. Redistributions of source code must retain the above copyright
9   notice, this list of conditions and the following disclaimer.
102. Redistributions in binary form must reproduce the above copyright
11   notice, this list of conditions and the following disclaimer in the
12   documentation and/or other materials provided with the distribution.
133. The name of the author may not be used to endorse or promote products
14   derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26|#
27(in-package :nio-yarpc)
28
29(declaim (optimize (debug 3) (speed 3) (space 0)))
30
31;;
32(defclass yarpc-packet-factory (packet-factory)())
33
34
35(defun yarpc-packet-factory ()
36  (make-instance 'yarpc-packet-factory))     
37
38(defconstant +CALL-METHOD-PACKET-ID+ #x0)
39(defconstant +METHOD-RESPONSE-PACKET-ID+ #x1)
40
41(defconstant +PACKET-ID-SIZE+ 1)
42(defconstant +PACKET-LENGTH-SIZE+ 4)
43(defconstant +PACKET-REQUEST-ID-SIZE+ 4)
44
45(defconstant +yarpc-packet-header-size+
46  (+ +PACKET-ID-SIZE+ +PACKET-LENGTH-SIZE+))
47
48(defconstant +yarpc-rpc-packet-header-size+ (+  +yarpc-packet-header-size+ +PACKET-REQUEST-ID-SIZE+))
49
50(defmethod get-packet ((pf yarpc-packet-factory) buf)
51  (flip buf)
52  (if (>= (remaining buf) +yarpc-packet-header-size+) ;; First byte denotes packet ID ;;bytes 2,3,4,5 denote packet size ;; 6,7,8,9 request-id
53      (let ((packet-id (bytebuffer-read-8 buf))
54            (packet-length (bytebuffer-read-32 buf)))
55        (if (<= (- packet-length +yarpc-packet-header-size+) (remaining buf)) ;is the whole packet available in the buffer?
56            (let* ((packet-request-id (bytebuffer-read-32 buf))
57                   (ret-packet (ecase packet-id
58                                (0 (progn 
59#+nio-debug                                  (format-log t "yarpc-packet-factory:get-packet - got CALL-METHOD-PACKET-ID~%") 
60                                     (call-method-packet (bytebuffer-read-string buf (- packet-length +yarpc-packet-header-size+ +PACKET-REQUEST-ID-SIZE+)) :request-id packet-request-id)))
61                                (1 (progn 
62#+nio-debug                                  (format-log t "yarpc-packet-factory:get-packet - got METHOD-RESPONSE-PACKET-ID~%") 
63                                     (method-response-packet (bytebuffer-read-string buf (- packet-length +yarpc-packet-header-size+ +PACKET-REQUEST-ID-SIZE+)) :request-id packet-request-id))))))
64              (compact buf)
65              #+nio-debug  (format-log t "yarpc-packet-factory:get-packet - after compact ~%~A~%" buf)
66              #+nio-debug  (format-log t "yarpc-packet-factory:get-packet - retuirning packet ~A~%" ret-packet)
67              ret-packet)
68                                        ;Failed to read a whole packet unflip and check size
69            (let ((buffer-capacity (buffer-capacity buf)))
70              (unflip buf)           
71              (if (> packet-length buffer-capacity) (error 'buffer-too-small-error :recommended-size packet-length)))))))
72
73
74
75(defclass yarpc-packet(packet)
76  ((request-id :initarg :request-id
77               :reader request-id)))
78
79(defclass call-method-packet (yarpc-packet)
80  ((call-string :initarg :call-string
81                :accessor call-string)))
82
83(defun call-method-packet (call-string &key request-id)
84  (make-instance 'call-method-packet :call-string call-string :request-id request-id))
85
86(defmethod print-object ((packet call-method-packet) stream)
87  (format stream "#<CALL-METHOD-PACKET ~A >" (call-string packet)))
88
89(defmethod write-bytes((packet call-method-packet) buf)
90  #+nio-debug  (format-log t "yarpc-packet-factory:write-bytes(call-method-packet) - writing ~%~A to ~%~A~%" packet buf)
91  (nio-buffer:mark buf)
92  (handler-case
93      (progn
94        (nio-buffer:bytebuffer-write-8 buf +CALL-METHOD-PACKET-ID+)
95        (nio-buffer:bytebuffer-write-32 buf 0) ; come back and write length later
96        (nio-buffer:bytebuffer-write-32 buf (request-id packet))
97        (nio-buffer:bytebuffer-write-string buf (call-string packet) :utf-8)
98        (nio-buffer:bytebuffer-insert-32 buf (buffer-position buf) 1)
99  #+nio-debug    (format-log t "yarpc-packet-factory:write-bytes(call-method-packet) - written ~%~A ~%" buf) 
100       )
101    (buffer-too-small-error (err)
102      (nio-buffer:reset buf)
103      (error err))))
104
105
106(defmethod get-packet-size ((packet call-method-packet))
107  (+ +yarpc-rpc-packet-header-size+
108     (length (sb-ext:string-to-octets (call-string packet) :external-format :utf-8))))
109
110(defclass method-response-packet (yarpc-packet)
111  ((response :initarg :response
112             :accessor response)))
113
114(defun method-response-packet (response &key request-id)
115  (make-instance 'method-response-packet :response response :request-id request-id))
116
117(defmethod print-object ((packet method-response-packet) stream)
118  (format stream "#<METHID-RESPONSE-PACKET ~A >" (response packet)))
119
120(defparameter +serialise-packet-fn+ #'(lambda (result)(write-to-string result)))
121
122(defmethod write-bytes((packet method-response-packet) buf)
123#+nio-debug    (format-log t "yarpc-packet-factory:write-bytes - writing ~A to ~A~%" packet buf)
124  (nio-buffer:mark buf)
125  (handler-case
126      (progn
127        (nio-buffer:bytebuffer-write-8 buf +METHOD-RESPONSE-PACKET-ID+)
128        (nio-buffer:bytebuffer-write-32 buf 0) ; come back and write length later
129        (nio-buffer:bytebuffer-write-32 buf (request-id packet))
130        (nio-buffer:bytebuffer-write-string buf (funcall +serialise-packet-fn+ (response packet)) :utf-8)
131        (nio-buffer:bytebuffer-insert-32 buf (buffer-position buf) 1)
132#+nio-debug    (format-log t "yarpc-packet-factory:write-bytes - written ~A~%" buf) 
133        )
134    (buffer-too-small-error (err)
135      (nio-buffer:reset buf)
136#+nio-debug (format-log t "yarpc-packet-factory:write-bytes - buffer too small caught, reset to ~A~%" buf)
137      (error err))))
138
139(defmethod get-packet-size ((packet method-response-packet))
140  (+ +yarpc-rpc-packet-header-size+
141     (length (sb-ext:string-to-octets (funcall +serialise-packet-fn+ (response packet)) :external-format :utf-8))))
Note: See TracBrowser for help on using the repository browser.