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