-
Notifications
You must be signed in to change notification settings - Fork 30.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
buffer: add buf.mask for ws #1202
Conversation
Environment* env = Environment::GetCurrent(args); | ||
|
||
uint32_t mask32 = args[0]->Uint32Value(); | ||
char* mask = (char*)&mask32; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use reinterpret_cast, don't use C-style casts.
I'm not sure if you're aware of this but this would have been pointer aliasing with any other pointer type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aliasing with char
is okay right? @bnoordhuis
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, a pointer to char may alias a pointer to another type (but not the other way around.)
Not a code review but +1 to these additions. :D |
uint32_t mask32 = args[0]->Uint32Value(); | ||
char* mask = (char*)&mask32; | ||
|
||
Local<Object> target = args[1]->ToObject(env->isolate()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before doing this should do CHECK(args[1]->IsObject());
and here do args[1].As<Object>()
. Unless you don't expect args[1]
to always be an object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do. Should I add a similar check to buffer.copy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Go ahead and add it to this PR, but leave it in a separate commit. Thanks :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add this to Copy
in a separate PR – it causes test failures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strange. well, don't worry about it then. don't want that change holding this up.
It might be worthwhile to get @3rd-Eden's opinion on these changes, too. |
@chrisdickinson see #1010 (comment) :) |
@Fishrock123 Ah, I meant that we should get @3rd-Eden's opinion on the specific differences from our mask vs. bufferutil's mask. @bnoordhuis Your comments should be addressed now, PTAL (and thanks for the review.) Do you think it would be worthwhile to add the following optimization for aligned addresses? #if INTPTR_MAX == INT64_MAX
if (!(target_data & 0x7) && !(obj_data & 0x7))
AlignedMaskCopy64(obj_data, target_data, mask)
else
#endif
if (!(target_data & 0x3) && !(obj_data & 0x3))
AlignedMaskCopy32(obj_data, target_data, mask)
else {
// current approach
} |
I'm a bit torn here... on the one hand it would be convenient to have core support for the native optimizations that both On the other hand, I think this particular mask function is so purpose-built that it would probably be used almost exclusively by the authors of WebSocket implementations. And on that basis, I don't think it really belongs in core. Also, see my comment on iojs/io.js#1010 – I think the real issue is the difficulty of building native modules on Windows, and the user experience when those modules fail to build. I'd rather put a little bit of effort into improving the UX for Windows users without the ability to build the native optimizations, as they're not really necessary to use WebSockets anyway. |
Environment* env = Environment::GetCurrent(args); | ||
|
||
CopyDWord mask; | ||
mask.as_dword = args[0]->Uint32Value(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't hurt but you don't have to store the mask in a union, just a uint32_t is alright.
I've been reading through #1010 and I agree with @theturtle32 that this buffer method seems kind of specific. |
From IRC, for posterity:
@theturtle32: I don't think that improving this part of the Windows experience will hinder other efforts to make the native module system better. There are still plenty of other native modules that will continue to cause pain for Windows users (node-sass springs immediately to mind). Also, keep in mind that my effort here is not diverting attention from addressing the Windows build UX problem – I am sure that the folks at npm, inc. are working on that issue separately. |
@bnoordhuis @chrisdickinson – re: the IRC snippet above, I have a differing opinion from @3rd-Eden about whether this should be in core. I don't think it should, because I feel that it's too niche, so I'm not asking for it. But if it is shipped in core, of course I'll update websocket to use it once it exists. On the other hand, I'd have to keep the existing native extensions to handle older versions of node/iojs anyway, which would still lead to a subpar experience for Windows users during |
@theturtle32 The snippet above confidently misses the remarks I made in the channel. Copied IRC messages always lack and are often pulled out of context.
|
Also, even if this change is merged in, it doesn't really solve anything as we will continue to ship our binary add-on as optionalDependency to support older versions of node and iojs. |
@3rd-Eden - based on that clarification, I'm pretty sure that you and I are actually on the same page. |
@3rd-Eden The snippet was pasted before you made those comments, sorry. I continued on in IRC to explain that this is the first of the bufferutil/validate-utf8 functions I was PR'ing in (not the last), and asked if that changes your opinion of including these changes, but got no response. In any case, this doesn't seem to be worthwhile. Closing. |
@chrisdickinson apologies for the cross-post, but I just mentioned in #1010: While I'm not crazy about adding WebSocket-specific masking to core, I would be in favor of adding something like this for UTF-8 validation: buffer.toString('utf8', 0, buffer.length, { strict: true }); // Throws on invalid UTF-8 |
This patch adds
buf.mask(maskValue, targetBuffer, targetOffset, sourceStart, sourceEnd)
, needed by the ws package for masking and unmasking websocket frames. The original implementation is here. It is implemented as a partially unrolled loop, operating on 32-bit values and dealing with the 0-3 byte remainder at the end – I'm not sure if we want to retain this optimization, since thesourceStart
andtargetOffset
params make it possible to trigger non-8-byte-aligned copies.I didn't implement
Unmask
: it should be equivalent tobuf.mask(mask, buf)
.Merge
is also omitted. I'll have another PR up forUtf8Validate
tomorrow.R=@trevnorris, @piscisaureus