-
(https://peter-ftp.co.uk/screenshots/20220728584742312.jpg)
/** A netconn descriptor */
struct netconn {
/** type of the netconn (TCP, UDP or RAW) */
enum netconn_type type;
/** current state of the netconn */
enum netconn_state state;
/** the lwIP internal protocol control block */
union {
struct ip_pcb *ip;
struct tcp_pcb *tcp;
struct udp_pcb *udp;
struct raw_pcb *raw;
} pcb;
I am trying to get hold of remote_ip.
Lots of examples online but none of them compile.
There is a union of four structs called ip tcp udp raw.
I've been trying e.g.
uint32_t ipr;
ipr = conn->pcb->ip->remote_ip;
but that one produces
error: invalid type argument of '->' (have 'union <anonymous>')
The actual remote_ip is ultimately defined (via about 5 more convolutions) as a uint32_t, and it contains the right value.
I avoid this convoluted stuff in my own code :)
-
ipr = conn->pcb->ip->remote_ip;
Assuming conn is of type struct netconn*, the pointed object contains an actual pcb union, not a pointer to a pcb union.
Union members are accessed using the . operator (as are struct members).
So:
ipr = conn->pcb.ip->remote_ip;
should be what you are after.
In the debug screen capture, you can notice that there is not arrow close to pcb, as opposed to e.g. conn or ip.
Ref (C11): 6.5.2.3 Structure and union members, ยง1.
BTW: nothing to do with GCC in particular, just plain C.
-
Unfortunately I had already tried that one.
error: incompatible types when assigning to type 'uint32_t' {aka 'long unsigned int'} from type 'ip_addr_t' {aka 'struct ip4_addr'}
/** This is the common part of all PCB types. It needs to be at the
beginning of a PCB type definition. It is located here so that
changes to this common part are made in one location instead of
having to change all PCB structs. */
#define IP_PCB \
/* ip addresses in network byte order */ \
ip_addr_t local_ip; \
ip_addr_t remote_ip; \
/* Socket options */ \
u8_t so_options; \
/* Type Of Service */ \
u8_t tos; \
/* Time To Live */ \
u8_t ttl \
/* link layer address resolution hint */ \
IP_PCB_ADDRHINT
struct ip_pcb {
/* Common members of all PCB types */
IP_PCB;
};
/** This is the aligned version of ip4_addr_t,
used as local variable, on the stack, etc. */
struct ip4_addr {
u32_t addr;
};
-
Unfortunately I had already tried that one.
error: incompatible types when assigning to type 'uint32_t' {aka 'long unsigned int'} from type 'ip_addr_t' {aka 'struct ip4_addr'}
Ah, of course, I forgot to go on in the data structure, I only noticed the problem with . and ->.
ipr = conn->pcb.ip->remote_ip.addr;
-
Then you have to access the members of ip_addr_t to get the bytes / integer. Since you didn't show that definition we can't tell you how to do that.
-
Then you have to access the members of ip_addr_t to get the bytes / integer. Since you didn't show that definition we can't tell you how to do that.
It's there, a bit hidden, in the picture...not so easy to spot from a phone. :-[
-
You are a genius, newbrain!
You can work for me anytime :) :) :)
Fate worse than death... I hear you say.
At my age, my brain can deal with just one level of indirection
ld l, (ix+0)
ld h, (ix+1)
I missed that too; I thought ipaddr_t was a uint32_t, which for ipv4 (which is all I am supporting) is just fine. Each byte is one of the four IP numbers.
-
I missed that too; I thought ipaddr_t was a uint32_t, which for ipv4 (which is all I am supporting) is just fine. Each byte is one of the four IP numbers.
It's probably just a union between a uint32_t addr and and something like uint8_t octects[4], so that one can access them separately (type punning guaranteed by the standard not to be UB, but caution with endianness).
Fate worse than death... I hear you say.
Let's just say it would be...interesting.
-
I missed that too; I thought ipaddr_t was a uint32_t, which for ipv4 (which is all I am supporting) is just fine. Each byte is one of the four IP numbers.
It's probably just a union between a uint32_t addr and and something like uint8_t octects[4], so that one can access them separately (type punning guaranteed by the standard not to be UB, but caution with endianness).
Another reason to use a struct is that an IPv6 address can't fit in a single scalar type. By making it a struct you can use assignment syntax to copy an address without an explicit call to memcpy. If you are going to use a struct ipv6_addr_t you probably want to use a struct ipv4_addr_t for symmetry and so you can use macros to access them in the same way. Most of the type you treat an ip address as a black box and don't access it's numerical value which is often stored in network byte order instead of host byte order, so the extra level of indirection to get to the integer representation doesn't usually matter.
-
Yes indeed; IPV6 is a compilation option of LWIP. In this project it is disabled because it is more work in other areas, and is generally (!) rarely used.