MXS-619: Allow backend authentication to complete
By deferring the closing of a DCB until the protocol tells that it's in a stable state, we avoid closing the connection mid-authentication. This makes sure that all connections have reached a stable state before they are closed which in turn prevents the connections from counting towards aborted connects (or failed authentications like it did with the old fix).
This commit is contained in:
parent
ae2cad9254
commit
a655c5d08c
@ -30,11 +30,17 @@ int64_t mxs_clock();
|
||||
/**
|
||||
* Convert heartbeats to seconds
|
||||
*/
|
||||
#define MXS_CLOCK_TO_SEC(a) ((int64_t)a / 10)
|
||||
static inline int64_t MXS_CLOCK_TO_SEC(int64_t a)
|
||||
{
|
||||
return a / 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert seconds to heartbeats
|
||||
*/
|
||||
#define MXS_SEC_TO_CLOCK(a) ((int64_t)a * 10)
|
||||
static inline int64_t MXS_SEC_TO_CLOCK(int64_t a)
|
||||
{
|
||||
return a * 10;
|
||||
}
|
||||
|
||||
MXS_END_DECLS
|
||||
|
@ -179,6 +179,18 @@ struct MXS_PROTOCOL
|
||||
* @return A buffer containing the error message
|
||||
*/
|
||||
GWBUF* (* reject)(const char* host);
|
||||
|
||||
/**
|
||||
* Check if the DCB can be closed in a controlled manner
|
||||
*
|
||||
* The DCB will be unconditionally closed if this entry point is not implemented or a hard-coded timeout
|
||||
* is exceeded.
|
||||
*
|
||||
* @param dcb DCB to check
|
||||
*
|
||||
* @return True if the DCB can be closed
|
||||
*/
|
||||
bool (* can_close)(DCB*);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -186,7 +198,7 @@ struct MXS_PROTOCOL
|
||||
* the MXS_PROTOCOL structure is changed. See the rules defined in modinfo.h
|
||||
* that define how these numbers should change.
|
||||
*/
|
||||
#define MXS_PROTOCOL_VERSION {2, 1, 0}
|
||||
#define MXS_PROTOCOL_VERSION {2, 2, 0}
|
||||
|
||||
/**
|
||||
* Specifies capabilities specific for protocol.
|
||||
|
@ -161,6 +161,15 @@ void modules_thread_finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool can_close_dcb(DCB* dcb)
|
||||
{
|
||||
auto idle = MXS_CLOCK_TO_SEC(mxs_clock() - dcb->last_read);
|
||||
|
||||
return idle > 5 // Timed out
|
||||
|| !dcb->func.can_close // Not implemented
|
||||
|| dcb->func.can_close(dcb); // Protocol says it's OK to close
|
||||
}
|
||||
}
|
||||
|
||||
namespace maxscale
|
||||
@ -550,6 +559,8 @@ void RoutingWorker::register_zombie(DCB* pDcb)
|
||||
|
||||
void RoutingWorker::delete_zombies()
|
||||
{
|
||||
Zombies not_ready;
|
||||
|
||||
// An algorithm cannot be used, as the final closing of a DCB may cause
|
||||
// other DCBs to be registered in the zombie queue.
|
||||
|
||||
@ -557,8 +568,18 @@ void RoutingWorker::delete_zombies()
|
||||
{
|
||||
DCB* pDcb = m_zombies.back();
|
||||
m_zombies.pop_back();
|
||||
dcb_final_close(pDcb);
|
||||
|
||||
if (can_close_dcb(pDcb))
|
||||
{
|
||||
dcb_final_close(pDcb);
|
||||
}
|
||||
else
|
||||
{
|
||||
not_ready.push_back(pDcb);
|
||||
}
|
||||
}
|
||||
|
||||
m_zombies.insert(m_zombies.end(), not_ready.begin(), not_ready.end());
|
||||
}
|
||||
|
||||
bool RoutingWorker::pre_run()
|
||||
|
@ -63,6 +63,7 @@ static bool get_ip_string_and_port(struct sockaddr_storage* sa,
|
||||
int iplen,
|
||||
in_port_t* port_out);
|
||||
static bool gw_connection_established(DCB* dcb);
|
||||
static bool gw_auth_is_complete(DCB* dcb);
|
||||
json_t* gw_json_diagnostics(DCB* dcb);
|
||||
|
||||
extern "C"
|
||||
@ -92,6 +93,8 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
||||
NULL, /* Connection limit reached */
|
||||
gw_connection_established,
|
||||
gw_json_diagnostics,
|
||||
NULL,
|
||||
gw_auth_is_complete,
|
||||
};
|
||||
|
||||
static MXS_MODULE info =
|
||||
@ -2018,6 +2021,24 @@ static bool gw_connection_established(DCB* dcb)
|
||||
&& !proto->stored_query;
|
||||
}
|
||||
|
||||
static bool gw_auth_is_complete(DCB* dcb)
|
||||
{
|
||||
MySQLProtocol* proto = (MySQLProtocol*)dcb->protocol;
|
||||
|
||||
switch (proto->protocol_auth_state)
|
||||
{
|
||||
case MXS_AUTH_STATE_FAILED:
|
||||
case MXS_AUTH_STATE_HANDSHAKE_FAILED:
|
||||
case MXS_AUTH_STATE_COMPLETE:
|
||||
MXS_DEBUG("(%lu) Auth is complete for DCB %lu", dcb->session->ses_id, dcb->m_uid);
|
||||
return true;
|
||||
|
||||
default:
|
||||
MXS_DEBUG("(%lu) Auth not yet complete for DCB %lu", dcb->session->ses_id, dcb->m_uid);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
json_t* gw_json_diagnostics(DCB* dcb)
|
||||
{
|
||||
MySQLProtocol* proto = static_cast<MySQLProtocol*>(dcb->protocol);
|
||||
|
Loading…
x
Reference in New Issue
Block a user