Subject: [Webpush] comments on latest draft-thomson-webpush-protocol-00

From: Benjamin Bangert <[email-masked]>
Date: Thu, 9 Jul 2015 11:58:40 -0700

-Sec 3: Subscribing
What should be done if a client has subscribed to as many subscriptions as
a server will allow per authenticated-client?

"The push server MUST provide a URI for the push resource corresponding to
the push message subscription using a link relation of type
"urn:ietf:params:push"."

Can this be the same push resource for a single authenticated client?
Explanation for this in next bit.

-Sec 6: Receiving Push Messages

This section appears to require a GET for every single subscription. If you
have 80 subscriptions, upon connect, you will send 80 GET's. Also, for the
server to maintain all your subscriptions, and optionally subscription
expiration information, can make a significant impact on the per-connection
memory overhead as all this state will need to be maintained on the server
handling all these subscriptions.

Just as the receipt subscription URL is likely to be the same for the
service as a whole, I would propose allowing a Push Service to provide an
authenticated client a single push subscription URL for all subscriptions
for that client (the Location handed to App-Servers would of course vary
for each subscription). The Push Promise path would then need to be the
Location given out, so that the client could determine which subscription
each message is for.

This would allow for a single GET on connect, to begin receiving all
notifications, for all subscriptions the client has setup previously. The
client would need to realize that if it is already monitoring a
subscription for notifications, and subscribes to another that has the same
URL, then it should start expecting those notifications to be associated
with the existing http2 stream.

As this section currently stands, its quite a bit of data to resume
subscription flow on a disconnect, which would be very expensive for mobile
clients.

Having a per-client subscription resource for *all subscriptions* would
allow clients to resume notification flow faster on disconnect, with lower
server resource overhead as the entire flow of notifications can resume on
a reconnect without waiting for all the individual subscription GET's. It
would also help avoid server overloading when large batches of clients come
online/offline at once (1k clients at 80 subscriptions each connecting at
once is a quick 80k hits, etc.).

This change would require 7.3 to be updated, so that expiration of
subscriptions can be communicated in some other manner, and the client
could DELETE them in some other manner.

"A 204 (No Content) status code with no associated server pushes indicates
that no messages are presently available. This could be because push
messages have expired."

This seems to indicate that a response will be returned for a GET to a push
subscription if there are no messages, once a response has been returned
though, no push promise frames for that GET can be sent (as far as I
understand http2 stream semantics at least). If there's no messages for a
push subscription, is the intention that a 204 is sent, or that its kept
open for push promise frames for eventual notifications?

-Sec 6.2: Receiving Push Message Receipts

If an application server has sent substantial quantities of notifications,
all with push receipts, and has failed to take any action to clear its
receipt queue, what should be done to indicate to the App-Server that it
isn't allowed to send any more until it clears out its receipt queue?

It feels like there should be some way to indicate this, as its possible
the App-Server is malfunctioning rather than is being a bad actor.

Cheers,
Ben

---

From: Costin Manolache <[email-masked]>
Date: Mon, 13 Jul 2015 10:40:28 -0700

On Thu, Jul 9, 2015 at 11:58 AM, Benjamin Bangert <[email-masked]>
wrote:

> This section appears to require a GET for every single subscription. If
> you have 80 subscriptions, upon connect, you will send 80 GET's. Also, for
> the server to maintain all your subscriptions, and optionally subscription

+1 - I expressed same concerns on a separate thread.

> This seems to indicate that a response will be returned for a GET to a
> push subscription if there are no messages, once a response has been
> returned though, no push promise frames for that GET can be sent (as far as
> I understand http2 stream semantics at least). If there's no messages for a
Very good question.

AppServer  may also get disconnected ( for example a restart or upgrade or
network issue ) for some time, and it would miss
any receipt for messages previously sent.

I think a push server supporting receipts will need to have some
persistence or some mechanism to indicate that delivery receipts
may have been dropped. GCM persists the receipts and handles re-delivery.

The more common problem is the App Server can't handle the rate of receipts
- most of the times the webpush server has more resources
than an app server, so it can accept far more incoming messages than the
App Server can process receipts for.  This is even worse if
push server provides additional broadcast services. In this case I assume
HTTP/2 max number of streams will be reached, and it will
act as a flow control for the webpush service sending receipts.

Costin

---

From: Brian Raymor <[email-masked]>
Date: Sun, 19 Jul 2015 20:59:38 +0000

On Thu, Jul 9, 2015 at 11:58 AM, Benjamin Bangert <[email-masked]> wrote:

> "A 204 (No Content) status code with no associated server pushes indicates that no messages are presently available. This could be because push messages have expired."
> This seems to indicate that a response will be returned for a GET to a push subscription if there are no messages, once a response has been returned though, no push promise frames for that
> GET can be sent (as far as I understand http2 stream semantics at least). If there's no messages for a push subscription, is the intention that a 204 is sent, or that its kept open for push
> promise frames for eventual notifications? 

This is a special case for polling:

     A user agent can request the contents of the push message
     subscription resource immediately by including a Prefer header field
     [RFC7240] with a "wait" parameter set to "0".

which immediately returns a 204 if no messages are available.

Would it be clearer if separated into its own section?

---

From: Benjamin Bangert <[email-masked]>
Date: Mon, 20 Jul 2015 09:21:27 -0700

On Sun, Jul 19, 2015 at 1:59 PM, Brian Raymor <[email-masked]>
wrote:

> > "A 204 (No Content) status code with no associated server pushes
> indicates that no messages are presently available. This could be because
> push messages have expired."
> returned though, no push promise frames for that
> > GET can be sent (as far as I understand http2 stream semantics at
> least). If there's no messages for a push subscription, is the intention
> that a 204 is sent, or that its kept open for push
I'd prefer to not have this ability at all. When a client is connected,
they should get notifications as soon as possible upon identifying
themselves. Due to the cost of maintaining connections, and for abuse
mitigation, I plan on implementing the server such that a failure to
immediately begin notification flow results in the connection being dropped.

What's the use-case of a client polling over a long-lived connection (which
would also mean we're stuck with connections that *could* have
notifications sent, but for some reason the client is forcing us to dump
the message to storage rather than delivering it immediately)?

As my original proposal in my first thread though, I don't want a GET per
subscription, that's way too expensive. A single GET to resume the
notification flow for all subscriptions is preferred.

---

From: Martin Thomson <[email-masked]>
Date: Mon, 20 Jul 2015 09:31:54 -0700

On 20 July 2015 at 09:21, Benjamin Bangert <[email-masked]> wrote:
> What's the use-case of a client polling over a long-lived connection

The use case is for a device that is only periodically online (a
constrained device) that wants to check in, then immediately go
offline again.

---

From: Benjamin Bangert <[email-masked]>
Date: Mon, 20 Jul 2015 10:38:35 -0700

> constrained device) that wants to check in, then immediately go

Ah, so after such a request the server can immediately drop the connection
(might be useful to mention in the spec). This would presume that it'd be a
GET to a single notification subscription URL. If its needed for every
single subscription URL, that creates a lot of work for both the client,
and the server, which doesn't seem very beneficial for a constrained device
to be doing.

---

From: Darshak Thakore <[email-masked]>
Date: Mon, 20 Jul 2015 21:41:30 +0000

It seems like we do want some mechanism that allows a client to retrieve
notifications for all subscriptions with a single fetch. For IoT based use
cases also this is desirable. I guess this keeps going back to the
aggregation-vs-disaggregation discussion. However I¹m wondering if its
possible to define/create a sort of ³aggregation-on-demand² mode with the
default being the current ³disaggregation² mode.

For example, once a client/UA has subscribed for the first time and holds
1 subscription, when it wants to create subsequent subscriptions, it can
include the first subscription in the request:

POST /subscribe/ HTTP/1.1
HOST: push.example.net
Link: </s/LBhhw0OohO-Wl4Oi971UGsB7sdQGUibx>;
rel=³urn:ietf:params:push:subcribe² (I¹m not sure if its ok to use Link
header in a request, if not we need to find something more suitable)

When a PS processes this request, it can associate the new subscription
with the one provided. (I think the additional data stored by the PS to
achieve this should be minimal). The response would contain the new
subscription info as currently defined (and maybe something additional to
indicate that the new subscription is tied to the one in the request)

When receiving PUSH messages, a client/UA can make a single GET request to
the primary subscription resource and the server will send push
notifications for all subscriptions associated with the primary
subscription.

For example, the request would be

HEADERS		[stream 7] +EHD_STREAM +END_HEADERS
  :method	= GET
  :path		= /s/LBhhw0OohO-Wl4Oi971UGsB7sdQGUibx
  :authority	= push.example.net

And the corresponding response would be

PUSH_PROMISE 	[stream 7; promised stream 4] +END_HEADERS
  :method	= GET
  :path		= /d/qDIYHNcfAIPP_5ITvURr-d6BGtYnTRnk
  :authority	= push.example.net

HEADERS		[stream 4] +END_HEADERS
  :status	= 200
  ‹‹OTHER HEADERS ‹‹
  :content-loc	= /s/LBhhw0OohO-Wl4Oi971UGsB7sdQGUibx

DATA 		[stream 4] +END_STREAM
     iChYuI3jMzt3ir20P8r_jgRR-dSuN182x7iB

PUSH_PROMISE 	[stream 7; promised stream 6] +END_HEADERS
  :method		= GET
  :path			= /d/gjuNJTYuZXkyylOOtjfAEo6ktRHCADui
  :authority		= push.example.net

HEADERS		[stream 6] +END_HEADERS
  :status	= 200
  ‹‹OTHER HEADERS ‹‹
  :content-loc	= /s/hJ0jW1ElCjhjfwwh4kTQw7rEYK4QyFFW

DATA 		[stream 6] +END_STREAM
{encoded/encrypted-notification-message}

‹‹ additional PUSH messages for other subscriptions ‹‹

In the above example, the responses can include a Content-Location (or
some other appropriate) header to indicate the associated subscription for
the notification message. This would allow the client/UA to send just one
GET request to retrieve (and keep receiving) notifications on all its
active subscriptions. A client/UA may even choose to keep certain
subscriptions separate and group only a subset of them (this would be
useful in IoT like cases)

Darshak

On 7/20/15, 10:31 AM, "Webpush on behalf of Martin Thomson"
<[email-masked] on behalf of [email-masked]> wrote:

>_______________________________________________
>Webpush mailing list
>[email-masked]
>https://www.ietf.org/mailman/listinfo/webpush

---

From: Martin Thomson <[email-masked]>
Date: Mon, 20 Jul 2015 23:43:34 -0700

I think that this might work.  If we don't want to go all the way back
to something like the registration+subscription model of my earlier
proposals, this could work.  I think that the nice part of a design
like this is that you could treat this like a
registration+subscription by refusing to share the primary
subscription information with anyone.

A potential bit of variation and therefore complexity is that the
server might refuse to perform the association.  That means that the
client would need to be able to recognize this and handle it.  The
added complexity for the client there is traded for extra flexibility
in how the server manages subscriptions.

I think that there are a few things that would need to be tweaked here
if we do it, but the basic idea could be done.

---

From: Benjamin Bangert <[email-masked]>
Date: Tue, 21 Jul 2015 09:26:23 -0700

My preference would be for the server to be able to require this, rather
than leaving it up to the client. If a server doesn't want to expend the
heavy resource cost of treating every single subscription as its own URL,
there should be a way for the server to indicate that in its subscription
response.

For an IoT use-case, where a client might want different sets of
subscriptions entirely, and to only check one group of them, it could open
a separate h2 connection to retrieve that set.

---

From: Costin Manolache <[email-masked]>
Date: Tue, 21 Jul 2015 17:48:15 -0700

I think one question is who makes the decision if subscrptions are
'aggregated' or not. And the only answer
I know is the push provider - since the push provider is the one bearing
the costs and defining the
requirements for UAs that connect to it.

If we agree that a push provider may require 'aggregation' - all
subscriptions from a device, when connecting
to such a provider, will need to have something in common, to allow the
aggregation. The original
 "registration + subscription" does it by having a first step where a
device gets the common element.
It can be simplified by defining the 'registration' as a regular
subscription, and allowing each app to
 have a 'child' subscription. This works nicely if a UA supports
profiles/multi-user for example - and may
be extended later for more complicated cases, where a UA acts as a proxy
for other UAs ( for example
a wearable device paired over BT ).

The subscription API should allow a way to create 'links' between
subscriptions. We do need to
finish the separate discussion on sender authentication and registration -
but assuming a push service
requires sender authentication, this is another 'link' between the app
subscription and the server id (
which can be another capability URL or subscription ).

I don't think it's a problem if the 'non-aggregated' model - where nothing
is shared - is defined even as default,
and some push providers may chose to support both, or only one model,
depending on their scale and costs.

Costin

---

From: Darshak Thakore <[email-masked]>
Date: Wed, 22 Jul 2015 08:16:23 +0000

I’m not sure how you can force the PS to require this. If a client makes independent subscription requests, it will receive “unassociated” subscriptions and the client will be required to do separate GET’s for each subscription (I don’t think it needs to be a separate h2 connection, just a separate GET)

I was initially suggesting that we make this “aggregation-on-demand” as a “server SHOULD support” but if we want to make it mandatory for PS’s to support it, I’m fine with it.

Darshak

On 7/21/15, 10:26 AM, "Benjamin Bangert" <[email-masked]<mailto:[email-masked]>> wrote:

My preference would be for the server to be able to require this, rather than leaving it up to the client. If a server doesn't want to expend the heavy resource cost of treating every single subscription as its own URL, there should be a way for the server to indicate that in its subscription response.

For an IoT use-case, where a client might want different sets of subscriptions entirely, and to only check one group of them, it could open a separate h2 connection to retrieve that set.

On Mon, Jul 20, 2015 at 2:41 PM, Darshak Thakore <[email-masked]<mailto:[email-masked]>> wrote:

HOST: push.example.net<http://push.example.net>

HEADERS         [stream 7] +EHD_STREAM +END_HEADERS
  :method       = GET
  :path         = /s/LBhhw0OohO-Wl4Oi971UGsB7sdQGUibx
  :authority    = push.example.net<http://push.example.net>

PUSH_PROMISE    [stream 7; promised stream 4] +END_HEADERS
  :method       = GET
  :path         = /d/qDIYHNcfAIPP_5ITvURr-d6BGtYnTRnk
  :authority    = push.example.net<http://push.example.net>

PUSH_PROMISE    [stream 7; promised stream 6] +END_HEADERS
  :method               = GET
  :path                 = /d/gjuNJTYuZXkyylOOtjfAEo6ktRHCADui
  :authority            = push.example.net<http://push.example.net>

Darshak

On 7/20/15, 10:31 AM, "Webpush on behalf of Martin Thomson"
<[email-masked]<mailto:[email-masked]> on behalf of [email-masked]<mailto:[email-masked]>> wrote:

>On 20 July 2015 at 09:21, Benjamin Bangert <[email-masked]<mailto:[email-masked]>> wrote:
>[email-masked]<mailto:[email-masked]>

_______________________________________________
Webpush mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/webpush

---

From: Darshak Thakore <[email-masked]>
Date: Wed, 22 Jul 2015 08:25:58 +0000

Comments below

On 7/21/15, 6:48 PM, "Costin Manolache" <[email-masked]<mailto:[email-masked]>> wrote:

I think one question is who makes the decision if subscrptions are 'aggregated' or not. And the only answer
I know is the push provider - since the push provider is the one bearing the costs and defining the
requirements for UAs that connect to it.

DT>> As I mentioned in the other email (Benjamin’s email), I’m not sure how a PS can force a UA to aggregate (unless the PS somehow identifies the client based on authentication/cookie/something-else). I think the PS should/must support it but it would be the client/UA’s decision to aggregate. We can put language to “strongly recommend” the client/UA to aggregate but it would still be the client’s decision to include the initial subscription when making subsequent subscription requests.

If we agree that a push provider may require 'aggregation' - all subscriptions from a device, when connecting
to such a provider, will need to have something in common, to allow the aggregation. The original
 "registration + subscription" does it by having a first step where a device gets the common element.
It can be simplified by defining the 'registration' as a regular subscription, and allowing each app to
 have a 'child' subscription. This works nicely if a UA supports profiles/multi-user for example - and may
be extended later for more complicated cases, where a UA acts as a proxy for other UAs ( for example
a wearable device paired over BT ).

DT>> I think within the context of the fact that a client does want to “aggregate”, all of the above is doable. However as I mentioned above, if a client does not send the “parent subscription” info in the subsequent subscription requests, there’s no easy way for a PS to force aggregation.

The subscription API should allow a way to create 'links' between subscriptions. We do need to
finish the separate discussion on sender authentication and registration - but assuming a push service
requires sender authentication, this is another 'link' between the app subscription and the server id (
which can be another capability URL or subscription ).

DT>> Yes, I believe that should be doable with the idea here.

I don't think it's a problem if the 'non-aggregated' model - where nothing is shared - is defined even as default,
and some push providers may chose to support both, or only one model, depending on their scale and costs

Costin

On Tue, Jul 21, 2015 at 9:26 AM, Benjamin Bangert <[email-masked]<mailto:[email-masked]>> wrote:
My preference would be for the server to be able to require this, rather than leaving it up to the client. If a server doesn't want to expend the heavy resource cost of treating every single subscription as its own URL, there should be a way for the server to indicate that in its subscription response.

Darshak

---

From: Costin Manolache <[email-masked]>
Date: Wed, 22 Jul 2015 08:27:50 -0700

On Wed, Jul 22, 2015 at 1:25 AM, Darshak Thakore <[email-masked]>
wrote:

>  Comments below
>
>   On 7/21/15, 6:48 PM, "Costin Manolache" <[email-masked]> wrote:
>
>  DT>> As I mentioned in the other email (Benjamin’s email), I’m not sure
> how a PS can force a UA to aggregate (unless the PS somehow identifies the
> client based on authentication/cookie/something-else).
>

In aggregate model, there is a registration (or subscription) for the UA,
and each origin/serviceworker have a subscription associated with the UA.

The PS can simply reject subscriptions that don't have an associated
parent, and not deliver the the registration/root. Than the UA
may chose a different PS, or aggregate.

Or: terms of service and abuse detection on PS.

There was a thread about PS returning a URL that may require additional
user interaction when the UA registers with the PS,
and may have separate relation ( like Setup Wizard in android ). For
example GCM attempts to determine device type, if it is rooted, etc.

I don't think the expectation is that a PS MUST accept arbitrary UAs, free
and without any checks or rules.

> I think the PS should/must support it but it would be the client/UA’s
> decision to aggregate. We can put language to “strongly recommend” the
> client/UA to aggregate but it would still be the client’s decision to
> include the initial subscription when making subsequent subscription
> requests.
>

>  DT>> I think within the context of the fact that a client does want to
> “aggregate”, all of the above is doable. However as I mentioned above, if a
> client does not send the “parent subscription” info in the subsequent
> subscription requests, there’s no easy way for a PS to force aggregation.
>

I wouldn't be very worried about a small percentage of devices not
aggregating - and anything large is usually detectable.

Costin

>  I don't think it's a problem if the 'non-aggregated' model - where
> nothing is shared - is defined even as default,
> depending on their scale and costs
>
>
>  Costin
>
>>  My preference would be for the server to be able to require this,
>> rather than leaving it up to the client. If a server doesn't want to expend
>> the heavy resource cost of treating every single subscription as its own
>> URL, there should be a way for the server to indicate that in its
>> subscription response.
>>
>> On Mon, Jul 20, 2015 at 2:41 PM, Darshak Thakore <[email-masked]
>> > wrote:
>>
>>>

---

From: Benjamin Bangert <[email-masked]>
Date: Wed, 22 Jul 2015 09:30:57 -0700

> and without any checks or rules.

I'm associating one h2 connection as being one UA, and treating the first
Subscribe operation, or the first Receive Push Messages operation as the
registration. Also, I am perhaps misreading the spec in which URL is given
out to whom, now that I think about it. In Sec 3, the Subscribe response is
such:

HTTP/1.1 201 Created
Date: Thu, 11 Dec 2014 23:56:52 GMT
Link: </p/JzLQ3raZJfFBR0aqvOMsLrt54w4rJUsV>;
        rel="urn:ietf:params:push"
Link: </receipts/xjTG79I3VuptNWS0DsFu4ihT97aE6UQJ>;
        rel="urn:ietf:params:push:receipt"
Location: https://push.example.net/s/LBhhw0OohO-Wl4Oi971UGsB7sdQGUibx
Cache-Control: max-age:864000, private

My thought was that the Location link is the one given to the AppServers,
and the urn:ietf:params:push link is the 'private URL' that the UA uses to
receive push messages. This way, after the initial Subscribe, the PS has
associated that h2 connection with the private URL, and new Subscribe
requests will return new Location links to give to the AppServer. It also
means the UA would need to store the Location for each Subscribe, since the
private URL would be unchanging for all later Subscribe requests.

On reconnect, receiving push messages by hitting the private URL would then
associate the h2 connection again, acting as the registration.

If a UA wants to operate independent batches of subscriptions, as the IoT
use-case previously cited, it must use entirely separate h2 connections for
each batch.

The spec includes a Location without identifying its actual use, as my
reading of it seems unclear on if the Link is the one given to the
AppServer, or if its the Location.

This presumes that there is no h2 proxying such that individual requests
over the same connection might be on behalf of different UA's. (I really
really don't like the thought of an h2 proxy of this nature, because it
means it could lie about whether a client is still actually 'alive' to ping
frames, and that's given us enough grief with mobile TCP proxies).

In this manner, the PS could choose whether to give the same private URL
back for all Subscribe requests over the same connection, or not. The
additional requirements on the UA:
- It must store the Location, since that's the guaranteed unique part
- If it gets the same private URL back, it should only use the Receive
operation once, and realize all new push messages will come over the
existing GET
- On reconnect, it MUST send the Receive operation before any new Subscribe
operations (since that's treated as 'registration' on reconnect)

This way a PS gets to choose, and the associating link is the push link
itself. If the thought was that the push Link is the one sent to
AppServers, then some of this will need a bit of changing of course.

>>> On Mon, Jul 20, 2015 at 2:41 PM, Darshak Thakore <
>>> [email-masked]> wrote:
>>>
>>>>

---

From: Benjamin Bangert <[email-masked]>
Date: Wed, 22 Jul 2015 09:45:43 -0700

I should also note, under my scheme, unsubscribe must be handled
differently (to include Location), and push messages will also need to
include the Location for the UA to identify them correctly.

Alternatively, another Link could be added to identify the aggregation URL
that should be used, and unsubscribe can operate the same.

On Wed, Jul 22, 2015 at 9:30 AM, Benjamin Bangert <[email-masked]>
wrote:

>> On Wed, Jul 22, 2015 at 1:25 AM, Darshak Thakore <[email-masked]
>> > wrote:
>>
>>>  Comments below
>>>
>>>  DT>> As I mentioned in the other email (Benjamin’s email), I’m not
>>> sure how a PS can force a UA to aggregate (unless the PS somehow identifies
>>> the client based on authentication/cookie/something-else).
>>>
>>
>> I don't think the expectation is that a PS MUST accept arbitrary UAs,
>> free and without any checks or rules.
>>
>
> Cache-Control <https://push.example.net/s/LBhhw0OohO-Wl4Oi971UGsB7sdQGUibxCache-Control>: max-age:864000, private
>
> On reconnect, receiving push messages by hitting the private URL would
> then associate the h2 connection again, acting as the registration.
>
> - On reconnect, it MUST send the Receive operation before any new
> Subscribe operations (since that's treated as 'registration' on reconnect)
>

---

From: Darshak Thakore <[email-masked]>
Date: Wed, 22 Jul 2015 21:44:14 +0000

I think you have it backwards (maybe we need to be more explicit in the spec). The Location link is the “private” link that the UA holds. That’s the link to which the UA/client is going to make the request to for getting the notifications  (Section 6 shows that the h2 GET is being done by the UA/client to the "/s/LBhhw0OohO-Wl4Oi971UGsB7sdQGUibx"). The “urn:ietf:params:push” link is the one that is distributed to the application servers (along wit the /receipts/xxxx). The current spec requires the UA/client to make separate GET’s to the URI provided in the Location field (albeit it can be done on the same h2 connection). By linking the subscriptions to the primary subscription, the UA/client can make a single h2 GET request to primary subscription URI (the one returned in the Location header of the primary subscription) and get notifications for all subsequent subscriptions.

On 7/22/15, 10:30 AM, "Benjamin Bangert" <[email-masked]<mailto:[email-masked]>> wrote:

On Wed, Jul 22, 2015 at 8:27 AM, Costin Manolache <[email-masked]<mailto:[email-masked]>> wrote:

On Wed, Jul 22, 2015 at 1:25 AM, Darshak Thakore <[email-masked]<mailto:[email-masked]>> wrote:
Comments below

DT>> As I mentioned in the other email (Benjamin’s email), I’m not sure how a PS can force a UA to aggregate (unless the PS somehow identifies the client based on authentication/cookie/something-else).

In aggregate model, there is a registration (or subscription) for the UA, and each origin/serviceworker have a subscription associated with the UA.

The PS can simply reject subscriptions that don't have an associated parent, and not deliver the the registration/root. Than the UA
may chose a different PS, or aggregate.

There was a thread about PS returning a URL that may require additional user interaction when the UA registers with the PS,
and may have separate relation ( like Setup Wizard in android ). For example GCM attempts to determine device type, if it is rooted, etc.

I don't think the expectation is that a PS MUST accept arbitrary UAs, free and without any checks or rules.

I'm associating one h2 connection as being one UA, and treating the first Subscribe operation, or the first Receive Push Messages operation as the registration. Also, I am perhaps misreading the spec in which URL is given out to whom, now that I think about it. In Sec 3, the Subscribe response is such:

HTTP/1.1 201 Created

My thought was that the Location link is the one given to the AppServers, and the urn:ietf:params:push link is the 'private URL' that the UA uses to receive push messages. This way, after the initial Subscribe, the PS has associated that h2 connection with the private URL, and new Subscribe requests will return new Location links to give to the AppServer. It also means the UA would need to store the Location for each Subscribe, since the private URL would be unchanging for all later Subscribe requests.

On reconnect, receiving push messages by hitting the private URL would then associate the h2 connection again, acting as the registration.

If a UA wants to operate independent batches of subscriptions, as the IoT use-case previously cited, it must use entirely separate h2 connections for each batch.

The spec includes a Location without identifying its actual use, as my reading of it seems unclear on if the Link is the one given to the AppServer, or if its the Location.

This presumes that there is no h2 proxying such that individual requests over the same connection might be on behalf of different UA's. (I really really don't like the thought of an h2 proxy of this nature, because it means it could lie about whether a client is still actually 'alive' to ping frames, and that's given us enough grief with mobile TCP proxies).

In this manner, the PS could choose whether to give the same private URL back for all Subscribe requests over the same connection, or not. The additional requirements on the UA:
- It must store the Location, since that's the guaranteed unique part
- If it gets the same private URL back, it should only use the Receive operation once, and realize all new push messages will come over the existing GET
- On reconnect, it MUST send the Receive operation before any new Subscribe operations (since that's treated as 'registration' on reconnect)

This way a PS gets to choose, and the associating link is the push link itself. If the thought was that the push Link is the one sent to AppServers, then some of this will need a bit of changing of course.

I think the PS should/must support it but it would be the client/UA’s decision to aggregate. We can put language to “strongly recommend” the client/UA to aggregate but it would still be the client’s decision to include the initial subscription when making subsequent subscription requests.

I wouldn't be very worried about a small percentage of devices not aggregating - and anything large is usually detectable.

Costin

Costin

Darshak

---

From: Benjamin Bangert <[email-masked]>
Date: Wed, 22 Jul 2015 15:22:36 -0700

Yea, that's what I figured on re-reading it. The reason I interpreted it
differently is because the urn:ietf:params:push link is *relative*, while
the Location is an absolute URI. In our current Push situation, the domain
the UA connects to is a different subdomain than the domain used for
app-servers to connect to, so a relative URL just seems wrong.

I had assumed based on this, that the absolute URL then, would be the only
reasonable thing to hand out to an appserver. Either way, it should work
fine as I said if the private one is just the same for all subscriptions,
or we tack on a new Link for receiving them that is the aggregation link
that must be used if present.

On Wed, Jul 22, 2015 at 2:44 PM, Darshak Thakore <[email-masked]>
wrote:

>   I think you have it backwards (maybe we need to be more explicit in the
> spec). The Location link is the “private” link that the UA holds. That’s
> the link to which the UA/client is going to make the request to for getting
> the notifications  (Section 6 shows that the h2 GET is being done by the
> UA/client to the "/s/LBhhw0OohO-Wl4Oi971UGsB7sdQGUibx"). The
> “urn:ietf:params:push” link is the one that is distributed to the
> application servers (along wit the /receipts/xxxx). The current spec
> requires the UA/client to make separate GET’s to the URI provided in the
> Location field (albeit it can be done on the same h2 connection). By
> linking the subscriptions to the primary subscription, the UA/client can
> make a single h2 GET request to primary subscription URI (the one returned
> in the Location header of the primary subscription) and get notifications
> for all subsequent subscriptions.
>
>
>   On 7/22/15, 10:30 AM, "Benjamin Bangert" <[email-masked]> wrote:
>
>>  In aggregate model, there is a registration (or subscription) for the
>> UA, and each origin/serviceworker have a subscription associated with the
>> UA.
>>
>  I'm associating one h2 connection as being one UA, and treating the
> first Subscribe operation, or the first Receive Push Messages operation as
> the registration. Also, I am perhaps misreading the spec in which URL is
> given out to whom, now that I think about it. In Sec 3, the Subscribe
> response is such:
>
> HTTP/1.1 201 Created
>  If a UA wants to operate independent batches of subscriptions, as the
> IoT use-case previously cited, it must use entirely separate h2 connections
> for each batch.
>

---

From: Martin Thomson <[email-masked]>
Date: Wed, 22 Jul 2015 21:18:53 -0700

If we take this path, it might be necessary to reverse the slots we use for
these two URIs, simply because we would now have a need to identify the
subscription in a request to a different resource (though we could avoid
that by making the subscription URI the target of a "create subscription"
request, it offers no option for the server to reject the proposed
grouping).

Note that the use of relative URIs was for economy only; the Location
header field requires absolute URIs though. Perhaps we should be more
explicit and use absolute everywhere to avoid risking confusion.
On Jul 23, 2015 12:22 AM, "Benjamin Bangert" <[email-masked]> wrote:

>>   I think you have it backwards (maybe we need to be more explicit in
>> the spec). The Location link is the “private” link that the UA holds.
>> That’s the link to which the UA/client is going to make the request to for
>> getting the notifications  (Section 6 shows that the h2 GET is being done
>> by the UA/client to the "/s/LBhhw0OohO-Wl4Oi971UGsB7sdQGUibx"). The
>>> On Wed, Jul 22, 2015 at 1:25 AM, Darshak Thakore <
>>>  There was a thread about PS returning a URL that may require
>>> additional user interaction when the UA registers with the PS,
>>  This presumes that there is no h2 proxying such that individual
>> requests over the same connection might be on behalf of different UA's. (I
>> really really don't like the thought of an h2 proxy of this nature, because
>> it means it could lie about whether a client is still actually 'alive' to
>> ping frames, and that's given us enough grief with mobile TCP proxies).
>>
>>  In this manner, the PS could choose whether to give the same private
>> URL back for all Subscribe requests over the same connection, or not. The
>>>>  DT>> I think within the context of the fact that a client does want
>>>> to “aggregate”, all of the above is doable. However as I mentioned above,
>>>> if a client does not send the “parent subscription” info in the subsequent
>>>> finish the separate discussion on sender authentication and
>>>> registration - but assuming a push service
>>>> On Tue, Jul 21, 2015 at 9:26 AM, Benjamin Bangert <[email-masked]
>>>> > wrote:
>>>>