Diff for /embedaddon/php/ext/mysqlnd/mysqlnd_net.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 23:47:58 version 1.1.1.2, 2012/05/29 12:34:41
Line 12 Line 12
   | obtain it through the world-wide-web, please send a note to          |    | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |    | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+    +----------------------------------------------------------------------+
  | Authors: Georg Richter <georg@mysql.com>                             |  | Authors: Andrey Hristov <andrey@mysql.com>                           |
  |          Andrey Hristov <andrey@mysql.com>                           | 
   |          Ulf Wendel <uwendel@mysql.com>                              |    |          Ulf Wendel <uwendel@mysql.com>                              |
     |          Georg Richter <georg@mysql.com>                             |
   +----------------------------------------------------------------------+    +----------------------------------------------------------------------+
 */  */
   
   /* $Id$ */
 #include "php.h"  #include "php.h"
 #include "php_globals.h"  #include "php_globals.h"
 #include "mysqlnd.h"  #include "mysqlnd.h"
Line 24 Line 26
 #include "mysqlnd_wireprotocol.h"  #include "mysqlnd_wireprotocol.h"
 #include "mysqlnd_statistics.h"  #include "mysqlnd_statistics.h"
 #include "mysqlnd_debug.h"  #include "mysqlnd_debug.h"
#include "ext/standard/sha1.h"#include "mysqlnd_ext_plugin.h"
 #include "php_network.h"  #include "php_network.h"
 #include "zend_ini.h"  #include "zend_ini.h"
 #ifdef MYSQLND_COMPRESSION_ENABLED  #ifdef MYSQLND_COMPRESSION_ENABLED
Line 59  mysqlnd_set_sock_no_delay(php_stream * stream TSRMLS_D Line 61  mysqlnd_set_sock_no_delay(php_stream * stream TSRMLS_D
 /* }}} */  /* }}} */
   
   
/* {{{ mysqlnd_net::network_read *//* {{{ mysqlnd_net::network_read_ex */
 static enum_func_status  static enum_func_status
MYSQLND_METHOD(mysqlnd_net, network_read)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC)MYSQLND_METHOD(mysqlnd_net, network_read_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
                                                                                          MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
 {  {
         enum_func_status return_value = PASS;          enum_func_status return_value = PASS;
         size_t to_read = count, ret;          size_t to_read = count, ret;
        size_t old_chunk_size = conn->net->stream->chunk_size;        size_t old_chunk_size = net->stream->chunk_size;
        DBG_ENTER("mysqlnd_net::network_read");        zend_uchar * p = buffer;
        DBG_INF_FMT("count=%u", count);
        conn->net->stream->chunk_size = MIN(to_read, conn->net->options.net_read_buffer_size);        DBG_ENTER("mysqlnd_net::network_read_ex");
         DBG_INF_FMT("count="MYSQLND_SZ_T_SPEC, count);
 
         net->stream->chunk_size = MIN(to_read, net->options.net_read_buffer_size);
         while (to_read) {          while (to_read) {
                if (!(ret = php_stream_read(conn->net->stream, (char *) buffer, to_read))) {                if (!(ret = php_stream_read(net->stream, (char *) p, to_read))) {
                         DBG_ERR_FMT("Error while reading header from socket");                          DBG_ERR_FMT("Error while reading header from socket");
                         return_value = FAIL;                          return_value = FAIL;
                         break;                          break;
                 }                  }
                buffer += ret;                p += ret;
                 to_read -= ret;                  to_read -= ret;
         }          }
        MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_BYTES_RECEIVED, count - to_read);        MYSQLND_INC_CONN_STATISTIC_W_VALUE(stats, STAT_BYTES_RECEIVED, count - to_read);
        conn->net->stream->chunk_size = old_chunk_size;        net->stream->chunk_size = old_chunk_size;
         DBG_RETURN(return_value);          DBG_RETURN(return_value);
 }  }
 /* }}} */  /* }}} */
   
   
/* {{{ mysqlnd_net::network_write *//* {{{ mysqlnd_net::network_write_ex */
 static size_t  static size_t
MYSQLND_METHOD(mysqlnd_net, network_write)(MYSQLND * const conn, const zend_uchar * const buf, size_t count TSRMLS_DC)MYSQLND_METHOD(mysqlnd_net, network_write_ex)(MYSQLND_NET * const net, const zend_uchar * const buffer, const size_t count,
                                                                                           MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
 {  {
         size_t ret;          size_t ret;
        DBG_ENTER("mysqlnd_net::network_write");        DBG_ENTER("mysqlnd_net::network_write_ex");
        ret = php_stream_write(conn->net->stream, (char *)buf, count);        ret = php_stream_write(net->stream, (char *)buffer, count);
         DBG_RETURN(ret);          DBG_RETURN(ret);
 }  }
 /* }}} */  /* }}} */
   
   /* {{{ mysqlnd_net::open_pipe */
   static enum_func_status
   MYSQLND_METHOD(mysqlnd_net, open_pipe)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
                                                                              const zend_bool persistent,
                                                                              MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
   {
   #if PHP_API_VERSION < 20100412
           unsigned int streams_options = ENFORCE_SAFE_MODE;
   #else
           unsigned int streams_options = 0;
   #endif
           DBG_ENTER("mysqlnd_net::open_pipe");
           if (persistent) {
                   streams_options |= STREAM_OPEN_PERSISTENT;
           }
           streams_options |= IGNORE_URL;
           net->stream = php_stream_open_wrapper((char*) scheme + sizeof("pipe://") - 1, "r+", streams_options, NULL);
           if (!net->stream) {
                   SET_CLIENT_ERROR(*error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "Unknown errror while connecting");
                   DBG_RETURN(FAIL);
           }
           /*
             Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
             be registered as resource (in EG(regular_list). So far, so good. However, it won't be
             unregistered yntil the script ends. So, we need to take care of that.
           */
           net->stream->in_free = 1;
           zend_hash_index_del(&EG(regular_list), net->stream->rsrc_id);
           net->stream->in_free = 0;
   
           DBG_RETURN(PASS);
   }
   /* }}} */
   
/* {{{ mysqlnd_net::connect */
 /* {{{ mysqlnd_net::open_tcp_or_unix */
 static enum_func_status  static enum_func_status
MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const scheme, size_t scheme_len, zend_bool persistent, char **errstr, int * errcode TSRMLS_DC)MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
                                                                                           const zend_bool persistent,
                                                                                           MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
 {  {
 #if PHP_API_VERSION < 20100412  #if PHP_API_VERSION < 20100412
         unsigned int streams_options = ENFORCE_SAFE_MODE;          unsigned int streams_options = ENFORCE_SAFE_MODE;
Line 110  MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net Line 152  MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net
         unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT;          unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT;
         char * hashed_details = NULL;          char * hashed_details = NULL;
         int hashed_details_len = 0;          int hashed_details_len = 0;
           char * errstr = NULL;
           int errcode = 0;
         struct timeval tv;          struct timeval tv;
         DBG_ENTER("mysqlnd_net::connect");  
   
           DBG_ENTER("mysqlnd_net::open_tcp_or_unix");
   
         if (persistent) {          if (persistent) {
                hashed_details_len = spprintf(&hashed_details, 0, "%p", net);                hashed_details_len = mnd_sprintf(&hashed_details, 0, "%p", net);
                 DBG_INF_FMT("hashed_details=%s", hashed_details);                  DBG_INF_FMT("hashed_details=%s", hashed_details);
         }          }
   
         net->packet_no = net->compressed_envelope_packet_no = 0;  
   
         if (net->stream) {  
                 /* close before opening a new one */  
                 DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);  
                 if (net->persistent) {  
                         php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);  
                 } else {  
                         php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);  
                 }  
                 net->stream = NULL;  
         }  
   
         if (net->options.timeout_connect) {          if (net->options.timeout_connect) {
                 tv.tv_sec = net->options.timeout_connect;                  tv.tv_sec = net->options.timeout_connect;
                 tv.tv_usec = 0;                  tv.tv_usec = 0;
Line 139  MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net Line 171  MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net
         DBG_INF_FMT("calling php_stream_xport_create");          DBG_INF_FMT("calling php_stream_xport_create");
         net->stream = php_stream_xport_create(scheme, scheme_len, streams_options, streams_flags,          net->stream = php_stream_xport_create(scheme, scheme_len, streams_options, streams_flags,
                                                                                   hashed_details, (net->options.timeout_connect) ? &tv : NULL,                                                                                    hashed_details, (net->options.timeout_connect) ? &tv : NULL,
                                                                                  NULL /*ctx*/, errstr, errcode);                                                                                  NULL /*ctx*/, &errstr, &errcode);
        if (errstr || !net->stream) {
        if (*errstr || !net->stream) {                DBG_ERR("Error");
                 if (hashed_details) {                  if (hashed_details) {
                        efree(hashed_details); /* allocated by spprintf */                        mnd_sprintf_free(hashed_details);
                 }                  }
                *errcode = CR_CONNECTION_ERROR;                errcode = CR_CONNECTION_ERROR;
                 SET_CLIENT_ERROR(*error_info, errcode? errcode:CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, errstr);
                 if (errstr) {
                         /* no mnd_ since we don't allocate it */
                         efree(errstr);
                 }
                 DBG_RETURN(FAIL);                  DBG_RETURN(FAIL);
         }          }
   
         if (hashed_details) {          if (hashed_details) {
                 /*                  /*
                   If persistent, the streams register it in EG(persistent_list).                    If persistent, the streams register it in EG(persistent_list).
Line 171  MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net Line 207  MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net
                 /* Shut-up the streams, they don't know what they are doing */                  /* Shut-up the streams, they don't know what they are doing */
                 net->stream->__exposed = 1;                  net->stream->__exposed = 1;
 #endif  #endif
                efree(hashed_details);                mnd_sprintf_free(hashed_details);
         }          }
   
         /*          /*
           Streams are not meant for C extensions! Thus we need a hack. Every connected stream will            Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
           be registered as resource (in EG(regular_list). So far, so good. However, it won't be            be registered as resource (in EG(regular_list). So far, so good. However, it won't be
          unregistered till the script ends. So, we need to take care of that.          unregistered yntil the script ends. So, we need to take care of that.
         */          */
         net->stream->in_free = 1;          net->stream->in_free = 1;
         zend_hash_index_del(&EG(regular_list), net->stream->rsrc_id);          zend_hash_index_del(&EG(regular_list), net->stream->rsrc_id);
         net->stream->in_free = 0;          net->stream->in_free = 0;
   
        if (!net->options.timeout_read) {        DBG_RETURN(PASS);
                /* should always happen because read_timeout cannot be set via API */}
                net->options.timeout_read = (unsigned int) MYSQLND_G(net_read_timeout);/* }}} */
        }
 
 /* {{{ mysqlnd_net::connect_ex */
 static void
 MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt)(MYSQLND_NET * const net,
                                                                                                   const char * const scheme, const size_t scheme_len,
                                                                                                   MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
 {
         DBG_ENTER("mysqlnd_net::post_connect_set_opt");
         if (net->options.timeout_read) {          if (net->options.timeout_read) {
                   struct timeval tv;
                 DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->options.timeout_read);                  DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->options.timeout_read);
                 tv.tv_sec = net->options.timeout_read;                  tv.tv_sec = net->options.timeout_read;
                 tv.tv_usec = 0;                  tv.tv_usec = 0;
Line 198  MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net Line 244  MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net
                 mysqlnd_set_sock_no_delay(net->stream TSRMLS_CC);                  mysqlnd_set_sock_no_delay(net->stream TSRMLS_CC);
         }          }
   
        {        DBG_VOID_RETURN;
                unsigned int buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/}
                net->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC);/* }}} */
        } 
   
   
        DBG_RETURN(PASS);/* {{{ mysqlnd_net::connect_ex */
 static enum_func_status
 MYSQLND_METHOD(mysqlnd_net, connect_ex)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
                                                                                 const zend_bool persistent,
                                                                                 MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
 {
         enum_func_status ret = FAIL;
         func_mysqlnd_net__open_stream open_stream = NULL;
         DBG_ENTER("mysqlnd_net::connect_ex");
 
         net->packet_no = net->compressed_envelope_packet_no = 0;
 
         net->m.close_stream(net, conn_stats, error_info TSRMLS_CC);
 
         open_stream = (scheme_len > (sizeof("pipe://") - 1) && !memcmp(scheme, "pipe://", sizeof("pipe://") - 1))? net->m.open_pipe:
                                                                                                                                                                                                                            net->m.open_tcp_or_unix;
 
         if (PASS == (ret = open_stream(net, scheme, scheme_len, persistent, conn_stats, error_info TSRMLS_CC))) {
                 net->m.post_connect_set_opt(net, scheme, scheme_len, conn_stats, error_info TSRMLS_CC);
         }
 
         DBG_RETURN(ret);
 }  }
 /* }}} */  /* }}} */
   
Line 218  MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net Line 284  MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net
 #define STORE_HEADER_SIZE(safe_storage, buffer)  COPY_HEADER((safe_storage), (buffer))  #define STORE_HEADER_SIZE(safe_storage, buffer)  COPY_HEADER((safe_storage), (buffer))
 #define RESTORE_HEADER_SIZE(buffer, safe_storage) STORE_HEADER_SIZE((safe_storage), (buffer))  #define RESTORE_HEADER_SIZE(buffer, safe_storage) STORE_HEADER_SIZE((safe_storage), (buffer))
   
/* {{{ mysqlnd_net::send */
 /* {{{ mysqlnd_net::send_ex */
 /*  /*
  IMPORTANT : It's expected that buf has place in the beginning for MYSQLND_HEADER_SIZE !!!!  IMPORTANT : It's expected that buffer has place in the beginning for MYSQLND_HEADER_SIZE !!!!
                           This is done for performance reasons in the caller of this function.                            This is done for performance reasons in the caller of this function.
                           Otherwise we will have to do send two TCP packets, or do new alloc and memcpy.                            Otherwise we will have to do send two TCP packets, or do new alloc and memcpy.
                           Neither are quick, thus the clients of this function are obligated to do                            Neither are quick, thus the clients of this function are obligated to do
                           what they are asked for.                            what they are asked for.
   
   `count` is actually the length of the payload data. Thus :    `count` is actually the length of the payload data. Thus :
  count + MYSQLND_HEADER_SIZE = sizeof(buf) (not the pointer but the actual buffer)  count + MYSQLND_HEADER_SIZE = sizeof(buffer) (not the pointer but the actual buffer)
 */  */
size_tstatic size_t
MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn, char * const buf, size_t count TSRMLS_DC)MYSQLND_METHOD(mysqlnd_net, send_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
                                                                          MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
 {  {
         zend_uchar safe_buf[((MYSQLND_HEADER_SIZE) + (sizeof(zend_uchar)) - 1) / (sizeof(zend_uchar))];          zend_uchar safe_buf[((MYSQLND_HEADER_SIZE) + (sizeof(zend_uchar)) - 1) / (sizeof(zend_uchar))];
        zend_uchar *safe_storage = safe_buf;        zend_uchar * safe_storage = safe_buf;
        MYSQLND_NET *net = conn->net;        size_t bytes_sent, packets_sent = 1;
        size_t old_chunk_size = net->stream->chunk_size; 
        size_t ret, packets_sent = 1; 
         size_t left = count;          size_t left = count;
        zend_uchar *p = (zend_uchar *) buf;        zend_uchar * p = (zend_uchar *) buffer;
         zend_uchar * compress_buf = NULL;          zend_uchar * compress_buf = NULL;
         size_t to_be_sent;          size_t to_be_sent;
   
        DBG_ENTER("mysqlnd_net::send");        DBG_ENTER("mysqlnd_net::send_ex");
        DBG_INF_FMT("conn=%llu count=%lu compression=%u", conn->thread_id, count, net->compressed);        DBG_INF_FMT("count=" MYSQLND_SZ_T_SPEC " compression=%u", count, net->compressed);
   
         net->stream->chunk_size = MYSQLND_MAX_PACKET_SIZE;  
   
         if (net->compressed == TRUE) {          if (net->compressed == TRUE) {
                 size_t comp_buf_size = MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE + MIN(left, MYSQLND_MAX_PACKET_SIZE);                  size_t comp_buf_size = MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE + MIN(left, MYSQLND_MAX_PACKET_SIZE);
                 DBG_INF_FMT("compress_buf_size="MYSQLND_SZ_T_SPEC, comp_buf_size);                  DBG_INF_FMT("compress_buf_size="MYSQLND_SZ_T_SPEC, comp_buf_size);
Line 280  MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn Line 344  MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn
                         int3store(compress_buf, payload_size);                          int3store(compress_buf, payload_size);
                         int1store(compress_buf + 3, net->packet_no);                          int1store(compress_buf + 3, net->packet_no);
                         DBG_INF_FMT("writing "MYSQLND_SZ_T_SPEC" bytes to the network", payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE);                          DBG_INF_FMT("writing "MYSQLND_SZ_T_SPEC" bytes to the network", payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE);
                        ret = conn->net->m.network_write(conn, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE TSRMLS_CC);                        bytes_sent = net->m.network_write_ex(net, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE,
                                                                                                  conn_stats, error_info TSRMLS_CC);
                         net->compressed_envelope_packet_no++;                          net->compressed_envelope_packet_no++;
   #if WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY    #if WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY
                         if (res == Z_OK) {                          if (res == Z_OK) {
Line 311  MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn Line 376  MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn
                         STORE_HEADER_SIZE(safe_storage, p);                          STORE_HEADER_SIZE(safe_storage, p);
                         int3store(p, to_be_sent);                          int3store(p, to_be_sent);
                         int1store(p + 3, net->packet_no);                          int1store(p + 3, net->packet_no);
                        ret = conn->net->m.network_write(conn, p, to_be_sent + MYSQLND_HEADER_SIZE TSRMLS_CC);                        bytes_sent = net->m.network_write_ex(net, p, to_be_sent + MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC);
                         RESTORE_HEADER_SIZE(p, safe_storage);                          RESTORE_HEADER_SIZE(p, safe_storage);
                         net->compressed_envelope_packet_no++;                          net->compressed_envelope_packet_no++;
                 }                  }
Line 327  MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn Line 392  MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn
                   indeed it then loop once more, then to_be_sent will become 0, left will stay 0. Empty                    indeed it then loop once more, then to_be_sent will become 0, left will stay 0. Empty
                   packet will be sent and this loop will end.                    packet will be sent and this loop will end.
                 */                  */
        } while (ret && (left > 0 || to_be_sent == MYSQLND_MAX_PACKET_SIZE));        } while (bytes_sent && (left > 0 || to_be_sent == MYSQLND_MAX_PACKET_SIZE));
   
         DBG_INF_FMT("packet_size="MYSQLND_SZ_T_SPEC" packet_no=%u", left, net->packet_no);          DBG_INF_FMT("packet_size="MYSQLND_SZ_T_SPEC" packet_no=%u", left, net->packet_no);
         /* Even for zero size payload we have to send a packet */  
         if (!ret) {  
                 DBG_ERR_FMT("Can't %u send bytes", count);  
                 conn->state = CONN_QUIT_SENT;  
                 SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);  
         }  
   
        MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn->stats,        MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats,
                         STAT_BYTES_SENT, count + packets_sent * MYSQLND_HEADER_SIZE,                          STAT_BYTES_SENT, count + packets_sent * MYSQLND_HEADER_SIZE,
                         STAT_PROTOCOL_OVERHEAD_OUT, packets_sent * MYSQLND_HEADER_SIZE,                          STAT_PROTOCOL_OVERHEAD_OUT, packets_sent * MYSQLND_HEADER_SIZE,
                         STAT_PACKETS_SENT, packets_sent);                          STAT_PACKETS_SENT, packets_sent);
   
         net->stream->chunk_size = old_chunk_size;  
         if (compress_buf) {          if (compress_buf) {
                 mnd_efree(compress_buf);                  mnd_efree(compress_buf);
         }          }
        DBG_RETURN(ret);
         /* Even for zero size payload we have to send a packet */
         if (!bytes_sent) {
                 DBG_ERR_FMT("Can't %u send bytes", count);
                 SET_CLIENT_ERROR(*error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
         }
         DBG_RETURN(bytes_sent);
 }  }
 /* }}} */  /* }}} */
   
Line 416  mysqlnd_create_read_buffer(size_t count TSRMLS_DC) Line 480  mysqlnd_create_read_buffer(size_t count TSRMLS_DC)
 /* }}} */  /* }}} */
   
   
/* {{{ mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer *//* {{{ mysqlnd_net::read_compressed_packet_from_stream_and_fill_read_buffer */
 static enum_func_status  static enum_func_status
mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(MYSQLND * conn, size_t net_payload_size TSRMLS_DC)MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buffer)
                 (MYSQLND_NET * net, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
 {  {
         MYSQLND_NET * net = conn->net;  
         size_t decompressed_size;          size_t decompressed_size;
         enum_func_status ret = PASS;          enum_func_status ret = PASS;
         zend_uchar * compressed_data = NULL;          zend_uchar * compressed_data = NULL;
         zend_uchar comp_header[COMPRESSED_HEADER_SIZE];          zend_uchar comp_header[COMPRESSED_HEADER_SIZE];
        DBG_ENTER("mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer");        DBG_ENTER("mysqlnd_net::read_compressed_packet_from_stream_and_fill_read_buffe");
   
         /* Read the compressed header */          /* Read the compressed header */
        if (FAIL == conn->net->m.network_read(conn, comp_header, COMPRESSED_HEADER_SIZE TSRMLS_CC)) {        if (FAIL == net->m.network_read_ex(net, comp_header, COMPRESSED_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) {
                 DBG_RETURN(FAIL);                  DBG_RETURN(FAIL);
         }          }
         decompressed_size = uint3korr(comp_header);          decompressed_size = uint3korr(comp_header);
Line 438  mysqlnd_read_compressed_packet_from_stream_and_fill_re Line 502  mysqlnd_read_compressed_packet_from_stream_and_fill_re
   
         if (decompressed_size) {          if (decompressed_size) {
                 compressed_data = mnd_emalloc(net_payload_size);                  compressed_data = mnd_emalloc(net_payload_size);
                if (FAIL == conn->net->m.network_read(conn, compressed_data, net_payload_size TSRMLS_CC)) {                if (FAIL == net->m.network_read_ex(net, compressed_data, net_payload_size, conn_stats, error_info TSRMLS_CC)) {
                         ret = FAIL;                          ret = FAIL;
                         goto end;                          goto end;
                 }                  }
Line 450  mysqlnd_read_compressed_packet_from_stream_and_fill_re Line 514  mysqlnd_read_compressed_packet_from_stream_and_fill_re
         } else {          } else {
                 DBG_INF_FMT("The server decided not to compress the data. Our job is easy. Copying %u bytes", net_payload_size);                  DBG_INF_FMT("The server decided not to compress the data. Our job is easy. Copying %u bytes", net_payload_size);
                 net->uncompressed_data = mysqlnd_create_read_buffer(net_payload_size TSRMLS_CC);                  net->uncompressed_data = mysqlnd_create_read_buffer(net_payload_size TSRMLS_CC);
                if (FAIL == conn->net->m.network_read(conn, net->uncompressed_data->data, net_payload_size TSRMLS_CC)) {                if (FAIL == net->m.network_read_ex(net, net->uncompressed_data->data, net_payload_size, conn_stats, error_info TSRMLS_CC)) {
                         ret = FAIL;                          ret = FAIL;
                         goto end;                          goto end;
                 }                  }
Line 467  end: Line 531  end:
   
 /* {{{ mysqlnd_net::decode */  /* {{{ mysqlnd_net::decode */
 static enum_func_status  static enum_func_status
MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncompressed_data, size_t uncompressed_data_len,MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncompressed_data, const size_t uncompressed_data_len,
                                                                        const zend_uchar * const compressed_data, size_t compressed_data_len TSRMLS_DC)                                                                        const zend_uchar * const compressed_data, const size_t compressed_data_len TSRMLS_DC)
 {  {
 #ifdef MYSQLND_COMPRESSION_ENABLED  #ifdef MYSQLND_COMPRESSION_ENABLED
         int error;          int error;
Line 492  MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncom Line 556  MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncom
 /* {{{ mysqlnd_net::encode */  /* {{{ mysqlnd_net::encode */
 static enum_func_status  static enum_func_status
 MYSQLND_METHOD(mysqlnd_net, encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len,  MYSQLND_METHOD(mysqlnd_net, encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len,
                                                                        const zend_uchar * const uncompressed_data, size_t uncompressed_data_len TSRMLS_DC)                                                                        const zend_uchar * const uncompressed_data, const size_t uncompressed_data_len TSRMLS_DC)
 {  {
 #ifdef MYSQLND_COMPRESSION_ENABLED  #ifdef MYSQLND_COMPRESSION_ENABLED
         int error;          int error;
Line 516  MYSQLND_METHOD(mysqlnd_net, encode)(zend_uchar * compr Line 580  MYSQLND_METHOD(mysqlnd_net, encode)(zend_uchar * compr
 /* }}} */  /* }}} */
   
   
/* {{{ mysqlnd_net::receive *//* {{{ mysqlnd_net::receive_ex */
 static enum_func_status  static enum_func_status
MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC)MYSQLND_METHOD(mysqlnd_net, receive_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count
                                                                                 MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
 {  {
         size_t to_read = count;          size_t to_read = count;
         zend_uchar * p = buffer;          zend_uchar * p = buffer;
         MYSQLND_NET * net = conn->net;  
   
        DBG_ENTER("mysqlnd_net::receive");        DBG_ENTER("mysqlnd_net::receive_ex");
 #ifdef MYSQLND_COMPRESSION_ENABLED  #ifdef MYSQLND_COMPRESSION_ENABLED
         if (net->compressed) {          if (net->compressed) {
                 if (net->uncompressed_data) {                  if (net->uncompressed_data) {
Line 546  MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, z Line 610  MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, z
                         size_t net_payload_size;                          size_t net_payload_size;
                         zend_uchar packet_no;                          zend_uchar packet_no;
   
                        if (FAIL == net->m.network_read(conn, net_header, MYSQLND_HEADER_SIZE TSRMLS_CC)) {                        if (FAIL == net->m.network_read_ex(net, net_header, MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) {
                                 DBG_RETURN(FAIL);                                  DBG_RETURN(FAIL);
                         }                          }
                         net_payload_size = uint3korr(net_header);                          net_payload_size = uint3korr(net_header);
Line 564  MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, z Line 628  MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, z
                         DBG_INF_FMT("HEADER: hwd_packet_no=%u size=%3u", packet_no, (unsigned long) net_payload_size);                          DBG_INF_FMT("HEADER: hwd_packet_no=%u size=%3u", packet_no, (unsigned long) net_payload_size);
 #endif  #endif
                         /* Now let's read from the wire, decompress it and fill the read buffer */                          /* Now let's read from the wire, decompress it and fill the read buffer */
                        mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(conn, net_payload_size TSRMLS_CC);                        net->m.read_compressed_packet_from_stream_and_fill_read_buffer(net, net_payload_size, conn_stats, error_info TSRMLS_CC);
   
                         /*                          /*
                           Now a bit of recursion - read from the read buffer,                            Now a bit of recursion - read from the read buffer,
Line 572  MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, z Line 636  MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, z
                           is not enough, then the recursive call will try to                            is not enough, then the recursive call will try to
                           satisfy it until it is satisfied.                            satisfy it until it is satisfied.
                         */                          */
                        DBG_RETURN(net->m.receive(conn, p, to_read TSRMLS_CC));                        DBG_RETURN(net->m.receive_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC));
                 }                  }
                 DBG_RETURN(PASS);                  DBG_RETURN(PASS);
         }          }
 #endif /* MYSQLND_COMPRESSION_ENABLED */  #endif /* MYSQLND_COMPRESSION_ENABLED */
        DBG_RETURN(net->m.network_read(conn, p, to_read TSRMLS_CC));        DBG_RETURN(net->m.network_read_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC));
 }  }
 /* }}} */  /* }}} */
   
Line 668  MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND Line 732  MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND
                 case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:                  case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
                         net->options.ssl_verify_peer = value? ((*(zend_bool *)value)? TRUE:FALSE): FALSE;                          net->options.ssl_verify_peer = value? ((*(zend_bool *)value)? TRUE:FALSE): FALSE;
                         break;                          break;
 #ifdef WHEN_SUPPORTED_BY_MYSQLI  
                 case MYSQL_OPT_READ_TIMEOUT:                  case MYSQL_OPT_READ_TIMEOUT:
                         DBG_INF("MYSQL_OPT_READ_TIMEOUT");  
                         net->options.timeout_read = *(unsigned int*) value;                          net->options.timeout_read = *(unsigned int*) value;
                         break;                          break;
   #ifdef WHEN_SUPPORTED_BY_MYSQLI
                 case MYSQL_OPT_WRITE_TIMEOUT:                  case MYSQL_OPT_WRITE_TIMEOUT:
                         DBG_INF("MYSQL_OPT_WRITE_TIMEOUT");  
                         net->options.timeout_write = *(unsigned int*) value;                          net->options.timeout_write = *(unsigned int*) value;
                         break;                          break;
 #endif  #endif
Line 744  static enum_func_status Line 806  static enum_func_status
 MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)  MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
 {  {
 #ifdef MYSQLND_SSL_SUPPORTED  #ifdef MYSQLND_SSL_SUPPORTED
        php_stream_context *context = php_stream_context_alloc();        php_stream_context *context = php_stream_context_alloc(TSRMLS_C);
         DBG_ENTER("mysqlnd_net::enable_ssl");          DBG_ENTER("mysqlnd_net::enable_ssl");
         if (!context) {          if (!context) {
                 DBG_RETURN(FAIL);                  DBG_RETURN(FAIL);
Line 753  MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET *  Line 815  MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * 
         if (net->options.ssl_key) {          if (net->options.ssl_key) {
                 zval key_zval;                  zval key_zval;
                 ZVAL_STRING(&key_zval, net->options.ssl_key, 0);                  ZVAL_STRING(&key_zval, net->options.ssl_key, 0);
                 DBG_INF("key");  
                 php_stream_context_set_option(context, "ssl", "local_pk", &key_zval);                  php_stream_context_set_option(context, "ssl", "local_pk", &key_zval);
         }          }
         if (net->options.ssl_verify_peer) {          if (net->options.ssl_verify_peer) {
                 zval verify_peer_zval;                  zval verify_peer_zval;
                 ZVAL_TRUE(&verify_peer_zval);                  ZVAL_TRUE(&verify_peer_zval);
                 DBG_INF("verify peer");  
                 php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval);                  php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval);
         }          }
         if (net->options.ssl_cert) {          if (net->options.ssl_cert) {
                 zval cert_zval;                  zval cert_zval;
                 ZVAL_STRING(&cert_zval, net->options.ssl_cert, 0);                  ZVAL_STRING(&cert_zval, net->options.ssl_cert, 0);
                 DBG_INF_FMT("local_cert=%s", net->options.ssl_cert);  
                 php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval);                  php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval);
                 if (!net->options.ssl_key) {                  if (!net->options.ssl_key) {
                         php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval);                          php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval);
Line 774  MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET *  Line 833  MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * 
         if (net->options.ssl_ca) {          if (net->options.ssl_ca) {
                 zval cafile_zval;                  zval cafile_zval;
                 ZVAL_STRING(&cafile_zval, net->options.ssl_ca, 0);                  ZVAL_STRING(&cafile_zval, net->options.ssl_ca, 0);
                 DBG_INF_FMT("cafile=%s", net->options.ssl_ca);  
                 php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval);                  php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval);
         }          }
         if (net->options.ssl_capath) {          if (net->options.ssl_capath) {
                 zval capath_zval;                  zval capath_zval;
                 ZVAL_STRING(&capath_zval, net->options.ssl_capath, 0);                  ZVAL_STRING(&capath_zval, net->options.ssl_capath, 0);
                 DBG_INF_FMT("capath=%s", net->options.ssl_capath);  
                 php_stream_context_set_option(context, "ssl", "cafile", &capath_zval);                  php_stream_context_set_option(context, "ssl", "cafile", &capath_zval);
         }          }
         if (net->options.ssl_passphrase) {          if (net->options.ssl_passphrase) {
Line 791  MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET *  Line 848  MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * 
         if (net->options.ssl_cipher) {          if (net->options.ssl_cipher) {
                 zval cipher_zval;                  zval cipher_zval;
                 ZVAL_STRING(&cipher_zval, net->options.ssl_cipher, 0);                  ZVAL_STRING(&cipher_zval, net->options.ssl_cipher, 0);
                 DBG_INF_FMT("ciphers=%s", net->options.ssl_cipher);  
                 php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval);                  php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval);
         }          }
         php_stream_context_set(net->stream, context);          php_stream_context_set(net->stream, context);
Line 838  MYSQLND_METHOD(mysqlnd_net, disable_ssl)(MYSQLND_NET * Line 894  MYSQLND_METHOD(mysqlnd_net, disable_ssl)(MYSQLND_NET *
 /* }}} */  /* }}} */
   
   
/* {{{ mysqlnd_net::set_client_option *//* {{{ mysqlnd_net::free_contents */
 static void  static void
 MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC)  MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC)
 {  {
Line 875  MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET Line 931  MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET
 }  }
 /* }}} */  /* }}} */
   
 static   
 MYSQLND_CLASS_METHODS_START(mysqlnd_net)  
         MYSQLND_METHOD(mysqlnd_net, connect),  
         MYSQLND_METHOD(mysqlnd_net, send),  
         MYSQLND_METHOD(mysqlnd_net, receive),  
         MYSQLND_METHOD(mysqlnd_net, set_client_option),  
         MYSQLND_METHOD(mysqlnd_net, network_read),  
         MYSQLND_METHOD(mysqlnd_net, network_write),  
         MYSQLND_METHOD(mysqlnd_net, decode),  
         MYSQLND_METHOD(mysqlnd_net, encode),  
         MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data),  
         MYSQLND_METHOD(mysqlnd_net, free_contents),  
         MYSQLND_METHOD(mysqlnd_net, enable_ssl),  
         MYSQLND_METHOD(mysqlnd_net, disable_ssl)  
 MYSQLND_CLASS_METHODS_END;  
   
/* {{{ mysqlnd_net::close_stream */
/* {{{ mysqlnd_net_init */static void
PHPAPI MYSQLND_NET *MYSQLND_METHOD(mysqlnd_net, close_stream)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
mysqlnd_net_init(zend_bool persistent TSRMLS_DC) 
 {  {
        size_t alloc_size = sizeof(MYSQLND_NET) + mysqlnd_plugin_count() * sizeof(void *);        DBG_ENTER("mysqlnd_net::close_stream");
        MYSQLND_NET * net = mnd_pecalloc(1, alloc_size, persistent);        if (net && net->stream) {
                zend_bool pers = net->persistent;
        DBG_ENTER("mysqlnd_net_init");                DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);
        DBG_INF_FMT("persistent=%u", persistent);                if (pers) {
        if (net) {                        if (EG(active)) {
                net->persistent = persistent;                                php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
                net->m = mysqlnd_mysqlnd_net_methods;                        } else {
                                /*
                {                                  otherwise we will crash because the EG(persistent_list) has been freed already,
                        unsigned int buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/                                  before the modules are shut down
                        net->m.set_client_option(net, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size TSRMLS_CC);                                */
                                 php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR);
                         }
                 } else {
                         php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
                 }                  }
                   net->stream = NULL;
         }          }
        DBG_RETURN(net);
         DBG_VOID_RETURN;
 }  }
 /* }}} */  /* }}} */
   
   
/* {{{ mysqlnd_net_free *//* {{{ mysqlnd_net::init */
PHPAPI voidstatic enum_func_status
mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC)MYSQLND_METHOD(mysqlnd_net, init)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
 {  {
        DBG_ENTER("mysqlnd_net_free");        unsigned int buf_size;
         DBG_ENTER("mysqlnd_net::init");
   
           buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/
           net->m.set_client_option(net, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size TSRMLS_CC);
   
           buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/
           net->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC);
   
           buf_size = MYSQLND_G(net_read_timeout); /* this is long, cast to unsigned int*/
           net->m.set_client_option(net, MYSQL_OPT_READ_TIMEOUT, (char *)&buf_size TSRMLS_CC);
   
           DBG_RETURN(PASS);
   }
   /* }}} */
   
   
   /* {{{ mysqlnd_net::dtor */
   static void
   MYSQLND_METHOD(mysqlnd_net, dtor)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
   {
           DBG_ENTER("mysqlnd_net::dtor");
         if (net) {          if (net) {
                 zend_bool pers = net->persistent;                  zend_bool pers = net->persistent;
        
                 net->m.free_contents(net TSRMLS_CC);                  net->m.free_contents(net TSRMLS_CC);
                   net->m.close_stream(net, stats, error_info TSRMLS_CC);
                 if (net->cmd_buffer.buffer) {                  if (net->cmd_buffer.buffer) {
                         DBG_INF("Freeing cmd buffer");                          DBG_INF("Freeing cmd buffer");
                         mnd_pefree(net->cmd_buffer.buffer, pers);                          mnd_pefree(net->cmd_buffer.buffer, pers);
                         net->cmd_buffer.buffer = NULL;                          net->cmd_buffer.buffer = NULL;
                 }                  }
                 if (net->stream) {  
                         DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);  
                         if (pers) {  
                                 php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);  
                         } else {  
                                 php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);  
                         }  
                         net->stream = NULL;  
                 }  
                 mnd_pefree(net, pers);                  mnd_pefree(net, pers);
         }          }
         DBG_VOID_RETURN;          DBG_VOID_RETURN;
Line 946  mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC) Line 1004  mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC)
 /* }}} */  /* }}} */
   
   
/* {{{ _mysqlnd_plugin_get_plugin_net_data */MYSQLND_CLASS_METHODS_START(mysqlnd_net)
PHPAPI void ** _mysqlnd_plugin_get_plugin_net_data(const MYSQLND_NET * net, unsigned int plugin_id TSRMLS_DC)        MYSQLND_METHOD(mysqlnd_net, init),
         MYSQLND_METHOD(mysqlnd_net, dtor),
         MYSQLND_METHOD(mysqlnd_net, connect_ex),
         MYSQLND_METHOD(mysqlnd_net, close_stream),
         MYSQLND_METHOD(mysqlnd_net, open_pipe),
         MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix),
         NULL, /* unused 1 */
         NULL, /* unused 2 */
         MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt),
         MYSQLND_METHOD(mysqlnd_net, set_client_option),
         MYSQLND_METHOD(mysqlnd_net, decode),
         MYSQLND_METHOD(mysqlnd_net, encode),
         MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data),
         MYSQLND_METHOD(mysqlnd_net, free_contents),
         MYSQLND_METHOD(mysqlnd_net, enable_ssl),
         MYSQLND_METHOD(mysqlnd_net, disable_ssl),
         MYSQLND_METHOD(mysqlnd_net, network_read_ex),
         MYSQLND_METHOD(mysqlnd_net, network_write_ex),
         MYSQLND_METHOD(mysqlnd_net, send_ex),
         MYSQLND_METHOD(mysqlnd_net, receive_ex),
 #ifdef MYSQLND_COMPRESSION_ENABLED
         MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buffer)
 #else
         NULL
 #endif
 MYSQLND_CLASS_METHODS_END;
 
 
 /* {{{ mysqlnd_net_init */
 PHPAPI MYSQLND_NET *
 mysqlnd_net_init(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
 {  {
        DBG_ENTER("_mysqlnd_plugin_get_plugin_net_data");        MYSQLND_NET * net;
        DBG_INF_FMT("plugin_id=%u", plugin_id);        DBG_ENTER("mysqlnd_net_init");
        if (!net || plugin_id >= mysqlnd_plugin_count()) {        net = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_io_channel(persistent, stats, error_info TSRMLS_CC);
                return NULL;        DBG_RETURN(net);
        } 
        DBG_RETURN((void *)((char *)net + sizeof(MYSQLND_NET) + plugin_id * sizeof(void *))); 
 }  }
 /* }}} */  /* }}} */
   
   
/* {{{ mysqlnd_net_get_methods *//* {{{ mysqlnd_net_free */
PHPAPI struct st_mysqlnd_net_methods *PHPAPI void
mysqlnd_net_get_methods()mysqlnd_net_free(MYSQLND_NET * const net, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
 {  {
        return &mysqlnd_mysqlnd_net_methods;        DBG_ENTER("mysqlnd_net_free");
         if (net) {
                 net->m.dtor(net, stats, error_info TSRMLS_CC);
         }
         DBG_VOID_RETURN;
 }  }
 /* }}} */  /* }}} */
   
   
   
 /*  /*

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>