// Handles the binary set command // Return 0 on success, -1 on error, -2 if missing data static int handle_binary_set(statsite_conn_handler *handle, uint16_t *header, int should_free) { /* * Abort if we haven't received the command * header[1] is the key length * header[2] is the set length */ char *key; int val_bytes = header[1] + header[2]; // Read the full command if available if (unlikely(should_free)) free(header); if (read_client_bytes(handle->conn, MIN_BINARY_HEADER_SIZE + val_bytes, (char**)&header, &should_free)) return -2; key = ((char*)header) + MIN_BINARY_HEADER_SIZE; // Verify the null terminators if (unlikely(*(key + header[1] - 1))) { syslog(LOG_WARNING, "Received command from binary stream with non-null terminated key: %.*s!", header[1], key); goto ERR_RET; } if (unlikely(*(key + val_bytes - 1))) { syslog(LOG_WARNING, "Received command from binary stream with non-null terminated set key: %.*s!", header[2], key+header[1]); goto ERR_RET; } // Increment the input counter if (GLOBAL_CONFIG->input_counter) metrics_add_sample(GLOBAL_METRICS, COUNTER, GLOBAL_CONFIG->input_counter, 1); // Update the set metrics_set_update(GLOBAL_METRICS, key, key+header[1]); // Make sure to free the command buffer if we need to if (unlikely(should_free)) free(header); return 0; ERR_RET: if (unlikely(should_free)) free(header); return -1; }
/** * Invoked to handle binary commands. * @arg handle The connection related information * @return 0 on success. */ static int handle_binary_client_connect(statsite_conn_handler *handle) { metric_type type; uint16_t key_len; int should_free; unsigned char *cmd, *key; while (1) { // Peek and check for the header. This is up to 12 bytes. // Magic byte - 1 byte // Metric type - 1 byte // Key length - 2 bytes // Metric value - 8 bytes OR Set Length 2 bytes if (peek_client_bytes(handle->conn, MIN_BINARY_HEADER_SIZE, (char**)&cmd, &should_free)) return 0; // Return if no command is available // Check for the magic byte if (unlikely(cmd[0] != BINARY_MAGIC_BYTE)) { syslog(LOG_WARNING, "Received command from binary stream without magic byte! Byte: %u", cmd[0]); goto ERR_RET; } // Get the metric type switch (cmd[1]) { case BIN_TYPE_KV: type = KEY_VAL; break; case BIN_TYPE_COUNTER: type = COUNTER; break; case BIN_TYPE_TIMER: type = TIMER; break; case BIN_TYPE_GAUGE: type = GAUGE; break; case BIN_TYPE_GAUGE_DELTA: type = GAUGE_DELTA; break; // Special case set handling case BIN_TYPE_SET: switch (handle_binary_set(handle, (uint16_t*)cmd, should_free)) { case -1: return -1; case -2: return 0; default: continue; } default: syslog(LOG_WARNING, "Received command from binary stream with unknown type: %u!", cmd[1]); goto ERR_RET; } // Abort if we haven't received the full key, wait for the data key_len = *(uint16_t*)(cmd+2); // Read the full command if available if (unlikely(should_free)) free(cmd); if (read_client_bytes(handle->conn, MAX_BINARY_HEADER_SIZE + key_len, (char**)&cmd, &should_free)) return 0; key = cmd + MAX_BINARY_HEADER_SIZE; // Verify the key contains a null terminator if (unlikely(*(key + key_len - 1))) { syslog(LOG_WARNING, "Received command from binary stream with non-null terminated key: %.*s!", key_len, key); goto ERR_RET; } // Increment the input counter if (GLOBAL_CONFIG->input_counter) metrics_add_sample(GLOBAL_METRICS, COUNTER, GLOBAL_CONFIG->input_counter, 1); // Add the sample metrics_add_sample(GLOBAL_METRICS, type, key, *(double*)(cmd+4)); // Make sure to free the command buffer if we need to if (unlikely(should_free)) free(cmd); } return 0; ERR_RET: if (unlikely(should_free)) free(cmd); return -1; }
/** * Invoked to handle binary commands. * @arg handle The connection related information * @return 0 on success. */ static int handle_binary_client_connect(statsite_proxy_conn_handler *handle) { metric_type type; int status, should_free; char *key; unsigned char header[BINARY_HEADER_SIZE]; uint8_t type_input; uint16_t key_len; while (1) { // Peek and check for the header. This is 12 bytes. // Magic byte - 1 byte // Metric type - 1 byte // Key length - 2 bytes // Metric value - 8 bytes status = peek_client_bytes(handle->conn, BINARY_HEADER_SIZE, (char*)&header); if (status == -1) return 0; // Return if no command is available // Check for the magic byte if (header[0] != BINARY_MAGIC_BYTE) { syslog(LOG_WARNING, "Received command from binary stream without magic byte!"); return -1; } // Get the metric type type_input = header[1]; switch (type_input) { case BIN_TYPE_KV: type = KEY_VAL; break; case BIN_TYPE_COUNTER: type = COUNTER; break; case BIN_TYPE_TIMER: type = TIMER; break; default: type = UNKNOWN; syslog(LOG_WARNING, "Received command from binary stream with unknown type: %u!", type_input); break; } // Extract the key length and value memcpy(&key_len, &header[2], 2); // Abort if we haven't received the full key, wait for the data if (available_bytes(handle->conn) < BINARY_HEADER_SIZE + key_len) return 0; // Seek past the header seek_client_bytes(handle->conn, BINARY_HEADER_SIZE); // Read the key now read_client_bytes(handle->conn, key_len, &key, &should_free); // Verify the key contains a null terminator if (memchr(key, '\0', key_len) == NULL) { syslog(LOG_WARNING, "Received command from binary stream with non-null terminated key: %.*s!", key_len, key); // For safety, we will just set the last byte to be null, and continue processing *(key + key_len - 1) = 0; } // Apply consistent hashing //char* server = hashring_getserver(handle->hashring, key); // Make sure to free the command buffer if we need to if (should_free) free(key); } return 0; }