-
-
Notifications
You must be signed in to change notification settings - Fork 415
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
Change NetAddress class to hide its fields behind functions, fixing cross-platform compatibility. #2734
Conversation
… the fields. Platform specific information is handled in these utility functions.
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.
Thanks for working on this!
I've left some small code style comments.
packages/net/net_address.pony
Outdated
@@ -1,3 +1,5 @@ | |||
type MaybeIPAddr is (U32 | Array[U32]) |
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 think the one place where this type alias is used doesn't really warrant adding another name to the namespace. I think this line should be removed, and the line below that uses it should just use (U32 | Array[U32])
directly
packages/net/net_address.pony
Outdated
and (this._addr2 == that._addr2) | ||
and (this._addr3 == that._addr3) | ||
and (this._addr4 == that._addr4) | ||
end |
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.
The end
here should be the same level of indentation as the if
that it terminates. That is, it should be indented one more level to the right.
packages/net/net_address.pony
Outdated
fun scope() : U32 => | ||
_scope | ||
|
||
fun addr() : MaybeIPAddr => |
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 think this method should probably have a docstring to explain exactly what it returns in the (U32 | Array[U32])
. That is, it should explain what those 32-bit integers mean in each case.
packages/net/net_address.pony
Outdated
end | ||
|
||
fun _v6_addr() : Array[U32] => | ||
[_addr1; _addr2; _addr3; _addr4] |
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.
This red icon is GitHub's way of saying that this file is missing an empty line at the end, which is a common convention for file endings. Adding an empty line at the end here will make this nag icon go away.
src/libponyrt/lang/socket.c
Outdated
@@ -90,7 +90,7 @@ typedef struct | |||
struct sockaddr_storage addr; | |||
} ipaddress_t; | |||
|
|||
static socklen_t address_length(ipaddress_t* ipaddr) | |||
PONY_API socklen_t address_length(ipaddress_t* ipaddr) |
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.
If we want to expose this for FFI use in the standard library, it needs to get either a pony_
or ponyint_
prefix to its name, for cleanliness of the function namespace. pony_
means it is a public API meant for use by third party code, whereas ponyint_
means it is internal. Unless there is a good reason to make it public, we should prefer to keep it internal because public functions require us to treat any changes to them as breaking changes in Pony.
So, this function should end up named ponyint_address_length
, or something else with that prefix.
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 left some inline comments. In general very promising first iteration.
packages/net/net_address.pony
Outdated
fun scope() : U32 => | ||
_scope | ||
|
||
fun addr() : (U32 | Array[U32]) => |
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.
what do you think about creating two different methods, on for the IPv4 and one for the IPv6 address?
The user has to check what kind of address this is anyways, with a method able to return each, a second match statement necessary, like so:
let addr: NetAddress = ... // somehow get a NetAddress
if addr.ip4() then
match addr.addr()
| let ip4: U32 => // do something with ip4 address
else
// somehow handle this actually impossible case, otherwise this would always return something or None
end
The as
statement is also an alternative here. But after all, it might be more straightforward to do:
let addr: NetAddress = ... // somehow get a NetAddress
if addr.ip4() then
let ip4: U32 = addr.ip4_addr()
// do something with ip4
end
It would need to be documented that the return value of a fun ip4_addr(): U32
method is actually invalid if ip4()
is not true. This would basically repeat the behavior we currently have with only the fields.
packages/net/net_address.pony
Outdated
fun scope() : U32 => | ||
_scope | ||
|
||
fun addr() : (U32 | Array[U32]) => |
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.
Also each returned integer value (except U8 of course) in any of these methods should be run through a method to convert between network and host byte order. These are ntohl
for U32 and ntohs
for U16.
packages/net/net_address.pony
Outdated
end | ||
|
||
fun family() : U8 => | ||
""" |
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.
please indent the function body with 2 spaces according to the style guide.
packages/net/net_address.pony
Outdated
end | ||
|
||
fun port() : U16 => | ||
_port |
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.
please use @noths[U16](_port)
here, to convert to host byte order.
packages/net/net_address.pony
Outdated
_port | ||
|
||
fun scope() : U32 => | ||
_scope |
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.
please use @nothl[U32](_scope)
here, to convert to host byte order.
packages/net/net_address.pony
Outdated
if ip4() then | ||
_addr | ||
else | ||
[_addr1; _addr2; _addr3; _addr4] |
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.
what do you think about returning a 4-tuple here instead? Just a thought, Array[U32]
is also fine.
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 agree that a 4-tuple is a better idea - the number of elements is a constant known at compile time, so a tuple is a better representation of that. Array[U32]
is more cumbersome because your code has to deal with the possibility of the array being more or fewer than 4 elements, which we know is impossible, but the compiler won't know it.
packages/net/net_address.pony
Outdated
end | ||
|
||
fun port() : U16 => | ||
_port |
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.
you can use parts of the port
field docstring here.
packages/net/net_address.pony
Outdated
fun port() : U16 => | ||
_port | ||
|
||
fun scope() : U32 => |
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.
you can move the scope
field docstring here.
…ad of returning an Array for IPV6 address, made it a 4-tuple to provide more compile time guarantees. Addressed few other review comments.
ifdef linux or windows then | ||
(@ponyint_address_length[U32](this)).u8() | ||
else | ||
ifdef bigendian then |
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.
Everything looks good, i am just not 100% sure about this check. Could we have a testcase that verifies that the methods actually return what they should?
I think the change log should be changed rather than fixed |
This is a breaking change, yes? If yes, before this is merged, can someone please supply release notes that show what code used to look like, what sort of error a user should expect and what they need to do to get their code working? |
I think the changelog entry belongs in both sections, which is why I added both tags and updated the PR name to make sense in both contexts. |
Marking this as "DO NOT MERGE". Can be removed once release notes are added. |
Release notes draft
All functions return the values in host byte order, that means conversion using |
made existing fields private. and exposed utility functions to access…… the fields. Platform specific information is handled in these utility functions.