~/bend-docscommunity

rtsp_core.bend checks

raw source on the hub · import 0xfbc4773809086afacef84e7fba6d620c/rtsp_core.bend as Rtsp_core

The pure core of the RTSP client (RFC 2326): URLs, requests, what comes back on the connection (replies, and RTP packets interleaved with them), authentication (Basic and Digest, RFC 2617), and the session description (SDP, RFC 4566). Nothing here does IO, so LAWS.bend can state laws about it; rtsp.bend is the dialog.

6 imports
import Base
import ./text.bend as T
import ./bytes.bend as B
import ./b64.bend as E
import ./md5.bend as D
import ./sha256.bend as H

Types

type Hdr source · line 14 · raw

Data

A header field.

type Url source · line 21 · raw

Data

rtsp://[user[:pass]@]host[:port][/path]; no host means not an RTSP URL.

type Resp source · line 168 · raw

Data

A reply: its status code (0 for a request the server sends us), its headers and its body.

type Msg source · line 174 · raw

Data

The first whole thing in a buffer, and what follows it: a reply; an interleaved packet ("$", channel, length; RFC 2326 10.12); Need when it is not all there yet; Bad when it can be neither.

type Chal source · line 343 · raw

Data

A challenge (WWW-Authenticate): its scheme in lower case ("" for none) and Digest's parameters.

type Scan source · line 353 · raw

Data

A parameter list cut at its commas, those inside quotes kept: where the scan is (in quotes, after a backslash), the item so far (reversed) and the items (reversed).

type Media source · line 545 · raw

Data

A media stream of a description: its kind ("video", "audio"), payload type, codec ("H264", in upper case) and clock rate (from a=rtpmap), control URL (a=control) and format parameters (a=fmtp).

type Sdp source · line 550 · raw

Data

A description: the session's control URL and its streams.

type Sdp.St source · line 558 · raw

Data

The reading so far: the session's control, the streams done (reversed), the stream being read and whether there is one.

Definitions

def Url.none source · line 24 · raw

Url

def Url.hex source · line 27 · raw

@+c:U32 -> U32

def Url.unpct.put source · line 32 · raw

@ok:Bool -> @+a:U32 -> @+b:U32 -> @rest:String -> String

def Url.unpct source · line 41 · raw

@s:String -> String

Percent-decoding (RFC 3986 2.1), for a user or password with "@" or ":" in it; a "%" not followed by two hex digits stays.

def Url.port source · line 50 · raw

@m:Maybe<&2, U32> -> @dflt:U32 -> U32

def Url.host source · line 58 · raw

@hp:List<&2, String> -> @dflt:U32 -> @user:String -> @pass:String -> @path:String -> Url

"host[:port]"; dflt: the port when absent.

def Url.creds source · line 69 · raw

@up:List<&2, String> -> @hp:List<&2, String> -> @dflt:U32 -> @path:String -> Url

"user[:pass]", percent-decoded.

def Url.auth source · line 80 · raw

@+ps:List<&2, String> -> @dflt:U32 -> @path:String -> Url

"[user[:pass]@]host[:port]"; the last "@" divides them.

def Url.rest source · line 85 · raw

@parts:List<&2, String> -> @dflt:U32 -> Url

def Url.of source · line 96 · raw

@+url:String -> @+scheme:String -> @dflt:U32 -> Url

The URL after "scheme://" (scheme in lower case, with its "://"), on its default port when it names none; anything else gives no host.

def Url.esc source · line 101 · raw

@s:String -> String

def Url.show source · line 112 · raw

@u:Url -> @scheme:String -> String

The URL as it goes in a request: no user or password, spaces escaped, no line end.

def Url.host.of source · line 116 · raw

@u:Url -> String

def Url.port.of source · line 120 · raw

@u:Url -> U32

def Url.user source · line 124 · raw

@u:Url -> String

def Url.pass source · line 128 · raw

@u:Url -> String

def Url.path source · line 132 · raw

@u:Url -> String

def Rtsp.text source · line 142 · raw

@raw:String -> String

A line of a request with no CR or LF in it, whatever went in, and the CRLF that ends it: no method, URL or header value can start another line. LAWS.bend proves it for every string.

def Rtsp.line source · line 145 · raw

@raw:String -> String

def Rtsp.fields source · line 148 · raw

@hs:List<&2, Hdr> -> String

def Rtsp.request source · line 158 · raw

@method:String -> @uri:String -> @cseq:U32 -> @hs:List<&2, Hdr> -> String

A request: the request line, CSeq, User-Agent, the given headers, and the empty line (RFC 2326 6).

def Hdr.trim source · line 180 · raw

@s:String -> String

def Hdr.of source · line 183 · raw

@parts:List<&2, String> -> Hdr

def Hdr.parse source · line 192 · raw

@ls:List<&2, String> -> List<&2, Hdr>

The header lines after the first, each as a field with its name in lower case.

def Hdr.get source · line 200 · raw

@hs:List<&2, Hdr> -> @+name:String -> String

The first value of a header (name in lower case), or "".

def Hdr.keep source · line 208 · raw

@hit:Bool -> @v:String -> @rest:List<&2, String> -> List<&2, String>

def Hdr.all source · line 216 · raw

@hs:List<&2, Hdr> -> @+name:String -> List<&2, String>

Every value of a header, in order.

def Resp.code source · line 224 · raw

@r:Resp -> U32

def Resp.headers source · line 228 · raw

@r:Resp -> List<&2, Hdr>

def Resp.body source · line 232 · raw

@r:Resp -> List<&2, U32>

def Resp.get source · line 236 · raw

@r:Resp -> @name:String -> String

def Rtsp.num source · line 239 · raw

@m:Maybe<&2, U32> -> U32

def Rtsp.word source · line 247 · raw

@ws:List<&2, String> -> @n:Nat -> String

The n-th word of a list, or "".

def Rtsp.status source · line 257 · raw

@+ws:List<&2, String> -> U32

The status of "RTSP/1.0 200 OK"; 0 for any other first line.

def Rtsp.uncr source · line 261 · raw

@s:String -> String

def Rtsp.head source · line 272 · raw

@bs:List<&2, U32> -> @acc:List<&2, U32> -> 0xfbc4773809086afacef84e7fba6d620c/bytes.Cut

The end of a message's head: the bytes before the first empty line, and the bytes after it. acc: the head so far, reversed.

def Rtsp.body source · line 281 · raw

@c:0xfbc4773809086afacef84e7fba6d620c/bytes.Cut -> @code:U32 -> @hs:List<&2, Hdr> -> Msg

def Rtsp.reply.with source · line 288 · raw

@code:U32 -> @+hs:List<&2, Hdr> -> @rest:List<&2, U32> -> Msg

def Rtsp.reply.lines source · line 292 · raw

@ls:List<&2, String> -> @rest:List<&2, U32> -> Msg

def Rtsp.reply source · line 299 · raw

@c:0xfbc4773809086afacef84e7fba6d620c/bytes.Cut -> Msg

def Rtsp.frame source · line 306 · raw

@chan:U32 -> @c:0xfbc4773809086afacef84e7fba6d620c/bytes.Cut -> Msg

def Rtsp.demux.text source · line 313 · raw

@letter:Bool -> @buf:List<&2, U32> -> Msg

def Rtsp.demux source · line 323 · raw

@buf:List<&2, U32> -> Msg

The first message in the buffer. A "$" opens an interleaved packet; a letter opens a reply (or a request from the server); the CR and LF some servers leave between messages are skipped.

def Chal.none source · line 347 · raw

Chal

def Chal.scan.ch source · line 356 · raw

@st:Scan -> @+c:U32 -> Scan

def Chal.scan.go source · line 366 · raw

@s:String -> @st:Scan -> Scan

def Chal.scan.fin source · line 373 · raw

@st:Scan -> List<&2, String>

def Chal.items source · line 378 · raw

@s:String -> List<&2, String>

"k=v, k="v, w"" as "k=v" items with the quotes taken off.

def Chal.kv source · line 381 · raw

@parts:List<&2, String> -> Hdr

def Chal.kvs source · line 388 · raw

@xs:List<&2, String> -> List<&2, Hdr>

def Chal.with source · line 395 · raw

@scheme:String -> @+ps:List<&2, Hdr> -> Chal

def Chal.words source · line 400 · raw

@ws:List<&2, String> -> Chal

def Chal.of source · line 408 · raw

@v:String -> Chal

One WWW-Authenticate value.

def Chal.all source · line 411 · raw

@vs:List<&2, String> -> List<&2, Chal>

def Chal.scheme source · line 418 · raw

@c:Chal -> String

def Chal.algo source · line 422 · raw

@c:Chal -> String

def Chal.digest source · line 428 · raw

@+c:Chal -> Bool

Whether this one can be answered: Basic, or Digest with MD5 (the default when no algorithm is named) or SHA-256 (RFC 7616).

def Chal.basic source · line 433 · raw

@c:Chal -> Bool

def Chal.first source · line 436 · raw

@cs:List<&2, Chal> -> @+digest:Bool -> Chal

def Chal.or.at source · line 444 · raw

@none:Bool -> @a:Chal -> @b:Chal -> Chal

def Chal.or source · line 451 · raw

@+a:Chal -> @b:Chal -> Chal

def Chal.pick source · line 458 · raw

@+cs:List<&2, Chal> -> Chal

The challenge to answer among a reply's: the first Digest one this client can answer, if there is one (the password does not travel; a server lists the one it prefers first, RFC 7616 3.7), else Basic, else none.

def Auth.md5 source · line 461 · raw

@s:String -> String

def Auth.sha256 source · line 464 · raw

@s:String -> String

def Auth.hash source · line 468 · raw

@sha:Bool -> @s:String -> String

The hash a Digest challenge names, in hex.

def Auth.esc source · line 475 · raw

@s:String -> String

def Auth.q source · line 487 · raw

@s:String -> String

A quoted string (RFC 2617 1.2), its quotes and backslashes escaped.

def Auth.response source · line 493 · raw

@+user:String -> @+realm:String -> @pass:String -> @method:String -> @+uri:String -> @+nonce:String -> @auth:Bool -> @+cnonce:String -> @+sha:Bool -> String

Digest's response (RFC 2617 3.2.2, RFC 7616 3.4.1): with qop=auth the nonce count and the client nonce enter the hash; without it, the 2069 form. sha: SHA-256 instead of MD5.

def Auth.opt source · line 501 · raw

@+v:String -> @text:String -> String

def Auth.digest source · line 504 · raw

@c:Chal -> @+user:String -> @pass:String -> @method:String -> @+uri:String -> @+cnonce:String -> String

def Auth.basic source · line 516 · raw

@user:String -> @pass:String -> String

def Auth.value.at source · line 519 · raw

@digest:Bool -> @basic:Bool -> @c:Chal -> @user:String -> @pass:String -> @method:String -> @uri:String -> @cnonce:String -> String

def Auth.value source · line 531 · raw

@+c:Chal -> @user:String -> @pass:String -> @method:String -> @uri:String -> @cnonce:String -> String

The Authorization value that answers a challenge for this request, or "" when there is none to answer. cnonce: a fresh random string.

def Auth.headers source · line 536 · raw

@+v:String -> List<&2, Hdr>

The headers that carry it: none when the value is empty.

def Media.none source · line 553 · raw

Media

def Sdp.push source · line 561 · raw

@has:Bool -> @cur:Media -> @done:List<&2, Media> -> List<&2, Media>

def Sdp.m source · line 569 · raw

@+ws:List<&2, String> -> Media

"m=video 0 RTP/AVP 96": the kind and the first payload type.

def Sdp.after source · line 572 · raw

@s:String -> @n:Nat -> String

def Sdp.rtpmap source · line 576 · raw

@+ws:List<&2, String> -> @m:Media -> Media

"96 H264/90000" into the stream, when it is about its payload type.

def Sdp.fmtp source · line 585 · raw

@+v:String -> @m:Media -> Media

"96 a=1; b=2" into the stream, when it is about its payload type.

def Sdp.control source · line 593 · raw

@v:String -> @m:Media -> Media

def Sdp.line source · line 597 · raw

@st:Sdp.St -> @+l:String -> Sdp.St

def Sdp.lines source · line 611 · raw

@ls:List<&2, String> -> @st:Sdp.St -> Sdp.St

def Sdp.fin source · line 618 · raw

@st:Sdp.St -> Sdp

def Sdp.of source · line 623 · raw

@text:String -> Sdp

A description from its text.

def Media.kind source · line 627 · raw

@m:Media -> String

def Media.pt source · line 631 · raw

@m:Media -> U32

def Media.codec source · line 635 · raw

@m:Media -> String

def Media.control source · line 639 · raw

@m:Media -> String

def Media.fmtp source · line 643 · raw

@m:Media -> String

def Sdp.find source · line 647 · raw

@ms:List<&2, Media> -> @+kind:String -> Media

def Sdp.media source · line 655 · raw

@s:Sdp -> @kind:String -> Media

The first stream of a kind (one with no kind when there is none).

def Sdp.session source · line 659 · raw

@s:Sdp -> String

def Sdp.param.of source · line 663 · raw

@parts:List<&2, String> -> Hdr

def Sdp.params source · line 670 · raw

@xs:List<&2, String> -> List<&2, Hdr>

def Sdp.param source · line 678 · raw

@fmtp:String -> @name:String -> String

A format parameter's value ("a=1; b=2" has "b" as "2"), or "".

def Sdp.sets source · line 681 · raw

@xs:List<&2, String> -> List<&2, List<&2, U32>>

def Sdp.some source · line 688 · raw

@s:String -> Bool

def Sdp.sprops source · line 694 · raw

@+fmtp:String -> List<&2, List<&2, U32>>

The parameter sets a stream announces, decoded: H.264's SPS and PPS (sprop-parameter-sets, RFC 6184 8.1), or H.265's VPS, SPS and PPS (sprop-vps, sprop-sps, sprop-pps; RFC 7798 7.1).

def Rtsp.control source · line 703 · raw

@+base:String -> @+control:String -> String

The URL a control attribute names (RFC 2326 C.1.1): itself when absolute, the base for "*" or none, else the base and it.

def Rtsp.session source · line 709 · raw

@v:String -> String

The session id of a Session header ("id;timeout=60").

def Rtsp.timeout.of source · line 712 · raw

@ps:List<&2, String> -> U32

def Rtsp.timeout source · line 723 · raw

@v:String -> U32

The seconds a Session header gives the session without a request ("id;timeout=30"); 60 when it says nothing (RFC 2326 12.37).

def Rtsp.signed.with source · line 726 · raw

@+auth:String -> @method:String -> @uri:String -> @cseq:U32 -> @+session:String -> @hs:List<&2, Hdr> -> String

def Rtsp.signed source · line 735 · raw

@c:Chal -> @user:String -> @pass:String -> @+method:String -> @+uri:String -> @cseq:U32 -> @cnonce:String -> @+session:String -> @hs:List<&2, Hdr> -> String

A request for this session: the given headers, the Session header once there is one, and the Authorization that answers the server's challenge for this method and URL.

def Sdp.problem source · line 742 · raw

@+m:Media -> String

What is wrong with a description for pulling video, or "": there must be a video stream, in H.264 or H.265.