/**
 * @file /include/ecl/devices/detail/socket_error_handler_pos.hpp
 *
 * @brief Defines error handlers for posix sockets.
 *
 * @date September 2009
 **/
/*****************************************************************************
** Ifdefs
*****************************************************************************/

#ifndef ECL_DEVICES_SOCKET_ERROR_HANDLER_POS_HPP_
#define ECL_DEVICES_SOCKET_ERROR_HANDLER_POS_HPP_

/*****************************************************************************
** Cross platform
*****************************************************************************/

#include <ecl/config/ecl.hpp>
#ifndef ECL_IS_APPLE
#ifdef ECL_IS_POSIX

/*****************************************************************************
** Includes
*****************************************************************************/

#include <errno.h>
#include <string>
#include <ecl/errors/handlers.hpp>
#include <netdb.h> // gethostbyname

/*****************************************************************************
** Namespaces
*****************************************************************************/

namespace ecl {
namespace devices {

/*****************************************************************************
** Methods
*****************************************************************************/
/**
 * This function generates a custom ecl::Error response
 * for posix error numbers generated by posix <i>socket</i> calls.
 * @return Error : the error type.
 */
inline ecl::Error socket_error() {
  switch( errno ) {
      case ( EACCES )     : return ecl::Error(ecl::OpenError);
      case ( EAFNOSUPPORT): return ecl::Error(ecl::NotSupportedError);
      case ( EINVAL )     : return ecl::Error(ecl::InvalidArgError);
      case ( EMFILE )     : return ecl::Error(ecl::OutOfRangeError);
      case ( ENFILE )     : return ecl::Error(ecl::OutOfResourcesError);
      case ( ENOBUFS )    : return ecl::Error(ecl::MemoryError);
      case ( ENOMEM )     : return ecl::Error(ecl::MemoryError);
      case ( EPROTONOSUPPORT )    : return ecl::Error(ecl::NotSupportedError);
              default             : return ecl::Error(UnknownError);
  }
}
/**
 * This function generates a custom ecl::Error response
 * for posix error numbers generated by posix <i>bind</i> calls.
 * @return Error : the error type.
 */
inline ecl::Error bind_error() {
  switch( errno ) {
      case ( EACCES )     : return ecl::Error(ecl::PermissionsError);
      case ( EADDRINUSE ) : return ecl::Error(ecl::BusyError);
      case ( EBADF )      : return ecl::Error(ecl::InvalidObjectError);
      case ( EINVAL )     : return ecl::Error(ecl::BusyError);
      case ( ENOTSOCK )   : return ecl::Error(ecl::InvalidObjectError);
      case ( EADDRNOTAVAIL ) : return ecl::Error(ecl::InvalidObjectError);
      case ( EFAULT )     : return ecl::Error(ecl::OutOfRangeError);
      case ( ELOOP )      : return ecl::Error(ecl::SystemFailureError);
      case ( ENAMETOOLONG )  : return ecl::Error(ecl::InvalidArgError);
      case ( ENOENT )     : return ecl::Error(ecl::InvalidObjectError);
      case ( ENOMEM )     : return ecl::Error(ecl::MemoryError);
      case ( ENOTDIR )    : return ecl::Error(ecl::InvalidArgError);
      case ( EROFS )      : return ecl::Error(ecl::PermissionsError);
              default             : return ecl::Error(UnknownError);
  }
}
/**
 * This function generates a custom ecl::Error response
 * for posix error numbers generated by posix <i>accept</i> calls.
 * @return Error : the error type.
 */
inline ecl::Error accept_error() {
  switch( errno ) {
              case ( EWOULDBLOCK ) : return ecl::Error(ecl::BlockingError);
              case ( EBADF )       : return ecl::Error(ecl::InvalidObjectError);
              case ( ECONNABORTED ): return ecl::Error(ecl::InterruptedError);
              case ( EINTR )       : return ecl::Error(ecl::InterruptedError);
              case ( EINVAL )      : return ecl::Error(ecl::UsageError);
              case ( EMFILE )      : return ecl::Error(ecl::OutOfResourcesError);
              case ( ENFILE )      : return ecl::Error(ecl::OutOfResourcesError);
              case ( ENOTSOCK )    : return ecl::Error(ecl::InvalidObjectError);
              case ( EOPNOTSUPP )  : return ecl::Error(ecl::InvalidObjectError);
              case ( EFAULT )      : return ecl::Error(ecl::PermissionsError);
              case ( ENOBUFS )     : return ecl::Error(ecl::MemoryError);
              case ( ENOMEM )      : return ecl::Error(ecl::MemoryError);
              case ( EPROTO )      : return ecl::Error(ecl::InvalidArgError);
              case ( EPERM )       : return ecl::Error(ecl::PermissionsError);
              default              : return ecl::Error(UnknownError);
  }
}
/**
 * This function generates a custom ecl::Error response
 * for posix error numbers generated by posix <i>recv</i> calls.
 * @return Error : the error type.
 */
inline ecl::Error receive_error() {

  switch( errno ) {
              case ( EAGAIN || EWOULDBLOCK ) : return ecl::Error(ecl::InterruptedError);
              case ( EBADF       ) : return ecl::Error(ecl::InvalidObjectError);
              case ( ECONNREFUSED) : return ecl::Error(ecl::ConnectionError);
              case ( EFAULT      ) : return ecl::Error(ecl::SystemFailureError);
              case ( EINTR       ) : return ecl::Error(ecl::InterruptedError);
              case ( EINVAL      ) : return ecl::Error(ecl::InvalidArgError);
              case ( ENOMEM      ) : return ecl::Error(ecl::MemoryError);
              case ( ENOTCONN    ) : return ecl::Error(ecl::ConnectionError);
              case ( ENOTSOCK    ) : return ecl::Error(ecl::InvalidObjectError);
              default              : return ecl::Error(UnknownError);
  }
}
/**
 * This function generates a custom ecl::Error response
 * for posix error numbers generated by posix <i>ioctl</i> calls.
 * @return Error : the error type.
 */
inline ecl::Error ioctl_error() {

  switch( errno ) {
          case ( EBADF       ) : return ecl::Error(ecl::InvalidObjectError);
          case ( EFAULT      ) : return ecl::Error(ecl::OutOfRangeError);
          case ( EINVAL      ) : return ecl::Error(ecl::InvalidArgError);
          case ( ENOTTY      ) : return ecl::Error(ecl::InvalidObjectError);
          default              : return ecl::Error(UnknownError);
}
}

/**
 * This function generates a custom ecl::Error response
 * for posix error numbers generated by posix <i>send</i> calls.
 * @return Error : the error type.
 */
inline ecl::Error send_error() {

  switch( errno ) {
          case ( EAGAIN || EWOULDBLOCK ) : return ecl::Error(ecl::BlockingError);
          case ( EWOULDBLOCK ) : return ecl::Error(ecl::BlockingError);
          case ( EACCES      ) : return ecl::Error(ecl::PermissionsError);
          case ( EBADF       ) : return ecl::Error(ecl::InvalidObjectError);
          case ( ECONNRESET  ) : return ecl::Error(ecl::InterruptedError);
          case ( EFAULT      ) : return ecl::Error(ecl::SystemFailureError);
          case ( EINTR       ) : return ecl::Error(ecl::InterruptedError);
          case ( EINVAL      ) : return ecl::Error(ecl::InvalidArgError);
          case ( EISCONN     ) : return ecl::Error(ecl::ConnectionError);
          case ( EMSGSIZE    ) : return ecl::Error(ecl::WriteError);
          case ( ENOBUFS     ) : return ecl::Error(ecl::OutOfResourcesError);
          case ( ENOMEM      ) : return ecl::Error(ecl::MemoryError);
          case ( ENOTCONN    ) : return ecl::Error(ecl::ConnectionError);
          case ( ENOTSOCK    ) : return ecl::Error(ecl::InvalidObjectError);
          case ( EOPNOTSUPP  ) : return ecl::Error(ecl::NotSupportedError);
          case ( EPIPE       ) : return ecl::Error(ecl::InterruptedError);
          default              : return ecl::Error(UnknownError);
}
}

/**
 * This function generates a custom ecl::Error response
 * for posix error numbers generated by posix <i>gethostbyname</i> calls.
 * @return Error : the error type.
 */
inline ecl::Error gethostbyname_error() {
  switch( h_errno ) {
          case ( HOST_NOT_FOUND ) : return ecl::Error(ecl::ConnectionError);
          case ( NO_ADDRESS )  : return ecl::Error(ecl::InvalidArgError);
          case ( NO_RECOVERY ) : return ecl::Error(ecl::UnknownError);
          default              : return ecl::Error(ecl::UnknownError);
  }
}
/**
 * This function generates a custom ecl::Error response
 * for posix error numbers generated by posix <i>connect</i> calls.
 * @return Error : the error type.
 */
inline ecl::Error connection_error() {
  switch( errno ) {
      case ( ( EACCES ) || ( EPERM ) ): return ecl::Error(ecl::PermissionsError);
      case ( EADDRINUSE )  : return ecl::Error(ecl::BusyError);
      case ( EAFNOSUPPORT ): return ecl::Error(ecl::NotSupportedError);
      case ( EAGAIN )      : return ecl::Error(ecl::OutOfResourcesError);
      case ( EALREADY )    : return ecl::Error(ecl::BlockingError);
      case ( EBADF )       : return ecl::Error(ecl::InvalidObjectError);
      case ( ECONNREFUSED ): return ecl::Error(ecl::ConnectionRefusedError);
      case ( EFAULT )      : return ecl::Error(ecl::OutOfRangeError);
      case ( EINPROGRESS ) : return ecl::Error(ecl::BlockingError);
      case ( EINTR )       : return ecl::Error(ecl::InterruptedError);
      case ( EISCONN )     : return ecl::Error(ecl::ConnectionError);
      case ( ENETUNREACH ) : return ecl::Error(ecl::ConfigurationError);
      case ( ENOTSOCK )    : return ecl::Error(ecl::InvalidObjectError);
      case ( ETIMEDOUT )   : return ecl::Error(ecl::TimeOutError);
              default              : return ecl::Error(ecl::UnknownError);
  }
}

} // namespace devices
} // namespace ecl

#endif /* ECL_IS_POSIX */
#endif /* !ECL_IS_APPLE */
#endif /* ECL_DEVICES_SOCKET_ERROR_HANDLER_POS_HPP_ */
