1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  *                    Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #ifndef INCL_MIO_H
22 #define INCL_MIO_H
23 
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27 #include "util/inaddr.h"
28 #include "ac-stdint.h"
29 
30 /* jabberd2 Windows DLL */
31 #ifndef JABBERD2_API
32 # ifdef _WIN32
33 #  ifdef JABBERD2_EXPORTS
34 #   define JABBERD2_API  __declspec(dllexport)
35 #  else /* JABBERD2_EXPORTS */
36 #   define JABBERD2_API  __declspec(dllimport)
37 #  endif /* JABBERD2_EXPORTS */
38 # else /* _WIN32 */
39 #  define JABBERD2_API extern
40 # endif /* _WIN32 */
41 #endif /* JABBERD2_API */
42 
43 #ifdef _WIN32
44 # define MIO_MAXFD FD_SETSIZE
45 #else
46 # define MIO_MAXFD 1024
47 #endif
48 
49 #include <stdio.h>
50 #include <errno.h>
51 #include <stdlib.h>
52 #include <stdarg.h>
53 
54 #ifdef HAVE_UNISTD_H
55 # include <unistd.h>
56 #endif
57 
58 #ifdef HAVE_SYS_SOCKET_H
59 # include <sys/socket.h>
60 #endif
61 
62 #ifdef HAVE_FCNTL_H
63 # include <fcntl.h>
64 #endif
65 
66 #ifdef HAVE_SYS_IOCTL_H
67 # include <sys/ioctl.h>
68 #endif
69 
70 #ifdef HAVE_SYS_FILIO_H
71 # include <sys/filio.h>
72 #endif
73 
74 #ifdef __cplusplus
75 extern "C" {
76 #endif
77 
78 /**
79  * @file mio/mio.h
80  * @brief mio - manage i/o
81  *
82  * This is the most simple fd wrapper possible. It is also customized
83  * per-app and may be limited/extended depending on needs.
84  *
85  * It's basically our own implementation of libevent or libev.
86  *
87  * Usage is pretty simple:
88  *  - create a manager
89  *  - add fds or tell it to listen
90  *  - assign an action handler
91  *  - tell mio to read or write with a fd
92  *  - process accept, read, write, and close requests
93  *
94  * Note: normal fd's don't get events unless the app calls mio_read/write() first!
95  */
96 
97 /** the master mio mama */
98 struct mio_st;
99 
100 typedef struct mio_fd_st
101 {
102     int fd;
103 } *mio_fd_t;
104 
105 /** these are the actions and a handler type assigned by the applicaiton using mio */
106 typedef enum { action_ACCEPT, action_READ, action_WRITE, action_CLOSE } mio_action_t;
107 typedef int (*mio_handler_t) (struct mio_st **m, mio_action_t a, struct mio_fd_st *fd, void* data, void *arg);
108 
109 typedef struct mio_st
110 {
111   void (*mio_free)(struct mio_st **m);
112 
113   struct mio_fd_st *(*mio_listen)(struct mio_st **m, int port, const char *sourceip,
114 				  mio_handler_t app, void *arg);
115 
116   struct mio_fd_st *(*mio_connect)(struct mio_st **m, int port, const char *hostip,
117 				   const char *srcip, mio_handler_t app, void *arg);
118 
119   struct mio_fd_st *(*mio_register)(struct mio_st **m, int fd,
120 				   mio_handler_t app, void *arg);
121 
122   void (*mio_app)(struct mio_st **m, struct mio_fd_st *fd,
123 		  mio_handler_t app, void *arg);
124 
125   void (*mio_close)(struct mio_st **m, struct mio_fd_st *fd);
126 
127   void (*mio_write)(struct mio_st **m, struct mio_fd_st *fd);
128 
129   void (*mio_read)(struct mio_st **m, struct mio_fd_st *fd);
130 
131   void (*mio_run)(struct mio_st **m, int timeout);
132 } **mio_t;
133 
134 /** create/free the mio subsytem */
135 JABBERD2_API mio_t mio_new(int maxfd); /* returns NULL if failed */
136 
137 #define mio_free(m) (*m)->mio_free(m)
138 
139 /** for creating a new listen socket in this mio (returns new fd or <0) */
140 #define mio_listen(m, port, sourceip, app, arg) \
141     (*m)->mio_listen(m, port, sourceip, app, arg)
142 
143 /** for creating a new socket connected to this ip:port (returns new fd or <0, use mio_read/write first) */
144 #define mio_connect(m, port, hostip, srcip, app, arg) \
145     (*m)->mio_connect(m, port, hostip, srcip, app, arg)
146 
147 /** for adding an existing socket connected to this mio */
148 #define mio_register(m, fd, app, arg) \
149     (*m)->mio_register(m, fd, app, arg)
150 
151 /** re-set the app handler */
152 #define mio_app(m, fd, app, arg) (*m)->mio_app(m, fd, app, arg)
153 
154 /** request that mio close this fd */
155 #define mio_close(m, fd) (*m)->mio_close(m, fd)
156 
157 /** mio should try the write action on this fd now */
158 #define mio_write(m, fd) (*m)->mio_write(m, fd)
159 
160 /** process read events for this fd */
161 #define mio_read(m, fd) (*m)->mio_read(m, fd)
162 
163 /** give some cpu time to mio to check it's sockets, 0 is non-blocking */
164 #define mio_run(m, timeout) (*m)->mio_run(m, timeout)
165 
166 /** all MIO related routines should use those for error reporting */
167 #ifndef _WIN32
168 # define MIO_ERROR       errno
169 # define MIO_SETERROR(e) (errno = e)
170 # define MIO_STRERROR(e) strerror(e)
171 # define MIO_WOULDBLOCK  (errno == EWOULDBLOCK || errno == EINTR || errno == EAGAIN)
172 #else /* _WIN32 */
173 JABBERD2_API char *mio_strerror(int code);
174 # define MIO_ERROR       WSAGetLastError()
175 # define MIO_SETERROR(e) WSASetLastError(e)
176 # define MIO_STRERROR(e) mio_strerror(e)
177 # define MIO_WOULDBLOCK  (WSAGetLastError() == WSAEWOULDBLOCK)
178 #endif /* _WIN32 */
179 
180 #ifdef __cplusplus
181 }
182 #endif
183 
184 #endif  /* INCL_MIO_H */
185 
186