|
@@ -344,6 +344,38 @@ static int is_sasl_auth_in_progress(zhandle_t* zh)
|
|
|
#endif /* HAVE_CYRUS_SASL_H */
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Extract the type field (ZOO_*_OP) of a serialized RequestHeader.
|
|
|
+ *
|
|
|
+ * (This is not the most efficient way of fetching 4 bytes, but it is
|
|
|
+ * currently only used during SASL negotiation.)
|
|
|
+ *
|
|
|
+ * \param buffer the buffer to extract the request type from. Must
|
|
|
+ * start with a serialized RequestHeader;
|
|
|
+ * \param len the buffer length. Must be positive.
|
|
|
+ * \param out_type out parameter; pointer to the location where the
|
|
|
+ * extracted type is to be stored. Cannot be NULL.
|
|
|
+ * \return ZOK on success, or < 0 if something went wrong
|
|
|
+ */
|
|
|
+static int extract_request_type(char *buffer, int len, int32_t *out_type)
|
|
|
+{
|
|
|
+ struct iarchive *ia;
|
|
|
+ struct RequestHeader h;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ ia = create_buffer_iarchive(buffer, len);
|
|
|
+ rc = ia ? ZOK : ZSYSTEMERROR;
|
|
|
+ rc = rc < 0 ? rc : deserialize_RequestHeader(ia, "header", &h);
|
|
|
+ deallocate_RequestHeader(&h);
|
|
|
+ if (ia) {
|
|
|
+ close_buffer_iarchive(&ia);
|
|
|
+ }
|
|
|
+
|
|
|
+ *out_type = h.type;
|
|
|
+
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+
|
|
|
#ifndef THREADED
|
|
|
/*
|
|
|
* abort due to the use of a sync api in a singlethreaded environment
|
|
@@ -2812,6 +2844,11 @@ static void finalize_session_establishment(zhandle_t *zh) {
|
|
|
LOG_DEBUG(LOGCALLBACK(zh), "Calling a watcher for a ZOO_SESSION_EVENT and the state=ZOO_CONNECTED_STATE");
|
|
|
zh->input_buffer = 0; // just in case the watcher calls zookeeper_process() again
|
|
|
PROCESS_SESSION_EVENT(zh, zh->state);
|
|
|
+
|
|
|
+ if (zh->sasl_client) {
|
|
|
+ /* some packets might have been delayed during SASL negotiaton. */
|
|
|
+ adaptor_send_queue(zh, 0);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
#ifdef HAVE_CYRUS_SASL_H
|
|
@@ -4855,6 +4892,20 @@ int flush_send_queue(zhandle_t*zh, int timeout)
|
|
|
// successful
|
|
|
lock_buffer_list(&zh->to_send);
|
|
|
while (zh->to_send.head != 0 && (is_connected(zh) || is_sasl_auth_in_progress(zh))) {
|
|
|
+ if (is_sasl_auth_in_progress(zh)) {
|
|
|
+ // We don't let non-SASL packets escape as long as
|
|
|
+ // negotiation is not complete. (SASL packets are always
|
|
|
+ // pushed to the front of the queue.)
|
|
|
+ buffer_list_t *buff = zh->to_send.head;
|
|
|
+ int32_t type;
|
|
|
+
|
|
|
+ rc = extract_request_type(buff->buffer, buff->len, &type);
|
|
|
+
|
|
|
+ if (rc < 0 || type != ZOO_SASL_OP) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if(timeout!=0){
|
|
|
#ifndef _WIN32
|
|
|
struct pollfd fds;
|
|
@@ -5020,8 +5071,14 @@ int zoo_add_auth(zhandle_t *zh,const char* scheme,const char* cert,
|
|
|
add_last_auth(&zh->auth_h, authinfo);
|
|
|
zoo_unlock_auth(zh);
|
|
|
|
|
|
- if (is_connected(zh) || zh->state == ZOO_ASSOCIATING_STATE)
|
|
|
+ if (is_connected(zh) ||
|
|
|
+ // When associating, only send info packets if no SASL
|
|
|
+ // negotiation is planned. (Such packets would be queued in
|
|
|
+ // front of SASL packets, which is forbidden, and SASL
|
|
|
+ // completion is followed by a 'send_auth_info' anyway.)
|
|
|
+ (zh->state == ZOO_ASSOCIATING_STATE && !zh->sasl_client)) {
|
|
|
return send_last_auth_info(zh);
|
|
|
+ }
|
|
|
|
|
|
return ZOK;
|
|
|
}
|