Skip to content

Publisher: event state publication (RFC 3903, PUBLISH) - #979

Open
neutrino38 wants to merge 1 commit into
versatica:masterfrom
neutrino38:publisher
Open

neutrino38 wants to merge 1 commit into
versatica:masterfrom
neutrino38:publisher

Conversation

@neutrino38

Copy link
Copy Markdown

Why

JsSIP can SUBSCRIBE to an event package and NOTIFY one, but it cannot PUBLISH its own state (RFC 3903) to a presence server. Today an application has to build the PUBLISH request on the SIPMessage and RequestSender internals and handle the entity-tag cycle itself.

What

ua.publish(target, eventName, contentType, options) returns a Publisher, built like Subscriber:

const publisher = ua.publish('sip:alice@example.com', 'presence', 'application/pidf+xml');

publisher.on('published', response => {});        // every 2xx
publisher.on('terminated', (code, response) => {}); // final

publisher.publish(pidf);   // initial publication, or a modification
publisher.terminate();     // removal (Expires: 0)
  • Lifecycle. Each 2xx carries a SIP-ETag, and later requests send it back in SIP-If-Match. Before expiry, the publication is refreshed with no body. The refresh is scheduled the same way as in Subscriber. terminate() sends nothing if nothing was published.
  • One request in flight. A body given while a PUBLISH is pending is sent once the response arrives, so the entity-tag always names the last publication the server accepted.
  • 412 (the server lost the entity-tag): the body is published again from scratch, once. 423: the PUBLISH is sent again with the given Min-Expires. Any other failure terminates the Publisher. terminated carries the response, so that 489, 405 or 501 can be told apart.
  • Same Call-ID for every PUBLISH, increasing CSeq, as Registrator does for REGISTER.
  • UA.stop() removes every publication before the un-REGISTER, so that watchers don't see a stale state until it expires.

Typings are in Publisher.d.ts and UA.d.ts, and C.PUBLISH is added.

JsSIP can SUBSCRIBE to an event package and NOTIFY one, but cannot
PUBLISH its own state to a presence server (or any RFC 3903 state
agent). Applications had to build the request on SIPMessage and
RequestSender internals.

`ua.publish(target, eventName, contentType, options)` returns a
Publisher, modelled on Subscriber:

- publish(body): the initial publication, or a modification. The
  SIP-ETag of each 2xx names the publication from then on.
- Refresh before expiry, with no body and SIP-If-Match, scheduled as
  Subscriber does to survive Chrome's intensive timer throttling.
- terminate(): removal, Expires: 0 and SIP-If-Match; nothing is sent if
  nothing was published.
- At most one PUBLISH in flight: a body given meanwhile is sent when the
  answer comes back, so the entity-tag always names the last accepted
  publication.
- 412 (the server lost the entity-tag: restart, or expiry while the
  page was frozen): published again from scratch, once.
- 423: published again with the Min-Expires given.
- Any other failure terminates the Publisher; `terminated` carries the
  code and the final response, so that 489/405/501 (no PUBLISH here)
  can be told from a passing failure.
- One Call-ID and an increasing CSeq for all requests, as for REGISTER.
- UA.stop() removes every publication before closing, so that watchers
  do not see a stale state until it expires.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant