Abstraction (which will save us merge hell with 1.2).
[awesomized/libmemcached] / libmemcached / response.cc
index faf20ff94149f15448c4c6a36a7d0d456419cb37..cf7ed41e6936492c0d6c44c3532b4cfdfb74b646 100644 (file)
@@ -38,7 +38,7 @@
 #include <libmemcached/common.h>
 #include <libmemcached/string.hpp>
 
-static memcached_return_t textual_value_fetch(memcached_server_write_instance_st instance,
+static memcached_return_t textual_value_fetch(org::libmemcached::Instance* instance,
                                               char *buffer,
                                               memcached_result_st *result)
 {
@@ -207,7 +207,7 @@ read_error:
   return MEMCACHED_PARTIAL_READ;
 }
 
-static memcached_return_t textual_read_one_response(memcached_server_write_instance_st instance,
+static memcached_return_t textual_read_one_response(org::libmemcached::Instance* instance,
                                                     char *buffer, const size_t buffer_length,
                                                     memcached_result_st *result)
 {
@@ -236,9 +236,9 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
       {
         /* 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);
+        char *endptr;
+        long int version= strtol(response_ptr, &endptr, 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;
@@ -246,10 +246,8 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
         }
         instance->major_version= uint8_t(version);
 
-        response_ptr= index(response_ptr, '.');
-        response_ptr++;
-
-        version= strtol(response_ptr, (char **)NULL, 10);
+        endptr++;
+        version= strtol(endptr, &endptr, 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;
@@ -257,10 +255,8 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
         }
         instance->minor_version= uint8_t(version);
 
-        response_ptr= index(response_ptr, '.');
-        response_ptr++;
-
-        version= strtol(response_ptr, (char **)NULL, 10);
+        endptr++;
+        version= strtol(endptr, &endptr, 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;
@@ -420,7 +416,17 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
           and buffer[6] == '_'
           and buffer[7] == 'E' and buffer[8] == 'R' and buffer[9] == 'R' and buffer[10] == 'O' and buffer[11] == 'R')
       {
-        return MEMCACHED_CLIENT_ERROR;
+        // Move past the basic error message and whitespace
+        char *startptr= buffer + memcached_literal_param_size("CLIENT_ERROR");
+        if (startptr[0] == ' ')
+        {
+          startptr++;
+        }
+
+        char *endptr= startptr;
+        while (*endptr != '\r' && *endptr != '\n') endptr++;
+
+        return memcached_set_error(*instance, MEMCACHED_CLIENT_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr));
       }
     }
     break;
@@ -474,7 +480,7 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
                              buffer, total_read);
 }
 
-static memcached_return_t binary_read_one_response(memcached_server_write_instance_st instance,
+static memcached_return_t binary_read_one_response(org::libmemcached::Instance* instance,
                                                    char *buffer, const size_t buffer_length,
                                                    memcached_result_st *result)
 {
@@ -588,6 +594,21 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
       break;
 
     case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS:
+      {
+        if (header.response.keylen != 0 || bodylen + 1 > buffer_length)
+        {
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+        else
+        {
+          if ((rc= memcached_safe_read(instance, buffer, bodylen)) != MEMCACHED_SUCCESS)
+          {
+            return MEMCACHED_UNKNOWN_READ_FAILURE;
+          }
+        }
+      }
+      break;
+
     case PROTOCOL_BINARY_CMD_VERSION:
       {
         char version_buffer[32]; // @todo document this number
@@ -598,8 +619,8 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
           return MEMCACHED_UNKNOWN_READ_FAILURE;
         }
 
-        char *p;
-        long int version= strtol(version_buffer, &p, 10);
+        char *endptr;
+        long int version= strtol(version_buffer, &endptr, 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;
@@ -607,16 +628,18 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         }
         instance->major_version= uint8_t(version);
 
-        version= strtol(p +1, &p, 10);
+        endptr++;
+        version= strtol(endptr, &endptr, 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_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
+          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version"));
         }
         instance->minor_version= uint8_t(version);
 
-        version= strtol(p + 1, NULL, 10);
-        if (errno == ERANGE)
+        endptr++;
+        version= strtol(endptr, &endptr, 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_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
@@ -774,7 +797,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
   return rc;
 }
 
-static memcached_return_t _read_one_response(memcached_server_write_instance_st instance,
+static memcached_return_t _read_one_response(org::libmemcached::Instance* instance,
                                              char *buffer, const size_t buffer_length,
                                              memcached_result_st *result)
 {
@@ -782,7 +805,7 @@ static memcached_return_t _read_one_response(memcached_server_write_instance_st
 
   if (result == NULL)
   {
-    memcached_st *root= (memcached_st *)instance->root;
+    Memcached *root= (Memcached *)instance->root;
     result = &root->result;
   }
 
@@ -804,7 +827,7 @@ static memcached_return_t _read_one_response(memcached_server_write_instance_st
   return rc;
 }
 
-memcached_return_t memcached_read_one_response(memcached_server_write_instance_st instance,
+memcached_return_t memcached_read_one_response(org::libmemcached::Instance* instance,
                                                memcached_result_st *result)
 {
   char buffer[SMALL_STRING_LEN];
@@ -818,7 +841,7 @@ memcached_return_t memcached_read_one_response(memcached_server_write_instance_s
   return _read_one_response(instance, buffer, sizeof(buffer), result);
 }
 
-memcached_return_t memcached_response(memcached_server_write_instance_st instance,
+memcached_return_t memcached_response(org::libmemcached::Instance* instance,
                                       memcached_result_st *result)
 {
   char buffer[1024];
@@ -826,7 +849,7 @@ memcached_return_t memcached_response(memcached_server_write_instance_st instanc
   return memcached_response(instance, buffer, sizeof(buffer), result);
 }
 
-memcached_return_t memcached_response(memcached_server_write_instance_st instance,
+memcached_return_t memcached_response(org::libmemcached::Instance* instance,
                                       char *buffer, size_t buffer_length,
                                       memcached_result_st *result)
 {