⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockutil.h

📁 伯克利做的SFTP安全文件传输协议
💻 H
字号:
// sockutil.h// some utilities built on top of sockets layer// copyright SafeTP Development Group, Inc., 2000  Terms of use are as specified in license.txt#ifndef __SOCKUTIL_H#define __SOCKUTIL_H#include "socket.h"      // socket funcs, fd_set, timeval#include "str.h"         // string#include "exc.h"         // exceptions#ifdef _MSC_VER  // MSVC may have a definition for this#ifdef interface#undef interface#endif#endif// ----------------- exceptions -----------------------// thrown by SOCKET funcsclass xSocket : public xBase {public:  SOCKET socket;       // socket on which failure occurred  bool graceful;       // true if is simple graceful closure  bool temporary;      // true if the failure might go away if we wait a while                       // (this field is set to false initially)  // for now, does not include much information for diagnosing  // the problem and recovering, because I'm not sure what  // info I want; however, all xSocket exceptions *do* imply  // that the socket has been closedpublic:  // error condition ctor  xSocket(SOCKET s, char const *msg);  // simple socket-closed ctor  xSocket(SOCKET s);  xSocket(xSocket const &obj);  ~xSocket();};// thrown by resolveHostNameclass xResolveFailure : public xBase {public:  string hostname;       // name we failed to mappublic:  xResolveFailure(char const *hostname);  xResolveFailure(xResolveFailure const &obj);  ~xResolveFailure();};// ---------------- open-socket counting ----------------------// this is (# of successful socket()/accept() calls) -//           (# of successful closesocket() calls)// sm: hiding this name because of thread-safety concerns//extern int socketsOpen;// this is (# of successful socket()/accept() calls) -//           (# of successful closesocket() calls)int numSocketsOpen();// inc/decrement the open-sockets countvoid incOpenSockets();void decOpenSockets();// ---------------- standalone funcs ----------------------// ------ receive helpers ------// block until next character read from socket// (relies on OS internal buffering...)char recvChar(SOCKET s);// block until next line (terminated by CRLF) is received// (very inefficient due to use of recvChar!)string recvLine(SOCKET s);// return the next string that appears on the wire, but don't// remove it from the network buffers; block until such a string// arrives; returns the string *without* the CRLF itself.// (also see notes in sockutil.cpp)string peekLine(SOCKET s);// read 4 bytes, convert from network byte order to host byte order,// and return them as an integerunsigned long recvNBO32(SOCKET s);// read 'len' bytes from 's', blocking as necessary; throws an// exception if EOF happens firstvoid recvAll(SOCKET s, char *buf, int len);// read up to 'len' bytes; may read less if EOF encountered; either// way, returns the # of bytes read (may be 0 for immediate EOF)int recvAllToEOF(SOCKET s, char *buf, int len);// block until at least one byte arrives, then read what is waiting,//   up to 'len' bytes// returns # of bytes actually read// returns 0 if the socket has been closed// throws an exception on error// intent is to route all receives through this fn, rather than calling//   recv() directlyint basicRecv(SOCKET s, char *buf, int len);// ------ send helpers ------// send a single charactervoid sendChar(SOCKET s, char c);// send all of 'buf', blocking as necessaryvoid sendAll(SOCKET s, char const *buf, int len);// calls sendAll(s, str, strlen(str))void sendAllString(SOCKET s, char const *str);// send end-of-line sequence (CRLF)void sendEOL(SOCKET s);// write value, as 4 bytes in network byte order, to 's'void sendNBO32(SOCKET s, unsigned long value);// block until we can send at least one byte;//   send up to 'len' bytes of 'data' to socket 's'// returns the # of bytes actually sent// returns 0 if the other side has closed the socket// throws exception on error// intent is to do all sends via this fn, rather than send() directlyint basicSend(SOCKET s, char const *data, int len);// ------ error handlers ------// generic socket error handler//   'msg' is normally the name of the socket lib function that failed//   's' is the socket on which the error occurred, or (SOCKET)NULL if//       no particular socket is to blame (e.g. select() failure)//   when 'close' is true, this fn will try to close the socket// it is generally expected that this fn throws an exception;// an alternative is to print a message and call exit or abort// (letting this fn return normally is very risky)void xsocket(SOCKET s, char const *msg, bool close=false);// throw the xsocket exception, with 'graceful' = truevoid xsocketClosed(SOCKET s);// ------ error determination ------// map an error code into a human-readable string, null-terminated but// with no newline, or NULL if the code is not understood; the returned// pointer must be treated as a pointer to a static area that will be// overwritten by the next call, even that is not necessarily true on// some systemschar const *errorCodeString(int socket_error_code);// return the error code for use with errorCodeString; only defined after// a socket function returns an error code (usually either SOCKET_ERROR// or INVALID_SOCKET)int getSocketErrorCode();// compose a complete error message string (msg is as in xsocket)string socketErrString(char const *msg);// ------ socket open and close ------// defines a range of allowable ports for use in some operation, or// says that any port is acceptableclass PortRange {public:  bool restricted;       // when true, use only ports from the given range  int low, high;         // allowable range; endpoints are *allowed*public:  PortRange();           // defaults to unrestricted  PortRange(int L, int H) {    setRange(L, H);  }  void setRange(int L, int H) {    low = L;    high = H;    restricted = true;  }};// create a listener socket to listen to a particular port on a// particular interface; if port=PORT_ANY, the OS picks the port to// listen toenum { PORT_ANY=0 };SOCKET interface_listen_socket(IPAddress interface, int port);// this one listens to the given port on *all* interfacesinline SOCKET listen_socket(int port)  { return interface_listen_socket(INADDR_ANY, port); }// this tries to bind any port in the specified range; eventually// it will give up and throw xSocket (with temporary=true) if it can'tSOCKET interface_listen_socket_range(IPAddress interface,                                     PortRange const &range);// accept a connection on the given listening socketSOCKET accept_socket(SOCKET s);// create a socket and connect it to a remote host/port; optionally// constrain the locally-bound port to 'range'SOCKET connect_socket(IPAddress ipaddr, int port,                      PortRange const *range = NULL);// close the socket; two reasons to not call OS directly://  - winsock uses closesocket() whereas UNIX uses close()//  - this fn calls xsocket on failurevoid close_socket(SOCKET s);// ------ endpoint queries ------// retrieve socket local address and local portvoid getSockName(SOCKET s, sockaddr_in &addr);IPAddress getLocalAddress(SOCKET s);int getLocalPort(SOCKET s);// retrieve socket remote address and remote portvoid getSockPeer(SOCKET s, sockaddr_in &addr);IPAddress getRemoteAddress(SOCKET s);int getRemotePort(SOCKET s);// ------ nonblocking tests ------// returns true if 's' has been closedbool isClosed(SOCKET s);// throw xSocket if 's' is closedvoid checkClosed(SOCKET s);// return true if the named socket has data waiting// (or has been closed, etc.)bool pollReadable(SOCKET s);// true if this socket is a listener socket// (always returns false under some systems.. :(   )bool isListening(SOCKET s);// ------ formatting ------// return string of form, "n.n.n.n"string formatAddress(IPAddress addr);// return string of form, "n.n.n.n, port m"string formatAddress(IPAddress addr, int port);// return a string of the form, "n.n.n.n, port m"string formatAddress(sockaddr_in const &saddr);// ------ most socket state ------// print to stdout info about local and remote endpoint names (host/port)void printSocketInfo(SOCKET s);// complete socket information, in form://   [l.l.l.l:p - r.r.r.r:q]//     l - local address//     p - local port//     r - remote address//     q - remote port// traps any exceptions, and prints if is listenerstring sockInfo(SOCKET s);// ------ system init/deinit ------// system-specific initializationvoid socket_lib_init();// similar deinitialization (needed only for Winsock...)void socket_lib_deinit();// ------ other random funcs ------// simple endianness check for the machine we're running onbool isBigEndian();// return the port number of a service, or 0 for not found// (the return value is in *host* byte order, unlike//  getservbyname(), the function this calls)int getServByName(char const *serviceName);// (blocking)// map string into address; correctly handles addresses in// decimal-dot notationIPAddress resolveHostName(char const *hostname);// -------------- parsing ---------------// given an address in "AAA.BBB.CCC.DDD" format, return the address// as an IPAddress; throws an exception if the address format is// invalidIPAddress parseDottedDecimal(char const *decimalAddr);// if 'addrAndPort' is of the form "AAA.BBB.CCC.DDD:PPPP", return with// 'ipaddr' equal to parsed AAA...DDD, and 'port' equal to parsed PPPP;// if 'addrAndPort' is of form "PPPP", return with 'ipaddr' set to// INADDR_ANY and 'port' set to parsed PPPP; any others will result in// a formatting exception being thrownvoid parseAddrAndPort(IPAddress &ipaddr, int &port, char const *addrAndPort);// ---------------- SocketSet -------------------// implements a set of sockets to improve the interface to select()://  - automate calculation of 'nfds', the first parameter to select//  - automatically call FD_ZERO//  - call xsocket when select() fails// I had originally been more ambitious about what this class would do,//   but limitations on easily available data structures reduced it to//   handling only the simplest casesclass SocketSet {private:      // data  fd_set set;          // socket api data structure  unsigned maxSocket;  // largest value of any SOCKET in the set  bool used;           // when true, must reset before another use  int numSockets;      // # of (valid) sockets added  static timeval timeZero;    // {0,0}, the "poll" timeout valuepublic:       // funcs  SocketSet();         // init to empty  ~SocketSet();        // dealloc  // ----- selectors -----  // determine if a specific socket is in the set  bool contains(SOCKET s) const;  // # of sockets added that were valid  // (we have this fn to code can add a bunch of sockets, some of which  // might be invalid, then ask how many were in fact valid)  int numAdded() const { return numSockets; }  // ----- mutators -----  // add the given socket to the set, unless the socket is INVALID_SOCKET,  // in which case it is not an error but nothing is changed  void add(SOCKET s);  // return to state where no sockets are in set,  // and thus allow re-use of the object  void reset();  // the select call:  //  - sets 'used', so must reset() before next add() or select()  //  - returns socket select()'s return value, unless select()  //    returns SOCKET_ERROR, in which case xsocket() is called  //  - this set is modified by the call, such that the sockets stll  //    in the set are the ones select() is saying have new information  //  - r/w/e are used to determine whether to pass this set as each of  //    the corresponding select() arguments; at least one of these must  //    be set to true  // the 'const' is commented out because some systems have select declared  // with non-const 'timeout' parameter.. I don't know if these systems  // actually modify timeout, or are just declared incorrectly; caller code  // probably should be prepared for the former  int select(bool read, bool write, bool except,             /*const*/ struct timeval *timeout);  // block until one of the sockets is readable, return how many there are then  int blockUntilReadable()    { return select(true, false, false, NULL); }  // return immediately the # of readable sockets  int pollReadable()    { return select(true, false, false, &timeZero); }};#endif // __SOCKUTIL_H

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -