Source: ../../libxorp/xorpfd.hh
|
|
|
|
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// vim:set sts=4 ts=8:
// Copyright (c) 2001-2009 XORP, Inc.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License, Version
// 2.1, June 1999 as published by the Free Software Foundation.
// Redistribution and/or modification of this program under the terms of
// any other version of the GNU Lesser General Public License is not
// permitted.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
// see the GNU Lesser General Public License, Version 2.1, a copy of
// which can be found in the XORP LICENSE.lgpl file.
//
// XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
// http://xorp.net
// $XORP: xorp/libxorp/xorpfd.hh,v 1.12 2009/01/05 18:30:58 jtc Exp $
#ifndef __LIBXORP_XORPFD_HH__
#define __LIBXORP_XORPFD_HH__
#include "xorp.h"
#include "c_format.hh"
/**
* @short XorpFd definition
*
* XorpFd is a wrapper class used to encapsulate a file descriptor.
*
* It exists because of fundamental differences between UNIX and Windows
* in terms of how the two families of operating systems deal with file
* descriptors; in most flavours of UNIX, all file descriptors are
* created equal, and may be represented using an 'int' type which is
* usually 32 bits wide. In Windows, sockets are of type SOCKET, which
* is a typedef alias of u_int; whereas all other system objects are
* of type HANDLE, which in turn is a typedef alias of 'void *'.
*
* The situation is made even more confusing by the fact that under
* Windows, SOCKETs and HANDLEs may both be passed to various Windows
* API functions.
*
* In order to prevent a situation where the developer has to explicitly
* cast all arguments passed to such functions (in order to keep the XORP
* code base compatible across all the operating systems we support), we
* define a wrapper class with casting operators for the underlying types.
*
* When constructed, we always initialize the encapsulated file descriptor
* to an invalid value appropriate to the OS under which we are running.
*
* The non-Windows case is very simple. We do not define both sets of
* functions at once so that the compiler will flag as an error those
* situations where file descriptors are being used in a UNIX-like way,
* i.e. where developers try to exploit the fact that UNIX file descriptors
* are monotonically increasing integers.
*
* XXX: Because Windows defines HANDLE in terms of a pointer, but also
* defines SOCKET in terms of a 32-bit-wide unsigned integer, beware of
* mixing 32-bit and 64-bit comparisons under Win64 when working with
* socket APIs (or indeed any C/C++ library which will potentially do
* work with sockets under Win64 such as libcomm).
*/
#ifdef HOST_OS_WINDOWS
#define BAD_XORPFD INVALID_HANDLE_VALUE
#else
#define BAD_XORPFD (-1)
#endif
#ifndef HOST_OS_WINDOWS
// Non-Windows code.
class XorpFd {
public:
XorpFd() : _filedesc(BAD_XORPFD) {}
XorpFd(int fd) : _filedesc(fd) {}
operator int() const { return _filedesc; }
string str() const { return c_format("%d", _filedesc); }
void clear() { _filedesc = BAD_XORPFD; }
bool is_valid() const { return (_filedesc != BAD_XORPFD); }
private:
int _filedesc;
};
#else // HOST_OS_WINDOWS
// Windows code.
class XorpFd {
public:
enum WinFdType {
FDTYPE_ERROR, // Invalid handle or method failure
FDTYPE_FILE, // Disk file
FDTYPE_CONSOLE, // Console or character device
FDTYPE_PIPE, // Named or anonymous pipe
FDTYPE_SOCKET, // Socket
FDTYPE_PROCESS, // Process handle
FDTYPE_OTHER // Unknown handle type
};
private:
//
// Helper function to return what kind of object the encapsulated
// Windows object handle points to. Optimized for sockets.
//
WinFdType get_type() const {
if (!this->is_valid())
return (FDTYPE_ERROR);
// Try to find invalid handles quickly at the cost of 1 syscall.
DWORD dwflags;
if (GetHandleInformation(*this, &dwflags) == 0)
return (FDTYPE_ERROR);
struct sockaddr_storage ss;
socklen_t len = sizeof(ss);
int ret = getsockname(*this, (struct sockaddr *)&ss, &len);
if (ret != -1)
return (FDTYPE_SOCKET);
else if (GetLastError() == WSAEINVAL)
return (FDTYPE_ERROR);
DWORD ntype = GetFileType(*this);
switch (ntype) {
case FILE_TYPE_CHAR:
return (FDTYPE_CONSOLE);
break;
case FILE_TYPE_DISK:
return (FDTYPE_FILE);
break;
case FILE_TYPE_PIPE:
return (FDTYPE_PIPE);
break;
default:
if (GetLastError() != NO_ERROR) {
if (0 != GetProcessId(*this)) {
return (FDTYPE_PROCESS);
}
return (FDTYPE_ERROR);
}
break;
}
return (FDTYPE_OTHER);
}
public:
XorpFd() : _filedesc(BAD_XORPFD), _type(FDTYPE_ERROR) {}
XorpFd(HANDLE h) : _filedesc(h), _type(get_type()) {}
// _get_osfhandle() returns a long. We need to force a call
// to get_type() to discover the underlying handle type.
XorpFd(long l)
: _filedesc(reinterpret_cast<HANDLE>(l)), _type(get_type())
{}
XorpFd(SOCKET s)
: _filedesc(reinterpret_cast<HANDLE>(s)), _type(FDTYPE_SOCKET)
{}
XorpFd(const XorpFd& rhand)
: _filedesc(rhand._filedesc), _type(rhand._type)
{}
operator HANDLE() const { return _filedesc; }
operator SOCKET() const { return reinterpret_cast<SOCKET>(_filedesc); }
void clear() { _filedesc = BAD_XORPFD; _type = FDTYPE_ERROR; }
string str() const { return c_format("%p", _filedesc); }
bool is_valid() const { return (_filedesc != BAD_XORPFD); }
WinFdType type() const { return _type; }
bool is_console() const { return (_type == FDTYPE_CONSOLE); }
bool is_process() const { return (_type == FDTYPE_PROCESS); }
bool is_pipe() const { return (_type == FDTYPE_PIPE); }
bool is_socket() const { return (_type == FDTYPE_SOCKET); }
// On Windows, HANDLE is a void *.
// Because there are several cast operators, and any may be
// invoked implicitly in the context of an expression containing
// an instance of XorpFd, we must disambiguate by providing
// comparison operators here.
bool operator ==(const XorpFd& rhand) const {
return (_filedesc == rhand._filedesc);
}
bool operator !=(const XorpFd& rhand) const {
return (_filedesc != rhand._filedesc);
}
bool operator >(const XorpFd& rhand) const {
return (_filedesc > rhand._filedesc);
}
bool operator <(const XorpFd& rhand) const {
return (_filedesc < rhand._filedesc);
}
private:
HANDLE _filedesc;
WinFdType _type;
};
#endif // HOST_OS_WINDOWS
#endif // __LIBXORP_XORPFD_HH__
Generated by: pavlin on kobe.xorp.net on Wed Jan 7 19:10:36 2009, using kdoc 2.0a54+XORP.