📄 bgppp.java
字号:
/* * 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. * */package oebb;/*** Ppp.java** communicate with jop via serial line.*/import joprt.RtThread;import util.Dbg;import util.Serial;import util.Timer;import ejip.*;/*** Ppp driver.*/public class BgPpp extends LinkLayer { private static final int MAX_BUF = 1500+4; // 1500 is PPP information field/*** period for thread in us.*/ private static final int IP = 0x0021; // Internet Protocol packet private static final int IPCP = 0x8021; // Internet Protocol Configuration Protocol packet private static final int CCP = 0x80fd; // Compression Configuration Protocol packet private static final int LCP = 0xc021; // Link Configuration Protocol packet private static final int PAP = 0xc023; // Password Authentication Protocol packet private static final int REQ = 1; // Request options list private static final int ACK = 2; // Acknowledge options list private static final int NAK = 3; // Not acknowledge options list private static final int REJ = 4; // Reject options list private static final int TERM = 5; // Termination private static final int NEG_SEND= 3000; // Period of send negotiation (in ms) private static final int IP_SEND= 10000; // Send timout for ip for reconnect (in ms)/*** 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;/*** a ppp 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;/*** flag (0x7e, ~) received*/ private static boolean flag;/*** number for lcp id*/ private static int lcpId;/*** state machine*/ private static int state;/*** reject counter*/ private static int rejCnt; private static final int MAX_REJ = 5;/*** remote ip address.*/ private static int ipRemote;/*** ip address.*/ private static int ip;/*** request for reconnect.*/ private static boolean reconnectRequest;/*** request for a disconnect.*/ private static boolean disconnectRequest; private static int connCount;/*** The one and only reference to this object.*/ private static BgPpp single; private static Serial ser; private static RtThread rth;/*** private constructor. The singleton object is created in init().*/ private BgPpp() { }/*** allocate buffer, start serial buffer and slip Thread.*/ public static LinkLayer init(Serial serPort, RtThread pppThread) { if (single != null) return single; // allready called init() rbuf = new int[MAX_BUF]; sbuf = new int[MAX_BUF]; cnt = 0; esc = false; ready = false; flag = false; scnt = 0; sent = 0; connCount = 0; lcpId = 0x11; ip = 0; ipRemote = 0; reconnectRequest = false; disconnectRequest = false; initStr(); ser = serPort; // new Serial(serAddr, 10, 3000); single = new BgPpp(); rth = pppThread; return single; } /** * Returns IP address, 0 if not connected. */ public int getIpAddress() { if (state==CONNECTED) { return ip; } else { return 0; } } /** * Set connection strings and connect. */ public void startConnection(StringBuffer dialstr, StringBuffer connect, StringBuffer user, StringBuffer passwd) { int i, j;// System.out.println("start Conn"); // TODO correct dial string in Strecken data // copyStr(dialstr, dial); con.setLength(0); con.append("AT+CGDCONT=1,\"IP\",\""); i = connect.length(); for (j=0; j<i; ++j) con.append(connect.charAt(j)); con.append("\"\r"); copyStr(user, uid); copyStr(passwd, pwd); reconnectRequest = true; connCount = 0; ip = 0; } /** * Forces the connection to be anew established. */ public void reconnect() {// System.out.println("reconnect"); reconnectRequest = true; connCount = 0; ip = 0; } /** * Force a disconnect */ public void disconnect() { disconnectRequest = true; ip = 0; }/*** main loop. However this loop NEVER returns!* TODO: change to a loop based version to use PPP without threads.*/ public void loop() { connect(); } /** * windoz PPP. */ private static String client; private static String ver; private static StringBuffer dial; private static StringBuffer con; private static StringBuffer uid; private static StringBuffer pwd; private static String ok; private static String connect; private static String ath; private static String pin; private static String flow; private static StringBuffer strBuf; /** * a little helper: */ static void copyStr(StringBuffer src, StringBuffer dst) { int i, j; dst.setLength(0); i = src.length(); for (j=0; j<i; ++j) dst.append(src.charAt(j)); } private static void initStr() { con = new StringBuffer(40); dial = new StringBuffer(20); uid = new StringBuffer(20); pwd = new StringBuffer(20);/* we get the information from startConnection con.append("AT+CGDCONT=1,\"IP\",\"A1.net\"\r"); uid.append("ppp@A1plus.at"); pwd.append("ppp");*/ dial.append("ATD*99***1#\r"); client = "CLIENT"; ver = "VER"; ok = "OK"; connect = "ECT"; ath = "|+++|ATH\r"; pin = "AT+CPIN=5644\r"; flow = "AT\\Q3\r"; strBuf = new StringBuffer(40); // int [] s7 = { 'A', 'T', '+', 'C', 'G', 'D', 'C', 'O', 'N', 'T', '=', '1', ',', '"', 'I', 'P', '"', ',', '"', 'w', 'e', 'b', '.', 'o', 'n', 'e', '.', 'a', 't', '"', '\r' }; /* A1 */ // int [] s7 = { 'A', 'T', '+', 'C', 'G', 'D', 'C', 'O', 'N', 'T', '=', '1', ',', '"', 'I', 'P', '"', ',', '"', 'A', '1', '.', 'n', 'e', 't', '"', '\r' }; /* OEBB VPN */ /* int [] s7 = { 'A', 'T', '+', 'C', 'G', 'D', 'C', 'O', 'N', 'T', '=', '1', ',', '"', 'I', 'P', '"', ',', '"', 'o', 'e', 'b', 'b', '.', 'A', '1', '.', 'n', 'e', 't', '"', '\r' }; */ /* int [] s8 = { 'A', 'T', 'D', '*', '9', '9', '*', '*', '*', '1', '#', '\r' }; int [] s9 = { 'A', 'T', '\\', 'Q', '3', '\r' }; */ } /** * wait seconds and drop IP packets */ void waitSec(int t) { int timer = Timer.getTimeoutMs(1000); for (int i=0; i<t; ++i) { while (!Timer.timeout(timer)) { rth.waitForNextPeriod(); } timer = Timer.getTimeoutMs(1000); dropIp(); } } /** * send a string to serial line buffer. * '|' has special meaning: wait one second. */ boolean wrString(StringBuffer s) { int i, j, k, val; i = ser.txFreeCnt(); j = s.length(); if (j>i) return false;Dbg.wr('\''); for (i=0; i<j; ++i) { val = s.charAt(i); if (val=='|') { waitSec(2); // for shure if send buffer is full } else { ser.wr(val);Dbg.wr(val); } }Dbg.wr('\'');Dbg.wr('\n'); return true; } boolean sendWait(String snd, String rcv, int timeout) { strBuf.setLength(0); strBuf.append(snd); return sendWait(strBuf, rcv, timeout); } /** * send a string and loop until rcv string arrives or it times out * timeout in seconds for receive string, is also used for send (if handshake lines are not set) * return false means timeout. */ boolean sendWait(StringBuffer snd, String rcv, int timeout) { timeout *= 1000; // // send string // int timer = Timer.getTimeoutMs(timeout); // use same timeout for send while (!wrString(snd)) { rth.waitForNextPeriod(); // wait till send buffer is free dropIp(); if (Timer.timeout(timer)) return false; // timeout on send means problem with handshake lines } if (rcv==null) return true; // no wait string, we're done int ptr = 0; int len = rcv.length(); // // now wait on response string // for (timer = Timer.getTimeoutMs(timeout); !Timer.timeout(timer); ) { rth.waitForNextPeriod(); dropIp(); for (int i = ser.rxCnt(); i>0; --i) { int val = ser.rd();Dbg.wr(val); if (val == rcv.charAt(ptr)) { ++ptr; if (ptr==len) {Dbg.wr('\n'); waitSec(1); return true; // we're done } } else { ptr = 0; // reset match pointer } } }Dbg.wr('?');Dbg.wr('\n'); return false; // timeout expired } private static int globTimer; // negotion send and ip-restart timer private static boolean lcpAck; private static boolean ipcpAck; /** * do the modem stuff till CONNECT */ void modemInit() { ++connCount; for (;;++connCount) {System.out.print("Modem init ");System.out.println(connCount); Led.stopModem(); waitSec(5); Led.startModem(); waitSec(1); if (sendWait(ath, ok, 3)) { if (sendWait(flow, ok, 3)) { if (!sendWait(con, ok, 2)) { // when ERROR PIN is not set sendWait(pin, ok, 30); if (!sendWait(con, ok, 20)) { continue; // something really strange happend! } } if (sendWait(dial, connect, 10)) { break; } } }// waitSec(1); } state = MODEM_OK; globTimer = Timer.getTimeoutMs(NEG_SEND); lcpAck = false; ipcpAck = false; } /** * cancel connection. */ void modemHangUp() {// System.out.print("Modem hangup ");// System.out.println(connCount); ip = 0; // stop sending ip data reconnectRequest = false; disconnectRequest = false; state = INIT; rejCnt = 0; // flush buffer for (int i = ser.rxCnt(); i>0; --i) { ser.rd(); } for (;;) { if (sendWait(ath, ok, 3)) { break; } waitSec(3); } } private static final int INIT = 0; private static final int MODEM_OK = 1; private static final int LCP_SENT = 2; private static final int LCP_OK = 3; private static final int PAP_SENT = 4; private static final int PAP_OK = 5; private static final int IPCP_SENT = 6; private static final int IPCP_SENT2 = 7; private static final int IPCP_OK = 8; private static final int CONNECTED = 9; /** * establish a connetcion. */ void connect() { state = INIT; rejCnt = 0; lcpAck = false; ipcpAck = false; // // wait for startConnection(...) // while (!reconnectRequest) { rth.waitForNextPeriod(); } reconnectRequest = false; // // start the modem // modemInit(); // // now LCP negotiation // for (;;) { rth.waitForNextPeriod(); pppLoop(); if (state==MODEM_OK) { } if (rejCnt > MAX_REJ) {// System.out.print("1"); modemHangUp(); // start over modemInit(); } if (ready && scnt==0) { // one packet is read and send buffer is freedbgCon(); int prot = (rbuf[2]<<8)+rbuf[3]; int code = rbuf[4]; if (prot == LCP) { if (code == REQ) { if (checkOptions(LCP)) { lcpAck = true;; } else { ++rejCnt; } } else if (code==ACK && rbuf[5]==lcpId) { state = LCP_OK; } else if (code==TERM) {// System.out.print("2"); modemHangUp(); // start over modemInit(); } } else if (prot == PAP) { if (rbuf[4]==ACK && rbuf[5]==lcpId) { state = PAP_OK; } } else if (prot == IPCP) { if (code == REQ) { if (checkOptions(IPCP)) { ipcpAck = true;; } } else if (code == NAK) { // with this NAK we will get our IP address ip= (rbuf[10]<<24) + (rbuf[11]<<16) + (rbuf[12]<<8) + rbuf[13]; dbgIp(ip); makeIPCP(); state = IPCP_SENT2; } else if (code == ACK) { state = IPCP_OK; // nothing more to do ? state = CONNECTED;Dbg.wr('C');Dbg.wr('\n'); }//// des is net guat: kommt nur hierher, wenn der Sendbuffer frei ist!!!// } else if (prot == IP) { // we finally got an ip packet :-) readIp(); } cnt = 0; ready = false; } doSend(); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -