log4cplus  2.0.0
socket.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 // Module:  Log4CPLUS
00003 // File:    socket.h
00004 // Created: 1/2010
00005 // Author:  Vaclav Haisman
00006 //
00007 //
00008 //  Copyright (C) 2010-2015, Vaclav Haisman. All rights reserved.
00009 //
00010 //  Redistribution and use in source and binary forms, with or without modifica-
00011 //  tion, are permitted provided that the following conditions are met:
00012 //
00013 //  1. Redistributions of  source code must  retain the above copyright  notice,
00014 //     this list of conditions and the following disclaimer.
00015 //
00016 //  2. Redistributions in binary form must reproduce the above copyright notice,
00017 //     this list of conditions and the following disclaimer in the documentation
00018 //     and/or other materials provided with the distribution.
00019 //
00020 //  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
00021 //  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
00022 //  FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
00023 //  APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
00024 //  INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
00025 //  DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
00026 //  OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
00027 //  ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
00028 //  (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
00029 //  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 
00037 #ifndef LOG4CPLUS_INTERNAL_SOCKET_H_
00038 #define LOG4CPLUS_INTERNAL_SOCKET_H_
00039 
00040 #include <log4cplus/config.hxx>
00041 
00042 #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
00043 #pragma once
00044 #endif
00045 
00046 #if ! defined (INSIDE_LOG4CPLUS)
00047 #  error "This header must not be be used outside log4cplus' implementation files."
00048 #endif
00049 
00050 #if defined(_WIN32)
00051 #include <log4cplus/config/windowsh-inc.h>
00052 #endif
00053 #include <log4cplus/helpers/socket.h>
00054 
00055 #include <cerrno>
00056 #ifdef LOG4CPLUS_HAVE_ERRNO_H
00057 #include <errno.h>
00058 #endif
00059 
00060 #ifdef LOG4CPLUS_HAVE_UNISTD_H
00061 #include <unistd.h>
00062 #endif
00063 
00064 #if defined (LOG4CPLUS_HAVE_NETDB_H)
00065 #include <netdb.h>
00066 #endif
00067 
00068 
00069 namespace log4cplus {
00070 
00071 namespace helpers {
00072 
00073 #if defined(_WIN32)
00074 typedef SOCKET os_socket_type;
00075 os_socket_type const INVALID_OS_SOCKET_VALUE = INVALID_SOCKET;
00076 
00077 struct ADDRINFOT_deleter
00078 {
00079     void
00080     operator () (ADDRINFOA * ptr) const
00081     {
00082         FreeAddrInfoA(ptr);
00083     }
00084 
00085     void
00086     operator () (ADDRINFOW * ptr) const
00087     {
00088         FreeAddrInfoW(ptr);
00089     }
00090 };
00091 
00092 
00093 struct socket_closer
00094 {
00095     void
00096     operator () (SOCKET s)
00097     {
00098         if (s && s != INVALID_OS_SOCKET_VALUE)
00099         {
00100             DWORD const eno = WSAGetLastError();
00101             ::closesocket(s);
00102             WSASetLastError(eno);
00103         }
00104     }
00105 };
00106 
00107 
00108 #else
00109 typedef int os_socket_type;
00110 os_socket_type const INVALID_OS_SOCKET_VALUE = -1;
00111 
00112 
00113 struct addrinfo_deleter
00114 {
00115     void
00116     operator () (struct addrinfo * ptr) const
00117     {
00118         freeaddrinfo(ptr);
00119     }
00120 };
00121 
00122 
00123 struct socket_closer
00124 {
00125     void
00126     operator () (os_socket_type s)
00127     {
00128         if (s >= 0)
00129         {
00130             int const eno = errno;
00131             close(s);
00132             errno = eno;
00133         }
00134     }
00135 };
00136 
00137 #endif
00138 
00139 
00140 struct socket_holder
00141 {
00142     os_socket_type sock;
00143 
00144     socket_holder()
00145         : sock(INVALID_OS_SOCKET_VALUE)
00146     { }
00147 
00148     socket_holder(os_socket_type s)
00149         : sock(s)
00150     { }
00151 
00152     ~socket_holder()
00153     {
00154         socket_closer()(sock);
00155     }
00156 
00157     void
00158     reset(os_socket_type s = INVALID_OS_SOCKET_VALUE)
00159     {
00160         if (sock != INVALID_OS_SOCKET_VALUE)
00161             socket_closer()(sock);
00162 
00163         sock = s;
00164     }
00165 
00166     os_socket_type
00167     detach()
00168     {
00169         os_socket_type s = sock;
00170         sock = INVALID_OS_SOCKET_VALUE;
00171         return s;
00172     }
00173 
00174     socket_holder(socket_holder &&) = delete;
00175     socket_holder(socket_holder const &) = delete;
00176 
00177     socket_holder operator = (socket_holder &&) = delete;
00178     socket_holder operator = (socket_holder const &) = delete;
00179 };
00180 
00181 
00182 static inline
00183 os_socket_type
00184 to_os_socket (SOCKET_TYPE const & x)
00185 {
00186     return static_cast<os_socket_type>(x);
00187 }
00188 
00189 
00190 static inline
00191 SOCKET_TYPE
00192 to_log4cplus_socket (os_socket_type const & x)
00193 {
00194     return static_cast<SOCKET_TYPE>(x);
00195 }
00196 
00197 
00198 static inline
00199 void
00200 set_last_socket_error (int err)
00201 {
00202     errno = err;
00203 }
00204 
00205 
00206 static inline
00207 int
00208 get_last_socket_error ()
00209 {
00210     return errno;
00211 }
00212 
00213 
00214 } // namespace helpers {
00215 
00216 } // namespace log4cplus {
00217 
00218 
00219 #endif // LOG4CPLUS_INTERNAL_SOCKET_H_