inspircd/include/socket.h
2006-02-07 16:55:02 +00:00

331 lines
8.4 KiB
C++

/* +------------------------------------+
* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
* InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
* E-mail:
* <brain@chatspike.net>
* <Craig@chatspike.net>
*
* Written by Craig Edwards, Craig McLure, and others.
* This program is free but copyrighted software; see
* the file COPYING for details.
*
* ---------------------------------------------------
*/
#ifndef __INSP_SOCKET_H__
#define __INSP_SOCKET_H__
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sstream>
#include <string>
#include "dns.h"
/**
* States which a socket may be in
*/
enum InspSocketState { I_DISCONNECTED, I_RESOLVING, I_CONNECTING, I_CONNECTED, I_LISTENING, I_ERROR };
/**
* Error types which a socket may exhibit
*/
enum InspSocketError { I_ERR_TIMEOUT, I_ERR_SOCKET, I_ERR_CONNECT, I_ERR_BIND, I_ERR_RESOLVE };
/**
* InspSocket is an extendable socket class which modules
* can use for TCP socket support. It is fully integrated
* into InspIRCds socket loop and attaches its sockets to
* the core's instance of the SocketEngine class, meaning
* that any sockets you create have the same power and
* abilities as a socket created by the core itself.
* To use InspSocket, you must inherit a class from it,
* and use the InspSocket constructors to establish connections
* and bindings.
*/
class InspSocket
{
private:
/**
* The file descriptor of this socket
*/
int fd;
/**
* The resolver for this socket
*/
DNS dns;
/**
* The hostname connected to
*/
std::string host;
/**
* The port connected to, or the port
* this socket is listening on
*/
int port;
/**
* The state for this socket, either
* listening, connecting, connected
* or error.
*/
InspSocketState state;
/**
* The host being connected to,
* in sockaddr form
*/
sockaddr_in addr;
/**
* The host being connected to,
* in in_addr form
*/
in_addr addy;
/**
* When this time is reached,
* the socket times out if it is
* in the CONNECTING state
*/
time_t timeout_end;
/**
* This value is true if the
* socket has timed out.
*/
bool timeout;
/**
* Socket input buffer, used by read(). The class which
* extends InspSocket is expected to implement an extendable
* buffer which can grow much larger than 64k,
* this buffer is just designed to be temporary storage.
* space.
*/
char ibuf[65535];
/**
* The output buffer for this socket
*/
std::string Buffer;
/**
* The IP address being connected
* to stored in string form for
* easy retrieval by accessors.
*/
std::string IP;
/**
* Client sockaddr structure used
* by accept()
*/
sockaddr_in client;
/**
* Server sockaddr structure used
* by accept()
*/
sockaddr_in server;
/**
* Used by accept() to indicate the
* sizes of the sockaddr_in structures
*/
socklen_t length;
/** Flushes the write buffer
*/
void FlushWriteBuffer();
void SetQueues(int nfd);
public:
/**
* The default constructor does nothing
* and should not be used.
*/
InspSocket();
/**
* This constructor is used to associate
* an existing connecting with an InspSocket
* class. The given file descriptor must be
* valid, and when initialized, the InspSocket
* will be set with the given IP address
* and placed in CONNECTED state.
*/
InspSocket(int newfd, char* ip);
/**
* This constructor is used to create a new
* socket, either listening for connections, or an outbound connection to another host.
* Note that if you specify a hostname in the 'host' parameter, then there will be an extra
* step involved (a nonblocking DNS lookup) which will cause your connection to be established
* slower than if it was an IP. Therefore, use an IP address where it is available instead.
* @param host The hostname to connect to, or bind to
* @param port The port number to connect to, or bind to
* @param listening true to listen on the given host:port pair, or false to connect to them
* @param maxtime Number of seconds to wait, if connecting, before the connection times out and an OnTimeout() event is generated
*/
InspSocket(std::string host, int port, bool listening, unsigned long maxtime);
/**
* This method is called when an outbound
* connection on your socket is completed.
* @return false to abort the connection, true to continue
*/
virtual bool OnConnected();
/**
* This method is called when an error occurs.
* A closed socket in itself is not an error,
* however errors also generate close events.
* @param e The error type which occured
*/
virtual void OnError(InspSocketError e);
/**
* When an established connection is terminated,
* the OnDisconnect method is triggered.
*/
virtual int OnDisconnect();
/**
* When there is data waiting to be read on a
* socket, the OnDataReady() method is called.
* Within this method, you *MUST* call the Read()
* method to read any pending data. At its lowest
* level, this event is signalled by the core via
* the socket engine. If you return false from this
* function, the core removes your socket from its
* list and erases it from the socket engine, then
* calls InspSocket::Close() and deletes it.
* @return false to close the socket
*/
virtual bool OnDataReady();
/**
* When an outbound connection fails, and the
* attempt times out, you will receive this event.
* The method will trigger once maxtime seconds are
* reached (as given in the constructor) just
* before the socket's descriptor is closed.
* A failed DNS lookup may cause this event if
* the DNS server is not responding, as well as
* a failed connect() call, because DNS lookups are
* nonblocking as implemented by this class.
*/
virtual void OnTimeout();
/**
* Whenever close() is called, OnClose() will be
* called first. Please note that this means
* OnClose will be called alongside OnError(),
* OnTimeout(), and Close(), and also when
* cancelling a listening socket by calling
* the destructor indirectly.
*/
virtual void OnClose();
/**
* Reads all pending bytes from the socket
* into a char* array which can be up to
* 16 kilobytes in length.
*/
virtual char* Read();
/**
* Returns the IP address associated with
* this connection, or an empty string if
* no IP address exists.
*/
std::string GetIP();
/**
* This function checks if the socket has
* timed out yet, given the current time
* in the parameter.
* @return true if timed out, false if not timed out
*/
bool Timeout(time_t current);
/**
* Writes a std::string to the socket. No carriage
* returns or linefeeds are appended to the string.
* @param data The data to send
*/
virtual int Write(std::string data);
/**
* If your socket is a listening socket, when a new
* connection comes in on the socket this method will
* be called. Given the new file descriptor in the
* parameters, and the IP, it is recommended you copy
* them to a new instance of your socket class,
* e.g.:
*
* MySocket* newsocket = new MySocket(newfd,ip);
*
* Once you have done this, you can then associate the
* new socket with the core using Server::AddSocket().
*/
virtual int OnIncomingConnection(int newfd, char* ip);
/**
* Changes the socket's state. The core uses this
* to change socket states, and you should not call
* it directly.
*/
void SetState(InspSocketState s);
/**
* Returns the current socket state.
*/
InspSocketState GetState();
/**
* Only the core should call this function.
* When called, it is assumed the socket is ready
* to read data, and the method call routes the
* event to the various methods of InspSocket
* for you to handle. This can also cause the
* socket's state to change.
*/
bool Poll();
/**
* This method returns the socket's file descriptor
* as assigned by the operating system, or -1
* if no descriptor has been assigned.
*/
int GetFd();
/**
* This method causes the socket to close, and may
* also be triggered by other methods such as OnTimeout
* and OnError.
*/
virtual void Close();
/**
* The destructor may implicitly call OnClose(), and
* will close() and shutdown() the file descriptor
* used for this socket.
*/
virtual ~InspSocket();
virtual bool DoResolve();
virtual bool DoConnect();
};
#endif