Mercurial > core / lisp/lib/net/proto/http.lisp
changeset 381: |
386d51cf61ca |
parent: |
de40bd522c84
|
child: |
849bbe48e32d |
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Tue, 28 May 2024 23:12:31 -0400 |
permissions: |
-rw-r--r-- |
description: |
add ffi/readline, net updates |
1 ;;; lib/net/proto/http.lisp --- HTTP Support 3 ;; based on https://github.com/fukamachi/fast-http 5 ;; see also: https://github.com/orthecreedence/http-parse 9 ;; Fukamachi has implemented the current state-of-the-art HTTP libraries 10 ;; (fast-http, dexador, etc). For the time being we'll be using these with 11 ;; minimal changes. At some point in the future it would be ideal to 12 ;; re-implement this in a sans-io style. 15 (in-package :net/proto/http) 18 (defmacro casev (keyform &body clauses) 22 ((eq val 'otherwise) val) 23 ((symbolp val) (symbol-value val)) 25 (T (error "CASEV can be used only with variables or constants"))))) 27 ,@(loop for (val . clause) in clauses 28 if (eq val 'otherwise) 29 collect `(otherwise ,@clause) 31 collect `((,@(mapcar #'get-val val)) ,@clause) 33 collect `(,(get-val val) ,@clause)))))) 35 (defmacro casev= (keyform &body clauses) 39 ((eq val 'otherwise) val) 40 ((symbolp val) (symbol-value val)) 42 (T (error "CASEV can be used only with variables or constants"))))) 44 ,@(loop for (val . clause) in clauses 45 if (eq val 'otherwise) 48 collect `((or ,@(mapcar (lambda (val) 49 `(= ,keyform ,(get-val val))) 53 collect `((= ,keyform ,(get-val val)) ,@clause)))))) 55 (defmacro case-byte (byte &body cases) 57 ,@(loop for (val . form) in cases 58 if (eq val 'otherwise) 59 collect `(,val ,@form) 61 collect `(,(mapcar #'char-code val) ,@form) 63 collect `(,(char-code val) ,@form)))) 65 (defmacro tagcase (keyform &body blocks) 66 (let ((end (gensym "END"))) 69 ,@(loop for (tag . body) in blocks 70 if (eq tag 'otherwise) 71 collect `(otherwise ,@body (go ,end)) 73 collect `(,tag (go ,(if (listp tag) (car tag) tag))))) 75 ,@(loop for (tag . body) in blocks 80 collect `(progn ,@body 84 (defmacro tagcasev (keyform &body blocks) 85 (let ((end (gensym "END"))) 88 ,@(loop for (tag . body) in blocks 89 if (eq tag 'otherwise) 90 collect `(otherwise ,@body (go ,end)) 92 collect `(,tag (go ,(if (listp tag) (car tag) tag))))) 94 ,@(loop for (tag . body) in blocks 97 else if (not (eq tag 'otherwise)) 99 collect `(progn ,@body 103 (defmacro tagcasev= (keyform &body blocks) 104 (let ((end (gensym "END"))) 107 ,@(loop for (tag . body) in blocks 108 if (eq tag 'otherwise) 109 collect `(otherwise ,@body (go ,end)) 111 collect `(,tag (go ,(if (listp tag) (car tag) tag))))) 113 ,@(loop for (tag . body) in blocks 116 else if (not (eq tag 'otherwise)) 118 collect `(progn ,@body 122 (defun make-collector () 123 (let ((none '#:none)) 124 (declare (dynamic-extent none)) 125 (with-collectors (buffer) 126 (return-from make-collector 127 (lambda (&optional (data none)) 128 (unless (eq data none) 132 (declaim (inline %whitespacep)) 133 (defun %whitespacep (char) 134 (declare (type character char) 135 (optimize (speed 3) (safety 0))) 136 (or (char= char #\Space) 139 (declaim (inline position-not-whitespace)) 140 (defun position-not-whitespace (string &key from-end) 141 (declare (type simple-string string) 142 (optimize (speed 3) (safety 0))) 143 (let* ((len (length string)) 144 (start (if from-end (1- len) 0)) 145 (end (if from-end 0 (1- len))) 146 (step-fn (if from-end #'1- #'1+))) 147 (declare (type integer len start end)) 148 (do ((i start (funcall step-fn i))) 150 (declare (type integer i)) 151 (unless (%whitespacep (aref string i)) 152 (return-from position-not-whitespace i))))) 154 (declaim (inline number-string-p)) 155 (defun number-string-p (string) 156 (declare (type simple-string string) 157 (optimize (speed 3) (safety 2))) 159 (when (zerop (length string)) 160 (return-from number-string-p nil)) 161 (let ((end (position-not-whitespace string :from-end t)) 165 ;; (return-from number-string-p)) 166 (locally (declare (type integer end) 167 (optimize (safety 0))) 169 (do ((i (the integer (or (position-not-whitespace string) 0)) (1+ i))) 171 (declare (type integer i)) 172 (let ((char (aref string i))) 173 (declare (type character char)) 176 (return-from number-string-p nil)) 177 ((digit-char-p char)) 180 (return-from number-string-p nil)) 182 (T (return-from number-string-p nil)))))))) 185 (defun make-http-parser (http &key first-line-callback header-callback body-callback finish-callback (head-request nil)) 186 (declare (type http http)) 189 (parse-fn (etypecase http 190 (http-request #'parse-request) 191 (http-response #'parse-response))) 195 (header-value-buffer nil) 201 (flet ((collect-prev-header-value () 202 (when header-value-buffer 204 (locally (declare (optimize (speed 3) (safety 0))) 206 (the (or octet-concatenated-xsubseqs octet-xsubseq) header-value-buffer))))) 208 (if (string= parsing-header-field "set-cookie") 209 (push header-value (gethash "set-cookie" headers)) 210 (multiple-value-bind (previous-value existp) 211 (gethash (the simple-string parsing-header-field) headers) 212 (setf (gethash (the simple-string parsing-header-field) headers) 214 (if (simple-string-p previous-value) 215 (concatenate 'string (the simple-string previous-value) ", " header-value) 216 (format nil "~A, ~A" previous-value header-value)) 220 :message-begin (lambda (http) 221 (declare (ignore http)) 222 (setq headers (make-hash-table :test 'equal) 223 header-complete-p nil 225 :url (lambda (http data start end) 226 (declare (type octet-vector data) 227 (type pointer start end)) 228 (setf (http-resource http) 229 (ascii-octets-to-string data :start start :end end))) 230 :status (lambda (http data start end) 231 (declare (type octet-vector data) 232 (type pointer start end)) 233 (setf (http-status-text http) 234 (ascii-octets-to-string data :start start :end end))) 235 :first-line (and first-line-callback 237 (declare (ignore http)) 238 (funcall (the function first-line-callback)))) 239 :header-field (lambda (http data start end) 240 (declare (ignore http) 241 (type octet-vector data) 242 (type pointer start end)) 243 (collect-prev-header-value) 244 (setq header-value-buffer (make-concatenated-xsubseqs)) 245 (setq parsing-header-field 246 (ascii-octets-to-lower-string data :start start :end end))) 247 :header-value (lambda (http data start end) 248 (declare (ignore http) 249 (type octet-vector data) 250 (type pointer start end)) 251 (xnconcf header-value-buffer 252 (xsubseq (subseq (the octet-vector data) start end) 0))) 253 :headers-complete (lambda (http) 254 (collect-prev-header-value) 255 (setq header-value-buffer nil) 256 (when (gethash "set-cookie" headers) 257 (setf (gethash "set-cookie" headers) 258 (nreverse (gethash "set-cookie" headers)))) 259 (setf (http-headers http) headers) 260 (when header-callback 261 (funcall (the function header-callback) headers)) 262 (when (and (not (http-chunked-p http)) 263 (not (numberp (http-content-length http)))) 265 (setq header-complete-p t)) 266 :body (and body-callback 267 (lambda (http data start end) 268 (declare (ignore http) 269 (type octet-vector data) 270 (type pointer start end)) 271 (funcall (the function body-callback) 273 :message-complete (lambda (http) 274 (declare (ignore http)) 275 (collect-prev-header-value) 276 (when finish-callback 277 (funcall (the function finish-callback))) 278 (setq completedp t))))) 280 (lambda (data &key (start 0) end) 281 (declare (optimize (speed 3) (safety 2))) 285 (when finish-callback 286 (funcall (the function finish-callback)))) 288 (locally (declare (type octet-vector data) 289 (type pointer start)) 290 (check-type end (or null pointer)) 294 (xnconc (xsubseq data-buffer 0) 295 (xsubseq (the octet-vector data) start (or end (length data)))))) 296 (setq data-buffer nil 299 (setf (http-mark http) start) 301 (funcall parse-fn http callbacks (the octet-vector data) :start start :end end :head-request head-request) 304 (subseq data (http-mark http) (or end (length data))))))))) 305 (values http header-complete-p completedp)))) 307 (defun find-boundary (content-type) 308 (declare (type string content-type)) 309 (let ((parsing-boundary nil)) 310 (parse-header-value-parameters content-type 311 :header-value-callback 312 (lambda (data start end) 313 (unless (string= data "multipart/form-data" 314 :start1 start :end1 end) 315 (return-from find-boundary nil))) 316 :header-parameter-key-callback 317 (lambda (data start end) 318 (when (string= data "boundary" 319 :start1 start :end1 end) 320 (setq parsing-boundary t))) 321 :header-parameter-value-callback 322 (lambda (data start end) 323 (when parsing-boundary 324 (return-from find-boundary (subseq data start end))))))) 327 (defconstant +cr+ (char-code #\Return)) 328 (defconstant +lf+ (char-code #\Linefeed)) 329 (defconstant +space+ (char-code #\Space)) 330 (defconstant +tab+ (char-code #\Tab)) 331 (defconstant +page+ (char-code #\Page)) 332 (defconstant +dash+ #.(char-code #\-)) 334 (define-constant +crlf+ 335 (make-array 2 :element-type '(unsigned-byte 8) 336 :initial-contents (list +cr+ +lf+)) 339 (deftype octet-vector (&optional (len '*)) 340 `(simple-array (unsigned-byte 8) (,len))) 342 (declaim (inline digit-byte-char-p 343 digit-byte-char-to-integer 345 alpha-byte-char-to-lower-char 346 alphanumeric-byte-char-p 349 (defun digit-byte-char-p (byte) 350 (declare (type (unsigned-byte 8) byte) 351 (optimize (speed 3) (safety 0))) 352 (<= #.(char-code #\0) byte #.(char-code #\9))) 354 (declaim (ftype (function ((unsigned-byte 8)) fixnum) digit-byte-char-to-integer)) 355 (defun digit-byte-char-to-integer (byte) 356 (declare (type (unsigned-byte 8) byte) 357 (optimize (speed 3) (safety 0))) 358 (the fixnum (- byte #.(char-code #\0)))) 360 (defun alpha-byte-char-p (byte) 361 (declare (type (unsigned-byte 8) byte) 362 (optimize (speed 3) (safety 0))) 363 (or (<= #.(char-code #\A) byte #.(char-code #\Z)) 364 (<= #.(char-code #\a) byte #.(char-code #\z)))) 366 (defun alpha-byte-char-to-lower-char (byte) 367 (declare (type (unsigned-byte 8) byte) 368 (optimize (speed 3) (safety 0))) 371 ((<= #.(char-code #\A) byte #.(char-code #\Z)) 372 (code-char (+ byte #x20))) 373 (T #+nil(<= #.(char-code #\a) byte #.(char-code #\z)) 376 (defun alphanumeric-byte-char-p (byte) 377 (declare (type (unsigned-byte 8) byte)) 378 (or (alpha-byte-char-p byte) 379 (digit-byte-char-p byte))) 381 (defun mark-byte-char-p (byte) 382 (declare (type (unsigned-byte 8) byte) 383 (optimize (speed 3) (safety 0))) 384 (or (= byte #.(char-code #\-)) 385 (= byte #.(char-code #\_)) 386 (= byte #.(char-code #\.)) 387 (= byte #.(char-code #\!)) 388 (= byte #.(char-code #\~)) 389 (= byte #.(char-code #\*)) 390 (= byte #.(char-code #\')) 391 (= byte #.(char-code #\()) 392 (= byte #.(char-code #\))))) 394 (declaim (ftype (function ((unsigned-byte 8)) (unsigned-byte 8)) byte-to-ascii-lower) 395 (inline byte-to-ascii-lower)) 396 (defun byte-to-ascii-lower (x) 397 (declare (type (unsigned-byte 8) x) 398 (optimize (speed 3) (safety 0))) 399 (if (<= #.(char-code #\A) x #.(char-code #\Z)) 400 (- x #.(- (char-code #\A) (char-code #\a))) 403 (declaim (inline ascii-octets-to-string)) 404 (defun ascii-octets-to-string (octets &key (start 0) (end (length octets))) 405 (declare (type octet-vector octets) 406 (type (unsigned-byte 64) start end) 407 (optimize (speed 3) (safety 0))) 408 (let* ((len (the (unsigned-byte 64) (- end start))) 409 (string (make-string len :element-type 'character))) 410 (declare (type (unsigned-byte 64) len) 411 (type simple-string string)) 415 (setf (aref string i) 416 (code-char (aref octets j)))))) 418 (declaim (inline ascii-octets-to-lower-string)) 419 (defun ascii-octets-to-lower-string (octets &key (start 0) (end (length octets))) 420 (declare (type octet-vector octets) 421 (type (unsigned-byte 64) start end) 422 (optimize (speed 3) (safety 0))) 423 (let* ((len (the (unsigned-byte 64) (- end start))) 424 (string (make-string len :element-type 'character))) 425 (declare (type (unsigned-byte 64) len) 426 (type simple-string string)) 430 (setf (aref string i) 431 (code-char (byte-to-ascii-lower (aref octets j))))))) 433 (defun append-byte-vectors (vec1 vec2) 434 (declare (type octet-vector vec1 vec2) 435 (optimize (speed 3) (safety 0))) 436 (let* ((vec1-len (length vec1)) 437 (vec2-len (length vec2)) 438 (result (make-array (+ vec1-len vec2-len) 439 :element-type '(unsigned-byte 8)))) 440 (declare (type octet-vector result)) 441 (replace result vec1 :start1 0) 442 (replace result vec2 :start1 vec1-len) 446 (defstruct (ll-multipart-parser (:constructor make-ll-multipart-parser 449 (let ((parser (make-http))) 450 (setf (http-state parser) +state-headers+) 452 (state 0 :type fixnum) 460 #.`(eval-when (:compile-toplevel :load-toplevel :execute) 462 for state in '(parsing-delimiter-dash-start 463 parsing-delimiter-dash 465 parsing-delimiter-end 466 parsing-delimiter-almost-done 467 parsing-delimiter-done 470 looking-for-delimiter 471 maybe-delimiter-start 472 maybe-delimiter-first-dash 473 maybe-delimiter-second-dash 476 collect `(defconstant ,(format-symbol t "+~A+" state) ,i))) 478 (defun http-multipart-parse (parser callbacks data &key (start 0) end) 479 (declare (type octet-vector data)) 480 (let* ((end (or end (length data))) 481 (boundary (map '(simple-array (unsigned-byte 8) (*)) #'char-code (ll-multipart-parser-boundary parser))) 482 (boundary-length (length boundary)) 483 (header-parser (ll-multipart-parser-header-parser parser))) 484 (declare (type octet-vector boundary)) 486 (return-from http-multipart-parse start)) 488 (macrolet ((with-body-cb (callback &body body) 489 `(handler-case (when-let ((,callback (callbacks-body callbacks))) 492 (error 'cb-body :error e)))) 493 (call-body-cb (&optional (end '(ll-multipart-parser-boundary-mark parser))) 494 (let ((g-end (gensym "END"))) 495 `(with-body-cb callback 496 (when (ll-multipart-parser-body-buffer parser) 497 (funcall callback parser 498 (ll-multipart-parser-body-buffer parser) 499 0 (length (ll-multipart-parser-body-buffer parser))) 500 (setf (ll-multipart-parser-body-buffer parser) nil)) 501 (when-let ((,g-end ,end)) 502 (funcall callback parser data 503 (ll-multipart-parser-body-mark parser) 505 (flush-boundary-buffer () 506 `(with-body-cb callback 507 (when (ll-multipart-parser-boundary-buffer parser) 508 (funcall callback parser 509 (ll-multipart-parser-boundary-buffer parser) 510 0 (length (ll-multipart-parser-boundary-buffer parser))) 511 (setf (ll-multipart-parser-boundary-buffer parser) nil))))) 513 (byte (aref data p))) 515 (log:debug (code-char byte)) 517 (macrolet ((go-state (tag &optional (advance 1)) 522 (otherwise `(incf p ,advance))) 523 (setf (ll-multipart-parser-state parser) ,tag) 525 (log:debug ,(princ-to-string tag)) 526 ,@(and (not (eql advance 0)) 529 (setq byte (aref data p)) 531 (log:debug (code-char byte)))) 533 (tagcasev (ll-multipart-parser-state parser) 534 (+parsing-delimiter-dash-start+ 535 (unless (= byte +dash+) 536 (go-state +header-field-start+ 0)) 537 (go-state +parsing-delimiter-dash+)) 539 (+parsing-delimiter-dash+ 540 (unless (= byte +dash+) 541 (error 'invalid-multipart-body)) 542 (go-state +parsing-delimiter+)) 545 (let ((end2 (+ p boundary-length))) 547 ((ll-multipart-parser-boundary-buffer parser) 548 (when (< (+ end (length (ll-multipart-parser-boundary-buffer parser)) -3) end2) 549 (setf (ll-multipart-parser-boundary-buffer parser) 550 (concatenate 'octet-vector 551 (ll-multipart-parser-boundary-buffer parser) 554 (let ((data2 (make-array boundary-length :element-type '(unsigned-byte 8))) 555 (boundary-buffer-length (length (ll-multipart-parser-boundary-buffer parser)))) 556 (replace data2 (ll-multipart-parser-boundary-buffer parser) 559 :start1 (- boundary-buffer-length 2)) 560 (unless (search boundary data2) 562 (when (ll-multipart-parser-body-mark parser) 564 (flush-boundary-buffer) 565 (go-state +looking-for-delimiter+)) 566 (error 'invalid-boundary)) 567 (go-state +parsing-delimiter-end+ (- boundary-length boundary-buffer-length -2)))) 570 (setf (ll-multipart-parser-boundary-buffer parser) 571 (if (ll-multipart-parser-boundary-buffer parser) 572 (concatenate 'octet-vector 573 (ll-multipart-parser-boundary-buffer parser) 574 (subseq data (max 0 (- p 2)))) 575 (subseq data (max 0 (- p 2))))) 578 (unless (search boundary data :start2 p :end2 end2) 580 (when (ll-multipart-parser-body-mark parser) 581 (go-state +looking-for-delimiter+)) 582 (error 'invalid-boundary)) 583 (go-state +parsing-delimiter-end+ boundary-length))))) 585 (+parsing-delimiter-end+ 587 (+cr+ (go-state +parsing-delimiter-almost-done+)) 588 (+lf+ (go-state +parsing-delimiter-almost-done+ 0)) 589 (+dash+ (go-state +body-almost-done+)) 592 (when (ll-multipart-parser-body-mark parser) 594 (flush-boundary-buffer) 595 (go-state +looking-for-delimiter+)) 596 (error 'invalid-boundary)))) 598 (+parsing-delimiter-almost-done+ 599 (unless (= byte +lf+) 600 (error 'invalid-boundary)) 601 (when (ll-multipart-parser-body-mark parser) 603 (when (ll-multipart-parser-boundary-mark parser) 605 (when-let ((callback (callbacks-message-complete callbacks))) 606 (handler-case (funcall callback parser) 608 (error 'cb-message-complete :error e))))) 609 (go-state +parsing-delimiter-done+)) 611 (+parsing-delimiter-done+ 612 (when-let ((callback (callbacks-message-begin callbacks))) 613 (handler-case (funcall callback parser) 615 (error 'cb-message-begin :error e)))) 616 (setf (ll-multipart-parser-body-mark parser) p) 617 (go-state +header-field-start+ 0)) 619 (+header-field-start+ 620 (let ((next (parse-headers header-parser callbacks data p end))) 621 (setq p (1- next)) ;; XXX 622 ;; parsing headers done 623 (when (= (http-state header-parser) +state-body+) 624 (when-let ((callback (callbacks-headers-complete callbacks))) 625 (handler-case (funcall callback parser) 627 (error 'cb-headers-complete :error e)))) 628 (setf (http-state header-parser) +state-headers+)) 629 (go-state +body-start+ 0))) 632 (setf (ll-multipart-parser-body-mark parser) (1+ p)) 633 (go-state +looking-for-delimiter+)) 635 (+looking-for-delimiter+ 636 (setf (ll-multipart-parser-boundary-mark parser) nil) 638 (+cr+ (setf (ll-multipart-parser-boundary-mark parser) p) 639 (go-state +maybe-delimiter-start+)) 640 (otherwise (go-state +looking-for-delimiter+)))) 642 (+maybe-delimiter-start+ 643 (unless (= byte +lf+) 644 (go-state +looking-for-delimiter+ 0)) 645 (go-state +maybe-delimiter-first-dash+)) 647 (+maybe-delimiter-first-dash+ 649 (go-state +maybe-delimiter-second-dash+) 652 (setf (ll-multipart-parser-boundary-mark parser) p) 653 (go-state +maybe-delimiter-start+)) 654 (go-state +looking-for-delimiter+)))) 656 (+maybe-delimiter-second-dash+ 658 (go-state +parsing-delimiter+) 659 (go-state +looking-for-delimiter+))) 663 (+dash+ (go-state +body-done+ 0)) 664 (otherwise (error 'invalid-multipart-body)))) 667 (when (ll-multipart-parser-body-mark parser) 669 (setf (ll-multipart-parser-body-buffer parser) nil) 671 (when-let ((callback (callbacks-message-complete callbacks))) 672 (handler-case (funcall callback parser) 674 (error 'cb-message-complete :error e)))) 675 (setf (ll-multipart-parser-body-mark parser) nil)) 678 (when (ll-multipart-parser-body-mark parser) 679 (when (<= +looking-for-delimiter+ 680 (ll-multipart-parser-state parser) 681 +maybe-delimiter-second-dash+) 682 (call-body-cb (or (ll-multipart-parser-boundary-mark parser) p))) 683 ;; buffer the last part 684 (when (ll-multipart-parser-boundary-mark parser) 685 (setf (ll-multipart-parser-body-buffer parser) 686 (if (ll-multipart-parser-body-buffer parser) 687 (concatenate 'octet-vector 688 (ll-multipart-parser-body-buffer parser) 689 (subseq data (ll-multipart-parser-boundary-mark parser))) 690 (subseq data (ll-multipart-parser-boundary-mark parser))))) 692 (setf (ll-multipart-parser-body-mark parser) 0 693 (ll-multipart-parser-boundary-mark parser) nil)) 696 (defun make-multipart-parser (content-type callback) 697 (check-type content-type string) 698 (let ((boundary (find-boundary content-type))) 700 (return-from make-multipart-parser nil)) 702 (let ((parser (make-ll-multipart-parser :boundary boundary)) 703 (headers (make-hash-table :test 'equal)) 704 parsing-content-disposition 708 (body-buffer (make-smart-buffer)) 710 (flet ((collect-prev-header-value () 711 (when header-value-buffer 713 (babel:octets-to-string 714 header-value-buffer))) 715 (when parsing-content-disposition 718 (field-meta (make-hash-table :test 'equal))) 719 (parse-header-value-parameters header-value 720 :header-parameter-key-callback 721 (lambda (data start end) 723 (string-downcase (subseq data start end)))) 724 :header-parameter-value-callback 725 (lambda (data start end) 726 (setf (gethash parsing-key field-meta) 727 (subseq data start end)))) 729 (setf (gethash parsing-header-field headers) 733 :header-field (lambda (parser data start end) 734 (declare (ignore parser)) 735 (collect-prev-header-value) 736 (setq header-value-buffer (make-concatenated-xsubseqs)) 739 (ascii-octets-to-lower-string data :start start :end end))) 740 (setq parsing-content-disposition 741 (string= header-name "content-disposition")) 742 (setq parsing-header-field header-name))) 743 :header-value (lambda (parser data start end) 744 (declare (ignore parser)) 745 (xnconcf header-value-buffer 746 (subseq (subseq data start end) 0))) 747 :headers-complete (lambda (parser) 748 (declare (ignore parser)) 749 (collect-prev-header-value)) 750 :message-complete (lambda (parser) 751 (declare (ignore parser)) 753 (gethash "name" field-meta) 757 (setq headers (make-hash-table :test 'equal) 759 header-value-buffer nil)) 760 :body (lambda (parser data start end) 761 (declare (ignore parser)) 762 (write-sequence data body-buffer start end))))) 764 (http-multipart-parse parser callbacks data) 765 (= (ll-multipart-parser-state parser) +body-done+))))) 771 (deftype status-code () '(integer 0 10000)) 776 (defconstant +state-first-line+ 0) 777 (defconstant +state-headers+ 1) 778 (defconstant +state-chunk-size+ 2) 779 (defconstant +state-body+ 3) 780 (defconstant +state-chunk-body-end-crlf+ 4) 781 (defconstant +state-trailing-headers+ 5) 783 (defstruct (http (:conc-name :http-)) 784 (method nil :type symbol) 785 (major-version 0 :type fixnum) 786 (minor-version 9 :type fixnum) 787 (status 0 :type status-code) 788 (content-length nil :type (or null integer)) 789 (chunked-p nil :type boolean) 790 (upgrade-p nil :type boolean) 795 (header-read 0 :type fixnum) 796 (mark -1 :type fixnum) 797 (state +state-first-line+ :type fixnum)) 799 (defun http-version (http) 801 (+ (http-major-version http) 802 (/ (http-minor-version http) 10)))) 804 (defstruct (http-request (:include http) 808 (defstruct (http-response (:include http) 813 (define-condition http-error (protocol-error) 816 (lambda (condition stream) 817 (format stream "~A: ~A" (type-of condition) (slot-value condition 'description))))) 821 ;; Callback-related errors 823 (define-condition callback-error (http-error) 824 ((error :initarg :error 826 (:report (lambda (condition stream) 827 (with-slots (description error) condition 828 (format stream "Callback Error: ~A~:[~;~:*~% ~A~]" 832 (define-condition cb-message-begin (callback-error) 833 ((description :initform "the message-begin callback failed"))) 834 (define-condition cb-url (callback-error) 835 ((description :initform "the url callback failed"))) 836 (define-condition cb-first-line (callback-error) 837 ((description :initform "the first line callback failed"))) 838 (define-condition cb-header-field (callback-error) 839 ((description :initform "the header-field callback failed"))) 840 (define-condition cb-header-value (callback-error) 841 ((description :initform "the header-value callback failed"))) 842 (define-condition cb-headers-complete (callback-error) 843 ((description :initform "the headers-complete callback failed"))) 844 (define-condition cb-body (callback-error) 845 ((description :initform "the body callback failed"))) 846 (define-condition cb-message-complete (callback-error) 847 ((description :initform "the message-complete callback failed"))) 848 (define-condition cb-status (callback-error) 849 ((description :initform "the status callback failed"))) 852 ;; Parsing-related errors 854 (define-condition parsing-error (http-error) ()) 856 (define-condition invalid-eof-state (parsing-error) 857 ((description :initform "stream ended at an unexpected time"))) 858 (define-condition header-overflow (parsing-error) 859 ((description :initform "too many header bytes seen; overflow detected"))) 860 (define-condition closed-connection (parsing-error) 861 ((description :initform "data received after completed connection: close message"))) 862 (define-condition invalid-version (parsing-error) 863 ((description :initform "invalid HTTP version"))) 864 (define-condition invalid-status (parsing-error) 865 ((description :initform "invalid HTTP status code") 866 (status-code :initarg :status-code 868 (:report (lambda (condition stream) 869 (with-slots (description status-code) condition 870 (format stream "~A: ~A~:[~;~:* (Code=~A)~]" 874 (define-condition invalid-method (parsing-error) 875 ((description :initform "invalid HTTP method"))) 876 (define-condition invalid-url (parsing-error) 877 ((description :initform "invalid URL"))) 878 (define-condition invalid-host (parsing-error) 879 ((description :initform "invalid host"))) 880 (define-condition invalid-port (parsing-error) 881 ((description :initform "invalid port"))) 882 (define-condition invalid-path (parsing-error) 883 ((description :initform "invalid path"))) 884 (define-condition invalid-query-string (parsing-error) 885 ((description :initform "invalid query string"))) 886 (define-condition invalid-fragment (parsing-error) 887 ((description :initform "invalid fragment"))) 888 (define-condition lf-expected (parsing-error) 889 ((description :initform "LF character expected"))) 890 (define-condition invalid-header-token (parsing-error) 891 ((description :initform "invalid character in header"))) 892 (define-condition invalid-content-length (parsing-error) 893 ((description :initform "invalid character in content-length header"))) 894 (define-condition invalid-chunk-size (parsing-error) 895 ((description :initform "invalid character in chunk size header"))) 896 (define-condition invalid-constant (parsing-error) 897 ((description :initform "invalid constant string"))) 899 (define-condition invalid-internal-state (parsing-error) 900 ((description :initform "encountered unexpected internal state") 901 (code :initarg :code)) 903 (lambda (condition stream) 904 (format stream "~A: ~A (Code=~A)" 906 (slot-value condition 'description) 907 (slot-value condition 'code))))) 908 (define-condition strict-error (parsing-error) 909 ((description :initform "strict mode assertion failed") 910 (form :initarg :form)) 912 (lambda (condition stream) 913 (format stream "~A: ~A~% ~A" 915 (slot-value condition 'description) 916 (slot-value condition 'form))))) 917 (define-condition paused-error (parsing-error) 918 ((description :initform "parser is paused"))) 919 (define-condition unknown-error (parsing-error) 920 ((description :initform "an unknown error occured"))) 926 (define-condition multipart-parsing-error (http-error) ()) 928 (define-condition invalid-multipart-body (multipart-parsing-error) 929 ((description :initform "invalid multipart body"))) 930 (define-condition invalid-boundary (multipart-parsing-error) 931 ((description :initform "invalid boundary"))) 935 ;; Header value parsing 937 (define-condition header-value-parsing-error (multipart-parsing-error) ()) 939 (define-condition invalid-header-value (header-value-parsing-error) 940 ((description :initform "invalid header value"))) 941 (define-condition invalid-parameter-key (header-value-parsing-error) 942 ((description :initform "invalid parameter key"))) 943 (define-condition invalid-parameter-value (header-value-parsing-error) 944 ((description :initform "invalid parameter value"))) 950 (declaim (type fixnum +max-header-line+)) 951 (defconstant +max-header-line+ 1024 952 "Maximum number of header lines allowed. 954 This restriction is for protecting users' application 955 against denial-of-service attacks where the attacker feeds 956 us a never-ending header that the application keeps buffering.") 962 (deftype pointer () 'integer) 969 (message-begin nil :type (or null function)) ;; 1 arg 970 (url nil :type (or null function)) 971 (first-line nil :type (or null function)) 972 (status nil :type (or null function)) 973 (header-field nil :type (or null function)) 974 (header-value nil :type (or null function)) 975 (headers-complete nil :type (or null function)) ;; 1 arg 976 (body nil :type (or null function)) 977 (message-complete nil :type (or null function))) 979 (defmacro callback-data (name http callbacks data start end) 980 (with-gensyms (callback e) 981 `(when-let ((,callback (,(format-symbol t "~A-~A" :callbacks name) ,callbacks))) 982 (handler-bind ((error 984 (unless (typep ,e 'http-error) 985 (error ',(format-symbol t "~A-~A" :cb name) 988 (funcall ,callback ,http ,data ,start ,end))))) 990 (defmacro callback-notify (name http callbacks) 991 (with-gensyms (callback e) 992 `(when-let ((,callback (,(format-symbol t "~A-~A" :callbacks name) ,callbacks))) 993 (handler-bind ((error 995 (unless (typep ,e 'http-error) 996 (error ',(format-symbol t "~A-~A" :cb name) 999 (funcall ,callback ,http))))) 1005 (define-condition eof () ()) 1007 (define-condition expect-failed (parsing-error) 1008 ((description :initform "expect failed"))) 1014 (declaim (type (simple-array character (128)) +tokens+)) 1015 (define-constant +tokens+ 1017 :element-type 'character 1019 '( #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul 1020 #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul 1021 #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul 1022 #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul 1023 #\Nul #\! #\Nul #\# #\$ #\% #\& #\' 1024 #\Nul #\Nul #\* #\+ #\Nul #\- #\. #\Nul 1025 #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 1026 #\8 #\9 #\Nul #\Nul #\Nul #\Nul #\Nul #\Nul 1027 #\Nul #\a #\b #\c #\d #\e #\f #\g 1028 #\h #\i #\j #\k #\l #\m #\n #\o 1029 #\p #\q #\r #\s #\t #\u #\v #\w 1030 #\x #\y #\z #\Nul #\Nul #\Nul #\^ #\_ 1031 #\` #\a #\b #\c #\d #\e #\f #\g 1032 #\h #\i #\j #\k #\l #\m #\n #\o 1033 #\p #\q #\r #\s #\t #\u #\v #\w 1034 #\x #\y #\z #\Nul #\| #\Nul #\~ #\Nul )) 1037 (declaim (type (simple-array fixnum (128)) +unhex+)) 1038 (define-constant +unhex+ 1039 (make-array 128 :element-type 'fixnum :initial-contents 1040 '(-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1041 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1042 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1043 0 1 2 3 4 5 6 7 8 9 -1 -1 -1 -1 -1 -1 1044 -1 10 11 12 13 14 15 -1 -1 -1 -1 -1 -1 -1 -1 -1 1045 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1046 -1 10 11 12 13 14 15 -1 -1 -1 -1 -1 -1 -1 -1 -1 1047 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1)) 1050 (defun unhex-byte (byte) 1051 (aref +unhex+ byte)) 1056 (defun parse-method (data start end) 1057 (declare (type octet-vector data) 1058 (type pointer start end)) 1059 (with-octets-parsing (data :start start :end end) 1060 (return-from parse-method 1064 ("CONNECT" :CONNECT) 1066 ("CHECKOUT" :CHECKOUT) 1072 ("MKCALENDAR" :MKCALENDAR) 1073 ("MKACTIVITY" :MKACTIVITY) 1076 ("M-SEARCH" :M-SEARCH) 1078 ("OPTIONS" :OPTIONS) 1080 ("PROPFIND" :PROPFIND) 1081 ("PROPPATCH" :PROPPATCH) 1087 ("SUBSCRIBE" :SUBSCRIBE) 1090 ("UNSUBSCRIBE" :UNSUBSCRIBE) 1091 (otherwise (error 'invalid-method))) 1092 (unless (= (current) +space+) 1093 (error 'invalid-method))) 1097 (defun parse-url (data start end) 1098 (declare (type octet-vector data) 1099 (type pointer start end)) 1100 (flet ((url-char-byte-p (byte) 1101 (or (<= (char-code #\!) byte (char-code #\~)) 1103 (with-octets-parsing (data :start start :end end) 1104 (skip-while url-char-byte-p) 1105 (return-from parse-url (pos))) 1108 (defun parse-http-version (data start end) 1109 (declare (type octet-vector data) 1110 (type pointer start end)) 1112 (with-octets-parsing (data :start start :end end) 1113 (or (match? "HTTP/") 1114 (return-from parse-http-version (values nil nil (pos)))) 1115 (if (digit-byte-char-p (current)) 1116 (setq major (digit-byte-char-to-integer (current))) 1117 (return-from parse-http-version (values nil nil (pos)))) 1119 (or (skip? #\.) (return-from parse-http-version (values nil nil (pos)))) 1120 (if (digit-byte-char-p (current)) 1121 (setq minor (digit-byte-char-to-integer (current))) 1122 (return-from parse-http-version (values nil nil (pos)))) 1124 (return-from parse-http-version 1125 (values major minor (pos)))) 1128 (defun parse-status-code (http callbacks data start end) 1129 (declare (type octet-vector data) 1130 (type pointer start end)) 1131 (or (with-octets-parsing (data :start start :end end) 1132 (if (digit-byte-char-p (current)) 1133 (setf (http-status http) (digit-byte-char-to-integer (current))) 1134 (error 'invalid-status)) 1138 ((digit-byte-char-p (current)) 1139 (setf (http-status http) 1140 (+ (the fixnum (* 10 (http-status http))) 1141 (digit-byte-char-to-integer (current)))) 1142 (when (< 999 (http-status http)) 1143 (error 'invalid-status :status-code (http-status http)))) 1144 ((= (current) +space+) 1145 ;; Reading the status text 1147 (let ((status-text-start (pos))) 1148 (skip* (not #\Return)) 1151 (callback-data :status http callbacks data status-text-start (- (pos) 1))) 1158 (T (error 'invalid-status)))) 1162 (defun parse-header-field-and-value (http callbacks data start end) 1163 (declare (type octet-vector data) 1164 (type pointer start end)) 1166 (with-octets-parsing (data :start start :end end) 1167 (let ((field-start (pos)) 1169 (macrolet ((skip-until-value-start-and (&body body) 1171 ;; skip #\: and leading spaces 1173 (skip* #\Space #\Tab) 1176 ;; continue to the next line 1180 ((or (= (current) +space+) 1181 (= (current) +tab+)) 1182 (skip* #\Space #\Tab) 1183 (if (= (current) +cr+) 1188 (callback-data :header-field http callbacks data field-start field-end) 1189 (callback-data :header-value http callbacks data (pos) (pos))) 1193 (callback-data :header-field http callbacks data field-start field-end) 1194 (callback-data :header-value http callbacks data (pos) (pos))))) 1196 (handle-otherwise () 1198 ;; skip until field end 1199 (do ((char (aref +tokens+ (current)) 1200 (aref +tokens+ (current)))) 1201 ((= (current) (char-code #\:))) 1202 (declare (type character char)) 1203 (when (char= char #\Nul) 1204 (error 'invalid-header-token)) 1207 (setq field-end (pos)) 1208 (skip-until-value-start-and 1210 (parse-header-value http callbacks data (pos) end field-start field-end))))) 1211 (expect-field-end (&body body) 1212 `(if (= (current) #.(char-code #\:)) 1214 (setq field-end (pos)) 1216 (handle-otherwise)))) 1220 (skip-until-value-start-and 1221 (multiple-value-bind (value-start value-end next content-length) 1222 (parse-header-value-content-length data (pos) end) 1223 (declare (type pointer next)) 1224 (setf (http-content-length http) content-length) 1226 (callback-data :header-field http callbacks data field-start field-end) 1227 (callback-data :header-value http callbacks data value-start value-end))))) 1228 ("transfer-encoding" 1230 (skip-until-value-start-and 1231 (multiple-value-bind (value-start value-end next chunkedp) 1232 (parse-header-value-transfer-encoding data (pos) end) 1233 (declare (type pointer next)) 1234 (setf (http-chunked-p http) chunkedp) 1236 (callback-data :header-field http callbacks data field-start field-end) 1237 (callback-data :header-value http callbacks data value-start value-end))))) 1240 (skip-until-value-start-and 1241 (setf (http-upgrade-p http) T) 1242 (let ((value-start (pos))) 1243 (skip* (not #\Return)) 1246 (callback-data :header-field http callbacks data field-start field-end) 1247 (callback-data :header-value http callbacks data value-start (- (pos) 2)))))) 1248 (otherwise (handle-otherwise))))) 1252 (defun parse-header-value (http callbacks data start end &optional field-start field-end) 1253 (or (with-octets-parsing (data :start start :end end) 1254 (skip* (not #\Return)) 1258 (callback-data :header-field http callbacks data field-start field-end)) 1259 (callback-data :header-value http callbacks data start (- (pos) 2)) 1263 (defun parse-header-value-transfer-encoding (data start end) 1264 (declare (type octet-vector data) 1265 (type pointer start end)) 1266 (with-octets-parsing (data :start start :end end) 1269 (if (= (current) +cr+) 1273 (return-from parse-header-value-transfer-encoding 1274 (values start (- (pos) 2) (pos) t))) 1276 (skip+ (not #\Return)) 1279 (return-from parse-header-value-transfer-encoding 1280 (values start (- (pos) 2) (pos) nil))))) 1282 (skip* (not #\Return)) 1285 (return-from parse-header-value-transfer-encoding 1286 (values start (- (pos) 2) (pos) nil))))) 1289 (defun parse-header-value-content-length (data start end) 1290 (declare (type octet-vector data) 1291 (type pointer start end)) 1292 (let ((content-length 0)) 1293 (declare (type integer content-length)) 1294 (with-octets-parsing (data :start start :end end) 1295 (if (digit-byte-char-p (current)) 1296 (setq content-length (digit-byte-char-to-integer (current))) 1297 (error 'invalid-content-length)) 1301 ((digit-byte-char-p (current)) 1302 (setq content-length 1303 (+ (* 10 content-length) 1304 (digit-byte-char-to-integer (current))))) 1308 (return-from parse-header-value-content-length 1309 (values start (- (pos) 2) (pos) content-length))) 1310 ((= (current) +space+) 1313 (t (error 'invalid-content-length))))) 1316 (defun parse-header-line (http callbacks data start end) 1317 (declare (type octet-vector data) 1318 (type pointer start end)) 1319 (when (<= end start) 1321 (let ((current (aref data start))) 1322 (declare (type (unsigned-byte 8) current)) 1324 ((or (= current +tab+) 1325 (= current +space+)) 1326 (parse-header-value http callbacks data start end)) 1328 (parse-header-field-and-value http callbacks data start end)) 1333 (setq current (aref data start)) 1334 (unless (= current +lf+) 1335 (error 'expect-failed)) 1336 (values (1+ start) t))))) 1338 (defun parse-headers (http callbacks data start end) 1339 (declare (type http http) 1340 (type octet-vector data) 1341 (type pointer start end)) 1342 (or (with-octets-parsing (data :start start :end end) 1344 (when (= (current) +cr+) 1346 (if (= (current) +lf+) 1347 (return-from parse-headers (1+ (pos))) 1348 (error 'expect-failed))) 1350 (advance-to* (parse-header-field-and-value http callbacks data start end)) 1352 (setf (http-mark http) (pos)) 1354 (when (= +max-header-line+ (the fixnum (incf (http-header-read http)))) 1355 (error 'header-overflow)) 1356 (multiple-value-bind (next endp) 1357 (parse-header-line http callbacks data (pos) end) 1361 (setf (http-mark http) (pos))) 1362 (setf (http-mark http) (pos)) 1363 (setf (http-state http) +state-body+) 1368 (defun read-body-data (http callbacks data start end) 1369 (declare (type http http) 1370 (type octet-vector data) 1371 (type pointer start end)) 1372 (let ((readable-count (the pointer (- end start)))) 1373 (declare (dynamic-extent readable-count) 1374 (type pointer readable-count)) 1375 (if (<= (http-content-length http) readable-count) 1376 (let ((body-end (+ start (http-content-length http)))) 1377 (declare (dynamic-extent body-end)) 1378 (setf (http-content-length http) 0) 1379 (callback-data :body http callbacks data start body-end) 1380 (setf (http-mark http) body-end) 1381 (values body-end t)) 1382 ;; still needs to read 1384 (decf (http-content-length http) readable-count) 1385 (callback-data :body http callbacks data start end) 1386 (setf (http-mark http) end) 1387 (values end nil))))) 1389 (defun http-message-needs-eof-p (http) 1390 (let ((status-code (http-status http))) 1391 (declare (type status-code status-code)) 1392 (when (= status-code 0) ;; probably request 1393 (return-from http-message-needs-eof-p nil)) 1395 (when (or (< 99 status-code 200) ;; 1xx e.g. Continue 1396 (= status-code 204) ;; No Content 1397 (= status-code 304)) ;; Not Modified 1398 (return-from http-message-needs-eof-p nil)) 1400 (when (or (http-chunked-p http) 1401 (http-content-length http)) 1402 (return-from http-message-needs-eof-p nil)) 1405 (defun parse-http-body (http callbacks data start end requestp) 1406 (declare (type http http) 1407 (type octet-vector data) 1408 (type pointer start end)) 1409 (macrolet ((message-complete () 1411 (callback-notify :message-complete http callbacks) 1412 (setf (http-state http) +state-first-line+)))) 1413 (case (http-content-length http) 1415 ;; Content-Length header given but zero: Content-Length: 0\r\n 1420 (not (http-message-needs-eof-p http))) 1421 ;; Assume content-length 0 - read the next 1424 ;; By returning "start", we'll continue 1425 ;; to parse the next request in case if 1426 ;; HTTP pipelining is used. Probably 1427 ;; we need some way to enable (or disable) 1428 ;; HTTP pipelining support. 1432 (callback-data :body http callbacks data start end) 1433 (setf (http-mark http) end) 1437 ;; Content-Length header given and non-zero 1438 (multiple-value-bind (next completedp) 1439 (read-body-data http callbacks data start end) 1444 (defun parse-chunked-body (http callbacks data start end) 1445 (declare (type http http) 1446 (type octet-vector data) 1447 (type pointer start end)) 1450 (return-from parse-chunked-body start)) 1452 (or (with-octets-parsing (data :start start :end end) 1455 ((= (http-state http) +state-chunk-size+) 1457 ((= (http-state http) +state-body+) 1459 ((= (http-state http) +state-chunk-body-end-crlf+) 1461 ((= (http-state http) +state-trailing-headers+) 1462 (go trailing-headers)) 1463 (T (error 'invalid-internal-state :code (http-state http)))) 1466 (let ((unhex-val (unhex-byte (current)))) 1467 (declare (type fixnum unhex-val) 1468 (dynamic-extent unhex-val)) 1469 (when (= unhex-val -1) 1470 (error 'invalid-chunk-size)) 1471 (setf (http-content-length http) unhex-val) 1475 (if (= (current) +cr+) 1483 (setq unhex-val (unhex-byte (current))) 1487 ((or (= (current) (char-code #\;)) 1488 (= (current) (char-code #\Space))) 1489 (skip* (not #\Return)) 1495 (t (error 'invalid-chunk-size)))) 1496 (t (setf (http-content-length http) 1497 (+ (* 16 (http-content-length http)) unhex-val))))))) 1498 (setf (http-state http) +state-body+) 1500 (return-from parse-chunked-body (pos)) 1501 (setf (http-mark http) (pos)))) 1505 ((zerop (http-content-length http)) 1507 (setf (http-state http) +state-trailing-headers+) 1508 (go trailing-headers)) 1510 (multiple-value-bind (next completedp) 1511 (read-body-data http callbacks data (pos) end) 1512 (declare (type pointer next)) 1514 (return-from parse-chunked-body (pos))) 1515 (setf (http-state http) +state-chunk-body-end-crlf+) 1516 (advance-to next)))) 1523 (setf (http-state http) +state-chunk-size+) 1525 (return-from parse-chunked-body (pos)))) 1526 (setf (http-mark http) (pos)) 1530 (return-from parse-chunked-body 1531 (prog1 (parse-headers http callbacks data (pos) end) 1532 (callback-notify :message-complete http callbacks))))) 1535 (defun parse-request (http callbacks data &key (start 0) end (head-request nil)) 1536 (declare (type http http) 1537 (type octet-vector data) 1538 (ignorable head-request)) 1539 (let ((end (or end (length data)))) 1540 (declare (type pointer start end)) 1541 (handler-bind ((match-failed 1543 (declare (ignore c)) 1544 (error 'expect-failed)))) 1545 (with-octets-parsing (data :start start :end end) 1546 (setf (http-mark http) start) 1549 (let ((state (http-state http))) 1550 (declare (type fixnum state)) 1552 ((= +state-first-line+ state) 1554 ((= +state-headers+ state) 1556 ((<= +state-chunk-size+ state +state-trailing-headers+) 1558 (T (error 'invalid-internal-state :code state)))) 1561 ;; skip first empty line (some clients add CRLF after POST content) 1562 (when (= (current) +cr+) 1568 (return-from parse-request (pos))))) 1570 (setf (http-mark http) (pos)) 1571 (callback-notify :message-begin http callbacks) 1573 (multiple-value-bind (method next) 1574 (parse-method data (pos) end) 1575 (declare (type pointer next)) 1576 (setf (http-method http) method) 1579 (let ((url-start-mark (pos)) 1580 (url-end-mark (parse-url data (pos) end))) 1581 (declare (type pointer url-start-mark url-end-mark)) 1582 (tagbody retry-url-parse 1583 (advance-to* url-end-mark) 1590 (callback-data :url http callbacks data url-start-mark url-end-mark) 1593 (t (multiple-value-bind (major minor next) 1594 (parse-http-version data (pos) end) 1595 (declare (type pointer next)) 1597 ;; Invalid HTTP version. 1598 ;; Assuming it's also a part of URI. 1599 (let ((new-url-end-mark (parse-url data next end))) 1600 (when (= url-end-mark new-url-end-mark) 1601 (error 'invalid-version)) 1602 (setq url-end-mark new-url-end-mark) 1603 (go retry-url-parse))) 1604 (callback-data :url http callbacks data url-start-mark url-end-mark) 1605 (setf (http-major-version http) major 1606 (http-minor-version http) minor) 1609 (skip #\Newline))))) 1611 (setf (http-mark http) (pos)) 1612 (setf (http-state http) +state-headers+) 1613 (callback-notify :first-line http callbacks) 1616 (advance-to* (parse-headers http callbacks data (pos) end)) 1618 (callback-notify :headers-complete http callbacks) 1619 (setf (http-header-read http) 0) 1621 ;; Exit, the rest of the connect is in a different protocol. 1622 (when (http-upgrade-p http) 1623 (setf (http-state http) +state-first-line+) 1624 (callback-notify :message-complete http callbacks) 1625 (return-from parse-request (pos))) 1627 (setf (http-state http) 1628 (if (http-chunked-p http) 1633 (if (http-chunked-p http) 1634 (advance-to* (parse-chunked-body http callbacks data (pos) end)) 1636 (and (advance-to* (parse-http-body http callbacks data (pos) end t)) 1638 (return-from parse-request (pos))))) 1641 (defun parse-response (http callbacks data &key (start 0) end (head-request nil)) 1642 (declare (type http http) 1643 (type octet-vector data)) 1646 (declare (type pointer start end)) 1647 (handler-bind ((match-failed 1649 (declare (ignore c)) 1650 (error 'expect-failed)))) 1651 (with-octets-parsing (data :start start :end end) 1652 (setf (http-mark http) start) 1655 (let ((state (http-state http))) 1656 (declare (type fixnum state)) 1658 ((= +state-first-line+ state) 1660 ((= +state-headers+ state) 1662 ((<= +state-chunk-size+ state +state-trailing-headers+) 1664 (T (error 'invalid-internal-state :code state)))) 1667 (setf (http-mark http) (pos)) 1668 (callback-notify :message-begin http callbacks) 1670 (multiple-value-bind (major minor next) 1671 (parse-http-version data (pos) end) 1672 (declare (type pointer next)) 1673 (setf (http-major-version http) major 1674 (http-minor-version http) minor) 1678 ((= (current) +space+) 1680 (advance-to (parse-status-code http callbacks data (pos) end))) 1683 (T (error 'invalid-version))) 1685 (setf (http-mark http) (pos)) 1686 (setf (http-state http) +state-headers+) 1687 (callback-notify :first-line http callbacks) 1690 (advance-to* (parse-headers http callbacks data (pos) end)) 1692 (callback-notify :headers-complete http callbacks) 1693 (setf (http-header-read http) 0) 1694 (setf (http-state http) 1695 (if (http-chunked-p http) 1700 (callback-notify :message-complete http callbacks) 1701 (setf (http-state http) +state-first-line+) 1702 (return-from parse-response (pos))) 1705 (if (http-chunked-p http) 1706 (advance-to* (parse-chunked-body http callbacks data (pos) end)) 1708 (advance-to* (parse-http-body http callbacks data (pos) end nil)) 1711 (return-from parse-response (pos))))) 1714 (defun parse-header-value-parameters (data &key 1715 header-value-callback 1716 header-parameter-key-callback 1717 header-parameter-value-callback) 1718 (declare (type simple-string data) 1719 (optimize (speed 3) (safety 2))) 1721 (let* ((header-name-mark 0) 1723 parameter-value-mark 1724 parsing-quoted-string-p 1727 (char (aref data p))) 1728 (declare (type character char)) 1731 (return-from parse-header-value-parameters 0)) 1733 (macrolet ((go-state (state &optional (advance 1)) 1734 `(locally (declare (optimize (speed 3) (safety 0))) 1738 (setq char (aref data p)) 1740 (flet ((tokenp (char) 1741 (declare (optimize (speed 3) (safety 0))) 1742 (let ((byte (char-code char))) 1744 (not (char= (the character (aref +tokens+ byte)) #\Nul)))))) 1746 parsing-header-value-start 1749 (go-state parsing-header-value)) 1751 (unless (tokenp char) 1752 (error 'invalid-header-value)) 1753 (setq header-name-mark p) 1754 (go-state parsing-header-value 0))) 1756 parsing-header-value 1759 (when header-value-callback 1760 (funcall (the function header-value-callback) 1761 data header-name-mark p)) 1762 (setq header-name-mark nil) 1763 (go-state looking-for-parameter-key)) 1764 (otherwise (go-state parsing-header-value))) 1766 looking-for-parameter-key 1768 ((#\Space #\Tab #\; #\Newline #\Return) 1769 (go-state looking-for-parameter-key)) 1771 (unless (tokenp char) 1772 (error 'invalid-parameter-key)) 1773 (setq parameter-key-mark p) 1774 (go-state parsing-parameter-key))) 1776 parsing-parameter-key 1779 (assert parameter-key-mark) 1780 (when header-parameter-key-callback 1781 (funcall (the function header-parameter-key-callback) 1782 data parameter-key-mark p)) 1783 (setq parameter-key-mark nil) 1784 (go-state parsing-parameter-value-start)) 1786 (unless (tokenp char) 1787 (error 'invalid-parameter-key)) 1788 (go-state parsing-parameter-key))) 1790 parsing-parameter-value-start 1794 (setq parameter-value-mark (1+ p)) 1795 (setq parsing-quoted-string-p t) 1796 (go-state parsing-parameter-quoted-value)) 1797 ((#.+space+ #.+tab+) 1798 (go-state parsing-parameter-value-start)) 1800 (setq parameter-value-mark p) 1801 (go-state parsing-parameter-value 0))) 1803 parsing-parameter-quoted-value 1804 (if (char= char #\") 1806 (assert parameter-value-mark) 1807 (setq parsing-quoted-string-p nil) 1808 (when header-parameter-value-callback 1809 (funcall (the function header-parameter-value-callback) 1810 data parameter-value-mark p)) 1811 (setq parameter-value-mark nil) 1812 (go-state looking-for-parameter-key)) 1813 (go-state parsing-parameter-quoted-value)) 1815 parsing-parameter-value 1818 (assert parameter-value-mark) 1819 (when header-parameter-value-callback 1820 (funcall (the function header-parameter-value-callback) 1821 data parameter-value-mark p)) 1822 (setq parameter-value-mark nil) 1823 (go-state looking-for-parameter-key)) 1825 (go-state parsing-parameter-value))) 1828 (when header-name-mark 1829 (when header-value-callback 1830 (funcall (the function header-value-callback) 1831 data header-name-mark p))) 1832 (when parameter-key-mark 1833 (error 'invalid-eof-state)) 1834 (when parameter-value-mark 1835 (when parsing-quoted-string-p 1836 (error 'invalid-eof-state)) 1837 (when header-parameter-value-callback 1838 (funcall (the function header-parameter-value-callback) 1839 data parameter-value-mark p))))))