include/df/network.hpp

00001 /*
00002 
00003 Network class def.
00004 
00005 Members to communicate over a network to other programs.
00006 
00007 */
00008 
00009 #define NETWORK_TIMEOUT_DEFAULT (30*1000)   //30 seconds for all operations
00010 #define NETWORK_BLOCK_SIZE 1460      //default transfer block size (HTTP,FTP,etc.)
00011 #define NETWORK_IDLE_MAX 100         //max idle count before going into Sleep() mode (less than 1 sec)
00012 
00013 //proto_type flgs
00014 #define NETWORK_PROTO_IP              0               /* dummy for IP */
00015 #define NETWORK_PROTO_ICMP            1               /* control message protocol */
00016 #define NETWORK_PROTO_IGMP            2               /* group management protocol */
00017 #define NETWORK_PROTO_TCP             6               /* tcp */
00018 #define NETWORK_PROTO_UDP             17              /* user datagram protocol */
00019 
00020 #define NETWORK_PROTO_RAW             255             /* raw IP packet */
00021 #define NETWORK_PROTO_MAX             256
00022 
00023 //sock_typ flgs
00024 #define NETWORK_SOCK_TCP 1
00025 #define NETWORK_SOCK_UDP 2
00026 #define NETWORK_SOCK_RAW 3
00027 
00028 #ifdef DF_WIN
00029 //Socket Options (SetOption())
00030 #define NETWORK_SO_DEBUG        0x0001          /* turn on debugging info recording */
00031 #define NETWORK_SO_ACCEPTCONN   0x0002          /* socket has had listen() */
00032 #define NETWORK_SO_REUSEADDR    0x0004          /* allow local address reuse */
00033 #define NETWORK_SO_KEEPALIVE    0x0008          /* keep connections alive */
00034 #define NETWORK_SO_DONTROUTE    0x0010          /* just use interface addresses */
00035 #define NETWORK_SO_BROADCAST    0x0020          /* permit sending of broadcast msgs */
00036 #define NETWORK_SO_USELOOPBACK  0x0040          /* bypass hardware when possible */
00037 #define NETWORK_SO_LINGER       0x0080          /* linger on close if data present */
00038 #define NETWORK_SO_OOBINLINE    0x0100          /* leave received OOB data in line */
00039 #define NETWORK_SO_DONTLINGER   (uint32)(~NETWORK_SO_LINGER)
00040 #else
00041 #define NETWORK_SO_DEBUG        0x0001          /* turn on debugging info recording */
00042 #define NETWORK_SO_ACCEPTCONN   0x001e          /* socket has had listen() */
00043 #define NETWORK_SO_REUSEADDR    0x0002          /* allow local address reuse */
00044 #define NETWORK_SO_KEEPALIVE    0x0009          /* keep connections alive */
00045 #define NETWORK_SO_DONTROUTE    0x0005          /* just use interface addresses */
00046 #define NETWORK_SO_BROADCAST    0x0006          /* permit sending of broadcast msgs */
00047 #define NETWORK_SO_LINGER       0x000d          /* linger on close if data present */
00048 #endif
00049 
00050 //flgs for Status()
00051 #define NETWORK_WRITE    0x01
00052 #define NETWORK_READ     0x02
00053 #define NETWORK_ERROR    0x04
00054 
00055 #define IP4_COMPATIBLE 0x0000  //::0000:0:0/96 = IPv4 Compatible
00056 #define IP4_MAPPED     0xffff  //::ffff:0:0/96 = IPv4 Mapped
00057 
00058 union IPAddr4 {    //when size matters (DF/3.0)
00059   uint8 x[4];
00060   uint32 ip;
00061   uint32 ip4;     //alias
00062   //CTORs
00063   IPAddr4() {ip4=0;}
00064   IPAddr4(uint32 _ip) {ip4=_ip;}
00065   IPAddr4(uint8 d1, uint8 d2, uint8 d3, uint8 d4) {
00066     x[0] = d1;x[1] = d2;x[2] = d3;x[3] = d4;
00067   }
00068   //operators
00069   BOOL operator ==(IPAddr4 &x) {
00070     if (ip4 == x.ip4) return TRUE;
00071     return FALSE;
00072   }
00073   BOOL operator !=(IPAddr4 &x) {
00074     if (ip4 != x.ip4) return TRUE;
00075     return FALSE;
00076   }
00077   void operator =(char * x);  //must be in form x.x.x.x (DF/1.3) (see network.cpp)
00078   void operator =(IPAddr &);  //(DF/3.0) (see network.cpp)
00079   BOOL IsIP4() { return TRUE; }
00080   BOOL IsIP6() { return FALSE; }
00081 };
00082 
00083 union IPAddr {    //IP Address (32/128bit)
00084   struct {
00085     uint8 pad[12];
00086     union {
00087       uint8 x[4];
00088       uint32 ip;
00089       uint32 ip4;
00090     };
00091   };
00092   uint8 ip6_8[16];
00093   uint16 ip6_16[8];
00094   uint32 ip6_32[4];
00095   uint64 ip6_64[2];
00096   //CTORs (IPv4)
00097   IPAddr() {ip6_64[0]=0;ip6_64[1]=0;}
00098   IPAddr(uint32 _ip4) {ip6_32[0]=_ip4;ip6_32[1]=0;ip6_32[2]=0;ip6_32[3]=0;}
00099   IPAddr(uint8 d1, uint8 d2, uint8 d3, uint8 d4) {
00100     ip6_64[0] = 0; ip6_64[1] = 0;
00101     x[0] = d1;x[1] = d2;x[2] = d3;x[3] = d4;
00102   }
00103   //CTORs (IPv6)
00104   IPAddr(uint64 ip6_lo, uint64 ip6_hi) {ip6_64[0]=ip6_lo;ip6_64[1]=ip6_hi;}
00105   //operators
00106   BOOL operator ==(IPAddr4 &x) {
00107     if (!IsIP4()) return FALSE;  //FIX - DF/3.0.4
00108     if (ip4 == x.ip4) return TRUE;
00109     return FALSE;
00110   }
00111   BOOL operator ==(IPAddr &x) {
00112     if ((ip6_64[0] == x.ip6_64[0]) && (ip6_64[1] == x.ip6_64[1])) return TRUE;
00113     return FALSE;
00114   }
00115   BOOL operator !=(IPAddr &x) {
00116     if (ip6_64[0] != x.ip6_64[0]) return TRUE;
00117     if (ip6_64[1] != x.ip6_64[1]) return TRUE;
00118     return FALSE;
00119   }
00120   void operator =(char *x);  //must be in form x.x.x.x or xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx (see network.cpp)
00121   BOOL IsIP4() { return (ip6_64[0] == 0) && (ip6_16[4] == 0) && ((ip6_16[5] == IP4_COMPATIBLE) || (ip6_16[5] == IP4_MAPPED)); }
00122   BOOL IsIP6() { return !IsIP4(); }
00123 };
00124 
00125 #include <df/ethernet.hpp>
00126 
00127 #define DNS_A     0x0001
00128 #define DNS_NS    0x0002
00129 #define DNS_MD    0x0003  //Obsolete. Use MX
00130 #define DNS_MF    0x0004  //Obsolete. Use MX
00131 #define DNS_CNAME 0x0005
00132 #define DNS_SOA   0x0006
00133 #define DNS_MB    0x0007
00134 #define DNS_MG    0x0008
00135 #define DNS_MR    0x0009
00136 #define DNS_NULL  0x000a
00137 #define DNS_WKS   0x000b
00138 #define DNS_PTR   0x000c
00139 #define DNS_HINFO 0x000d
00140 #define DNS_MINFO 0x000e
00141 #define DNS_MX    0x000f
00142 #define DNS_TXT   0x0010
00143 #define DNS_SRV   0x0021
00144 
00145 #ifndef AF_UNSPEC
00146 #define AF_UNSPEC 0
00147 #define AF_UNIX   1
00148 #define AF_INET   2
00149 #endif
00150 
00151 #ifndef AF_INET6
00152 #define AF_INET6  23
00153 #endif
00154 
00155 class Network : public EncryptionCallbacks {
00156     friend class OSAPI;
00157     friend class FTP;
00158     friend class HTTP;
00159     friend class MsgServer;
00160     friend class NetworkServer;
00161     friend class NetworkSession;
00162     friend class MsgClient;
00163     friend class SMTPServer;
00164     friend class FTPServer;
00165     friend class FTPSession;
00166   _PROTECTED_:
00167     //private data
00168     EncryptionClass *eptr;
00169     EncryptionSession *esess;
00170     uint32 handle;             //network socket handle
00171     BOOL douninit;             //Close() on DTOR? (not for x11 network objects)
00172     BOOL inited;               //was init successfully called
00173     BOOL Secure;               //SSL? (SSH someday)
00174     IPAddr ProxyIP;
00175     uint16 ProxyPort;
00176     BOOL useproxy;
00177     //static private members
00178     BOOL activity;
00179     BOOL calluninit;
00180 #ifdef DF_LNX
00181     BOOL islisten;   //is a listening socket
00182 #endif
00183     //private members
00184     BOOL init();
00185     void uninit();
00186     int32 EncryptionWrite(PTR, int32);
00187     int32 EncryptionRead(PTR, int32);
00188     //    BOOL readln(char*,int);    //read a line from port (\x0d\x0a terminated)
00189   public:
00190     PTR UserData;  //user definable
00191     BOOL StatusFlag; //NA=INIT | TRUE=CONNECTED | FALSE=DISCONNECTED
00192     BOOL SetEncryption(EncryptionClass *);
00193     EncryptionClass *GetEncryption() { return eptr;}
00194     BOOL InitAccept();
00195     BOOL InitConnect();
00196     int BufferSize;  //Max Data to transfer per data transfer
00197     Thread *This;
00198     BOOL Valid;                //socket/node allocated (Alloc)
00199 
00200     Network();
00201     ~Network() { if (Valid) Close(); if (inited) uninit();}
00202 
00203     uint32 GetLastError();
00204     IPAddr localip;            //local IP (not filled in till connect/accept)
00205     uint16 localport;          //local port
00206     IPAddr remoteip;           //remote IP (not filled in till connect/accept)
00207     uint16 remoteport;         //remote IP:port (not filled in till connect/accept)
00208 
00209     static void GetComputerName(String &s);
00210 
00211     BOOL IsWinSock2();
00212 
00213     void SetBufferSize(int siz) {BufferSize = siz;}
00214     BOOL Connected() { return StatusFlag;}
00215 
00216     uint32 GetTimeSeconds();  //get current time in seconds
00217 
00218     //Setup Proxy Server
00219     void SetProxy(IPAddr *ip, uint16 port) {  //To disable use NULL IP and port=0
00220       if ((ip == NULL) || (port == 0)) {
00221         useproxy = FALSE;
00222         ProxyIP.ip = 0;
00223         ProxyPort = 0;
00224       } else {
00225         useproxy = TRUE;
00226         ProxyIP = *ip;
00227         ProxyPort = port;
00228       }
00229     }
00230 
00231     //timeout values
00232     int Timeout;
00233 
00234     //Returns a list of NICs installed in system
00235     char **EnumNICs(void);
00236 
00237     //AllocSocket() creates a Socket and Binds it to a port or node
00238     //returns port used
00239     BOOL AllocSocket(uint16 port = 0, int sock_type = NETWORK_SOCK_TCP
00240                      , int proto_type = NETWORK_PROTO_IP, BOOL poll = TRUE, BOOL reuse = FALSE);
00241     //if port==0 then poll to bind (if poll=TRUE)
00242     BOOL BindSocket(uint16 port);  //binds a port if port==0 in AllocSocket()
00243     BOOL BindSocket(uint16 port, IPAddr &ip);  //binds a port if port==0 in AllocSocket()
00244     BOOL BindSocket(uint16 port, MAC &mac);  //binds a port if port==0 in AllocSocket()
00245 
00246     //Listen/Accept are for the Servers end of a Server/Client connection
00247     BOOL Listen();
00248     //accepts a connect from another host after calling Listen()
00249     //if successful then connection == new socket and remote_addr/port is filled
00250     // in with clients address.
00251     BOOL Accept(Network &connection, BOOL doinit = TRUE);
00252     //doinit should be FALSE if you need init to occur in another thread (win32 only)
00253 
00254     //Open() connects Clients end of a Server/Client connection
00255     //Connects to another socket that is listening
00256     BOOL Open(IPAddr &, uint16 port);
00257     //OpenFromHandle() creates a Network object from a HANDLE
00258     BOOL Duplicate(Network *, BOOL isconnected);
00259     //close a connection
00260     BOOL Close();  //also frees socket (must call AllocSocket() again)
00261     //Send Data over a connected socket
00262     int32 Write(PTR, int32 len);
00263     int32 Write(char *str) {
00264       return Write(str, SystemCode::strlen(str));
00265     }
00266     //intelligent Send (Blocking Mode)
00267     int32 iWrite(PTR, int32);
00268     int32 iWrite(char *str) {
00269       return iWrite(str, SystemCode::strlen(str));
00270     }
00271     //Send Data over a connectionless socket
00272     int32 Write(IPAddr &, uint16 port, PTR, int32 len);
00273     //Receive Data over connected socket
00274     int32 Read(PTR, int32 len);
00275     //Receive Data over connectionless socket
00276     int32 Read(IPAddr &, uint16 &port, PTR, int32 len);
00277     //Async funcs
00278     virtual void AsyncRead();   //inbound data ready
00279     virtual void AsyncAccept(); //inbound connection requested
00280     virtual void AsyncClose();  //connection lost
00281     BOOL AsyncStartListen();
00282     BOOL AsyncStart();
00283     BOOL AsyncStop();
00284     //Status reporting functions
00285     int Status(int flgs);    //checks for NETWORK_WRITE, NETWORK_READ, NETWORK_ERROR if selected
00286     //returns -1 on error (!FALSE)
00287     //TCP/UDP/IP functions
00288     static void MakeIP(IPAddr &ip, uint8 d1, uint8 d2, uint8 d3, uint8 d4) {
00289       ip.x[0] = d1;
00290       ip.x[1] = d2;
00291       ip.x[2] = d3;
00292       ip.x[3] = d4;
00293     }
00294     static void GetIP(uint8 *d1, uint8 *d2, uint8 *d3, uint8 *d4, IPAddr &ip) {
00295       *d1 = ip.x[0];
00296       *d2 = ip.x[1];
00297       *d3 = ip.x[2];
00298       *d4 = ip.x[3];
00299     }
00300     BOOL SetOption(int so, int state);
00301     BOOL GetOption(int so, int &state);
00302     //stuff for async operations
00303     static Network *Find(uint32 handle);
00304     void Attach();
00305     BOOL Detach();
00306     //dns stuff (use to a class in its own) //DF/1.6.5 - all DNS members are now static
00307     static BOOL Lookup(char *addr, IPAddr &ip, int type = DNS_A);
00308     static BOOL LookupAll(char *addr, List<IPAddr> &iplst, int type = DNS_A);
00309     static BOOL ReverseLookup(IPAddr &ip, String &addr);
00310     static void SplitURL(char *url , String *proto, String *host, String *file);
00311     static void MergeURL(String &url, char *proto , char *host , char *file);
00312     static void SplitHOST(char *fullhost, String *user, String *pwd, String *host, String *port);
00313     static void MergeHOST(String &fullhost, char *user, char *pwd, char *host, char *port);
00314 };
00315 
00316 //Generic Network Server which spawns new threads to handle each
00317 // incoming request (NetworkSession)
00318 //this is an ABSTRACT class
00319 class NetworkServer : public Network, public SystemCode {
00320     friend class MsgServerSession;
00321     friend class NetworkSesssion;
00322   _PROTECTED_:
00323     BOOL running;
00324     ThreadManager *tm;
00325   public:
00326     //ctor/dtor
00327     NetworkServer();
00328     ~NetworkServer() {StopServer();StopSessions();}
00329     //misc
00330     virtual void AsyncAccept();  //would not work via Event() handler unless user app passed it on
00331     //User members
00332     BOOL ServerStatusFlag;  //TRUE=READY | FALSE=DONE
00333     int16 StartServer(uint16 _port, ThreadManager *_tm);  //0=find any port (returns 0 if failed)
00334     BOOL StopServer();    //stops listening for new connections (and closes the socket)
00335     BOOL StopSessions();  //stops all sessions
00336     virtual void Log(char *);   //log an error message (default = do nothing)
00337     void Cleanup();  //call to periodically delete dead Threads
00338     PTR GetFirstThread() { return tm->GetFirstThread();}
00339     PTR GetNextThread(BOOL inc = TRUE) { return tm->GetNextThread(inc);}
00340 };
00341 
00342 //Processes a new connection
00343 //this is an ABSTRACT class
00344 class NetworkSession : public Network, public TimerCallback, public Thread {
00345     friend class NetworkServer;
00346   _PROTECTED_:
00347     Timer timer;
00348   public:
00349     void TimerEvent();  //called by Timer to trigger NULL event
00350     NetworkServer *Server;
00351     NetworkSession();
00352     BOOL StartTimer();  //timeout timer
00353     BOOL StopTimer();
00354     virtual uint32 Main(int32 param);  //param = undefined
00355     virtual void Log(char *);  //log an error message (default = do nothing)
00356     virtual void Process();     //process connection
00357     virtual void AsyncRead();   //inbound data ready
00358 };
00359 
00360 class HTTP : public Network, public SystemCode {
00361   private:
00362     BOOL useHTTP11;  //use HTTP/1.1
00363     BOOL isHTTP11;   //last Get() returned an HTTP/1.1 response
00364     uint32 GetContentLength(void *data, uint32 datalen, uint32 *headerlen);
00365     PTR buffer;  //4K Buffer
00366     BOOL connected;
00367     String connectedhost;
00368     String xHeaders;  //DF/3.0.4
00369   public:
00370     HTTP();
00371     ~HTTP();
00372     void SetHTTPVersion(BOOL use11) {useHTTP11 = use11;}  //TRUE=1.1 FALSE=1.0(default)
00373     void SetHeaders(char *x) {xHeaders = x;}  //use to set cookies, etc. (it's added to default headers)
00374     BOOL Get(char *fullurl, void **data, uint32 *datalen, uint32 *headerlen = (uint32*)NULL, uint32 *contentlen = (uint32*)NULL);  //perform full query (blocking)
00375 };
00376 
00377 // HTTP Server
00378 
00379 struct HTTPMimeType {
00380   String ext;
00381   String mime;
00382   HTTPMimeType(char *ext, char *mime);
00383 };
00384 
00385 struct HTTPAlias {
00386   String _domain; //default = "127.0.0.1"
00387   String _unix;   //Unix alias ie: '/'
00388   String _local;  //local (Dos|unix) direc. ie: 'c:\wwwroot'
00389   BOOL isScript;  //Is a Script only Path (Execute .EXE files)
00390   HTTPAlias(char *d,char *u, char *l, BOOL _isScript);
00391 };
00392 
00393 struct HTTPAuth {
00394   String _local;  //local (Dos|unix) direc. ie: 'c:\wwwroot'
00395   String _file;   //.htpasswd filename
00396   HTTPAuth(char *__local,char *__file);
00397 };
00398 
00399 struct HTTPExtension {
00400   String ext;
00401   String path;
00402   HTTPExtension(char *_ext, char *_path) {
00403     ext = _ext;
00404     path = _path;
00405   }
00406   ExclusiveUsage InUse;  //only run external process one at a time (else it doesn't run sometimes)
00407   DLL dll;  //for ISAPI only
00408   PTR isapi;  //ISAPI func
00409 };
00410 
00411 class HTTPSession : public NetworkSession {
00412     friend class HTTPServer;
00413   _PROTECTED_:
00414     int32 exitcode;    //ErrorCode (if TX not OK) (0=ok)
00415     char *SendResponse(int);  //send error header only
00416     void SendError(int);  //send error msg
00417     void SendEOH();  //end of header
00418     void SendMimeType(char *);  //based on EXT
00419     void GetMimeType(String &s, char *);  //based on EXT
00420     void SendServer(); //send "Server: " message
00421     void SendLength(uint32);
00422     void exec_script(char *, char *, char *, char *, char *);
00423 
00424     String pathinfo, pathtranslated;
00425     String xHeaders;
00426     BOOL isScript;
00427     BOOL needAuth;
00428     String AuthFile;  //.htpasswd file
00429     String isapi;
00430     void exec_isapi_direct(char *, char *, char *, char *, char *, char *, uint32);
00431     void exec_isapi(char *, char *, char *, char *, char *, char *, uint32, PTR);
00432     BOOL GetAllTags(char *dest, uint32 *destlen);
00433     BOOL GetTag(char *dest, uint32 *destlen, char *var);
00434 
00435     BOOL TranslatePath(char *path, String &trans_path, String &trans_full);
00436     BOOL ValidAuth();
00437     void SendFile(char *, char *, char *, uint32);
00438     void SendFolderList(char *, char *);
00439     static List<HTTPMimeType*> HTTPMimeArray;
00440     static ExclusiveUsage HTTPMimeArrayUsage;
00441     Memory data;
00442     Memory outdata;
00443     int outdatalen;
00444     Memory req;
00445     int reqlen;
00446     String domain;  //"Host:" tag (default=127.0.0.1)
00447   public:
00448     int iWrite(PTR data, int len);
00449     int32 iWrite(char *str) {
00450       return iWrite(str, SystemCode::strlen(str));
00451     }
00452     BOOL Flush();
00453     BOOL isapi_getservervariable(char *, void *, uint32 *);
00454     BOOL isapi_writeclient(void *, uint32 *, uint32);
00455     BOOL isapi_readclient(void *, uint32 *);
00456     BOOL isapi_serversupportfunction(uint32, void *, uint32 *, uint32 *);
00457     HTTPSession();
00458     void Log(char *);
00459     virtual void Process();
00460     virtual void AsyncRead();   //more data to be read
00461 };
00462 
00463 class HTTPServer : public NetworkServer {
00464     //simply listens for HTTP clients and spawns HTTPSession per client
00465     friend class HTTPSession;
00466   _PROTECTED_:
00467     List<HTTPAlias*> HTTPAliasList; //alias'es
00468     List<HTTPAuth*> HTTPAuthList; //auth
00469     List<HTTPExtension*> HTTPExtList;
00470     String Default;
00471     ExclusiveUsage HTTPAliasUsage;
00472     ExclusiveUsage HTTPAuthUsage;
00473     ExclusiveUsage HTTPExtUsage;
00474     LogFile *logfile;
00475     ExclusiveUsage logfileUsage;
00476   public:
00477     HTTPServer();
00478     ~HTTPServer();  //delete lists
00479     void SetDomain(char *);
00480     int16 StartServer(uint16 port);
00481     void Log(char *);
00482     void SetLogFile(LogFile *);
00483     BOOL AddExtension(char *_ext, char *_path);
00484     BOOL DelExtension(char *ext);
00485     BOOL AddMimeType(char *_ext, char *_path);
00486     BOOL DelMimeType(char *ext);
00487     void SetDefault(char *def);
00488     BOOL SetCustomErrorMsg(uint32 errcode, char *msg);
00489     void AddAlias(char *_domain,char *_unix, char *_local, BOOL isScript = FALSE);
00490     BOOL DelAlias(char *_unix);
00491     void AddAuth(char *_local, char *_htpasswdfilename);
00492     BOOL DelAuth(char *_local);
00493 };
00494 
00495 //ping.cpp (requires WinSock2.0 for Windows)
00496 class Ping : public Network, public SystemCode {
00497   _PROTECTED_:
00498     int packetsize;
00499     IPAddr ip;
00500     BOOL result;
00501   public:
00502     BOOL Start(IPAddr &, uint32 _packetsize);
00503     BOOL Process();         //process ping (keep trying as long as you like)
00504     void Stop();            //stop Ping in process
00505 };
00506 
00507 class SMTP : public Network, public SystemCode {
00508   _PROTECTED_:
00509     BOOL GetResponse();
00510     BOOL adv;  //does server support adv features (STARTTLS)
00511   public:
00512     SMTP() {}  //don't know why but this is needed, else compiler generates errors
00513     BOOL Open(IPAddr &_ip, uint16 port = 25) {   //open SMTP connection
00514       return Network::Open(_ip, port);
00515     }
00516     String Response; //for error checking
00517     //use AllocSocket() / Open() first, then call each member below in sequence
00518     BOOL Connect();  //read init welcome message
00519     BOOL Authenticate(char *user, char *pwd);  //optional (DF/0.5.4 : New)
00520     BOOL MessageFrom(char *);
00521     BOOL MessageTo(char *);
00522     BOOL MessageStartData();
00523     BOOL MessageData(void *data, uint32 datalen); //call as many times as you need to send data
00524     BOOL MessageEndData();
00525     BOOL Quit();
00526     BOOL StartEncryption(EncryptionClass *);  //DF/1.3.2 - new member
00527 };
00528 
00529 //FTP Modes
00530 #define FTP_PASV 0x01  //server listens
00531 #define FTP_PORT 0x02  //client listens
00532 
00533 //FTP Types
00534 #define FTP_ASCII  0x01
00535 #define FTP_BINARY 0x02
00536 #define FTP_AUTO   0x04
00537 
00538 class FTP : public Network, public SystemCode {
00539   _PROTECTED_:
00540     IPAddr ip;    //ip connected to (to later make data connection)
00541     BOOL gotResponse;
00542     BOOL GetResponse(BOOL wait = TRUE);
00543     IPAddr dataip;
00544     uint16 dataport;
00545     BOOL WriteType(BOOL list = FALSE);
00546     BOOL WriteMode();
00547     Network DataPort;
00548     BOOL ConnectDataPort();
00549     char resbuf[512];  //response buffer
00550     uint32 resbufsiz;  //response buffer size
00551   public:
00552     FTP();
00553     String Response;
00554     int Mode;
00555     int Type;
00556     BOOL Open(IPAddr &_ip, uint16 port = 21) {   //open FTP connection
00557       ip = _ip;
00558       return Network::Open(_ip, port);
00559     }
00560     BOOL Close() {
00561       DataPort.Close();
00562       return Network::Close();
00563     }
00564     //usefull FTP functions
00565     BOOL Connect();      //confirms a valid connection
00566     BOOL Disconnect();   //QUIT
00567     BOOL Login(char *user, char *pwd);      //login to site
00568     BOOL ListPath(char *fname);   //Response will hold response
00569     BOOL Get(char *fname);   //download file (a Data connection will be needed to send data)
00570     BOOL Put(char *fname);   //upload file (a Data connection will be needed to recv data)
00571     BOOL GetCurrentPath(String &);         //cd  (get working dir.)
00572     BOOL SetCurrentPath(char *fname);      //cd x
00573     BOOL CreatePath(char *fname);          //md x
00574     BOOL Delete(char *fname);              //delete file
00575     BOOL DeletePath(char *path);           //delete dir
00576     BOOL MoveFile(char *src, char *dest);   //move file
00577     //data send/receive functions
00578     int32 WriteData(PTR data, int32 datalen);    //returns FALSE when no more data/error
00579     int32 ReadData(PTR data, int32 datalen); //returns FALSE when no more data/error
00580     BOOL CloseData();  //disconnect data port after transfer
00581     BOOL TransferComplete();  //is RX complete?
00582     PTR Download(uint32 *len);  //Free() it when your done
00583     BOOL Upload(PTR file, uint32 len);
00584     //config members
00585     void SetMode(int);  //FTP_PASV(default) or FTP_PORT(not supported!)
00586     void SetType(int);  //FTP_ASCII or FTP_BINARY or FTP_AUTO(default)
00587 };
00588 
00589 struct FTPAlias {
00590   String name;  //unique name (for access control)
00591   String _unix;  //Unix alias ie: '/'
00592   String _local;   //DOS folder ie: 'c:\wwwroot'
00593 };
00594 
00595 struct FTPAccount {
00596   String user;
00597   String pwd;
00598   uint32 id;  //access ID
00599 };
00600 
00601 struct FTPResource {
00602   String name;        //name of FTPAlias
00603   BOOL rd, wr, ls, cf;   //read/write/list/createFolder access
00604   FTPResource() {
00605     rd = wr = ls = cf = FALSE;
00606   }
00607   FTPResource(BOOL fullaccess) {
00608     if (fullaccess)
00609       rd = wr = ls = cf = TRUE;
00610     else
00611       rd = wr = ls = cf = FALSE;
00612   }
00613 };
00614 
00615 struct FTPAccess {
00616   uint32 id;  //access ID
00617   Array<FTPResource*> list;
00618   ExclusiveUsage listUsage;
00619 };
00620 
00621 class FTPServer : public NetworkServer {
00622     //simply listens for FTP clients and spawns FTP Session for each client
00623     friend class FTPSession;
00624   _PROTECTED_:
00625     LogFile *logfile;
00626     ExclusiveUsage logfileUsage;
00627     Array<FTPAccount*> userslist;
00628     ExclusiveUsage userslistUsage;
00629     Array<FTPAccess*> accesslist;
00630     ExclusiveUsage accesslistUsage;
00631     Array<FTPAlias*> aliaslist;
00632     ExclusiveUsage aliaslistUsage;
00633     Array<String*> nologinlist;  //local mode only
00634     ExclusiveUsage nologinlistUsage;
00635     EncryptionClass *eeptr;   //explicit SSL (port 21 : "AUTH SSL")
00636     uint16 pasvport_start, pasvport_count, pasvport_current;
00637     ExclusiveUsage pasvportinuse;
00638     BOOL b_local;  //user local users/file access restrictions (else use cfg)
00639     String Domain;
00640     uint16 Getpasvport();
00641   public:
00642     int16 StartServer(uint16 port);
00643     FTPServer();
00644     void SetLogFile(LogFile *);
00645     void Log(char *);
00646     void SetExplicitEncryption(EncryptionClass *);
00647     BOOL SetCustomErrorMsg(uint32 errcode, char *msg);
00648     BOOL AddAlias(FTPAlias *);
00649     BOOL DelAlias(char *name);
00650     BOOL AddAccount(FTPAccount *);
00651     BOOL DelAccount(char *user);
00652     BOOL AddAccess(FTPAccess *);
00653     BOOL DelAccess(uint32 id);
00654     BOOL AddNoLogin(char *);
00655     BOOL DelNoLogin(char *);
00656     void SetPasvPortRange(uint16 start, uint16 len);
00657     void Init(BOOL _b_local); //DF/1.7.1
00658     void SetDomain(char *d);
00659 };
00660 
00661 //DF/1.7.3 - new async data port handler
00662 class FTPDataSession : public Network, public SystemCode {
00663   public:
00664     FTPSession *Session;
00665     FTPDataSession();
00666     ~FTPDataSession();
00667     PTR data;
00668     uint32 Size;
00669     uint32 Pos;
00670     void AsyncRead();
00671     void AsyncWrite();
00672     void AsyncClose();
00673     BOOL bGet;  //else Put(upload)
00674     BOOL bError;
00675     BOOL bDone;
00676     MemFile _memfile;
00677     File _file;
00678     File *f;     //preOpen and ready to read/write
00679     void Flush();
00680 };
00681 
00682 class FTPSession : public NetworkSession {
00683     //a session created by FTPServer
00684   _PROTECTED_:
00685     PTR data;
00686     PTR req;
00687     int reqlen;
00688     String user, pwd;
00689     BOOL validuser;  //logged on ok?
00690     uint32 id;       //access ID
00691     FTPAccess *access;
00692     FTPResource *res;
00693     FTPDataSession DataPort; //data connection
00694     Network ListenPort; //data connection
00695     uint16 port;     //PORT #,#,#,#,x,y
00696     BOOL pasv;       //use PASV mode (default=TRUE)
00697     BOOL pasvinit;   //pasv mode ready
00698     BOOL portinit;   //port mode ready
00699     BOOL bTxMode;
00700     String wd;       //working directory
00701     String movefrom; //Move from
00702     uint32 rest;     //restore offset
00703     EncryptionClass *oeptr;
00704     void SendError(uint32 errcode, BOOL dash = FALSE, char *altmsg = (char*)NULL);
00705     void ProcessCmd();
00706     void ValidateUserLocal();
00707     void ValidateUserCfg();
00708     BOOL setupDataPort();
00709     void closeDataPort();
00710     BOOL FindMatch(char *file, String &path, String &fullpath);
00711     BOOL ValidFilename(char *);
00712     void cmdList(char *);
00713     void cmdNList(char *);
00714     void cmdChangePath(char *);
00715     void cmdCDUP();
00716     void cmdCreatePath(char *);
00717     void cmdDeletePath(char *);
00718     void cmdGet(char *);
00719     void cmdPut(char *, BOOL);
00720     void cmdDelete(char *);
00721     void cmdRenameFrom(char *);
00722     void cmdRenameTo(char *);
00723     BOOL IsInternetClient();
00724   public:
00725     FTPSession() {
00726       data = NULL;
00727       validuser = FALSE;
00728       id = 0;
00729       port = 0;
00730       pasv = TRUE;
00731       pasvinit = FALSE;
00732       portinit = FALSE;
00733       wd = "/";
00734       rest = 0;
00735       oeptr = (EncryptionClass*)NULL;
00736       bTxMode = FALSE;
00737     }
00738     void Log(char *);
00739     virtual void Process();
00740     virtual void AsyncRead();   //more data to be read
00741     void TxComplete();  //called from FTPDataSession class
00742 };
00743 
00744 class SMTPServer : public NetworkServer, public TimerCallback {
00745     //simply listens for SMTP clients and spawns SMTP Session for each client
00746     friend class SMTPThread;
00747     friend class SMTPSession;
00748   _PROTECTED_:
00749     LogFile *logfile;
00750     ExclusiveUsage logfileUsage;
00751     IPAddr netmask;   //default=255.255.255.0
00752     String user, pwd;  //auth
00753     String domain;
00754     String mailroot;
00755     String outmail;
00756     uint32 maxlen;
00757     Timer timer;  //24H timer (to start SMTP Thread's)
00758     //every 24H the server will try to send out failed emails for 7 days
00759     void CreateThread(char *fn);
00760     BOOL initScan;
00761     EncryptionClass *eeptr;   //explicit SSL ("STARTTLS")
00762   public:
00763     void TimerEvent();
00764     void Init(char *_mailroot, char *_outmail, char *_domain) {
00765       mailroot = _mailroot;
00766       outmail = _outmail;
00767       domain = _domain;
00768     }
00769     void SetExplicitEncryption(EncryptionClass *);
00770     void SetMaxMessageSize(uint32 max) {maxlen = max;}
00771     void SetNetmask(IPAddr &mask) {netmask = mask;}
00772     int16 StartServer(uint16 port);
00773     SMTPServer();
00774     void SetLogFile(LogFile *);
00775     void Log(char *);
00776     BOOL SetCustomErrorMsg(uint32 errcode, char *msg);
00777 };
00778 
00779 //this thread handles incoming requests and stores into files to be send later
00780 class SMTPSession : public NetworkSession {
00781     //a session created by SMTPServer
00782   _PROTECTED_:
00783     PTR data;
00784     PTR req;
00785     int reqlen;
00786     String user, pwd;  //auth
00787     String from;
00788     List<String*> to;
00789     BOOL bData;
00790     BOOL bLocal;  //is client on local LAN
00791     BOOL bError;
00792     uint16 iError;
00793     BOOL bAuth;
00794     uint32 TotalSize;
00795     String tmpfn;  //temp file name
00796     File tmpfile;  //temp file to hold inbound data (then copy to mbx)
00797     void SendError(uint32 errcode, BOOL dash = FALSE, char *altmsg = (char*)NULL);
00798     void ProcessCmd();
00799     void ClearTo();
00800     BOOL OpenEML(char *);
00801     void MessageData(PTR, uint32);
00802     char last5[5];  //to detect end of DATA session
00803     uint32 last5len;
00804     void DataEnd(uint32 remove = 0);
00805     EncryptionClass *oeptr;   //old value
00806   public:
00807     SMTPSession() {
00808       data = NULL;
00809       oeptr = (EncryptionClass*)NULL;
00810     }
00811     void Log(char *);
00812     virtual void Process();
00813     virtual void AsyncRead();   //more data to be read
00814 };
00815 
00816 //this thread does the actual sending out of emails
00817 class SMTPThread : public Thread {
00818     friend class SMTPServer;
00819   _PROTECTED_:
00820     //setup by SMTPServer
00821     String fn;  //filename of full email (see smtpsvr.cpp for format)
00822     SMTPServer *Server;  //to lookup stuff
00823     //setup by SMTPThread
00824     String from, _to_;
00825     int daysold;
00826     void Log(char *msg);
00827     BOOL Savembx(char *usermbx, File &tf, uint32 tfp, uint32 tfs);
00828     void SendFailed(char *to);
00829     Time ft;  //file time (creation)
00830     BOOL SendData(SMTP &client, File &f, uint32 fp, uint32 fs);
00831     uint32 getdaysold();
00832   public:
00833     uint32 Main(int32);
00834 };
00835 
00836 struct POP3Account {
00837   String user, pwd;
00838 };
00839 
00840 class POP3Server : public NetworkServer {
00841     //simply listens for POP3 clients and spawns POP3 Session for each client
00842     friend class POP3Session;
00843   _PROTECTED_:
00844     LogFile *logfile;
00845     ExclusiveUsage logfileUsage;
00846     String mailroot;
00847     Array<POP3Account*> userslist;
00848     ExclusiveUsage userslistUsage;
00849   public:
00850     void Init(char *_mailroot) {
00851       mailroot = _mailroot;
00852     }
00853     BOOL AddAccount(POP3Account *);
00854     BOOL DelAccount(char *user);
00855     int16 StartServer(uint16 port);
00856     POP3Server();
00857     void SetLogFile(LogFile *);
00858     void Log(char *);
00859 };
00860 
00861 struct POP3Email {
00862   uint32 Offset;  //offset into MBX file
00863   uint32 Size;    //message size
00864   uint32 no;      //number
00865   BOOL isDelete;  //already is deleted
00866   BOOL Delete;    //Delete it
00867 };
00868 
00869 class POP3Session : public NetworkSession {
00870     //a session created by POP3Server
00871   _PROTECTED_:
00872     PTR data;
00873     PTR req;
00874     int reqlen;
00875     String user, pwd;
00876     BOOL Valid;
00877     File mbx;
00878     void SendError(char *msg);
00879     void SendOK(char *msg = "");
00880     void ProcessCmd();
00881     BOOL Openmbx(char *mailroot);
00882     void Closembx(char *mailroot);  //delete msgs marked for deletion
00883     void ValidateUser();  //does user exist & password match
00884     void cmdStat(); //STAT
00885     void cmdList(); //LIST
00886     void cmdDele(char *); //DELE #
00887     void cmdGet(char *);  //RETR #
00888     void cmdRset();
00889     void cmdTOP(char *);  //DF/3.0
00890     void cmdUIDL(char *); //DF/3.0
00891     Array<POP3Email*> list;
00892     void Freelist();
00893   public:
00894     POP3Session() { data = NULL; }
00895     void Log(char *);
00896     virtual void Process();
00897     virtual void AsyncRead();   //more data to be read
00898 };
00899 
00900 /*
00901   --Currently incomplete--
00902 class POP3 : public Network, public SystemCode  {
00903   public:
00904     //use AllocSocket() / Open() first
00905     BOOL Connect(char *user,char *pass);  //send user/password
00906     int GetNumMessages();                 //returns # of messages waiting
00907     BOOL GetMessageHeader(int msg,String &mh);       //get message header
00908     BOOL GetMessage(int msg);    //start message download
00909     BOOL Process(void **data,uint32 *datalen,BOOL readall=FALSE);
00910       //After each call the data ptr could change!
00911     void Stop() {Close();}  //stop request
00912 };
00913 */
00914 
00915 struct DHCPMapping {
00916   IPAddr ip;
00917   MAC mac;  //see ethernet.hpp
00918   String host;  //optional (will use DHCPInterface if NULL)
00919 };
00920 
00921 //Note:Server doesn't delete interfaces when delete'ed.
00922 struct DHCPInterface {
00923   IPAddr ip;
00924   IPAddr mask;
00925   IPAddr pool;   //1st IP of pool
00926   int pool_cnt;  //# of IPs in pool
00927   IPAddr router;
00928   IPAddr dns_1, dns_2;
00929   String domain;
00930   String host;  //"host%03d%03d%03d%03d"
00931   int time;  //lease time in seconds (12hrs=43200s) [0s=forever]
00932   List<DHCPMapping*> list;  //specific MAC->IP mappings
00933   String dbPath;
00934   DHCPInterface() {
00935     pool_cnt = 0;
00936     time = 0;
00937   }
00938   String dns_mysql_db, dns_mysql_user, dns_mysql_passwd;  //to update records to DNS server
00939 };
00940 
00941 //Because DHCP uses UDP it cannot derive from the NetworkServer class
00942 //this implementation is NOT multi-threaded.
00943 class DHCPServer : public Network, public SystemCode {
00944     //simply listens for DHCP clients and spawns DHCP Session for each client
00945   _PROTECTED_:
00946     LogFile *logfile;
00947     ExclusiveUsage logfileUsage;
00948     DHCPInterface *dif;
00949     ExclusiveUsage busy;  //using all tables (get_ip())
00950     Array<BOOL> inuse;  //list of IPs in use (size set to pool_cnt)
00951     Array<uint32> inusetime;  //time that IP was leased (seconds since year 2000)
00952     Array<MAC> inuseby; //who is using it
00953     uint16 port;
00954     BOOL get_ip(MAC &clientmac, IPAddr &ip, BOOL alloc, String &, IPAddr &);
00955     void free_ip(MAC &clientmac, IPAddr &ip);
00956     File f;  //db file
00957     BOOL InitTables();
00958     void update_db(uint32);
00959     void update_dns(IPAddr &, char *hostname);
00960     void delete_dns(IPAddr &);
00961     uint32 oo;  //Offer Offset
00962   public:
00963     String dns_mysql_db, dns_mysql_user, dns_mysql_passwd;
00964     void Init(DHCPInterface *_if) {dif = _if;}
00965     int16 StartServer(uint16 port = 67);
00966     void StopServer() {
00967       Close();
00968     }
00969     DHCPServer() {
00970       logfile = (LogFile*)NULL;
00971       dif = (DHCPInterface*)NULL;
00972     }
00973     void SetLogFile(LogFile *);
00974     void Log(char *);
00975     virtual void AsyncRead();   //a request has arrived
00976 };
00977 
00978 class DHCP : public Network, public SystemCode {  //client
00979   _PROTECTED_:
00980     IPAddr ip;
00981     IPAddr router;
00982     IPAddr dns1, dns2;
00983     String domain, host;
00984   public:
00985     BOOL Query(MAC &, IPAddr *ip, IPAddr *router, IPAddr *dns1, IPAddr *dns2, String *domain, String *host);
00986 };
00987 
00988 struct DNSRecord {
00989   String query;   //queried domain (for NS records this would be the domain it controls)
00990   uint16 type;    //see DNS_...
00991   uint8 *data;    //raw data
00992   String domain;  //for DNS_NS(auth server), DNS_CNAME(alias), DNS_MX(domain), DNS_SRV(domain)
00993   IPAddr ip;      //for DNS_A
00994   int Priority, Weight, Port;  //for DNS_SRV
00995   DNSRecord();
00996   ~DNSRecord();
00997 };
00998 
00999 //NOTE : Use Network::Lookup() & Network::LookupAll() instead
01000 class DNS : public Network, public SystemCode {
01001   private:
01002     BOOL _decode_string(int &pos, int &rlen, String &name);
01003     BOOL _decode_records(int &Count, Array<DNSRecord*> &records, int &pos, int &rlen);
01004     BOOL _query(char *domain, uint16 type, IPAddr &server);
01005     BOOL _is_ip(char *domain);
01006   public:
01007     uint8 data[512];
01008     uint32 datalen;
01009     Array<DNSRecord*> answers;      //A,MX,CNAME
01010     Array<DNSRecord*> authorities;  //NS
01011     Array<DNSRecord*> additionals;  //A of NS
01012 
01013     ~DNS();
01014     BOOL Query(char *domain, uint16 type);  //type = DNS_...
01015     void Clear();
01016 };
01017 

Generated on Mon Mar 5 09:49:14 2007 for DigiForce by  doxygen 1.4.7