9ed88c01e15401a16d00ed26242d34c08eb3653f
[citadel.git] / citadel / event_client.h
1 #ifndef __EVENT_CLIENT_H__
2 #define __EVENT_CLIENT_H__
3 #define EV_COMPAT3 0
4 #include <ev.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <netdb.h>
8 #include <arpa/nameser.h>
9 #include <ares.h>
10 #include <curl/curl.h>
11
12 typedef struct AsyncIO AsyncIO;
13
14 typedef enum _eNextState {
15         eSendDNSQuery,
16         eReadDNSReply,
17         eConnect,
18         eSendReply, 
19         eSendMore,
20         eReadMessage, 
21         eReadMore,
22         eTerminateConnection,
23         eAbort
24 }eNextState;
25
26 typedef eNextState (*IO_CallBack)(AsyncIO *IO);
27 typedef eReadState (*IO_LineReaderCallback)(AsyncIO *IO);
28 typedef void (*ParseDNSAnswerCb)(AsyncIO*, unsigned char*, int);
29 typedef void (*FreeDNSReply)(void *DNSData);
30
31 typedef struct _DNSQueryParts {
32         ParseDNSAnswerCb DNS_CB;
33         IO_CallBack PostDNS;
34
35         int DNSStatus;
36         void *VParsedDNSReply;
37         FreeDNSReply DNSReplyFree;
38         void *Data;
39 } DNSQueryParts;
40
41 typedef struct _evcurl_request_data 
42 {
43         CURL              *chnd;
44         struct curl_slist *headers;
45         char               errdesc[CURL_ERROR_SIZE];
46
47         int                attached;
48
49         char              *PlainPostData;
50         long               PlainPostDataLen;
51         StrBuf            *PostData;
52
53         StrBuf            *ReplyData;
54         long               httpcode;
55 } evcurl_request_data;
56
57 struct AsyncIO {
58         eNextState NextState;
59
60         /* connection related */
61         ParsedURL *ConnectMe;
62         
63         /* read/send related... */
64         StrBuf *IOBuf;
65         IOBuffer SendBuf, 
66                 RecvBuf;
67
68         /* our events... */
69         ev_cleanup abort_by_shutdown; /* server wants to go down... */
70         ev_timer conn_fail,           /* connection establishing timed out */
71                 rw_timeout;           /* timeout while sending data */
72         ev_idle unwind_stack,         /* get c-ares out of the stack */
73                 conn_fail_immediate;  /* unwind stack, but fail immediately. */
74         ev_io recv_event,             /* receive data from the client */
75                 send_event,           /* send more data to the client */
76                 conn_event;           /* Connection successfully established */
77
78         StrBuf *ErrMsg; /* if we fail to connect, or lookup, error goes here. */
79
80         /* Citadel application callbacks... */
81         IO_CallBack ReadDone, /* Theres new data to read... */
82                 SendDone,     /* we may send more data */
83                 Terminate,    /* shutting down... */
84                 Timeout,      /* Timeout handler; may also be connection timeout */
85                 ConnFail,     /* What to do when one connection failed? */
86                 ShutdownAbort;/* we're going down. make your piece. */ 
87
88         IO_LineReaderCallback LineReader; /* if we have linereaders, maybe we want to read more lines before the real application logic is called? */
89
90         /* DNS Related */
91         ev_io dns_recv_event, 
92                 dns_send_event;
93         struct ares_options DNSOptions;
94         ares_channel DNSChannel;
95         DNSQueryParts *DNSQuery;
96         
97         evcurl_request_data HttpReq;
98
99         /* Saving / loading a message async from / to disk */
100
101         struct CtdlMessage *AsyncMsg;
102         struct recptypes *AsyncRcp;
103         /* Custom data; its expected to contain  AsyncIO so we can save malloc()s... */
104         void *Data;        /* application specific data */
105         void *CitContext;  /* Citadel Session context... */
106 };
107
108 typedef struct _IOAddHandler {
109         AsyncIO *IO;
110         IO_CallBack EvAttch;
111 }IOAddHandler; 
112
113 void FreeAsyncIOContents(AsyncIO *IO);
114
115 void NextDBOperation(AsyncIO *IO, IO_CallBack CB);
116 int QueueDBOperation(AsyncIO *IO, IO_CallBack CB);
117 int QueueEventContext(AsyncIO *IO, IO_CallBack CB);
118 int ShutDownEventQueue(void);
119
120 eNextState InitEventIO(AsyncIO *IO, 
121                        void *pData, 
122                        double conn_timeout, 
123                        double first_rw_timeout,
124                        int ReadFirst);
125 void IO_postdns_callback(struct ev_loop *loop, ev_idle *watcher, int revents);
126
127 int QueueQuery(ns_type Type, const char *name, AsyncIO *IO, DNSQueryParts *QueryParts, IO_CallBack PostDNS);
128 void QueueGetHostByName(AsyncIO *IO, const char *Hostname, DNSQueryParts *QueryParts, IO_CallBack PostDNS);
129
130 void QueryCbDone(AsyncIO *IO);
131
132 void StopClient(AsyncIO *IO);
133
134 void StopClientWatchers(AsyncIO *IO);
135
136 void SetNextTimeout(AsyncIO *IO, double timeout);
137
138 void InitC_ares_dns(AsyncIO *IO);
139
140 #include <curl/curl.h>
141
142 #define OPT(s, v) \
143         do { \
144                 sta = curl_easy_setopt(chnd, (CURLOPT_##s), (v)); \
145                 if (sta)  {                                             \
146                         CtdlLogPrintf(CTDL_ERR, "error setting option " #s " on curl handle: %s", curl_easy_strerror(sta)); \
147         } } while (0)
148
149
150 int evcurl_init(AsyncIO *IO, 
151                 void *CustomData, 
152                 const char* Desc,
153                 IO_CallBack CallBack, 
154                 IO_CallBack Terminate);
155
156 void evcurl_handle_start(AsyncIO *IO);
157
158 #endif /* __EVENT_CLIENT_H__ */