Merge
This commit is contained in:
		@ -176,7 +176,7 @@ CONFIG_CONTEXT		*obj;
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			char *servers = config_get_value(obj->parameters, "servers");
 | 
								char *servers = config_get_value(obj->parameters, "servers");
 | 
				
			||||||
			char *roptions = config_get_value(obj->parameters, "router_options");
 | 
								char *roptions = config_get_value(obj->parameters, "router_options");
 | 
				
			||||||
			if (servers)
 | 
								if (servers && obj->element)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				char *s = strtok(servers, ",");
 | 
									char *s = strtok(servers, ",");
 | 
				
			||||||
				while (s)
 | 
									while (s)
 | 
				
			||||||
@ -191,7 +191,7 @@ CONFIG_CONTEXT		*obj;
 | 
				
			|||||||
					s = strtok(NULL, ",");
 | 
										s = strtok(NULL, ",");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (roptions)
 | 
								if (roptions && obj->element)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				char *s = strtok(roptions, ",");
 | 
									char *s = strtok(roptions, ",");
 | 
				
			||||||
				while (s)
 | 
									while (s)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										13
									
								
								core/dcb.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								core/dcb.c
									
									
									
									
									
								
							@ -35,6 +35,10 @@
 | 
				
			|||||||
 * 28/06/13	Mark Riddoch		Changed the free mechanism ti
 | 
					 * 28/06/13	Mark Riddoch		Changed the free mechanism ti
 | 
				
			||||||
 * 					introduce a zombie state for the
 | 
					 * 					introduce a zombie state for the
 | 
				
			||||||
 * 					dcb
 | 
					 * 					dcb
 | 
				
			||||||
 | 
					 * 02/07/2013	Massimiliano Pinto	Addition of delayqlock, delayq and authlock
 | 
				
			||||||
 | 
					 *					for handling backend asynchronous protocol connection
 | 
				
			||||||
 | 
					 *					and a generic lock for backend authentication
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * @endverbatim
 | 
					 * @endverbatim
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
@ -77,7 +81,10 @@ DCB	*rval;
 | 
				
			|||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spinlock_init(&rval->writeqlock);
 | 
						spinlock_init(&rval->writeqlock);
 | 
				
			||||||
 | 
						spinlock_init(&rval->delayqlock);
 | 
				
			||||||
 | 
						spinlock_init(&rval->authlock);
 | 
				
			||||||
	rval->writeq = NULL;
 | 
						rval->writeq = NULL;
 | 
				
			||||||
 | 
						rval->delayq = NULL;
 | 
				
			||||||
	rval->remote = NULL;
 | 
						rval->remote = NULL;
 | 
				
			||||||
	rval->state = DCB_STATE_ALLOC;
 | 
						rval->state = DCB_STATE_ALLOC;
 | 
				
			||||||
	rval->next = NULL;
 | 
						rval->next = NULL;
 | 
				
			||||||
@ -251,7 +258,8 @@ GWPROTOCOL	*funcs;
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if ((funcs = (GWPROTOCOL *)load_module(protocol, MODULE_PROTOCOL)) == NULL)
 | 
						if ((funcs = (GWPROTOCOL *)load_module(protocol, MODULE_PROTOCOL)) == NULL)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		dcb_free(dcb);
 | 
							dcb_final_free(dcb);
 | 
				
			||||||
 | 
							fprintf(stderr, "Failed to load protocol module for %s, feee dcb %p\n", protocol, dcb);
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	memcpy(&(dcb->func), funcs, sizeof(GWPROTOCOL));
 | 
						memcpy(&(dcb->func), funcs, sizeof(GWPROTOCOL));
 | 
				
			||||||
@ -259,7 +267,8 @@ GWPROTOCOL	*funcs;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if ((dcb->fd = dcb->func.connect(dcb, server, session)) == -1)
 | 
						if ((dcb->fd = dcb->func.connect(dcb, server, session)) == -1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		dcb_free(dcb);
 | 
							dcb_final_free(dcb);
 | 
				
			||||||
 | 
							fprintf(stderr, "Failed to connect to server, feee dcb %p\n", dcb);
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	atomic_add(&server->stats.n_connections, 1);
 | 
						atomic_add(&server->stats.n_connections, 1);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										474
									
								
								core/depend.mk
									
									
									
									
									
								
							
							
						
						
									
										474
									
								
								core/depend.mk
									
									
									
									
									
								
							@ -1,474 +0,0 @@
 | 
				
			|||||||
atomic.o: atomic.c
 | 
					 | 
				
			||||||
buffer.o: buffer.c /usr/include/stdlib.h /usr/include/features.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
 | 
					 | 
				
			||||||
 /usr/include/endian.h /usr/include/bits/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/byteswap.h /usr/include/sys/types.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigset.h /usr/include/bits/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
 | 
					 | 
				
			||||||
 /usr/include/alloca.h ../include/buffer.h
 | 
					 | 
				
			||||||
spinlock.o: spinlock.c ../include/spinlock.h ../include/thread.h \
 | 
					 | 
				
			||||||
 /usr/include/pthread.h /usr/include/features.h /usr/include/sys/cdefs.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs-64.h /usr/include/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
 | 
					 | 
				
			||||||
 /usr/include/sched.h /usr/include/bits/types.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/time.h /usr/include/bits/sched.h /usr/include/bits/time.h \
 | 
					 | 
				
			||||||
 /usr/include/xlocale.h /usr/include/bits/pthreadtypes.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/setjmp.h ../include/atomic.h
 | 
					 | 
				
			||||||
gateway.o: gateway.c ../include/gw.h /usr/include/stdio.h \
 | 
					 | 
				
			||||||
 /usr/include/features.h /usr/include/sys/cdefs.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/ctype.h /usr/include/endian.h /usr/include/bits/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/byteswap.h /usr/include/xlocale.h /usr/include/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/errno.h /usr/include/linux/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/errno-base.h /usr/include/netdb.h \
 | 
					 | 
				
			||||||
 /usr/include/netinet/in.h /usr/include/stdint.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wchar.h /usr/include/sys/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/uio.h /usr/include/sys/types.h /usr/include/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/select.h /usr/include/bits/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigset.h /usr/include/bits/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/uio.h /usr/include/bits/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/socket.h /usr/include/asm/sockios.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/sockios.h /usr/include/bits/in.h \
 | 
					 | 
				
			||||||
 /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/fcntl.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/fcntl.h /usr/include/bits/stat.h /usr/include/unistd.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/syslog.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/syslog.h /usr/include/bits/syslog-path.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/stdlib.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
 | 
					 | 
				
			||||||
 /usr/include/alloca.h /usr/include/pwd.h /usr/include/sys/epoll.h \
 | 
					 | 
				
			||||||
 /usr/include/signal.h /usr/include/bits/signum.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigcontext.h /usr/include/bits/sigstack.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ucontext.h /usr/include/bits/sigthread.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h \
 | 
					 | 
				
			||||||
 /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ttydefaults.h /usr/include/arpa/inet.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdbool.h \
 | 
					 | 
				
			||||||
 ../include/gateway_mysql.h ../include/dcb.h ../include/spinlock.h \
 | 
					 | 
				
			||||||
 ../include/thread.h /usr/include/pthread.h /usr/include/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sched.h /usr/include/bits/setjmp.h ../include/buffer.h \
 | 
					 | 
				
			||||||
 ../include/mysql_protocol.h ../include/dcb.h ../include/service.h \
 | 
					 | 
				
			||||||
 ../include/server.h ../include/session.h ../include/modules.h \
 | 
					 | 
				
			||||||
 ../include/config.h ../include/poll.h
 | 
					 | 
				
			||||||
gateway_mysql_protocol.o: gateway_mysql_protocol.c ../include/gw.h \
 | 
					 | 
				
			||||||
 /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/ctype.h /usr/include/endian.h /usr/include/bits/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/byteswap.h /usr/include/xlocale.h /usr/include/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/errno.h /usr/include/linux/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/errno-base.h /usr/include/netdb.h \
 | 
					 | 
				
			||||||
 /usr/include/netinet/in.h /usr/include/stdint.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wchar.h /usr/include/sys/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/uio.h /usr/include/sys/types.h /usr/include/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/select.h /usr/include/bits/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigset.h /usr/include/bits/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/uio.h /usr/include/bits/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/socket.h /usr/include/asm/sockios.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/sockios.h /usr/include/bits/in.h \
 | 
					 | 
				
			||||||
 /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/fcntl.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/fcntl.h /usr/include/bits/stat.h /usr/include/unistd.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/syslog.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/syslog.h /usr/include/bits/syslog-path.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/stdlib.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
 | 
					 | 
				
			||||||
 /usr/include/alloca.h /usr/include/pwd.h /usr/include/sys/epoll.h \
 | 
					 | 
				
			||||||
 /usr/include/signal.h /usr/include/bits/signum.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigcontext.h /usr/include/bits/sigstack.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ucontext.h /usr/include/bits/sigthread.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h \
 | 
					 | 
				
			||||||
 /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ttydefaults.h /usr/include/arpa/inet.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdbool.h \
 | 
					 | 
				
			||||||
 ../include/gateway_mysql.h ../include/dcb.h ../include/spinlock.h \
 | 
					 | 
				
			||||||
 ../include/thread.h /usr/include/pthread.h /usr/include/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sched.h /usr/include/bits/setjmp.h ../include/buffer.h \
 | 
					 | 
				
			||||||
 ../include/mysql_protocol.h ../include/dcb.h ../include/session.h \
 | 
					 | 
				
			||||||
 /usr/include/openssl/sha.h /usr/include/openssl/e_os2.h \
 | 
					 | 
				
			||||||
 /usr/include/openssl/opensslconf.h \
 | 
					 | 
				
			||||||
 /usr/include/openssl/opensslconf-x86_64.h
 | 
					 | 
				
			||||||
gw_utils.o: gw_utils.c ../include/gw.h /usr/include/stdio.h \
 | 
					 | 
				
			||||||
 /usr/include/features.h /usr/include/sys/cdefs.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/ctype.h /usr/include/endian.h /usr/include/bits/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/byteswap.h /usr/include/xlocale.h /usr/include/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/errno.h /usr/include/linux/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/errno-base.h /usr/include/netdb.h \
 | 
					 | 
				
			||||||
 /usr/include/netinet/in.h /usr/include/stdint.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wchar.h /usr/include/sys/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/uio.h /usr/include/sys/types.h /usr/include/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/select.h /usr/include/bits/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigset.h /usr/include/bits/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/uio.h /usr/include/bits/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/socket.h /usr/include/asm/sockios.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/sockios.h /usr/include/bits/in.h \
 | 
					 | 
				
			||||||
 /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/fcntl.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/fcntl.h /usr/include/bits/stat.h /usr/include/unistd.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/syslog.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/syslog.h /usr/include/bits/syslog-path.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/stdlib.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
 | 
					 | 
				
			||||||
 /usr/include/alloca.h /usr/include/pwd.h /usr/include/sys/epoll.h \
 | 
					 | 
				
			||||||
 /usr/include/signal.h /usr/include/bits/signum.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigcontext.h /usr/include/bits/sigstack.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ucontext.h /usr/include/bits/sigthread.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h \
 | 
					 | 
				
			||||||
 /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ttydefaults.h /usr/include/arpa/inet.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdbool.h \
 | 
					 | 
				
			||||||
 ../include/gateway_mysql.h ../include/dcb.h ../include/spinlock.h \
 | 
					 | 
				
			||||||
 ../include/thread.h /usr/include/pthread.h /usr/include/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sched.h /usr/include/bits/setjmp.h ../include/buffer.h \
 | 
					 | 
				
			||||||
 ../include/mysql_protocol.h ../include/dcb.h ../include/session.h
 | 
					 | 
				
			||||||
utils.o: utils.c ../include/gw.h /usr/include/stdio.h \
 | 
					 | 
				
			||||||
 /usr/include/features.h /usr/include/sys/cdefs.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/ctype.h /usr/include/endian.h /usr/include/bits/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/byteswap.h /usr/include/xlocale.h /usr/include/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/errno.h /usr/include/linux/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/errno-base.h /usr/include/netdb.h \
 | 
					 | 
				
			||||||
 /usr/include/netinet/in.h /usr/include/stdint.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wchar.h /usr/include/sys/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/uio.h /usr/include/sys/types.h /usr/include/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/select.h /usr/include/bits/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigset.h /usr/include/bits/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/uio.h /usr/include/bits/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/socket.h /usr/include/asm/sockios.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/sockios.h /usr/include/bits/in.h \
 | 
					 | 
				
			||||||
 /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/fcntl.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/fcntl.h /usr/include/bits/stat.h /usr/include/unistd.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/syslog.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/syslog.h /usr/include/bits/syslog-path.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/stdlib.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
 | 
					 | 
				
			||||||
 /usr/include/alloca.h /usr/include/pwd.h /usr/include/sys/epoll.h \
 | 
					 | 
				
			||||||
 /usr/include/signal.h /usr/include/bits/signum.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigcontext.h /usr/include/bits/sigstack.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ucontext.h /usr/include/bits/sigthread.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/ioctls.h /usr/include/asm-generic/ioctls.h \
 | 
					 | 
				
			||||||
 /usr/include/linux/ioctl.h /usr/include/asm/ioctl.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/ttydefaults.h /usr/include/arpa/inet.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdbool.h \
 | 
					 | 
				
			||||||
 ../include/gateway_mysql.h ../include/dcb.h ../include/spinlock.h \
 | 
					 | 
				
			||||||
 ../include/thread.h /usr/include/pthread.h /usr/include/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sched.h /usr/include/bits/setjmp.h ../include/buffer.h \
 | 
					 | 
				
			||||||
 ../include/mysql_protocol.h ../include/dcb.h ../include/session.h \
 | 
					 | 
				
			||||||
 ../include/mysql_protocol.h /usr/include/openssl/sha.h \
 | 
					 | 
				
			||||||
 /usr/include/openssl/e_os2.h /usr/include/openssl/opensslconf.h \
 | 
					 | 
				
			||||||
 /usr/include/openssl/opensslconf-x86_64.h ../include/poll.h
 | 
					 | 
				
			||||||
dcb.o: dcb.c /usr/include/stdio.h /usr/include/features.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/stdlib.h /usr/include/bits/waitflags.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitstatus.h /usr/include/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/select.h /usr/include/bits/sigset.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/xlocale.h ../include/dcb.h \
 | 
					 | 
				
			||||||
 ../include/spinlock.h ../include/thread.h /usr/include/pthread.h \
 | 
					 | 
				
			||||||
 /usr/include/sched.h /usr/include/bits/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/setjmp.h ../include/buffer.h ../include/server.h \
 | 
					 | 
				
			||||||
 ../include/session.h ../include/service.h ../include/modules.h \
 | 
					 | 
				
			||||||
 ../include/router.h /usr/include/errno.h /usr/include/bits/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/linux/errno.h /usr/include/asm/errno.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
 | 
					 | 
				
			||||||
 ../include/gw.h /usr/include/ctype.h /usr/include/netdb.h \
 | 
					 | 
				
			||||||
 /usr/include/netinet/in.h /usr/include/stdint.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wchar.h /usr/include/sys/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/uio.h /usr/include/bits/uio.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/in.h /usr/include/rpc/netdb.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/netdb.h /usr/include/fcntl.h /usr/include/bits/fcntl.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stat.h /usr/include/unistd.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/syslog.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/syslog.h /usr/include/bits/syslog-path.h \
 | 
					 | 
				
			||||||
 /usr/include/pwd.h /usr/include/sys/epoll.h /usr/include/signal.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/signum.h /usr/include/bits/siginfo.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigaction.h /usr/include/bits/sigcontext.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigstack.h /usr/include/sys/ucontext.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigthread.h /usr/include/sys/ioctl.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/ioctls.h /usr/include/asm/ioctls.h \
 | 
					 | 
				
			||||||
 /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/ioctl.h /usr/include/asm-generic/ioctl.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h \
 | 
					 | 
				
			||||||
 /usr/include/arpa/inet.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdbool.h \
 | 
					 | 
				
			||||||
 ../include/gateway_mysql.h ../include/mysql_protocol.h ../include/dcb.h \
 | 
					 | 
				
			||||||
 ../include/poll.h ../include/atomic.h
 | 
					 | 
				
			||||||
load_utils.o: load_utils.c /usr/include/sys/param.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/limits.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/syslimits.h \
 | 
					 | 
				
			||||||
 /usr/include/limits.h /usr/include/features.h /usr/include/sys/cdefs.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs-64.h /usr/include/bits/posix1_lim.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/posix2_lim.h /usr/include/linux/param.h \
 | 
					 | 
				
			||||||
 /usr/include/asm/param.h /usr/include/asm-generic/param.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/types.h /usr/include/bits/types.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/typesizes.h /usr/include/time.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/endian.h /usr/include/bits/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/byteswap.h /usr/include/sys/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/select.h /usr/include/bits/sigset.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/pthreadtypes.h /usr/include/stdio.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/stdlib.h /usr/include/bits/waitflags.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitstatus.h /usr/include/alloca.h \
 | 
					 | 
				
			||||||
 /usr/include/unistd.h /usr/include/bits/posix_opt.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/environments.h /usr/include/bits/confname.h \
 | 
					 | 
				
			||||||
 /usr/include/getopt.h /usr/include/string.h /usr/include/xlocale.h \
 | 
					 | 
				
			||||||
 /usr/include/dlfcn.h /usr/include/bits/dlfcn.h ../include/modules.h \
 | 
					 | 
				
			||||||
 ../include/dcb.h ../include/spinlock.h ../include/thread.h \
 | 
					 | 
				
			||||||
 /usr/include/pthread.h /usr/include/sched.h /usr/include/bits/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/setjmp.h ../include/buffer.h
 | 
					 | 
				
			||||||
session.o: session.c /usr/include/stdio.h /usr/include/features.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/stdlib.h /usr/include/bits/waitflags.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitstatus.h /usr/include/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/select.h /usr/include/bits/sigset.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
 | 
					 | 
				
			||||||
 /usr/include/unistd.h /usr/include/bits/posix_opt.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/environments.h /usr/include/bits/confname.h \
 | 
					 | 
				
			||||||
 /usr/include/getopt.h /usr/include/string.h /usr/include/xlocale.h \
 | 
					 | 
				
			||||||
 ../include/session.h ../include/service.h ../include/spinlock.h \
 | 
					 | 
				
			||||||
 ../include/thread.h /usr/include/pthread.h /usr/include/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sched.h /usr/include/bits/setjmp.h ../include/dcb.h \
 | 
					 | 
				
			||||||
 ../include/buffer.h ../include/server.h ../include/router.h \
 | 
					 | 
				
			||||||
 ../include/atomic.h
 | 
					 | 
				
			||||||
service.o: service.c /usr/include/stdio.h /usr/include/features.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/stdlib.h /usr/include/bits/waitflags.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitstatus.h /usr/include/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/select.h /usr/include/bits/sigset.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/xlocale.h ../include/session.h \
 | 
					 | 
				
			||||||
 ../include/service.h ../include/spinlock.h ../include/thread.h \
 | 
					 | 
				
			||||||
 /usr/include/pthread.h /usr/include/sched.h /usr/include/bits/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/setjmp.h ../include/dcb.h ../include/buffer.h \
 | 
					 | 
				
			||||||
 ../include/server.h ../include/router.h ../include/modules.h \
 | 
					 | 
				
			||||||
 ../include/users.h ../include/hashtable.h ../include/atomic.h \
 | 
					 | 
				
			||||||
 ../include/dbusers.h ../include/poll.h
 | 
					 | 
				
			||||||
server.o: server.c /usr/include/stdio.h /usr/include/features.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/stdlib.h /usr/include/bits/waitflags.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitstatus.h /usr/include/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/select.h /usr/include/bits/sigset.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/xlocale.h ../include/session.h \
 | 
					 | 
				
			||||||
 ../include/server.h ../include/dcb.h ../include/spinlock.h \
 | 
					 | 
				
			||||||
 ../include/thread.h /usr/include/pthread.h /usr/include/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sched.h /usr/include/bits/setjmp.h ../include/buffer.h
 | 
					 | 
				
			||||||
poll.o: poll.c /usr/include/stdio.h /usr/include/features.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/xlocale.h /usr/include/unistd.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/confname.h /usr/include/getopt.h /usr/include/stdlib.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
 | 
					 | 
				
			||||||
 /usr/include/endian.h /usr/include/bits/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/byteswap.h /usr/include/sys/types.h \
 | 
					 | 
				
			||||||
 /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigset.h /usr/include/bits/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
 | 
					 | 
				
			||||||
 /usr/include/alloca.h /usr/include/sys/epoll.h /usr/include/stdint.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wchar.h ../include/poll.h ../include/dcb.h \
 | 
					 | 
				
			||||||
 ../include/spinlock.h ../include/thread.h /usr/include/pthread.h \
 | 
					 | 
				
			||||||
 /usr/include/sched.h /usr/include/bits/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/setjmp.h ../include/buffer.h ../include/atomic.h
 | 
					 | 
				
			||||||
config.o: config.c /usr/include/stdio.h /usr/include/features.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/xlocale.h /usr/include/stdlib.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
 | 
					 | 
				
			||||||
 /usr/include/endian.h /usr/include/bits/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/byteswap.h /usr/include/sys/types.h \
 | 
					 | 
				
			||||||
 /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sigset.h /usr/include/bits/time.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
 | 
					 | 
				
			||||||
 /usr/include/alloca.h ../inih/ini.h ../include/config.h \
 | 
					 | 
				
			||||||
 ../include/service.h ../include/spinlock.h ../include/thread.h \
 | 
					 | 
				
			||||||
 /usr/include/pthread.h /usr/include/sched.h /usr/include/bits/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/setjmp.h ../include/dcb.h ../include/buffer.h \
 | 
					 | 
				
			||||||
 ../include/server.h ../include/users.h ../include/hashtable.h \
 | 
					 | 
				
			||||||
 ../include/atomic.h
 | 
					 | 
				
			||||||
users.o: users.c /usr/include/stdio.h /usr/include/features.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/stdlib.h /usr/include/bits/waitflags.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitstatus.h /usr/include/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/select.h /usr/include/bits/sigset.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/xlocale.h ../include/users.h \
 | 
					 | 
				
			||||||
 ../include/hashtable.h ../include/spinlock.h ../include/thread.h \
 | 
					 | 
				
			||||||
 /usr/include/pthread.h /usr/include/sched.h /usr/include/bits/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/setjmp.h ../include/atomic.h ../include/dcb.h \
 | 
					 | 
				
			||||||
 ../include/buffer.h
 | 
					 | 
				
			||||||
hashtable.o: hashtable.c /usr/include/stdio.h /usr/include/features.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/stdlib.h /usr/include/bits/waitflags.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/waitstatus.h /usr/include/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/select.h /usr/include/bits/sigset.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
 | 
					 | 
				
			||||||
 /usr/include/string.h /usr/include/xlocale.h ../include/hashtable.h \
 | 
					 | 
				
			||||||
 ../include/spinlock.h ../include/thread.h /usr/include/pthread.h \
 | 
					 | 
				
			||||||
 /usr/include/sched.h /usr/include/bits/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/setjmp.h ../include/atomic.h ../include/dcb.h \
 | 
					 | 
				
			||||||
 ../include/buffer.h
 | 
					 | 
				
			||||||
dbusers.o: dbusers.c /usr/include/stdio.h /usr/include/features.h \
 | 
					 | 
				
			||||||
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
 | 
					 | 
				
			||||||
 /usr/include/mysql/mysql.h /usr/include/sys/types.h /usr/include/time.h \
 | 
					 | 
				
			||||||
 /usr/include/endian.h /usr/include/bits/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/byteswap.h /usr/include/sys/select.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/select.h /usr/include/bits/sigset.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/pthreadtypes.h /usr/include/mysql/mysql_version.h \
 | 
					 | 
				
			||||||
 /usr/include/mysql/mysql_com.h /usr/include/mysql/mysql_time.h \
 | 
					 | 
				
			||||||
 /usr/include/mysql/my_list.h /usr/include/mysql/typelib.h \
 | 
					 | 
				
			||||||
 /usr/include/mysql/my_alloc.h ../include/dcb.h ../include/spinlock.h \
 | 
					 | 
				
			||||||
 ../include/thread.h /usr/include/pthread.h /usr/include/sched.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/sched.h /usr/include/xlocale.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/setjmp.h ../include/buffer.h ../include/service.h \
 | 
					 | 
				
			||||||
 ../include/server.h ../include/users.h ../include/hashtable.h \
 | 
					 | 
				
			||||||
 ../include/atomic.h
 | 
					 | 
				
			||||||
thread.o: thread.c ../include/thread.h /usr/include/pthread.h \
 | 
					 | 
				
			||||||
 /usr/include/features.h /usr/include/sys/cdefs.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
 | 
					 | 
				
			||||||
 /usr/include/gnu/stubs-64.h /usr/include/endian.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
 | 
					 | 
				
			||||||
 /usr/include/sched.h /usr/include/bits/types.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/typesizes.h \
 | 
					 | 
				
			||||||
 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
 | 
					 | 
				
			||||||
 /usr/include/time.h /usr/include/bits/sched.h /usr/include/bits/time.h \
 | 
					 | 
				
			||||||
 /usr/include/xlocale.h /usr/include/bits/pthreadtypes.h \
 | 
					 | 
				
			||||||
 /usr/include/bits/setjmp.h
 | 
					 | 
				
			||||||
@ -87,7 +87,7 @@ int gw_read_gwbuff(DCB *dcb, GWBUF **head, int b) {
 | 
				
			|||||||
	int n = -1;
 | 
						int n = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (b <= 0) {
 | 
						if (b <= 0) {
 | 
				
			||||||
		fprintf(stderr, "||| read_gwbuff called with 0 bytes for %i, closing\n", dcb->fd);
 | 
							//fprintf(stderr, "||| read_gwbuff called with 0 bytes for %i, closing\n", dcb->fd);
 | 
				
			||||||
		dcb->func.close(dcb);
 | 
							dcb->func.close(dcb);
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -141,6 +141,7 @@ struct	epoll_event	events[MAX_EVENTS];
 | 
				
			|||||||
int			i, nfds;
 | 
					int			i, nfds;
 | 
				
			||||||
int			thread_id = (int)arg;
 | 
					int			thread_id = (int)arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Add this thread to the bitmask of running polling threads */
 | 
				
			||||||
	bitmask_set(&poll_mask, thread_id);
 | 
						bitmask_set(&poll_mask, thread_id);
 | 
				
			||||||
	while (1)
 | 
						while (1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -174,11 +175,15 @@ int			thread_id = (int)arg;
 | 
				
			|||||||
				{
 | 
									{
 | 
				
			||||||
					atomic_add(&pollStats.n_error, 1);
 | 
										atomic_add(&pollStats.n_error, 1);
 | 
				
			||||||
					dcb->func.error(dcb);
 | 
										dcb->func.error(dcb);
 | 
				
			||||||
 | 
										if (DCB_ISZOMBIE(dcb))
 | 
				
			||||||
 | 
											continue;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (ev & EPOLLHUP)
 | 
									if (ev & EPOLLHUP)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					atomic_add(&pollStats.n_hup, 1);
 | 
										atomic_add(&pollStats.n_hup, 1);
 | 
				
			||||||
					dcb->func.hangup(dcb);
 | 
										dcb->func.hangup(dcb);
 | 
				
			||||||
 | 
										if (DCB_ISZOMBIE(dcb))
 | 
				
			||||||
 | 
											continue;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (ev & EPOLLOUT)
 | 
									if (ev & EPOLLOUT)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
@ -203,6 +208,7 @@ int			thread_id = (int)arg;
 | 
				
			|||||||
		dcb_process_zombies(thread_id);
 | 
							dcb_process_zombies(thread_id);
 | 
				
			||||||
		if (shutdown)
 | 
							if (shutdown)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								/* Remove this thread from the bitmask of running polling threads */
 | 
				
			||||||
			bitmask_clear(&poll_mask, thread_id);
 | 
								bitmask_clear(&poll_mask, thread_id);
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -39,6 +39,9 @@ struct service;
 | 
				
			|||||||
 * 11/06/13	Mark Riddoch		Updated GWPROTOCOL structure with new
 | 
					 * 11/06/13	Mark Riddoch		Updated GWPROTOCOL structure with new
 | 
				
			||||||
 *					entry points
 | 
					 *					entry points
 | 
				
			||||||
 * 18/06/13	Mark Riddoch		Addition of the listener entry point
 | 
					 * 18/06/13	Mark Riddoch		Addition of the listener entry point
 | 
				
			||||||
 | 
					 * 02/06/2013	Massimiliano Pinto	Addition of delayqlock, delayq and authlock
 | 
				
			||||||
 | 
					 *					for handling backend asynchronous protocol connection
 | 
				
			||||||
 | 
					 *					and a generic lock for backend authentication
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @endverbatim
 | 
					 * @endverbatim
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -134,6 +137,7 @@ typedef struct dcb {
 | 
				
			|||||||
	GWBUF		*writeq;	/**< Write Data Queue */
 | 
						GWBUF		*writeq;	/**< Write Data Queue */
 | 
				
			||||||
	SPINLOCK	delayqlock;	/**< Delay Backend Write Queue spinlock */
 | 
						SPINLOCK	delayqlock;	/**< Delay Backend Write Queue spinlock */
 | 
				
			||||||
	GWBUF		*delayq;	/**< Delay Backend Write Data Queue */
 | 
						GWBUF		*delayq;	/**< Delay Backend Write Data Queue */
 | 
				
			||||||
 | 
						SPINLOCK	authlock;	/**< Generic Authorization spinlock */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DCBSTATS	stats;		/**< DCB related statistics */
 | 
						DCBSTATS	stats;		/**< DCB related statistics */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,6 +25,8 @@
 | 
				
			|||||||
 * 01-06-2013   Mark Riddoch            Initial implementation
 | 
					 * 01-06-2013   Mark Riddoch            Initial implementation
 | 
				
			||||||
 * 14-06-2013   Massimiliano Pinto      Added specific data
 | 
					 * 14-06-2013   Massimiliano Pinto      Added specific data
 | 
				
			||||||
 *                                      for MySQL session
 | 
					 *                                      for MySQL session
 | 
				
			||||||
 | 
					 * 04-07-2013	Massimiliano Pinto	Added new MySQL protocol status for asynchronous connection
 | 
				
			||||||
 | 
					 *					Added authentication reply status
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
@ -103,14 +105,19 @@ typedef struct mysql_session {
 | 
				
			|||||||
} MYSQL_session;
 | 
					} MYSQL_session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MySQL Protocol States */
 | 
					/* MySQL Protocol States */
 | 
				
			||||||
#define MYSQL_ALLOC             0       /* Allocate data */
 | 
					#define MYSQL_ALLOC		0	/* Allocate data */
 | 
				
			||||||
#define MYSQL_AUTH_SENT         1       /* Authentication handshake has been sent */
 | 
					#define MYSQL_PENDING_CONNECT	1	/* Backend socket pending connect */
 | 
				
			||||||
#define MYSQL_AUTH_RECV         2       /* Received user, password, db and capabilities */
 | 
					#define MYSQL_CONNECTED		2	/* Backend socket Connected */
 | 
				
			||||||
#define MYSQL_AUTH_FAILED       3       /* Auth failed, return error packet */
 | 
					#define MYSQL_AUTH_SENT		3	/* Authentication handshake has been sent */
 | 
				
			||||||
#define MYSQL_IDLE              4       /* Auth done. Protocol is idle, waiting for statements */
 | 
					#define MYSQL_AUTH_RECV		4	/* Received user, password, db and capabilities */
 | 
				
			||||||
#define MYSQL_ROUTING           5       /* The received command has been routed to backend(s) */
 | 
					#define MYSQL_AUTH_FAILED	5	/* Auth failed, return error packet */
 | 
				
			||||||
#define MYSQL_WAITING_RESULT    6       /* Waiting for result set */
 | 
					#define MYSQL_IDLE		6	/* Auth done. Protocol is idle, waiting for statements */
 | 
				
			||||||
#define MYSQL_CONNECTED   	7       /* Backend socket Connected */
 | 
					#define MYSQL_ROUTING		7	/* The received command has been routed to backend(s) */
 | 
				
			||||||
 | 
					#define MYSQL_WAITING_RESULT	8	/* Waiting for result set */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* MySQL states for authentication reply */
 | 
				
			||||||
 | 
					#define MYSQL_FAILED_AUTHENTICATION	1
 | 
				
			||||||
 | 
					#define MYSQL_SUCCESFUL_AUTHENTICATION	0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Protocol packing macros. */
 | 
					/* Protocol packing macros. */
 | 
				
			||||||
#define gw_mysql_set_byte2(__buffer, __int) do { \
 | 
					#define gw_mysql_set_byte2(__buffer, __int) do { \
 | 
				
			||||||
@ -210,6 +217,9 @@ int gw_receive_backend_auth(MySQLProtocol *conn);
 | 
				
			|||||||
int gw_decode_mysql_server_handshake(MySQLProtocol *conn, uint8_t *payload);
 | 
					int gw_decode_mysql_server_handshake(MySQLProtocol *conn, uint8_t *payload);
 | 
				
			||||||
int gw_read_backend_handshake(MySQLProtocol *conn);
 | 
					int gw_read_backend_handshake(MySQLProtocol *conn);
 | 
				
			||||||
int gw_send_authentication_to_backend(char *dbname, char *user, uint8_t *passwd, MySQLProtocol *conn);
 | 
					int gw_send_authentication_to_backend(char *dbname, char *user, uint8_t *passwd, MySQLProtocol *conn);
 | 
				
			||||||
 | 
					const char *gw_mysql_protocol_state2string(int state);
 | 
				
			||||||
 | 
					int gw_do_connect_to_backend(char *host, int port, MySQLProtocol *conn);
 | 
				
			||||||
 | 
					int mysql_send_custom_error (DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out);
 | 
					extern void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out);
 | 
				
			||||||
extern void gw_sha1_2_str(const uint8_t *in, int in_len, const uint8_t *in2, int in2_len, uint8_t *out);
 | 
					extern void gw_sha1_2_str(const uint8_t *in, int in_len, const uint8_t *in2, int in2_len, uint8_t *out);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										429
									
								
								modules/protocol/httpd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										429
									
								
								modules/protocol/httpd.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,429 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is distributed as part of the SkySQL Gateway.  It 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,
 | 
				
			||||||
 | 
					 * version 2.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program 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 General Public License for more
 | 
				
			||||||
 | 
					 * details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along with
 | 
				
			||||||
 | 
					 * this program; if not, write to the Free Software Foundation, Inc., 51
 | 
				
			||||||
 | 
					 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright SkySQL Ab 2013
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <dcb.h>
 | 
				
			||||||
 | 
					#include <buffer.h>
 | 
				
			||||||
 | 
					#include <service.h>
 | 
				
			||||||
 | 
					#include <session.h>
 | 
				
			||||||
 | 
					#include <sys/ioctl.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					#include <router.h>
 | 
				
			||||||
 | 
					#include <poll.h>
 | 
				
			||||||
 | 
					#include <atomic.h>
 | 
				
			||||||
 | 
					#include <gw.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file httpd.c - HTTP daemon protocol module
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The httpd protocol module is intended as a mechanism to allow connections
 | 
				
			||||||
 | 
					 * into the gateway for the purpose of accessing information within
 | 
				
			||||||
 | 
					 * the gateway with a REST interface
 | 
				
			||||||
 | 
					 * databases.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * In the first instance it is intended to allow a debug connection to access
 | 
				
			||||||
 | 
					 * internal data structures, however it may also be used to manage the 
 | 
				
			||||||
 | 
					 * configuration of the gateway via REST interface.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @verbatim
 | 
				
			||||||
 | 
					 * Revision History
 | 
				
			||||||
 | 
					 * Date		Who			Description
 | 
				
			||||||
 | 
					 * 08/07/2013	Massimiliano Pinto	Initial version
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @endverbatim
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ISspace(x) isspace((int)(x))
 | 
				
			||||||
 | 
					#define HTTP_SERVER_STRING "Gateway(c) v.1.0.0\r\n"
 | 
				
			||||||
 | 
					static char *version_str = "V1.0.0";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int httpd_read_event(DCB* dcb);
 | 
				
			||||||
 | 
					static int httpd_write_event(DCB *dcb);
 | 
				
			||||||
 | 
					static int httpd_write(DCB *dcb, GWBUF *queue);
 | 
				
			||||||
 | 
					static int httpd_error(DCB *dcb);
 | 
				
			||||||
 | 
					static int httpd_hangup(DCB *dcb);
 | 
				
			||||||
 | 
					static int httpd_accept(DCB *dcb);
 | 
				
			||||||
 | 
					static int httpd_close(DCB *dcb);
 | 
				
			||||||
 | 
					static int httpd_listen(DCB *dcb, char *config);
 | 
				
			||||||
 | 
					static int httpd_get_line(int sock, char *buf, int size);
 | 
				
			||||||
 | 
					static void httpd_send_headers(int client, const char *filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The "module object" for the httpd protocol module.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static GWPROTOCOL MyObject = { 
 | 
				
			||||||
 | 
						httpd_read_event,			/**< Read - EPOLLIN handler	 */
 | 
				
			||||||
 | 
						httpd_write,				/**< Write - data from gateway	 */
 | 
				
			||||||
 | 
						httpd_write_event,			/**< WriteReady - EPOLLOUT handler */
 | 
				
			||||||
 | 
						httpd_error,				/**< Error - EPOLLERR handler	 */
 | 
				
			||||||
 | 
						httpd_hangup,				/**< HangUp - EPOLLHUP handler	 */
 | 
				
			||||||
 | 
						httpd_accept,				/**< Accept			 */
 | 
				
			||||||
 | 
						NULL,					/**< Connect			 */
 | 
				
			||||||
 | 
						httpd_close,				/**< Close			 */
 | 
				
			||||||
 | 
						httpd_listen				/**< Create a listener		 */
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					httpd_command(DCB *, char *cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Implementation of the mandatory version entry point
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return version string of the module
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					char *
 | 
				
			||||||
 | 
					version()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return version_str;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The module initialisation routine, called when the module
 | 
				
			||||||
 | 
					 * is first loaded.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ModuleInit()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						fprintf(stderr, "Initialise HTTPD Protocol module.\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The module entry point routine. It is this routine that
 | 
				
			||||||
 | 
					 * must populate the structure that is referred to as the
 | 
				
			||||||
 | 
					 * "module object", this is a structure with the set of
 | 
				
			||||||
 | 
					 * external entry points for this module.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return The module object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					GWPROTOCOL *
 | 
				
			||||||
 | 
					GetModuleObject()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return &MyObject;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Read event for EPOLLIN on the httpd protocol module.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dcb	The descriptor control block
 | 
				
			||||||
 | 
					 * @return
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					httpd_read_event(DCB* dcb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					int		n = -1;
 | 
				
			||||||
 | 
					GWBUF		*head = NULL;
 | 
				
			||||||
 | 
					SESSION		*session = dcb->session;
 | 
				
			||||||
 | 
					ROUTER_OBJECT	*router = session->service->router;
 | 
				
			||||||
 | 
					ROUTER		*router_instance = session->service->router_instance;
 | 
				
			||||||
 | 
					void		*rsession = session->router_session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int numchars = 1;
 | 
				
			||||||
 | 
					char buf[1024];
 | 
				
			||||||
 | 
					char *query_string = NULL;
 | 
				
			||||||
 | 
					char *path_info = NULL;
 | 
				
			||||||
 | 
					char method[255];
 | 
				
			||||||
 | 
					char url[255];
 | 
				
			||||||
 | 
					char path[512];
 | 
				
			||||||
 | 
					int cgi = 0;
 | 
				
			||||||
 | 
					size_t i, j;
 | 
				
			||||||
 | 
					GWBUF *buffer=NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dcb->state = DCB_STATE_PROCESSING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						numchars = httpd_get_line(dcb->fd, buf, sizeof(buf));
 | 
				
			||||||
 | 
						i = 0; j = 0;
 | 
				
			||||||
 | 
						while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) {
 | 
				
			||||||
 | 
							method[i] = buf[j];
 | 
				
			||||||
 | 
							i++; j++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						method[i] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) {
 | 
				
			||||||
 | 
							//httpd_unimplemented(dcb->fd);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((buffer = gwbuf_alloc(1024)) == NULL) {
 | 
				
			||||||
 | 
							//httpd_error(dcb->fd);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (strcasecmp(method, "POST") == 0)
 | 
				
			||||||
 | 
							cgi = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						i = 0;
 | 
				
			||||||
 | 
						while (ISspace(buf[j]) && (j < sizeof(buf)))
 | 
				
			||||||
 | 
							j++;
 | 
				
			||||||
 | 
						while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) {
 | 
				
			||||||
 | 
							url[i] = buf[j];
 | 
				
			||||||
 | 
							i++; j++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						url[i] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (strcasecmp(method, "GET") == 0) {
 | 
				
			||||||
 | 
							query_string = url;
 | 
				
			||||||
 | 
							while ((*query_string != '?') && (*query_string != '\0'))
 | 
				
			||||||
 | 
								query_string++;
 | 
				
			||||||
 | 
							if (*query_string == '?') {
 | 
				
			||||||
 | 
								cgi = 1;
 | 
				
			||||||
 | 
								*query_string = '\0';
 | 
				
			||||||
 | 
								query_string++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */
 | 
				
			||||||
 | 
							numchars = httpd_get_line(dcb->fd, buf, sizeof(buf));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						httpd_send_headers(dcb->fd, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strcpy(GWBUF_DATA(buffer), "Welcome to HTTPD Gateway (c)\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dcb->func.write(dcb, buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dcb_close(dcb);	
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dcb->state = DCB_STATE_POLLING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return n;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * EPOLLOUT handler for the HTTPD protocol module.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dcb	The descriptor control block
 | 
				
			||||||
 | 
					 * @return
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					httpd_write_event(DCB *dcb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return dcb_drain_writeq(dcb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Write routine for the HTTPD protocol module.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Writes the content of the buffer queue to the socket
 | 
				
			||||||
 | 
					 * observing the non-blocking principles of the gateway.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dcb	Descriptor Control Block for the socket
 | 
				
			||||||
 | 
					 * @param queue	Linked list of buffes to write
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					httpd_write(DCB *dcb, GWBUF *queue)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return dcb_write(dcb, queue);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Handler for the EPOLLERR event.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dcb	The descriptor control block
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					httpd_error(DCB *dcb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Handler for the EPOLLHUP event.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dcb	The descriptor control block
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					httpd_hangup(DCB *dcb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Handler for the EPOLLIN event when the DCB refers to the listening
 | 
				
			||||||
 | 
					 * socket for the protocol.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dcb	The descriptor control block
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					httpd_accept(DCB *dcb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					int	n_connect = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int			so;
 | 
				
			||||||
 | 
							struct sockaddr_in	addr;
 | 
				
			||||||
 | 
							socklen_t		addrlen;
 | 
				
			||||||
 | 
							DCB			*client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ((so = accept(dcb->fd, (struct sockaddr *)&addr, &addrlen)) == -1)
 | 
				
			||||||
 | 
								return n_connect;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								atomic_add(&dcb->stats.n_accepts, 1);
 | 
				
			||||||
 | 
								client = dcb_alloc();
 | 
				
			||||||
 | 
								client->fd = so;
 | 
				
			||||||
 | 
								client->remote = strdup(inet_ntoa(addr.sin_addr));
 | 
				
			||||||
 | 
								memcpy(&client->func, &MyObject, sizeof(GWPROTOCOL));
 | 
				
			||||||
 | 
								client->session = session_alloc(dcb->session->service, client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								client->state = DCB_STATE_IDLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (poll_add_dcb(client) == -1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									return n_connect;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								n_connect++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								client->state = DCB_STATE_POLLING;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return n_connect;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The close handler for the descriptor. Called by the gateway to
 | 
				
			||||||
 | 
					 * explicitly close a connection.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dcb	The descriptor control block
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					httpd_close(DCB *dcb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						dcb_close(dcb);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * HTTTP daemon listener entry point
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param	listener	The Listener DCB
 | 
				
			||||||
 | 
					 * @param	config		Configuration (ip:port)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					httpd_listen(DCB *listener, char *config)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					struct sockaddr_in	addr;
 | 
				
			||||||
 | 
					char			*port;
 | 
				
			||||||
 | 
					int			one = 1;
 | 
				
			||||||
 | 
					short			pnum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(&listener->func, &MyObject, sizeof(GWPROTOCOL));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						port = strrchr(config, ':');
 | 
				
			||||||
 | 
						if (port)
 | 
				
			||||||
 | 
							port++;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							port = "6442";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						addr.sin_family = AF_INET;
 | 
				
			||||||
 | 
						addr.sin_addr.s_addr = htonl(INADDR_ANY);
 | 
				
			||||||
 | 
						pnum = atoi(port);
 | 
				
			||||||
 | 
						addr.sin_port = htons(pnum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((listener->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* socket options */
 | 
				
			||||||
 | 
						setsockopt(listener->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* set NONBLOCKING mode */
 | 
				
			||||||
 | 
					        setnonblocking(listener->fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* bind address and port */
 | 
				
			||||||
 | 
					        if (bind(listener->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
					        	return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						listener->state = DCB_STATE_LISTENING; 
 | 
				
			||||||
 | 
						listen(listener->fd, SOMAXCONN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (poll_add_dcb(listener) == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * HTTPD command implementation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Called for each command in the HTTP stream.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Currently we do no command execution
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param	dcb	The client DCB
 | 
				
			||||||
 | 
					 * @param	cmd	The command stream
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					httpd_command(DCB *dcb, char *cmd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int httpd_get_line(int sock, char *buf, int size) {
 | 
				
			||||||
 | 
					 int i = 0;
 | 
				
			||||||
 | 
					 char c = '\0';
 | 
				
			||||||
 | 
					 int n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 while ((i < size - 1) && (c != '\n'))
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					  n = recv(sock, &c, 1, 0);
 | 
				
			||||||
 | 
					  /* DEBUG printf("%02X\n", c); */
 | 
				
			||||||
 | 
					  if (n > 0)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					   if (c == '\r')
 | 
				
			||||||
 | 
					   {
 | 
				
			||||||
 | 
					    n = recv(sock, &c, 1, MSG_PEEK);
 | 
				
			||||||
 | 
					    /* DEBUG printf("%02X\n", c); */
 | 
				
			||||||
 | 
					    if ((n > 0) && (c == '\n'))
 | 
				
			||||||
 | 
					     recv(sock, &c, 1, 0);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					     c = '\n';
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					   buf[i] = c;
 | 
				
			||||||
 | 
					   i++;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					   c = '\n';
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 buf[i] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 return(i);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void httpd_send_headers(int client, const char *filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					 char buf[1024];
 | 
				
			||||||
 | 
					 (void)filename;  /* could use filename to determine file type */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 strcpy(buf, "HTTP/1.0 200 OK\r\n");
 | 
				
			||||||
 | 
					 send(client, buf, strlen(buf), 0);
 | 
				
			||||||
 | 
					 strcpy(buf, HTTP_SERVER_STRING);
 | 
				
			||||||
 | 
					 send(client, buf, strlen(buf), 0);
 | 
				
			||||||
 | 
					 sprintf(buf, "Content-Type: text/html\r\n");
 | 
				
			||||||
 | 
					 send(client, buf, strlen(buf), 0);
 | 
				
			||||||
 | 
					 strcpy(buf, "\r\n");
 | 
				
			||||||
 | 
					 send(client, buf, strlen(buf), 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
@ -34,10 +34,11 @@
 | 
				
			|||||||
 *                          and necessary headers.
 | 
					 *                          and necessary headers.
 | 
				
			||||||
 * 01/07/2013	Massimiliano Pinto	Put Log Manager example code behind SS_DEBUG macros.
 | 
					 * 01/07/2013	Massimiliano Pinto	Put Log Manager example code behind SS_DEBUG macros.
 | 
				
			||||||
 * 03/07/2013	Massimiliano Pinto	Added delayq for incoming data before mysql connection
 | 
					 * 03/07/2013	Massimiliano Pinto	Added delayq for incoming data before mysql connection
 | 
				
			||||||
 | 
					 * 04/07/2013	Massimiliano Pinto	Added asyncrhronous MySQL protocol connection to backend
 | 
				
			||||||
 | 
					 * 05/07/2013	Massimiliano Pinto	Added closeSession if backend auth fails
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *version_str = "V1.0.0";
 | 
					static char *version_str = "V2.0.0";
 | 
				
			||||||
extern char *gw_strend(register const char *s);
 | 
					 | 
				
			||||||
int gw_mysql_connect(char *host, int port, char *dbname, char *user, uint8_t *passwd, MySQLProtocol *conn);
 | 
					int gw_mysql_connect(char *host, int port, char *dbname, char *user, uint8_t *passwd, MySQLProtocol *conn);
 | 
				
			||||||
static int gw_create_backend_connection(DCB *client_dcb, SERVER *server, SESSION *in_session);
 | 
					static int gw_create_backend_connection(DCB *client_dcb, SERVER *server, SESSION *in_session);
 | 
				
			||||||
static int gw_read_backend_event(DCB* dcb);
 | 
					static int gw_read_backend_event(DCB* dcb);
 | 
				
			||||||
@ -45,15 +46,18 @@ static int gw_write_backend_event(DCB *dcb);
 | 
				
			|||||||
static int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue);
 | 
					static int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue);
 | 
				
			||||||
static int gw_error_backend_event(DCB *dcb);
 | 
					static int gw_error_backend_event(DCB *dcb);
 | 
				
			||||||
static int gw_backend_close(DCB *dcb);
 | 
					static int gw_backend_close(DCB *dcb);
 | 
				
			||||||
 | 
					static int gw_backend_hangup(DCB *dcb);
 | 
				
			||||||
static int backend_write_delayqueue(DCB *dcb);
 | 
					static int backend_write_delayqueue(DCB *dcb);
 | 
				
			||||||
static void backend_set_delayqueue(DCB *dcb, GWBUF *queue);
 | 
					static void backend_set_delayqueue(DCB *dcb, GWBUF *queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern char *gw_strend(register const char *s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static GWPROTOCOL MyObject = { 
 | 
					static GWPROTOCOL MyObject = { 
 | 
				
			||||||
	gw_read_backend_event,			/* Read - EPOLLIN handler	 */
 | 
						gw_read_backend_event,			/* Read - EPOLLIN handler	 */
 | 
				
			||||||
	gw_MySQLWrite_backend,			/* Write - data from gateway	 */
 | 
						gw_MySQLWrite_backend,			/* Write - data from gateway	 */
 | 
				
			||||||
	gw_write_backend_event,			/* WriteReady - EPOLLOUT handler */
 | 
						gw_write_backend_event,			/* WriteReady - EPOLLOUT handler */
 | 
				
			||||||
	gw_error_backend_event,			/* Error - EPOLLERR handler	 */
 | 
						gw_error_backend_event,			/* Error - EPOLLERR handler	 */
 | 
				
			||||||
	NULL,					/* HangUp - EPOLLHUP handler	 */
 | 
						gw_backend_hangup,			/* HangUp - EPOLLHUP handler	 */
 | 
				
			||||||
	NULL,					/* Accept			 */
 | 
						NULL,					/* Accept			 */
 | 
				
			||||||
	gw_create_backend_connection,		/* Connect			 */
 | 
						gw_create_backend_connection,		/* Connect			 */
 | 
				
			||||||
	gw_backend_close,			/* Close			 */
 | 
						gw_backend_close,			/* Close			 */
 | 
				
			||||||
@ -101,58 +105,106 @@ GetModuleObject()
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//////////////////////////////////////////
 | 
					/**
 | 
				
			||||||
//backend read event triggered by EPOLLIN
 | 
					 * Backend Read Event for EPOLLIN on the MySQL backend protocol module
 | 
				
			||||||
//////////////////////////////////////////
 | 
					 * @param dcb   The backend Descriptor Control Block
 | 
				
			||||||
 | 
					 * @return 1 on operation, 0 for no action
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
static int gw_read_backend_event(DCB *dcb) {
 | 
					static int gw_read_backend_event(DCB *dcb) {
 | 
				
			||||||
	int n;
 | 
					 | 
				
			||||||
	MySQLProtocol *client_protocol = NULL;
 | 
						MySQLProtocol *client_protocol = NULL;
 | 
				
			||||||
 | 
						MySQLProtocol *backend_protocol = NULL;
 | 
				
			||||||
 | 
						MYSQL_session *current_session = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dcb)
 | 
						if(dcb->session) {
 | 
				
			||||||
		if(dcb->session)
 | 
							client_protocol = SESSION_PROTOCOL(dcb->session, MySQLProtocol);
 | 
				
			||||||
			client_protocol = SESSION_PROTOCOL(dcb->session, MySQLProtocol);
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef GW_DEBUG_READ_EVENT
 | 
						backend_protocol = (MySQLProtocol *) dcb->protocol;
 | 
				
			||||||
	fprintf(stderr, "Backend ready! Read from Backend %i, write to client %i, client state %i\n", dcb->fd, dcb->session->client->fd, client_protocol->state);
 | 
						current_session = (MYSQL_session *)dcb->session->data;
 | 
				
			||||||
#endif
 | 
					
 | 
				
			||||||
 | 
						//fprintf(stderr, ">>> backend EPOLLIN from %i, protocol state [%s]\n", dcb->fd, gw_mysql_protocol_state2string(backend_protocol->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* backend is connected:
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * 1. read server handshake
 | 
				
			||||||
 | 
						 * 2. and write auth request
 | 
				
			||||||
 | 
						 * 3.  and return
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (backend_protocol->state == MYSQL_CONNECTED) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							gw_read_backend_handshake(backend_protocol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							gw_send_authentication_to_backend(current_session->db, current_session->user, current_session->client_sha1, backend_protocol);
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* ready to check the authentication reply from backend */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (backend_protocol->state == MYSQL_AUTH_RECV) {
 | 
				
			||||||
 | 
						        ROUTER_OBJECT   *router = NULL;
 | 
				
			||||||
 | 
					       		ROUTER          *router_instance = NULL;
 | 
				
			||||||
 | 
					       		void            *rsession = NULL;
 | 
				
			||||||
 | 
							int rv = -1;
 | 
				
			||||||
 | 
							SESSION *session = dcb->session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (session) {
 | 
				
			||||||
 | 
					                         router = session->service->router;
 | 
				
			||||||
 | 
					                         router_instance = session->service->router_instance;
 | 
				
			||||||
 | 
					                         rsession = session->router_session;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* read backed auth reply */
 | 
				
			||||||
 | 
							rv = gw_receive_backend_auth(backend_protocol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch (rv) {
 | 
				
			||||||
 | 
								case MYSQL_FAILED_AUTHENTICATION:
 | 
				
			||||||
 | 
									fprintf(stderr, ">>>> Backend Auth failed for user [%s], fd %i\n", current_session->user, dcb->fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									backend_protocol->state = MYSQL_AUTH_FAILED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/* send an error to the client */
 | 
				
			||||||
 | 
									mysql_send_custom_error(dcb->session->client, 1, 0, "Connection to backend lost right now");
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
									/* close the active session */		
 | 
				
			||||||
 | 
									router->closeSession(router_instance, rsession);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/* force the router_session to NULL
 | 
				
			||||||
 | 
									 * Later we will implement a proper status for the session
 | 
				
			||||||
 | 
									 */
 | 
				
			||||||
 | 
									session->router_session = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case MYSQL_SUCCESFUL_AUTHENTICATION:
 | 
				
			||||||
 | 
									spinlock_acquire(&dcb->authlock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									backend_protocol->state = MYSQL_IDLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/* check the delay queue and flush the data */
 | 
				
			||||||
 | 
									if(dcb->delayq) {
 | 
				
			||||||
 | 
										backend_write_delayqueue(dcb);
 | 
				
			||||||
 | 
										spinlock_release(&dcb->authlock);
 | 
				
			||||||
 | 
										return 1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									spinlock_release(&dcb->authlock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									/* no other authentication state here right now, so just return */
 | 
				
			||||||
 | 
									return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* reading MySQL command output from backend and writing to the client */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((client_protocol->state == MYSQL_WAITING_RESULT) || (client_protocol->state == MYSQL_IDLE)) {
 | 
						if ((client_protocol->state == MYSQL_WAITING_RESULT) || (client_protocol->state == MYSQL_IDLE)) {
 | 
				
			||||||
		int b = -1;
 | 
							GWBUF   *head = NULL;
 | 
				
			||||||
		GWBUF	*buffer, *head;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (ioctl(dcb->fd, FIONREAD, &b)) {
 | 
							/* read available backend data */
 | 
				
			||||||
			fprintf(stderr, "Backend Ioctl FIONREAD error %i, %s\n", errno , strerror(errno));
 | 
							dcb_read(dcb, &head);
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			//fprintf(stderr, "Backend IOCTL FIONREAD bytes to read = %i\n", b);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/* and write the gwbuffer to client */
 | 
				
			||||||
		 * Read all the data that is available into a chain of buffers
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		head = NULL;
 | 
					 | 
				
			||||||
		while (b > 0)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			int bufsize = b < MAX_BUFFER_SIZE ? b : MAX_BUFFER_SIZE;
 | 
					 | 
				
			||||||
			if ((buffer = gwbuf_alloc(bufsize)) == NULL)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				/* Bad news, we have run out of memory */
 | 
					 | 
				
			||||||
				return 0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			GW_NOINTR_CALL(n = read(dcb->fd, GWBUF_DATA(buffer), bufsize); dcb->stats.n_reads++);
 | 
					 | 
				
			||||||
			if (n < 0)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// if eerno == EAGAIN || EWOULDBLOCK is missing
 | 
					 | 
				
			||||||
				// do the right task, not just break
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			head = gwbuf_append(head, buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// how many bytes left
 | 
					 | 
				
			||||||
			b -= n;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// write the gwbuffer to client
 | 
					 | 
				
			||||||
		dcb->session->client->func.write(dcb->session->client, head);
 | 
							dcb->session->client->func.write(dcb->session->client, head);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
@ -168,6 +220,22 @@ static int gw_read_backend_event(DCB *dcb) {
 | 
				
			|||||||
 * @return      The number of bytes written
 | 
					 * @return      The number of bytes written
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int gw_write_backend_event(DCB *dcb) {
 | 
					static int gw_write_backend_event(DCB *dcb) {
 | 
				
			||||||
 | 
						MySQLProtocol *backend_protocol = dcb->protocol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//fprintf(stderr, ">>> backend EPOLLOUT %i, protocol state [%s]\n", backend_protocol->fd, gw_mysql_protocol_state2string(backend_protocol->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// spinlock_acquire(&dcb->connectlock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (backend_protocol->state == MYSQL_PENDING_CONNECT) {
 | 
				
			||||||
 | 
							backend_protocol->state = MYSQL_CONNECTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// spinlock_release(&dcb->connectlock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// spinlock_release(&dcb->connectlock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return dcb_drain_writeq(dcb);
 | 
					        return dcb_drain_writeq(dcb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -181,87 +249,123 @@ static int gw_write_backend_event(DCB *dcb) {
 | 
				
			|||||||
static int
 | 
					static int
 | 
				
			||||||
gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
 | 
					gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						MySQLProtocol *backend_protocol = dcb->protocol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spinlock_acquire(&dcb->authlock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Now put the incoming data to the delay queue unless backend is connected with auth ok
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (backend_protocol->state != MYSQL_IDLE) {
 | 
				
			||||||
 | 
							//fprintf(stderr, ">>> Writing in the backend %i delay queue\n", dcb->fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							backend_set_delayqueue(dcb, queue);
 | 
				
			||||||
 | 
							spinlock_release(&dcb->authlock);
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spinlock_release(&dcb->authlock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return dcb_write(dcb, queue);
 | 
						return dcb_write(dcb, queue);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Backend Error Handling
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
static int gw_error_backend_event(DCB *dcb) {
 | 
					static int gw_error_backend_event(DCB *dcb) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fprintf(stderr, "#### Handle Backend error function for %i\n", dcb->fd);
 | 
					        fprintf(stderr, ">>> Handle Backend error function for %i\n", dcb->fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (dcb->state != DCB_STATE_LISTENING) {
 | 
						dcb_close(dcb);
 | 
				
			||||||
                if (poll_remove_dcb(dcb) == -1) {
 | 
					 | 
				
			||||||
                                fprintf(stderr, "Backend poll_remove_dcb: from events check failed to delete %i, [%i]:[%s]\n", dcb->fd, errno, strerror(errno));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef GW_EVENT_DEBUG
 | 
					 | 
				
			||||||
                fprintf(stderr, "Backend closing fd [%i]=%i, from events check\n", dcb->fd, protocol->fd);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
                if (dcb->fd) {
 | 
					 | 
				
			||||||
                        dcb->state = DCB_STATE_DISCONNECTED;
 | 
					 | 
				
			||||||
                        fprintf(stderr, "Freeing backend MySQL conn %p, %p\n", dcb->protocol, &dcb->protocol);
 | 
					 | 
				
			||||||
                        gw_mysql_close((MySQLProtocol **)&dcb->protocol);
 | 
					 | 
				
			||||||
                        fprintf(stderr, "Freeing backend MySQL conn %p, %p\n", dcb->protocol, &dcb->protocol);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Create a new MySQL backend connection.
 | 
					 * Create a new backend connection.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This routine performs the MySQL connection to the backend and fills the session->backends of the callier dcb
 | 
					 * This routine will connect to a backend server and it is called by dbc_connect in router->newSession
 | 
				
			||||||
 * with the new allocatetd dcb and adds the new socket to the poll set
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * - backend dcb allocation
 | 
					 * @param backend The Backend DCB allocated from dcb_connect
 | 
				
			||||||
 * - MySQL session data fetch
 | 
					 * @param server  The selected server to connect to
 | 
				
			||||||
 * - backend connection using data in MySQL session
 | 
					 * @param session The current session from Client DCB
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param client_dcb The client DCB struct
 | 
					 | 
				
			||||||
 * @return 0 on Success or 1 on Failure.
 | 
					 * @return 0 on Success or 1 on Failure.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int gw_create_backend_connection(DCB *backend, SERVER *server, SESSION *session) {
 | 
					static int gw_create_backend_connection(DCB *backend, SERVER *server, SESSION *session) {
 | 
				
			||||||
	MySQLProtocol *ptr_proto = NULL;
 | 
						MySQLProtocol *protocol = NULL;
 | 
				
			||||||
	MYSQL_session *s_data = NULL;
 | 
						MYSQL_session *s_data = NULL;
 | 
				
			||||||
 | 
						int rv = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fprintf(stderr, "HERE, the server to connect is [%s]:[%i]\n", server->name, server->port);
 | 
						//fprintf(stderr, "HERE, the server to connect is [%s]:[%i]\n", server->name, server->port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	backend->protocol = (MySQLProtocol *) calloc(1, sizeof(MySQLProtocol));
 | 
						protocol = (MySQLProtocol *) calloc(1, sizeof(MySQLProtocol));
 | 
				
			||||||
 | 
						protocol->state = MYSQL_ALLOC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						backend->protocol = protocol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* put the backend dcb in the protocol struct */
 | 
				
			||||||
 | 
						protocol->descriptor = backend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ptr_proto = (MySQLProtocol *)backend->protocol;
 | 
					 | 
				
			||||||
	s_data = (MYSQL_session *)session->client->data;
 | 
						s_data = (MYSQL_session *)session->client->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//	fprintf(stderr, "HERE before connect, s_data is [%p]\n", s_data);
 | 
						/**
 | 
				
			||||||
//	fprintf(stderr, "HERE before connect, username is [%s]\n", s_data->user);
 | 
						 * let's try to connect to a backend server, only connect sys call
 | 
				
			||||||
 | 
						 * The socket descriptor is in Non Blocking status, this is set in the function
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						rv = gw_do_connect_to_backend(server->name, server->port, protocol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// this is blocking until auth done
 | 
						// we could also move later, this in to the gw_do_connect_to_backend using protocol->descriptor
 | 
				
			||||||
	if (gw_mysql_connect(server->name, server->port, s_data->db, s_data->user, s_data->client_sha1, backend->protocol) == 0) {
 | 
					 | 
				
			||||||
		memcpy(&backend->fd,  &ptr_proto->fd, sizeof(backend->fd));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		setnonblocking(backend->fd);
 | 
						memcpy(&backend->fd,  &protocol->fd, sizeof(backend->fd));
 | 
				
			||||||
		fprintf(stderr, "Connected to backend mysql server. fd is %i\n", backend->fd);
 | 
					
 | 
				
			||||||
	} else {
 | 
						switch (rv) {
 | 
				
			||||||
		fprintf(stderr, "<<<< NOT Connected to backend mysql server!!!\n");
 | 
					
 | 
				
			||||||
		backend->fd = -1;
 | 
							case 0:
 | 
				
			||||||
		return -1;
 | 
								//fprintf(stderr, "Connected to backend mysql server: fd is %i\n", backend->fd);
 | 
				
			||||||
 | 
								protocol->state = MYSQL_CONNECTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case 1:
 | 
				
			||||||
 | 
								//fprintf(stderr, ">>> Connection is PENDING to backend mysql server: fd is %i\n", backend->fd);
 | 
				
			||||||
 | 
								protocol->state = MYSQL_PENDING_CONNECT;	
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								fprintf(stderr, ">>> ERROR: NOT Connected to the backend mysql server!!!\n");
 | 
				
			||||||
 | 
								backend->fd = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// if connected, it will be addeed to the epoll from the caller of connect()
 | 
						fprintf(stderr, ">>> Backend [%s:%i] added [%i], in the client session [%i]\n", server->name, server->port, backend->fd, session->client->fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (backend->fd <= 0) {
 | 
						backend->state = DCB_STATE_POLLING;
 | 
				
			||||||
		perror("ERROR: epoll_ctl: backend sock");
 | 
					 | 
				
			||||||
		backend->fd = -1;
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		fprintf(stderr, "--> Backend conn added, bk_fd [%i], scramble [%s], is session with client_fd [%i]\n", backend->fd, ptr_proto->scramble, session->client->fd);
 | 
					 | 
				
			||||||
		backend->state = DCB_STATE_POLLING;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return backend->fd;
 | 
						return backend->fd;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return -1;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Hangup routine the backend dcb: it does nothing right now
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dcb The current Backend DCB
 | 
				
			||||||
 | 
					 * @return 1 always
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					gw_backend_hangup(DCB *dcb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Close the backend dcb
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dcb The current Backend DCB
 | 
				
			||||||
 | 
					 * @return 1 always
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
gw_backend_close(DCB *dcb)
 | 
					gw_backend_close(DCB *dcb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -269,444 +373,6 @@ gw_backend_close(DCB *dcb)
 | 
				
			|||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Create a new MySQL connection.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This routine performs the full MySQL connection to the specified server.
 | 
					 | 
				
			||||||
 * It does 
 | 
					 | 
				
			||||||
 * - socket init
 | 
					 | 
				
			||||||
 * - socket connect
 | 
					 | 
				
			||||||
 * - server handshake parsing
 | 
					 | 
				
			||||||
 * - authenticatio reply
 | 
					 | 
				
			||||||
 * - the Auth ack receive
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * Please note, all socket operation are in blocking state
 | 
					 | 
				
			||||||
 * Status: work in progress.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param host The TCP/IP host address to connect to
 | 
					 | 
				
			||||||
 * @param port The TCP/IP host port to connect to
 | 
					 | 
				
			||||||
 * @param dbname The optional database name. Use NULL if not interested in
 | 
					 | 
				
			||||||
 * @param user The MySQL database Username: required
 | 
					 | 
				
			||||||
 * @param passwd The MySQL database Password: required
 | 
					 | 
				
			||||||
 * @param conn The MySQLProtocol structure to be filled: must be preallocated with gw_mysql_init()
 | 
					 | 
				
			||||||
 * @return 0 on Success or 1 on Failure.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int gw_mysql_connect(char *host, int port, char *dbname, char *user, uint8_t *passwd, MySQLProtocol *conn) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        struct sockaddr_in serv_addr;
 | 
					 | 
				
			||||||
	int compress = 0;
 | 
					 | 
				
			||||||
	int rv;
 | 
					 | 
				
			||||||
	int so = 0;
 | 
					 | 
				
			||||||
	int ciclo = 0;
 | 
					 | 
				
			||||||
	uint8_t buffer[SMALL_CHUNK];
 | 
					 | 
				
			||||||
	uint8_t packet_buffer[SMALL_CHUNK];
 | 
					 | 
				
			||||||
	uint8_t *payload = NULL;
 | 
					 | 
				
			||||||
	int server_protocol;
 | 
					 | 
				
			||||||
	uint8_t *server_version_end = NULL;
 | 
					 | 
				
			||||||
	uint16_t mysql_server_capabilities_one;
 | 
					 | 
				
			||||||
	uint16_t mysql_server_capabilities_two;
 | 
					 | 
				
			||||||
	unsigned long tid =0;
 | 
					 | 
				
			||||||
	long bytes;
 | 
					 | 
				
			||||||
	uint8_t scramble_data_1[8 + 1] = "";
 | 
					 | 
				
			||||||
	uint8_t scramble_data_2[12 + 1] = "";
 | 
					 | 
				
			||||||
	uint8_t capab_ptr[4];
 | 
					 | 
				
			||||||
	int scramble_len;
 | 
					 | 
				
			||||||
	uint8_t scramble[GW_MYSQL_SCRAMBLE_SIZE + 1];
 | 
					 | 
				
			||||||
	uint8_t client_scramble[GW_MYSQL_SCRAMBLE_SIZE + 1];
 | 
					 | 
				
			||||||
	uint8_t client_capabilities[4];
 | 
					 | 
				
			||||||
	uint32_t server_capabilities;
 | 
					 | 
				
			||||||
	uint32_t final_capabilities;
 | 
					 | 
				
			||||||
	char dbpass[129]="";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	char *curr_db = NULL;
 | 
					 | 
				
			||||||
	uint8_t *curr_passwd = NULL;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	if (strlen(dbname))
 | 
					 | 
				
			||||||
		curr_db = dbname;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (strlen((char *)passwd))
 | 
					 | 
				
			||||||
		curr_passwd = passwd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	conn->state = MYSQL_ALLOC;
 | 
					 | 
				
			||||||
	conn->fd = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(&server_capabilities, '\0', sizeof(server_capabilities));
 | 
					 | 
				
			||||||
	memset(&final_capabilities, '\0', sizeof(final_capabilities));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	//fprintf(stderr, ")))) Connect to MySQL: user[%s], SHA1(passwd)[%s], db [%s]\n", user, passwd, dbname);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        memset(&serv_addr, 0, sizeof serv_addr);
 | 
					 | 
				
			||||||
        serv_addr.sin_family = AF_INET;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	so = socket(AF_INET,SOCK_STREAM,0);
 | 
					 | 
				
			||||||
	if (so < 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "Errore creazione socket: [%s] %i\n", strerror(errno), errno);
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	conn->fd = so;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	setipaddress(&serv_addr.sin_addr, host);
 | 
					 | 
				
			||||||
	serv_addr.sin_port = htons(port);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Socket initialized\n");
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while(1) {
 | 
					 | 
				
			||||||
		if ((rv = connect(so, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) < 0) {
 | 
					 | 
				
			||||||
			fprintf(stderr, "Errore connect %i, %s: RV = [%i]\n", errno, strerror(errno), rv);
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			if (errno == EINPROGRESS) {
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				close(so);
 | 
					 | 
				
			||||||
				return -1;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "CONNECT is DONE\n");
 | 
					 | 
				
			||||||
	fprintf(stderr, "Socket FD is %i\n", so);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(&buffer, '\0', sizeof(buffer));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bytes = SMALL_CHUNK;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rv = read(so, buffer, bytes);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ( rv >0 ) {
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
		fprintf(stderr, "RESPONSE ciclo %i HO letto [%s] bytes %li\n",ciclo, buffer, bytes);
 | 
					 | 
				
			||||||
		fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		ciclo++;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if (rv == 0 && errno == EOF) {
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
			fprintf(stderr, "EOF reached. Bytes = %li\n", bytes);
 | 
					 | 
				
			||||||
			fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
			fprintf(stderr, "###### Receive error FINAL : connection not completed %i %s:  RV = [%i]\n", errno, strerror(errno), rv);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
			close(so);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return -1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fwrite(buffer, bytes, 1, stderr);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	//decode mysql handshake
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	payload = buffer + 4;
 | 
					 | 
				
			||||||
	server_protocol= payload[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Server Protocol [%i]\n", server_protocol);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	payload++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Protocol Version [%s]\n", payload);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	server_version_end = (uint8_t *) gw_strend((char*) payload);
 | 
					 | 
				
			||||||
	payload = server_version_end + 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TID
 | 
					 | 
				
			||||||
	tid = gw_mysql_get_byte4(payload);
 | 
					 | 
				
			||||||
	memcpy(&conn->tid, &tid, 4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Thread ID is %lu\n", conn->tid);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	payload +=4;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// scramble_part 1
 | 
					 | 
				
			||||||
	memcpy(scramble_data_1, payload, 8);
 | 
					 | 
				
			||||||
	payload += 8;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 1 filler
 | 
					 | 
				
			||||||
	payload++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mysql_server_capabilities_one = gw_mysql_get_byte2(payload);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Capab_1[\n");
 | 
					 | 
				
			||||||
	fwrite(&mysql_server_capabilities_one, 2, 1, stderr);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	//2 capab_part 1 + 1 language + 2 server_status
 | 
					 | 
				
			||||||
	payload +=5;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mysql_server_capabilities_two = gw_mysql_get_byte2(payload);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "]Capab_2[\n");
 | 
					 | 
				
			||||||
	fwrite(&mysql_server_capabilities_two, 2, 1, stderr);
 | 
					 | 
				
			||||||
	fprintf(stderr, "]\n");
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memcpy(&capab_ptr, &mysql_server_capabilities_one, 2);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Capab_1[\n");
 | 
					 | 
				
			||||||
	fwrite(capab_ptr, 2, 1, stderr);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memcpy(&(capab_ptr[2]), &mysql_server_capabilities_two, 2);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Capab_2[\n");
 | 
					 | 
				
			||||||
	fwrite(capab_ptr, 2, 1, stderr);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 2 capab_part 2
 | 
					 | 
				
			||||||
	payload+=2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	scramble_len = payload[0] -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Scramble_len  [%i]\n", scramble_len);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	payload += 11;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memcpy(scramble_data_2, payload, scramble_len - 8);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Scramble_buff1[");
 | 
					 | 
				
			||||||
	fwrite(scramble_data_1, 8, 1, stderr);
 | 
					 | 
				
			||||||
	fprintf(stderr, "]\nScramble_buff2  [");
 | 
					 | 
				
			||||||
	fwrite(scramble_data_2, scramble_len - 8, 1, stderr);
 | 
					 | 
				
			||||||
	fprintf(stderr, "]\n");
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memcpy(scramble, scramble_data_1, 8);
 | 
					 | 
				
			||||||
	memcpy(scramble + 8, scramble_data_2, scramble_len - 8);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Full Scramble 20 bytes is  [\n");
 | 
					 | 
				
			||||||
	fwrite(scramble, GW_MYSQL_SCRAMBLE_SIZE, 1, stderr);
 | 
					 | 
				
			||||||
	fprintf(stderr, "\n]\n");
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memcpy(conn->scramble, scramble, GW_MYSQL_SCRAMBLE_SIZE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Scramble from MYSQL_Conn is  [\n");
 | 
					 | 
				
			||||||
	fwrite(scramble, GW_MYSQL_SCRAMBLE_SIZE, 1, stderr);
 | 
					 | 
				
			||||||
	fprintf(stderr, "\n]\n");
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
	fprintf(stderr, "Now sending user, pass & db\n[");
 | 
					 | 
				
			||||||
	fwrite(&server_capabilities, 4, 1, stderr);
 | 
					 | 
				
			||||||
	fprintf(stderr, "]\n");
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "CAPABS [%u]\n", final_capabilities);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	memset(packet_buffer, '\0', sizeof(packet_buffer));
 | 
					 | 
				
			||||||
	//packet_header(byte3 +1 pack#)
 | 
					 | 
				
			||||||
	packet_buffer[3] = '\x01';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	final_capabilities |= GW_MYSQL_CAPABILITIES_PROTOCOL_41;
 | 
					 | 
				
			||||||
	final_capabilities |= GW_MYSQL_CAPABILITIES_CLIENT;
 | 
					 | 
				
			||||||
	if (compress) {
 | 
					 | 
				
			||||||
		final_capabilities |= GW_MYSQL_CAPABILITIES_COMPRESS;
 | 
					 | 
				
			||||||
		fprintf(stderr, "Backend Connection with compression\n");
 | 
					 | 
				
			||||||
		fflush(stderr);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (curr_passwd != NULL) {
 | 
					 | 
				
			||||||
		uint8_t hash1[GW_MYSQL_SCRAMBLE_SIZE]="";
 | 
					 | 
				
			||||||
		uint8_t hash2[GW_MYSQL_SCRAMBLE_SIZE]="";
 | 
					 | 
				
			||||||
		uint8_t new_sha[GW_MYSQL_SCRAMBLE_SIZE]="";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		memcpy(hash1, passwd, GW_MYSQL_SCRAMBLE_SIZE);
 | 
					 | 
				
			||||||
		gw_sha1_str(hash1, GW_MYSQL_SCRAMBLE_SIZE, hash2);
 | 
					 | 
				
			||||||
		gw_bin2hex(dbpass, hash2, GW_MYSQL_SCRAMBLE_SIZE);
 | 
					 | 
				
			||||||
		gw_sha1_2_str(scramble, GW_MYSQL_SCRAMBLE_SIZE, hash2, GW_MYSQL_SCRAMBLE_SIZE, new_sha);
 | 
					 | 
				
			||||||
		gw_str_xor(client_scramble, new_sha, hash1, GW_MYSQL_SCRAMBLE_SIZE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
		fprintf(stderr, "Hash1 [%s]\n", hash1);
 | 
					 | 
				
			||||||
		fprintf(stderr, "Hash2 [%s]\n", hash2);
 | 
					 | 
				
			||||||
		fprintf(stderr, "SHA1(SHA1(password in hex)\n");
 | 
					 | 
				
			||||||
		fprintf(stderr, "PAss [%s]\n", dbpass);
 | 
					 | 
				
			||||||
		fflush(stderr);
 | 
					 | 
				
			||||||
		fprintf(stderr, "newsha [%s]\n", new_sha);
 | 
					 | 
				
			||||||
		fprintf(stderr, "Client send scramble 20 [\n");
 | 
					 | 
				
			||||||
		fwrite(client_scramble, GW_MYSQL_SCRAMBLE_SIZE, 1, stderr);
 | 
					 | 
				
			||||||
		fprintf(stderr, "\n]\n");
 | 
					 | 
				
			||||||
		fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (curr_db == NULL) {
 | 
					 | 
				
			||||||
		// now without db!!
 | 
					 | 
				
			||||||
		final_capabilities &= ~GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		final_capabilities |= GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	payload = packet_buffer + 4;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	final_capabilities |= GW_MYSQL_CAPABILITIES_PLUGIN_AUTH;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	gw_mysql_set_byte4(client_capabilities, final_capabilities);
 | 
					 | 
				
			||||||
	memcpy(payload, client_capabilities, 4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	//packet_buffer[4] = '\x8d';
 | 
					 | 
				
			||||||
	//packet_buffer[5] = '\xa6';
 | 
					 | 
				
			||||||
	//packet_buffer[6] = '\x0f';
 | 
					 | 
				
			||||||
	//packet_buffer[7] = '\x00';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// set now the max-packet size
 | 
					 | 
				
			||||||
	payload += 4;
 | 
					 | 
				
			||||||
	gw_mysql_set_byte4(payload, 16777216);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// set the charset
 | 
					 | 
				
			||||||
	payload += 4;
 | 
					 | 
				
			||||||
	*payload = '\x08';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	payload++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "User is [%s]\n", user);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
        // 4 + 4 + 4 + 1 + 23 = 36
 | 
					 | 
				
			||||||
	payload += 23;
 | 
					 | 
				
			||||||
	memcpy(payload, user, strlen(user));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // 4 + 4 + 1 + 23  = 32 + 1 (scramble_len) + 20 (fixed_scramble) + 1 (user NULL term) + 1 (db NULL term) = 55
 | 
					 | 
				
			||||||
	bytes = 32;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bytes += strlen(user);
 | 
					 | 
				
			||||||
	// the NULL
 | 
					 | 
				
			||||||
	bytes++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	payload += strlen(user);
 | 
					 | 
				
			||||||
	payload++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (curr_passwd != NULL) {
 | 
					 | 
				
			||||||
		// set the auth-length
 | 
					 | 
				
			||||||
		*payload = GW_MYSQL_SCRAMBLE_SIZE;
 | 
					 | 
				
			||||||
		payload++;
 | 
					 | 
				
			||||||
		bytes++;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		//copy the 20 bytes scramble data after packet_buffer+36+user+NULL+1 (byte of auth-length)
 | 
					 | 
				
			||||||
		memcpy(payload, client_scramble, GW_MYSQL_SCRAMBLE_SIZE);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		payload += GW_MYSQL_SCRAMBLE_SIZE;
 | 
					 | 
				
			||||||
		bytes += GW_MYSQL_SCRAMBLE_SIZE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// skip the auth-length and write a NULL
 | 
					 | 
				
			||||||
		payload++;
 | 
					 | 
				
			||||||
		bytes++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// if the db is not NULL append it
 | 
					 | 
				
			||||||
	if (curr_db) {
 | 
					 | 
				
			||||||
		memcpy(payload, curr_db, strlen(curr_db));
 | 
					 | 
				
			||||||
		payload += strlen(curr_db);
 | 
					 | 
				
			||||||
		payload++;
 | 
					 | 
				
			||||||
		bytes += strlen(curr_db);
 | 
					 | 
				
			||||||
		// the NULL
 | 
					 | 
				
			||||||
		bytes++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memcpy(payload, "mysql_native_password", strlen("mysql_native_password"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	payload += strlen("mysql_native_password");
 | 
					 | 
				
			||||||
	payload++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bytes +=strlen("mysql_native_password");
 | 
					 | 
				
			||||||
	bytes++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	gw_mysql_set_byte3(packet_buffer, bytes);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// the packet header
 | 
					 | 
				
			||||||
	bytes += 4;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rv = write(so, packet_buffer, bytes);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "Sent [%s], [%i] bytes\n", packet_buffer, bytes);
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (rv == -1) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "CONNECT Error in send auth\n");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bytes = SMALL_CHUNK;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(buffer, '\0', sizeof (buffer));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rv = read(so, buffer, SMALL_CHUNK);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (rv == -1) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "CONNCET Error in recv OK for auth\n");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
	fprintf(stderr, "ok packet\[");
 | 
					 | 
				
			||||||
	fwrite(buffer, bytes, 1, stderr);
 | 
					 | 
				
			||||||
	fprintf(stderr, "]\n");
 | 
					 | 
				
			||||||
	fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	if (buffer[4] == '\x00') {
 | 
					 | 
				
			||||||
#ifdef MYSQL_CONN_DEBUG
 | 
					 | 
				
			||||||
		fprintf(stderr, "OK packet received, packet # %i\n", buffer[3]);
 | 
					 | 
				
			||||||
		fflush(stderr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		conn->state = MYSQL_IDLE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		close(so);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This routine put into the delay queue the input queue
 | 
					 * This routine put into the delay queue the input queue
 | 
				
			||||||
 * The input is what backend DCB is receiving
 | 
					 * The input is what backend DCB is receiving
 | 
				
			||||||
 | 
				
			|||||||
@ -179,87 +179,6 @@ mysql_send_ok(DCB *dcb, int packet_number, int in_affected_rows, const char* mys
 | 
				
			|||||||
	return sizeof(mysql_packet_header) + mysql_payload_size;
 | 
						return sizeof(mysql_packet_header) + mysql_payload_size;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * mysql_send_auth_error
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Send a MySQL protocol Generic ERR message, to the dcb
 | 
					 | 
				
			||||||
 * Note the errno and state are still fixed now
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param dcb Descriptor Control Block for the connection to which the OK is sent
 | 
					 | 
				
			||||||
 * @param packet_number
 | 
					 | 
				
			||||||
 * @param in_affected_rows
 | 
					 | 
				
			||||||
 * @param mysql_message
 | 
					 | 
				
			||||||
 * @return packet length
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
mysql_send_custom_error (DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message) {
 | 
					 | 
				
			||||||
        uint8_t *outbuf = NULL;
 | 
					 | 
				
			||||||
        uint8_t mysql_payload_size = 0;
 | 
					 | 
				
			||||||
        uint8_t mysql_packet_header[4];
 | 
					 | 
				
			||||||
        uint8_t *mysql_payload = NULL;
 | 
					 | 
				
			||||||
        uint8_t field_count = 0;
 | 
					 | 
				
			||||||
        uint8_t mysql_err[2];
 | 
					 | 
				
			||||||
        uint8_t mysql_statemsg[6];
 | 
					 | 
				
			||||||
        unsigned int mysql_errno = 0;
 | 
					 | 
				
			||||||
        const char *mysql_error_msg = NULL;
 | 
					 | 
				
			||||||
        const char *mysql_state = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GWBUF   *buf;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        mysql_errno = 2003;
 | 
					 | 
				
			||||||
        mysql_error_msg = "An errorr occurred ...";
 | 
					 | 
				
			||||||
        mysql_state = "HY000";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        field_count = 0xff;
 | 
					 | 
				
			||||||
        gw_mysql_set_byte2(mysql_err, mysql_errno);
 | 
					 | 
				
			||||||
        mysql_statemsg[0]='#';
 | 
					 | 
				
			||||||
        memcpy(mysql_statemsg+1, mysql_state, 5);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (mysql_message != NULL) {
 | 
					 | 
				
			||||||
		mysql_error_msg = mysql_message;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        mysql_payload_size = sizeof(field_count) + sizeof(mysql_err) + sizeof(mysql_statemsg) + strlen(mysql_error_msg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // allocate memory for packet header + payload
 | 
					 | 
				
			||||||
	if ((buf = gwbuf_alloc(sizeof(mysql_packet_header) + mysql_payload_size)) == NULL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	outbuf = GWBUF_DATA(buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // write packet header with packet number
 | 
					 | 
				
			||||||
        gw_mysql_set_byte3(mysql_packet_header, mysql_payload_size);
 | 
					 | 
				
			||||||
        mysql_packet_header[3] = packet_number;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // write header
 | 
					 | 
				
			||||||
        memcpy(outbuf, mysql_packet_header, sizeof(mysql_packet_header));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        mysql_payload = outbuf + sizeof(mysql_packet_header);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // write field
 | 
					 | 
				
			||||||
        memcpy(mysql_payload, &field_count, sizeof(field_count));
 | 
					 | 
				
			||||||
        mysql_payload = mysql_payload + sizeof(field_count);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // write errno
 | 
					 | 
				
			||||||
        memcpy(mysql_payload, mysql_err, sizeof(mysql_err));
 | 
					 | 
				
			||||||
        mysql_payload = mysql_payload + sizeof(mysql_err);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // write sqlstate
 | 
					 | 
				
			||||||
        memcpy(mysql_payload, mysql_statemsg, sizeof(mysql_statemsg));
 | 
					 | 
				
			||||||
        mysql_payload = mysql_payload + sizeof(mysql_statemsg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // write err messg
 | 
					 | 
				
			||||||
        memcpy(mysql_payload, mysql_error_msg, strlen(mysql_error_msg));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// writing data in the Client buffer queue
 | 
					 | 
				
			||||||
	dcb->func.write(dcb, buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sizeof(mysql_packet_header) + mysql_payload_size;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * mysql_send_auth_error
 | 
					 * mysql_send_auth_error
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -542,8 +461,6 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
 | 
				
			|||||||
		fprintf(stderr, "<<< Client is NOT connected with db\n");
 | 
							fprintf(stderr, "<<< Client is NOT connected with db\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fprintf(stderr, "HERE auth token len is %i\n", auth_token_len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// allocate memory for token only if auth_token_len > 0
 | 
						// allocate memory for token only if auth_token_len > 0
 | 
				
			||||||
	if (auth_token_len) {
 | 
						if (auth_token_len) {
 | 
				
			||||||
		auth_token = (uint8_t *)malloc(auth_token_len);
 | 
							auth_token = (uint8_t *)malloc(auth_token_len);
 | 
				
			||||||
@ -558,10 +475,8 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
 | 
				
			|||||||
	if (auth_token)
 | 
						if (auth_token)
 | 
				
			||||||
		free(auth_token);
 | 
							free(auth_token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (auth_ret == 0) {
 | 
						if (auth_ret != 0) {
 | 
				
			||||||
		fprintf(stderr, "<<< CLIENT AUTH is OK\n");
 | 
							fprintf(stderr, "<<< CLIENT AUTH FAILEDi for user [%s]\n", username);
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		fprintf(stderr, "<<< CLIENT AUTH FAILED\n");
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return auth_ret;
 | 
						return auth_ret;
 | 
				
			||||||
@ -586,7 +501,6 @@ static int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_pas
 | 
				
			|||||||
		fprintf(stderr, ">>> MYSQL user NOT FOUND: %s\n", username);
 | 
							fprintf(stderr, ">>> MYSQL user NOT FOUND: %s\n", username);
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	fprintf(stderr, ">>> MYSQL user FOUND !!!!: [%s]:[%s]\n", username, user_password);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// convert hex data (40 bytes) to binary (20 bytes)
 | 
						// convert hex data (40 bytes) to binary (20 bytes)
 | 
				
			||||||
	// gateway_password represents the SHA1(SHA1(real_password))
 | 
						// gateway_password represents the SHA1(SHA1(real_password))
 | 
				
			||||||
@ -618,16 +532,14 @@ static int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int t
 | 
				
			|||||||
	if (ret_val) {
 | 
						if (ret_val) {
 | 
				
			||||||
		fprintf(stderr, "<<<< User [%s] was not found\n", username);
 | 
							fprintf(stderr, "<<<< User [%s] was not found\n", username);
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		fprintf(stderr, "<<<< User [%s] OK\n", username);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (token && token_len) {
 | 
						if (token && token_len) {
 | 
				
			||||||
		fprintf(stderr, ">>> continue with auth\n");
 | 
					 | 
				
			||||||
		// convert in hex format: this is the content of mysql.user table, field password without the '*' prefix
 | 
							// convert in hex format: this is the content of mysql.user table, field password without the '*' prefix
 | 
				
			||||||
		// an it is 40 bytes long
 | 
							// and it is 40 bytes long
 | 
				
			||||||
		gw_bin2hex(hex_double_sha1, password, SHA_DIGEST_LENGTH);
 | 
							gw_bin2hex(hex_double_sha1, password, SHA_DIGEST_LENGTH);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							// check if the password is not set in the user table
 | 
				
			||||||
		if (!strlen((char *)password)) {
 | 
							if (!strlen((char *)password)) {
 | 
				
			||||||
			fprintf(stderr, ">>> continue WITHOUT auth, no password\n");
 | 
								fprintf(stderr, ">>> continue WITHOUT auth, no password\n");
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
@ -673,14 +585,12 @@ static int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int t
 | 
				
			|||||||
	gw_sha1_str(step2, SHA_DIGEST_LENGTH, check_hash);
 | 
						gw_sha1_str(step2, SHA_DIGEST_LENGTH, check_hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fprintf(stderr, "<<<< Client_SHA1 [%20s]\n", stage1_hash);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef GW_DEBUG_CLIENT_AUTH
 | 
					#ifdef GW_DEBUG_CLIENT_AUTH
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		char inpass[128]="";
 | 
							char inpass[128]="";
 | 
				
			||||||
		gw_bin2hex(inpass, check_hash, SHA_DIGEST_LENGTH);
 | 
							gw_bin2hex(inpass, check_hash, SHA_DIGEST_LENGTH);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		//fprintf(stderr, "The CLIENT hex(SHA1(SHA1(password))) for \"%s\" is [%s]", username, inpass);
 | 
							fprintf(stderr, "The CLIENT hex(SHA1(SHA1(password))) for \"%s\" is [%s]", username, inpass);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -865,6 +775,8 @@ int gw_read_client_event(DCB* dcb) {
 | 
				
			|||||||
				int ret = -1;
 | 
									int ret = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				session = dcb->session;
 | 
									session = dcb->session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// get the backend session, if available
 | 
				
			||||||
				if (session) {
 | 
									if (session) {
 | 
				
			||||||
					router = session->service->router;
 | 
										router = session->service->router;
 | 
				
			||||||
					router_instance = session->service->router_instance;
 | 
										router_instance = session->service->router_instance;
 | 
				
			||||||
@ -877,65 +789,66 @@ int gw_read_client_event(DCB* dcb) {
 | 
				
			|||||||
				if ((ret = gw_read_gwbuff(dcb, &gw_buffer, b)) != 0)
 | 
									if ((ret = gw_read_gwbuff(dcb, &gw_buffer, b)) != 0)
 | 
				
			||||||
					return ret;
 | 
										return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// Now assuming in the first buffer there is the information form mysql command
 | 
									/* Now, we are assuming in the first buffer there is the information form mysql command */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// following code is only for debug now
 | 
					 | 
				
			||||||
				queue = gw_buffer;
 | 
									queue = gw_buffer;
 | 
				
			||||||
				len = GWBUF_LENGTH(queue);
 | 
									len = GWBUF_LENGTH(queue);
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
				ptr_buff = GWBUF_DATA(queue);
 | 
									ptr_buff = GWBUF_DATA(queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// get mysql commang
 | 
									/* get mysql commang at fourth byte */
 | 
				
			||||||
				if (ptr_buff)
 | 
									if (ptr_buff)
 | 
				
			||||||
					mysql_command = ptr_buff[4];
 | 
										mysql_command = ptr_buff[4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (mysql_command  == '\x03') {
 | 
									if (mysql_command  == '\x03') {
 | 
				
			||||||
					/// this is a query !!!!
 | 
										/// this is a standard MySQL query !!!!
 | 
				
			||||||
					//fprintf(stderr, "<<< MySQL Query from Client %i bytes: [%s]\n", len, ptr_buff+5);
 | 
					 | 
				
			||||||
				//else
 | 
					 | 
				
			||||||
					//fprintf(stderr, "<<< Reading from Client %i bytes: [%s]\n", len, ptr_buff);
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/**
 | 
				
			||||||
 | 
									* Routing Client input to Backend
 | 
				
			||||||
 | 
									*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/* Do not route the query without session! */
 | 
				
			||||||
				if(!rsession) {
 | 
									if(!rsession) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
					if (mysql_command == '\x01') {
 | 
										if (mysql_command == '\x01') {
 | 
				
			||||||
						fprintf(stderr, "COM_QUIT received with no connected backends\n");
 | 
											/* COM_QUIT handling */
 | 
				
			||||||
 | 
											//fprintf(stderr, "COM_QUIT received with no connected backends from %i\n", dcb->fd);
 | 
				
			||||||
                                        	(dcb->func).close(dcb);
 | 
					                                        	(dcb->func).close(dcb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						return 1;
 | 
											return 1;
 | 
				
			||||||
					}
 | 
										} else {
 | 
				
			||||||
					mysql_send_custom_error(dcb, 1, 0, "Connection to backend lost");
 | 
											/* Send a custom error as MySQL command reply */	
 | 
				
			||||||
					protocol->state = MYSQL_IDLE;
 | 
											mysql_send_custom_error(dcb, 1, 0, "Connection to backend lost");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					break;
 | 
											protocol->state = MYSQL_IDLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											return 1;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
				///////////////////////////
 | 
									/* We can route the query */		
 | 
				
			||||||
				// Handling the COM_QUIT
 | 
					 | 
				
			||||||
				//////////////////////////
 | 
					 | 
				
			||||||
				if (mysql_command == '\x01') {
 | 
					 | 
				
			||||||
					fprintf(stderr, "COM_QUIT received\n");
 | 
					 | 
				
			||||||
					// uncomment the following lines for closing
 | 
					 | 
				
			||||||
					// client and backend conns
 | 
					 | 
				
			||||||
					// dcb still to be freed
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
					// this will propagate COM_QUIT to backends
 | 
									/* COM_QUIT handling */
 | 
				
			||||||
 | 
									if (mysql_command == '\x01') {
 | 
				
			||||||
 | 
										//fprintf(stderr, "COM_QUIT received from %i and passed to backed\n", dcb->fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										/* this will propagate COM_QUIT to backend(s) */
 | 
				
			||||||
 | 
										//fprintf(stderr, "<<< Routing the COM_QUIT ...\n");
 | 
				
			||||||
					router->routeQuery(router_instance, rsession, queue);
 | 
										router->routeQuery(router_instance, rsession, queue);
 | 
				
			||||||
					// close client
 | 
					
 | 
				
			||||||
 | 
										/* close client connection */
 | 
				
			||||||
                                        (dcb->func).close(dcb);
 | 
					                                        (dcb->func).close(dcb);
 | 
				
			||||||
					// call errors, it will be removed after tests
 | 
					 | 
				
			||||||
					//(dcb->func).error(dcb);
 | 
					 | 
				
			||||||
				
 | 
									
 | 
				
			||||||
					return 1;
 | 
										return 1;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/* MySQL Command Routing */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				protocol->state = MYSQL_ROUTING;
 | 
									protocol->state = MYSQL_ROUTING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				///////////////////////////////////////
 | 
									/* writing in the backend buffer queue, via routeQuery */
 | 
				
			||||||
				// writing in the backend buffer queue, via routeQuery
 | 
					 | 
				
			||||||
				///////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									//fprintf(stderr, "<<< Routing the Query ...\n");
 | 
				
			||||||
				router->routeQuery(router_instance, rsession, queue);
 | 
									router->routeQuery(router_instance, rsession, queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				protocol->state = MYSQL_WAITING_RESULT;
 | 
									protocol->state = MYSQL_WAITING_RESULT;
 | 
				
			||||||
@ -1085,7 +998,6 @@ int gw_MySQLAccept(DCB *listener) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if (c_sock == -1) {
 | 
							if (c_sock == -1) {
 | 
				
			||||||
			if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
 | 
								if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
 | 
				
			||||||
				fprintf(stderr, ">>>> NO MORE conns for MySQL Listener: errno is %i for %i\n", errno, listener->fd);
 | 
					 | 
				
			||||||
				/* We have processed all incoming connections. */
 | 
									/* We have processed all incoming connections. */
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
@ -1145,7 +1057,8 @@ int gw_MySQLAccept(DCB *listener) {
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
static int gw_error_client_event(DCB *dcb) {
 | 
					static int gw_error_client_event(DCB *dcb) {
 | 
				
			||||||
	fprintf(stderr, "#### Handle error function gw_error_client_event, for [%i] is [%s]\n", dcb->fd, gw_dcb_state2string(dcb->state));
 | 
						//fprintf(stderr, "#### Handle error function gw_error_client_event, for [%i] is [%s]\n", dcb->fd, gw_dcb_state2string(dcb->state));
 | 
				
			||||||
 | 
					        //dcb_close(dcb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -432,4 +432,162 @@ int gw_send_authentication_to_backend(char *dbname, char *user, uint8_t *passwd,
 | 
				
			|||||||
	else
 | 
						else
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Only backend connect syscall
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int gw_do_connect_to_backend(char *host, int port, MySQLProtocol *conn) {
 | 
				
			||||||
 | 
						struct sockaddr_in serv_addr;
 | 
				
			||||||
 | 
						int rv;
 | 
				
			||||||
 | 
						int so = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&serv_addr, 0, sizeof serv_addr);
 | 
				
			||||||
 | 
						serv_addr.sin_family = AF_INET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						so = socket(AF_INET,SOCK_STREAM,0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						conn->fd = so;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (so < 0) {
 | 
				
			||||||
 | 
							fprintf(stderr, "Error creating backend socket: [%s] %i\n", strerror(errno), errno);
 | 
				
			||||||
 | 
							/* this is an error */
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setipaddress(&serv_addr.sin_addr, host);
 | 
				
			||||||
 | 
						serv_addr.sin_port = htons(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* set NON BLOCKING here */
 | 
				
			||||||
 | 
						setnonblocking(so);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((rv = connect(so, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) < 0) {
 | 
				
			||||||
 | 
							/* If connection is not yet completed just return 1 */
 | 
				
			||||||
 | 
							if (errno == EINPROGRESS) {
 | 
				
			||||||
 | 
								//fprintf(stderr, ">>> Connection is not yet completed for backend server [%s:%i]: errno %i, %s: RV = [%i]\n", host, port, errno, strerror(errno), rv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* this is a real error */
 | 
				
			||||||
 | 
								fprintf(stderr, ">>> ERROR connecting to backend server [%s:%i]: errno %i, %s: RV = [%i]\n", host, port, errno, strerror(errno), rv);
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The connection succesfully completed now */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return a string representation of a MySQL protocol state.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param state The protocol state
 | 
				
			||||||
 | 
					 * @return String representation of the state
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const char *
 | 
				
			||||||
 | 
					gw_mysql_protocol_state2string (int state) {
 | 
				
			||||||
 | 
					        switch(state) {
 | 
				
			||||||
 | 
					                case MYSQL_ALLOC:
 | 
				
			||||||
 | 
					                        return "MySQL Protocl struct allocated";
 | 
				
			||||||
 | 
					                case MYSQL_PENDING_CONNECT:
 | 
				
			||||||
 | 
					                        return "MySQL Backend socket PENDING connect";
 | 
				
			||||||
 | 
					                case MYSQL_CONNECTED:
 | 
				
			||||||
 | 
					                        return "MySQL Backend socket CONNECTED";
 | 
				
			||||||
 | 
					                case MYSQL_AUTH_SENT:
 | 
				
			||||||
 | 
					                        return "MySQL Authentication handshake has been sent";
 | 
				
			||||||
 | 
					                case MYSQL_AUTH_RECV:
 | 
				
			||||||
 | 
					                        return "MySQL Received user, password, db and capabilities";
 | 
				
			||||||
 | 
					                case MYSQL_AUTH_FAILED:
 | 
				
			||||||
 | 
					                        return "MySQL Authentication failed";
 | 
				
			||||||
 | 
					                case MYSQL_IDLE:
 | 
				
			||||||
 | 
					                        return "MySQL Auth done. Protocol is idle, waiting for statements";
 | 
				
			||||||
 | 
					                case MYSQL_ROUTING:
 | 
				
			||||||
 | 
					                        return "MySQL received command has been routed to backend(s)";
 | 
				
			||||||
 | 
					                case MYSQL_WAITING_RESULT:
 | 
				
			||||||
 | 
					                        return "MySQL Waiting for result set";
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                        return "MySQL (unknown protocol state)";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * mysql_send_custom_error
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Send a MySQL protocol Generic ERR message, to the dcb
 | 
				
			||||||
 | 
					 * Note the errno and state are still fixed now
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dcb Descriptor Control Block for the connection to which the OK is sent
 | 
				
			||||||
 | 
					 * @param packet_number
 | 
				
			||||||
 | 
					 * @param in_affected_rows
 | 
				
			||||||
 | 
					 * @param mysql_message
 | 
				
			||||||
 | 
					 * @return packet length
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					mysql_send_custom_error (DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message) {
 | 
				
			||||||
 | 
					        uint8_t *outbuf = NULL;
 | 
				
			||||||
 | 
					        uint8_t mysql_payload_size = 0;
 | 
				
			||||||
 | 
					        uint8_t mysql_packet_header[4];
 | 
				
			||||||
 | 
					        uint8_t *mysql_payload = NULL;
 | 
				
			||||||
 | 
					        uint8_t field_count = 0;
 | 
				
			||||||
 | 
					        uint8_t mysql_err[2];
 | 
				
			||||||
 | 
					        uint8_t mysql_statemsg[6];
 | 
				
			||||||
 | 
					        unsigned int mysql_errno = 0;
 | 
				
			||||||
 | 
					        const char *mysql_error_msg = NULL;
 | 
				
			||||||
 | 
					        const char *mysql_state = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GWBUF   *buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mysql_errno = 2003;
 | 
				
			||||||
 | 
					        mysql_error_msg = "An errorr occurred ...";
 | 
				
			||||||
 | 
					        mysql_state = "HY000";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        field_count = 0xff;
 | 
				
			||||||
 | 
					        gw_mysql_set_byte2(mysql_err, mysql_errno);
 | 
				
			||||||
 | 
					        mysql_statemsg[0]='#';
 | 
				
			||||||
 | 
					        memcpy(mysql_statemsg+1, mysql_state, 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (mysql_message != NULL) {
 | 
				
			||||||
 | 
					                mysql_error_msg = mysql_message;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mysql_payload_size = sizeof(field_count) + sizeof(mysql_err) + sizeof(mysql_statemsg) + strlen(mysql_error_msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // allocate memory for packet header + payload
 | 
				
			||||||
 | 
					        if ((buf = gwbuf_alloc(sizeof(mysql_packet_header) + mysql_payload_size)) == NULL)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					                return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        outbuf = GWBUF_DATA(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // write packet header with packet number
 | 
				
			||||||
 | 
					        gw_mysql_set_byte3(mysql_packet_header, mysql_payload_size);
 | 
				
			||||||
 | 
					        mysql_packet_header[3] = packet_number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // write header
 | 
				
			||||||
 | 
					        memcpy(outbuf, mysql_packet_header, sizeof(mysql_packet_header));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mysql_payload = outbuf + sizeof(mysql_packet_header);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // write field
 | 
				
			||||||
 | 
					        memcpy(mysql_payload, &field_count, sizeof(field_count));
 | 
				
			||||||
 | 
					        mysql_payload = mysql_payload + sizeof(field_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // write errno
 | 
				
			||||||
 | 
					        memcpy(mysql_payload, mysql_err, sizeof(mysql_err));
 | 
				
			||||||
 | 
					        mysql_payload = mysql_payload + sizeof(mysql_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // write sqlstate
 | 
				
			||||||
 | 
					        memcpy(mysql_payload, mysql_statemsg, sizeof(mysql_statemsg));
 | 
				
			||||||
 | 
					        mysql_payload = mysql_payload + sizeof(mysql_statemsg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // write err messg
 | 
				
			||||||
 | 
					        memcpy(mysql_payload, mysql_error_msg, strlen(mysql_error_msg));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // writing data in the Client buffer queue
 | 
				
			||||||
 | 
					        dcb->func.write(dcb, buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return sizeof(mysql_packet_header) + mysql_payload_size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/////
 | 
					/////
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user