mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-02 11:33:21 +00:00
[MAJOR] added generic protocol support
A new generic protocol mechanism has been added. It provides an easy method to implement new protocols with different listeners (eg: unix sockets). The listeners are automatically started at the right moment and enabled after the possible fork().
This commit is contained in:
parent
d680371064
commit
dd81598553
2
Makefile
2
Makefile
@ -226,7 +226,7 @@ LDFLAGS = -g
|
||||
|
||||
all: haproxy
|
||||
|
||||
OBJS = src/haproxy.o src/sessionhash.o src/base64.o \
|
||||
OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
|
||||
src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
|
||||
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
|
||||
src/checks.o src/queue.o src/client.o src/proxy.o \
|
||||
|
@ -98,7 +98,7 @@ LIBS = $(LIBS.$(TARGET)) $(LIBS.$(REGEX)) $(ADDLIB)
|
||||
CFLAGS = -Wall $(COPTS) $(DEBUG)
|
||||
LDFLAGS = -g
|
||||
|
||||
OBJS = src/haproxy.o src/sessionhash.o src/base64.o \
|
||||
OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
|
||||
src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
|
||||
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
|
||||
src/checks.o src/queue.o src/client.o src/proxy.o \
|
||||
|
@ -95,7 +95,7 @@ LIBS = $(LIBS.$(TARGET)) $(LIBS.$(REGEX)) $(ADDLIB)
|
||||
CFLAGS = -Wall $(COPTS) $(DEBUG) -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386
|
||||
LDFLAGS = -g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386
|
||||
|
||||
OBJS = src/haproxy.o src/sessionhash.o src/base64.o \
|
||||
OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
|
||||
src/uri_auth.o src/standard.o src/buffers.o src/log.o src/task.o \
|
||||
src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \
|
||||
src/checks.o src/queue.o src/client.o src/proxy.o \
|
||||
|
61
include/proto/protocols.h
Normal file
61
include/proto/protocols.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
include/proto/protocols.h
|
||||
This file declares generic protocol primitives.
|
||||
|
||||
Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation, version 2.1
|
||||
exclusively.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _PROTO_PROTOCOLS_H
|
||||
#define _PROTO_PROTOCOLS_H
|
||||
|
||||
#include <types/protocols.h>
|
||||
|
||||
/* Registers the protocol <proto> */
|
||||
void protocol_register(struct protocol *proto);
|
||||
|
||||
/* Unregisters the protocol <proto>. Note that all listeners must have
|
||||
* previously been unbound.
|
||||
*/
|
||||
void protocol_unregister(struct protocol *proto);
|
||||
|
||||
/* binds all listeneres of all registered protocols. Returns a composition
|
||||
* of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
|
||||
*/
|
||||
int protocol_bind_all(void);
|
||||
|
||||
/* unbinds all listeners of all registered protocols. They are also closed.
|
||||
* This must be performed before calling exit() in order to get a chance to
|
||||
* remove file-system based sockets and pipes.
|
||||
* Returns a composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
|
||||
*/
|
||||
int protocol_unbind_all(void);
|
||||
|
||||
/* enables all listeners of all registered protocols. This is intended to be
|
||||
* used after a fork() to enable reading on all file descriptors. Returns a
|
||||
* composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
|
||||
*/
|
||||
int protocol_enable_all(void);
|
||||
|
||||
|
||||
#endif /* _PROTO_PROTOCOLS_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
@ -30,6 +30,7 @@
|
||||
#include <common/config.h>
|
||||
#include <types/task.h>
|
||||
#include <types/buffers.h>
|
||||
#include <types/protocols.h>
|
||||
|
||||
/* different possible states for the fd */
|
||||
#define FD_STCLOSE 0
|
||||
@ -66,6 +67,7 @@ struct fdtab {
|
||||
unsigned char ev; /* event seen in return of poll() : FD_POLL_* */
|
||||
struct sockaddr *peeraddr; /* pointer to peer's network address, or NULL if unset */
|
||||
socklen_t peerlen; /* peer's address length, or 0 if unset */
|
||||
struct listener *listener; /* the listener which created this fd, or NULL if unset */
|
||||
};
|
||||
|
||||
/*
|
||||
|
93
include/types/protocols.h
Normal file
93
include/types/protocols.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
include/types/protocols.h
|
||||
This file defines the structures used by generic network protocols.
|
||||
|
||||
Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation, version 2.1
|
||||
exclusively.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _TYPES_PROTOCOLS_H
|
||||
#define _TYPES_PROTOCOLS_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <common/config.h>
|
||||
#include <common/mini-clist.h>
|
||||
|
||||
/* max length of a protcol name, including trailing zero */
|
||||
#define PROTO_NAME_LEN 16
|
||||
|
||||
/* return codes for bind_all() */
|
||||
#define ERR_NONE 0 /* no error */
|
||||
#define ERR_RETRYABLE 1 /* retryable error, may be cumulated */
|
||||
#define ERR_FATAL 2 /* fatal error, may be cumulated */
|
||||
|
||||
/* listener state */
|
||||
#define LI_NEW 0 /* not initialized yet */
|
||||
#define LI_LISTEN 1 /* started, listening but not enabled */
|
||||
#define LI_READY 2 /* started, listening and enabled */
|
||||
#define LI_FULL 3 /* reached its connection limit */
|
||||
|
||||
/* The listener will be directly referenced by the fdtab[] which holds its
|
||||
* socket. The listener provides the protocol-specific accept() function to
|
||||
* the fdtab.
|
||||
*/
|
||||
struct listener {
|
||||
int fd; /* the listen socket */
|
||||
int state; /* state: NEW, READY, FULL */
|
||||
struct sockaddr_storage addr; /* the address we listen to */
|
||||
struct protocol *proto; /* protocol this listener belongs to */
|
||||
int nbconn; /* current number of connections on this listener */
|
||||
int maxconn; /* maximum connections allowed on this listener */
|
||||
struct listener *next; /* next address for the same proxy, or NULL */
|
||||
struct list proto_list; /* list in the protocol header */
|
||||
int (*accept)(int fd); /* accept() function passed to fdtab[] */
|
||||
void (*handler)(struct task *t, struct timeval *next); /* protocol handler */
|
||||
struct timeval *timeout; /* pointer to client-side timeout */
|
||||
void *private; /* any private data which may be used by accept() */
|
||||
};
|
||||
|
||||
/* This structure contains all information needed to easily handle a protocol.
|
||||
* Its primary goal is to ease listeners maintenance. Specifically, the
|
||||
* bind_all() primitive must be used before any fork(), and the enable_all()
|
||||
* primitive must be called after the fork() to enable all fds. Last, the
|
||||
* unbind_all() primitive closes all listeners.
|
||||
*/
|
||||
struct protocol {
|
||||
char name[PROTO_NAME_LEN]; /* protocol name, zero-terminated */
|
||||
int sock_domain; /* socket domain, as passed to socket() */
|
||||
int sock_type; /* socket type, as passed to socket() */
|
||||
int sock_prot; /* socket protocol, as passed to socket() */
|
||||
sa_family_t sock_family; /* socket family, for sockaddr */
|
||||
int (*read)(int fd); /* generic read function */
|
||||
int (*write)(int fd); /* generic write function */
|
||||
int (*bind_all)(struct protocol *proto); /* bind all unbound listeners */
|
||||
int (*unbind_all)(struct protocol *proto); /* unbind all bound listeners */
|
||||
int (*enable_all)(struct protocol *proto); /* enable all bound listeners */
|
||||
struct list listeners; /* list of listeners using this protocol */
|
||||
int nb_listeners; /* number of listeners */
|
||||
struct list list; /* list of registered protocols */
|
||||
};
|
||||
|
||||
#endif /* _TYPES_PROTOCOLS_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
@ -37,6 +37,7 @@
|
||||
#include <types/acl.h>
|
||||
#include <types/buffers.h>
|
||||
#include <types/httperr.h>
|
||||
#include <types/protocols.h>
|
||||
#include <types/session.h>
|
||||
#include <types/server.h>
|
||||
|
||||
@ -63,18 +64,6 @@
|
||||
#define PR_CAP_RS 0x0004
|
||||
#define PR_CAP_LISTEN (PR_CAP_FE|PR_CAP_BE|PR_CAP_RS)
|
||||
|
||||
/* return codes for start_proxies */
|
||||
#define ERR_NONE 0 /* no error */
|
||||
#define ERR_RETRYABLE 1 /* retryable error, may be cumulated */
|
||||
#define ERR_FATAL 2 /* fatal error, may be cumulated */
|
||||
|
||||
|
||||
struct listener {
|
||||
int fd; /* the listen socket */
|
||||
struct sockaddr_storage addr; /* the address we listen to */
|
||||
struct listener *next; /* next address or NULL */
|
||||
};
|
||||
|
||||
struct proxy {
|
||||
struct listener *listen; /* the listen addresses and sockets */
|
||||
struct in_addr mon_net, mon_mask; /* don't forward connections from this net (network order) FIXME: should support IPv6 */
|
||||
|
@ -85,6 +85,7 @@
|
||||
#include <proto/client.h>
|
||||
#include <proto/fd.h>
|
||||
#include <proto/log.h>
|
||||
#include <proto/protocols.h>
|
||||
#include <proto/proto_http.h>
|
||||
#include <proto/proxy.h>
|
||||
#include <proto/queue.h>
|
||||
@ -720,7 +721,9 @@ void deinit(void)
|
||||
p = p->next;
|
||||
free(p0);
|
||||
}/* end while(p) */
|
||||
|
||||
|
||||
protocol_unbind_all();
|
||||
|
||||
if (global.chroot) free(global.chroot);
|
||||
global.chroot = NULL;
|
||||
|
||||
@ -838,6 +841,14 @@ int main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (protocol_bind_all() != ERR_NONE) {
|
||||
Alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
|
||||
protocol_unbind_all(); /* cleanup everything we can */
|
||||
if (nb_oldpids)
|
||||
tell_old_pids(SIGTTIN);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* prepare pause/play signals */
|
||||
signal(SIGTTOU, sig_pause);
|
||||
signal(SIGTTIN, sig_listen);
|
||||
@ -865,6 +876,7 @@ int main(int argc, char **argv)
|
||||
Alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
|
||||
if (nb_oldpids)
|
||||
tell_old_pids(SIGTTIN);
|
||||
protocol_unbind_all();
|
||||
exit(1);
|
||||
}
|
||||
pidfile = fdopen(pidfd, "w");
|
||||
@ -904,6 +916,7 @@ int main(int argc, char **argv)
|
||||
" Make sure you have enough permissions and that the module is loadable.\n"
|
||||
" Alternatively, you may disable the 'tcpsplice' options in the configuration.\n"
|
||||
"", argv[0], global.gid);
|
||||
protocol_unbind_all();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -919,6 +932,7 @@ int main(int argc, char **argv)
|
||||
argv[0],
|
||||
(ret == -1) ? " Incorrect module version.\n"
|
||||
: " Make sure you have enough permissions and that the module is loaded.\n");
|
||||
protocol_unbind_all();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -927,6 +941,7 @@ int main(int argc, char **argv)
|
||||
if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
|
||||
Alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
|
||||
"", argv[0], global.gid);
|
||||
protocol_unbind_all();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -936,6 +951,7 @@ int main(int argc, char **argv)
|
||||
Alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
|
||||
if (nb_oldpids)
|
||||
tell_old_pids(SIGTTIN);
|
||||
protocol_unbind_all();
|
||||
exit(1);
|
||||
}
|
||||
chdir("/");
|
||||
@ -951,11 +967,13 @@ int main(int argc, char **argv)
|
||||
/* setgid / setuid */
|
||||
if (global.gid && setgid(global.gid) == -1) {
|
||||
Alert("[%s.main()] Cannot set gid %d.\n", argv[0], global.gid);
|
||||
protocol_unbind_all();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (global.uid && setuid(global.uid) == -1) {
|
||||
Alert("[%s.main()] Cannot set uid %d.\n", argv[0], global.uid);
|
||||
protocol_unbind_all();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -976,6 +994,7 @@ int main(int argc, char **argv)
|
||||
ret = fork();
|
||||
if (ret < 0) {
|
||||
Alert("[%s.main()] Cannot fork.\n", argv[0]);
|
||||
protocol_unbind_all();
|
||||
exit(1); /* there has been an error */
|
||||
}
|
||||
else if (ret == 0) /* child breaks here */
|
||||
@ -1010,6 +1029,7 @@ int main(int argc, char **argv)
|
||||
fork_poller();
|
||||
}
|
||||
|
||||
protocol_enable_all();
|
||||
/*
|
||||
* That's it : the central polling loop. Run until we stop.
|
||||
*/
|
||||
|
90
src/protocols.c
Normal file
90
src/protocols.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Protocol registration functions.
|
||||
*
|
||||
* Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <common/config.h>
|
||||
#include <common/mini-clist.h>
|
||||
#include <common/standard.h>
|
||||
|
||||
#include <types/protocols.h>
|
||||
|
||||
/* List head of all registered protocols */
|
||||
static struct list protocols = LIST_HEAD_INIT(protocols);
|
||||
|
||||
/* Registers the protocol <proto> */
|
||||
void protocol_register(struct protocol *proto)
|
||||
{
|
||||
LIST_ADDQ(&protocols, &proto->list);
|
||||
}
|
||||
|
||||
/* Unregisters the protocol <proto>. Note that all listeners must have
|
||||
* previously been unbound.
|
||||
*/
|
||||
void protocol_unregister(struct protocol *proto)
|
||||
{
|
||||
LIST_DEL(&proto->list);
|
||||
LIST_INIT(&proto->list);
|
||||
}
|
||||
|
||||
/* binds all listeneres of all registered protocols. Returns a composition
|
||||
* of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
|
||||
*/
|
||||
int protocol_bind_all(void)
|
||||
{
|
||||
struct protocol *proto;
|
||||
int err;
|
||||
|
||||
err = 0;
|
||||
list_for_each_entry(proto, &protocols, list) {
|
||||
if (proto->bind_all)
|
||||
err |= proto->bind_all(proto);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* unbinds all listeners of all registered protocols. They are also closed.
|
||||
* This must be performed before calling exit() in order to get a chance to
|
||||
* remove file-system based sockets and pipes.
|
||||
* Returns a composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
|
||||
*/
|
||||
int protocol_unbind_all(void)
|
||||
{
|
||||
struct protocol *proto;
|
||||
int err;
|
||||
|
||||
err = 0;
|
||||
list_for_each_entry(proto, &protocols, list) {
|
||||
if (proto->unbind_all)
|
||||
err |= proto->unbind_all(proto);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* enables all listeners of all registered protocols. This is intended to be
|
||||
* used after a fork() to enable reading on all file descriptors. Returns a
|
||||
* composition of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
|
||||
*/
|
||||
int protocol_enable_all(void)
|
||||
{
|
||||
struct protocol *proto;
|
||||
int err;
|
||||
|
||||
err = 0;
|
||||
list_for_each_entry(proto, &protocols, list) {
|
||||
if (proto->enable_all)
|
||||
err |= proto->enable_all(proto);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user