summaryrefslogtreecommitdiffstats
path: root/gatchat/gatppp.c
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2011-02-26 00:14:29 -0600
committerDenis Kenzior <denkenz@gmail.com>2011-02-28 16:13:55 -0600
commitb6bc221bc8c27d8654ce6008d9707f2e458321c8 (patch)
tree64573e52e73c94cb07a0e94e7e6a4c31e8602f23 /gatchat/gatppp.c
parent802962adbc29e6e0c2c4f64efc9ba1e5f1e29753 (diff)
downloadofono-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.c52
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);
}