MXS-1689 Properly check for duplicate port/socket of service
It is now impossible to create two listeners for a service that would listen on the same port/socket (as before), but the error message is now sensible and provides detailed information to the user.
This commit is contained in:
		@ -236,6 +236,24 @@ bool serviceAddBackend(SERVICE *service, SERVER *server);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
bool serviceHasBackend(SERVICE *service, SERVER *server);
 | 
					bool serviceHasBackend(SERVICE *service, SERVER *server);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Find listener with specified properties.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param service Service to check
 | 
				
			||||||
 | 
					 * @param socket  Listener socket path
 | 
				
			||||||
 | 
					 * @param address Listener address
 | 
				
			||||||
 | 
					 * @param port    Listener port number
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @note Either socket should be NULL and port non-zero or socket
 | 
				
			||||||
 | 
					 *       non-NULL and port zero.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return True if service has the listener
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SERV_LISTENER* service_find_listener(SERVICE* service,
 | 
				
			||||||
 | 
					                                     const char* socket,
 | 
				
			||||||
 | 
					                                     const char* address,
 | 
				
			||||||
 | 
					                                     unsigned short port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @brief Check if a service has a listener
 | 
					 * @brief Check if a service has a listener
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
@ -3456,13 +3456,17 @@ int create_new_listener(CONFIG_CONTEXT *obj)
 | 
				
			|||||||
        SERVICE *service = service_find(service_name);
 | 
					        SERVICE *service = service_find(service_name);
 | 
				
			||||||
        if (service)
 | 
					        if (service)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            SERV_LISTENER *listener;
 | 
				
			||||||
            SSL_LISTENER *ssl_info = make_ssl_structure(obj, true, &error_count);
 | 
					            SSL_LISTENER *ssl_info = make_ssl_structure(obj, true, &error_count);
 | 
				
			||||||
            if (socket)
 | 
					            if (socket)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (serviceHasListener(service, obj->object, protocol, address, 0))
 | 
					                listener = service_find_listener(service, socket, NULL, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (listener)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    MXS_ERROR("Listener '%s' for service '%s' already has a socket at '%s.",
 | 
					                    MXS_ERROR("Creation of listener '%s' for service '%s' failed, because "
 | 
				
			||||||
                              obj->object, service_name, socket);
 | 
					                              "listener '%s' already listens on the socket '%s'.",
 | 
				
			||||||
 | 
					                              obj->object, raw_service_name, listener->name, socket);
 | 
				
			||||||
                    error_count++;
 | 
					                    error_count++;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
@ -3474,12 +3478,13 @@ int create_new_listener(CONFIG_CONTEXT *obj)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (port)
 | 
					            if (port)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (serviceHasListener(service, obj->object, protocol, address, atoi(port)))
 | 
					                listener = service_find_listener(service, NULL, address, atoi(port));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (listener)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    MXS_ERROR("Listener '%s', for service '%s', already have port %s.",
 | 
					                    MXS_ERROR("Creation of listener '%s' for service '%s' failed, because "
 | 
				
			||||||
                              obj->object,
 | 
					                              "listener '%s' already listens on the port %s.",
 | 
				
			||||||
                              service_name,
 | 
					                              obj->object, raw_service_name, listener->name, port);
 | 
				
			||||||
                              port);
 | 
					 | 
				
			||||||
                    error_count++;
 | 
					                    error_count++;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
 | 
				
			|||||||
@ -806,6 +806,46 @@ SERV_LISTENER* serviceCreateListener(SERVICE *service, const char *name, const c
 | 
				
			|||||||
    return proto;
 | 
					    return proto;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SERV_LISTENER* service_find_listener(SERVICE* service,
 | 
				
			||||||
 | 
					                                     const char* socket,
 | 
				
			||||||
 | 
					                                     const char* address, unsigned short port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    LISTENER_ITERATOR iter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (SERV_LISTENER *listener = listener_iterator_init(service, &iter);
 | 
				
			||||||
 | 
					         listener; listener = listener_iterator_next(&iter))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (listener_is_active(listener))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            bool is_same_port = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (port && (port == listener->port) &&
 | 
				
			||||||
 | 
					                ((address && listener->address && strcmp(listener->address, address) == 0) ||
 | 
				
			||||||
 | 
					                 (address == NULL && listener->address == NULL)))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                is_same_port = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            bool is_same_socket = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!is_same_port)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (socket && listener->address && strcmp(listener->address, socket) == 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    is_same_socket = true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (is_same_port || is_same_socket)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return listener;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Check if a protocol/port pair is part of the service
 | 
					 * Check if a protocol/port pair is part of the service
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user