mistserver/sockets/sw_base.h

205 lines
6.9 KiB
C++

// C++ Socket Wrapper
// SocketW base socket header
//
// Started 020316
//
// License: LGPL v2.1+ (see the file LICENSE)
// (c)2002-2003 Anders Lindström
/***********************************************************************
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
***********************************************************************/
#ifndef sw_base_H
#define sw_base_H
#include "sw_internal.h"
#include <unistd.h>
#include <string>
// Set error handling mode
// throw_errors == true : Throws the error class on unhandled errors
// throw_errors == false : Exit on unhandled errors
// verbose == true : Prints the error message to stderr on unhandled errors
//
// Default is throw_errors == false and verbose == true
void sw_setThrowMode(bool throw_errors);
void sw_setVerboseMode(bool verbose);
bool sw_getThrowMode(void);
bool sw_getVerboseMode(void);
// Abstract base class for streaming sockets
class DECLSPEC SWBaseSocket
{
public:
SWBaseSocket();
virtual ~SWBaseSocket();
// Error types
// ok - operation succesful
// fatal - unspecified error
// notReady - you should call the function again
// indicates that the function would block (if nowait/nonblocking)
// portInUse - this port is used by another socket ( on listen() )
// notConnected - socket not connected (or valid)
// msgTooLong - the message size it too big for send()
// terminated - connection terminated (by peer)
// noResponse - can't connect() to peer
// timeout - a read/write operation timed out (only if a timeout value is set and if in blocking mode)
// interrupted - operation was interrupted by a nonblocked signal
enum base_error{ok, fatal, notReady, portInUse, notConnected, msgTooLong, terminated, noResponse, timeout, interrupted};
class DECLSPEC SWBaseError
{
public:
SWBaseError();
SWBaseError(base_error e);
virtual ~SWBaseError(){;}
virtual std::string get_error();
virtual SWBaseSocket* get_failedClass(void);
virtual bool operator==(SWBaseError e);
virtual bool operator!=(SWBaseError e);
virtual void set_errorString(std::string msg);
virtual void set_failedClass(SWBaseSocket *pnt);
protected:
friend class SWBaseSocket;
// The base error type
base_error be;
// Human readable error string
std::string error_string;
// A pointer to the class causing the error
SWBaseSocket *failed_class;
};
// Note: If no SWBaseError class is provided with a method call (==NULL),
// SocketW will print the error to stderr and exit or throw on errors.
// Note: All bool functions returns true on success.
// Block mode
// blocking - everythings blocks until completly done
// noWait - operations block but only once
// useful with blocking w. select()
// nonblocking - don't block (you should use select())
enum block_type{nonblocking, noWait, blocking};
// Connection methods
// qLimit - the maximum length the queue of pending connections.
// Accept returns a new socket class connected with peer (should be
// freed with delete) or NULL on failure. You can cast the class to
// the correct type if you need to ( eg. (SWInetSocket *)mysocket ).
virtual bool listen(int qLimit = 5, SWBaseError *error = NULL);
virtual SWBaseSocket* accept(SWBaseError *error = NULL);
// bind() and connect() are implemented in child classes
// do the disconnect ritual (signal peer, wait for close singal and close socket)
virtual bool disconnect(SWBaseError *error = NULL);
// force close socket
virtual bool close_fd(); //use with care, disconnect() is cleaner
// Direct I/O (raw)
// Can send/recv less bytes than specified!
// Returns the actual amount of bytes sent/recv on sucess
// and an negative integer on failure.
virtual int send(const char *buf, int bytes, SWBaseError *error = NULL);
virtual int sendmsg(const std::string msg, SWBaseError *error = NULL);
virtual int recv(char *buf, int bytes, SWBaseError *error = NULL);
virtual std::string recvmsg(int bytes = 256, SWBaseError *error = NULL);
// Forced I/O
// Force system to send/recv the specified amount of bytes.
// On nowait/nonblocking: might return with notReady and then you
// MUST call the same method again (eg. wait with select() to know when)
// with the same parameters until the operation is finished.
// Returns 'bytes' when finished, negative integer on failure and
// 'notReady'. In the 'notReady' case, -(return value) is the amount of
// bytes sent/recv so far.
virtual int fsend(const char *buf, int bytes, SWBaseError *error = NULL);
virtual int fsendmsg(const std::string msg, SWBaseError *error = NULL);
virtual int frecv(char *buf, int bytes, SWBaseError *error = NULL);
// Tools
// get_fd() - get socket descriptor, can be used with select()
// returns -1 on failure.
// get_host/peer fills the provided structures with info about the
// host/peer (see man unix & ip).
// SWInetSocket has some more tools for TCP/IP sockets.
virtual int get_fd(SWBaseError *error);
virtual bool get_host(sockaddr *host, SWBaseError *error = NULL);
virtual bool get_peer(sockaddr *peer, SWBaseError *error = NULL);
// Set recv timeout (only in blocking mode).
// set_timeout(0,0) means wait forever (default).
// This affects the functions recv(), send(), accept() and disconnect()
// and others that use those, i.e. all frecvmsg().
void set_timeout(Uint32 sec, Uint32 usec){ tsec = sec, tusec = usec; }
// Error handling
virtual void print_error(); //prints the last error if any to stderr
virtual std::string get_error(){return error_string;} //returns a human readable error string
protected:
// get a new socket if myfd < 0
virtual void get_socket()=0;
// create a new class for accept() using socketdescriptor
virtual SWBaseSocket* create(int socketdescriptor, SWBaseError *error)=0;
// reset state
virtual void reset();
// wait for I/O (with timeout)
enum io_type{read, write, except, rw, all};
virtual bool waitIO(io_type &type, SWBaseError *error);
bool waitRead(SWBaseError *error);
bool waitWrite(SWBaseError *error);
// internal error handling
virtual void handle_errno(SWBaseError *error, std::string msg);
virtual void no_error(SWBaseError *error);
virtual void set_error(SWBaseError *error, SWBaseError name, std::string msg);
// our socket descriptor
int myfd;
// last error
std::string error_string;
// data for fsend
bool fsend_ready;
int fsend_total;
int fsend_bytesleft;
// data for frecv
bool frecv_ready;
int frecv_total;
int frecv_bytesleft;
// have we recived a shutdown signal?
bool recv_close;
//blocking mode (set by child classes)
block_type block_mode;
//timeout for waitIO()
int tsec;
int tusec;
};
#endif /* sw_base_H */