PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/mysqlnd - mysqlnd_net.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 336 399 84.2 %
Date: 2014-07-23 Functions: 19 23 82.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 5                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 2006-2013 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Authors: Georg Richter <georg@mysql.com>                             |
      16             :   |          Andrey Hristov <andrey@mysql.com>                           |
      17             :   |          Ulf Wendel <uwendel@mysql.com>                              |
      18             :   +----------------------------------------------------------------------+
      19             : */
      20             : #include "php.h"
      21             : #include "php_globals.h"
      22             : #include "mysqlnd.h"
      23             : #include "mysqlnd_priv.h"
      24             : #include "mysqlnd_wireprotocol.h"
      25             : #include "mysqlnd_statistics.h"
      26             : #include "mysqlnd_debug.h"
      27             : #include "ext/standard/sha1.h"
      28             : #include "php_network.h"
      29             : #include "zend_ini.h"
      30             : #ifdef MYSQLND_COMPRESSION_ENABLED
      31             : #include <zlib.h>
      32             : #endif
      33             : 
      34             : #ifndef PHP_WIN32
      35             : #include <netinet/tcp.h>
      36             : #else
      37             : #include <winsock.h>
      38             : #endif
      39             : 
      40             : 
      41             : /* {{{ mysqlnd_set_sock_no_delay */
      42             : static int
      43           2 : mysqlnd_set_sock_no_delay(php_stream * stream TSRMLS_DC)
      44             : {
      45             : 
      46           2 :         int socketd = ((php_netstream_data_t*)stream->abstract)->socket;
      47           2 :         int ret = SUCCESS;
      48           2 :         int flag = 1;
      49           2 :         int result = setsockopt(socketd, IPPROTO_TCP,  TCP_NODELAY, (char *) &flag, sizeof(int));
      50             : 
      51           2 :         DBG_ENTER("mysqlnd_set_sock_no_delay");
      52             : 
      53           2 :         if (result == -1) {
      54           0 :                 ret = FAILURE;
      55             :         }
      56             : 
      57           2 :         DBG_RETURN(ret);
      58             : }
      59             : /* }}} */
      60             : 
      61             : 
      62             : /* {{{ mysqlnd_net::network_read */
      63             : static enum_func_status
      64      524536 : MYSQLND_METHOD(mysqlnd_net, network_read)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC)
      65             : {
      66      524536 :         enum_func_status return_value = PASS;
      67      524536 :         size_t to_read = count, ret;
      68      524536 :         size_t old_chunk_size = conn->net->stream->chunk_size;
      69      524536 :         DBG_ENTER("mysqlnd_net::network_read");
      70      524536 :         DBG_INF_FMT("count=%u", count);
      71      524536 :         conn->net->stream->chunk_size = MIN(to_read, conn->net->options.net_read_buffer_size);
      72     1573670 :         while (to_read) {
      73      524601 :                 if (!(ret = php_stream_read(conn->net->stream, (char *) buffer, to_read))) {
      74           3 :                         DBG_ERR_FMT("Error while reading header from socket");
      75           3 :                         return_value = FAIL;
      76           3 :                         break;
      77             :                 }
      78      524598 :                 buffer += ret;
      79      524598 :                 to_read -= ret;
      80             :         }
      81      524536 :         MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_BYTES_RECEIVED, count - to_read);
      82      524536 :         conn->net->stream->chunk_size = old_chunk_size;
      83      524536 :         DBG_RETURN(return_value);
      84             : }
      85             : /* }}} */
      86             : 
      87             : 
      88             : /* {{{ mysqlnd_net::network_write */
      89             : static size_t
      90       38034 : MYSQLND_METHOD(mysqlnd_net, network_write)(MYSQLND * const conn, const zend_uchar * const buf, size_t count TSRMLS_DC)
      91             : {
      92             :         size_t ret;
      93       38034 :         DBG_ENTER("mysqlnd_net::network_write");
      94       38034 :         ret = php_stream_write(conn->net->stream, (char *)buf, count);
      95       38034 :         DBG_RETURN(ret);
      96             : }
      97             : /* }}} */
      98             : 
      99             : 
     100             : 
     101             : /* {{{ mysqlnd_net::connect */
     102             : static enum_func_status
     103        1829 : 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)
     104             : {
     105             : #if PHP_API_VERSION < 20100412
     106        1829 :         unsigned int streams_options = ENFORCE_SAFE_MODE;
     107             : #else
     108             :         unsigned int streams_options = 0;
     109             : #endif
     110        1829 :         unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT;
     111        1829 :         char * hashed_details = NULL;
     112        1829 :         int hashed_details_len = 0;
     113             :         struct timeval tv;
     114        1829 :         DBG_ENTER("mysqlnd_net::connect");
     115             : 
     116        1829 :         if (persistent) {
     117        1093 :                 hashed_details_len = spprintf(&hashed_details, 0, "%p", net);
     118        1093 :                 DBG_INF_FMT("hashed_details=%s", hashed_details);
     119             :         }
     120             : 
     121        1829 :         net->packet_no = net->compressed_envelope_packet_no = 0;
     122             : 
     123        1829 :         if (net->stream) {
     124             :                 /* close before opening a new one */
     125           2 :                 DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);
     126           2 :                 if (net->persistent) {
     127           2 :                         php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
     128             :                 } else {
     129           0 :                         php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
     130             :                 }
     131           2 :                 net->stream = NULL;
     132             :         }
     133             : 
     134        1829 :         if (net->options.timeout_connect) {
     135         239 :                 tv.tv_sec = net->options.timeout_connect;
     136         239 :                 tv.tv_usec = 0;
     137             :         }
     138             : 
     139        1829 :         DBG_INF_FMT("calling php_stream_xport_create");
     140        1829 :         net->stream = php_stream_xport_create(scheme, scheme_len, streams_options, streams_flags,
     141             :                                                                                   hashed_details, (net->options.timeout_connect) ? &tv : NULL,
     142             :                                                                                   NULL /*ctx*/, errstr, errcode);
     143             : 
     144        1829 :         if (*errstr || !net->stream) {
     145          14 :                 if (hashed_details) {
     146           2 :                         efree(hashed_details); /* allocated by spprintf */
     147             :                 }
     148          14 :                 *errcode = CR_CONNECTION_ERROR;
     149          14 :                 DBG_RETURN(FAIL);
     150             :         }
     151             : 
     152        1815 :         if (hashed_details) {
     153             :                 /*
     154             :                   If persistent, the streams register it in EG(persistent_list).
     155             :                   This is unwanted. ext/mysql or ext/mysqli are responsible to clean,
     156             :                   whatever they have to.
     157             :                 */
     158             :                 zend_rsrc_list_entry *le;
     159             : 
     160        1091 :                 if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_len + 1, (void*) &le) == SUCCESS) {
     161             :                         /*
     162             :                           in_free will let streams code skip destructing - big HACK,
     163             :                           but STREAMS suck big time regarding persistent streams.
     164             :                           Just not compatible for extensions that need persistency.
     165             :                         */
     166        1091 :                         net->stream->in_free = 1;
     167        1091 :                         zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_len + 1);
     168        1091 :                         net->stream->in_free = 0;
     169             :                 }
     170             : #if ZEND_DEBUG
     171             :                 /* Shut-up the streams, they don't know what they are doing */
     172             :                 net->stream->__exposed = 1;
     173             : #endif
     174        1091 :                 efree(hashed_details);
     175             :         }
     176             :         /*
     177             :           Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
     178             :           be registered as resource (in EG(regular_list). So far, so good. However, it won't be
     179             :           unregistered till the script ends. So, we need to take care of that.
     180             :         */
     181        1815 :         net->stream->in_free = 1;
     182        1815 :         zend_hash_index_del(&EG(regular_list), net->stream->rsrc_id);
     183        1815 :         net->stream->in_free = 0;
     184             : 
     185        1815 :         if (!net->options.timeout_read) {
     186             :                 /* should always happen because read_timeout cannot be set via API */
     187        1813 :                 net->options.timeout_read = (unsigned int) MYSQLND_G(net_read_timeout);
     188             :         }
     189        1815 :         if (net->options.timeout_read) {
     190        1812 :                 DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->options.timeout_read);
     191        1812 :                 tv.tv_sec = net->options.timeout_read;
     192        1812 :                 tv.tv_usec = 0;
     193        1812 :                 php_stream_set_option(net->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
     194             :         }
     195             : 
     196        1815 :         if (!memcmp(scheme, "tcp://", sizeof("tcp://") - 1)) {
     197             :                 /* TCP -> Set TCP_NODELAY */
     198           2 :                 mysqlnd_set_sock_no_delay(net->stream TSRMLS_CC);
     199             :         }
     200             : 
     201             :         {
     202        1815 :                 unsigned int buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/
     203        1815 :                 net->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC);
     204             :         }
     205             : 
     206             : 
     207        1815 :         DBG_RETURN(PASS);
     208             : }
     209             : /* }}} */
     210             : 
     211             : 
     212             : /* We assume that MYSQLND_HEADER_SIZE is 4 bytes !! */
     213             : #define COPY_HEADER(T,A)  do { \
     214             :                 *(((char *)(T)))   = *(((char *)(A)));\
     215             :                 *(((char *)(T))+1) = *(((char *)(A))+1);\
     216             :                 *(((char *)(T))+2) = *(((char *)(A))+2);\
     217             :                 *(((char *)(T))+3) = *(((char *)(A))+3); } while (0)
     218             : #define STORE_HEADER_SIZE(safe_storage, buffer)  COPY_HEADER((safe_storage), (buffer))
     219             : #define RESTORE_HEADER_SIZE(buffer, safe_storage) STORE_HEADER_SIZE((safe_storage), (buffer))
     220             : 
     221             : /* {{{ mysqlnd_net::send */
     222             : /*
     223             :   IMPORTANT : It's expected that buf has place in the beginning for MYSQLND_HEADER_SIZE !!!!
     224             :                           This is done for performance reasons in the caller of this function.
     225             :                           Otherwise we will have to do send two TCP packets, or do new alloc and memcpy.
     226             :                           Neither are quick, thus the clients of this function are obligated to do
     227             :                           what they are asked for.
     228             : 
     229             :   `count` is actually the length of the payload data. Thus :
     230             :   count + MYSQLND_HEADER_SIZE = sizeof(buf) (not the pointer but the actual buffer)
     231             : */
     232             : size_t
     233       38034 : MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn, char * const buf, size_t count TSRMLS_DC)
     234             : {
     235             :         zend_uchar safe_buf[((MYSQLND_HEADER_SIZE) + (sizeof(zend_uchar)) - 1) / (sizeof(zend_uchar))];
     236       38034 :         zend_uchar *safe_storage = safe_buf;
     237       38034 :         MYSQLND_NET *net = conn->net;
     238       38034 :         size_t old_chunk_size = net->stream->chunk_size;
     239       38034 :         size_t ret, packets_sent = 1;
     240       38034 :         size_t left = count;
     241       38034 :         zend_uchar *p = (zend_uchar *) buf;
     242       38034 :         zend_uchar * compress_buf = NULL;
     243             :         size_t to_be_sent;
     244             : 
     245       38034 :         DBG_ENTER("mysqlnd_net::send");
     246       38034 :         DBG_INF_FMT("conn=%llu count=%lu compression=%u", conn->thread_id, count, net->compressed);
     247             : 
     248       38034 :         net->stream->chunk_size = MYSQLND_MAX_PACKET_SIZE;
     249             : 
     250       38034 :         if (net->compressed == TRUE) {
     251          13 :                 size_t comp_buf_size = MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE + MIN(left, MYSQLND_MAX_PACKET_SIZE);
     252          13 :                 DBG_INF_FMT("compress_buf_size="MYSQLND_SZ_T_SPEC, comp_buf_size);
     253          13 :                 compress_buf = mnd_emalloc(comp_buf_size);
     254             :         }
     255             : 
     256             :         do {
     257       38034 :                 to_be_sent = MIN(left, MYSQLND_MAX_PACKET_SIZE);
     258             : #ifdef MYSQLND_COMPRESSION_ENABLED
     259       38034 :                 if (net->compressed == TRUE) {
     260             :                         /* here we need to compress the data and then write it, first comes the compressed header */
     261          13 :                         size_t tmp_complen = to_be_sent;
     262             :                         size_t payload_size;
     263          13 :                         zend_uchar * uncompressed_payload = p; /* should include the header */
     264             : 
     265          13 :                         STORE_HEADER_SIZE(safe_storage, uncompressed_payload);
     266          13 :                         int3store(uncompressed_payload, to_be_sent);
     267          13 :                         int1store(uncompressed_payload + 3, net->packet_no);
     268          13 :                         if (PASS == net->m.encode((compress_buf + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE), &tmp_complen,
     269             :                                                                            uncompressed_payload, to_be_sent + MYSQLND_HEADER_SIZE TSRMLS_CC))
     270             :                         {
     271           2 :                                 int3store(compress_buf + MYSQLND_HEADER_SIZE, to_be_sent + MYSQLND_HEADER_SIZE);
     272           2 :                                 payload_size = tmp_complen;
     273             :                         } else {
     274          11 :                                 int3store(compress_buf + MYSQLND_HEADER_SIZE, 0);
     275          11 :                                 memcpy(compress_buf + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, uncompressed_payload, to_be_sent + MYSQLND_HEADER_SIZE);
     276          11 :                                 payload_size = to_be_sent + MYSQLND_HEADER_SIZE;
     277             :                         }
     278          13 :                         RESTORE_HEADER_SIZE(uncompressed_payload, safe_storage);
     279             : 
     280          13 :                         int3store(compress_buf, payload_size);
     281          13 :                         int1store(compress_buf + 3, net->packet_no);
     282          13 :                         DBG_INF_FMT("writing "MYSQLND_SZ_T_SPEC" bytes to the network", payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE);
     283          13 :                         ret = conn->net->m.network_write(conn, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE TSRMLS_CC);
     284          13 :                         net->compressed_envelope_packet_no++;
     285             :   #if WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY
     286             :                         if (res == Z_OK) {
     287             :                                 size_t decompressed_size = left + MYSQLND_HEADER_SIZE;
     288             :                                 zend_uchar * decompressed_data = mnd_malloc(decompressed_size);
     289             :                                 int error = net->m.decode(decompressed_data, decompressed_size,
     290             :                                                                                   compress_buf + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, payload_size);
     291             :                                 if (error == Z_OK) {
     292             :                                         int i;
     293             :                                         DBG_INF("success decompressing");
     294             :                                         for (i = 0 ; i < decompressed_size; i++) {
     295             :                                                 if (i && (i % 30 == 0)) {
     296             :                                                         printf("\n\t\t");
     297             :                                                 }
     298             :                                                 printf("%.2X ", (int)*((char*)&(decompressed_data[i])));
     299             :                                                 DBG_INF_FMT("%.2X ", (int)*((char*)&(decompressed_data[i])));
     300             :                                         }
     301             :                                 } else {
     302             :                                         DBG_INF("error decompressing");
     303             :                                 }
     304             :                                 mnd_free(decompressed_data);
     305             :                         }
     306             :   #endif /* WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY */
     307             :                 } else
     308             : #endif /* MYSQLND_COMPRESSION_ENABLED */
     309             :                 {
     310       38021 :                         DBG_INF("no compression");
     311       38021 :                         STORE_HEADER_SIZE(safe_storage, p);
     312       38021 :                         int3store(p, to_be_sent);
     313       38021 :                         int1store(p + 3, net->packet_no);
     314       38021 :                         ret = conn->net->m.network_write(conn, p, to_be_sent + MYSQLND_HEADER_SIZE TSRMLS_CC);
     315       38021 :                         RESTORE_HEADER_SIZE(p, safe_storage);
     316       38021 :                         net->compressed_envelope_packet_no++;
     317             :                 }
     318       38034 :                 net->packet_no++;
     319             : 
     320       38034 :                 p += to_be_sent;
     321       38034 :                 left -= to_be_sent;
     322       38034 :                 packets_sent++;
     323             :                 /*
     324             :                   if left is 0 then there is nothing more to send, but if the last packet was exactly 
     325             :                   with the size MYSQLND_MAX_PACKET_SIZE we need to send additional packet, which has
     326             :                   empty payload. Thus if left == 0 we check for to_be_sent being the max size. If it is
     327             :                   indeed it then loop once more, then to_be_sent will become 0, left will stay 0. Empty
     328             :                   packet will be sent and this loop will end.
     329             :                 */
     330       38034 :         } while (ret && (left > 0 || to_be_sent == MYSQLND_MAX_PACKET_SIZE));
     331             : 
     332       38034 :         DBG_INF_FMT("packet_size="MYSQLND_SZ_T_SPEC" packet_no=%u", left, net->packet_no);
     333             :         /* Even for zero size payload we have to send a packet */
     334       38034 :         if (!ret) {
     335          12 :                 DBG_ERR_FMT("Can't %u send bytes", count);
     336          12 :                 conn->state = CONN_QUIT_SENT;
     337          12 :                 SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
     338             :         }
     339             : 
     340       38034 :         MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn->stats,
     341             :                         STAT_BYTES_SENT, count + packets_sent * MYSQLND_HEADER_SIZE,
     342             :                         STAT_PROTOCOL_OVERHEAD_OUT, packets_sent * MYSQLND_HEADER_SIZE,
     343             :                         STAT_PACKETS_SENT, packets_sent);
     344             : 
     345       38034 :         net->stream->chunk_size = old_chunk_size;
     346       38034 :         if (compress_buf) {
     347          13 :                 mnd_efree(compress_buf);
     348             :         }
     349       38034 :         DBG_RETURN(ret);
     350             : }
     351             : /* }}} */
     352             : 
     353             : 
     354             : #ifdef MYSQLND_COMPRESSION_ENABLED
     355             : /* {{{ php_mysqlnd_read_buffer_is_empty */
     356             : static zend_bool
     357       32200 : php_mysqlnd_read_buffer_is_empty(MYSQLND_READ_BUFFER * buffer)
     358             : {
     359       32200 :         return buffer->len? FALSE:TRUE;
     360             : }
     361             : /* }}} */
     362             : 
     363             : 
     364             : /* {{{ php_mysqlnd_read_buffer_read */
     365             : static void
     366       32200 : php_mysqlnd_read_buffer_read(MYSQLND_READ_BUFFER * buffer, size_t count, zend_uchar * dest)
     367             : {
     368       32200 :         if (buffer->len >= count) {
     369       32200 :                 memcpy(dest, buffer->data + buffer->offset, count);
     370       32200 :                 buffer->offset += count;
     371       32200 :                 buffer->len -= count;
     372             :         }
     373       32200 : }
     374             : /* }}} */
     375             : 
     376             : 
     377             : /* {{{ php_mysqlnd_read_buffer_bytes_left */
     378             : static size_t
     379       32204 : php_mysqlnd_read_buffer_bytes_left(MYSQLND_READ_BUFFER * buffer)
     380             : {
     381       32204 :         return buffer->len;
     382             : }
     383             : /* }}} */
     384             : 
     385             : 
     386             : /* {{{ php_mysqlnd_read_buffer_free */
     387             : static void
     388          14 : php_mysqlnd_read_buffer_free(MYSQLND_READ_BUFFER ** buffer TSRMLS_DC)
     389             : {
     390          14 :         DBG_ENTER("php_mysqlnd_read_buffer_free");
     391          14 :         if (*buffer) {
     392          14 :                 mnd_efree((*buffer)->data);
     393          14 :                 mnd_efree(*buffer);
     394          14 :                 *buffer = NULL;
     395             :         }
     396          14 :         DBG_VOID_RETURN;
     397             : }
     398             : /* }}} */
     399             : 
     400             : 
     401             : /* {{{ php_mysqlnd_create_read_buffer */
     402             : static MYSQLND_READ_BUFFER *
     403          14 : mysqlnd_create_read_buffer(size_t count TSRMLS_DC)
     404             : {
     405          14 :         MYSQLND_READ_BUFFER * ret = mnd_emalloc(sizeof(MYSQLND_READ_BUFFER));
     406          14 :         DBG_ENTER("mysqlnd_create_read_buffer");
     407          14 :         ret->is_empty = php_mysqlnd_read_buffer_is_empty;
     408          14 :         ret->read = php_mysqlnd_read_buffer_read;
     409          14 :         ret->bytes_left = php_mysqlnd_read_buffer_bytes_left;
     410          14 :         ret->free_buffer = php_mysqlnd_read_buffer_free;
     411          14 :         ret->data = mnd_emalloc(count);
     412          14 :         ret->size = ret->len = count;
     413          14 :         ret->offset = 0;
     414          14 :         DBG_RETURN(ret);
     415             : }
     416             : /* }}} */
     417             : 
     418             : 
     419             : /* {{{ mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer */
     420             : static enum_func_status
     421          14 : mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(MYSQLND * conn, size_t net_payload_size TSRMLS_DC)
     422             : {
     423          14 :         MYSQLND_NET * net = conn->net;
     424             :         size_t decompressed_size;
     425          14 :         enum_func_status ret = PASS;
     426          14 :         zend_uchar * compressed_data = NULL;
     427             :         zend_uchar comp_header[COMPRESSED_HEADER_SIZE];
     428          14 :         DBG_ENTER("mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer");
     429             : 
     430             :         /* Read the compressed header */
     431          14 :         if (FAIL == conn->net->m.network_read(conn, comp_header, COMPRESSED_HEADER_SIZE TSRMLS_CC)) {
     432           0 :                 DBG_RETURN(FAIL);
     433             :         }
     434          14 :         decompressed_size = uint3korr(comp_header);
     435             : 
     436             :         /* When decompressed_size is 0, then the data is not compressed, and we have wasted 3 bytes */
     437             :         /* we need to decompress the data */
     438             : 
     439          14 :         if (decompressed_size) {
     440          10 :                 compressed_data = mnd_emalloc(net_payload_size);
     441          10 :                 if (FAIL == conn->net->m.network_read(conn, compressed_data, net_payload_size TSRMLS_CC)) {
     442           0 :                         ret = FAIL;
     443           0 :                         goto end;
     444             :                 }
     445          10 :                 net->uncompressed_data = mysqlnd_create_read_buffer(decompressed_size TSRMLS_CC);
     446          10 :                 ret = net->m.decode(net->uncompressed_data->data, decompressed_size, compressed_data, net_payload_size TSRMLS_CC);
     447          10 :                 if (ret == FAIL) {
     448           0 :                         goto end;
     449             :                 }
     450             :         } else {
     451           4 :                 DBG_INF_FMT("The server decided not to compress the data. Our job is easy. Copying %u bytes", net_payload_size);
     452           4 :                 net->uncompressed_data = mysqlnd_create_read_buffer(net_payload_size TSRMLS_CC);
     453           4 :                 if (FAIL == conn->net->m.network_read(conn, net->uncompressed_data->data, net_payload_size TSRMLS_CC)) {
     454           0 :                         ret = FAIL;
     455             :                         goto end;
     456             :                 }
     457             :         }
     458             : end:
     459          14 :         if (compressed_data) {
     460          10 :                 mnd_efree(compressed_data);
     461             :         }
     462          14 :         DBG_RETURN(ret);
     463             : }
     464             : /* }}} */
     465             : #endif /* MYSQLND_COMPRESSION_ENABLED */
     466             : 
     467             : 
     468             : /* {{{ mysqlnd_net::decode */
     469             : static enum_func_status
     470          10 : MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncompressed_data, size_t uncompressed_data_len,
     471             :                                                                         const zend_uchar * const compressed_data, size_t compressed_data_len TSRMLS_DC)
     472             : {
     473             : #ifdef MYSQLND_COMPRESSION_ENABLED
     474             :         int error;
     475          10 :         uLongf tmp_complen = uncompressed_data_len;
     476          10 :         DBG_ENTER("mysqlnd_net::decode");
     477          10 :         error = uncompress(uncompressed_data, &tmp_complen, compressed_data, compressed_data_len);
     478             : 
     479          10 :         DBG_INF_FMT("compressed data: decomp_len=%lu compressed_size="MYSQLND_SZ_T_SPEC, tmp_complen, compressed_data_len);
     480          10 :         if (error != Z_OK) {
     481           0 :                 DBG_INF_FMT("decompression NOT successful. error=%d Z_OK=%d Z_BUF_ERROR=%d Z_MEM_ERROR=%d", error, Z_OK, Z_BUF_ERROR, Z_MEM_ERROR);
     482             :         }
     483          10 :         DBG_RETURN(error == Z_OK? PASS:FAIL);
     484             : #else
     485             :         DBG_ENTER("mysqlnd_net::decode");
     486             :         DBG_RETURN(FAIL);
     487             : #endif
     488             : }
     489             : /* }}} */
     490             : 
     491             : 
     492             : /* {{{ mysqlnd_net::encode */
     493             : static enum_func_status
     494          13 : MYSQLND_METHOD(mysqlnd_net, encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len,
     495             :                                                                         const zend_uchar * const uncompressed_data, size_t uncompressed_data_len TSRMLS_DC)
     496             : {
     497             : #ifdef MYSQLND_COMPRESSION_ENABLED
     498             :         int error;
     499          13 :         uLongf tmp_complen = *compress_buffer_len;
     500          13 :         DBG_ENTER("mysqlnd_net::encode");
     501          13 :         error = compress(compress_buffer, &tmp_complen, uncompressed_data, uncompressed_data_len);
     502             : 
     503          13 :         if (error != Z_OK) {
     504          11 :                 DBG_INF_FMT("compression NOT successful. error=%d Z_OK=%d Z_BUF_ERROR=%d Z_MEM_ERROR=%d", error, Z_OK, Z_BUF_ERROR, Z_MEM_ERROR);
     505             :         } else {
     506           2 :                 *compress_buffer_len = tmp_complen;
     507           2 :                 DBG_INF_FMT("compression successful. compressed size=%lu", tmp_complen);
     508             :         }
     509             :         
     510          13 :         DBG_RETURN(error == Z_OK? PASS:FAIL);
     511             : #else
     512             :         DBG_ENTER("mysqlnd_net::encode");
     513             :         DBG_RETURN(FAIL);
     514             : #endif
     515             : }
     516             : /* }}} */
     517             : 
     518             : 
     519             : /* {{{ mysqlnd_net::receive */
     520             : static enum_func_status
     521      556704 : MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC)
     522             : {
     523      556704 :         size_t to_read = count;
     524      556704 :         zend_uchar * p = buffer;
     525      556704 :         MYSQLND_NET * net = conn->net;
     526             : 
     527      556704 :         DBG_ENTER("mysqlnd_net::receive");
     528             : #ifdef MYSQLND_COMPRESSION_ENABLED
     529      556704 :         if (net->compressed) {
     530       32210 :                 if (net->uncompressed_data) {
     531       32200 :                         size_t to_read_from_buffer = MIN(net->uncompressed_data->bytes_left(net->uncompressed_data), to_read);
     532       32200 :                         DBG_INF_FMT("reading %u from uncompressed_data buffer", to_read_from_buffer);
     533       32200 :                         if (to_read_from_buffer) {
     534       32200 :                                 net->uncompressed_data->read(net->uncompressed_data, to_read_from_buffer, (zend_uchar *) p);
     535       32200 :                                 p += to_read_from_buffer;
     536       32200 :                                 to_read -= to_read_from_buffer;
     537             :                         }
     538       32200 :                         DBG_INF_FMT("left %u to read", to_read);
     539       32200 :                         if (TRUE == net->uncompressed_data->is_empty(net->uncompressed_data)) {
     540             :                                 /* Everything was consumed. This should never happen here, but for security */
     541          14 :                                 net->uncompressed_data->free_buffer(&net->uncompressed_data TSRMLS_CC);
     542             :                         }
     543             :                 }
     544       32210 :                 if (to_read) {
     545             :                         zend_uchar net_header[MYSQLND_HEADER_SIZE];
     546             :                         size_t net_payload_size;
     547             :                         zend_uchar packet_no;
     548             : 
     549          14 :                         if (FAIL == net->m.network_read(conn, net_header, MYSQLND_HEADER_SIZE TSRMLS_CC)) {
     550           0 :                                 DBG_RETURN(FAIL);
     551             :                         }
     552          14 :                         net_payload_size = uint3korr(net_header);
     553          14 :                         packet_no = uint1korr(net_header + 3);
     554          14 :                         if (net->compressed_envelope_packet_no != packet_no) {
     555           0 :                                 DBG_ERR_FMT("Transport level: packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
     556           0 :                                                         net->compressed_envelope_packet_no, packet_no, net_payload_size);
     557             : 
     558           0 :                                 php_error(E_WARNING, "Packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
     559           0 :                                                   net->compressed_envelope_packet_no, packet_no, net_payload_size);
     560           0 :                                 DBG_RETURN(FAIL);
     561             :                         }
     562          14 :                         net->compressed_envelope_packet_no++;
     563             : #ifdef MYSQLND_DUMP_HEADER_N_BODY
     564             :                         DBG_INF_FMT("HEADER: hwd_packet_no=%u size=%3u", packet_no, (unsigned long) net_payload_size);
     565             : #endif
     566             :                         /* Now let's read from the wire, decompress it and fill the read buffer */
     567          14 :                         mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(conn, net_payload_size TSRMLS_CC);
     568             : 
     569             :                         /*
     570             :                           Now a bit of recursion - read from the read buffer,
     571             :                           if the data which we have just read from the wire
     572             :                           is not enough, then the recursive call will try to
     573             :                           satisfy it until it is satisfied.
     574             :                         */
     575          14 :                         DBG_RETURN(net->m.receive(conn, p, to_read TSRMLS_CC));
     576             :                 }
     577       32196 :                 DBG_RETURN(PASS);
     578             :         }
     579             : #endif /* MYSQLND_COMPRESSION_ENABLED */
     580      524494 :         DBG_RETURN(net->m.network_read(conn, p, to_read TSRMLS_CC));
     581             : }
     582             : /* }}} */
     583             : 
     584             : 
     585             : /* {{{ mysqlnd_net::set_client_option */
     586             : static enum_func_status
     587        3968 : MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND_NET * const net, enum mysqlnd_option option, const char * const value TSRMLS_DC)
     588             : {
     589        3968 :         DBG_ENTER("mysqlnd_net::set_client_option");
     590        3968 :         DBG_INF_FMT("option=%u", option);
     591        3968 :         switch (option) {
     592             :                 case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
     593        1894 :                         DBG_INF("MYSQLND_OPT_NET_CMD_BUFFER_SIZE");
     594        1894 :                         if (*(unsigned int*) value < MYSQLND_NET_CMD_BUFFER_MIN_SIZE) {
     595           0 :                                 DBG_RETURN(FAIL);
     596             :                         }
     597        1894 :                         net->cmd_buffer.length = *(unsigned int*) value;
     598        1894 :                         DBG_INF_FMT("new_length=%u", net->cmd_buffer.length);
     599        1894 :                         if (!net->cmd_buffer.buffer) {
     600        1894 :                                 net->cmd_buffer.buffer = mnd_pemalloc(net->cmd_buffer.length, net->persistent);
     601             :                         } else {
     602           0 :                                 net->cmd_buffer.buffer = mnd_perealloc(net->cmd_buffer.buffer, net->cmd_buffer.length, net->persistent);
     603             :                         }
     604        1894 :                         break;
     605             :                 case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
     606        1815 :                         DBG_INF("MYSQLND_OPT_NET_READ_BUFFER_SIZE");
     607        1815 :                         net->options.net_read_buffer_size = *(unsigned int*) value;
     608        1815 :                         DBG_INF_FMT("new_length=%u", net->options.net_read_buffer_size);
     609        1815 :                         break;
     610             :                 case MYSQL_OPT_CONNECT_TIMEOUT:
     611         241 :                         DBG_INF("MYSQL_OPT_CONNECT_TIMEOUT");
     612         241 :                         net->options.timeout_connect = *(unsigned int*) value;
     613         241 :                         break;
     614             :                 case MYSQLND_OPT_SSL_KEY:
     615             :                         {
     616           3 :                                 zend_bool pers = net->persistent;
     617           3 :                                 if (net->options.ssl_key) {
     618           0 :                                         mnd_pefree(net->options.ssl_key, pers);
     619             :                                 }
     620           3 :                                 net->options.ssl_key = value? mnd_pestrdup(value, pers) : NULL;
     621           3 :                                 break;
     622             :                         }
     623             :                 case MYSQLND_OPT_SSL_CERT:
     624             :                         {
     625           3 :                                 zend_bool pers = net->persistent;
     626           3 :                                 if (net->options.ssl_cert) {
     627           0 :                                         mnd_pefree(net->options.ssl_cert, pers);
     628             :                                 }
     629           3 :                                 net->options.ssl_cert = value? mnd_pestrdup(value, pers) : NULL;
     630           3 :                                 break;
     631             :                         }
     632             :                 case MYSQLND_OPT_SSL_CA:
     633             :                         {
     634           3 :                                 zend_bool pers = net->persistent;
     635           3 :                                 if (net->options.ssl_ca) {
     636           0 :                                         mnd_pefree(net->options.ssl_ca, pers);
     637             :                                 }
     638           3 :                                 net->options.ssl_ca = value? mnd_pestrdup(value, pers) : NULL;
     639           3 :                                 break;
     640             :                         }
     641             :                 case MYSQLND_OPT_SSL_CAPATH:
     642             :                         {
     643           3 :                                 zend_bool pers = net->persistent;
     644           3 :                                 if (net->options.ssl_capath) {
     645           0 :                                         mnd_pefree(net->options.ssl_capath, pers);
     646             :                                 }
     647           3 :                                 net->options.ssl_capath = value? mnd_pestrdup(value, pers) : NULL;
     648           3 :                                 break;
     649             :                         }
     650             :                 case MYSQLND_OPT_SSL_CIPHER:
     651             :                         {
     652           3 :                                 zend_bool pers = net->persistent;
     653           3 :                                 if (net->options.ssl_cipher) {
     654           0 :                                         mnd_pefree(net->options.ssl_cipher, pers);
     655             :                                 }
     656           3 :                                 net->options.ssl_cipher = value? mnd_pestrdup(value, pers) : NULL;
     657           3 :                                 break;
     658             :                         }
     659             :                 case MYSQLND_OPT_SSL_PASSPHRASE:
     660             :                         {
     661           0 :                                 zend_bool pers = net->persistent;
     662           0 :                                 if (net->options.ssl_passphrase) {
     663           0 :                                         mnd_pefree(net->options.ssl_passphrase, pers);
     664             :                                 }
     665           0 :                                 net->options.ssl_passphrase = value? mnd_pestrdup(value, pers) : NULL;
     666           0 :                                 break;
     667             :                         }
     668             :                 case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
     669           3 :                         net->options.ssl_verify_peer = value? ((*(zend_bool *)value)? TRUE:FALSE): FALSE;
     670           3 :                         break;
     671             : #ifdef WHEN_SUPPORTED_BY_MYSQLI
     672             :                 case MYSQL_OPT_READ_TIMEOUT:
     673             :                         DBG_INF("MYSQL_OPT_READ_TIMEOUT");
     674             :                         net->options.timeout_read = *(unsigned int*) value;
     675             :                         break;
     676             :                 case MYSQL_OPT_WRITE_TIMEOUT:
     677             :                         DBG_INF("MYSQL_OPT_WRITE_TIMEOUT");
     678             :                         net->options.timeout_write = *(unsigned int*) value;
     679             :                         break;
     680             : #endif
     681             :                 case MYSQL_OPT_COMPRESS:
     682           0 :                         net->options.flags |= MYSQLND_NET_FLAG_USE_COMPRESSION;
     683           0 :                         break;
     684             :                 default:
     685           0 :                         DBG_RETURN(FAIL);
     686             :         }
     687        3968 :         DBG_RETURN(PASS);
     688             : }
     689             : /* }}} */
     690             : 
     691             : /* {{{ mysqlnd_net::consume_uneaten_data */
     692             : size_t 
     693           0 : MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data)(MYSQLND_NET * const net, enum php_mysqlnd_server_command cmd TSRMLS_DC)
     694             : {
     695             : #ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
     696             :         /*
     697             :           Switch to non-blocking mode and try to consume something from
     698             :           the line, if possible, then continue. This saves us from looking for
     699             :           the actuall place where out-of-order packets have been sent.
     700             :           If someone is completely sure that everything is fine, he can switch it
     701             :           off.
     702             :         */
     703             :         char tmp_buf[256];
     704             :         size_t skipped_bytes = 0;
     705             :         int opt = PHP_STREAM_OPTION_BLOCKING;
     706             :         int was_blocked = net->stream->ops->set_option(net->stream, opt, 0, NULL TSRMLS_CC);
     707             : 
     708             :         DBG_ENTER("mysqlnd_net::consume_uneaten_data");
     709             : 
     710             :         if (PHP_STREAM_OPTION_RETURN_ERR != was_blocked) {
     711             :                 /* Do a read of 1 byte */
     712             :                 int bytes_consumed;
     713             : 
     714             :                 do {
     715             :                         skipped_bytes += (bytes_consumed = php_stream_read(net->stream, tmp_buf, sizeof(tmp_buf)));
     716             :                 } while (bytes_consumed == sizeof(tmp_buf));
     717             : 
     718             :                 if (was_blocked) {
     719             :                         net->stream->ops->set_option(net->stream, opt, 1, NULL TSRMLS_CC);
     720             :                 }
     721             : 
     722             :                 if (bytes_consumed) {
     723             :                         DBG_ERR_FMT("Skipped %u bytes. Last command %s hasn't consumed all the output from the server",
     724             :                                                 bytes_consumed, mysqlnd_command_to_text[net->last_command]);
     725             :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Skipped %u bytes. Last command %s hasn't "
     726             :                                                          "consumed all the output from the server",
     727             :                                                          bytes_consumed, mysqlnd_command_to_text[net->last_command]);
     728             :                 }
     729             :         }
     730             :         net->last_command = cmd;
     731             : 
     732             :         DBG_RETURN(skipped_bytes);
     733             : #else
     734           0 :         return 0;
     735             : #endif
     736             : }
     737             : /* }}} */
     738             : 
     739             : /*
     740             :   in libmyusql, if cert and !key then key=cert
     741             : */
     742             : /* {{{ mysqlnd_net::enable_ssl */
     743             : static enum_func_status
     744           3 : MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
     745             : {
     746             : #ifdef MYSQLND_SSL_SUPPORTED
     747           3 :         php_stream_context *context = php_stream_context_alloc();
     748           3 :         DBG_ENTER("mysqlnd_net::enable_ssl");
     749           3 :         if (!context) {
     750           0 :                 DBG_RETURN(FAIL);
     751             :         }
     752             : 
     753           3 :         if (net->options.ssl_key) {
     754             :                 zval key_zval;
     755           1 :                 ZVAL_STRING(&key_zval, net->options.ssl_key, 0);
     756           1 :                 DBG_INF("key");
     757           1 :                 php_stream_context_set_option(context, "ssl", "local_pk", &key_zval);
     758             :         }
     759           3 :         if (net->options.ssl_verify_peer) {
     760             :                 zval verify_peer_zval;
     761           0 :                 ZVAL_TRUE(&verify_peer_zval);
     762           0 :                 DBG_INF("verify peer");
     763           0 :                 php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval);
     764             :         }
     765           3 :         if (net->options.ssl_cert) {
     766             :                 zval cert_zval;
     767           1 :                 ZVAL_STRING(&cert_zval, net->options.ssl_cert, 0);
     768           1 :                 DBG_INF_FMT("local_cert=%s", net->options.ssl_cert);
     769           1 :                 php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval);
     770           1 :                 if (!net->options.ssl_key) {
     771           0 :                         php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval);
     772             :                 }
     773             :         }
     774           3 :         if (net->options.ssl_ca) {
     775             :                 zval cafile_zval;
     776           1 :                 ZVAL_STRING(&cafile_zval, net->options.ssl_ca, 0);
     777           1 :                 DBG_INF_FMT("cafile=%s", net->options.ssl_ca);
     778           1 :                 php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval);
     779             :         }
     780           3 :         if (net->options.ssl_capath) {
     781             :                 zval capath_zval;
     782           0 :                 ZVAL_STRING(&capath_zval, net->options.ssl_capath, 0);
     783           0 :                 DBG_INF_FMT("capath=%s", net->options.ssl_capath);
     784           0 :                 php_stream_context_set_option(context, "ssl", "cafile", &capath_zval);
     785             :         }
     786           3 :         if (net->options.ssl_passphrase) {
     787             :                 zval passphrase_zval;
     788           0 :                 ZVAL_STRING(&passphrase_zval, net->options.ssl_passphrase, 0);
     789           0 :                 php_stream_context_set_option(context, "ssl", "passphrase", &passphrase_zval);
     790             :         }
     791           3 :         if (net->options.ssl_cipher) {
     792             :                 zval cipher_zval;
     793           2 :                 ZVAL_STRING(&cipher_zval, net->options.ssl_cipher, 0);
     794           2 :                 DBG_INF_FMT("ciphers=%s", net->options.ssl_cipher);
     795           2 :                 php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval);
     796             :         }
     797           3 :         php_stream_context_set(net->stream, context);
     798           3 :         if (php_stream_xport_crypto_setup(net->stream, STREAM_CRYPTO_METHOD_TLS_CLIENT, NULL TSRMLS_CC) < 0 ||
     799           0 :             php_stream_xport_crypto_enable(net->stream, 1 TSRMLS_CC) < 0)
     800             :         {
     801           3 :                 DBG_ERR("Cannot connect to MySQL by using SSL");
     802           3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot connect to MySQL by using SSL");
     803           3 :                 DBG_RETURN(FAIL);
     804             :         }
     805             :         /*
     806             :           get rid of the context. we are persistent and if this is a real pconn used by mysql/mysqli,
     807             :           then the context would not survive cleaning of EG(regular_list), where it is registered, as a
     808             :           resource. What happens is that after this destruction any use of the network will mean usage
     809             :           of the context, which means usage of already freed memory, bad. Actually we don't need this
     810             :           context anymore after we have enabled SSL on the connection. Thus it is very simple, we remove it.
     811             :         */
     812           0 :         php_stream_context_set(net->stream, NULL);
     813             : 
     814           0 :         if (net->options.timeout_read) {
     815             :                 struct timeval tv;
     816           0 :                 DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->options.timeout_read);
     817           0 :                 tv.tv_sec = net->options.timeout_read;
     818           0 :                 tv.tv_usec = 0;
     819           0 :                 php_stream_set_option(net->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
     820             :         }
     821             : 
     822           0 :         DBG_RETURN(PASS);
     823             : #else
     824             :         DBG_ENTER("mysqlnd_net::enable_ssl");
     825             :         DBG_RETURN(PASS);
     826             : #endif
     827             : }
     828             : /* }}} */
     829             : 
     830             : 
     831             : /* {{{ mysqlnd_net::disable_ssl */
     832             : static enum_func_status
     833           0 : MYSQLND_METHOD(mysqlnd_net, disable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
     834             : {
     835           0 :         DBG_ENTER("mysqlnd_net::disable_ssl");
     836           0 :         DBG_RETURN(PASS);
     837             : }
     838             : /* }}} */
     839             : 
     840             : 
     841             : /* {{{ mysqlnd_net::set_client_option */
     842             : static void
     843        3761 : MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC)
     844             : {
     845        3761 :         zend_bool pers = net->persistent;
     846        3761 :         DBG_ENTER("mysqlnd_net::free_contents");
     847             : 
     848             : #ifdef MYSQLND_COMPRESSION_ENABLED
     849        3761 :         if (net->uncompressed_data) {
     850           0 :                 net->uncompressed_data->free_buffer(&net->uncompressed_data TSRMLS_CC);
     851             :         }
     852             : #endif
     853        3761 :         if (net->options.ssl_key) {
     854           1 :                 mnd_pefree(net->options.ssl_key, pers);
     855           1 :                 net->options.ssl_key = NULL;
     856             :         }
     857        3761 :         if (net->options.ssl_cert) {
     858           1 :                 mnd_pefree(net->options.ssl_cert, pers);
     859           1 :                 net->options.ssl_cert = NULL;
     860             :         }
     861        3761 :         if (net->options.ssl_ca) {
     862           1 :                 mnd_pefree(net->options.ssl_ca, pers);
     863           1 :                 net->options.ssl_ca = NULL;
     864             :         }
     865        3761 :         if (net->options.ssl_capath) {
     866           0 :                 mnd_pefree(net->options.ssl_capath, pers);
     867           0 :                 net->options.ssl_capath = NULL;
     868             :         }
     869        3761 :         if (net->options.ssl_cipher) {
     870           2 :                 mnd_pefree(net->options.ssl_cipher, pers);
     871           2 :                 net->options.ssl_cipher = NULL;
     872             :         }
     873             : 
     874        3761 :         DBG_VOID_RETURN;
     875             : }
     876             : /* }}} */
     877             : 
     878             : static 
     879             : MYSQLND_CLASS_METHODS_START(mysqlnd_net)
     880             :         MYSQLND_METHOD(mysqlnd_net, connect),
     881             :         MYSQLND_METHOD(mysqlnd_net, send),
     882             :         MYSQLND_METHOD(mysqlnd_net, receive),
     883             :         MYSQLND_METHOD(mysqlnd_net, set_client_option),
     884             :         MYSQLND_METHOD(mysqlnd_net, network_read),
     885             :         MYSQLND_METHOD(mysqlnd_net, network_write),
     886             :         MYSQLND_METHOD(mysqlnd_net, decode),
     887             :         MYSQLND_METHOD(mysqlnd_net, encode),
     888             :         MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data),
     889             :         MYSQLND_METHOD(mysqlnd_net, free_contents),
     890             :         MYSQLND_METHOD(mysqlnd_net, enable_ssl),
     891             :         MYSQLND_METHOD(mysqlnd_net, disable_ssl)
     892             : MYSQLND_CLASS_METHODS_END;
     893             : 
     894             : 
     895             : /* {{{ mysqlnd_net_init */
     896             : PHPAPI MYSQLND_NET *
     897        1894 : mysqlnd_net_init(zend_bool persistent TSRMLS_DC)
     898             : {
     899        1894 :         size_t alloc_size = sizeof(MYSQLND_NET) + mysqlnd_plugin_count() * sizeof(void *);
     900        1894 :         MYSQLND_NET * net = mnd_pecalloc(1, alloc_size, persistent);
     901             : 
     902        1894 :         DBG_ENTER("mysqlnd_net_init");
     903        1894 :         DBG_INF_FMT("persistent=%u", persistent);
     904        1894 :         if (net) {
     905        1894 :                 net->persistent = persistent;
     906        1894 :                 net->m = mysqlnd_mysqlnd_net_methods;
     907             : 
     908             :                 {
     909        1894 :                         unsigned int buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/
     910        1894 :                         net->m.set_client_option(net, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size TSRMLS_CC);
     911             :                 }
     912             :         }
     913        1894 :         DBG_RETURN(net);
     914             : }
     915             : /* }}} */
     916             : 
     917             : 
     918             : /* {{{ mysqlnd_net_free */
     919             : PHPAPI void
     920        1853 : mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC)
     921             : {
     922        1853 :         DBG_ENTER("mysqlnd_net_free");
     923             : 
     924        1853 :         if (net) {
     925        1853 :                 zend_bool pers = net->persistent;
     926             : 
     927        1853 :                 net->m.free_contents(net TSRMLS_CC);
     928        1853 :                 if (net->cmd_buffer.buffer) {
     929        1853 :                         DBG_INF("Freeing cmd buffer");
     930        1853 :                         mnd_pefree(net->cmd_buffer.buffer, pers);
     931        1853 :                         net->cmd_buffer.buffer = NULL;
     932             :                 }
     933        1853 :                 if (net->stream) {
     934        1812 :                         DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);
     935        1812 :                         if (pers) {
     936        1089 :                                 php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
     937             :                         } else {
     938         723 :                                 php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
     939             :                         }
     940        1812 :                         net->stream = NULL;
     941             :                 }
     942        1853 :                 mnd_pefree(net, pers);
     943             :         }
     944        1853 :         DBG_VOID_RETURN;
     945             : }
     946             : /* }}} */
     947             : 
     948             : 
     949             : /* {{{ _mysqlnd_plugin_get_plugin_net_data */
     950           0 : PHPAPI void ** _mysqlnd_plugin_get_plugin_net_data(const MYSQLND_NET * net, unsigned int plugin_id TSRMLS_DC)
     951             : {
     952           0 :         DBG_ENTER("_mysqlnd_plugin_get_plugin_net_data");
     953           0 :         DBG_INF_FMT("plugin_id=%u", plugin_id);
     954           0 :         if (!net || plugin_id >= mysqlnd_plugin_count()) {
     955           0 :                 return NULL;
     956             :         }
     957           0 :         DBG_RETURN((void *)((char *)net + sizeof(MYSQLND_NET) + plugin_id * sizeof(void *)));
     958             : }
     959             : /* }}} */
     960             : 
     961             : 
     962             : /* {{{ mysqlnd_net_get_methods */
     963             : PHPAPI struct st_mysqlnd_net_methods *
     964           0 : mysqlnd_net_get_methods()
     965             : {
     966           0 :         return &mysqlnd_mysqlnd_net_methods;
     967             : }
     968             : /* }}} */
     969             : 
     970             : 
     971             : /*
     972             :  * Local variables:
     973             :  * tab-width: 4
     974             :  * c-basic-offset: 4
     975             :  * End:
     976             :  * vim600: noet sw=4 ts=4 fdm=marker
     977             :  * vim<600: noet sw=4 ts=4
     978             :  */

Generated by: LCOV version 1.10

Generated at Wed, 23 Jul 2014 19:58:34 +0000 (17 hours ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.