xorp

xorpfd.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 // vim:set sts=4 ts=8:
00003 
00004 // Copyright (c) 2001-2011 XORP, Inc and Others
00005 //
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU Lesser General Public License, Version
00008 // 2.1, June 1999 as published by the Free Software Foundation.
00009 // Redistribution and/or modification of this program under the terms of
00010 // any other version of the GNU Lesser General Public License is not
00011 // permitted.
00012 // 
00013 // This program is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00016 // see the GNU Lesser General Public License, Version 2.1, a copy of
00017 // which can be found in the XORP LICENSE.lgpl file.
00018 // 
00019 // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00020 // http://xorp.net
00021 
00022 #ifndef __LIBXORP_XORPFD_HH__
00023 #define __LIBXORP_XORPFD_HH__
00024 
00025 #include "xorp.h"
00026 
00027 #include "c_format.hh"
00028 
00067 #ifdef HOST_OS_WINDOWS
00068 #define BAD_XORPFD  INVALID_HANDLE_VALUE
00069 #else
00070 #define BAD_XORPFD  (-1)
00071 #endif
00072 
00073 #ifndef HOST_OS_WINDOWS
00074 // Non-Windows code.
00075 class XorpFd {
00076 public:
00077     XorpFd() : _filedesc(BAD_XORPFD) {}
00078 
00079     XorpFd(int fd) : _filedesc(fd) {}
00080 
00081     operator int() const  { return _filedesc; }
00082     int getSocket() const { return _filedesc; }
00083 
00084     string str() const      { return c_format("%d", _filedesc); }
00085 
00086     void clear()        { _filedesc = BAD_XORPFD; }
00087 
00088     bool is_valid() const   { return (_filedesc != BAD_XORPFD); }
00089 
00090 private:
00091     int     _filedesc;
00092 };
00093 
00094 #else // HOST_OS_WINDOWS
00095 // Windows code.
00096 class XorpFd {
00097 public:
00098     enum WinFdType {
00099     FDTYPE_ERROR,       // Invalid handle or method failure
00100     FDTYPE_FILE,        // Disk file
00101     FDTYPE_CONSOLE,     // Console or character device
00102     FDTYPE_PIPE,        // Named or anonymous pipe
00103     FDTYPE_SOCKET,      // Socket
00104     FDTYPE_PROCESS,     // Process handle
00105     FDTYPE_OTHER        // Unknown handle type
00106     };
00107 
00108 private:
00109     //
00110     // Helper function to return what kind of object the encapsulated
00111     // Windows object handle points to. Optimized for sockets.
00112     //
00113     WinFdType get_type() const {
00114     if (!this->is_valid())
00115         return (FDTYPE_ERROR);
00116 
00117     // Try to find invalid handles quickly at the cost of 1 syscall.
00118     DWORD dwflags;
00119     if (GetHandleInformation(*this, &dwflags) == 0)
00120         return (FDTYPE_ERROR);
00121 
00122     struct sockaddr_storage ss;
00123     socklen_t len = sizeof(ss);
00124     int ret = getsockname(getSocket(), (struct sockaddr *)&ss, &len);
00125     if (ret != -1)
00126         return (FDTYPE_SOCKET);
00127     else if (GetLastError() == WSAEINVAL)
00128         return (FDTYPE_ERROR);
00129 
00130     DWORD ntype = GetFileType(*this);
00131     switch (ntype) {
00132     case FILE_TYPE_CHAR:
00133         return (FDTYPE_CONSOLE);
00134         break;
00135     case FILE_TYPE_DISK:
00136         return (FDTYPE_FILE);
00137         break;
00138     case FILE_TYPE_PIPE:
00139         return (FDTYPE_PIPE);
00140         break;
00141     default:
00142         if (GetLastError() != NO_ERROR) {
00143         if (0 != GetProcessId(*this)) {
00144             return (FDTYPE_PROCESS);
00145         }
00146         return (FDTYPE_ERROR);
00147         }
00148         break;
00149     }
00150 
00151     return (FDTYPE_OTHER);
00152     }
00153 
00154 public:
00155     XorpFd() : _filedesc(BAD_XORPFD), _type(FDTYPE_ERROR) {}
00156 
00157     XorpFd(HANDLE h) : _filedesc(h), _type(get_type()) {}
00158 
00159     // _get_osfhandle() returns a long. We need to force a call
00160     // to get_type() to discover the underlying handle type.
00161     XorpFd(long l)
00162      : _filedesc(reinterpret_cast<HANDLE>(l)), _type(get_type())
00163     {}
00164 
00165     XorpFd(SOCKET s)
00166      : _filedesc(reinterpret_cast<HANDLE>(s)), _type(FDTYPE_SOCKET)
00167     {}
00168 
00169     XorpFd(const XorpFd& rhand)
00170      : _filedesc(rhand._filedesc), _type(rhand._type)
00171     {}
00172 
00173     operator HANDLE() const { return _filedesc; }
00174 
00175     operator SOCKET() const { return getSocket(); }
00176 
00177     SOCKET getSocket() const { return reinterpret_cast<SOCKET>(_filedesc); }
00178 
00179     void clear() { _filedesc = BAD_XORPFD; _type = FDTYPE_ERROR; }
00180 
00181     string str() const { return c_format("%p", _filedesc); }
00182 
00183     bool is_valid() const { return (_filedesc != BAD_XORPFD); }
00184 
00185     WinFdType type() const { return _type; }
00186 
00187     bool is_console() const { return (_type == FDTYPE_CONSOLE); }
00188 
00189     bool is_process() const { return (_type == FDTYPE_PROCESS); }
00190 
00191     bool is_pipe() const { return (_type == FDTYPE_PIPE); }
00192 
00193     bool is_socket() const { return (_type == FDTYPE_SOCKET); }
00194 
00195     // On Windows, HANDLE is a void *.
00196     // Because there are several cast operators, and any may be
00197     // invoked implicitly in the context of an expression containing
00198     // an instance of XorpFd, we must disambiguate by providing
00199     // comparison operators here.
00200 
00201     bool operator ==(const XorpFd& rhand) const {
00202     return (_filedesc == rhand._filedesc);
00203     }
00204 
00205     bool operator !=(const XorpFd& rhand) const {
00206     return (_filedesc != rhand._filedesc);
00207     }
00208 
00209     bool operator >(const XorpFd& rhand) const {
00210     return (_filedesc > rhand._filedesc);
00211     }
00212 
00213     bool operator <(const XorpFd& rhand) const {
00214     return (_filedesc < rhand._filedesc);
00215     }
00216 
00217 private:
00218     HANDLE  _filedesc;
00219     WinFdType   _type;
00220 };
00221 #endif // HOST_OS_WINDOWS
00222 
00223 #endif // __LIBXORP_XORPFD_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations