# Error handling

Intro
  class SWBaseError
    Constructors
    get_error()
    get_failedClass()
    set_errorString()
    set_failedClass()
    Operators
  Example: Error handling
Using Exceptions
  sw_setThrowMode()
  sw_setVerboseMode()
  sw_getThrowMode()
  sw_getVerboseMode()
  Example: Using exceptions

## Introduction

SocketW provides two error handling mechanisms; by default information about errors (and successes) will be provided by objects passed to the class methods but SocketW can also support standard C++ exception handling.
Every method that can fail has an optional "SWBaseError *error" as its last argument. You can set this argument either to "NULL" or provide a pointer to an allocated SWBaseError class (or a derived class). If provided, the SWBaseError class pointed to, will be setup to indicate if the method succeeded or if an error occurred.

SWBaseSocket::SWBaseError
This is the basic error information class.
Constructors:

> SWBaseError()
> Users should always use this constructor when creating a new class, eg. "SWBaseSocket::SWBaseError myError;".
> SWBaseError(base_error e)
> Used to convert from the base_error datatype.

Methods:

> virtual std::string get_error()
> Get a human readable error string (empty if no error occurred).
> virtual SWBaseSocket* get_failedClass(void)
> Get a pointer to the class where the error occurred (or NULL if no error occurred).
> virtual void set_errorString(std::string msg)
> Set the error string. Should normally not be used.
> virtual void set_failedClass(SWBaseSocket *pnt)
> Set the failed class pointer. Should normally not be used.
> virtual bool operator==(SWBaseError e)
> virtual bool operator!=(SWBaseError e)
> Allows you to compare this object with other errors. This is explained below.

The comparison operators == and != are used to find out what error type (if any) the class represents (comparison is the only valid way to find the error type). The possible error types are (in SWBaseSocket) represented by a enum data type:
enum SWBaseSocket::base_error{ok, fatal, notReady, portInUse, notConnected, msgTooLong, terminated, noResponse, timeout, interrupted}
The meaning of each error type is explained in the documentation for the socket classes.
Classes derived from SWBaseSocket might have more error types and therefore other error classes (but these are derived from SWBaseError). For example, SWSSLSocket has additional error types defined in the enum SWSSLSocket::ssl_error which are handled in the error handling class SWSSLSocket::SWSSLError derived directly from SWBaseSocket::SWBaseError.
A SWBaseSocket method can use error types only from the SWBaseSocket::base_error enum, but a SWSSLSocket method can use error types from both the SWBaseSocket::base_error enum and the SWSSLSocket::ssl_error enum. You can still provide a SWBaseSocket::SWBaseError error class as the last argument to a SWSSLSocket method but you might then lose information about SSL specific errors (such as SWSSLSocket::badPasswd) and get a less informative error (such as SWBaseSocket::fatal).
You should not compare (== or !=) a SWBaseError class with a SWSSLSocket specific error type but comparing a SWSSLError class with a SWBaseSocket error type is of course perfectly normal.
Example:

    ...
    SWInetSocket myInetSocket;
    SWSSLSocket mySSLSocket;

    SWBaseSocket::SWBaseError BError;
    SWSSLSocket::SWSSLError SError;
    ...

    myInetSocket.foo(&BError);

    if( BError != SWBaseSocket::ok )
        // ...
    if( BError == SWSSLSocket::badPasswd )	// NOT OK! Can't compare with SWSSLSocket specific errors
        // ...
    ...

    myInetSocket.foo(&SError);

    if( SError != SWBaseSocket::ok )
        // ...
    if( SError == SWSSLSocket::badPasswd )	// Ok, but SWInetSocket will never generate this error
        // ...
    ...

    mySSLSocket.bar(&BError);

    if( BError != SWBaseSocket::ok )
        // ...
    if( BError == SWSSLSocket::badPasswd )  // STILL NOT OK! SWSSLSocket can generate this error
        // ...                              // but SWBaseError can not represent it. BError will
    ...                                     // indicate SWBaseSocket::fatal instead.

    mySSLSocket.bar(&SError);

    if( SError != SWBaseSocket::ok )
        // ...
    if( SError == SWSSLSocket::badPasswd )	// Ok, badPasswd is a possible error
        // ...

Note that both "SError == SWBaseSocket::fatal" and "SError == SWSSLSocket::badPasswd" can be true in the last method call in the above example. An SWSSLError class will always report "SWBaseSocket::fatal" when compared to an SWBaseSocket error type if a SSL specific error type is set (i.e. the SSL specific error is represented as "SWBaseSocket::fatal" when not compared to SSL specific error types).

## Using Exceptions

You can choose to omit the error argument (or equivalent; setting it to "NULL"). The default action on errors will then be to print an error message to stderr and terminate the application, but this can be controlled by the following functions:

- void sw_setThrowMode(bool throw_errors)
  Setting "throw_errors" to true will cause SocketW to use the standard C++ exception handling mechanism. SocketW will in this case throw the SWBaseError class if the method fails and no error argument is provided. The default behavior, setting "throw_errors" to false, is to terminate the application with exit(-1).
- void sw_setVerboseMode(bool verbose)
  Setting "verbose" to false will stop SocketW from printing error messages to stderr when the method fails and no error argument is provided. Setting "verbose" to true will restore the default behavior.
- bool sw_getThrowMode(void)
  Returns the current error handling mode.
- bool sw_getVerboseMode(void)
  Returns the current verbose mode.

When SocketW is set to use exceptions, it always throws the simplest type of error class that is able to represent the error, eg. SWInetSocket always throws the SWBaseSocket::SWBaseError class but SWSSLSocket can throw both the SWSSLSocket::SWSSLError class and the SWBaseSocket::SWBaseError class depending on the error type. The exception can always be caught by "catch(SWBaseSocket::SWBaseError &error)" but non SWBaseSocket error types will be lost (and reported as "SWBaseSocket::fatal") if the faulting method used such an error type.
Example:

    sw_setThrowMode(true);
    sw_setVerboseMode(false);

    SWInetSocket myInetSocket;
    SWSSLSocket mySSLSocket;
    ...
    try{
        myInetSocket.foo();
        mySSLSocket.bar();
    }
    catch( SWSSLSocket::SWSSLError &error ){
        // Will catch all exceptions from SWSSLSocket
        // and derived classes that have a SSL specific
        // error type

        if( error == SWSSLSocket::badPasswd )
            ...
    }
    catch( SWBaseSocket::SWBaseError &error ){
        // Will catch all exceptions from SWBaseSocket
        // and derived classes

        if( error == SWBaseSocket::terminated )
            ...
    }

Copyright © 2003 Anders Lindström
Last updated 031023