/* * Copyright (c) Martin Schoeberl, martin@jopdesign.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Martin Schoeberl * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ // // Nullmodem cable (both female): // // 1 NC // 2 3 // 3 2 // 4 6 // 5 5 // 6 4 // 7 8 // 8 7 // 9 NC // package ejip_old; /** * Slip.java * * communicate with jopbb via serial line. */ import util.Dbg; import util.Serial; /** * Slip driver. */ public class Slip extends LinkLayer { private static final int MAX_BUF = 1500; // or should we use 1006 private static final int END = 0xc0; private static final int ESC = 0xdb; private static final int ESC_END = 0xdc; private static final int ESC_ESC = 0xdd; private static int simSendErr, simRcvErr; /** * receive buffer */ private static int[] rbuf; /** * send buffer */ private static int[] sbuf; /** * bytes received. */ private static int cnt; /** * mark escape sequence. */ private static boolean esc; /** * an ip packet is in the receive buffer. */ private static boolean ready; /** * bytes to be sent. 0 means txFree */ private static int scnt; /** * allready sent bytes. */ private static int sent; /** * The one and only reference to this object. */ private static Slip single; private static Serial ser; /** * private constructor. The singleton object is created in init(). */ private Slip() { } /** * allocate buffer, start serial buffer and slip Thread. */ public static LinkLayer init(Serial serPort, int ipAddr) { if (single != null) return single; // allready called init() rbuf = new int[MAX_BUF]; sbuf = new int[MAX_BUF]; cnt = 0; esc = false; ready = false; scnt = 0; sent = 0; ser = serPort; single = new Slip(); single.ip = ipAddr; return single; } public int getIpAddress() { return ip; } /** * Set connection strings and connect. */ public void startConnection(StringBuffer dialstr, StringBuffer connect, StringBuffer user, StringBuffer passwd) { // useless in Slip } /** * Forces the connection to be new established. * On Slip ignored. */ public void reconnect() { } static int timer; /** * main loop. */ public void loop() { Packet p; // // read, write loop // if (ipLoop()) { timer = 0; } else { ++timer; if (timer>100 && cnt>0) { // flush buffer on timeout (100*10ms) Dbg.wr('t'); for (int i=0; i<cnt; ++i) { int val = rbuf[i]; if (val=='\r') { Dbg.wr('r'); } else { Dbg.wr(val); } } cnt = 0; esc = false; ready = false; timer = 0; // send anything back for windoz slip version if (ser.txFreeCnt()>0) { ser.wr('C'); ser.wr('L'); ser.wr('I'); ser.wr('E'); ser.wr('N'); ser.wr('T'); ser.wr('S'); ser.wr('E'); ser.wr('R'); ser.wr('V'); ser.wr('E'); ser.wr('R'); ser.wr('\r'); } } } // // copy packet to packet buffer. // if (ready) { // we got a packet read(); } if (scnt==0) { // transmit buffer is free // // get a ready to send packet with source from this driver. // p = Packet.getTxPacket(single); if (p!=null) { send(p); // send one packet } } } /** * get a Packet buffer and copy from receive buffer. */ private static void read() { int i, j, k; Packet p = Packet.getPacket(Packet.FREE, Packet.ALLOC, single); if (p==null) { Dbg.wr('!'); cnt = 0; // drop it ready = false; // don't block the receiver return; } int[] pb = p.buf; rbuf[cnt] = 0; // fill remaining bytes to word rbuf[cnt+1] = 0; // boundry with 0 for UDP rbuf[cnt+2] = 0; // checksum // copy buffer k = 0; for (i=0; i<cnt; i+=4) { for (j=0; j<4; ++j) { k <<= 8; k += rbuf[i+j]; } pb[i>>>2] = k; } p.len = cnt; Dbg.wr('r'); Dbg.intVal(cnt); cnt = 0; ready = false; /* ++simRcvErr; if (simRcvErr%5==1) { p.setStatus(Packet.FREE); Dbg.wr(" rcv dropped"); Dbg.lf(); return; } */ p.setStatus(Packet.RCV); // inform upper layer } /** * copy packet to send buffer. */ private static void send(Packet p) { int i, k; int[] pb = p.buf; Dbg.wr('s'); Dbg.intVal(p.len); /* ++simSendErr; if (simSendErr%7==3) { p.setStatus(Packet.FREE); Dbg.wr(" send dropped"); Dbg.lf(); return; } */ scnt = p.len; sent = 0; for (i=0; i<scnt; i+=4) { k = pb[i>>>2]; sbuf[i] = k>>>24; sbuf[i+1] = (k>>>16)&0xff; sbuf[i+2] = (k>>>8)&0xff; sbuf[i+3] = k&0xff; } if (p.getStatus()==Packet.SND_TCP) { p.setStatus(Packet.TCP_ONFLY); // mark on the fly } else { p.setStatus(Packet.FREE); // mark packet free } } /* warum geht das nicht !!!!! private void loop() { */ /** * read from serial buffer and build an ip packet. * send a packet if one is in our send buffer. */ private static boolean ipLoop() { int i; boolean ret = false; i = ser.rxCnt(); if (i!=0) { ret = true; rcv(i); } if (cnt==MAX_BUF && !ready) cnt = 0; // buffer full, but not ready => drop it if (scnt!=0) { i = ser.txFreeCnt(); if (i>2) { snd(i); } } return ret; } /** * copy from send buffer to serial buffer. */ private static void snd(int free) { int i; if (sent==0) { ser.wr(END); --free; } for (i=sent; free>1 && i<scnt; ++i) { int c = sbuf[i]; if (c==END) { ser.wr(ESC); ser.wr(ESC_END); free -= 2; } else if (c==ESC) { ser.wr(ESC); ser.wr(ESC_ESC); free -= 2; } else { ser.wr(c); --free; } } sent = i; if (sent==scnt && free!=0) { ser.wr(END); scnt = 0; sent = 0; } } /** * copy from serial buffer to receive buffer. */ private static void rcv(int len) { int i; // get all bytes from serial buffer for (i=0; i<len && cnt<MAX_BUF; ++i) { if (ready) break; // wait till buffer is copied int val = ser.rd(); if (esc) { if (val == ESC_END) { rbuf[cnt++] = END; } else if (val == ESC_ESC) { rbuf[cnt++] = ESC; } else { rbuf[cnt++] = val; } esc = false; continue; } if (val == ESC) { esc = true; } else { esc = false; if (val==END) { if (cnt>=20) { ready = true; // we got one packet break; } else { // ignore too short packages cnt = 0; continue; } } else { rbuf[cnt++] = val; } } } } /* (non-Javadoc) * @see ejip.LinkLayer#getConnCount() */ public int getConnCount() { return 0; } }