---
gatchat/gatppp.c | 347 +++++++++-------------------------------------------
gatchat/ppp.h | 11 ++
gatchat/ppp_auth.c | 2 +-
gatchat/ppp_cp.c | 6 +-
gatchat/ppp_net.c | 3 +-
5 files changed, 75 insertions(+), 294 deletions(-)
diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c
index e1e49e6..5b6ba4e 100644
--- a/gatchat/gatppp.c
+++ b/gatchat/gatppp.c
@@ -34,6 +34,7 @@
#include <glib.h>
+#include "gathdlc.h"
#include "gatutil.h"
#include "gatppp.h"
#include "crc-ccitt.h"
@@ -41,10 +42,6 @@
#define DEFAULT_MRU 1500
-#define BUFFERSZ (DEFAULT_MRU * 2)
-
-#define PPP_ESC 0x7d
-#define PPP_FLAG_SEQ 0x7e
#define PPP_ADDR_FIELD 0xff
#define PPP_CTRL 0x03
@@ -55,24 +52,19 @@ struct _GAtPPP {
struct pppcp_data *ipcp;
struct ppp_net *net;
struct ppp_chap *chap;
- guint8 buffer[BUFFERSZ];
- int index;
gint mru;
char username[256];
char password[256];
guint32 xmit_accm[8];
guint32 recv_accm;
- GIOChannel *modem;
GAtPPPConnectFunc connect_cb;
gpointer connect_data;
GAtDisconnectFunc disconnect_cb;
gpointer disconnect_data;
- gint read_watch;
- gint write_watch;
GAtDebugFunc debugf;
gpointer debug_data;
int record_fd;
- GQueue *xmit_queue;
+ GAtHDLC *hdlc;
};
void ppp_debug(GAtPPP *ppp, const char *str)
@@ -91,81 +83,59 @@ struct frame_buffer {
guint8 bytes[0];
};
+static void ppp_record(GAtPPP *ppp, gboolean in, guint8 *data, guint16 length)
+{
+ guint16 len = htons(length);
+ guint32 ts;
+ struct timeval now;
+ unsigned char id;
+ int err;
+
+ if (ppp->record_fd < 0)
+ return;
+
+ gettimeofday(&now, NULL);
+ ts = htonl(now.tv_sec & 0xffffffff);
+
+ id = 0x07;
+ err = write(ppp->record_fd, &id, 1);
+ err = write(ppp->record_fd, &ts, 4);
+
+ id = in ? 0x02 : 0x01;
+ err = write(ppp->record_fd, &id, 1);
+ err = write(ppp->record_fd, &len, 2);
+ err = write(ppp->record_fd, data, length);
+}
+
/*
* escape any chars less than 0x20, and check the transmit accm table to
* see if this character should be escaped.
*/
-static gboolean ppp_escape(GAtPPP *ppp, guint8 c, gboolean lcp)
+static gboolean ppp_escape(gpointer user_data, guint8 c, gboolean lcp)
{
+ GAtPPP *ppp = user_data;
+
if ((lcp && c < 0x20) || (ppp->xmit_accm[c >> 5] & (1 <<
(c & 0x1f))))
return TRUE;
return FALSE;
}
-static void ppp_put(GAtPPP *ppp, guint8 *buf, int *pos,
- guint8 c, gboolean lcp)
+static gboolean ppp_hdlc_scan(gpointer user_data, const unsigned char *data)
{
- int i = *pos;
-
- /* escape characters if needed, copy into buf, increment pos */
- if (ppp_escape(ppp, c, lcp)) {
- buf[i++] = PPP_ESC;
- buf[i++] = c ^ 0x20;
- } else
- buf[i++] = c;
- *pos = i;
-}
+ guint16 proto = ppp_proto(data);
-static struct frame_buffer *ppp_encode(GAtPPP *ppp, guint8 *data, int len)
-{
- int pos = 0;
- int i = 0;
- guint16 fcs = PPPINITFCS16;
- guint16 proto = get_host_short(data);
- gboolean lcp = (proto == LCP_PROTOCOL);
- guint8 *frame;
- struct frame_buffer *fb =
- g_try_malloc0(BUFFERSZ + sizeof(struct frame_buffer));
-
- if (!fb)
- return NULL;
- frame = fb->bytes;
-
- /* copy in the HDLC framing */
- frame[pos++] = PPP_FLAG_SEQ;
-
- /* from here till end flag, calculate FCS over each character */
- fcs = crc_ccitt_byte(fcs, PPP_ADDR_FIELD);
- ppp_put(ppp, frame, &pos, PPP_ADDR_FIELD, lcp);
- fcs = crc_ccitt_byte(fcs, PPP_CTRL);
- ppp_put(ppp, frame, &pos, PPP_CTRL, lcp);
-
- /*
- * for each byte, first calculate FCS, then do escaping if
- * neccessary
- */
- while (len--) {
- fcs = crc_ccitt_byte(fcs, data[i]);
- ppp_put(ppp, frame, &pos, data[i++], lcp);
- }
-
- /* add FCS */
- fcs ^= 0xffff; /* complement */
- ppp_put(ppp, frame, &pos, (guint8)(fcs & 0x00ff), lcp);
- ppp_put(ppp, frame, &pos, (guint8)((fcs >> 8) & 0x00ff), lcp);
-
- /* add flag */
- frame[pos++] = PPP_FLAG_SEQ;
-
- fb->len = pos;
- return fb;
+ if (proto == LCP_PROTOCOL)
+ return TRUE;
+ return FALSE;
}
-/* called when we have received a complete ppp frame */
-static void ppp_recv(GAtPPP *ppp, struct frame_buffer *frame)
+static void ppp_hdlc_recv(const unsigned char *data, gsize size, gpointer user_data)
{
- guint16 protocol = ppp_proto(frame->bytes);
- guint8 *packet = ppp_info(frame->bytes);
+ GAtPPP *ppp = user_data;
+ guint16 protocol = ppp_proto(data);
+ guint8 *packet = (guint8 *) ppp_info(data);
+
+ ppp_record(ppp, TRUE, (guint8 *) data, size);
switch (protocol) {
case PPP_IP_PROTO:
@@ -186,144 +156,18 @@ static void ppp_recv(GAtPPP *ppp, struct frame_buffer *frame)
}
/* fall through */
default:
- pppcp_send_protocol_reject(ppp->lcp, frame->bytes, frame->len);
+ pppcp_send_protocol_reject(ppp->lcp, (guint8 *) data, size);
break;
};
}
-static struct frame_buffer *ppp_decode(GAtPPP *ppp, guint8 *frame)
+static gboolean ppp_recv_escape(gpointer user_data, guint8 c)
{
- guint8 *data;
- guint pos;
- int i;
- guint16 fcs;
- struct frame_buffer *fb;
-
- fb = g_try_malloc0(sizeof(struct frame_buffer) + ppp->mru + 10);
- if (!fb)
- return NULL;
- data = fb->bytes;
-
- /* skip the first flag char */
- pos = 1;
-
- fcs = PPPINITFCS16;
- i = 0;
-
- while (frame[pos] != PPP_FLAG_SEQ) {
- /* Skip the characters in receive ACCM */
- if (frame[pos] < 0x20 &&
- (ppp->recv_accm & (1 << frame[pos])) != 0) {
- pos++;
- continue;
- }
-
- /* scan for escape character */
- if (frame[pos] == PPP_ESC) {
- /* skip that char */
- pos++;
- data[i] = frame[pos] ^ 0x20;
- } else
- data[i] = frame[pos];
-
- fcs = crc_ccitt_byte(fcs, data[i]);
-
- i++; pos++;
- }
+ GAtPPP *ppp = user_data;
- fb->len = i;
-
- /* see if we have a good FCS */
- if (fcs != PPPGOODFCS16) {
- g_free(fb);
- return NULL;
- }
-
- return fb;
-}
-
-static void ppp_feed(GAtPPP *ppp, guint8 *data, gsize len)
-{
- guint pos = 0;
- struct frame_buffer *frame;
-
- /* collect bytes until we detect we have received a complete frame */
- /* examine the data. If we are at the beginning of a new frame,
- * allocate memory to buffer the frame.
- */
-
- for (pos = 0; pos < len; pos++) {
- if (data[pos] == PPP_FLAG_SEQ) {
- if (ppp->index != 0) {
- /* store last flag character & decode */
- ppp->buffer[ppp->index++] = data[pos];
- frame = ppp_decode(ppp, ppp->buffer);
- if (frame) {
- /* process receive frame */
- ppp_recv(ppp, frame);
- g_free(frame);
- }
-
- /* zero buffer */
- memset(ppp->buffer, 0, BUFFERSZ);
- ppp->index = 0;
- continue;
- }
- }
- /* copy byte to buffer */
- if (ppp->index < BUFFERSZ)
- ppp->buffer[ppp->index++] = data[pos];
- }
-}
-
-static void ppp_record(GAtPPP *ppp, gboolean in, guint8 *data, guint16 length)
-{
- guint16 len = htons(length);
- guint32 ts;
- struct timeval now;
- unsigned char id;
- int err;
-
- if (ppp->record_fd < 0)
- return;
-
- gettimeofday(&now, NULL);
- ts = htonl(now.tv_sec & 0xffffffff);
-
- id = 0x07;
- err = write(ppp->record_fd, &id, 1);
- err = write(ppp->record_fd, &ts, 4);
-
- id = in ? 0x02 : 0x01;
- err = write(ppp->record_fd, &id, 1);
- err = write(ppp->record_fd, &len, 2);
- err = write(ppp->record_fd, data, length);
-}
-
-static gboolean ppp_read_cb(GIOChannel *channel, GIOCondition cond,
- gpointer data)
-{
- GAtPPP *ppp = data;
- GIOStatus status;
- gchar buf[256];
- gsize bytes_read;
- GError *error = NULL;
-
- if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
- return FALSE;
-
- if (cond & G_IO_IN) {
- status = g_io_channel_read_chars(channel, buf, 256,
- &bytes_read, &error);
- if (bytes_read > 0) {
- ppp_record(ppp, TRUE, (guint8 *) buf, bytes_read);
- ppp_feed(ppp, (guint8 *) buf, bytes_read);
- }
- if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN)
- return FALSE;
- }
-
- return TRUE;
+ if (c < 0x20 && (ppp->recv_accm & (1 << c)) != 0)
+ return TRUE;
+ return FALSE;
}
static void ppp_dead(GAtPPP *ppp)
@@ -371,12 +215,6 @@ void ppp_enter_phase(GAtPPP *ppp, enum ppp_phase phase)
}
}
-static void read_watcher_destroy_notify(GAtPPP *ppp)
-{
- ppp->read_watch = 0;
- pppcp_signal_down(ppp->lcp);
-}
-
void ppp_set_auth(GAtPPP *ppp, const guint8* auth_data)
{
guint16 proto = get_host_short(auth_data);
@@ -540,13 +378,7 @@ void g_at_ppp_unref(GAtPPP *ppp)
if (ppp->record_fd > fileno(stderr))
close(ppp->record_fd);
- /* cleanup queue */
- g_queue_free(ppp->xmit_queue);
-
- /* cleanup modem channel */
- g_source_remove(ppp->read_watch);
- g_source_remove(ppp->write_watch);
- g_io_channel_unref(ppp->modem);
+ g_at_hdlc_unref(ppp->hdlc);
lcp_free(ppp->lcp);
ppp_chap_free(ppp->chap);
@@ -566,11 +398,15 @@ GAtPPP *g_at_ppp_new(GIOChannel *modem)
if (!ppp)
return NULL;
- if (!g_at_util_setup_io(modem, G_IO_FLAG_NONBLOCK)) {
+ ppp->hdlc = g_at_hdlc_new(modem);
+ if (ppp->hdlc == NULL) {
g_free(ppp);
return NULL;
}
- g_io_channel_set_buffered(modem, FALSE);
+ g_at_hdlc_set_receive(ppp->hdlc, ppp_hdlc_recv, ppp);
+ g_at_hdlc_set_recv_escape(ppp->hdlc, ppp_recv_escape, ppp);
+ g_at_hdlc_set_send_escape(ppp->hdlc, ppp_escape, ppp);
+ g_at_hdlc_set_scan(ppp->hdlc, ppp_hdlc_scan, ppp);
ppp->ref_count = 1;
@@ -580,70 +416,16 @@ GAtPPP *g_at_ppp_new(GIOChannel *modem)
ppp->xmit_accm[0] = ~0U;
ppp->xmit_accm[3] = 0x60000000; /* 0x7d, 0x7e */
- ppp->index = 0;
-
- /* intialize the queue */
- ppp->xmit_queue = g_queue_new();
-
/* initialize the lcp state */
ppp->lcp = lcp_new(ppp);
/* initialize IPCP state */
ppp->ipcp = ipcp_new(ppp);
-
- /* start listening for packets from the modem */
- ppp->read_watch = g_io_add_watch_full(modem, G_PRIORITY_DEFAULT,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- ppp_read_cb, ppp,
- (GDestroyNotify)read_watcher_destroy_notify);
-
- ppp->modem = modem;
ppp->record_fd = -1;
return ppp;
}
-static gboolean ppp_xmit_cb(GIOChannel *channel, GIOCondition cond,
- gpointer data)
-{
- GAtPPP *ppp = data;
- struct frame_buffer *fb;
- GError *error = NULL;
- GIOStatus status;
- gsize bytes_written;
-
- if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
- return FALSE;
-
- if (cond & G_IO_OUT) {
- while ((fb = g_queue_peek_head(ppp->xmit_queue))) {
- status = g_io_channel_write_chars(ppp->modem,
- (gchar *) fb->bytes, fb->len,
- &bytes_written, &error);
- if (status != G_IO_STATUS_NORMAL &&
- status != G_IO_STATUS_AGAIN)
- return FALSE;
-
- if (bytes_written < fb->len)
- return TRUE;
-
- ppp_record(ppp, FALSE, fb->bytes, bytes_written);
- g_free(g_queue_pop_head(ppp->xmit_queue));
- }
- }
- return FALSE;
-}
-
-static void ppp_xmit_destroy_notify(gpointer destroy_data)
-{
- GAtPPP *ppp = destroy_data;
-
- ppp->write_watch = 0;
-
- if (ppp->phase == PPP_PHASE_DEAD)
- ppp_dead(ppp);
-}
-
/*
* transmit out through the lower layer interface
*
@@ -651,22 +433,11 @@ static void ppp_xmit_destroy_notify(gpointer destroy_data)
*/
void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen)
{
- struct frame_buffer *fb;
-
- /*
- * do the octet stuffing. Add 2 bytes to the infolen to
- * include the protocol field.
- */
- fb = ppp_encode(ppp, packet, infolen + 2);
- if (!fb) {
- g_printerr("Failed to encode packet to transmit\n");
- return;
- }
- /* push decoded frame onto xmit queue */
- g_queue_push_tail(ppp->xmit_queue, fb);
+ struct ppp_header *header = (struct ppp_header *) packet;
+ gsize len = infolen + sizeof(struct ppp_header);
- /* transmit this whenever we can write without blocking */
- ppp->write_watch = g_io_add_watch_full(ppp->modem, G_PRIORITY_DEFAULT,
- G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- ppp_xmit_cb, ppp, ppp_xmit_destroy_notify);
+ header->address = PPP_ADDR_FIELD;
+ header->control = PPP_CTRL;
+ g_at_hdlc_send(ppp->hdlc, packet, len);
+ ppp_record(ppp, FALSE, packet, len);
}
diff --git a/gatchat/ppp.h b/gatchat/ppp.h
index a8a0486..c41bb05 100644
--- a/gatchat/ppp.h
+++ b/gatchat/ppp.h
@@ -39,6 +39,8 @@ struct ppp_chap;
struct ppp_net;
struct ppp_header {
+ guint8 address;
+ guint8 control;
guint16 proto;
guint8 info[0];
} __attribute__((packed));
@@ -84,6 +86,15 @@ static inline void __put_unaligned_short(void *p, guint16 val)
#define ppp_proto(packet) \
(get_host_short(packet + 2))
+#define ppp_hdlc_proto(packet) \
+ (get_host_short(packet + 4))
+
+#define ppp_hdlc_info(packet) \
+ (packet + 6)
+
+#define ppp_hdlc_packet(packet) \
+ ((guint8 *) packet + 2)
+
/* LCP related functions */
struct pppcp_data *lcp_new(GAtPPP *ppp);
void lcp_free(struct pppcp_data *lcp);
diff --git a/gatchat/ppp_auth.c b/gatchat/ppp_auth.c
index 57203ab..b8c0628 100644
--- a/gatchat/ppp_auth.c
+++ b/gatchat/ppp_auth.c
@@ -83,7 +83,7 @@ static void chap_process_challenge(struct ppp_chap *chap, guint8
*packet)
*/
digest_len = g_checksum_type_get_length(chap->method);
response_length = digest_len + sizeof(*header) + 1;
- ppp_packet = g_try_malloc0(response_length + 2);
+ ppp_packet = g_try_malloc0(response_length + sizeof(struct ppp_header));
if (!ppp_packet)
goto challenge_out;
diff --git a/gatchat/ppp_cp.c b/gatchat/ppp_cp.c
index 6cd3681..ce8c94a 100644
--- a/gatchat/ppp_cp.c
+++ b/gatchat/ppp_cp.c
@@ -61,10 +61,8 @@ static const char *pppcp_event_strings[] = {
g_free(str); \
} while (0);
-#define PPP_HEADROOM 2
-
#define pppcp_to_ppp_packet(p) \
- (((guint8 *) p) - PPP_HEADROOM)
+ (((guint8 *) p) - sizeof(struct ppp_header))
#define INITIAL_RESTART_TIMEOUT 3 /* restart interval in seconds */
#define MAX_TERMINATE 2
@@ -206,7 +204,7 @@ static struct pppcp_packet *pppcp_packet_new(struct pppcp_data *data,
struct ppp_header *ppp_packet;
guint16 packet_length = bufferlen + sizeof(*packet);
- ppp_packet = g_try_malloc0(packet_length + 2);
+ ppp_packet = g_try_malloc0(packet_length + sizeof(struct ppp_header));
if (!ppp_packet)
return NULL;
diff --git a/gatchat/ppp_net.c b/gatchat/ppp_net.c
index 325e859..9fbd1d7 100644
--- a/gatchat/ppp_net.c
+++ b/gatchat/ppp_net.c
@@ -80,7 +80,8 @@ static gboolean ppp_net_callback(GIOChannel *channel, GIOCondition
cond,
if (cond & G_IO_IN) {
/* leave space to add PPP protocol field */
- status = g_io_channel_read_chars(channel, buf + 2, MAX_PACKET,
+ status = g_io_channel_read_chars(channel,
+ buf + sizeof(struct ppp_header), MAX_PACKET,
&bytes_read, &error);
if (bytes_read > 0) {
ppp->proto = htons(PPP_IP_PROTO);
--
1.6.6.1