205 lines
6.9 KiB
C++
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{blocking, noWait, nonblocking};
|
|
|
|
|
|
// 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 */
|