Richie Bonventre wrote:
[..] In addition, the state the struct returns
to is identical to the state of a brand new tcp_pcb, "CLOSED".
This caused me to believe that I could tcp_connect() again on
the same tcp_pcb. As you've said, this is not actually ok.
After tcp_close returns, lwip no longer knows about your
tcp_pcb struct, and although the memory isn't cleared, lwip
has designated that memory space as free so the next time you
create a connection with tcp_new() it may place it there and
overwrite your old tcp_pcb.
Clearing the memory would not help: it might already be re-allocated
and thus have a valid state. Plus "CLOSED" is 0, I think...
Anyway, it is documented that a pcb may not be referenced after
tcp_close() returned ERR_OK (even if the pcb might not be
deallocated at that point, it will eventually be).
So my four situations:
1) I ctrl-C the listener on the other machine.
This will send some sort of packet to your lwip machine
telling you the connection is closing. Lwip will move tcp_pcb
into the CLOSE_WAIT state, and will call the recv_callback
with a NULL argument. In the recv_callback you should then
check that this packet is coming from your currently opened
connection. If it isn't, it must be from an old connection
that you already attempted to close, so you can ignore it.
If you do get a NULL-recv-callback for an older connection, it means
you haven't closed it correctly (remember to set the recv callback
to NULL before calling tcp_close - that way you won't get informed
when the remote FIN arrives, if you don't need that). However, it
doesn't hurt to always call tcp_close() when you get a
NULL-recv-callback.
If it is, then you must call tcp_close()
yourself. This then completes some more acking with the other
machine and eventually places the tcp_pcb into the CLOSED
state, and then calls the err_callback with ERR_ABRT.
No, this is wrong: the err-callback is only called in an error
condition (e.g. a timeout, RST received or something like that). It
is *not* called in a normal graceful-close-scenario.
At this point, the tcp_pcb is "freed" and
should not be touched again.
Again, do *not* reference the pcb after tcp_close() has returned
ERR_OK, please read the documentation (doc/rawapi.txt)!
A new tcp_pcb should be tcp_new()'d and then
you can tcp_connect() again.
2) I try to connect from lwip but no cable is
plugged in.
Lwip will try and send a SYN packet and wait for
an ack. Until it gets the ack, a counter is being incremented
until it times out. When it times out, it calls the
err_callback with ERR_ABRT. It is not clear to me if the
tcp_pcb is CLOSED at this point, but it looks like the memory
is freed anyway.
From an application point of view, a pcb is always freed *before*
the err-callback is called.
Should I have to call tcp_close() here? Once
the memory is freed in lwip you can again tcp_new() and
tcp_connect().
3) I try to connect from lwip and the cable is
plugged in, but nothing is listening.
The other machine should immediately send Lwip
back a rst packet. Lwip will then call the err_callback with
ERR_RST. I noted though that at this point when the error
callback is called, the old tcp_pcb is not yet closed nor
freed.
How did you notice that? The pcb is freed after the err-callback is
called. There's no need to set the state to CLOSED before freeing
the memory. Please don't try to assume anything from reading the pcb
contents here.
Simon
|