#ifndef __COMM_H__ #define __COMM_H__ #include "squid.h" #include "AsyncEngine.h" #include "CompletionDispatcher.h" #include "StoreIOBuffer.h" #include "Array.h" #define COMMIO_FD_READCB(fd) (&commfd_table[(fd)].readcb) #define COMMIO_FD_WRITECB(fd) (&commfd_table[(fd)].writecb) typedef enum { COMM_OK = 0, COMM_ERROR = -1, COMM_NOMESSAGE = -3, COMM_TIMEOUT = -4, COMM_SHUTDOWN = -5, COMM_IDLE = -6, /* there are no active fds and no pending callbacks. */ COMM_INPROGRESS = -7, COMM_ERR_CONNECT = -8, COMM_ERR_DNS = -9, COMM_ERR_CLOSING = -10 } comm_err_t; typedef void IOFCB(int fd, StoreIOBuffer receivedData, comm_err_t flag, int xerrno, void *data); typedef void IOWCB(int fd, char *buffer, size_t len, comm_err_t flag, int xerrno, void *data); typedef void CWCB(int fd, char *, size_t size, comm_err_t flag, void *data); typedef void CNCB(int fd, comm_err_t status, int xerrno, void *data); typedef void IOCB(int fd, char *, size_t size, comm_err_t flag, int xerrno, void *data); /* comm.c */ extern void comm_calliocallback(void); extern bool comm_iocallbackpending(void); /* inline candidate */ extern int comm_listen(int fd); SQUIDCEXTERN int commSetNonBlocking(int fd); SQUIDCEXTERN int commUnsetNonBlocking(int fd); SQUIDCEXTERN void commSetCloseOnExec(int fd); extern void _comm_close(int fd, char const *file, int line); #define comm_close(fd) (_comm_close((fd), __FILE__, __LINE__)) SQUIDCEXTERN void comm_reset_close(int fd); #if LINGERING_CLOSE SQUIDCEXTERN void comm_lingering_close(int fd); #endif SQUIDCEXTERN void commConnectStart(int fd, const char *, u_short, CNCB *, void *); SQUIDCEXTERN int comm_connect_addr(int sock, const struct sockaddr_in *); SQUIDCEXTERN void comm_init(void); SQUIDCEXTERN void comm_exit(void); SQUIDCEXTERN int comm_open(int, int, struct IN_ADDR, u_short port, int, const char *note); SQUIDCEXTERN int comm_openex(int, int, struct IN_ADDR, u_short, int, unsigned char TOS, const char *); SQUIDCEXTERN u_short comm_local_port(int fd); SQUIDCEXTERN int comm_set_tos(int fd, int tos); SQUIDCEXTERN void commSetSelect(int, unsigned int, PF *, void *, time_t); SQUIDCEXTERN void commResetSelect(int); SQUIDCEXTERN int comm_udp_sendto(int, const struct sockaddr_in *, int, const void *, int); extern void comm_write(int fd, const char *buf, int len, IOCB *callback, void *callback_data, FREE *func); SQUIDCEXTERN void comm_write_mbuf(int fd, MemBuf *mb, IOCB * handler, void *handler_data); SQUIDCEXTERN void commCallCloseHandlers(int fd); SQUIDCEXTERN int commSetTimeout(int fd, int, PF *, void *); SQUIDCEXTERN int ignoreErrno(int); SQUIDCEXTERN void commCloseAllSockets(void); SQUIDCEXTERN void checkTimeouts(void); /* * comm_select.c */ SQUIDCEXTERN void comm_select_init(void); SQUIDCEXTERN comm_err_t comm_select(int); SQUIDCEXTERN void comm_quick_poll_required(void); class ConnectionDetail; typedef void IOACB(int fd, int nfd, ConnectionDetail *details, comm_err_t flag, int xerrno, void *data); extern void comm_accept(int fd, IOACB *handler, void *handler_data); extern void comm_add_close_handler(int fd, PF *, void *); extern void comm_remove_close_handler(int fd, PF *, void *); extern int comm_has_pending_read_callback(int fd); extern bool comm_has_pending_read(int fd); extern void comm_read(int fd, char *buf, int len, IOCB *handler, void *data); extern void comm_read_cancel(int fd, IOCB *callback, void *data); extern void fdc_open(int fd, unsigned int type, char const *desc); extern int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); extern int comm_udp_recv(int fd, void *buf, size_t len, int flags); extern ssize_t comm_udp_send(int s, const void *buf, size_t len, int flags); extern void commMarkHalfClosed(int); extern int commIsHalfClosed(int); extern void commCheckHalfClosed(void *); extern bool comm_has_incomplete_write(int); /* Not sure where these should live yet */ class Acceptor { public: typedef void AcceptorFunction (int, int, ConnectionDetail *, comm_err_t, int, void *); AcceptorFunction *theFunction; int acceptFD; void *theData; }; class AcceptLimiter { public: static AcceptLimiter &Instance(); void defer (int, Acceptor::AcceptorFunction *, void *); void kick(); bool deferring() const; private: static AcceptLimiter Instance_; Vector deferred; }; /* App layer doesn't want any more data from the socket, as the read channel is * closed, but we need to detect aborts, so this lets us do so. */ class AbortChecker { public: static AbortChecker &Instance(); /* the current method of checking, is via a 0 length read every second. * if nothing is returned by the next IO loop, we let it be. * If an error occurs, we close the conn. * Note that some tcp environments may allow direct polling for the socket status * and this could be adjusted to use that method for the test. (in which case * the singleton should be refactored to have the tcp engine register the * instance with it). */ static IOCB AbortCheckReader; void monitor (int); void stopMonitoring (int); void doIOLoop(); private: static AbortChecker Instance_; static void AddCheck (int const &, void *); static int IntCompare (int const &, int const &); static void RemoveCheck (int const &, void *); AbortChecker() : fds (NULL), checking (false), lastCheck (0){} mutable SplayNode *fds; bool checking; time_t lastCheck; bool contains (int const) const; void remove (int const); void add (int const); void addCheck (int const); void removeCheck (int const); }; /* a dispatcher for comms events */ class CommDispatcher : public CompletionDispatcher { public: virtual bool dispatch(); }; /* A comm engine that calls comm_select */ class CommSelectEngine : public AsyncEngine { public: virtual int checkEvents(int timeout); }; #endif