root/cserver/server.h

Revision 1203, 7.7 kB (checked in by efphe, 1 year ago)

moving code from fenilot.org

Line 
1 /*
2  * Copyright (c) 2006, Federico Tomassini AKA efphe (effetom AT gmail DOT com)
3  * All rights reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #ifndef SERVER_
29 #define SERVER_H
30
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <netdb.h>
35 #include <unistd.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <arpa/inet.h>
41 #include <pthread.h>
42 #include <poll.h>
43 #include <signal.h>
44 typedef void (*sighandler_t)(int);
45
46 #include "wlog.h"
47
48 #define MAX_SERVER_NAME_LEN     32
49 #define MAX_SERVER_HOSTNAMES    12
50 #define MAX_SERVER_SOCKETS      12
51 #define MAX_THREADS_PER_SOCKET  25
52 #define DEF_THREADS_PER_SOCKET  10
53 #define MAX_SERVER_BACKLOG      12
54 #define DEF_SERVER_BACKLOG      12
55
56
57 /*
58  **                   
59  ***                  *
60  **** ABOUT LOGGING: **
61  ***                  *
62  **                   
63  *
64  * With the function:
65  * 
66  *   server_log_init(LogLevel level, SyslogFacility facility, int on_stderr)
67  *
68  * it's possible to configure the logging library.
69  * In particular, if `level` and `facility` are -1, default values are used,
70  * and it's safe to call:
71  *
72  *   server_log_init(-1, -1, on_stderr);
73  *
74  * If on_stderr is 1 (or, in general, is True), logging will be printed to
75  * STDERR, otherwise syslog will be used.
76  * By default, STDERR is used.
77  *
78  * To debug your code, you can use the following function:
79  *
80  *   void     fatal(const char *, ...)   -> log and exit (deliver a SIGINT)
81  *   void     error(const char *, ...)   -> log
82  *   void     logit(const char *, ...)   -> log
83  *   void     verbose(const char *, ...) -> log
84  *   void     debug(const char *, ...)   -> log if level is high enough
85  *   void     debug2(const char *, ...)  -> log if level is high enough
86  *   void     debug3(const char *, ...)  -> log if level is high enough
87  *
88  * For example:
89  *   
90  *   char *msg= "ciao"
91  *   logit("This is a beatiful message: %s", a);
92  * 
93  */
94
95
96 /*
97  **                   
98  ***                  *
99  **** ABOUT SIGNALS: **
100  ***                  *
101  **                   
102  *               
103  * Signals are programmable for each server instance.
104  * Using the function:
105  *
106  *   void server_set_signal_handler(server *s, int signum, void(*f)(int));
107  *
108  * it's possible to define server behaviour when receiving the signal
109  * signum.
110  *
111  **
112  ***                    *
113  **** STOPPING SERVERS **
114  ***                    *
115  **
116  *
117  * To stop the server when a signal is delivered, it's sufficient
118  * to call the function:
119  *
120  *   void servers_stop()
121  *
122  * inside the handler. Note that the memory allocated by servers struct
123  * will be free() automatically.
124  *
125  * To stop servers, but waiting for active connections to be worked, call:
126  *
127  *   void servers_slow_stop()
128  *
129  **
130  ***                   *
131  **** DEFAULT ACTIONS **
132  ***                   *
133  **
134  *
135  * If the same handler is set for multiple signals, all
136  * signals associate to that handler will be blocked during
137  * the execution of the hanlder.
138  *
139  * By default, the following signals will be handled:
140  *
141  *  - SIGINT
142  *      - Threads exit immediately.
143  *      - Memory allocation of server(s) struct will be free()
144  *
145  *          (simply call of:  servers_stop() )
146  *
147  *  - SIGTERM (simply call of servers_slow_stop() )
148  *      - Threads waiting for connections exit immediately.
149  *      - Threads working for active connections finish their work and exit.
150  *      - Memory allocation of server(s) struct will be free()
151  *     
152  *          (simply call of:  servers_slow_stop() )
153  *
154  ***
155  * By the way, you can overwrite the handler of the two signals.
156  ***
157  */
158
159
160 typedef pthread_mutex_t pmt;
161 typedef pthread_cond_t pct;
162
163 /* server signal handler */
164 struct ssh
165 {
166     int         signum;
167     void        (*f)(int);
168     sigset_t    sa_mask;
169     struct ssh  *next;
170 };
171 typedef struct ssh ssh;
172 #define SSH_SIZE sizeof(ssh)
173
174 typedef struct
175 {
176     char            name[MAX_SERVER_NAME_LEN];
177     int             port;
178     int             type; /* default SOCK_STREAM */
179     int             family; /* default AF_INET */
180     int             backlog; /* default DEF_SERVER_BACKLOG */
181     int             threads_per_socket; /* default DEF_THREADS_PER_SOCKET */       
182     int             hostnames_n;
183     char            *hostnames[MAX_SERVER_HOSTNAMES];
184     int             sockets_n;
185     int             sockets[MAX_SERVER_SOCKETS];
186     pmt             sockets_mutex[MAX_SERVER_SOCKETS];
187     int             processing_socket;
188     pmt             processing_socket_mutex;
189     int             threads_counter;
190     pmt             threads_counter_mutex;
191     pct             threads_counter_cond;
192     void            (*handler)(int,struct sockaddr*,socklen_t*);
193     pmt             start;
194     ssh             *signal_handlers;
195 } server;
196
197 /*
198  * Api.
199  */
200
201
202 void    server_log_init(LogLevel level, SyslogFacility facility, int on_stderr);
203 void    server_set_signal_handler(server *s, int signum, void(*f)(int));
204 void    server_init(server *s);
205 void    server_set_name(server *s,char *name);
206 void    server_set_backlog(server *s,int backlog);
207 void    server_set_tps(server *s,int tps);
208 void    servers_destroy(server *s, int nserver);
209 int     server_add_hostname(server *s,char *hname);
210 void    server_set_type(server *s, int type);
211 void    server_set_family(server *s, int family);
212 void    server_set_port(server *s,uint16_t port);
213 void    server_set_handler(server *s, void (*f)(int,struct sockaddr*,socklen_t*));
214 void    servers_serve(server *servers,int nserver);
215 int     server_setsockopt(server *s,int level,int optname,const void *optval,socklen_t optlen);
216 void    servers_stop(void);
217 void    servers_slow_stop(void);
218
219
220 /*
221  * Internals.
222  */
223
224 ssh*    _server_new_signal_handler(int signum, sigset_t *sa_mask, void(*f)(int));
225 ssh*    _server_has_signal_handler(server *s, int signum);
226 int     _servers_are_stopped();
227 void    _server_destroy(server *s);
228 int     _server_add_socket(server *s,int skt);
229 int     _server_prepare_bind_sockets(server *s);
230 void    _server_listen(server *s);
231 void    _servers_thread_begin_work(void);
232 void    _server_thread_ends_work(void);
233 int     _server_thread_begins(pmt *m);
234 void* _server_accept_thread(void *arg);
235 void    _server_init_signals(server *s);
236 void    _server_init_mutexes(server *s);
237 void    _server_default_sigint_handler(int signum);
238 void    _server_default_sigterm_handler(int signum);
239 void    _server_serve(server *s);
240 #endif
Note: See TracBrowser for help on using the browser.