initial import

This commit is contained in:
2023-10-03 18:20:30 -07:00
commit 1092c73986
96 changed files with 46170 additions and 0 deletions

39
include/README Normal file
View File

@@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

47
include/connSettings.h Normal file
View File

@@ -0,0 +1,47 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
enum ConnFlag
{
FLAG_DISCONNECT_ON_EXIT=1,
FLAG_PETSCII=2,
FLAG_TELNET=4,
FLAG_ECHO=8,
FLAG_XONXOFF=16,
FLAG_SECURE=32,
FLAG_RTSCTS=64
};
class ConnSettings
{
public:
boolean petscii = false;
boolean telnet = false;
boolean echo = false;
boolean xonxoff = false;
boolean rtscts = false;
boolean secure = false;
ConnSettings(int flagBitmap);
ConnSettings(const char *dmodifiers);
ConnSettings(String modifiers);
int getBitmap();
int getBitmap(FlowControlType forceCheck);
void setFlag(ConnFlag flagMask, boolean newVal);
String getFlagString();
static void IPtoStr(IPAddress *ip, String &str);
static IPAddress *parseIP(const char *ipStr);
};

48
include/filelog.h Normal file
View File

@@ -0,0 +1,48 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
enum LogOutputState
{
LOS_NADA=0,
LOS_SocketIn=1,
LOS_SocketOut=2,
LOS_SerialIn=3,
LOS_SerialOut=4
};
static unsigned long expectedSerialTime = 1000;
static boolean logFileOpen = false;
static bool logFileDebug= false;
static File logFile;
static void logSerialOut(const uint8_t c);
static void logSocketOut(const uint8_t c);
static void logSerialIn(const uint8_t c);
static void logSocketIn(const uint8_t c);
static void logPrint(const char* msg);
static void logPrintln(const char* msg);
static void logPrintf(const char* format, ...);
static void logPrintfln(const char* format, ...);
static char *TOHEX(const char *s, char *hex, const size_t len);
static char *TOHEX(long a);
static char *TOHEX(int a);
static char *TOHEX(unsigned int a);
static char *TOHEX(unsigned long a);
static char *tohex(uint8_t a);
static char *TOHEX(uint8_t a);
static uint8_t FROMHEX(uint8_t a1, uint8_t a2);
static char *FROMHEX(const char *hex, char *s, const size_t len);

75
include/pet2asc.h Normal file
View File

@@ -0,0 +1,75 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifdef ZIMODEM_ESP32
# include <WiFi.h>
# define ENC_TYPE_NONE WIFI_AUTH_OPEN
# include <HardwareSerial.h>
# include <SPIFFS.h>
# include <Update.h>
# include "SD.h"
# include "SPI.h"
# include "driver/uart.h"
static HardwareSerial HWSerial(UART_NUM_2);
#else
# include "ESP8266WiFi.h"
# define HWSerial Serial
#endif
#include <FS.h>
char petToAsc(char c);
bool ascToPet(char *c, Stream *stream);
char ascToPetcii(char c);
bool handleAsciiIAC(char *c, Stream *stream);
static void setCharArray(char **target, const char *src)
{
if(src == NULL)
return;
if(*target != NULL)
free(*target);
*target = (char *)malloc(strlen(src)+1);
strcpy(*target,src);
}
static void freeCharArray(char **arr)
{
if(*arr == NULL)
return;
free(*arr);
*arr = NULL;
}
static int modifierCompare(const char *match1, const char *match2)
{
if(strlen(match1) != strlen(match2))
return -1;
for(int i1=0;i1<strlen(match1);i1++)
{
char c1=tolower(match1[i1]);
bool found=false;
for(int i2=0;i2<strlen(match2);i2++)
{
char c2=tolower(match2[i2]);
found = found || (c1==c2);
}
if(!found)
return -1;
}
return 0;
}

35
include/phonebook.h Normal file
View File

@@ -0,0 +1,35 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
class PhoneBookEntry
{
public:
unsigned long number;
const char *address;
const char *modifiers;
const char *notes;
PhoneBookEntry *next = null;
PhoneBookEntry(unsigned long phnum, const char *addr, const char *mod, const char *note);
~PhoneBookEntry();
static void loadPhonebook();
static void clearPhonebook();
static void savePhonebook();
static bool checkPhonebookEntry(String cmd);
static PhoneBookEntry *findPhonebookEntry(long number);
static PhoneBookEntry *findPhonebookEntry(String number);
};

44
include/proto_ftp.h Normal file
View File

@@ -0,0 +1,44 @@
#ifdef INCLUDE_SD_SHELL
#ifndef ZIMODEM_PROTO_FTP
#define ZIMODEM_PROTO_FTP
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
class FTPHost
{
public:
char *hostIp = 0;
int port = 0;
bool doSSL = false;
char *username = 0;
char *pw = 0;
char *path = 0;
char *file = 0;
~FTPHost();
bool doGet(FS *fs, const char *localpath, const char *remotepath);
bool doPut(File &f, const char *remotepath);
bool doLS(ZSerial *serial, const char *remotepath);
bool parseUrl(uint8_t *vbuf, char **req);
void fixPath(const char *remotepath);
};
FTPHost *makeFTPHost(bool isUrl, FTPHost **host, uint8_t *buf, char **req);
bool parseFTPUrl(uint8_t *vbuf, char **hostIp, char **req, int *port, bool *doSSL, char **username, char **pw);
bool doFTPGet(FS *fs, const char *hostIp, int port, const char *localpath, const char *remotepath, const char *username, const char *pw, const bool doSSL);
bool doFTPPut(File &f, const char *hostIp, int port, const char *remotepath, const char *username, const char *pw, const bool doSSL);
bool doFTPLS(ZSerial *serial, const char *hostIp, int port, const char *remotepath, const char *username, const char *pw, const bool doSSL);
#endif
#endif

84
include/proto_hostcm.h Normal file
View File

@@ -0,0 +1,84 @@
#ifdef INCLUDE_SD_SHELL
#ifdef INCLUDE_HOSTCM
/* Converted from source reverse engineered from SP9000 roms by Rob Ferguson */
#include <FS.h>
# define HCM_BUFSIZ 104
# define HCM_SENDBUF (208/2 - 6)
# define HCM_FNSIZ 32
# define HCM_MAXFN 16
typedef struct _HCMFile
{
char descriptor;
File f;
uint8_t mode;
uint8_t format;
uint8_t type;
int reclen;
char filename[HCM_FNSIZ+1];
struct _HCMFile *nxt;
} HCMFile;
class HostCM
{
private:
ZSerial hserial;
const struct _HCOpts
{
unsigned int speed = 15; //B9600
unsigned int parity = 0;// ?!
unsigned int stopb=0;
unsigned char lineend=0xd;
unsigned char prompt=0x11;
unsigned char response=0x13;
unsigned char ext=0;
} opt PROGMEM;
uint8_t outbuf[HCM_BUFSIZ];
int odex = 0;
uint8_t inbuf[HCM_BUFSIZ+1];
int idex = 0;
bool aborted = false;
unsigned long lastNonPlusTm = 0;
unsigned int plussesInARow = 0;
unsigned long plusTimeExpire = 0;
HCMFile files[HCM_MAXFN];
FS *hFS = &SD;
File openDirF = (File)0;
File renameF = (File)0;
char checksum(uint8_t *b, int n);
void checkDoPlusPlusPlus(const int c, const unsigned long tm);
bool checkPlusPlusPlusExpire(const unsigned long tm);
void sendNAK();
void sendACK();
void sendError(const char* format, ...);
bool closeAllFiles();
HCMFile *addNewFileEntry();
void delFileEntry(HCMFile *e);
HCMFile *getFileByDescriptor(char c);
int numOpenFiles();
void protoOpenFile();
void protoCloseFile();
void protoPutToFile();
void protoGetFileBytes();
void protoOpenDir();
void protoNextDirFile();
void protoCloseDir();
void protoSetRenameFile();
void protoFinRenameFile();
void protoEraseFile();
void protoSeekFile();
public:
void receiveLoop();
bool isAborted();
HostCM(FS *fs);
~HostCM();
};
#endif
#endif

22
include/proto_http.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef ZIMODEM_PROTO_HTTP
#define ZIMODEM_PROTO_HTTP
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
bool parseWebUrl(uint8_t *vbuf, char **hostIp, char **req, int *port, bool *doSSL);
bool doWebGetBytes(const char *hostIp, int port, const char *req, const bool doSSL, uint8_t *buf, int *bufSize);
WiFiClient *doWebGetStream(const char *hostIp, int port, const char *req, bool doSSL, uint32_t *responseSize);
bool doWebGet(const char *hostIp, int port, FS *fs, const char *filename, const char *req, const bool doSSL);
#endif

155
include/proto_kermit.h Normal file
View File

@@ -0,0 +1,155 @@
#include <FS.h>
class KModem
{
private:
static const int MAXPACKSIZ = 94; /* Maximum packet size */
static const int MAXTRY = 20; /* Times to retry a packet */
static const int MYTIME = 10; /* (10) Seconds after which I should be timed out */
static const int MAXTIM = 60; /* (60) Maximum timeout interval */
static const int MINTIM = 2; /* (2) Minumum timeout interval */
static const char MYQUOTE ='#'; /* Quote character I will use */
static const int MYPAD = 0; /* Number of padding characters I will need */
static const int MYPCHAR = 0; /* Padding character I need (NULL) */
static const char MYEOL = '\n'; /* End-Of-Line character I need */
static const char SOH = 1; /* Start of header */
static const char CR = 13; /* ASCII Carriage Return */
static const char SP = 32; /* ASCII space */
static const char DEL = 127; /* Delete (rubout) */
static const char ESCCHR = '^'; /* Default escape character for CONNECT */
static const char NUL = '\0'; /* Null character */
static const char FALSE = 0;
static const char TRUE = -1;
int size=0, /* Size of present data */
rpsiz=0, /* Maximum receive packet size */
spsiz=0, /* Maximum send packet size */
pad=0, /* How much padding to send */
timint=0, /* Timeout for foreign host on sends */
n=0, /* Packet number */
numtry=0, /* Times this packet retried */
oldtry=0, /* Times previous packet retried */
image=1, /* -1 means 8-bit mode */
debug=99, /* indicates level of debugging output (0=none) */
filecount=0, /* Number of files left to send */
filenum=0,
mflg=0, /* Flag for MacKermit mode */
xflg=0; /* flag for xmit directory structure */
char state, /* Present state of the automaton */
padchar, /* Padding character to send */
eol, /* End-Of-Line character to send */
escchr, /* Connect command escape character */
quote, /* Quote character in incoming data */
*filnam, /* Current file name */
*filnamo, /* File name sent */
*ttyline, /* Pointer to tty line */
recpkt[MAXPACKSIZ], /* Receive packet buffer */
packet[MAXPACKSIZ], /* Packet buffer */
ldata[1024]; /* First line of data to send over connection */
String **filelist = 0;
int (*recvChar)(ZSerial *ser, int);
void (*sendChar)(ZSerial *ser, char);
bool (*dataHandler)(File *kfp, unsigned long number, char *buffer, int len);
void flushinput();
void rpar(char data[]);
void spar(char data[]);
int gnxtfl();
void bufemp(char buffer[], int len);
void prerrpkt(char *msg);
int bufill(char buffer[]);
int rpack(int *len, int *num, char *data);
int spack(char type, int num, int len, char *data);
char rdata();
char rinit();
char rfile();
char sfile();
char sinit();
char sdata();
char sbreak();
char seof();
bool kfpClosed = true;
String *errStr = 0;
public:
String rootpath = "";
FS *kfileSystem = &SD;
File kfp;
ZSerial kserial;
KModem(FlowControlType commandFlow,
int (*recvChar)(ZSerial *ser, int),
void (*sendChar)(ZSerial *ser, char),
bool (*dataHandler)(File *kfp, unsigned long, char*, int),
String &errors);
void setTransmitList(String **fileList, int numFiles);
bool receive();
bool transmit();
};
static int kReceiveSerial(ZSerial *ser, int del)
{
unsigned long end=millis() + (del * 1000L);
while(millis() < end)
{
serialOutDeque();
if(ser->available() > 0)
{
int c=ser->read();
logSerialIn(c);
return c;
}
yield();
}
return -1;
}
static void kSendSerial(ZSerial *ser, char c)
{
ser->write((uint8_t)c);
ser->flush();
}
static bool kUDataHandler(File *kfp, unsigned long number, char *buf, int sz)
{
for(int i=0;i<sz;i++)
kfp->write((uint8_t)buf[i]);
return true;
}
static bool kDDataHandler(File *kfp, unsigned long number, char *buf, int sz)
{
for(int i=0;i<sz;i++)
{
int c=kfp->read();
if(c<0)
{
if(i==0)
return false;
buf[i] = (char)26;
}
else
buf[i] = (char)c;
}
return true;
}
static boolean kDownload(FlowControlType commandFlow, FS &fs, String **fileList, int fileCount, String &errors)
{
KModem kmo(commandFlow, kReceiveSerial, kSendSerial, kDDataHandler, errors);
kmo.kfileSystem = &fs;
kmo.setTransmitList(fileList,fileCount);
bool result = kmo.transmit();
return result;
}
static boolean kUpload(FlowControlType commandFlow, FS &fs, String rootPath, String &errors)
{
KModem kmo(commandFlow, kReceiveSerial, kSendSerial, kUDataHandler, errors);
kmo.kfileSystem = &fs;
kmo.rootpath = rootPath;
bool result = kmo.receive();
return result;
}

21
include/proto_ping.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef ZIMODEM_PROTO_PING
#define ZIMODEM_PROTO_PING
#ifdef INCLUDE_PING
/*
Copyright 2023-2023 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
int ping(char *host);
#endif
#endif

140
include/proto_xmodem.h Normal file
View File

@@ -0,0 +1,140 @@
/*
Copyright 2018-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <FS.h>
class XModem
{
typedef enum
{
Crc,
ChkSum
} transfer_t;
private:
//holds readed byte (due to dataAvail())
int byte;
//expected block number
unsigned char blockNo;
//extended block number, send to dataHandler()
unsigned long blockNoExt;
//retry counter for NACK
int retries;
//buffer
char buffer[128];
//repeated block flag
bool repeatedBlock;
File *xfile = null;
ZSerial xserial;
int (*recvChar)(ZSerial *ser, int);
void (*sendChar)(ZSerial *ser, char);
bool (*dataHandler)(File *xfile, unsigned long number, char *buffer, int len);
unsigned short crc16_ccitt(char *buf, int size);
bool dataAvail(int delay);
int dataRead(int delay);
void dataWrite(char symbol);
bool receiveFrameNo(void);
bool receiveData(void);
bool checkCrc(void);
bool checkChkSum(void);
bool receiveFrames(transfer_t transfer);
bool sendNack(void);
void init(void);
bool transmitFrames(transfer_t);
unsigned char generateChkSum(void);
public:
static const unsigned char XMO_NACK = 21;
static const unsigned char XMO_ACK = 6;
static const unsigned char XMO_SOH = 1;
static const unsigned char XMO_EOT = 4;
static const unsigned char XMO_CAN = 0x18;
static const int receiveDelay=7000;
static const int rcvRetryLimit = 10;
XModem(File &f,
FlowControlType commandFlow,
int (*recvChar)(ZSerial *ser, int),
void (*sendChar)(ZSerial *ser, char),
bool (*dataHandler)(File *xfile, unsigned long, char*, int));
bool receive();
bool transmit();
};
static int xReceiveSerial(ZSerial *ser, int del)
{
unsigned long end=micros() + (del * 1000L);
while(micros() < end)
{
serialOutDeque();
if(ser->available() > 0)
{
int c=ser->read();
logSerialIn(c);
return c;
}
yield();
}
return -1;
}
static void xSendSerial(ZSerial *ser, char c)
{
ser->write((uint8_t)c);
ser->flush();
}
static bool xUDataHandler(File *xfile, unsigned long number, char *buf, int sz)
{
for(int i=0;i<sz;i++)
xfile->write((uint8_t)buf[i]);
return true;
}
static bool xDDataHandler(File *xfile, unsigned long number, char *buf, int sz)
{
for(int i=0;i<sz;i++)
{
int c=xfile->read();
if(c<0)
{
if(i==0)
return false;
buf[i] = (char)26;
}
else
buf[i] = (char)c;
}
return true;
}
static boolean xDownload(FlowControlType commandFlow, File &f, String &errors)
{
XModem xmo(f,commandFlow, xReceiveSerial, xSendSerial, xDDataHandler);
bool result = xmo.transmit();
return result;
}
static boolean xUpload(FlowControlType commandFlow, File &f, String &errors)
{
XModem xmo(f,commandFlow, xReceiveSerial, xSendSerial, xUDataHandler);
bool result = xmo.receive();
return result;
}

504
include/proto_zmodem.h Normal file
View File

@@ -0,0 +1,504 @@
/*
* zmodem.h
* zmodem constants
* (C) Mattheij Computer Service 1994
*
* Date: Thu, 19 Nov 2015 10:10:02 +0100
* From: Jacques Mattheij
* Subject: Re: zmodem license
* To: Stephen Hurd, Fernando Toledo
* CC: Rob Swindell
*
* Hello there to all of you,
*
* So, this email will then signify as the transfer of any and all rights I
* held up to this point with relation to the copyright of the zmodem
* package as released by me many years ago and all associated files to
* Stephen Hurd. Fernando Toledo and Rob Swindell are named as
* witnesses to this transfer.
*
* ...
*
* best regards,
*
* Jacques Mattheij
*/
/* $Id: zmodem.h,v 1.55 2018/02/01 08:20:19 deuce Exp $ */
#ifndef _ZMODEM_H
#define _ZMODEM_H
#define ZMODEM_FILE_SIZE_MAX 0xffffffff /* 32-bits, blame Chuck */
/*
* ascii constants
*/
#define BOOL bool
#define BYTE uint8_t
#define uchar uint8_t
#define MAX_PATH 253
#define NOINP -1 /* input buffer empty (incom only) */
#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
#define ZMO_DLE 0x10
#define ZMO_XON 0x11
#define ZMO_XOFF 0x13
#define ZMO_CAN 0x18
#ifndef INT_TO_BOOL
#define INT_TO_BOOL(x) ((x)?ZTRUE:ZFALSE)
#endif
#define ZFALSE 0
#define ZTRUE 1
#define TERMINATE(str) str[sizeof(str)-1]=0
/* This is a bound-safe version of strcpy basically - only works with fixed-length arrays */
#ifdef SAFECOPY_USES_SPRINTF
#define SAFECOPY(dst,src) sprintf(dst,"%.*s",(int)sizeof(dst)-1,src)
#else /* strncpy is faster */
#define SAFECOPY(dst,src) (strncpy(dst,src,sizeof(dst)), TERMINATE(dst))
#endif
/*
* zmodem constants
*/
#define ZBLOCKLEN 1024 /* "true" Zmodem max subpacket length */
#define ZMAXHLEN 0x10 /* maximum header information length */
#define ZMAXSPLEN 0x400 /* maximum subpacket length */
#define ZPAD 0x2a /* pad character; begins frames */
#define ZDLE 0x18 /* ctrl-x zmodem escape */
#define ZDLEE 0x58 /* escaped ZDLE */
#define ZBIN 0x41 /* binary frame indicator (CRC16) */
#define ZHEX 0x42 /* hex frame indicator */
#define ZBIN32 0x43 /* binary frame indicator (CRC32) */
#define ZBINR32 0x44 /* run length encoded binary frame (CRC32) */
#define ZVBIN 0x61 /* binary frame indicator (CRC16) */
#define ZVHEX 0x62 /* hex frame indicator */
#define ZVBIN32 0x63 /* binary frame indicator (CRC32) */
#define ZVBINR32 0x64 /* run length encoded binary frame (CRC32) */
#define ZRESC 0x7e /* run length encoding flag / escape character */
/*
* zmodem frame types
*/
#define ZRQINIT 0x00 /* request receive init (s->r) */
#define ZRINIT 0x01 /* receive init (r->s) */
#define ZSINIT 0x02 /* send init sequence (optional) (s->r) */
#define ZACK 0x03 /* ack to ZRQINIT ZRINIT or ZSINIT (s<->r) */
#define ZFILE 0x04 /* file name (s->r) */
#define ZSKIP 0x05 /* skip this file (r->s) */
#define ZNAK 0x06 /* last packet was corrupted (?) */
#define ZABORT 0x07 /* abort batch transfers (?) */
#define ZFIN 0x08 /* finish session (s<->r) */
#define ZRPOS 0x09 /* resume data transmission here (r->s) */
#define ZDATA 0x0a /* data packet(s) follow (s->r) */
#define ZEOF 0x0b /* end of file reached (s->r) */
#define ZFERR 0x0c /* fatal read or write error detected (?) */
#define ZCRC 0x0d /* request for file CRC and response (?) */
#define ZCHALLENGE 0x0e /* security challenge (r->s) */
#define ZCOMPL 0x0f /* request is complete (?) */
#define ZCAN 0x10 /* pseudo frame;
other end cancelled session with 5* CAN */
#define ZFREECNT 0x11 /* request free bytes on file system (s->r) */
#define ZCOMMAND 0x12 /* issue command (s->r) */
#define ZSTDERR 0x13 /* output data to stderr (??) */
/*
* ZDLE sequences
*/
#define ZCRCE 0x68 /* CRC next, frame ends, header packet follows */
#define ZCRCG 0x69 /* CRC next, frame continues nonstop */
#define ZCRCQ 0x6a /* CRC next, frame continuous, ZACK expected */
#define ZCRCW 0x6b /* CRC next, frame ends, ZACK expected */
#define ZRUB0 0x6c /* translate to rubout 0x7f */
#define ZRUB1 0x6d /* translate to rubout 0xff */
/*
* frame specific data.
* entries are prefixed with their location in the header array.
*/
/*
* Byte positions within header array
*/
#define FTYPE 0 /* frame type */
#define ZF0 4 /* First flags byte */
#define ZF1 3
#define ZF2 2
#define ZF3 1
#define ZP0 1 /* Low order 8 bits of position */
#define ZP1 2
#define ZP2 3
#define ZP3 4 /* High order 8 bits of file position */
/*
* ZRINIT frame
* zmodem receiver capability flags
*/
#define ZF0_CANFDX 0x01 /* Receiver can send and receive true full duplex */
#define ZF0_CANOVIO 0x02 /* receiver can receive data during disk I/O */
#define ZF0_CANBRK 0x04 /* receiver can send a break signal */
#define ZF0_CANCRY 0x08 /* Receiver can decrypt DONT USE */
#define ZF0_CANLZW 0x10 /* Receiver can uncompress DONT USE */
#define ZF0_CANFC32 0x20 /* Receiver can use 32 bit Frame Check */
#define ZF0_ESCCTL 0x40 /* Receiver expects ctl chars to be escaped */
#define ZF0_ESC8 0x80 /* Receiver expects 8th bit to be escaped */
#define ZF1_CANVHDR 0x01 /* Variable headers OK */
/*
* ZSINIT frame
* zmodem sender capability
*/
#define ZF0_TESCCTL 0x40 /* Transmitter expects ctl chars to be escaped */
#define ZF0_TESC8 0x80 /* Transmitter expects 8th bit to be escaped */
#define ZATTNLEN 0x20 /* Max length of attention string */
#define ALTCOFF ZF1 /* Offset to alternate canit string, 0 if not used */
/*
* ZFILE frame
*/
/*
* Conversion options one of these in ZF0
*/
#define ZF0_ZCBIN 1 /* Binary transfer - inhibit conversion */
#define ZF0_ZCNL 2 /* Convert NL to local end of line convention */
#define ZF0_ZCRESUM 3 /* Resume interrupted file transfer */
/*
* Management include options, one of these ored in ZF1
*/
#define ZF1_ZMSKNOLOC 0x80 /* Skip file if not present at rx */
#define ZF1_ZMMASK 0x1f /* Mask for the choices below */
#define ZF1_ZMNEWL 1 /* Transfer if source newer or longer */
#define ZF1_ZMCRC 2 /* Transfer if different file CRC or length */
#define ZF1_ZMAPND 3 /* Append contents to existing file (if any) */
#define ZF1_ZMCLOB 4 /* Replace existing file */
#define ZF1_ZMNEW 5 /* Transfer if source newer */
#define ZF1_ZMDIFF 6 /* Transfer if dates or lengths different */
#define ZF1_ZMPROT 7 /* Protect destination file */
#define ZF1_ZMCHNG 8 /* Change filename if destination exists */
/*
* Transport options, one of these in ZF2
*/
#define ZF2_ZTNOR 0 /* no compression */
#define ZF2_ZTLZW 1 /* Lempel-Ziv compression */
#define ZF2_ZTRLE 3 /* Run Length encoding */
/*
* Extended options for ZF3, bit encoded
*/
#define ZF3_ZCANVHDR 0x01 /* Variable headers OK */
/* Receiver window size override */
#define ZF3_ZRWOVR 0x04 /* byte position for receive window override/256 */
#define ZF3_ZXSPARS 0x40 /* encoding for sparse file operations */
/*
* ZCOMMAND frame
*/
#define ZF0_ZCACK1 0x01 /* Acknowledge, then do command */
typedef struct {
BYTE rxd_header[ZMAXHLEN]; /* last received header */
int rxd_header_len; /* last received header size */
uint32_t rxd_header_pos; /* last received header position value */
/*
* receiver capability flags
* extracted from the ZRINIT frame as received
*/
BOOL can_full_duplex;
BOOL can_overlap_io;
BOOL can_break;
BOOL can_fcs_32;
BOOL want_fcs_16;
BOOL escape_ctrl_chars;
BOOL escape_8th_bit;
/*
* file management options.
* only one should be on
*/
int management_newer;
int management_clobber;
int management_protect;
/* from zmtx.c */
BYTE tx_data_subpacket[8192];
BYTE rx_data_subpacket[8192]; /* zzap = 8192 */
char current_file_name[MAX_PATH+1];
int64_t current_file_size;
int64_t current_file_pos;
time_t current_file_time;
unsigned current_file_num;
unsigned total_files;
int64_t total_bytes;
unsigned files_remaining;
int64_t bytes_remaining;
int64_t transfer_start_pos;
time_t transfer_start_time;
int receive_32bit_data;
int use_crc16;
int32_t ack_file_pos; /* file position used in acknowledgement of correctly */
/* received data subpackets */
int last_sent;
int n_cans;
/* Stuff added by RRS */
/* Status */
BOOL cancelled;
BOOL local_abort;
BOOL file_skipped;
BOOL no_streaming;
BOOL frame_in_transit;
unsigned recv_bufsize; /* Receiver specified buffer size */
int32_t crc_request;
unsigned errors;
unsigned consecutive_errors;
/* Configuration */
BOOL escape_telnet_iac;
unsigned init_timeout;
unsigned send_timeout;
unsigned recv_timeout;
unsigned crc_timeout;
unsigned max_errors;
unsigned block_size;
unsigned max_block_size;
int64_t max_file_size; /* 0 = unlimited */
int *log_level;
/* error C2520: conversion from unsigned __int64 to double not implemented, use signed __int64 */
void* cbdata;
} zmodem_t;
class ZModem
{
public:
ZModem(FS *zfs, void* cbdata);
~ZModem();
BOOL send_file( char* name, File* fp, BOOL request_init, time_t* start, uint64_t* bytes_sent);
int get_zfin();
int recv_init();
int lputs(void* unused, int level, const char* str);
int lprintf(int level, const char *fmt, ...);
int send_zabort();
int send_zfin();
int recv_files(const char* download_dir, uint64_t* bytes_received);
unsigned recv_file_data( File*, int64_t offset);
zmodem_t *zm=0;
ZSerial zserial;
FS *zfileSystem=0;
private:
char* ver(char *buf);
const char* source(void);
int rx();
int tx(BYTE ch);
int send_ack( int32_t pos);
int send_nak();
int send_zskip();
int send_zrinit();
int send_pos_header(int type, int32_t pos, BOOL hex);
int get_zrinit();
BOOL get_crc( int32_t length, uint32_t* crc);
void parse_zrinit();
void parse_zfile_subpacket();
int recv_file_frame(File* fp);
int recv_header_and_check();
int send_hex(uchar val);
int send_padded_zdle();
int send_hex_header(unsigned char * p);
int send_bin32_header(unsigned char * p);
int send_bin16_header(unsigned char * p);
int send_bin_header(unsigned char * p);
int send_data32(uchar subpkt_type, unsigned char * p, size_t l);
int send_data16(uchar subpkt_type,unsigned char * p, size_t l);
int send_data(uchar subpkt_type, unsigned char * p, size_t l);
int send_data_subpkt(uchar subpkt_type, unsigned char * p, size_t l);
int data_waiting(unsigned timeout);
void recv_purge();
void flush();
int send_raw(unsigned char ch);
int send_esc(unsigned char c);
int recv_data32(unsigned char * p, unsigned maxlen, unsigned* l);
int recv_data16(register unsigned char* p, unsigned maxlen, unsigned* l);
int recv_data(unsigned char* p, size_t maxlen, unsigned* l, BOOL ack);
BOOL recv_subpacket(BOOL ack);
int recv_nibble();
int recv_hex();
int recv_raw();
BOOL recv_bin16_header();
BOOL recv_hex_header();
BOOL recv_bin32_header();
int recv_header_raw(int errors);
int recv_header();
BOOL request_crc(int32_t length);
BOOL recv_crc(uint32_t* crc);
BOOL handle_zrpos(uint64_t* pos);
BOOL handle_zack();
BOOL is_connected();
BOOL is_cancelled();
int send_from(File* fp, uint64_t pos, uint64_t* sent);
int send_znak();
int send_zeof(uint32_t pos);
void progress(void* cbdata, int64_t current_pos);
int send_byte(void* unused, uchar ch, unsigned timeout);
int recv_byte(void* unused, unsigned timeout); /* seconds */
ulong frame_pos(int type);
char* getfname(const char* path);
};
static ZModem *initZSerial(FS &fs, FlowControlType commandFlow)
{
ZModem *modem = new ZModem(&SD, NULL);
modem->zserial.setFlowControlType(FCT_DISABLED);
if(commandFlow==FCT_RTSCTS)
modem->zserial.setFlowControlType(FCT_RTSCTS);
else
modem->zserial.setFlowControlType(FCT_NORMAL);
modem->zserial.setPetsciiMode(false);
modem->zserial.setXON(true);
return modem;
}
static boolean zDownload(FlowControlType flow, FS &fs, String filePath, String &errors)
{
time_t starttime = 0;
uint64_t bytes_sent=0;
BOOL success=ZFALSE;
char filePathC[MAX_PATH];
File F;
ZModem *modem = initZSerial(fs, flow);
//static int send_files(char** fname, uint fnames)
F=modem->zfileSystem->open(filePath);
modem->zm->files_remaining = 1;
modem->zm->bytes_remaining = F.size();
strcpy(filePathC,filePath.c_str());
success=modem->send_file(filePathC, &F, ZTRUE, &starttime, &bytes_sent);
if(success)
modem->get_zfin();
F.close();
modem->zserial.flushAlways();
delete modem;
return (success==ZTRUE) && (modem->zm->cancelled==ZFALSE);
}
static boolean zUpload(FlowControlType flow, FS &fs, String dirPath, String &errors)
{
BOOL success=ZFALSE;
int i;
char str[MAX_PATH];
File fp;
int err;
ZModem *modem = initZSerial(fs,flow);
//static int receive_files(char** fname_list, int fnames)
//TODO: loop might be necc around here, for multiple files?
i=modem->recv_init();
if(modem->zm->cancelled || (i<0))
{
delete modem;
return ZFALSE;
}
switch(i) {
case ZFILE:
//SAFECOPY(fname,zm.current_file_name);
//file_bytes = zm.current_file_size;
//ftime = zm.current_file_time;
//total_files = zm.files_remaining;
//total_bytes = zm.bytes_remaining;
break;
case ZFIN:
case ZCOMPL:
delete modem;
return ZTRUE; // was (!success)
default:
delete modem;
return ZFALSE;
}
strcpy(str,dirPath.c_str());
if(str[strlen(str)-1]!='/')
{
str[strlen(str)]='/';
str[strlen(str)+1]=0;
}
strcpy(str+strlen(str),modem->zm->current_file_name);
fp = modem->zfileSystem->open(str,FILE_WRITE);
if(!fp)
{
modem->lprintf(LOG_ERR,"Error %d creating %s",errno,str);
modem->send_zabort();
//zmodem_send_zskip(); //TODO: for when we move to multiple files
//continue;
delete modem;
return ZFALSE;
}
err=modem->recv_file_data(&fp,0);
if(err<=modem->zm->max_errors && !modem->zm->cancelled)
success=ZTRUE;
if(success)
modem->send_zfin();
fp.close();
if(modem->zm->local_abort)
{
modem->lprintf(LOG_ERR,"Locally aborted, sending cancel to remote");
modem->send_zabort();
delete modem;
return ZFALSE;
}
modem->zserial.flushAlways();
delete modem;
return (success == ZTRUE);
}
#endif

174
include/rt_clock.h Normal file
View File

@@ -0,0 +1,174 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <WiFiUdp.h>
static const char *TimeZones[243][2] PROGMEM = { {"UTC","0"},
{"A","1"},{"CDT","10:30"},{"ACST","9:30"},{"ACT","-5"},
{"ACT","9:30/10:30"},{"ACWST","8:45"},{"ADT","3"},{"ADT","-3"},
{"AEDT","11"},{"AEST","10"},{"AET","11"},{"AFT","4:30"},
{"AKDT","-8"},{"AKST","-9"},{"ALMT","6"},{"AMST","-3"},{"AMST","5"},
{"AMT","-4"},{"AMT","4"},{"ANAST","12"},{"ANAT","12"},{"AQTT","5"},
{"ART","-3"},{"AST","2"},{"AST","-4"},{"AT","-4/-3"},{"AWDT","9"},
{"AWST","8"},{"AZOST","0"},{"AZOT","-1"},{"AZST","5"},{"AZT","4"},
{"AOE","-12"},{"B","2"},{"BNT","8"},{"BOT","-4"},{"BRST","-2"},
{"BRT","-3"},{"BST","6"},{"BST","11"},{"BST","1"},{"BTT","6"},
{"C","3"},{"CAST","8"},{"CAT","2"},{"CCT","6:30"},{"CDT","-5"},
{"CDT","-4"},{"CEST","2"},{"CET","1"},{"CHADT","13:45"},
{"CHAST","12:45"},{"CHOST","9"},{"CHOT","8"},{"CHUT","10"},
{"CIDST","-4"},{"CIST","-5"},{"CKT","-10"},{"CLST","-3"},
{"CLT","-4"},{"COT","-5"},{"CST","-6"},{"CST","8"},{"CST","-5"},
{"CT","-6/-5"},{"CVT","-1"},{"CXT","7"},{"ChST","10"},{"D","4"},
{"DAVT","7"},{"DDUT","10"},{"E","5"},{"EASST","-5"},{"EAST","-6"},
{"EAT","3"},{"ECT","-5"},{"EDT","-4"},{"EEST","3"},{"EET","2"},
{"EGST","0"},{"EGT","-1"},{"EST","-5"},{"ET","-5/-4"},{"F","6"},
{"FET","3"},{"FJST","13"},{"FJT","12"},{"FKST","-3"},{"FKT","-4"},
{"FNT","-2"},{"G","7"},{"GALT","-6"},{"GAMT","-9"},{"GET","4"},
{"GFT","-3"},{"GILT","12"},{"GMT","0"},{"GST","4"},{"GST","-2"},
{"GYT","-4"},{"H","8"},{"HADT","-9"},{"HAST","-10"},{"HKT","8"},
{"HOVST","8"},{"HOVT","7"},{"I","9"},{"ICT","7"},{"IDT","3"},
{"IOT","6"},{"IRDT","4:30"},{"IRKST","9"},{"IRKT","8"},
{"IRST","3:30"},{"IST","5:30"},{"IST","1"},{"IST","2"},{"JST","9"},
{"K","10"},{"KGT","6"},{"KOST","11"},{"KRAST","8"},{"KRAT","7"},
{"KST","9"},{"KUYT","4"},{"L","11"},{"LHDT","11"},{"LHST","10:30"},
{"LINT","14"},{"M","12"},{"MAGST","12"},{"MAGT","11"},{"MART","-9:30"},
{"MAWT","5"},{"MDT","-6"},{"MHT","12"},{"MMT","6:30"},{"MSD","4"},
{"MSK","3"},{"MST","-7"},{"MT","-7/-6"},{"MUT","4"},{"MVT","5"},
{"MYT","8"},{"N","-1"},{"NCT","11"},{"NDT","-2:30"},{"NFT","11"},
{"NOVST","7"},{"NOVT","6"},{"NPT","5:45"},{"NRT","12"},{"NST","-3:30"},
{"NUT","-11"},{"NZDT","13"},{"NZST","12"},{"O","-2"},{"OMSST","7"},
{"OMST","6"},{"ORAT","5"},{"P","-3"},{"PDT","-7"},{"PET","-5"},
{"PETST","12"},{"PETT","12"},{"PGT","10"},{"PHOT","13"},{"PHT","8"},
{"PKT","5"},{"PMDT","-2"},{"PMST","-3"},{"PONT","11"},{"PST","-8"},
{"PST","-8"},{"PT","-8/-7"},{"PWT","9"},{"PYST","-3"},{"PYT","-4"},
{"PYT","8:30"},{"Q","-4"},{"QYZT","6"},{"R","-5"},{"RET","4"},
{"ROTT","-3"},{"S","-6"},{"SAKT","11"},{"SAMT","4"},{"SAST","2"},
{"SBT","11"},{"SCT","4"},{"SGT","8"},{"SRET","11"},{"SRT","-3"},
{"SST","-11"},{"SYOT","3"},{"T","-7"},{"TAHT","-10"},{"TFT","5"},
{"TJT","5"},{"TKT","13"},{"TLT","9"},{"TMT","5"},{"TOST","14"},
{"TOT","13"},{"TRT","3"},{"TVT","12"},{"U","-8"},{"ULAST","9"},
{"ULAT","8"},{"UYST","-2"},{"UYT","-3"},{"UZT","5"},
{"V","-9"},{"VET","-4"},{"VLAST","11"},{"VLAT","10"},{"VOST","6"},
{"VUT","11"},{"W","-10"},{"WAKT","12"},{"WARST","-3"},{"WAST","2"},
{"WAT","1"},{"WEST","1"},{"WET","0"},{"WFT","12"},{"WGST","-2"},
{"WGT","-3"},{"WIB","7"},{"WIT","9"},{"WITA","8"},{"WST","14"},
{"WST","1"},{"WT","0"},{"X","-11"},{"Y","-12"},{"YAKST","10"},
{"YAKT","9"},{"YAPT","10"},{"YEKST","6"},{"YEKT","5"},{"Z","0"}
};
class DateTimeClock
{
public:
DateTimeClock(uint32_t epochSecs);
DateTimeClock();
DateTimeClock(int year, int month, int day, int hour, int min, int sec, int millis);
protected:
uint16_t year=0;
uint8_t month=0;
uint8_t day=0;
uint8_t hour=0;
uint8_t min=0;
uint8_t sec=0;
uint16_t milsec=0;
char str[55];
bool isLeapYear();
uint8_t getDaysInThisMonth();
public:
int getYear();
void setYear(int y);
void addYear(uint32_t y);
int getMonth();
void setMonth(int m);
void addMonth(uint32_t m);
int getDay();
void setDay(int d);
void addDay(uint32_t d);
int getHour();
void setHour(int h);
void addHour(uint32_t h);
int getMinute();
void setMinute(int mm);
void addMinute(uint32_t mm);
int getSecond();
void setSecond(int s);
void addSecond(uint32_t s);
int getMillis();;
void setMillis(int s);
void addMillis(uint64_t s);
void setByUnixEpoch(uint32_t unisex);
uint32_t getUnixEpoch();
int getDoWNumber();
const char *getDoW();
bool isInStandardTime();
bool isInDaylightSavingsTime();
void setTime(DateTimeClock &clock);
};
class RealTimeClock : DateTimeClock
{
public:
RealTimeClock(uint32_t epochSecs);
RealTimeClock();
RealTimeClock(int year, int month, int day, int hour, int min, int sec, int millis);
void tick();
bool isTimeSet();
bool reset();
int getTimeZoneCode();
void setTimeZoneCode(int val);
bool setTimeZone(String str);
String getFormat();
void setFormat(String fmt);
String getNtpServerHost();
void setNtpServerHost(String newHost);
bool isDisabled();
void setDisabled(bool tf);
void forceUpdate();
DateTimeClock &getCurrentTime();
String getCurrentTimeFormatted();
// should be private
private:
bool disabled = false;
DateTimeClock adjClock;
WiFiUDP udp;
bool udpStarted = false;
uint32_t lastMillis = 0;
uint32_t nextNTPMillis = 0;
int32_t ntpPeriodMillis = 60 * 1000; // every minute
int32_t ntpPeriodLongMillis = 5 * 60 * 60 * 1000; // every 5 hours
uint8_t tzCode = 0;
String format="%M/%d/%yyyy %h:%mm:%ss%aa %z";
String ntpServerName = "time.nist.gov";
void startUdp();
bool sendTimeRequest();
};

91
include/serout.h Normal file
View File

@@ -0,0 +1,91 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef ZHEADER_SEROUT_H
#define ZHEADER_SEROUT_H
#define DBG_BYT_CTR 20
#define SER_WRITE_BUFSIZE 4096
enum FlowControlType
{
FCT_RTSCTS=0,
FCT_NORMAL=1,
FCT_AUTOOFF=2,
FCT_MANUAL=3,
FCT_DISABLED=4,
FCT_INVALID=5
};
static bool enableRtsCts = true;
#ifdef ZIMODEM_ESP32
# define SER_BUFSIZE 0x7F
#else
# define SER_BUFSIZE 128
#endif
static uint8_t TBUF[SER_WRITE_BUFSIZE];
static char FBUF[256];
static int TBUFhead=0;
static int TBUFtail=0;
static int serialDelayMs = 0;
static void serialDirectWrite(uint8_t c);
static void serialOutDeque();
static int serialOutBufferBytesRemaining();
static void clearSerialOutBuffer();
class ZSerial : public Stream
{
private:
bool petsciiMode = false;
FlowControlType flowControlType=DEFAULT_FCT;
bool XON_STATE=true;
void enqueByte(uint8_t c);
public:
ZSerial();
void setPetsciiMode(bool petscii);
bool isPetsciiMode();
void setFlowControlType(FlowControlType type);
FlowControlType getFlowControlType();
void setXON(bool isXON);
bool isXON();
bool isSerialOut();
bool isSerialHalted();
bool isSerialCancelled();
bool isPacketOut();
int getConfigFlagBitmap();
void prints(String str);
void prints(const char *expr);
void printc(const char c);
void printc(uint8_t c);
virtual size_t write(uint8_t c);
size_t write(uint8_t *buf, int bufSz);
void printb(uint8_t c);
void printd(double f);
void printi(int i);
void printf(const char* format, ...);
void flush();
void flushAlways();
int availableForWrite();
char drainForXonXoff();
virtual int available();
virtual int read();
virtual int peek();
};
#endif

27
include/stringstream.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef _STRING_STREAM_H_INCLUDED_
#define _STRING_STREAM_H_INCLUDED_
class StringStream : public Stream
{
public:
StringStream(const String &s)
{
str = s;
position = 0;
}
// Stream methods
virtual int available() { return str.length() - position; }
virtual int read() { return position < str.length() ? str[position++] : -1; }
virtual int peek() { return position < str.length() ? str[position] : -1; }
virtual void flush() { };
// Print methods
virtual size_t write(uint8_t c) { str += (char)c; return 1;};
private:
String str;
int length;
int position;
};
#endif // _STRING_STREAM_H_INCLUDED_

123
include/wificlientnode.h Normal file
View File

@@ -0,0 +1,123 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#define PACKET_BUF_SIZE 256
#ifdef ZIMODEM_ESP32
# include <WiFiClientSecure.h>
#endif
#ifdef INCLUDE_SSH
# include "wifisshclient.h"
#endif
static WiFiClient *createWiFiClient(bool SSL)
{
#ifdef ZIMODEM_ESP32
if(SSL)
{
WiFiClientSecure *c = new WiFiClientSecure();
c->setInsecure();
return c;
}
else
#else
//WiFiClientSecure *c = new WiFiClientSecure();
//c->setInsecure();
#endif
return new WiFiClient();
}
typedef struct Packet
{
uint8_t num = 0;
uint16_t len = 0;
uint8_t buf[PACKET_BUF_SIZE] = {0};
};
class WiFiClientNode : public Stream
{
private:
void finishConnectionLink();
int flushOverflowBuffer();
void fillUnderflowBuf();
WiFiClient client;
WiFiClient *clientPtr;
bool answered=true;
int ringsRemain=0;
unsigned long nextRingMillis = 0;
unsigned long nextDisconnect = 0;
void constructNode();
void constructNode(char *hostIp, int newport, int flagsBitmap, int ringDelay);
void constructNode(char *hostIp, int newport, char *username, char *password, int flagsBitmap, int ringDelay);
public:
int id=0;
char *host;
int port;
bool wasConnected=false;
bool serverClient=false;
int flagsBitmap = 0;
char *delimiters = NULL;
char *maskOuts = NULL;
char *stateMachine = NULL;
char *machineState = NULL;
String machineQue = "";
uint8_t nextPacketNum=1;
uint8_t blankPackets=0;
struct Packet lastPacket[3]; // 0 = current buf, 1&2 are back-cache bufs
//struct Packet underflowBuf; // underflows no longer handled this way
WiFiClientNode *next = null;
WiFiClientNode(char *hostIp, int newport, int flagsBitmap);
WiFiClientNode(char *hostIp, int newport, char *username, char *password, int flagsBitmap);
WiFiClientNode(WiFiClient newClient, int flagsBitmap, int ringDelay);
~WiFiClientNode();
bool isConnected();
FlowControlType getFlowControl();
bool isPETSCII();
bool isEcho();
bool isTelnet();
bool isAnswered();
void answer();
int ringsRemaining(int delta);
unsigned long nextRingTime(long delta);
void markForDisconnect();
bool isMarkedForDisconnect();
bool isDisconnectedOnStreamExit();
void setDisconnectOnStreamExit(bool tf);
void setNoDelay(bool tf);
size_t write(uint8_t c);
size_t write(const uint8_t *buf, size_t size);
void print(String s);
int read();
int peek();
void flush();
void flushAlways();
int available();
int read(uint8_t *buf, size_t size);
String readLine(unsigned int timeout);
static int getNumOpenWiFiConnections();
static void checkForAutoDisconnections();
};

52
include/wifiservernode.h Normal file
View File

@@ -0,0 +1,52 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
static int WiFiNextClientId = 0;
class WiFiServerSpec
{
public:
int port;
int id;
int flagsBitmap = 0;
char *delimiters = NULL;
char *maskOuts = NULL;
char *stateMachine = NULL;
WiFiServerSpec();
WiFiServerSpec(WiFiServerSpec &copy);
~WiFiServerSpec();
WiFiServerSpec& operator=(const WiFiServerSpec&);
};
class WiFiServerNode : public WiFiServerSpec
{
public:
WiFiServer *server;
WiFiServerNode *next = null;
WiFiServerNode(int port, int flagsBitmap);
bool hasClient();
~WiFiServerNode();
static WiFiServerNode *FindServer(int port);
static void DestroyAllServers();
static bool ReadWiFiServer(File &f, WiFiServerSpec &node);
static void SaveWiFiServers();
static void RestoreWiFiServers();
};

79
include/wifisshclient.h Normal file
View File

@@ -0,0 +1,79 @@
#ifdef INCLUDE_SSH
/*
Copyright 2023-2023 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "Arduino.h"
#include "IPAddress.h"
#include <WiFi.h>
#include "src/libssh2/libssh2_config.h"
#include "src/libssh2/libssh2.h"
class WiFiSSHClient : public WiFiClient
{
protected:
String _username = "";
String _password = "";
libssh2_socket_t sock = null;
LIBSSH2_SESSION *session = null;
LIBSSH2_CHANNEL *channel = null;
static const size_t INTERNAL_BUF_SIZE = 1024;
size_t ibufSz = 0;
char ibuf[INTERNAL_BUF_SIZE];
bool finishLogin();
void closeSSH();
void intern_buffer_fill();
public:
WiFiSSHClient();
~WiFiSSHClient();
int connect(IPAddress ip, uint16_t port) override;
int connect(IPAddress ip, uint16_t port, int32_t timeout_ms) override;
int connect(const char *host, uint16_t port) override;
int connect(const char *host, uint16_t port, int32_t timeout_ms) override;
void setLogin(String username, String password);
int peek() override;
size_t write(uint8_t data) override;
size_t write(const uint8_t *buf, size_t size) override;
int available() override;
int read() override;
int read(uint8_t *buf, size_t size) override;
void flush() {}
void stop() override;
uint8_t connected() override;
int fd() const override;
operator bool()
{
return connected();
}
WiFiSSHClient &operator=(const WiFiSSHClient &other);
bool operator==(const bool value)
{
return bool() == value;
}
bool operator!=(const bool value)
{
return bool() != value;
}
bool operator==(const WiFiSSHClient &);
bool operator!=(const WiFiSSHClient &rhs)
{
return !this->operator==(rhs);
};
private:
};
#endif

61
include/zbrowser.h Normal file
View File

@@ -0,0 +1,61 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifdef INCLUDE_SD_SHELL
class ZBrowser : public ZMode
{
private:
enum ZBrowseState
{
ZBROW_MAIN=0,
} currState;
ZSerial serial;
void switchBackToCommandMode();
String makePath(String addendum);
String fixPathNoSlash(String path);
String stripDir(String path);
String stripFilename(String path);
String stripArgs(String line, String &argLetters);
String cleanOneArg(String line);
String cleanFirstArg(String line);
String cleanRemainArg(String line);
bool isMask(String mask);
bool matches(String fname, String mask);
void makeFileList(String ***l, int *n, String p, String mask, bool recurse);
void deleteFile(String fname, String mask, bool recurse);
void showDirectory(String path, String mask, String prefix, bool recurse);
void copyFiles(String source, String mask, String target, bool recurse, bool overwrite);
FTPHost *ftpHost = 0;
bool showMenu;
bool savedEcho;
String path="/";
String EOLN;
char EOLNC[5];
unsigned long lastNumber;
String lastString;
public:
~ZBrowser();
void switchTo();
void serialIncoming();
void loop();
void init();
void doModeCommand(String &line);
};
#endif

202
include/zcommand.h Normal file
View File

@@ -0,0 +1,202 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const int MAX_COMMAND_SIZE=256;
static const char *CONFIG_FILE_OLD = "/zconfig.txt";
static const char *CONFIG_FILE = "/zconfig_v2.txt";
#define ZI_STATE_MACHINE_LEN 7
#define DEFAULT_TERMTYPE "Zimodem"
#define DEFAULT_BUSYMSG "\r\nBUSY\r\n7\r\n"
static void parseHostInfo(uint8_t *vbuf, char **hostIp, int *port, char **username, char **password);
static bool validateHostInfo(uint8_t *vbuf);
enum ZResult
{
ZOK,
ZERROR,
ZCONNECT,
ZNOCARRIER,
ZNOANSWER,
ZIGNORE,
ZIGNORE_SPECIAL
};
enum ConfigOptions
{
CFG_WIFISSI=0,
CFG_WIFIPW=1,
CFG_BAUDRATE=2,
CFG_EOLN=3,
CFG_FLOWCONTROL=4,
CFG_ECHO=5,
CFG_RESP_SUPP=6,
CFG_RESP_NUM=7,
CFG_RESP_LONG=8,
CFG_PETSCIIMODE=9,
CFG_DCDMODE=10,
CFG_UART=11,
CFG_CTSMODE=12,
CFG_RTSMODE=13,
CFG_DCDPIN=14,
CFG_CTSPIN=15,
CFG_RTSPIN=16,
CFG_S0_RINGS=17,
CFG_S41_STREAM=18,
CFG_S60_LISTEN=19,
CFG_RIMODE=20,
CFG_DTRMODE=21,
CFG_DSRMODE=22,
CFG_RIPIN=23,
CFG_DTRPIN=24,
CFG_DSRPIN=25,
CFG_TIMEZONE=26,
CFG_TIMEFMT=27,
CFG_TIMEURL=28,
CFG_HOSTNAME=29,
CFG_PRINTDELAYMS=30,
CFG_PRINTSPEC=31,
CFG_TERMTYPE=32,
CFG_STATIC_IP=33,
CFG_STATIC_DNS=34,
CFG_STATIC_GW=35,
CFG_STATIC_SN=36,
CFG_BUSYMSG=37,
CFG_S62_TELNET=38,
CFG_LAST=38
};
const ConfigOptions v2HexCfgs[] = { CFG_WIFISSI, CFG_WIFIPW, CFG_TIMEZONE, CFG_TIMEFMT, CFG_TIMEURL,
CFG_PRINTSPEC, CFG_BUSYMSG, CFG_HOSTNAME, CFG_TERMTYPE, (ConfigOptions)255 };
enum BinType
{
BTYPE_NORMAL=0,
BTYPE_HEX=1,
BTYPE_DEC=2,
BTYPE_NORMAL_NOCHK=3,
BTYPE_NORMAL_PLUS=4,
BTYPE_HEX_PLUS=5,
BTYPE_DEC_PLUS=6,
BTYPE_INVALID=7
};
class ZCommand : public ZMode
{
friend class WiFiClientNode;
friend class ZConfig;
friend class ZBrowser;
#ifdef INCLUDE_IRCC
friend class ZIRCMode;
#endif
private:
char CRLF[4];
char LFCR[4];
char LF[2];
char CR[2];
char BS=8;
char ringCounter = 1;
ZSerial serial;
bool packetXOn = true;
BinType binType = BTYPE_NORMAL;
uint8_t nbuf[MAX_COMMAND_SIZE];
char hbuf[MAX_COMMAND_SIZE];
int eon=0;
int lastServerClientId = 0;
WiFiClientNode *current = null;
bool autoStreamMode=false;
bool telnetSupport=true;
bool preserveListeners=false;
unsigned long lastNonPlusTimeMs = 0;
unsigned long currentExpiresTimeMs = 0;
char *tempDelimiters = NULL;
char *tempMaskOuts = NULL;
char *tempStateMachine = NULL;
char *delimiters = NULL;
char *maskOuts = NULL;
char *stateMachine = NULL;
char *machineState = NULL;
String machineQue = "";
String previousCommand = "";
WiFiClientNode *nextConn=null;
int lastPacketId = -1;
byte CRC8(const byte *data, byte len);
void showInitMessage();
bool readSerialStream();
void clearPlusProgress();
bool checkPlusEscape();
String getNextSerialCommand();
ZResult doSerialCommand();
void setConfigDefaults();
void parseConfigOptions(String configArguments[]);
void setOptionsFromSavedConfig(String configArguments[]);
void reSaveConfig();
void reSendLastPacket(WiFiClientNode *conn, uint8_t which);
void acceptNewConnection();
void headerOut(const int channel, const int num, const int sz, const int crc8);
void sendConnectionNotice(int nodeId);
void sendNextPacket();
void connectionArgs(WiFiClientNode *c);
void updateAutoAnswer();
uint8_t *doStateMachine(uint8_t *buf, uint16_t *bufLen, char **machineState, String *machineQue, char *stateMachine);
uint8_t *doMaskOuts(uint8_t *buf, uint16_t *bufLen, char *maskOuts);
ZResult doWebDump(Stream *in, int len, const bool cacheFlag);
ZResult doWebDump(const char *filename, const bool cache);
ZResult doResetCommand();
ZResult doNoListenCommand();
ZResult doBaudCommand(int vval, uint8_t *vbuf, int vlen);
ZResult doTransmitCommand(int vval, uint8_t *vbuf, int vlen, bool isNumber, const char *dmodifiers, int *crc8);
ZResult doLastPacket(int vval, uint8_t *vbuf, int vlen, bool isNumber);
ZResult doConnectCommand(int vval, uint8_t *vbuf, int vlen, bool isNumber, const char *dmodifiers);
ZResult doWiFiCommand(int vval, uint8_t *vbuf, int vlen, bool isNumber, const char *dmodifiers);
ZResult doDialStreamCommand(unsigned long vval, uint8_t *vbuf, int vlen, bool isNumber, const char *dmodifiers);
ZResult doPhonebookCommand(unsigned long vval, uint8_t *vbuf, int vlen, bool isNumber, const char *dmodifiers);
ZResult doAnswerCommand(int vval, uint8_t *vbuf, int vlen, bool isNumber, const char *dmodifiers);
ZResult doHangupCommand(int vval, uint8_t *vbuf, int vlen, bool isNumber);
ZResult doEOLNCommand(int vval, uint8_t *vbuf, int vlen, bool isNumber);
ZResult doInfoCommand(int vval, uint8_t *vbuf, int vlen, bool isNumber);
ZResult doWebStream(int vval, uint8_t *vbuf, int vlen, bool isNumber, const char *filename, bool cache);
ZResult doUpdateFirmware(int vval, uint8_t *vbuf, int vlen, bool isNumber);
ZResult doTimeZoneSetupCommand(int vval, uint8_t *vbuf, int vlen, bool isNumber);
public:
int packetSize = 127;
bool suppressResponses;
bool numericResponses;
bool longResponses;
boolean doEcho;
String EOLN;
char EC='+';
char ECS[32];
ZCommand();
void loadConfig();
FlowControlType getFlowControlType();
int getConfigFlagBitmap();
void sendOfficialResponse(ZResult res);
void serialIncoming();
void loop();
void reset();
};

67
include/zconfigmode.h Normal file
View File

@@ -0,0 +1,67 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
class ZConfig : public ZMode
{
private:
enum ZConfigMenu
{
ZCFGMENU_MAIN=0,
ZCFGMENU_NUM=1,
ZCFGMENU_ADDRESS=2,
ZCFGMENU_OPTIONS=3,
ZCFGMENU_WIMENU=4,
ZCFGMENU_WIFIPW=5,
ZCFGMENU_WICONFIRM=6,
ZCFGMENU_FLOW=7,
ZCFGMENU_BBSMENU=8,
ZCFGMENU_NEWPORT=9,
ZCFGMENU_NEWHOST=10,
ZCFGMENU_NOTES=11,
ZCFGMENU_NETMENU=12,
ZCFGMENU_SUBNET=13,
ZCFGMENU_NEWPRINT=14
} currState;
ZSerial serial; // storage for serial settings only
void switchBackToCommandMode();
void doModeCommand();
bool showMenu;
bool savedEcho;
String EOLN;
const char *EOLNC;
unsigned long lastNumber;
String lastAddress;
String lastOptions;
String lastNotes;
WiFiServerSpec serverSpec;
bool newListen;
bool useDHCP;
bool settingsChanged=false;
char netOpt = ' ';
int lastNumNetworks=0;
IPAddress lastIP;
IPAddress lastDNS;
IPAddress lastGW;
IPAddress lastSN;
public:
void switchTo();
void serialIncoming();
void loop();
};

34
include/zhostcmmode.h Normal file
View File

@@ -0,0 +1,34 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifdef INCLUDE_SD_SHELL
#ifdef INCLUDE_HOSTCM
#include "proto_hostcm.h"
class ZHostCMMode : public ZMode
{
private:
void switchBackToCommandMode();
HostCM *proto = 0;
public:
void switchTo();
void serialIncoming();
void loop();
};
#endif
#endif

54
include/zircmode.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* zircmode.h
*
* Created on: May 18, 2022
* Author: Bo Zimmerman
*/
#ifdef INCLUDE_IRCC
class ZIRCMode: public ZMode
{
private:
ZSerial serial; // storage for serial settings only
bool showMenu;
bool savedEcho;
String EOLN;
const char *EOLNC;
WiFiClientNode *current = null;
unsigned long lastNumber;
unsigned long timeout=0;
String buf;
String nick;
String lastAddress;
String lastOptions;
String lastNotes;
String channelName;
bool joinReceived;
enum ZIRCMenu
{
ZIRCMENU_MAIN=0,
ZIRCMENU_NICK=1,
ZIRCMENU_ADDRESS=2,
ZIRCMENU_NUM=3,
ZIRCMENU_NOTES=4,
ZIRCMENU_OPTIONS=5,
ZIRCMENU_COMMAND=6
} currState;
enum ZIRCState
{
ZIRCSTATE_WAIT=0,
ZIRCSTATE_COMMAND=1
} ircState;
void switchBackToCommandMode();
void doIRCCommand();
void loopMenuMode();
void loopCommandMode();
public:
void switchTo();
void serialIncoming();
void loop();
};
#endif /* INCLUDE_IRCC */

66
include/zprint.h Normal file
View File

@@ -0,0 +1,66 @@
/*
Copyright 2020-2020 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
enum PrintPayloadType
{
PETSCII,
ASCII,
RAW
};
static unsigned int DEFAULT_DELAY_MS = 5000;
class ZPrint : public ZMode
{
private:
WiFiClientNode *wifiSock = null;
File tfile;
Stream *outStream = null;
unsigned int timeoutDelayMs = DEFAULT_DELAY_MS;
char *lastPrinterSpec = 0;
unsigned long currentExpiresTimeMs = 0;
unsigned long nextFlushMs = 0;
PrintPayloadType payloadType = PETSCII;
unsigned long lastNonPlusTimeMs = 0;
int plussesInARow=0;
size_t pdex=0;
size_t coldex=0;
char pbuf[258];
ZSerial serial;
char lastLastC = 0;
char lastC = 0;
short jobNum = 0;
size_t writeStr(char *s);
size_t writeChunk(char *s, int len);
void switchBackToCommandMode(bool error);
ZResult finishSwitchTo(char *hostIp, char *req, int port, bool doSSL);
void announcePrintJob(const char *hostIp, const int port, const char *req);
public:
ZResult switchTo(char *vbuf, int vlen, bool petscii);
ZResult switchToPostScript(char *prefix);
void setLastPrinterSpec(const char *spec);
bool testPrinterSpec(const char *vbuf, int vlen, bool petscii);
char *getLastPrinterSpec();
void setTimeoutDelayMs(int ms);
int getTimeoutDelayMs();
void serialIncoming();
void loop();
};

34
include/zslipmode.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* zslipmode.h
*
* Created on: May 17, 2022
* Author: Bo Zimmerman
*/
#ifdef INCLUDE_SLIP
extern "C" {
#include "lwip/raw.h"
#include "slipif.h"
}
static ZSerial sserial;
class ZSLIPMode: public ZMode
{
private:
void switchBackToCommandMode();
String inPacket;
bool started=false;
bool escaped=false;
raw_pcb *_pcb = 0;
public:
static const char SLIP_END = '\xc0';
static const char SLIP_ESC = '\xdb';
static const char SLIP_ESC_END = '\xdc';
static const char SLIP_ESC_ESC = '\xdd';
void switchTo();
void serialIncoming();
void loop();
};
#endif /* INCLUDE_SLIP_ */

51
include/zstream.h Normal file
View File

@@ -0,0 +1,51 @@
/*
Copyright 2016-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#define ZSTREAM_ESC_BUF_MAX 10
class ZStream : public ZMode
{
private:
WiFiClientNode *current = null;
unsigned long lastNonPlusTimeMs = 0;
unsigned long currentExpiresTimeMs = 0;
unsigned long nextFlushMs = 0;
int plussesInARow = 0;
ZSerial serial;
int lastDTR = 0;
uint8_t escBuf[ZSTREAM_ESC_BUF_MAX];
unsigned long nextAlarm = millis() + 5000;
void switchBackToCommandMode(bool logout);
void socketWrite(uint8_t c);
void socketWrite(uint8_t *buf, uint8_t len);
void baudDelay();
bool isPETSCII();
bool isEcho();
FlowControlType getFlowControl();
bool isTelnet();
bool isDisconnectedOnStreamExit();
public:
void switchTo(WiFiClientNode *conn);
void serialIncoming();
void loop();
};