summaryrefslogtreecommitdiffstats
path: root/gatchat/gatppp.c
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2010-04-28 15:31:59 -0500
committerDenis Kenzior <denkenz@gmail.com>2010-04-28 17:27:35 -0500
commit4cdf49f0de4257d32b81e73985dc42dfa996ef24 (patch)
tree06bc79101fbcfaa3146619ad67d5f357eac3e779 /gatchat/gatppp.c
parentfa8614cc78603d760f90dbff870ad175af4da583 (diff)
downloadofono-4cdf49f0de4257d32b81e73985dc42dfa996ef24.tar.bz2
ppp: Initial port of PPP to use GAtHDLC
Diffstat (limited to 'gatchat/gatppp.c')
-rw-r--r--gatchat/gatppp.c400
1 files changed, 41 insertions, 359 deletions
diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c
index c7bf089b..bd230bf4 100644
--- a/gatchat/gatppp.c
+++ b/gatchat/gatppp.c
@@ -35,6 +35,7 @@
#include <glib.h>
#include "gatutil.h"
+#include "gathdlc.h"
#include "gatppp.h"
#include "crc-ccitt.h"
#include "ppp.h"
@@ -42,13 +43,6 @@
#define DEFAULT_MRU 1500
#define DEFAULT_MTU 1500
-#define BUFFERSZ (DEFAULT_MRU * 2)
-
-#define PPP_ESC 0x7d
-#define PPP_FLAG_SEQ 0x7e
-#define PPP_ADDR_FIELD 0xff
-#define PPP_CTRL 0x03
-
struct _GAtPPP {
gint ref_count;
enum ppp_phase phase;
@@ -56,25 +50,17 @@ struct _GAtPPP {
struct pppcp_data *ipcp;
struct ppp_net *net;
struct ppp_chap *chap;
- guint8 buffer[BUFFERSZ];
- int index;
+ GAtHDLC *hdlc;
gint mru;
gint mtu;
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;
};
void ppp_debug(GAtPPP *ppp, const char *str)
@@ -85,99 +71,11 @@ void ppp_debug(GAtPPP *ppp, const char *str)
ppp->debugf(str, ppp->debug_data);
}
-#define PPPINITFCS16 0xffff /* Initial FCS value */
-#define PPPGOODFCS16 0xf0b8 /* Good final FCS value */
-
-struct frame_buffer {
- gsize len;
- guint8 bytes[0];
-};
-
-/*
- * 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)
-{
- 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)
-{
- 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;
-}
-
-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);
- guint8 code;
- 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;
-
- /*
- * all LCP Link Configuration, Link Termination, and Code-Reject
- * packets must be sent with the default sending ACCM
- */
- if (lcp) {
- code = pppcp_get_code(data);
- lcp = code > 0 && code < 8;
- }
-
- /* 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;
-}
-
-/* called when we have received a complete ppp frame */
-static void ppp_recv(GAtPPP *ppp, struct frame_buffer *frame)
+static void ppp_receive(const unsigned char *buf, gsize len, void *data)
{
- guint16 protocol = ppp_proto(frame->bytes);
- guint8 *packet = ppp_info(frame->bytes);
+ GAtPPP *ppp = data;
+ guint16 protocol = ppp_proto(buf);
+ const guint8 *packet = ppp_info(buf);
/*
* Any non-LCP packets received during Link Establishment
@@ -205,144 +103,42 @@ 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, buf, len);
break;
};
}
-static struct frame_buffer *ppp_decode(GAtPPP *ppp, guint8 *frame)
-{
- 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++;
- }
-
- 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)
+/*
+ * transmit out through the lower layer interface
+ *
+ * infolen - length of the information part of the packet
+ */
+void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen)
{
- guint pos = 0;
- struct frame_buffer *frame;
+ guint16 proto = get_host_short(packet);
+ guint8 code;
+ gboolean lcp = (proto == LCP_PROTOCOL);
+ guint32 xmit_accm = 0;
- /* 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.
+ /*
+ * all LCP Link Configuration, Link Termination, and Code-Reject
+ * packets must be sent with the default sending ACCM
*/
-
- 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];
+ if (lcp) {
+ code = pppcp_get_code(packet);
+ lcp = code > 0 && code < 8;
}
-}
-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;
+ if (lcp) {
+ xmit_accm = g_at_hdlc_get_xmit_accm(ppp->hdlc);
+ g_at_hdlc_set_xmit_accm(ppp->hdlc, ~0U);
}
- return TRUE;
+ if (g_at_hdlc_send(ppp->hdlc, packet, infolen + 2) == FALSE)
+ 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)
@@ -392,12 +188,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);
@@ -451,12 +241,12 @@ void ppp_net_down_notify(GAtPPP *ppp)
void ppp_set_recv_accm(GAtPPP *ppp, guint32 accm)
{
- ppp->recv_accm = accm;
+ g_at_hdlc_set_recv_accm(ppp->hdlc, accm);
}
void ppp_set_xmit_accm(GAtPPP *ppp, guint32 accm)
{
- ppp->xmit_accm[0] = accm;
+ g_at_hdlc_set_xmit_accm(ppp->hdlc, accm);
}
/*
@@ -536,23 +326,6 @@ void g_at_ppp_set_debug(GAtPPP *ppp, GAtDebugFunc func, gpointer user_data)
ppp->debug_data = user_data;
}
-void g_at_ppp_set_recording(GAtPPP *ppp, const char *filename)
-{
- if (ppp == NULL)
- return;
-
- if (ppp->record_fd > fileno(stderr)) {
- close(ppp->record_fd);
- ppp->record_fd = -1;
- }
-
- if (filename == NULL)
- return;
-
- ppp->record_fd = open(filename, O_WRONLY | O_CREAT | O_APPEND,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-}
-
void g_at_ppp_shutdown(GAtPPP *ppp)
{
pppcp_signal_close(ppp->lcp);
@@ -572,24 +345,15 @@ void g_at_ppp_unref(GAtPPP *ppp)
if (is_zero == FALSE)
return;
- if (ppp->record_fd > fileno(stderr))
- close(ppp->record_fd);
-
- /* cleanup queue */
- g_queue_free(ppp->xmit_queue);
+ if (ppp->net)
+ ppp_net_free(ppp->net);
- /* cleanup modem channel */
- g_source_remove(ppp->read_watch);
- g_source_remove(ppp->write_watch);
- g_io_channel_unref(ppp->modem);
+ if (ppp->chap)
+ ppp_chap_free(ppp->chap);
lcp_free(ppp->lcp);
- ppp_chap_free(ppp->chap);
ipcp_free(ppp->ipcp);
- if (ppp->net)
- ppp_net_free(ppp->net);
-
g_free(ppp);
}
@@ -601,25 +365,18 @@ 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);
ppp->ref_count = 1;
/* set options to defaults */
ppp->mru = DEFAULT_MRU;
ppp->mtu = DEFAULT_MTU;
- ppp->recv_accm = ~0U;
- 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);
@@ -627,82 +384,7 @@ GAtPPP *g_at_ppp_new(GIOChannel *modem)
/* 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;
+ g_at_hdlc_set_receive(ppp->hdlc, ppp_receive, ppp);
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
- *
- * infolen - length of the information part of the packet
- */
-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);
-
- /* 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);
-}