diff options
author | Denis Kenzior <denkenz@gmail.com> | 2011-02-26 00:14:29 -0600 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2011-02-28 16:13:55 -0600 |
commit | b6bc221bc8c27d8654ce6008d9707f2e458321c8 (patch) | |
tree | 64573e52e73c94cb07a0e94e7e6a4c31e8602f23 /gatchat/gatppp.c | |
parent | 802962adbc29e6e0c2c4f64efc9ba1e5f1e29753 (diff) | |
download | ofono-b6bc221bc8c27d8654ce6008d9707f2e458321c8.tar.bz2 |
gatppp: Send the final terminate ack
In the case where we're going down, but have a pending terminate ack,
delay signaling the upper layers until the ack has been put on the wire.
Diffstat (limited to 'gatchat/gatppp.c')
-rw-r--r-- | gatchat/gatppp.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c index bbd8ab1a..df035b38 100644 --- a/gatchat/gatppp.c +++ b/gatchat/gatppp.c @@ -74,6 +74,7 @@ struct _GAtPPP { GAtPPPDisconnectReason disconnect_reason; GAtDebugFunc debugf; gpointer debug_data; + gboolean sta_pending; }; void ppp_debug(GAtPPP *ppp, const char *str) @@ -84,6 +85,28 @@ void ppp_debug(GAtPPP *ppp, const char *str) ppp->debugf(str, ppp->debug_data); } +static void ppp_dead(GAtPPP *ppp) +{ + DBG(ppp, ""); + + /* notify interested parties */ + if (ppp->disconnect_cb) + ppp->disconnect_cb(ppp->disconnect_reason, + ppp->disconnect_data); +} + +static void sta_sent(gpointer userdata) +{ + GAtPPP *ppp = userdata; + + DBG(ppp, ""); + + ppp->sta_pending = FALSE; + + if (ppp->phase == PPP_PHASE_DEAD) + ppp_dead(ppp); +} + struct ppp_header *ppp_packet_new(gsize infolen, guint16 protocol) { struct ppp_header *ppp_packet; @@ -171,6 +194,7 @@ void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen) guint8 code; gboolean lcp = (proto == LCP_PROTOCOL); guint32 xmit_accm = 0; + gboolean sta = FALSE; /* * all LCP Link Configuration, Link Termination, and Code-Reject @@ -179,6 +203,15 @@ void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen) if (lcp) { code = pppcp_get_code(packet); lcp = code > 0 && code < 8; + + /* + * If we're going down, we try to make sure to send the final + * ack before informing the upper layers via the ppp_disconnect + * function. Once we enter PPP_DEAD phase, no further packets + * will be sent + */ + if (code == PPPCP_CODE_TYPE_TERMINATE_ACK) + sta = TRUE; } if (lcp) { @@ -190,27 +223,26 @@ void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen) header->control = PPP_CTRL; if (g_at_hdlc_send(ppp->hdlc, packet, - infolen + sizeof(*header)) == FALSE) + infolen + sizeof(*header)) == TRUE) { + if (sta) { + GAtIO *io = g_at_hdlc_get_io(ppp->hdlc); + + ppp->sta_pending = TRUE; + g_at_io_set_write_done(io, sta_sent, ppp); + } + } else g_print("Failed to send a frame\n"); if (lcp) g_at_hdlc_set_xmit_accm(ppp->hdlc, xmit_accm); } -static void ppp_dead(GAtPPP *ppp) -{ - /* notify interested parties */ - if (ppp->disconnect_cb) - ppp->disconnect_cb(ppp->disconnect_reason, - ppp->disconnect_data); -} - static inline void ppp_enter_phase(GAtPPP *ppp, enum ppp_phase phase) { g_print("Entering new phase: %d\n", phase); ppp->phase = phase; - if (phase == PPP_PHASE_DEAD) + if (phase == PPP_PHASE_DEAD && ppp->sta_pending == FALSE) ppp_dead(ppp); } |