-
Notifications
You must be signed in to change notification settings - Fork 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
sock: Introduction of new application layer API #5758
Conversation
This introduces a new alternative and better API to `conn`. It differs in the following aspects: * a common address type for both IPv4 and IPv6 addresses is introduced * communication end-points are abstracted as end-point types `sock_x_ep_t`, containing the address, its family, its port (if required for protocol) and the interface identifier. * All functions require some kind of state. Sending of datagrams to the same source or replying to incoming datagrams is thus simplified * TCP connection establishment was overall reworked: connected sockets and listening sockets are now two distinct types. An accept on a listening socket than yields a connected socket
*/ | ||
typedef struct { | ||
sock_addr_ip_t addr; /**< IP address */ | ||
int family; /**< family of sock_tcp_ep_t::addr */ |
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.
Any reason why this is an int? (maybe we can carve off two bytes here)
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.
At least on 32-bit platforms those would return anyways due to alignment. But I'm thinking of moving it to the top, that so that endpoints can be identified to a degree even after casting, if addr
isn't an IP address, but e.g. a name for an ICN-based sock
. And then int
is the only type that would make sense, due to the alignment of the following array.
To be nitpicky: the correct title of this PR should be: "sock: Introduction of a new transport layer API" since the API is usually described by the services that can be accessed through it, not by the services that are calling it. |
Some things:
|
|
What do you mean by |
The API as is documents error return values like -ENOTCON, -EINVAL, Imagine a hypothetical implementation like
The network stack might return STACK_CONNECTION_NOT_SETUP defined to an I fear that implementations will have, at the end of every function of |
@miri64 What do you think? |
Then I can be nitpicky, too: raw IP isn't transport layer 😜 How about "network application API"?
That's news to me... which PR are you referring to? #5511 is only important for 100% waterproof implementation of this API, but it certainly can also use stack-specific netif identifiers for now (which I did for GNRC for now, because otherwise the number of interdependent PRs will grow very large again ;-)). @kaspar030 (sorry had to go to a meeting so I couldn't finish my replies):
In the scope of If globally: I guess that will make a lot of people mad, that came to love the
True, but worst-case this can be dealt with in a switch-case which shouldn't take as much memory. For our user-friendliness goal it is certainly more helpful to have a well-defined error behavior (because it simplifies debugging and testability "oh well I had an error, but I don't know what I did wrong exactly").
While I'm not a friend of wild include pathes, I tend to agree. Especially since this will definitely prevent some double inclusions that might happen due to faulty USEMODULE composition.
Is this type available for all platforms. I remember some issues last time I tried to use it (way back when I implemented the first POSIX socket wrapper for DEStiny). |
Addressed comments that were straight forward ;-) |
Hm, if we remove the redundancy of the endpoint structs, it's not so
I think it is. (quick grep shows avr and msp430 support, the rest has it |
Do you mean something like the following?
typedef struct {
int family;
union {
#ifdef SOCK_HAS_IPV6
uint8_t ipv6[16];
#endif
uint32_t ipv4;
} addr;
} sock_addr_ip_t;
typedef struct {
sock_addr_ip_t addr;
/* ... */
} sock_x_ep_t Otherwise I don't know what you mean by "remov[ing] the redundancy of the endpoint structs".
And then those sock-specific errors need to be translated for the POSIX wrapper again :-/. I'm really not a fan of API-specific error values. They tend to produce exactly the problem you are describing: need for translating the errors in APIs that use the other API. True, if a stack also has its own error values we have the problem, too, but I see it way less problematic translating them one time here, than translating it for every abstraction layer.
I dislike both equally :P But in this particular case I guess path meddling can help with the readability and maintainability of the API definition ;-).
Okay great, then I will use it :-). |
No, I mean, if the API saiy "SOCK_ENOSPC", than the sock implementation |
Mhhh, then |
Hmm then i think about it: Why not use -ENOTCONN as well. I mean the existing handle is not connected anymore to the original connection ... |
Would also work, yes. Do you really need that for |
What I mean is: for disconnect I imagine it is easier to just fail gracefully (i.e. in case of an error: do nothing). |
I think this doesn't pose a problem. A ptr to "sock_tcp_t" is the only handle an application gets. There's no (simple enough) way to find out if the underlying connection completely disconnected and is now used for another connection. I rather propose to always require an explicit "close()" issued by the application, even if the connection is already disconnected. Only after the explicit "close()" the stack can re-use that connection object for a new connection. |
Include missing header
Add more error classes
I found some more error classes myself while porting lwIP. |
@kaspar - That a good Idea, then only read() and write() need a -ENOTCONN. However the documentation should mention that a passive connection can only be reopend by issueing a disconnect()-call. |
They already have :-).
I'm always confused by what you mean with "passive connection". In terms of socket-speak that a listening connection? Where should I put that documentation. |
In socket-speak: Hmm maybe you could a note at the disconnect()-call that says: |
That wording is a little bit confusing IMHO. How about "A |
Let's try to keep both the RFC nomenclature (active, passive) and the notion that queue members are "connected, disconnected or listening" out of the docs. The former is confusing (I assume as only actual implementors seem to know the meaning. The latter is IMHO mixing up things, as it is weird to have a memory area "listening", and it also seems implementation dependent. -----Original Message----- In socket-speak: Hmm maybe you could a note at the disconnect()-call that says: You are receiving this because you were mentioned. |
yes, or maybe clarify that it will not be reused (by accept) for new connections until closed. -----Original Message-----
That wording is a little bit confusing IMHO. How about "A You are receiving this because you were mentioned. |
How about? A |
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'm not happy with the documentation, but let's merge this and (maybe) improve later.
/** | ||
* @defgroup net_sock Sock API | ||
* @ingroup net | ||
* @brief Provides a minimal common API for applications to connect to the |
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 don't like that tagline.
The API is supposed to be used to write network applications. Would you mind to rephrase?
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 there is so much doc change needed, why did you merge?!?
* ~~~~~~~~~~~~~~~~~~~~ | ||
* | ||
* This module provides a minimal set of functions to establish connections or | ||
* send and receives datagrams using different types of communication. Together, |
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.
- why minimal set? (pls drop if you can't explain)
- receives -> receive
"differnet types of communication"? please rephrase
* | ||
* This module provides a minimal set of functions to establish connections or | ||
* send and receives datagrams using different types of communication. Together, | ||
* they serve as a common API that connects application- and network stack code. |
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.
- why common?
- again, I find it misleading to describe this API as "connecting application with network stack code".
* * @ref sock_tcp_t (net/sock/tcp.h): TCP sock | ||
* * @ref sock_udp_t (net/sock/udp.h): UDP sock | ||
* | ||
* Each network stack must implement at least one sock 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.
I think you can drop this.
* | ||
* Each network stack must implement at least one sock type. | ||
* | ||
* Note that there might be no relation between the different sock types. |
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 does that mean?
* @param[in] data Pointer where the received data should be stored. | ||
* May be `NULL` if `len == 0`. | ||
* @param[in] len Maximum space available at @p data. | ||
* @param[in] proto Protocol to use in the packet send, in case |
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.
send -> sent or "to be sent"
* @param[in] proto Protocol to use in the packet send, in case | ||
* `sock == NULL`. If `sock != NULL` this parameter will be | ||
* ignored. | ||
* @param[in] remote Remote end point for the send data. |
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.
"to be sent" as above
* sock_ip_ep_t::family may be AF_UNSPEC, if local | ||
* end point of @p sock provides this information. | ||
* | ||
* @note Function blocks until packet is handed to the stack. |
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.
?
* | ||
* @note Function blocks until packet is handed to the stack. | ||
* | ||
* @return The number of bytes send on success. |
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.
send -> sent
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 anyone is going to fix this: there are various more occurrences of this typo all over the place.
typedef struct _sock_tl_ep sock_tcp_ep_t; /**< An end point for a TCP sock object */ | ||
|
||
/** | ||
* @brief Implementation-specific type of a TCP sock 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.
pls drop implementation specific
@kaspar030 accidently hit the merge button? 🍻 |
No, I realized that the API has been thoroughly discussed and my only complaints are either doxygen typos or require a longer (out-of-scope discussion) of the documentation style as a whole. |
I am refering to the commit list. 18 commits marked as fixup (: |
Why does this happen to me? :) What do we do? |
simple solution. just bring some beer for the next hack'n'ack (: |
Will do. Sorry @everyone for messing up our beautiful commit history. |
This introduces a new alternative and better API to
conn
. It differs in thefollowing aspects:
sock_x_ep_t
,containing the address, its family, its port (if required for protocol) and
the interface identifier.
source or replying to incoming datagrams is thus simplified
listening sockets are now two distinct types. An accept on a listening socket
than yields a connected socket