sock: Introduction of new application layer API#5758
sock: Introduction of new application layer API#5758kaspar030 merged 19 commits intoRIOT-OS:masterfrom
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
sys/include/net/sock/tcp.h
Outdated
| */ | ||
| 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.
Any reason why this is an int? (maybe we can carve off two bytes here)
There was a problem hiding this comment.
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_tOtherwise 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 |
kaspar030
left a comment
There was a problem hiding this comment.
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.
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.
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.
- 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.
- 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.
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. |
| * @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.
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. |
| * 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. |
| * | ||
| * @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.
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.
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