async.c revision 6735
119304Speter/*
219304Speter *	             PPP Async HDLC Module
319304Speter *
419304Speter *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
519304Speter *
619304Speter *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
719304Speter *
819304Speter * Redistribution and use in source and binary forms are permitted
919304Speter * provided that the above copyright notice and this paragraph are
1019304Speter * duplicated in all such forms and that any documentation,
1119304Speter * advertising materials, and other materials related to such
1219304Speter * distribution and use acknowledge that the software was developed
13254225Speter * by the Internet Initiative Japan, Inc.  The name of the
1419304Speter * IIJ may not be used to endorse or promote products derived
1519304Speter * from this software without specific prior written permission.
1619304Speter * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1719304Speter * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1819304Speter * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1919304Speter *
2019304Speter * $Id:$
2119304Speter *
2219304Speter */
2319304Speter#include "fsm.h"
2419304Speter#include "hdlc.h"
2519304Speter#include "lcp.h"
2619304Speter#include "lcpproto.h"
2719304Speter#include "modem.h"
2819304Speter#include "vars.h"
2919304Speter
3019304Speter#define HDLCSIZE	(MAX_MRU*2+6)
31281373Sbapt
3219304Speterstruct async_state {
3319304Speter  int mode;
34254225Speter  int length;
3519304Speter  u_char hbuff[HDLCSIZE];	/* recv buffer */
3619304Speter  u_char xbuff[HDLCSIZE];	/* xmit buffer */
3719304Speter  u_long my_accmap;
3819304Speter  u_long his_accmap;
3919304Speter} AsyncState;
4019304Speter
4119304Speter#define MODE_HUNT 0x01
4219304Speter#define MODE_ESC  0x02
4319304Speter
4419304Spetervoid
4519304SpeterAsyncInit()
4619304Speter{
4719304Speter  struct async_state *stp = &AsyncState;
4819304Speter
4919304Speter  stp->mode = MODE_HUNT;
5019304Speter  stp->length = 0;
5119304Speter  stp->my_accmap = stp->his_accmap = 0xffffffff;
5219304Speter}
5319304Speter
5419304Spetervoid
5519304SpeterSetLinkParams(lcp)
5619304Speterstruct lcpstate *lcp;
5719304Speter{
5819304Speter  struct async_state *stp = &AsyncState;
5919304Speter
6019304Speter  stp->my_accmap = lcp->want_accmap;
6119304Speter  stp->his_accmap = lcp->his_accmap;
6219304Speter}
6319304Speter
6419304Speter/*
6519304Speter * Encode into async HDLC byte code if necessary
6619304Speter */
6719304Speterstatic void
6819304SpeterHdlcPutByte(cp, c, proto)
6919304Speteru_char **cp;
7019304Speteru_char c;
7119304Speterint proto;
7219304Speter{
7319304Speter  u_char *wp;
7419304Speter
7519304Speter  wp = *cp;
7619304Speter  if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1<<c))))
7719304Speter	|| (c == HDLC_ESC) || (c == HDLC_SYN)) {
78281373Sbapt    *wp++ = HDLC_ESC;
7919304Speter    c ^= HDLC_XOR;
8019304Speter  }
81254225Speter  if (EscMap[32] && EscMap[c >> 3] & (c&7)) {
8219304Speter    *wp++ = HDLC_ESC;
8319304Speter    c ^= HDLC_XOR;
8419304Speter  }
8519304Speter  *wp++ = c;
8619304Speter  *cp = wp;
8719304Speter}
8819304Speter
8919304Spetervoid
9019304SpeterAsyncOutput(pri, bp, proto)
9119304Speterint pri;
9219304Speterstruct mbuf *bp;
9319304Speterint proto;
9419304Speter{
9519304Speter  struct async_state *hs = &AsyncState;
9619304Speter  u_char *cp, *sp, *ep;
9719304Speter  struct mbuf *wp;
9819304Speter  int cnt;
9919304Speter
10019304Speter  if (plength(bp) > HDLCSIZE) {
10119304Speter    pfree(bp);
10219304Speter    return;
10319304Speter  }
104  cp = hs->xbuff;
105  ep = cp + HDLCSIZE - 10;
106  wp = bp;
107  *cp ++ = HDLC_SYN;
108  while (wp) {
109    sp = MBUF_CTOP(wp);
110    for (cnt = wp->cnt; cnt > 0; cnt--) {
111      HdlcPutByte(&cp, *sp++, proto);
112      if (cp >= ep) {
113	pfree(bp);
114	return;
115      }
116    }
117    wp = wp->next;
118  }
119  *cp ++ = HDLC_SYN;
120
121  cnt = cp - hs->xbuff;
122  LogDumpBuff(LOG_ASYNC, "WriteModem", hs->xbuff, cnt);
123  WriteModem(pri, (char *)hs->xbuff, cnt);
124  OsAddOutOctets(cnt);
125  pfree(bp);
126}
127
128struct mbuf *
129AsyncDecode(c)
130u_char c;
131{
132  struct async_state *hs = &AsyncState;
133  struct mbuf *bp;
134
135  if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
136    return(NULLBUFF);
137
138  switch (c) {
139  case HDLC_SYN:
140    hs->mode &= ~MODE_HUNT;
141    if (hs->length) {	/* packet is ready. */
142      bp = mballoc(hs->length, MB_ASYNC);
143      mbwrite(bp, hs->hbuff, hs->length);
144      hs->length = 0;
145      return(bp);
146    }
147    break;
148  case HDLC_ESC:
149    if (!(hs->mode & MODE_ESC)) {
150      hs->mode |= MODE_ESC;
151      break;
152    }
153    /* Fall into ... */
154  default:
155    if (hs->length >= HDLCSIZE) {
156      /* packet is too large, discard it */
157      logprintf("too large, diacarding.\n");
158      hs->length = 0;
159      hs->mode = MODE_HUNT;
160      break;
161    }
162    if (hs->mode & MODE_ESC) {
163      c ^= HDLC_XOR;
164      hs->mode &= ~MODE_ESC;
165    }
166    hs->hbuff[hs->length++] = c;
167    break;
168  }
169  return NULLBUFF;
170}
171
172void
173AsyncInput(buff, cnt)
174u_char *buff;
175int cnt;
176{
177  struct mbuf *bp;
178
179  OsAddInOctets(cnt);
180  if (DEV_IS_SYNC) {
181    bp = mballoc(cnt, MB_ASYNC);
182    bcopy(buff, MBUF_CTOP(bp), cnt);
183    bp->cnt = cnt;
184    HdlcInput(bp);
185  } else {
186    while (cnt > 0) {
187      bp = AsyncDecode(*buff++);
188      if (bp)
189        HdlcInput(bp);
190      cnt--;
191    }
192  }
193}
194