Skip to content
This repository has been archived by the owner on Jul 31, 2018. It is now read-only.

uv_link_t: initial #32

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 000-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

* [Public C++ Streams](001-public-stream-base.md)
* [ES6 Module Interoperability](002-es6-modules.md)
* [Port core to uv_link_t](xxx-uv_link_t.md)
72 changes: 72 additions & 0 deletions xxx-uv_link_t.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
| Title | Port core to uv_link_t |
|--------|-----------------------------|
| Author | @indutny |
| Status | DRAFT |
| Date | 2016-06-03 |

## 1. Proposal

I propose to replace `StreamBase` with [`uv_link_t`][0], and port existing
classes that inherit from `StreamBase`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had a conflict in StreamBase that lead to the method GetAsyncWrap() and GetObject(). Will this play nicely with AsyncWrap, and allow the class to propagate like it does with JSStream?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conflict was due to the use of vtable and virtual methods in StreamBase. uv_link_t is a C project, there won't be any such conflict.

In fact, I believe that exposing an External getter for the pointer to internal uv_link_t is enough to get things running. This getter can be a per-class, or could be shared, but the inheritance won't be a roadblock for this.


## 2. Current state of C++ Streams in Node

The fast HTTP and TLS protocol implementation in Node core depends on so called
`StreamBase` C++ class. This class is an analog of JavaScript streams in C++.
The main ideas behind `StreamBase` are to:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean you'll be removing associated classes like StreamReq and StreamResource?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be noted in the text

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack.


1. Avoid unnecessary memory allocations by reading data directly into buffer
from which it will be synchronously parsed
2. Avoid calling JavaScript unless absolutely necessary

However, this API has lots of dependencies on the core internals, and thus
can't be used outside of it.

## 3. uv_link_t

From [`uv_link_t`][0] readme:

Chainable libuv streams.

It is quite easy to write a TCP server/client in [libuv][1]. Writing HTTP
server/client is a bit harder. Writing HTTP server/client on top of TLS
server could be unwieldy.

`uv_link_t` aims to solve complexity problem that quickly escalates once
using multiple layers of protocols in [libuv][1] by providing a way to
implement protocols separately and chain them together in easy and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"in an easy and..."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack.

high-performant way using very narrow interfaces.

Given that [`uv_link_t`][0] depends only on [libuv][1], it is very easy to
envision how it will be used in Node.js addons. Even core modules could
be reimplemented on a user level without a need to patch the core itself.

Additionally, with the `uv_link_observer_t` (which is a part of [`uv_link_t`][0]
distribution), all of the reads that right now happen internally within the
`StreamBase` will be **observable**. This means that JavaScript user code will
still be able to listen for `data` events on the `net.Socket` that was consumed
by some `uv_link_t` stream.

## 4. Proof-of-Concept

Several modules were created as a Proof-of-Concept [`uv_link_t`][0]
implementations (which possibly could be modified to fit into core):

* [`uv_ssl_t`][2]
* [`uv_http_t`][3]

They can be combined together quite trivially as demonstrated in
[file-shooter][4].

## 5. Further Thoughts

Another abstraction level could be added for multiplexing [`uv_link_t`][0]s to
provide a common C interface for http2 and http1.1. This will help us bring
a http2 implementation into the core while reusing as much as possible of the
existing code.

[0]: https://github.com/indutny/uv_link_t
[1]: https://github.com/libuv/libuv
[2]: https://github.com/indutny/uv_ssl_t
[3]: https://github.com/indutny/uv_http_t
[4]: https://github.com/indutny/file-shooter