Use Overview
ReSIProcate is an object oriented SIP interface and stack implemented in C++. The reSIProcate approach emphasizes consistency, type safety, and ease of use.
A central component of any SIP service is handling of SIP messages and their parts. A SIP message consists of headers, request/status line, and body.
Contents
- 1 Headers
- 2 Body
- 3 Header Types
- 4 Parameters
- 5 MethodTypes
- 6 Uri
- 7 Contents
- 8 MultipartRelatedContents
- 9 MultipartMixedContents
- 10 MultipartSigned
- 11 SdpContents
- 12 Pkcs7Contents
- 13 OctetContents
- 14 SipMessage
- 15 New Content Type
- 16 Extension Header
- 17 Extension parameters
- 18 Header Access Via Strings
Headers[edit]
Headers are accessed from messages with the header method. The header method is overloaded so that its return value is appopriate for each type of header. The actual header method is determined by the header type token passed to the overloaded header method.
Header Access Tokens[edit]
Each header type defined in RFC3261 has a corresponding header access token. For example, the header access tokens for To and From headers are h_To and h_From. The rule for determing the header access token from a header as named in RFC3261 is to remove all dashes from the header name and prefix the result with "h_". For example, "Content-Disposition" becomes h_ContentDisposition.
Given an existing message, fetching the To header is simply:
const NameAddr& to = message->header(h_To);
Well-formedness check[edit]
Each header-field-value type has a function that may be used to determine whether or not it is well-formed.
if(message->header(h_To).isWellFormed()) { // Do stuff with the header }
Right now, isWellFormed() is minimally picky; it will only return false if the header-field-value is unparsable. It does not report the presence of forbidden characters, unless their presence makes it impossible to parse the header. No method exists to carry out a full, pedantic syntax check on a header-field-value. This functionality may be added in the future.
Accessor/Setters[edit]
The header methods are both accessors and setters. Accessing a header that isn't in the message creates the header in a default state if the message is non-const.
To set an empty message's To header:
SipMessage message; // displayName and uri are accessor/setter methods on NameAddr, the storage class // for To headers. message.header(h_To).displayName() = "Speedy Shannon"; message.header(h_To).uri() = Uri("speedy@home.com");
Please note: If a header is malformed, and it has not yet been parsed, these accessors/setters will throw a ParseBuffer::Exception!
Existence Check[edit]
The header methods are used also to access existing headers. If you want to make sure that you are accessing an existing header and are not creating a default header, use the exists method. The exists method is overloaded with the same access tokens.
SipMessage* message; if (!message->exists(h_To)) { // complain bitterly ... } else { NameAddr& to = message->header(h_To); ... }
Const Access[edit]
However, if the message variable is declared const, the header methods will not create a default instance of a missing header, but will throw SipMessage::Exception. This is a typical mode when working with incoming messages.
try { const SipMessage* message; To::Type& to = message->header(h_To); ... } catch (SipMessage::Exception e) { // complain bitterly ... }
Remove[edit]
The remove method is also overloaded for the access tokens. Removing a header that does not exist is a no-op.
SipMessage* message = ...; message->remove(h_RecordRoutes);
Single Instance[edit]
Each header type is either a single instance or multiple instance. For example, the header type To is single instance while the header type Record-Route is multiple instance. The return types differ accordingly.
Multiple Instance[edit]
Multiple instance headers are accessed through a collection of the appropriate header type. As a programming hint, access tokens for multiple headers are pluralized.
Similarly, the collection of each header type is named the pluralized header type. Below is an example accessing a collection of NameAddr instances.
NameAddrs& rr = message.header(h_RecordRoutes);
The collection of header values can be iterated in the usual stl like fashion.
for (NameAddrs::iterator i = rr.begin(); i != rr.end(); ++i) { NameAddr& r = *i; ... }
All collections of header values support begin, end, empty, size, front, back, push_back, push_front, reverse, and clear. Each collection is specific to the header type so no casting is necessary.
NameAddr na; na.displayName() = "Alice"; na.uri() = Uri("sip:alice@company.com"); rr.push_back(na);
Request/Status Line[edit]
The request/status lines are special cases of headers. They are accessed by the header method with the header type tokens h_RequestLine and h_StatusLine. A message may have one or the other of these headers but never both. To determine if a message has a Request Line, use:
if (message->isRequest()) { ... }
Similarly for Status Line:
if (message->isResponse()) { ... }
Note that a newly created message has neither a request or status line. The application must add one or the other for the message to be well formed.
Body[edit]
A message body is accessed with the getContents method. The retured value is of type Contents*, an abstract type. The return value must be cast (dynamic_cast is recommended for runtime type safety) to be used. The content type of a message can be determined by examining the Content-Type header of the message.
New message contents are created by instantiating an instance of a type derived from Contents. For example, SdpContents. A variety of content types are currently supported, including mulitpart, signed, and Pkcs7. New content types can be created either inside or outside of the reSIP library (see Creating a New Contents Type).
Setting the contents of a message takes care of setting the Content-Type and Content-Length of the message.
Pkcs7* pres = new Pkcs7(); ... message->setContents(pres);
Alternatively, pass the newly created contents as an auto_ptr and avoid the copy:
std::auto_ptr<Contents> pres(new Pkcs7()); ... message->setContents(pres);
Recursive multipart contents are supported.
Header Types[edit]
Every RFC 3261 header has a corresponding access token. However, many of the headers have identical form. For example. The To and From header values both consist of a display name and a URI. The To and From headers are managed programmatically as NameAddr instances. The class that manages each header type is responsible for parsing header text, providing storage and access during the life of the message, and serializing the header value to text for transmission.
The table below shows the reSIP types for each of the built in RFC headers currently supported by reSIP. The reSIP type is the return type of a SipMessage header call with the access token as its argument. Plural values mean that the return value is a collection of the type indicated by the singular. The plural type exists in reSIP and is an STL like container.
RFC Name | reSIP Access Token | reSIP Type |
---|---|---|
Accept | h_Accepts | Mimes |
Accept-Contact | h_AcceptContacts | NameAddrs |
Accept-Encoding | h_AcceptEncodings | Tokens |
Accept-Language | h_AcceptLanguages | Tokens |
Alert-Info | h_AlertInfos | GenericUris |
Allow | h_Allows | Tokens |
Allow-Events | h_AllowEvents | Tokens |
Answer-Mode | h_AnswerMode | Token |
Authentication-Info | h_AuthenticationInfos | Auths |
Authorization | h_Authorizations | Auths |
Call-ID | h_CallID | CallId |
Call-Info | h_CallInfos | GenericUris |
Contact | h_Contacts | NameAddrs |
Content-Disposition | h_ContentDisposition | Tokens |
Content-Encoding | h_ContentEncoding | Tokens |
Content-ID | h_ContentId | Tokens |
Content-Language | h_ContentLanguages | Tokens |
Content-Length | h_ContentLength | UInt32Category |
Content-Type | h_ContentType | Mime |
Content-Transfer-Encoding | h_ContentTransferEncoding | StringCategory |
CSeq | h_CSeq | CSeqCategory |
Date | h_Date | DateCategory |
Error-Info | h_ErrorInfos | GenericUris |
Event | h_Event | Token |
Expires | h_Expires | ExpiresCategory |
Flow-Timer | h_FlowTimer | UInt32Category |
From | h_From | NameAddr |
History-Info | h_HistoryInfos | NameAddrs |
Identity | h_Identity | StringCategory |
Identity-Info | h_IdentityInfo | GenericUri |
In-ReplyTo | h_InReplyTo | CallId |
Join | h_Join | CallId |
Max-Forwards | h_MaxForwards | UInt32Category |
MIME-Version | h_MIMEVersion | Tokens |
Min-Expires | h_MinExpires | UInt32Category |
Min-SE | h_MinSE | ExpiresCategory |
Organization | h_Organization | StringCategory |
P-Asserted-Identity | h_PAssertedIdentitys | NameAddrs |
P-Associated-URI | h_PAssociatedUris | NameAddrs |
P-Called-Party-ID | h_PCalledPartyId | NameAddr |
P-Preferred-Identity | h_PPreferredIdentitys | NameAddrs |
P-Media-Autorization | h_PMediaAuthorization | Tokens |
Path | h_Paths | NameAddrs |
Priority | h_Priority | Tokens |
Priv-Answer-Mode | h_PrivAnswerMode | Token |
Privacy | h_Privacys | PrivacyCategorys |
Proxy-Authenticate | h_ProxyAuthenticates | Auths |
Proxy-Authorization | h_ProxyAuthorizations | Auths |
Proxy-Require | h_ProxyRequires | Tokens |
Reason | h_Reasons | Tokens |
Record-Route | h_RecordRoutes | NameAddrs |
Refer-Sub | h_ReferSub | Token |
Refer-To | h_ReferTo | NameAddr |
Referred-By | h_ReferredBy | NameAddr |
Reject-Contact | h_RejectContacts | NameAddrs |
Remote-Party-ID | h_RemotePartyIds | NameAddrs |
Replaces | h_Replaces | CallId |
Reply-To | h_ReplyTo | NameAddr |
Request-Disposition | h_RequestDisposition | Tokens |
Require | h_Requires | Tokens |
Retry-After | h_RetryAfter | UInt32Category |
RSeq | h_RSeq | UInt32Category |
RAck | h_RAck | RAckCategory |
Route | h_Routes | NameAddrs |
Security-Client | h_SecurityClient | Tokens |
Security-Server | h_SecurityServer | Tokens |
Security-Verify | h_SecurityVerify | Tokens |
Server | h_Server | StringCategory |
Service-Route | h_ServiceRoutes | NameAddrs |
Session-Expires | h_SessionExpires | ExpiresCategory |
SIP-ETag | h_SIPETag | Token |
SIP-If-Match | h_SIPIfMatch | Token |
Subject | h_Subject | StringCategory |
Subscription-State | h_SubscriptionState | Token |
Supported | h_Supporteds | Tokens |
Target-Dialog | h_TagetDialog | CallId |
Timestamp | h_Timestamp | StringCategory |
To | h_To | NameAddr |
Unsupported | h_Unsupporteds | Tokens |
User-Agent | h_UserAgent | StringCategory |
Via | h_Vias | Vias |
Warning | h_Warnings | WarningCategories |
WWW-Authenticate | h_WWWAuthenticates | Auths |
The following table lists each of the reSIP types for managing headers. A complete list of accessors is included for each type. Recall that many headers are multi-valued; the return type in the multi-valued cases must be iterated to get to the types shown. Multi-values headers are identified with multi-valued.
RequestLine[edit]
RFC name: Request-Line Description: The first line of a request message. Does not correspond to a header proper but is accessed with the header interface in reSIP. Example: INVITE sip:bob@biloxi.com SIP/2.0 Parts: RFC Name accessor reSIP type settable -------------------------------------------------------------- Request-URI uri() Uri yes Method getMethod() MethodTypes yes Method unknownMethodName() Data yes SIP-Version getSipVersion() Data no
RFC Headers: <none>
StatusLine[edit]
RFC name: Status-Line Description: The first line of a response message. Does not correspond to a header proper but is accessed with the header interface in reSIP. Example: SIP/2.0 200 OK Parts: RFC Name accessor reSIP type settable -------------------------------------------------------------- Status-Code statusCode() int yes SIP-Version getSipVersion() Data no Reason-Phrase reason() Data yes
RFC Headers: <none>
Auth[edit]
RFC name: challenge Description: Identifies the authentication scheme in a challenge response. Example: Digest-Authenticate: username="Alice", realm="atlanta.com", nonce="84a4cc6f3082121f32b42a2187831a9e", response="7587245234b3434cc3412213e5f113a5432" Parts: RFC Name accessor reSIP type settable ---------------------------------------------------------- auth-scheme scheme() Data yes
RFC Headers:
- Authentication-Info
- Authorization multi-valued
- Proxy-Authenticate multi-valued
- Proxy-Authorization multi-valued
- WWW-Authenticate multi-valued
Note that the parameters to the Auth type are comma separated. reSIP correctly interprets the commas as separating parameters and not header values.
CSeqCategory[edit]
RFC name: CSeq Description: Places the message in sequence in the call. Example: CSeq: 314159 INVITE Parts: RFC Name accessor reSIP type settable -------------------------------------------------------------- sequence() int yes Method method() MethodTypes yes unknownMethodName() Data no
RFC Headers:
- CSeq
CallId[edit]
RFC name: Call-ID Description: Uniquely identifies the call. Example: Call-ID: a84b4c76e66710@pc33.atlanta.com Parts: RFC Name accessor reSIP type settable ---------------------------------------------------------- value() Data yes
RFC Headers:
- Call-ID
Note: C++ type synonym for CallID
DateCategory[edit]
RFC name: SIP-date Description: Human readable date string. Example: Date: Sat, 13 Nov 2010 23:29:00 GMT Parts: RFC Name accessor reSIP type settable ---------------------------------------------------------- wkday dayOfWeek() DayOfWeek yes date1 dayOfMonth int yes month() int yes year() int yes time hour() int yes minute() int yes second() int yes
RFC Headers:
- Date
GenericUri[edit]
RFC name: absoluteURI Description: Non-structured human readable URI. Example: Alert-Info: <http://www.example.com/sounds/moo.wav> Parts: RFC Name accessor reSIP type settable ---------------------------------------------------------- uri() Data yes
RFC Headers:
- Alert-Info
- Call-Info
- Error-Info
ExpiresCategory[edit]
RFC name: expires Description: Seconds to expiration. Example: Expires: 5 Parts: RFC Name accessor reSIP type settable ---------------------------------------------------------- value() int yes
RFC Headers:
- Expires
Mime[edit]
RFC name: media-type Description: Mime type and sub-type. Example: Content-Type: application/sdp Parts: RFC Name accessor reSIP type settable ---------------------------------------------------------- m-type type() Data yes m-subtype subType() Data yes
RFC Headers:
- Accept multi-valued
- Content-Type
NameAddr[edit]
RFC name: name-addr Description: URI and display name. Example: To: Bob <sip:bob@biloxi.com> Parts: RFC Name accessor reSIP type settable ---------------------------------------------------------- display-name displayName() Data yes addr-spec uri() Uri yes
RFC Headers:
- Contact multi-valued
- From
- Record-Route multi-valued
- Refer-To
- Referred-By
- Reply-To
- Route multi-valued
- To
StringCategory[edit]
RFC name: TEXT-UTF8-TRIM Description: Unstructured human readable text. Example: Organization: Boxes by Bob Parts: RFC Name accessor reSIP type settable ---------------------------------------------------------- value() Data yes
RFC Headers:
- Content-Transfer-Encoding
- Organization
- Server
- Subject
- User-Agent
- Timestamp
- Extension Header multi-valued
Token[edit]
RFC name: token Description: A word. Example: Accept-Encoding: gzip Parts: RFC Name accessor reSIP type settable ---------------------------------------------------------- value() Data yes
RFC Headers:
- Accept-Encoding multi-valued
- Accept-Language multi-valued
- Allow multi-valued
- Allow-Events multi-valued
- Content-Disposition
- Content-Encoding
- Content-Language multi-valued
- Event
- Mime-Version
- Priority
- Proxy-Require multi-valued
- Require multi-valued
- Security-Client multi-valued
- Security-Server multi-valued
- Security-Verify multi-valued
- Subscription-State multi-valued
- Supported multi-valued
- Unsupported multi-valued
UInt32Category[edit]
RFC name: 1*DIGIT Description: An integer. Example: Max-Forwards: 70 Parts: RFC Name accessor reSIP type settable ---------------------------------------------------------- value() int yes comment comment() Data yes
RFC Headers:
- Content-Length does not permit (comment) but reSIP does
- Max-Forwards does not permit (comment) but reSIP does
- Min-Expires does not permit (comment) but reSIP does
- Retry-After
Via[edit]
RFC name: via-parm Description: Via entry. Example: Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds Parts: RFC Name accessor reSIP type settable ------------------------------------------------------------ protocol-name protocolName() Data yes protocol-version protocolVersion() Data yes transport transport() Data yes host sentHost() Data yes port sentPort() int yes
RFC RFC Headers:
- Via (multi-valued)
WarningCategory[edit]
RFC name: warning-value Description: Example: Parts: RFC Name accessor reSIP type settable -------------------------------------------------------- warn-code code() int yes warn-agent hostname() Data yes warn-text text() Data yes
RFC Headers:
- Warning multi-valued
Parameters[edit]
Parameters are accessed from headers. The syntax is similar to header access.
Like headers, there is an overloaded accessor method. For parameters, this
method is param
. The argument to param
is a parameter
type token indicating the parameter to be accessed. The parameter type
token always begins with "p_" and the rest is camelCase starting with a
lowercase.
For example:
const Data& tag = msg->header(h_To).param(p_tag);
Like headers, there is also an overloaded exists
method and
an overloaded remove
method. For both methods, the argument is
again the parameter type token.
According to the grammar, each header has a set of acceptable parameters. Some headers accept no parameters. reSIP makes a simplifying assumption; all headers can have all parameters. While it is the goal of reSIP that every legal SIP message be parseable, reSIP does not strictly enforce production of legal SIP. In practice, correct usage will result in legal SIP, but it is not very difficult to use reSIP to produce a problematic message. Take home lesson -- the reSIP programmer must take responsibilty when adding parameters to a header.
A corollary to this simplifying assumption is that the form of a parameter is independent of the header it appears in. A ttl parameter must always be followed by an integer even when used in a header that does not specify the syntax for a ttl parameter. (!dlb! potential compatibility issue)
Parameters, like headers, corresponds to a small set of classes that manage parsing, accesing, and serializing to text.
RFC name | reSIP access token | reSIP type |
---|---|---|
+sip.instance | p_Instance | QuotedDataParameter |
access-type | p_accessType | DataParameter |
actor | p_actor | QuotedDataParameter |
algorithm | p_algorithm | DataParameter |
app-id | p_appId | DataParameter |
application | p_application | ExistsParameter |
boundary | p_boundary | DataParameter |
branch | p_branch | BranchParameter |
charset | p_charset | DataParameter |
cnonce | p_cnonce | QuotedDataParameter |
comp | p_comp | DataParameter |
control | p_control | ExistsParameter |
d-alg | p_dAlg | DataParameter |
d-qop | p_dQop | DataParameter |
d-ver | p_dVer | QuotedDataParameter |
data | p_data | ExistsParameter |
description | p_description | QuotedDataParameter |
directory | p_directory | DataParameter |
document | p_document | DataParameter |
domain | p_domain | QuotedDataParameter |
duration | p_duration | UInt32Parameter |
early-only | p_earlyOnly | ExistsParameter |
effective-by | p_effectiveBy | UInt32Parameter |
events | p_events | QuotedDataParameter |
expiration | p_expiration | QuotedDataParameter |
expires | p_expires | UInt32Parameter |
ext | p_extension | DataParameter |
extensions | p_extensions | QuotedDataParameter |
filename | p_filename | DataParameter |
from-tag | p_fromTag | DataParameter |
gr | p_gr | ExistsOrDataParameter |
handling | p_handling | DataParameter |
id | p_id | DataParameter |
isfocus | p_isfocus | ExistsParameter |
language | p_language | QuotedDataParameter |
lr | p_lr | ExistsParameter |
maddr | p_maddr | DataParameter |
method | p_method | DataParameter |
methods | p_methods | QuotedDataParameter |
micalg | p_micalg | DataParameter |
mobility | p_mobility | QuotedDataParameter |
mode | p_mode | DataParameter |
model | p_model | QuotedDataParameter |
name | p_name | DataParameter |
nc | p_nc | DataParameter |
network-user | p_networkUser | DataParameter |
nonce | p_nonce | QuotedDataParameter |
ob | p_ob | ExistsParameter |
opaque | p_opaque | QuotedDataParameter |
permission | p_permission | DataParameter |
priority | p_priority | QuotedDataParameter |
profile-type | p_profileType | DataParameter |
protocol | p_protocol | QuotedDataParameter |
pub-gruu | p_pubGruu | QuotedDataParameter |
purpose | p_purpose | DataParameter |
q | p_q | QValueParameter |
qop | p_qop | DataParameter |
realm | p_realm | QuotedDataParameter |
reason | p_reason | DataParameter |
received | p_received | DataParameter |
refresher | p_refresher | DataParameter |
reg-id | p_regid | UInt32Parameter |
response | p_response | QuotedDataParameter |
retry-after | p_retryAfter | UInt32Parameter |
rinstance | p_rinstance | DataParameter |
rport | p_rport | RportParameter |
schemes | p_schemes | QuotedDataParameter |
server | p_server | DataParameter |
sigcomp-id | p_sigcompId | QuotedDataParameter |
site | p_site | DataParameter |
size | p_size | DataParameter |
smime-type | p_smimeType | DataParameter |
stale | p_stale | DataParameter |
tag | p_tag | DataParameter |
temp-gruu | p_tempGruu | QuotedDataParameter |
text | p_text | ExistsOrDataParameter |
to-tag | p_toTag | DataParameter |
transport | p_transport | DataParameter |
ttl | p_ttl | UInt32Parameter |
type | p_type | QuotedDataParameter |
uri | p_uri | QuotedDataParameter |
url | p_url | QuotedDataParameter |
user | p_user | DataParameter |
username | p_username | DataParameter or QuotedDataParameter |
vendor | p_vendor | QuotedDataParameter |
version | p_version | QuotedDataParameter |
video | p_video | ExistsParameter |
BranchParameter[edit]
RFC name: Description: May have RFC 3261 marker, may have reSIP specific data, may have client data. Example: Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds Parts: accessor reSIP type settable ---------------------------------------------------- hasMagicCookie() bool no getTransactionId() Data no incrementTransportSequence void no reset(const Data&) void yes clientData() Data yes
RCF Parameters:
- branch
DataParameter[edit]
RFC name: token Description: Quoted or unquoted. Unquoted must be single word. Example: Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds Parts: accessor reSIP type settable ------------------------------------------------ value() Data yes isQuoted() bool no setQuoted(bool) void yes
RFC parameters:
- access-type
- algorithm
- boundary
- charset
- comp
- d-alg
- d-qop
- directory
- filename
- from-tag
- handling
- id
- maddr
- method
- micalg
- mode
- name
- nc
- permission
- purpose
- reason
- received
- require
- rinstance
- server
- site
- size
- smime-type
- stale
- tag
- to-tag
- transport
- user
- extension
- username
- refresher
- profile-type
- document
- app-id
- network-user
- qop
ExistsOrDataParameter[edit]
RFC name: Description: Either has no value; and is not followed by "=" or contains a Data token Quoted or unquoted. Unquoted must be single word. Example: Reason: SIP ;cause=200 ;text="Call completed elsewhere" Parts: accessor reSIP type settable ------------------------------------------------ value() Data yes isQuoted() bool no setQuoted(bool) void yes
RFC parameters:
- text
- gr
ExistsParameter[edit]
RFC name: Description: Has no value; is not followed by "=". Example: Record-Route: <sip:p1.example.com;lr> Parts: accessor reSIP type settable ------------------------------------------------ value() bool yes
RFC parameters:
- data
- control
- application
- video
- isfocus
- ob
- lr
- early-only
IntegerParameter[edit]
RFC name: Description: Integer Example: sip:alice@atlanta.com;maddr=239.255.255.1;ttl=15 Parts: accessor reSIP type settable ------------------------------------------------ value() int yes
RFC parameters:
QValueParameter[edit]
RFC name: qvalue Description: 0-1 inclusive, up to three digits after decimal point. Example: Accept-Language: da, en-gb;q=0.8, en;q=0.7 Parts: accessor reSIP type settable ------------------------------------------------ value() QValue yes qval() int (0-1000) yes
RFC parameters:
- q
QuotedDataParameter[edit]
RFC name: quoted-string Description: Quoted text. Example: Authorization: Digest username="bob", realm="biloxi.com", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", uri="sip:bob@biloxi.com", qop=auth, nc=00000001, cnonce="0a4f113b", response="6629fae49393a05397450978507c4ef1", opaque="5ccc069c403ebaf9f0171e9517f40e41" Parts: accessor reSIP type settable ------------------------------------------------ value() Data yes
RFC Parameters:
- mobility
- description
- events
- priority
- methods
- schemes
- language
- type
- actor
- extensions
- +sip.instance
- pub-gruu
- temp-gruu
- cnonce
- d-ver
- domain
- expiration
- nonce
- opaque
- protocol
- realm
- response
- uri
- vendor
- model
- version
- url
- sigcomp-id
RportParameter[edit]
RFC name: rport Description: May have a value or not. Example: Via: SIP/2.0/UDP whistler.gloo.net:6064;rport=6064;received=192.168.2.220;branch=z9hG4bK-kcD23-4-1 Parts: accessor reSIP type settable -------------------------------------------- port() int yes hasValue() bool no
RFC Parameters:
- rport
UInt32Parameter[edit]
RFC name: Description: Integer Example: sip:alice@atlanta.com;maddr=239.255.255.1;ttl=15 Parts: accessor reSIP type settable ------------------------------------------------ value() UInt32 yes
RFC Parameters:
- reg-id
- duration
- expires
- retry-after
- ttl
- effective-by
MethodTypes[edit]
- ACK
- BYE
- CANCEL
- INVITE
- NOTIFY
- OPTIONS
- REFER
- REGISTER
- SUBSCRIBE
- RESPONSE
- MESSAGE
- INFO
- PRACK
- PUBLISH
- SERVICE
- UPDATE
Uri[edit]
RFC name: addr-spec Description: URI Example: sip:alice:secretword@atlanta.com;transport=tcp Parts: RFC Name accessor reSIP type settable ------------------------------------------------------------ header embedded() SipMessage yes userinfo+hostport getAor() Data no userinfo+host getAorNoPort() Data no hasEmbedded() bool no host host() Data yes host opaque() Data yes password password() Data yes port port() int yes userinfo user() Data yes // note: does not include user parameters userParameters() Data yes scheme() Data yes
Uri Parameters[edit]
A URI can have parameters. This can be confusing when a Uri is part of a NameAddr header which can also have parameters. The NameAddr parameters can be disambiguated from the Uri parameters by enclosing the Uri in angle brackets. However, in general, parameter attribution can be ambiguous. When parameters can be interpreted to belong the either a Uri or NameAddr, the Uri receives the parameters:
- maddr
- ttl,
- user
- method
- lr
The NameAddr receives any remaining parameters.
Contents[edit]
RFC name: message-body Description: Base class for all content types. Each derived content type defines its own parse, accessors and stream rendering. Example: --boundary42 Content-Type: message/sip INVITE sip:bob@biloxi.com SIP/2.0 Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8 To: Bob <bob@biloxi.com> From: Alice <alice@atlanta.com>;tag=1928301774 Call-ID: a84b4c76e66710 CSeq: 314159 INVITE Max-Forwards: 70 Date: Thu, 21 Feb 2002 13:02:03 GMT Contact: <sip:alice@pc33.atlanta.com> Content-Type: application/sdp Content-Length: 147 v=0 o=UserA 2890844526 2890844526 IN IP4 here.com s=Session SDP c=IN IP4 pc33.atlanta.com t=0 0 m=audio 49172 RTP/AVP 0 a=rtpmap:0 PCMU/8000 --boundary42 Content-Type: application/pkcs7-signature; name=smime.p7s Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=smime.p7s; handling=required ghyHhHUujhJhjH77n8HHGTrfvbnj756tbB9HG4VQpfyF467GhIGfHfYT6 4VQpfyF467GhIGfHfYT6jH77n8HHGghyHhHUujhJh756tbB9HGTrfvbnj n8HHGTrfvhJhjH776tbB9HG4VQbnj7567GhIGfHfYT6ghyHhHUujpfyF4 7GhIGfHfYT64VQbnj756 --boundary42- Parts: accessor reSIP type settable notes ---------------------------------------------------------- exists bool no remove void no header <various> yes // shared header types H_ContentType::Type& header(const H_ContentType& headerType) const; H_ContentDisposition::Type& header(const H_ContentDisposition& headerType) const; H_ContentTransferEncoding::Type& header(const H_ContentTransferEncoding& headerType) const; H_ContentLanguages::Type& header(const H_ContentLanguages& headerType) const; // MIME specific header types H_ContentID::Type& header(const H_ContentID& headerType) const; H_ContentDescription::Type& header(const H_ContentDescription& headerType) const; int& verion() {return mVersion;} int& minorVersion() {return mMinorVersion;}
Declaring a Contents Type[edit]
class NewContents : public Contents { public: static const NewContents Empty;
NewContents(); NewContents(const Data& text); NewContents(HeaderFieldValue* hfv, const Mime& contentType); NewContents(const Data& data, const Mime& contentType); NewContents(const NewContents& rhs); virtual ~NewContents(); NewContents& operator=(const NewContents& rhs);
virtual Contents* clone() const;
virtual Data getBodyData() const;
static const Mime& getStaticType() ;
virtual std::ostream& encodeParsed(std::ostream& str) const; virtual void parse(ParseBuffer& pb);
// new content specific interfaces...
static bool init();
private: // new content specific store... };
Defining a Contents Type[edit]
MultipartRelatedContents[edit]
MultipartMixedContents[edit]
MultipartSigned[edit]
SdpContents[edit]
Pkcs7Contents[edit]
OctetContents[edit]
SipMessage[edit]
SipMessage is an object-oriented representation of a message. A SipMessage can be created from the serialized form received from the wire or can be built up in an application and serialized and sent over the wire.
Headers[edit]
A detailed listing of the supported headers and their storage/parser type is here.
SipMessage has an array of built in headers and a list of unknown/extension headers. In either case, the header value or values are accessed with the overloaded header method and a header access token.
std::cerr << msg->header(h_To).uri().host() << std::endl;
The header access token is also used to check for the existence of a header:
if (msg->exists(h_Routes)) { ....
The header acesss token is also used to remove a header. It is not an error to remove a header that is not present in the message.
msg->remove(h_Warnings);
The header method will create a header value if the request header is not present in the message and the message is not const. So headers can be added to non-const messages simply by accessing the header.
msg->header(h_To) = NameAddr("Joe <joseph@example.com>");
If the message is const, accessing a header that is not present in the message will raise a SipMessage::Exception. Often, a SIP element will check if the header exists before accessing it rather than handle the exception.
Some headers have multiple values. The values of a multi-valued header are maintained in a container class named after the type contained. For example, msg->header(h_Contacts) returns a reference to NameAddrs. The containers have STL container syntax.
for (NameAddrs::const_iterator i = msg->header(h_Contacts).begin(); i != msg->header(h_Contacts.end(); ++i) { const NameAddr& na = *i; ...;
Multi-valued header values correspond to comma separated values with one header or multiple header lines each with their own header. When serialized to the wire, multiple values are emitted comma separated.
Contents[edit]
reSIP represents a message body as a derived Content instance. The contents instance associated with the SipMessage is accessible:
SdpContents* sdp = dynamic_cast<SdpContents*>(msg->getContents());
SipMessage also acts somewhat like an auto_ptr<Contents>. SipMessage supports releaseContents() and
std::auto_ptr<Contents> contents(new SdpContents)); // populate the sdp... then set into message msg->setContents(contents);
The setContents that takes a Contents* copies the contents through the pointer before assigning it to the SipMessage.
Other Interfaces[edit]
SipMessage can deterine if it is a request:
if (msg->isRequest()) { ...
SipMessage can determine if it is a response:
if (msg->isResponse()) { ...
A message can be neither a request or a response if it is locally created (as opposed to being deserialzed from the wire) and has neither a request nor status line.
New Content Type[edit]
Extension Header[edit]
SIP is an open specification. Elements may add headers that are not generally known. Extension headers are always of type StringCategory and are multiple valued but not comma separated. Extension headers may have parameters, however, not all stacks will consider semi-colons in extension headers significant, so extension header parameters may cause interop problems.
Extension headers are declared, for example:
static const resip::ExtensionHeader h_XFoos("X-Foo");
They are used similarly to built-in headers; the h_XFoos declared above is a header access token.
msg->header(h_XFoos).push_back(StringCategory("value"));
Extension parameters[edit]
SIP is an open specification. Elements may add parameters that are not generally known. Extension parameters are always of type Data. An extension parameter may not have a value; that is, it can act as an exists parameter. An extension parameter may occur on any header including an extension header.
Extension parameters are declared, for example:
static const resip::ExtensionParameter p_xstid("x-stid");
Extension parameters are be used like other parameters:
msg->header(h_To).param(p_xstid) = "2134";
Header Access Via Strings[edit]
Sometimes it is desirable to access SIP header information using strings instead of using the header type objects discussed above. This is especially useful when wanting to make behavior externally configurable (ie. a datastore or configuration file). For example: If header X contains some string Y, then reject a request - where X and Y are runtime configurable parameters and not known at compilation time.
Sample Code:
// Check to see if it is a standard header Headers::Type headerType = Headers::getType(headerName.c_str(), headerName.size()); if(headerType != Headers::UNKNOWN) { Data headerData; const HeaderFieldValueList* hfv = msg.getRawHeader(headerType); for(HeaderFieldValueList::const_iterator it = hfv->begin(); it != hfv->end(); it++) { it->toShareData(headerData); // Do something with headerData..... } } else // Check if custom header { ExtensionHeader exHeader(headerName); if(msg.exists(exHeader)) { const StringCategories& exHeaders = msg.header(exHeader); for(StringCategories::const_iterator it = exHeaders.begin(); it != exHeaders.end(); it++) { // Do something with it->value() } } }