Can you connect a MQTT client directly from a PPPoS status callback?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Can you connect a MQTT client directly from a PPPoS status callback?

Freddie Chopin-2
Hi!

I'm working on an open-source demo project in which there is a MQTT
client talking via PPPoS to a GSM modem. The project also has a RTOS,
so I have threads and synchronization objects.

I'm wondering whether I could connect a MQTT client to a broker
directly from a PPPoS status callback? The scenario I have in mind is
that when PPPoS connection is established then I would like to
immediately connect to the MQTT broker. Is that a viable idea, or
should I avoid calling such high-level functions as
mqtt_client_connect() from such low-level places as status callbacks of
netifs? The problem I'm seeing is that mqtt_client_connect() requires
you to hold a TCP/IP core lock, which is already held when the PPPoS
callback is executed. I can make this lock recursive, not a problem (at
least for me, but I doubt lwIP would care about such a change), but
then I'm wondering whether there's a chance for a deadlock or data
corruption in such a scenario...

Thanks in advance for any input!

Regards,
FCh


_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: Can you connect a MQTT client directly from a PPPoS status callback?

Devanand Biradar
I have connected to mosquito cloud using Lwip via MQTT.
Using PPPOS with GSM module.



On Thu, 16 May 2019, 19:55 Freddie Chopin, <[hidden email]> wrote:
Hi!

I'm working on an open-source demo project in which there is a MQTT
client talking via PPPoS to a GSM modem. The project also has a RTOS,
so I have threads and synchronization objects.

I'm wondering whether I could connect a MQTT client to a broker
directly from a PPPoS status callback? The scenario I have in mind is
that when PPPoS connection is established then I would like to
immediately connect to the MQTT broker. Is that a viable idea, or
should I avoid calling such high-level functions as
mqtt_client_connect() from such low-level places as status callbacks of
netifs? The problem I'm seeing is that mqtt_client_connect() requires
you to hold a TCP/IP core lock, which is already held when the PPPoS
callback is executed. I can make this lock recursive, not a problem (at
least for me, but I doubt lwIP would care about such a change), but
then I'm wondering whether there's a chance for a deadlock or data
corruption in such a scenario...

Thanks in advance for any input!

Regards,
FCh


_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: Can you connect a MQTT client directly from a PPPoS status callback?

Freddie Chopin-2
Hello Devanand!

On Thu, 2019-05-16 at 20:41 +0530, Devanand Biradar wrote:
> I have connected to mosquito cloud using Lwip via MQTT.
> Using PPPOS with GSM module.

Yes, I know this can be done, because I already have done it and it
works (; But now I would like to make it more error-proof and
responsive - my code so far is just a dirty proof-of-concept using
stupid things like global flags and polling.

So what I'm asking is this - is it safe to have code like this:

// this function is registered via pppapi_pppos_create(...)
// it is executed from within lwIP's TCP/IP thread
void pppLinkStatus(ppp_pcb* pcb, int errorCode, void* context)
{
  if (errorCode == PPPERR_NONE) // PPP is connected successfully?
    mqtt_client_connect(...);
  else // PPP connection is lost
    mqtt_client_disconnect(...);
}

The alternative is - for example - to call mqtt_client_connect(...)
until it succeeds (including the last phase done in the MQTT's connect
callback) periodically, for example every 10 seconds. However - if
possible - I would prefer the first version, more "event based" and not
requiring a thread that would have to monitor that.

Regards,
FCh


_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: Can you connect a MQTT client directly from a PPPoS status callback?

goldsimon@gmx.de
Am 16.05.2019 um 18:31 schrieb Freddie Chopin:

> Hello Devanand!
>
> On Thu, 2019-05-16 at 20:41 +0530, Devanand Biradar wrote:
>> I have connected to mosquito cloud using Lwip via MQTT.
>> Using PPPOS with GSM module.
>
> Yes, I know this can be done, because I already have done it and it
> works (; But now I would like to make it more error-proof and
> responsive - my code so far is just a dirty proof-of-concept using
> stupid things like global flags and polling.
>
> So what I'm asking is this - is it safe to have code like this:

It's probably not safe as you risk calling back into modules that are
not reentrant. I don't know this for sure, just as a saftey measurement...

Maybe you could use tcpip_trycallback() from that callback?

Regards,
Simon

>
> // this function is registered via pppapi_pppos_create(...)
> // it is executed from within lwIP's TCP/IP thread
> void pppLinkStatus(ppp_pcb* pcb, int errorCode, void* context)
> {
>    if (errorCode == PPPERR_NONE) // PPP is connected successfully?
>      mqtt_client_connect(...);
>    else // PPP connection is lost
>      mqtt_client_disconnect(...);
> }
>
> The alternative is - for example - to call mqtt_client_connect(...)
> until it succeeds (including the last phase done in the MQTT's connect
> callback) periodically, for example every 10 seconds. However - if
> possible - I would prefer the first version, more "event based" and not
> requiring a thread that would have to monitor that.
>
> Regards,
> FCh
>
>
> _______________________________________________
> lwip-users mailing list
> [hidden email]
> https://lists.nongnu.org/mailman/listinfo/lwip-users
>


_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: Can you connect a MQTT client directly from a PPPoS status callback?

Freddie Chopin-2
On Thu, 2019-05-16 at 19:51 +0200, [hidden email] wrote:
> It's probably not safe as you risk calling back into modules that are
> not reentrant. I don't know this for sure, just as a saftey
> measurement...

Yes, this is what I was afraid of.

> Maybe you could use tcpip_trycallback() from that callback?

I assume you are talking about tcpip_try_callback() right? Only thing I
could find about tcpip_trycallback() is this:

tcpip_trycallback() was renamed to tcpip_callbackmsg_trycallback() to avoid confusion
    with tcpip_try_callback()

It seems that the name was (and still is) very confusing (;

Anyway tcpip_try_callback() does indeed look as what I could use for my
purpose, so thanks for info! I'll try that tomorrow, however I'm not
sure how will I be able to deal with an error when posting the callback
(or allocating the message) will not be possible. The other function -
tcpip_callbackmsg_trycallback() -  also looks like I could use it, one
possible failure point less.

Regards,
FCh


_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: Can you connect a MQTT client directly from a PPPoS status callback?

goldsimon@gmx.de
Am 16.05.2019 um 20:56 schrieb Freddie Chopin:
> On Thu, 2019-05-16 at 19:51 +0200, [hidden email] wrote:
>> It's probably not safe as you risk calling back into modules that are
>> not reentrant. I don't know this for sure, just as a saftey
>> measurement...
>
> Yes, this is what I was afraid of.

And it shows you're actually asking the correct question :-)

>
>> Maybe you could use tcpip_trycallback() from that callback?
>
> I assume you are talking about tcpip_try_callback() right?

Yeah, sorry.

> Only thing I could find about tcpip_trycallback() is this:
>
> tcpip_trycallback() was renamed to tcpip_callbackmsg_trycallback() to avoid confusion
>      with tcpip_try_callback()
>
> It seems that the name was (and still is) very confusing (;

Hrmpf :(

>
> Anyway tcpip_try_callback() does indeed look as what I could use for my
> purpose, so thanks for info! I'll try that tomorrow, however I'm not
> sure how will I be able to deal with an error when posting the callback
> (or allocating the message) will not be possible.

Yeah, well, but what would you do inside that callback when
mqtt_connect() (or whatever) would return such an out-of-resources
error? In such an embedded system, you just have to implement guards to
either set the red lamp or keep retrying... Probably in a
state-machine-like cyclic task... but that's far beyond what lwIP provides.

Regards,
Simon

> The other function -
> tcpip_callbackmsg_trycallback() -  also looks like I could use it, one
> possible failure point less.
>
> Regards,
> FCh
>
>
> _______________________________________________
> lwip-users mailing list
> [hidden email]
> https://lists.nongnu.org/mailman/listinfo/lwip-users
>


_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: Can you connect a MQTT client directly from a PPPoS status callback?

Sylvain Rochet
In reply to this post by goldsimon@gmx.de
Hi,

On Thu, May 16, 2019 at 07:51:45PM +0200, [hidden email] wrote:

> Am 16.05.2019 um 18:31 schrieb Freddie Chopin:
> >Hello Devanand!
> >
> >On Thu, 2019-05-16 at 20:41 +0530, Devanand Biradar wrote:
> >>I have connected to mosquito cloud using Lwip via MQTT.
> >>Using PPPOS with GSM module.
> >
> >Yes, I know this can be done, because I already have done it and it
> >works (; But now I would like to make it more error-proof and
> >responsive - my code so far is just a dirty proof-of-concept using
> >stupid things like global flags and polling.
> >
> >So what I'm asking is this - is it safe to have code like this:
>
> It's probably not safe as you risk calling back into modules that are
> not reentrant. I don't know this for sure, just as a saftey measurement...
Hummm, I guess it's safe, I doubt PPP status callback can actually be
called from a module.

Looking at the code it can only be called:
  - Right from ppp_close(), only if the session is already dead;
  - If the lower level link failed to setup, i.e. timeout. in
    ppp_link_failed();
  - If the link is shutting down, i.e. timeout or LCP "Term" packet
    received in ppp_link_end();
  - If the link is UP, after a packet is received, in sifup() and
    sif6up().

Unless you are calling ppp_close() from a module, which I highly doubt,
it is safe because other triggers are only rx packet or timeouts.

Sylvain

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users

signature.asc (188 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Can you connect a MQTT client directly from a PPPoS status callback?

Freddie Chopin-2
On Thu, 2019-05-16 at 21:28 +0200, Sylvain Rochet wrote:
> Unless you are calling ppp_close() from a module, which I highly
> doubt,
> it is safe because other triggers are only rx packet or timeouts.

Forgive my ignorance, but what is a "module" in the lwIP world? (;

Generally closing/disconnection are not that much important - when the
PPPoS dies I guess MQTT will die by itself anyway, that's why my main
concern is mqtt_client_connect().

Let's say I would try to do it directly from the callback - it there
anything I could check to tell with confidence that this was wrong or
ok?

Regards,
FCh


_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: Can you connect a MQTT client directly from a PPPoS status callback?

Sylvain Rochet
Hi Freddie,

On Thu, May 16, 2019 at 10:09:49PM +0200, Freddie Chopin wrote:
> On Thu, 2019-05-16 at 21:28 +0200, Sylvain Rochet wrote:
> > Unless you are calling ppp_close() from a module, which I highly
> > doubt,
> > it is safe because other triggers are only rx packet or timeouts.
>
> Forgive my ignorance, but what is a "module" in the lwIP world? (;

I just used module because this is what was previously used. But this is
basically any function that can't be re-entered.


> Generally closing/disconnection are not that much important - when the
> PPPoS dies I guess MQTT will die by itself anyway, that's why my main
> concern is mqtt_client_connect().
>
> Let's say I would try to do it directly from the callback - it there
> anything I could check to tell with confidence that this was wrong or
> ok?

As usual with locks, re-entrancy, shared variables, shared memory, or
such. Some tools (e.g. coverity, coccinelle) can help checking that it
looks right but until now it is left to poor humans to check that it is
actually right.

For PPP callback, apart from ppp_close, it is safe because it can only
be called on the RX packet path or from timeouts, where having anything
else in the call stack than rx packet handler and timeout handler from
main() or tcpip thread is highly impossible.

So you either have to trust me, or to check yourself all possible call
stack leading to PPP callback being called. Luckily there are only a few
places where the callback is actually called and diving into all the
possible call stack is not a combinatorial explosion.

Basically, all possible call stack are:

ppp_close()
pcb->link_status_cb()

~timeout-handler~
pppoe_timeout()
pppoe_abort_connect()
ppp_link_failed()
pcb->link_status_cb()

~rx-packet-handler~
~udp-recv-callback~
pppol2tp_input();
pppol2tp_dispatch_control_packet()
pppol2tp_abort_connect()
ppp_link_failed()
pcb->link_status_cb()

~timeout-handler~
pppol2tp_timeout()
pppol2tp_abort_connect()
ppp_link_failed()
pcb->link_status_cb()

ppp_close()
ppp_link_terminated()
pcb->link_cb->disconnect() -> pppos_disconnect() or pppoe_disconnect() or pppol2tp_disconnect()
ppp_link_end()
pcb->link_status_cb()

ppp_close()
lcp_lowerdown()
fsm_lowerdown()
f->callbacks->down() -> lcp_down()
link_down()
upper_layers_down()
protp->close -> lcp_close()
lcp_finished()
link_terminated()
ppp_link_terminated()
pcb->link_cb->disconnect() -> pppos_disconnect() or pppoe_disconnect() or pppol2tp_disconnect()
ppp_link_end()
pcb->link_status_cb()

~rx-packet-handler~
ppp_input()
lcp_input()
fsm_input()
fsm_rtermack()
f->callbacks->finished() -> lcp_finished()
link_terminated()
ppp_link_terminated()
pcb->link_cb->disconnect() -> pppos_disconnect() or pppoe_disconnect() or pppol2tp_disconnect()
ppp_link_end()
pcb->link_status_cb()

~rx-packet-handler~
ppp_input()
lcp_input()
fsm_input()
fsm_rtermreq() or fsm_rtermack()
f->callbacks->down() -> lcp_down()
link_down()
upper_layers_down()
protp->close -> lcp_close()
lcp_finished()
link_terminated()
ppp_link_terminated()
pcb->link_cb->disconnect() -> pppos_disconnect() or pppoe_disconnect() or pppol2tp_disconnect()
ppp_link_end()
pcb->link_status_cb()

~timeout-handler~
LcpEchoTimeout()
LcpEchoCheck()
LcpSendEchoRequest()
LcpLinkFailure()
lcp_close()
lcp_finished()
link_terminated()
ppp_link_terminated()
pcb->link_cb->disconnect() -> pppos_disconnect() or pppoe_disconnect() or pppol2tp_disconnect()
ppp_link_end()
pcb->link_status_cb()

~rx-packet-handler~
ppp_input()
protp->input() -> ipcp_input()
fsm_input()
fsm_rconfreq() or fsm_rconfack()
f->callbacks->up() -> ipcp_up()
sifup()
pcb->link_status_cb()

~rx-packet-handler~
ppp_input()
protp->input() -> ipv6cp_input()
fsm_input()
fsm_rconfreq() or fsm_rconfack()
f->callbacks->up() -> ipv6cp_up()
sif6up()
pcb->link_status_cb()


Sylvain

_______________________________________________
lwip-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-users

signature.asc (188 bytes) Download Attachment