Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Issue 494573002: A change for the setPause() api in chrome.sockets.tcp:

Created:
6 years, 4 months ago by lally
Modified:
4 years, 11 months ago
CC:
cbentzel+watch_chromium.org, chromium-apps-reviews_chromium.org, chromium-reviews, extensions-reviews_chromium.org, ldixon
Target Ref:
refs/pending/heads/master
Project:
chromium
Visibility:
Public.

Description

A change for the setPause() api in chrome.sockets.tcp: - setPause's callback will not be invoked until after any pending onReceive callbacks have already been invoked. - No onReceive callbacks will be invoked until setPause(false) is invoked after a successful setPause(true). BUG=403076

Patch Set 1 #

Patch Set 2 : Substantially cleaned up, and verified to make secure() work in STARTLS cases. #

Patch Set 3 : Updated to pause TLS sockets and a substantial refactor. #

Patch Set 4 : Cosmetics and commentary. #

Total comments: 15
Unified diffs Side-by-side diffs Delta from patch set Stats (+1103 lines, -43 lines) Patch
A extensions/browser/api/socket/passthrough.h View 1 2 1 chunk +129 lines, -0 lines 2 comments Download
M extensions/browser/api/socket/tcp_socket.h View 1 2 3 7 chunks +190 lines, -2 lines 9 comments Download
M extensions/browser/api/socket/tcp_socket.cc View 1 2 6 chunks +240 lines, -3 lines 0 comments Download
A extensions/browser/api/socket/tcp_socket_unittest.cc View 1 2 1 chunk +150 lines, -0 lines 0 comments Download
M extensions/browser/api/socket/tls_socket.h View 1 2 4 chunks +5 lines, -8 lines 0 comments Download
M extensions/browser/api/socket/tls_socket.cc View 1 2 5 chunks +10 lines, -6 lines 2 comments Download
M extensions/browser/api/sockets_tcp/sockets_tcp_api.h View 1 2 1 chunk +2 lines, -0 lines 0 comments Download
M extensions/browser/api/sockets_tcp/sockets_tcp_api.cc View 1 2 4 chunks +22 lines, -1 line 2 comments Download
M extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc View 1 2 5 chunks +336 lines, -12 lines 0 comments Download
M extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc View 1 2 5 chunks +17 lines, -10 lines 0 comments Download
M extensions/extensions_tests.gypi View 1 2 1 chunk +1 line, -0 lines 0 comments Download
M net/socket/tcp_client_socket.h View 1 2 1 chunk +1 line, -1 line 0 comments Download

Messages

Total messages: 33 (3 generated)
rpaquay
I am adding rsleevi@ for his advice on this issue. I am wondering is there ...
6 years, 4 months ago (2014-08-22 17:50:05 UTC) #1
chromium-reviews
I was hoping to have it a little better "cooked" before Ryan saw it, but ...
6 years, 4 months ago (2014-08-22 19:02:50 UTC) #2
rpaquay
On 2014/08/22 19:02:50, chromium-reviews wrote: > I was hoping to have it a little better ...
6 years, 4 months ago (2014-08-22 19:18:57 UTC) #3
Ryan Sleevi
On 2014/08/22 19:18:57, rpaquay wrote: > On 2014/08/22 19:02:50, chromium-reviews wrote: > > I was ...
6 years, 4 months ago (2014-08-25 04:20:57 UTC) #4
Ryan Sleevi
In general, I think I'm fairly strongly opposed to this API - or more importantly, ...
6 years, 4 months ago (2014-08-25 04:23:10 UTC) #5
chromium-reviews
Fair enough. I've updated the BUG= in the description to point to the original bug ...
6 years, 4 months ago (2014-08-25 20:54:13 UTC) #6
lally
Hello, this is a fix to sockets.tcp's setPause() implementation. setPause() has a TCPSocketEventDispatcher, which issues ...
5 years ago (2015-12-04 19:32:40 UTC) #10
Ken Rockot(use gerrit already)
On 2015/12/04 at 19:32:40, lally wrote: > Hello, this is a fix to sockets.tcp's setPause() ...
5 years ago (2015-12-07 15:54:29 UTC) #11
Ken Rockot(use gerrit already)
On 2015/12/07 at 15:54:29, Ken Rockot wrote: > On 2015/12/04 at 19:32:40, lally wrote: > ...
5 years ago (2015-12-07 16:00:53 UTC) #12
chromium-reviews
I'm happy with a "start paused" option, and a read() method to access a paused ...
5 years ago (2015-12-07 16:24:33 UTC) #13
Ken Rockot(use gerrit already)
I think it would be reasonable (for #5) to have a max pending receive option. ...
5 years ago (2015-12-07 16:32:39 UTC) #14
chromium-reviews
I'm happy with an N > 1 approach. I'm not sure how else to fix ...
5 years ago (2015-12-07 17:15:06 UTC) #15
Ken Rockot(use gerrit already)
I'm not convinced it needs to be fixed as long as it's understood that there's ...
5 years ago (2015-12-07 17:17:14 UTC) #16
chromium-reviews
In avoiding this, I think we'd just be making clients implement the same buffer in ...
5 years ago (2015-12-07 20:12:49 UTC) #17
Ken Rockot(use gerrit already)
On 2015/12/07 at 20:12:49, chromium-reviews wrote: > In avoiding this, I think we'd just be ...
5 years ago (2015-12-08 20:48:13 UTC) #18
chromium-reviews
I believe Lally shared the the proposed design <https://docs.google.com/document/d/1sAWQZ0Dvbz-xl_zo6Qv4CARIBA5BLrb0SKPiao8sy3c/> quite a while ago and it ...
5 years ago (2015-12-08 21:14:56 UTC) #19
Ken Rockot(use gerrit already)
I'm happy to schedule a VC, but I've read the document, and we've discussed alternative ...
5 years ago (2015-12-08 21:26:51 UTC) #20
chromium-reviews
#2 is correct. #1 works fine as long as you have a trivial STARTLS protocol. ...
5 years ago (2015-12-10 18:53:36 UTC) #21
Ken Rockot(use gerrit already)
On Thu, Dec 10, 2015 at 10:52 AM, Lally Singh <lally@google.com> wrote: > #2 is ...
5 years ago (2015-12-10 19:00:13 UTC) #22
chromium-reviews
I asked around the team for where we were having and seeing pain points: * ...
5 years ago (2015-12-14 16:46:45 UTC) #23
chromium-reviews
Reading a set of bytes can be important for STARTTLS flows, especially because I don't ...
5 years ago (2015-12-14 17:39:05 UTC) #24
rpaquay
Reading through this thread, it seems the main concern is the complexity of the current ...
5 years ago (2015-12-14 19:07:00 UTC) #25
chromium-reviews
Hi Renaud, Thank you for this -- any ideas on making this simpler help. I ...
5 years ago (2015-12-14 21:46:50 UTC) #26
chromium-reviews
Oh, and I forgot to respond to your second part. There's another CL I've written ...
5 years ago (2015-12-14 21:55:27 UTC) #27
Ken Rockot(use gerrit already)
I did a first pass here. Note that I haven't reviewed the details of SocketPauseBuffer's ...
5 years ago (2015-12-15 17:17:49 UTC) #28
chromium-reviews
Thanks Ken. I'm pretty happy to look into this. Thank you for your consideration. I'll ...
5 years ago (2015-12-15 17:26:00 UTC) #29
chromium-reviews
Hi Ken, I've been thinking about this. How's this? 1. The TCPSocketEventDispatcher keeps buffers for ...
5 years ago (2015-12-22 19:45:16 UTC) #30
Ken Rockot(use gerrit already)
On Tue, Dec 22, 2015 at 11:44 AM, Lally Singh <lally@google.com> wrote: > Hi Ken, ...
4 years, 11 months ago (2016-01-04 19:39:03 UTC) #31
Ken Rockot(use gerrit already)
On Mon, Jan 4, 2016 at 11:39 AM, Ken Rockot <rockot@chromium.org> wrote: > On Tue, ...
4 years, 11 months ago (2016-01-04 20:10:26 UTC) #32
chromium-reviews
4 years, 11 months ago (2016-01-04 20:11:35 UTC) #33
On Mon, Jan 4, 2016 at 2:39 PM, Ken Rockot <rockot@chromium.org> wrote:

> On Tue, Dec 22, 2015 at 11:44 AM, Lally Singh <lally@google.com> wrote:
>
>> Hi Ken,
>>
>> I've been thinking about this.  How's this?
>>
>> 1. The TCPSocketEventDispatcher keeps buffers for the last N reads,
>> feeding them once at a time to JavaScript.
>>
>
> I don't really see the point of buffering in the event dispatcher. That
> introduces roughly the same complexity of my proposal (i.e. having to push
> data back to buffers) without avoiding unnecessary receive latency.
>
> If we're going to dismiss the importance of avoiding said latency, IMHO we
> should just go with your original approach and buffer at the socket API
> layer. But I'm not convinced that we should dismiss it.
>

I didn't meant to dismiss latency.  I just wanted to avoid touching the
javascript event queue -- it's a separate part of code that doesn't have
anyone else touching it in any way close to this right now.


>
>
>> 2. If JavaScript pauses the socket, it pauses similarly to the current CL
>> (modulo any changes you've wanted on it), and pushes the data from the
>> buffers back into the SocketBuffer we have now (conceptually -- there are
>> some optimizations available here)
>> 3. If we secure(), the pushed-back data naturally gets fed into the TLS
>> stack.
>> 4. On unpause, the TCPSocketEventDispatcher will re-execute N reads from
>> the socket, putting them in buffers to dispatch to JavaScript.  If data in
>> the buffers from step 1 were encrypted, these N buffers will be unencrypted
>> versions (roughly -- handshakes, headers, etc., change the size
>> relationship between cyphertext and cleartext) of them.
>>
>> The big benefit is that we don't have to try to un-queue javascript
>> events, which avoids trying to push data backwards from the
>> javascript-running thread back to the TCPSocketEventDispatcher's thread.
>> So far, AFAICT, there isn't any per-event specialization that fiddles with
>> that queue, so it seems avoiding special logic for onReceive is
>> preferable.  We can be a bit smart about when we generate the actual JS
>> events and keep data in the SocketBuffer until absolutely necessary, making
>> the push-back just a subtraction or two.
>>
>
> No need to muck with generic event dispatch logic. The idea would be to
> introduce a new event (e.g. onReceiveInternal) which
> TCPSocketEventDispatcher would dispatch instead of onReceive. We'd add a
> listener for this event in custom bindings JS which would do its own simple
> queuing, and would dispatch onReceive events as desired.
>
> The custom bindings could then trivially implement a synchronous pause()
> entirely in JS. secure() would be straightforward as well: we'd move the
> existing secure() to a secureInternal() (still a browser-side C++ impl)
> which also takes a list of outstanding receive buffers. The JS
> implementation of secure() would steal all queued receives and feed them to
> secureInternal().
>

Oh, this all sounds pretty reasonable.


>
>
>> But you still have two cons on read latency:
>>  - we still read into a separate buffer and copy into events
>>  - still a full round-trip per read event, but that's only an issue if
>> there's another read event waiting for you when the ack comes back.
>> High-throughput apps should probably raise the per-read size (independent
>> of this change), and possibly reduce N if they don't want excess RAM
>> overhead.
>>
>
>>
>>
>>
>> Cheers,
>> $ ls
>>
>> Lally Singh | Google Ideas <http://www.google.com/ideas/> | Engineering |
>>  lally@google.com
>>
>>
>> On Tue, Dec 15, 2015 at 12:17 PM, <rockot@chromium.org> wrote:
>>
>>> I did a first pass here. Note that I haven't reviewed the details of
>>> SocketPauseBuffer's implementation at all yet, and this review mostly
>>> covers
>>> stylistic and readability concerns. But before reading all my inline
>>> comments...
>>>
>>> I really, really want to make sure we're doing the right thing here and
>>> I'm
>>> still not convinced :(
>>>
>>> It seems very sad to say we're going to only allow 1 pending receive
>>> event at a
>>> time. I know you agreed that we can/should add an option for variable
>>> queue
>>> length, but that's only useful for configuring back-pressure when NOT
>>> using TLS.
>>>
>>> AFAICT (please correct me if I'm wrong) many folks who need to perform
>>> TLS setup
>>> (including uProxy) will in practice be forced to set the queue length to
>>> 1,
>>> because you need to ensure that every other receive is still buffered in
>>> the
>>> browser process at the time you call secure().
>>>
>>> This means that in practice you're going to force a complete IPC
>>> round-trip
>>> between every socket read, and that can't be good. Of course you could
>>> bump up
>>> the receive queue length once TLS is established, but what do you do on a
>>> connection that isn't TLS yet but which might want to upgrade at any
>>> time?
>>>
>>> Here's another strawman counter-proposal:
>>>  1. Implement a max receive queue option *strictly* to support efficient
>>> back-pressure.
>>>  2. Add a private API that lets internal bindings push data from pending
>>> receive
>>> events back the browser
>>>  3. Implement additional pause logic in the JS layer that immediately
>>> stops
>>> receive events from firing
>>>  4. (optional if needed) implement a read() API which can be used while
>>> paused.
>>> This can pull data from buffered events if available.
>>>  5. have secure() push any pending receive event data back to the
>>> browser before
>>> upgrading
>>>
>>> This of course introduces some non-trivial complexity to support pushing
>>> data
>>> back into socket objects, and that might make it undesirable... but it
>>> allows
>>> you to reliably implement back-pressure and get the setPaused() and
>>> secure()
>>> semantics you desire without forcing you to settle for higher-latency
>>> reads
>>> everywhere. WDYT?
>>>
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> File extensions/browser/api/socket/passthrough.h (right):
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/passthrough.h:24: class Passthrough :
>>> public DefaultInitializer<BaseSocket> {
>>> I am generally not happy with this approach. It saves a few lines of
>>> code at the expense of readability.
>>>
>>> Could you please just delete Passthrough<T> and DefaultInitializer<T>,
>>> and and implement BufferingStreamSocket and BufferingTCPClientSocket
>>> without them?
>>>
>>> There should not be much redundancy since BufferingTCPClientSocket can
>>> still inherit from BufferingStreamSocket.
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/passthrough.h:27: :
>>> base_socket_(impl.Pass()) {}
>>> nit: (everywhere) New code should use std::move instead of Pass()
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> File extensions/browser/api/socket/tcp_socket.h (right):
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tcp_socket.h:23: typedef
>>> base::Callback<void(void)> PauseCompletionCallback;
>>> nit: please use a type alias instead of typedef now
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tcp_socket.h:33: class SocketPauseBuffer {
>>> This class should be in its own header and cc file
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tcp_socket.h:35: typedef base::Callback<
>>> nit: type alias
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tcp_socket.h:89: void
>>> InsureBufferCanHold(int num_bytes);
>>> nit: s/Insure/Ensure/
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tcp_socket.h:103: // BufferingStreamSocket
>>> is a client of downstream_socket_.
>>> downstream_socket_ doesn't exist
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tcp_socket.h:105: //
>>> scoped_ptr<net::StreamSocket> downstream_socket_;
>>> Remove this?
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tcp_socket.h:144: class
>>> BufferingStreamSocket : public Passthrough<net::StreamSocket> {
>>> This class should have its own header and cc
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tcp_socket.h:174: class
>>> BufferingTCPClientSocket : public Passthrough<net::TCPClientSocket> {
>>> This class should have its own header and cc
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tcp_socket.h:314: void ApiPauseComplete();
>>> nit: How about NotifyPauseComplete?
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> File extensions/browser/api/socket/tls_socket.cc (right):
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tls_socket.cc:53: // Wrap the StreamSocket
>>> in a BufferingTCPSocket, to support SetPaused().
>>> nit: s/BufferingTCPSocket/BufferingStreamSocket/
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/socket/tls_socket.cc:54:
>>> scoped_ptr<BufferingStreamSocket> buffer_sock(
>>> nit: buffer_socket? No real value in abbreviating here
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> File extensions/browser/api/sockets_tcp/sockets_tcp_api.cc (right):
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/sockets_tcp/sockets_tcp_api.cc:5: #include
>>> <hash_set>
>>> Thanks for adding this :)  But it should be
>>> "base/containers/hash_tables.h" (and down below with chromium headers)
>>>
>>>
>>>
https://codereview.chromium.org/494573002/diff/60001/extensions/browser/api/s...
>>> extensions/browser/api/sockets_tcp/sockets_tcp_api.cc:198:
>>> client_sock->Pause();
>>> How about just making Pause take a callback? Or if that's too annoying
>>> (i.e. too many existing callsites to update), how about introducing a
>>> PauseAsync call which takes a callback?
>>>
>>> https://codereview.chromium.org/494573002/
>>>
>>
>>
>

-- 
You received this message because you are subscribed to the Google Groups
"Chromium-reviews" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to chromium-reviews+unsubscribe@chromium.org.

Powered by Google App Engine
This is Rietveld 408576698