#ifndef ASCON_I #define ASCON_I #include #include "ascon.h" #include "dynstring.h" /** \file * \brief Asynchronous connection handling for devices controlled over tcp-ip * connections. Interface for the implementation of custom protocols. * * For the implmentation of a custom protocol, hou have to implement * the handler function and the init function, declare the protocol * of type AsconProtocol and call AsconInsertProtocol on startup. * The handler and init functions are normally be a wrapper around AsconStdHandler * and AsconStdInit * * The functions with fd as the first argument are utility functions with * may be used in handler wrapper functions. * On error, the return value may be one of the defined macros ASCON_xxx, * and errno will give more details about the error. */ /** * A sub-state of the connection. Only states with sub-state AsconStart may * be set by the caller, and only when the sub-state is not AsconOnTheWay */ typedef enum { AsconOnTheWay=0, AsconStart=1, AsconFinished=2, AsconFailed=3 } AsconMode; /** * The state of the connection. The sub-state is state % 4. */ typedef enum { AsconNotConnected=0+AsconFinished, AsconKillMe=0+AsconStart, AsconConnecting=4+AsconOnTheWay, AsconConnectStart=AsconConnecting+AsconStart, AsconConnectDone=AsconConnecting+AsconFinished, AsconConnectFailed=AsconConnecting+AsconFailed, AsconWriting=8+AsconOnTheWay, AsconWriteStart=AsconWriting+AsconStart, AsconWriteDone=AsconWriting+AsconFinished, AsconReading=12+AsconOnTheWay, AsconReadStart=AsconReading+AsconStart, AsconReadDone=AsconReading+AsconFinished, AsconIdle=16+AsconFinished } AsconState; /** \brief the task handler function prototype * * custom handlers must have this prototype */ typedef int (* AsconHandler)(Ascon *connection); /** Ascon struct * all members are public, allowing access by handler wrappers */ struct Ascon { AsconState state; /**< the current state */ int fd; /**< socket */ int readState; /**< default implementation: 'was cr' */ pDynString rdBuffer;/**< read buffer */ pDynString wrBuffer;/**< write buffer */ int wrPos; /**< write buffer position */ double timeout; /**< read timeout (sec) */ char *hostport; /**< host:port to connect */ ErrMsg *errList; /**< error message list */ double start; /**< unix time when read was started */ void *private; /**< private data of protocol */ int noResponse; /**< no response expected */ int responseValid; /**< a valid response is ready */ AsconHandler handler; /**< handler function */ double reconnectInterval; /**< reconnect interval */ double lastReconnect; /**< last connect try */ }; #define ASCON_SELECT_ERROR -1 #define ASCON_RECV_ERROR -2 #define ASCON_SEND_ERROR -3 #define ASCON_DISCONNECTED -4 /** \brief the standard handler routine. * \param a the connection * \return 0 when task has finished (connection to be closed), 1 when active * * In most cases a custom handler may be a wrapper around AsconStdHandler */ int AsconStdHandler(Ascon *a); /** \brief initialize a standard connection * \param a the connection * \param hostport the tcp/ip address (syntax: host:port) * * In most cases a custom init function may be a wrapper around AsconStdInit */ void AsconStdInit(Ascon *a, char *hostport); /** The Ascon Protocol */ typedef struct AsconProtocol { struct AsconProtocol *next; char *name; AsconHandler handler; void (*init)(Ascon *s, int argc, char *argv[]); } AsconProtocol; /** \brief Insert a new protocol into the protocol list * protocol the protocol (must be allocated by the caller, may be statically) */ void AsconInsertProtocol(AsconProtocol *protocol); /** \brief close the connection and free internal used memory * \param a the connection to be closed * remark: the connection struct itself has to be freed manually */ void AsconClose(Ascon *a); /** \brief swallow garbage (utility function) * \param fd the socket * \return >=0: number of chars swallowed, else error */ int AsconReadGarbage(int fd); /** \brief check if a connection has succeded (utility function) * \param fd the socket * \return 1: connection succesful, 0: connection in progress, <0: error */ int AsconConnectSuccess(int fd); /** \brief read one character, if available (utility function) * \param fd the socket * \param chr the result * \return 1: succes, 0: no data available, <0: error */ int AsconReadChar(int fd, char *chr); /** \brief non blocking write (utility function) * \param fd the socket * \param data the data (not nul-terminated, may contain nul) * \param length the length of the data * \return >0: number of written chars,0: write not yet possible, <0: error */ int AsconWriteChars(int fd, char *data, int length); #endif