#ifndef SOCK_H_INCLUDED
#define SOCK_H_INCLUDED
#ifdef WIN32
#include <winsock.h>
#else // WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef struct sockaddr_in SOCKADDR_IN;
typedef int SOCKET;
#endif // WIN32
class CTcpSock;
/**
* The TCallBack type is used for all callbacks whenever the @ref CTcpSock
* changes state.
*
* @param sock pointer to the socket object that changed state.
*/
typedef void TCallBack(CTcpSock* sock);
/**
* Lookup an address consisting of host name (or IP) and port number.
*
* @param host The hostname or IP address in dot notaion, e.g. "192.168.0.1"
* @param port port number
* @param pAdr pointer to a variable for storing the result
* @return zero on success
*/
int get_address(const char* host, int port, SOCKADDR_IN* pAdr);
/**
* Retrieve the error code of the last failed socket operation.
*
* @return error code
*/
int getSocketError();
/**
* The CTcpSock represents a socket used for asynchronous operation.
*
* When a CTcpSock has been created, it can be registered with an
* @ref CEventLoop which passes 'events' from a select system
* call to the socket object, whenever data arrives or the socket
* is ready to recieve more data for writing.
*
* Handling of the events is implemented as a finite state machine.
* Callbacks can be registered for whenever the socket changes state.
* Callback function pointers are stored in the m_cb* member variables.
*
* @short This class represents an asynchronous TCP socket.
* @see CEventLoop
* @author Pelle Johnsen
*/
class CTcpSock
{
public:
/**
* Constructor which initializes datamembers.
*/
CTcpSock(void);
/**
* Destructor which automatically closes the socket if it has
* been connected.
*/
~CTcpSock(void);
/**
* Creates the socket, i.e. gets a socket handle ( @ref m_sock ).
*
* @return zero on success
*/
int create(void);
/**
* Closes the socket if it has been connected. It is safe to call
* close even if the socket wasn't created or connected.
*
* @return zero on success
*/
int close(void);
/**
* Start connecting the socket to a remote peer. When the connect
* completes the @ref m_cbConnectOk callback will be called.
*
* @param name address (host, port) of the remote peer
* @return zero or EINPROGRESS on success
*/
int connect(SOCKADDR_IN* name);
/**
* Start sending a buffer to the remote peer. When all bytes have
* been send the @ref m_cbSendOk callback will be called.
*
* @param buf pointer to the buffer
* @param len number of bytes to send
* @return number of bytes sent so far
*/
int send(const char* buf, int len);
/**
* Start sending a zero terminated string. When the whole string has
* been sent the @ref m_cbSendOk callback will be called.
*
* @param str the string to send
* @return number of bytes sent so far
*/
int sendString(const char* str);
/**
* Start receiving a buffer. When the desired number of bytes have
* been read or the remote end has closed the socket, the
* @ref m_cbRecvBufOk callback will be called.
*
* @param buf pointer to buffer for receiving data
* @param len number of bytes to receive
* @return zero on success
*/
int recvBuf(char* buf, int len);
/**
* Start reading a line from the socket. When a full line have
* been read or the remote end has closed the socket, the
* @ref m_cbReadLineOk callback will be called.
*
* @param buf pointer to buffer for receiving data
* @param max_len maximum number of bytes to read.
* @return zero on success
*/
int readLine(char* buf, int max_len);
/**
* Sets fd_sets for this socket depending on it's state. The fd_sets
* are used by a @ref CEventLoop for the select system call. Basically
* this socket indicates to the EventLoop if it is currently interested
* in read, write or exception events.
*
* @param rfds read fd_set
* @param wfds write fd_set
* @param efds exception fd_set
* @return zero on success
*/
int setFdSets(fd_set* rfds, fd_set* wfds, fd_set* efds);
/**
* Checks fd_sets for this socket after the @ref CEventLoop returns
* from the select system call, to see if there was any events for
* this socket. If an event arrived @ref processEvent is called.
* Before returning to the EventLoop any new internal events are
* handled by calling the appropriate callback.
*
* @param rfds read fd_set
* @param wfds write fd_set
* @param efds exception fd_set
* @return zero on success
*/
int checkFdSets(fd_set* rfds, fd_set* wfds, fd_set* efds);
/**
* Ask the socket to delete itself, just before returning to the
* EventLoop. This allows for 'nested' callbacks that needs
* to delete the socket object.
*/
void deleteSock(void);
/**
* The socket handle (i.e. file descriptor on UNIX)
*/
SOCKET m_sock;
/**
* This is a pointer to some arbitrary context you can assign
* to the socket. This is useful if you have one set of callback
* functions which handle multiple sockets. They can use the context
* data to figure out where the particular socket 'belong'
*/
void* m_context;
/**
* Callback for when the socket has succesfully connected to the
* remote peer.
*/
TCallBack* m_cbConnectOk;
/**
* Callback for when a send or sendString has completed.
*/
TCallBack* m_cbSendOk;
/**
* Callback for when a line has been read from the socket.
*/
TCallBack* m_cbReadLineOk;
/**
* Callback for when a buffer has been received.
*/
TCallBack* m_cbRecvBufOk;
/**
* Pointer to the buffer being written ( @ref send ,
* @ref sendString ).
*/
const char* m_wbuf;
/**
* Number of bytes to be sent.
*/
int m_wlen;
/**
* Number of bytes actually sent (so far).
*/
int m_sent;
/**
* Pointer to the buffer being read to ( @ref readLine ,
* @ref recvBuf ).
*/
char* m_rbuf;
/**
* Number of bytes to be read
*/
int m_rlen;
/**
* Number of bytes actually read (so far).
*/
int m_read;
/**
* Non-zero if the socket has been closed at the remote end.
*/
int m_eof;
protected:
/**
* The different states of the socket
*/
enum ESockStates
{
start,
created,
connecting,
ready,
sending,
recievingBuf,
readingLine,
closed
};
ESockStates m_state;
/**
* Types of events received from the EventLoop
*/
enum EEvents
{
read = 1,
write = 2,
except = 4
};
/**
* Internal events used to do callbacks and delete the socket
* before returning to the EventLoop, if needed.
*/
enum ESockInternalEvents
{
noEvent,
connectOk,
sendOk,
readLineOk,
recvBufOk,
deleteEvent
};
ESockInternalEvents m_intStatus;
/**
* Processes an event received from the EventLoop. Takes the
* appropriate action depending on the current state ( @ref m_state ).
*
* @param event type of event: read, write, exception
* @return zero on success
*/
int processEvent(int event);
/**
* Called every time data arrives, when reading a line
*/
void readLineLoop(void);
/**
* Called every time data arrives, when reading to a buffer
*/
void recvBufLoop(void);
};
#endif // SOCK_H_INCLUDED
| Generated by: pelle@pjws.localdomain on Wed Mar 14 12:09:22 2001, using kdoc 2.0a52. |