X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;ds=sidebyside;f=libmemcached%2Fresponse.cc;h=b840e9d7037a1a8a5cfe0b81674242f0bbb6f7ea;hb=ab9ea0e2b9e1cb2bf88510f3077950cd8e464622;hp=e876123d4290ef9a468ac1ff7946a29875c2b777;hpb=2959e927ae7c1da490db7a88f0cd589e8bc6b45f;p=awesomized%2Flibmemcached diff --git a/libmemcached/response.cc b/libmemcached/response.cc index e876123d..b840e9d7 100644 --- a/libmemcached/response.cc +++ b/libmemcached/response.cc @@ -180,14 +180,12 @@ read_error: return MEMCACHED_PARTIAL_READ; } -static memcached_return_t textual_read_one_response(memcached_server_write_instance_st ptr, +static memcached_return_t textual_read_one_response(memcached_server_write_instance_st instance, char *buffer, const size_t buffer_length, - memcached_result_st *result, - uint64_t& numeric_value) + memcached_result_st *result) { - numeric_value= UINT64_MAX; size_t total_read; - memcached_return_t rc= memcached_io_readline(ptr, buffer, buffer_length, total_read); + memcached_return_t rc= memcached_io_readline(instance, buffer, buffer_length, total_read); if (memcached_failed(rc)) { @@ -203,12 +201,46 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta if (buffer[1] == 'A' and buffer[2] == 'L' and buffer[3] == 'U' and buffer[4] == 'E') /* VALUE */ { /* We add back in one because we will need to search for END */ - memcached_server_response_increment(ptr); - return textual_value_fetch(ptr, buffer, result); + memcached_server_response_increment(instance); + return textual_value_fetch(instance, buffer, result); } // VERSION else if (buffer[1] == 'E' and buffer[2] == 'R' and buffer[3] == 'S' and buffer[4] == 'I' and buffer[5] == 'O' and buffer[6] == 'N') /* VERSION */ { + /* Find the space, and then move one past it to copy version */ + char *response_ptr= index(buffer, ' '); + response_ptr++; + + long int version= strtol(response_ptr, (char **)NULL, 10); + if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0) + { + instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX; + return memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version")); + } + instance->major_version= uint8_t(version); + + response_ptr= index(response_ptr, '.'); + response_ptr++; + + version= strtol(response_ptr, (char **)NULL, 10); + if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX) + { + instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX; + return memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version")); + } + instance->minor_version= uint8_t(version); + + response_ptr= index(response_ptr, '.'); + response_ptr++; + + version= strtol(response_ptr, (char **)NULL, 10); + if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX) + { + instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX; + return memcached_set_error(*instance, MEMCACHED_PROTOCOL_ERROR, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version")); + } + instance->micro_version= uint8_t(version); + return MEMCACHED_SUCCESS; } } @@ -229,7 +261,7 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta // STAT if (buffer[1] == 'T' and buffer[2] == 'A' and buffer[3] == 'T') /* STORED STATS */ { - memcached_server_response_increment(ptr); + memcached_server_response_increment(instance); return MEMCACHED_STAT; } // SERVER_ERROR @@ -242,12 +274,18 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta return MEMCACHED_SERVER_ERROR; } - if (total_read > memcached_literal_param_size("SERVER_ERROR object too large for cache") and + if (total_read >= memcached_literal_param_size("SERVER_ERROR object too large for cache") and (memcmp(buffer, memcached_literal_param("SERVER_ERROR object too large for cache")) == 0)) { return MEMCACHED_E2BIG; } + if (total_read >= memcached_literal_param_size("SERVER_ERROR out of memory storing object") and + (memcmp(buffer, memcached_literal_param("SERVER_ERROR out of memory storing object")) == 0)) + { + return MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE; + } + // Move past the basic error message and whitespace char *startptr= buffer + memcached_literal_param_size("SERVER_ERROR"); if (startptr[0] == ' ') @@ -258,7 +296,7 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta char *endptr= startptr; while (*endptr != '\r' && *endptr != '\n') endptr++; - return memcached_set_error(*ptr, MEMCACHED_SERVER_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr)); + return memcached_set_error(*instance, MEMCACHED_SERVER_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr)); } // STORED else if (buffer[1] == 'T' and buffer[2] == 'O' and buffer[3] == 'R') // and buffer[4] == 'E' and buffer[5] == 'D') @@ -313,6 +351,11 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta return MEMCACHED_PROTOCOL_ERROR; } #endif + // ERROR + else if (buffer[1] == 'R' and buffer[2] == 'R' and buffer[3] == 'O' and buffer[4] == 'R') + { + return MEMCACHED_ERROR; + } // EXISTS else if (buffer[1] == 'X' and buffer[2] == 'I' and buffer[3] == 'S' and buffer[4] == 'T' and buffer[5] == 'S') { @@ -337,7 +380,7 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta if (buffer[1] == 'T' and buffer[2] == 'E' and buffer[3] == 'M') { /* We add back in one because we will need to search for END */ - memcached_server_response_increment(ptr); + memcached_server_response_increment(instance); return MEMCACHED_ITEM; } } @@ -370,16 +413,18 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta if (auto_return_value == ULLONG_MAX and errno == ERANGE) { - return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, + result->numeric_value= UINT64_MAX; + return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("Numeric response was out of range")); } else if (errno == EINVAL) { - return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, + result->numeric_value= UINT64_MAX; + return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("Numeric response was out of range")); } - numeric_value= uint64_t(auto_return_value); + result->numeric_value= uint64_t(auto_return_value); WATCHPOINT_STRING(buffer); return MEMCACHED_SUCCESS; @@ -394,11 +439,11 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta if (total_read >= sizeof("STORSTORED") -1) { fprintf(stderr, "%s:%d '%s', %.*s\n", __FILE__, __LINE__, - buffer, MEMCACHED_MAX_BUFFER, ptr->read_buffer); + buffer, MEMCACHED_MAX_BUFFER, instance->read_buffer); assert(memcmp(buffer,"STORSTORED", sizeof("STORSTORED") -1)); } #endif - return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, + return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, buffer, total_read); } @@ -498,21 +543,20 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan case PROTOCOL_BINARY_CMD_INCREMENT: case PROTOCOL_BINARY_CMD_DECREMENT: { - if (bodylen != sizeof(uint64_t) or buffer_length != sizeof(uint64_t)) + if (bodylen != sizeof(uint64_t)) { + result->numeric_value= UINT64_MAX; return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT); } - WATCHPOINT_ASSERT(bodylen == buffer_length); uint64_t val; if ((rc= memcached_safe_read(ptr, &val, sizeof(val))) != MEMCACHED_SUCCESS) { - WATCHPOINT_ERROR(rc); + result->numeric_value= UINT64_MAX; return MEMCACHED_UNKNOWN_READ_FAILURE; } - val= memcached_ntohll(val); - memcpy(buffer, &val, sizeof(val)); + result->numeric_value= memcached_ntohll(val); } break; @@ -683,8 +727,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan static memcached_return_t _read_one_response(memcached_server_write_instance_st ptr, char *buffer, const size_t buffer_length, - memcached_result_st *result, - uint64_t& numeric_value) + memcached_result_st *result) { memcached_server_response_decrement(ptr); @@ -701,15 +744,11 @@ static memcached_return_t _read_one_response(memcached_server_write_instance_st } else { - rc= textual_read_one_response(ptr, buffer, buffer_length, result, numeric_value); + rc= textual_read_one_response(ptr, buffer, buffer_length, result); assert(rc != MEMCACHED_PROTOCOL_ERROR); } - if (rc == MEMCACHED_UNKNOWN_READ_FAILURE or - rc == MEMCACHED_READ_FAILURE or - rc == MEMCACHED_PROTOCOL_ERROR or - rc == MEMCACHED_CLIENT_ERROR or - rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE) + if (memcached_fatal(rc)) { memcached_io_reset(ptr); } @@ -720,7 +759,6 @@ static memcached_return_t _read_one_response(memcached_server_write_instance_st memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr, memcached_result_st *result) { - uint64_t numeric_value; char buffer[SMALL_STRING_LEN]; if (memcached_is_udp(ptr->root)) @@ -729,22 +767,20 @@ memcached_return_t memcached_read_one_response(memcached_server_write_instance_s } - return _read_one_response(ptr, buffer, sizeof(buffer), result, numeric_value); + return _read_one_response(ptr, buffer, sizeof(buffer), result); } memcached_return_t memcached_response(memcached_server_write_instance_st ptr, - char *buffer, size_t buffer_length, memcached_result_st *result) { - uint64_t numeric_value; + char buffer[1024]; - return memcached_response(ptr, buffer, buffer_length, result, numeric_value); + return memcached_response(ptr, buffer, sizeof(buffer), result); } memcached_return_t memcached_response(memcached_server_write_instance_st ptr, char *buffer, size_t buffer_length, - memcached_result_st *result, - uint64_t& numeric_value) + memcached_result_st *result) { if (memcached_is_udp(ptr->root)) { @@ -771,17 +807,10 @@ memcached_return_t memcached_response(memcached_server_write_instance_st ptr, while (memcached_server_response_count(ptr) > 1) { - memcached_return_t rc= _read_one_response(ptr, buffer, buffer_length, junked_result_ptr, numeric_value); + memcached_return_t rc= _read_one_response(ptr, buffer, buffer_length, junked_result_ptr); // @TODO should we return an error on another but a bad read case? - if (rc != MEMCACHED_END and - rc != MEMCACHED_STORED and - rc != MEMCACHED_SUCCESS and - rc != MEMCACHED_STAT and - rc != MEMCACHED_DELETED and - rc != MEMCACHED_NOTFOUND and - rc != MEMCACHED_NOTSTORED and - rc != MEMCACHED_DATA_EXISTS) + if (memcached_fatal(rc)) { memcached_result_free(junked_result_ptr); return rc; @@ -790,5 +819,5 @@ memcached_return_t memcached_response(memcached_server_write_instance_st ptr, memcached_result_free(junked_result_ptr); } - return _read_one_response(ptr, buffer, buffer_length, result, numeric_value); + return _read_one_response(ptr, buffer, buffer_length, result); }