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

📄 sockutil.cpp

📁 伯克利做的SFTP安全文件传输协议
💻 CPP
📖 第 1 页 / 共 3 页
字号:
void SocketSet::reset(){  FD_ZERO(&set);  maxSocket = 0;  used = false;  numSockets = 0;}int SocketSet::select(bool read, bool write, bool except,                      /*const*/ struct timeval *timeout){  xassert(!used);  xassert(numSockets > 0);   // need at least one valid socket!  selectDiagnostic("blocked on select()");  int result = ::select(    maxSocket+1,                      // nfds    read? &set : (fd_set*)NULL,       // readfds    write? &set : (fd_set*)NULL,      // writefds    except? &set : (fd_set*)NULL,     // exceptfds    timeout);  if (result == SOCKET_ERROR) {    xsocket((SOCKET)NULL, "select");  }  selectDiagnostic("select() unblocked");  used = true;  return result;}// ----------------- xsocket -----------------------// compose a complete error message stringstring socketErrString(char const *msg){  int code = getSocketErrorCode();  char const *codetext = errorCodeString(code);  if (!codetext) {    codetext = "unknown error";  }  return stringb(    msg << ": " <<    codetext <<    " (code " << code << ")");}// handle an error// (originally had 3rd param named 'close'; that is a problem// on unix, where 'closesocket' is #defined to 'close')void xsocket(SOCKET s, char const *msg, bool doClose){  xSocket x(s, socketErrString(msg));  if (doClose &&      closesocket(s) != SOCKET_ERROR) {    decOpenSockets();  }  THROW(x);}void xsocketClosed(SOCKET s){  xSocket tmp(s);  THROW(tmp);}// ------------------- endian junk ---------------------// force the definition of either SAFETP_LITTLE_ENDIAN or SAFETP_BIG_ENDIAN#if !defined(SAFETP_LITTLE_ENDIAN) && !defined(SAFETP_BIG_ENDIAN)#  error define SAFETP_LITTLE_ENDIAN or SAFETP_BIG_ENDIAN#endif// return true if this is a big-endian machine, false if is// little-endian (reference to endianness discussion might// be nice here..)#if 0   // this code crashes gcc-2.95.2 -O2 on solaris/sparcbool isBigEndian(){  union {    int i;                  // machine word    byte b[sizeof(int)];    // b[0] overlaid with first byte of i  };  i = 0xFF;    // set lsb, zero all others  return b[0] != 0xFF;}#else   // 1// x must be global to work around an egcs-1.1.2 optimizer bugstatic int endianTestValue = 0;     // start with all bits 0bool isBigEndian(){  // little endian: sets endianTestValue to 1  // big endian: sets endianTestValue to a large number (e.g. 0x01000000 if 32 bits)  *((char*)(&endianTestValue)) = 1;  if (endianTestValue == 1) {    return false;   // little  }  else {    return true;    // big  }}#endif  // 0/1// --------------- nonportable routines ----------------------------#ifdef __WIN32__// (exported)// return string associated with a given codechar const *errorCodeString(int code){  static struct {    int code;    char const *message;  } const arr[] = {    { WSAEACCES,          "Broadcast address requested, proper flags not set" },    { WSAEADDRINUSE,      "Specified address already in use" },    { WSAEADDRNOTAVAIL,   "Address not available or accessible" },    { WSAEAFNOSUPPORT,    "Address format not supported" },    { WSAEALREADY,        "\"already\" something (?)" },    // already what?    { WSAEBADF,           "Bad file number" },    { WSAECONNABORTED,    "Connection aborted, possibly due to timeout" },    { WSAECONNREFUSED,    "Connection refused" },    { WSAECONNRESET,      "Connection reset by remote side" },    { WSAEDESTADDRREQ,    "Destination address required" },    { WSAEDISCON,         "Socket disconnected" },    { WSAEDQUOT,          "\"DQUOT\" (?)" },     // what does this mean?    { WSAEFAULT,          "Memory buffer too small" },    { WSAEHOSTDOWN,       "Remote host is down" },    { WSAEHOSTUNREACH,    "Remote host is unreachable" },    { WSAEINPROGRESS,     "Blocking call in progress" },    { WSAEINTR,           "Blocking call interrupted" },    { WSAEINVAL,          "Invalid parameter" },    { WSAEISCONN,         "Socket already connected" },    { WSAELOOP,           "Routing loop discovered (?)" },    { WSAEMFILE,          "No more file descriptors available" },    { WSAEMSGSIZE,        "Message size exceeds maximum datagram size" },    { WSAENAMETOOLONG,    "Name too long" },    { WSAENETDOWN,        "Network subsystem failure detected" },    { WSAENETRESET,       "Connection was reset" },    { WSAENETUNREACH,     "Network is unreachable" },    { WSAENOBUFS,         "Insufficient buffer space available" },    { WSAENOPROTOOPT,     "Invalid protocol option" },    { WSAENOTCONN,        "Socket is not connected" },    { WSAENOTEMPTY,       "Buffer not empty" },    { WSAENOTSOCK,        "Connection is already closed" },    { WSAEOPNOTSUPP,      "Operation not supported (e.g. OOB)" },    { WSAEPFNOSUPPORT,    "Protocol family not supported" },    { WSAEPROCLIM,        "\"PROCLIM\" (?)" },    // anyone know what this means?    { WSAEPROTONOSUPPORT, "The specified protocol is not supported" },    { WSAEPROTOTYPE,      "Specified protocol is wrong type" },    { WSAEREMOTE,         "Error at remote host" },    { WSAESHUTDOWN,       "Socket has been shut down" },    { WSAESOCKTNOSUPPORT, "Socket type not supported" },    { WSAESTALE,          "Stale handle" },    { WSAETIMEDOUT,       "Connection timed out" },    { WSAETOOMANYREFS,    "Too many references" },    { WSAEUSERS,          "Too many users" },    { WSAEWOULDBLOCK,     "Asynchronous operation cannot be scheduled" },    { WSAHOST_NOT_FOUND,  "Authoritative Answer Host not found" },    { WSANO_ADDRESS,      "No address, look for MX record (?)" },    { WSANO_DATA,         "Valid name, no data record of requested type" },    { WSANO_RECOVERY,     "Non-recoverable error" },    { WSANOTINITIALISED,  "Winsock not initialized" },    { WSASYSNOTREADY,     "Network subsystem not ready" },    { WSATRY_AGAIN,       "Non-Authoritative Host not found" },    { WSAVERNOTSUPPORTED, "Winsock version not supported" },    { 0,                  "No error" }  };  loopi(TABLESIZE(arr)) {    if (arr[i].code == code) {      return arr[i].message;    }  }  // unknown code  return NULL;}// (exported)int getSocketErrorCode(){   return WSAGetLastError();}// (exported)void socket_lib_init(){  WSADATA d;  if (0 != WSAStartup(MAKEWORD(1,1), &d)) {    xsocket(INVALID_SOCKET, "WSAStartup");  }  // randomize  srand(getProcessId());}// (exported)void socket_lib_deinit(){  // added this because Dan says he wants sftpd to do this  WSACleanup();}#else                   //  --  win32 above, unix below  --#include <errno.h>      // errno, strerrorchar const *errorCodeString(int code){  return strerror(code);}int getSocketErrorCode(){  return errno;}void socket_lib_init(){  // nothing special required for berkeley sockets  // but I want to randomize rand() so that two different  // server processes won't request the same sequence of ports  // (which would exacerbate the reliability problem with  // SO_REUSEADDR)  srand(getProcessId());}void socket_lib_deinit(){  // nothing special required for berkeley sockets}#endif //    ^^ unix// --------------------- test code ----------------------#ifdef TEST_SOCKUTIL#include "test.h"    // USUAL_MAIN#ifdef __UNIX__#include <sys/wait.h>     // wait// actually try to make some connections and send some datavoid communicationTests(){  printf("start of communicationTests\n");  int childPid = fork();  if (childPid != 0) {    // --------------- parent ---------------    // don't let this take too long    alarm(20);    // listen for a connection from the child    printf("parent: waiting for child to connect\n");    SOCKET listener = interface_listen_socket(INADDR_LOOPBACK, 2345);    SOCKET s = accept_socket(listener);    close_socket(listener);    // connected; send something trivial    printf("parent: sending int\n");    sendNBO32(s, 0x4567890A);    // receive something trivial    printf("parent: waiting for char\n");    char ch = recvChar(s);    printf("parent: received char: %c\n", ch);    xassert(ch == 'x');    // listen on a range    printf("parent: making a range listener\n");    PortRange range(5000,5050);    listener = interface_listen_socket_range(INADDR_LOOPBACK, range);    // check that we got a port in the range requested    int port = getLocalPort(listener);    printf("parent: got a listener on port %d\n", port);    xassert(5000 <= port && port <= 5050);    // tell the client which port we got    sendNBO32(s, (unsigned long)port);        // wait for the connection    SOCKET t = accept_socket(listener);    close_socket(listener);    printf("parent: got child's second connection\n");        // close everything down    close_socket(t);    close_socket(s);    // wait for child to exit    int status;    wait(&status);    printf("parent: child exited with code %d\n", status);    xassert(status == 0);  }  else {    // ---------------- child ---------------    // wait for parent to be ready to accept a connection    sleep(1);    // connect to parent    printf("child: connecting\n");    SOCKET s = connect_socket(INADDR_LOOPBACK, 2345);    // receive the integer    printf("child: connected; waiting for int\n");    unsigned long val = recvNBO32(s);    printf("child: received 0x%lX\n", val);    xassert(val == 0x4567890A);    // send a char    printf("child: sending char\n");    sendChar(s, 'x');    // receive port that parent is now listening at    int remotePort = (int)recvNBO32(s);    // connect to it, using a range for my local port    printf("child: connecting to parent at port %d\n", remotePort);    PortRange range(6000,6070);    SOCKET t = connect_socket(INADDR_LOOPBACK, remotePort, &range);    // verify range    int localPort = getLocalPort(t);    printf("child: my local port is %d\n", localPort);    xassert(6000 <= localPort && localPort <= 6070);    // close it all down    close_socket(t);    close_socket(s);    exit(0);  }    printf("end of communicationTests\n");}    #else  // windowsvoid communicationTests(){  // windows doesn't have fork (right?) so this would be more painful..  // forget it}#endif // !__UNIX__void testParseDottedDecimal(char const *decimal, IPAddress expected){  try {    IPAddress got = parseDottedDecimal(decimal);    xassert(got == expected);  }  catch (...) {    // did we expect the failure?    xassert(expected == INADDR_NONE);  }}void testParseAddrAndPort(char const *addrAndPort,                          IPAddress expAddr, int expPort){  try {    IPAddress gotAddr;    int gotPort;    parseAddrAndPort(gotAddr, gotPort, addrAndPort);    xassert(gotAddr == expAddr && gotPort == expPort);  }  catch (...) {    xassert(expAddr == INADDR_NONE);  }}int entry(){  socket_lib_init();  // reduce clutter  xBase::logExceptions = false;  // verify endianness  #if defined(SAFETP_LITTLE_ENDIAN)    if (isBigEndian()) {      xfailure("SAFETP_LITTLE_ENDIAN is defined but isBigEndian() returns true");    }  #elif defined(SAFETP_BIG_ENDIAN)    if (!isBigEndian()) {      xfailure("SAFETP_BIG_ENDIAN is defined but isBigEndian() returns false");    }  #else    xfailure("neither SAFETP_LITTLE_ENDIAN nor SAFETP_BIG_ENDIAN are defined");  #endif  // test vectors for parseDottedDecimal  testParseDottedDecimal("1.2.3.4", 0x01020304);  testParseDottedDecimal("0.0.0.0", 0);  testParseDottedDecimal("255.255.255.255", 0xffffffff);  testParseDottedDecimal("1234", INADDR_NONE);  // test vectors for parseAddrAndPort  testParseAddrAndPort("1.2.3.4:5", 0x01020304, 5);  testParseAddrAndPort("67", INADDR_ANY, 67);  testParseAddrAndPort(":", INADDR_NONE, 0);  testParseAddrAndPort("2.3.4.5:", INADDR_NONE, 0);  // verify that binding the same port twice doesn't work (at least  // from the same process...)  SOCKET s = listen_socket(3456);  try {    listen_socket(3456);    xfailure("it let me bind the same port twice!");  }  catch (xSocket&) {    printf("good: it didn't let me bind the same port twice\n");  }  close_socket(s);  communicationTests();  printf("sockutil passed tests\n");  socket_lib_deinit();  return 0;}USUAL_MAIN#endif // TEST_SOCKUTIL

⌨️ 快捷键说明

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