[IOMultiplexerV2] Merge branch 'v2'
[NextIRCd.git] / src / IOHandler / IOSockets.h
1 /* IOSockets.h - IOMultiplexer v2
2  * Copyright (C) 2014  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #ifndef _IOSockets_h
18 #define _IOSockets_h
19 #include <sys/time.h>
20 #include <stddef.h>
21 #include "IODNSAddress.struct.h"
22
23 struct IOSocketBuffer {
24     char *buffer;
25     size_t bufpos, buflen;
26 };
27
28 #ifndef _IOHandler_internals
29 #include "IOHandler.h"
30 #else
31
32 struct _IOSocket;
33 struct IOSocket;
34 struct IOSocketBuffer;
35 struct IOSSLDescriptor;
36 struct _IODNSQuery;
37 struct IODNSEvent;
38
39 struct IOEngine {
40     const char *name;
41     int (*init)(void);
42     void (*add)(struct _IOSocket *iosock);
43     void (*remove)(struct _IOSocket *iosock);
44     void (*update)(struct _IOSocket *iosock);
45     void (*loop)(struct timeval *timeout);
46     void (*cleanup)(void);
47 };
48
49 /* IO Engines */
50 extern struct IOEngine engine_select; /* select system call (should always be useable) */
51 extern struct IOEngine engine_kevent;
52 extern struct IOEngine engine_epoll;
53 extern struct IOEngine engine_win32;
54
55
56 /* _IOSocket linked list */
57 extern struct _IOSocket *iosocket_first;
58 extern struct _IOSocket *iosocket_last;
59
60 /* _IOSocket socket_flags */
61 #define IOSOCKETFLAG_ACTIVE           0x00000001
62 #define IOSOCKETFLAG_LISTENING        0x00000002
63 #define IOSOCKETFLAG_IPV6SOCKET       0x00000004
64 #define IOSOCKETFLAG_INCOMING         0x00000008 /* incoming (accepted) connection */
65 #define IOSOCKETFLAG_CONNECTING       0x00000010
66 #define IOSOCKETFLAG_SHUTDOWN         0x00000020 /* disconnect pending */
67 #define IOSOCKETFLAG_DEAD             0x00000040 /* socket dead (disconnected) */
68 #define IOSOCKETFLAG_RECONNECT_IPV4   0x00000080 /* possible fallback to ipv4 connect if ipv6 fails */
69
70 /* DNS Flags */
71 #define IOSOCKETFLAG_PENDING_BINDDNS  0x00000100
72 #define IOSOCKETFLAG_PENDING_DESTDNS  0x00000200
73 #define IOSOCKETFLAG_DNSDONE_BINDDNS  0x00000400
74 #define IOSOCKETFLAG_DNSDONE_DESTDNS  0x00000800
75 #define IOSOCKETFLAG_DNSERROR         0x00001000
76
77 /* SSL Flags */
78 #define IOSOCKETFLAG_SSLSOCKET        0x00002000 /* use ssl after connecting */
79 #define IOSOCKETFLAG_SSL_HANDSHAKE    0x00004000 /* SSL Handshake in progress */
80 #define IOSOCKETFLAG_SSL_WANTWRITE    0x00008000 /* ssl module wants write access */
81 #define IOSOCKETFLAG_SSL_READHS       0x00010000 /* ssl read rehandshake */
82 #define IOSOCKETFLAG_SSL_WRITEHS      0x00020000 /* ssl write rehandshake */
83 #define IOSOCKETFLAG_SSL_ESTABLISHED  0x00040000 /* ssl connection established */
84
85 /* WANT_READ / WANT_WRITE override */
86 #define IOSOCKETFLAG_OVERRIDE_WANT_RW 0x00080000
87 #define IOSOCKETFLAG_OVERRIDE_WANT_R  0x00100000
88 #define IOSOCKETFLAG_OVERRIDE_WANT_W  0x00200000
89
90 /* Parent descriptors */
91 #define IOSOCKETFLAG_PARENT_PUBLIC    0x10000000
92 #define IOSOCKETFLAG_PARENT_DNSENGINE 0x20000000
93 /* reserved flags for additional descriptor types? */
94
95 struct IOSocketDNSLookup {
96         unsigned int bindlookup : 1;
97         char hostname[256];
98         struct _IOSocket *iosocket;
99         struct _IODNSQuery *query;
100         struct IODNSResult *result;
101 };
102
103 struct _IOSocket {
104     int fd;
105         
106         unsigned int socket_flags : 32;
107         
108         struct {
109                 struct IODNSAddress addr;
110                 struct IOSocketDNSLookup *addrlookup;
111         } bind;
112         struct {
113                 struct IODNSAddress addr;
114                 struct IOSocketDNSLookup *addrlookup;
115         } dest;
116         
117         unsigned int port : 16;
118         
119         struct IOSocketBuffer readbuf;
120     struct IOSocketBuffer writebuf;
121         
122         struct IOSSLDescriptor *sslnode;
123         
124         void *parent;
125         
126         struct _IOSocket *next, *prev;
127 };
128
129 void _init_sockets();
130 struct _IOSocket *_create_socket();
131 void _free_socket(struct _IOSocket *iosock);
132 void iosocket_activate(struct _IOSocket *iosock);
133 void iosocket_deactivate(struct _IOSocket *iosock);
134 void iosocket_update(struct _IOSocket *iosock);
135
136 void iosocket_loop(int usec);
137 void iosocket_lookup_callback(struct IOSocketDNSLookup *lookup, struct IODNSEvent *event);
138 void iosocket_events_callback(struct _IOSocket *iosock, int readable, int writeable);
139
140 #define iosocket_wants_reads(IOSOCK) \
141 (\
142         ((IOSOCK->socket_flags & (IOSOCKETFLAG_SSL_READHS | IOSOCKETFLAG_SSL_WRITEHS)) && !(IOSOCK->socket_flags & IOSOCKETFLAG_SSL_WANTWRITE)) || \
143         (!(IOSOCK->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_RW)) || \
144         ((IOSOCK->socket_flags & (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_R)) == (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_R)) \
145 )\r
146 #define iosocket_wants_writes(IOSOCK) \
147 (\
148         ((IOSOCK->socket_flags & (IOSOCKETFLAG_SSL_READHS | IOSOCKETFLAG_SSL_WRITEHS | IOSOCKETFLAG_SSL_WANTWRITE)) > IOSOCKETFLAG_SSL_WANTWRITE) || \
149         (!(IOSOCK->socket_flags & IOSOCKETFLAG_OVERRIDE_WANT_RW) && (IOSOCK->writebuf.bufpos || (IOSOCK->socket_flags & IOSOCKETFLAG_CONNECTING))) || \
150         ((IOSOCK->socket_flags & (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_W)) == (IOSOCKETFLAG_OVERRIDE_WANT_RW | IOSOCKETFLAG_OVERRIDE_WANT_W)) \
151 )
152
153 #endif
154
155 struct IOSocketEvent;
156
157 #define IOSOCKET_CALLBACK(NAME) void NAME(struct IOSocketEvent *event)
158 typedef IOSOCKET_CALLBACK(iosocket_callback);
159
160 enum IOSocketStatus { 
161     IOSOCKET_CLOSED, /* descriptor is dead (socket waiting for removal or timer) */
162     IOSOCKET_LISTENING, /* descriptor is waiting for connections (server socket) */
163     IOSOCKET_CONNECTING, /* descriptor is waiting for connection approval (connecting client socket) */
164     IOSOCKET_CONNECTED, /* descriptor is connected (connected client socket) */
165         IOSOCKET_SSLHANDSHAKE /* descriptor is waiting for ssl (handshake) */
166 };
167
168 enum IOSocketEventType {
169     IOSOCKETEVENT_IGNORE,
170     IOSOCKETEVENT_RECV, /* client socket received something (read_lines == 1  =>  recv_str valid;  read_lines == 0  =>  recv_buf valid) */
171     IOSOCKETEVENT_CONNECTED, /* client socket connected successful */
172     IOSOCKETEVENT_NOTCONNECTED, /* client socket could not connect (errid valid) */
173     IOSOCKETEVENT_CLOSED, /* client socket lost connection (errid valid) */
174     IOSOCKETEVENT_ACCEPT, /* server socket accepted new connection (accept_socket valid) */
175         IOSOCKETEVENT_DNSFAILED /* failed to lookup DNS information (recv_str contains error message) */
176 };
177
178 #define IOSOCKET_ADDR_IPV4 0x01
179 #define IOSOCKET_ADDR_IPV6 0x02 /* overrides IOSOCKET_ADDR_IPV4 */
180 #define IOSOCKET_PROTO_UDP 0x04
181
182 #if !defined IOSOCKET_CPP
183 struct IOSocket {
184         void *iosocket;
185         
186         enum IOSocketStatus status;
187         int listening : 1;
188         int ssl : 1;
189         int parse_delimiter : 1;
190         int parse_empty : 1; /* parse "empty" lines (only if parse_delimiter is set) */
191         unsigned char delimiters[IOSOCKET_PARSE_DELIMITERS_COUNT];
192         
193         void *data;
194         iosocket_callback *callback;
195 };
196
197 struct IOSocketEvent {
198     enum IOSocketEventType type;
199     struct IOSocket *socket;
200     union {
201         char *recv_str;
202                 struct IOSocketBuffer *recv_buf;
203         int errid;
204         struct IOSocket *accept_socket;
205     } data;
206 };
207
208 struct IOSocket *iosocket_connect(const char *hostname, unsigned int port, int ssl, const char *bindhost, iosocket_callback *callback);
209 struct IOSocket *iosocket_connect_flags(const char *hostname, unsigned int port, int ssl, const char *bindhost, iosocket_callback *callback, int flags);
210 struct IOSocket *iosocket_listen(const char *hostname, unsigned int port, iosocket_callback *callback);
211 struct IOSocket *iosocket_listen_flags(const char *hostname, unsigned int port, iosocket_callback *callback, int flags);
212 struct IOSocket *iosocket_listen_ssl(const char *hostname, unsigned int port, const char *certfile, const char *keyfile, iosocket_callback *callback);
213 struct IOSocket *iosocket_listen_ssl_flags(const char *hostname, unsigned int port, const char *certfile, const char *keyfile, iosocket_callback *callback, int flags);
214 void iosocket_write(struct IOSocket *iosocket, const char *line);
215 void iosocket_send(struct IOSocket *iosocket, const char *data, size_t datalen);
216 void iosocket_printf(struct IOSocket *iosocket, const char *text, ...);
217 void iosocket_close(struct IOSocket *iosocket);
218
219 #endif
220 #endif