Confirmed users
632
edits
(After IRC discussions, the simplePush notification should spread accross the owner's devices regard less of its presence in the room.) |
|||
(52 intermediate revisions by 4 users not shown) | |||
Line 25: | Line 25: | ||
|- | |- | ||
| Wed Oct 1 14:55:42 CEST 2014 || Rémy Hubscher || Add the ctime parameter on GET /rooms/:token. | | Wed Oct 1 14:55:42 CEST 2014 || Rémy Hubscher || Add the ctime parameter on GET /rooms/:token. | ||
|- | |||
| Thu Oct 2 16:32:42 CEST 2014 || Rémy Hubscher || Improve the notification description. | |||
|- | |||
| Thu Oct 3 16:32:42 CEST 2014 || Alexis Métaireau || Use Numbers instead of Strings in JSON outputs / inputs. | |||
|- | |||
| Mon Oct 6 14:51:52 UTC 2014 || Adam Roach || Added room URL to GET /rooms and GET /rooms/:token | |||
|- | |||
| Thu Oct 9 15:40:15 UTC 2014 || Adam Roach || Added sessionToken to "action: refresh" and "action: leave" operations for correlation and auth. | |||
|- | |||
| Wed Oct 22 15:16:38 UTC 2014 || Adam Roach || Modifications based on discussion in {{Bug|1074665}}: list of rooms now contains the same information as is indicated when retrieving a single room directly. Additionally, when getting a versioned list of rooms, any rooms that have been deleted since the indicated version will be listed, with a "deleted: true" field. | |||
|- | |||
| Mon Dec 29 16:55:10 UTC 2014 || Rémy Hubscher || Proposal to handle {{Bug|1106562}}: Multiple rooms deletion in one HTTP call. | |||
|- | |||
| Wed Feb 25 22:26:48 UTC 2015 || Adam Roach || Added new operation to <tt>POST /rooms/:token</tt> to send room session state to Loop server for logging purposes. | |||
|} | |} | ||
Line 42: | Line 56: | ||
"displayName": "Alexis", | "displayName": "Alexis", | ||
"account": "alexis@example.com", | "account": "alexis@example.com", | ||
" | "roomConnectionId": "2a1787a6-4a73-43b5-ae3e-906ec1e763cb" | ||
} | } | ||
* '''displayName''' - The user-friendly name that should be displayed for this participant | * '''displayName''' - The user-friendly name that should be displayed for this participant | ||
* '''account''' - If the user is logged in, this is the FxA account name or MSISDN that was used to authenticate the user for this session | * '''account''' - If the user is logged in, this is the FxA account name or MSISDN that was used to authenticate the user for this session | ||
* ''' | * '''roomConnectionId''' - An id, unique within the room for the lifetime of the room, used to identify a participant ''for the duration of one instance of joining the room''. If the user departs and re-joins, this id will change. Note that this document uses a UUID in its examples, since they can be used in this fashion without having to store additional state; however, anything that is unique within a room for its entire lifetime (e.g., a constantly increasing integer) would be suitable as well. | ||
== Room Size Handling == | == Room Size Handling == | ||
Line 173: | Line 187: | ||
{ | { | ||
"roomName": "UX Discussion", | "roomName": "UX Discussion", | ||
"expiresIn": | "expiresIn": 5, | ||
"roomOwner": "Alexis", | "roomOwner": "Alexis", | ||
"maxSize": | "maxSize": 2 | ||
} | } | ||
Line 212: | Line 226: | ||
{ | { | ||
" | "context": { | ||
"expiresIn": | "value": "PWjHj89HBS-...ICUX3Iqd9ZsfDNLoUeAb5KGJgEtDy-7ag52rYY5mGgP2GQ==", | ||
"alg": "AES-GCM", | |||
"wrappedKey": "KLPCJEy8vewUeHFFLtvMNA" | |||
}, | |||
"expiresIn": 24 | |||
} | } | ||
Line 244: | Line 262: | ||
Date: Wed, 16 Jul 2014 13:12:46 GMT | Date: Wed, 16 Jul 2014 13:12:46 GMT | ||
Server-Authorization: <stripped> | Server-Authorization: <stripped> | ||
''Client implementation note: Before deleting a room, the client should check room membership and forceDisconnect() all current participants'' | |||
=== PATCH /rooms === | |||
Destroys a list of user's previously-created rooms. | |||
PATCH /rooms HTTP/1.1 | |||
Accept: */* | |||
Accept-Encoding: gzip, deflate | |||
Authorization: <stripped> | |||
Content-Length: 0 | |||
Host: localhost:5000 | |||
{"deleteRoomTokens": ["_nxD4V4FflQ", "_xaB2Z5GdTV"]} | |||
HTTP/1.1 207 Multi-Status | |||
Connection: keep-alive | |||
Date: Wed, 16 Jul 2014 13:12:46 GMT | |||
Server-Authorization: <stripped> | |||
{ | |||
"responses": { | |||
"_nxD4V4FflQ": { "code": 200 }, | |||
"_xaB2Z5GdTV": { "code": 200 } | |||
} | |||
} | |||
In case of error for some token: | |||
HTTP/1.1 207 Multi-Status | |||
Connection: keep-alive | |||
Date: Wed, 16 Jul 2014 13:12:46 GMT | |||
Server-Authorization: <stripped> | |||
{ | |||
"responses": { | |||
"_nxD4V4FflQ": { "code": 200 }, | |||
"_xaB2Z5GdTV": { "code": 404, errno: 105, message: "Room not found" }, | |||
} | |||
} | |||
''Client implementation note: Before deleting a room, the client should check room membership and forceDisconnect() all current participants'' | ''Client implementation note: Before deleting a room, the client should check room membership and forceDisconnect() all current participants'' | ||
Line 249: | Line 309: | ||
=== GET /rooms/{token} === | === GET /rooms/{token} === | ||
This endpoint is used to retrieve information about a single room, including a list of room participants. | This endpoint is used to retrieve information about a single room, including a list of room participants. | ||
<s>Because providing this information to users who are not in the room would be surprising for those in the room, we only allow the room owner and users in the room to access this method. Room owners are authenticated via their HAWK credentials, while room participants are authenticated via the sessionToken bearer token provided to them when they joined the room.</s> | |||
GET /rooms/3jKS_Els9IU HTTP/1.1 | GET /rooms/3jKS_Els9IU HTTP/1.1 | ||
Accept: */* | Accept: */* | ||
Accept-Encoding: gzip, deflate | Accept-Encoding: gzip, deflate | ||
'''Authorization: <elided>''' | |||
Host: localhost:5000 | Host: localhost:5000 | ||
* For a desktop client user, the "Authorization" header field is populated with the HAWK token (using a scheme of "Hawk"), just like it is for other requests. | |||
* For the standalone client, the "Authorization" header field is encoded using [http://tools.ietf.org/html/rfc1945#section-11.1 Basic authentication]. The user ID portion is the sessionToken provided to the user when they joined the room, and the password is blank. | |||
HTTP/1.1 200 OK | HTTP/1.1 200 OK | ||
Line 264: | Line 331: | ||
{ | { | ||
"roomToken": "3jKS_Els9IU", | |||
"roomName": "UX Discussion", | "roomName": "UX Discussion", | ||
"roomUrl": "http://localhost:3000/rooms/3jKS_Els9IU", | |||
"roomOwner": "Alexis", | "roomOwner": "Alexis", | ||
"maxSize": 2, | "maxSize": 2, | ||
"clientMaxSize": 2, | "clientMaxSize": 2, | ||
"creationTime": 1405517546, | "creationTime": 1405517546, | ||
"ctime": 1405517824, | |||
"expiresAt": 1405534180, | "expiresAt": 1405534180, | ||
"participants": [ | "participants": [ | ||
{ "displayName": "Alexis", "account": "alexis@example.com", " | { "displayName": "Alexis", "account": "alexis@example.com", "roomConnectionId": "2a1787a6-4a73-43b5-ae3e-906ec1e763cb" }, | ||
{ "displayName": "Adam", " | { "displayName": "Adam", "roomConnectionId": "781f012b-f1ea-4ce1-9105-7cfc36fb4ec7" } | ||
] | ] | ||
} | } | ||
* '''roomToken''' - The token that uniquely identifies this room | |||
* '''roomName''' - The room-owner-assigned name used to identify this room. | * '''roomName''' - The room-owner-assigned name used to identify this room. | ||
* '''roomUrl''' - A URL that can be given to other users to allow them to join the room. | |||
* '''roomOwner''' - The user-friendly display name indicating the name of the room's owner. | * '''roomOwner''' - The user-friendly display name indicating the name of the room's owner. | ||
* '''maxSize''' - The maximum number of users allowed in the room at one time (as configured by the room owner). | * '''maxSize''' - The maximum number of users allowed in the room at one time (as configured by the room owner). | ||
Line 283: | Line 355: | ||
* '''expiresAt''' - The time (in seconds since the Unix epoch) at which the room goes away. | * '''expiresAt''' - The time (in seconds since the Unix epoch) at which the room goes away. | ||
* '''participants''' - An array containing a list of the current room participants. Each participant is formatted with the same fields as described in [[#User Identification in a Room]]. | * '''participants''' - An array containing a list of the current room participants. Each participant is formatted with the same fields as described in [[#User Identification in a Room]]. | ||
* '''ctime''' - Similar in spirit to the Unix filesystem "ctime" (change time) attribute. The time, in seconds since the Unix epoch, that any of the following happened to the room: | |||
** The room was created | |||
** The owner modified its attributes with "PATCH /rooms/{token}" | |||
** A user joined the room | |||
** A user left the room | |||
=== POST /rooms/{token} === | === POST /rooms/{token} === | ||
Line 289: | Line 366: | ||
==== Joining a Room ==== | ==== Joining a Room ==== | ||
Server implementation note: associate user token with sessionToken here. Room owner must have "moderator" privileges. | Server implementation note: associate user token with sessionToken here. Room owner must have "moderator" privileges. | ||
* For a desktop client user, the "Authorization" header field is populated with the HAWK token (using a scheme of "Hawk"), just like it is for other requests. | |||
* For the standalone client, on this endpoint action there is no Authorization header | |||
POST /rooms/QzBbvGmIZWU HTTP/1.1 | POST /rooms/QzBbvGmIZWU HTTP/1.1 | ||
Line 300: | Line 380: | ||
"action": "join", | "action": "join", | ||
"displayName": "Adam", | "displayName": "Adam", | ||
"clientMaxSize": | "clientMaxSize": 2 | ||
} | } | ||
Line 320: | Line 400: | ||
} | } | ||
* '''apiKey''' - The | * '''apiKey''' - The TokBox public api Key | ||
* '''sessionId''' - The | * '''sessionId''' - The TokBox session identifier (identifies the room) | ||
* '''sessionToken''' - The | * '''sessionToken''' - The TokBox session token (identifies the room participant) | ||
* '''expires''' - The number of seconds within which the client must send another POST to this endpoint to remain a participant in this room. See [[#Room Membership and Soft State]] | * '''expires''' - The number of seconds within which the client must send another POST to this endpoint to remain a participant in this room. See [[#Room Membership and Soft State]] | ||
==== Refreshing Membership in a Room ==== | ==== Refreshing Membership in a Room ==== | ||
* For a desktop client user, the "Authorization" header field is populated with the HAWK token (using a scheme of "Hawk"), just like it is for other requests. | |||
* For the standalone client, the "Authorization" header field is encoded using [http://tools.ietf.org/html/rfc1945#section-11.1 Basic authentication]. The user ID portion is the sessionToken provided to the user when they joined the room, and the password is blank. | |||
POST /rooms/QzBbvGmIZWU HTTP/1.1 | POST /rooms/QzBbvGmIZWU HTTP/1.1 | ||
Line 339: | Line 422: | ||
* '''action''' - For refreshing the soft state relationship, this will be "refresh". | * '''action''' - For refreshing the soft state relationship, this will be "refresh". | ||
* '''sessionToken''' - The session token received when joining the room. Used to identify the session to be refreshed as well as to authorize the user to perform the refresh. | |||
HTTP/1.1 200 OK | HTTP/1.1 200 OK | ||
Line 347: | Line 431: | ||
{ | { | ||
"expires": | "expires": 600 | ||
} | } | ||
Line 353: | Line 437: | ||
==== Leaving a Room ==== | ==== Leaving a Room ==== | ||
* For a desktop client user, the "Authorization" header field is populated with the HAWK token (using a scheme of "Hawk"), just like it is for other requests. | |||
* For the standalone client, the "Authorization" header field is encoded using [http://tools.ietf.org/html/rfc1945#section-11.1 Basic authentication]. The user ID portion is the sessionToken provided to the user when they joined the room, and the password is blank. | |||
POST /rooms/QzBbvGmIZWU HTTP/1.1 | POST /rooms/QzBbvGmIZWU HTTP/1.1 | ||
Line 366: | Line 453: | ||
* '''action''' - For leaving a room, this will be "leave". | * '''action''' - For leaving a room, this will be "leave". | ||
* '''sessionToken''' - The session token received when joining the room. Used to identify the session to be left as well as to authorize the user to perform the leave. | |||
HTTP/1.1 204 No Content | |||
Connection: keep-alive | |||
Server-Authorization: <stripped> | |||
==== Updating Session State ==== | |||
In order to track room state for metric purposes, the client will also send a POST message to the "/rooms/{token}" endpoint whenever a state change occurs, according to the following state machine: | |||
[[File:loop-room-state.png|center|Room Session State Diagram]] | |||
<center><graphviz format="png" renderer="dot"> | |||
digraph loop_room_state { | |||
init; | |||
waiting; | |||
starting; | |||
sending; | |||
receiving; | |||
sendrecv; | |||
cleanup; | |||
init->waiting [label="Sesssion.connectionCreated"] | |||
waiting->starting [label="Sesssion.connectionCreated"] | |||
starting->receiving [label="Sesssion.streamCreated"] | |||
starting->sending [label="Publisher.streamCreated"] | |||
receiving->sendrecv [label="Publisher.streamCreated"] | |||
sending->sendrecv [label="Session.streamCreated"] | |||
sendrecv->receiving [label="Publisher.streamDestroyed\nif send count = 0"] | |||
sendrecv->sending [label="Session.streamDestroyed\nif recv count = 0"] | |||
sending->cleanup [label="Publisher.streamDestroyed\nif send count = 0"] | |||
receiving->cleanup [label="Session.streamDestroyed\nif recv count = 0"] | |||
cleanup->waiting [label="Session.connectionDestroyed\nif connection count = 1"] | |||
waiting->init [label="Session.connectionDestroyed"] | |||
} | |||
</graphviz></center> | |||
Note that there are some exceptional transitions that are not shown; in particular, a "session.connectionDestroyed" event from any of the "starting", "sending", "receiving", or "sendrecv" states will cause a transition to "waiting." | |||
In order to run this state machine, the client must (in addition to the current state) keep track of three counters: | |||
# Total connection count | |||
#* Increased when event "Session.connectionCreated" occurs | |||
#* Decreased when event "Session.connectionDestroyed" occurs | |||
# Count of streams currently being received | |||
#* Increased when event "Session.streamCreated" occurs | |||
#* Decreased when event "Session.StreamDestroyed" occurs | |||
# Count of streams currently being sent | |||
#* Increased when event "Publisher.streamCreated" occurs | |||
#* Decreased when event "Publisher.StreamDestroyed" occurs | |||
* For a desktop client user, the "Authorization" header field is populated with the HAWK token (using a scheme of "Hawk"), just like it is for other requests. | |||
* For the standalone client, the "Authorization" header field is encoded using [http://tools.ietf.org/html/rfc1945#section-11.1 Basic authentication]. The user ID portion is the sessionToken provided to the user when they joined the room, and the password is blank. | |||
POST /rooms/QzBbvGmIZWU HTTP/1.1 | |||
Accept: application/json | |||
Accept-Encoding: gzip, deflate | |||
Content-Type: application/json; charset=utf-8 | |||
Authorization: <stripped> | |||
Host: localhost:5000 | |||
{ | |||
"action": "status", | |||
"event": "Session.connectionCreated", | |||
"state": "sendrecv", | |||
"connections": 2, | |||
"sendStreams": 1, | |||
"recvStreams": 1 | |||
} | |||
* '''action''' - For updating session state, this will be "status". | |||
* '''event''' - The event that cause the state to be updated. These are currently based on the TokBox events. Possible values include: | |||
** ''Session.connectionCreated'' | |||
** ''Session.connectionDestroyed'' | |||
** ''Session.streamCreated'' | |||
** ''Session.streamDestroyed'' | |||
** ''Publisher.streamCreated'' | |||
** ''Publisher.streamDestroyed'' | |||
* '''state''' - From the state diagram above. Will be one of: | |||
** ''init'' - Initial and terminal state | |||
** ''waiting'' - Client is in room, is waiting for another user to show up | |||
** ''starting'' - Other user has joined, and media is being established | |||
** ''sending'' - Outbound media streams are set up, but inbound are not | |||
** ''receiving'' - Inbound media streams are set up, but outbound are not | |||
** ''sendrecv'' - Client is sending and receiving media: the session is set up | |||
** ''cleanup'' - No streams are being sent or received, and the session connection should be torn down momentarily | |||
* '''connections''' - Number of ongoing connections (learned by counting Session.connectionCreated and Session.connectionDestroyed) | |||
* '''sendStreams''' - Number of streams being sent (learned by counting Publisher.streamCreated and Publisher.streamDestroyed) | |||
* '''recvStreams''' - Number of streams being received (learned by counting Session.streamCreated and Session.streamDestroyed) | |||
HTTP/1.1 204 No Content | HTTP/1.1 204 No Content | ||
Line 394: | Line 571: | ||
"roomToken": "_nxD4V4FflQ", | "roomToken": "_nxD4V4FflQ", | ||
"roomName": "First Room Name", | "roomName": "First Room Name", | ||
" | "roomUrl": "http://localhost:3000/rooms/_nxD4V4FflQ", | ||
" | "roomOwner": "Alexis", | ||
"ctime": " | "maxSize": 2, | ||
"creationTime": 1405517546, | |||
"ctime": 1405517546, | |||
"expiresAt": 1405534180, | |||
"participants": [] | |||
}, | }, | ||
{ | { | ||
"roomToken": "QzBbvGmIZWU", | "roomToken": "QzBbvGmIZWU", | ||
"roomName": "Second Room Name", | "roomName": "Second Room Name", | ||
" | "roomUrl": "http://localhost:3000/rooms/QzBbvGmIZWU", | ||
" | "roomOwner": "Alexis", | ||
"ctime": " | "maxSize": 2, | ||
"creationTime": 1405517546, | |||
"ctime": 1405517546, | |||
"expiresAt": 1405534180, | |||
"participants": [] | |||
}, | }, | ||
{ | { | ||
"roomToken": "3jKS_Els9IU", | "roomToken": "3jKS_Els9IU", | ||
"roomName": " | "roomName": "UX Discussion", | ||
" | "roomUrl": "http://localhost:3000/rooms/3jKS_Els9IU", | ||
"clientMaxSize": " | "roomOwner": "Alexis", | ||
" | "maxSize": 2, | ||
" | "clientMaxSize": 2, | ||
"creationTime": 1405517546, | |||
"ctime": 1405517818, | |||
"expiresAt": 1405534180, | |||
"participants": [ | |||
{ "displayName": "Alexis", "account": "alexis@example.com", "roomConnectionId": "2a1787a6-4a73-43b5-ae3e-906ec1e763cb" }, | |||
{ "displayName": "Adam", "roomConnectionId": "781f012b-f1ea-4ce1-9105-7cfc36fb4ec7" } | |||
] | |||
}, | |||
{ | |||
"roomToken": "z9Hg4Bk19_Z", | |||
"deleted": true | |||
} | } | ||
] | ] | ||
This body is an array of rooms, each of which is formatted as described in [[#GET_.2Frooms.2F.7Btoken.7D]]. | |||
Additionally, if a "?version=<version>" parameter is included, then the list will include the rooms that have been deleted since that version. These entries will simply include the roomToken, plus a field "deleted" with a value of "true". None of the other fields need to be included for deleted rooms. | |||
[[Category:Firefox Hello]] | |||