This source file includes following definitions.
- mysqlnd_set_sock_no_delay
- mysqlnd_set_sock_keepalive
- php_mysqlnd_read_buffer_is_empty
- php_mysqlnd_read_buffer_read
- php_mysqlnd_read_buffer_bytes_left
- php_mysqlnd_read_buffer_free
- mysqlnd_create_read_buffer
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_CLASS_METHODS_START
- mysqlnd_net_free
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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"
29 #include "mysqlnd_ext_plugin.h"
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
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
64
65 static int
66 mysqlnd_set_sock_keepalive(php_stream * stream TSRMLS_DC)
67 {
68
69 int socketd = ((php_netstream_data_t*)stream->abstract)->socket;
70 int ret = SUCCESS;
71 int flag = 1;
72 int result = setsockopt(socketd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int));
73
74 DBG_ENTER("mysqlnd_set_sock_keepalive");
75
76 if (result == -1) {
77 ret = FAILURE;
78 }
79
80 DBG_RETURN(ret);
81 }
82
83
84
85
86 static enum_func_status
87 MYSQLND_METHOD(mysqlnd_net, network_read_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
88 MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
89 {
90 enum_func_status return_value = PASS;
91 php_stream * net_stream = net->data->m.get_stream(net TSRMLS_CC);
92 size_t old_chunk_size = net_stream->chunk_size;
93 size_t to_read = count, ret;
94 zend_uchar * p = buffer;
95
96 DBG_ENTER("mysqlnd_net::network_read_ex");
97 DBG_INF_FMT("count="MYSQLND_SZ_T_SPEC, count);
98
99 net_stream->chunk_size = MIN(to_read, net->data->options.net_read_buffer_size);
100 while (to_read) {
101 if (!(ret = php_stream_read(net_stream, (char *) p, to_read))) {
102 DBG_ERR_FMT("Error while reading header from socket");
103 return_value = FAIL;
104 break;
105 }
106 p += ret;
107 to_read -= ret;
108 }
109 MYSQLND_INC_CONN_STATISTIC_W_VALUE(stats, STAT_BYTES_RECEIVED, count - to_read);
110 net_stream->chunk_size = old_chunk_size;
111 DBG_RETURN(return_value);
112 }
113
114
115
116
117 static size_t
118 MYSQLND_METHOD(mysqlnd_net, network_write_ex)(MYSQLND_NET * const net, const zend_uchar * const buffer, const size_t count,
119 MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
120 {
121 size_t ret;
122 DBG_ENTER("mysqlnd_net::network_write_ex");
123 DBG_INF_FMT("sending %u bytes", count);
124 ret = php_stream_write(net->data->m.get_stream(net TSRMLS_CC), (char *)buffer, count);
125 DBG_RETURN(ret);
126 }
127
128
129
130 static php_stream *
131 MYSQLND_METHOD(mysqlnd_net, open_pipe)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
132 const zend_bool persistent,
133 MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
134 {
135 #if PHP_API_VERSION < 20100412
136 unsigned int streams_options = ENFORCE_SAFE_MODE;
137 #else
138 unsigned int streams_options = 0;
139 #endif
140 php_stream * net_stream = NULL;
141
142 DBG_ENTER("mysqlnd_net::open_pipe");
143 if (persistent) {
144 streams_options |= STREAM_OPEN_PERSISTENT;
145 }
146 streams_options |= IGNORE_URL;
147 net_stream = php_stream_open_wrapper((char*) scheme + sizeof("pipe://") - 1, "r+", streams_options, NULL);
148 if (!net_stream) {
149 SET_CLIENT_ERROR(*error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "Unknown errror while connecting");
150 DBG_RETURN(NULL);
151 }
152
153
154
155
156
157 net_stream->in_free = 1;
158 zend_hash_index_del(&EG(regular_list), net_stream->rsrc_id);
159 net_stream->in_free = 0;
160
161
162 DBG_RETURN(net_stream);
163 }
164
165
166
167
168 static php_stream *
169 MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
170 const zend_bool persistent,
171 MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
172 {
173 #if PHP_API_VERSION < 20100412
174 unsigned int streams_options = ENFORCE_SAFE_MODE;
175 #else
176 unsigned int streams_options = 0;
177 #endif
178 unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT;
179 char * hashed_details = NULL;
180 int hashed_details_len = 0;
181 char * errstr = NULL;
182 int errcode = 0;
183 struct timeval tv;
184 php_stream * net_stream = NULL;
185
186 DBG_ENTER("mysqlnd_net::open_tcp_or_unix");
187
188 net->data->stream = NULL;
189
190 if (persistent) {
191 hashed_details_len = mnd_sprintf(&hashed_details, 0, "%p", net);
192 DBG_INF_FMT("hashed_details=%s", hashed_details);
193 }
194
195 if (net->data->options.timeout_connect) {
196 tv.tv_sec = net->data->options.timeout_connect;
197 tv.tv_usec = 0;
198 }
199
200 DBG_INF_FMT("calling php_stream_xport_create");
201 net_stream = php_stream_xport_create(scheme, scheme_len, streams_options, streams_flags,
202 hashed_details, (net->data->options.timeout_connect) ? &tv : NULL,
203 NULL , &errstr, &errcode);
204 if (errstr || !net_stream) {
205 DBG_ERR("Error");
206 if (hashed_details) {
207 mnd_sprintf_free(hashed_details);
208 }
209 SET_CLIENT_ERROR(*error_info,
210 CR_CONNECTION_ERROR,
211 UNKNOWN_SQLSTATE,
212 errstr? errstr:"Unknown error while connecting");
213 if (errstr) {
214
215 efree(errstr);
216 }
217 DBG_RETURN(NULL);
218 }
219 if (hashed_details) {
220
221
222
223
224
225 zend_rsrc_list_entry *le;
226
227 if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_len + 1, (void*) &le) == SUCCESS) {
228
229
230
231
232
233 net_stream->in_free = 1;
234 zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_len + 1);
235 net_stream->in_free = 0;
236 }
237 #if ZEND_DEBUG
238
239 net_stream->__exposed = 1;
240 #endif
241 mnd_sprintf_free(hashed_details);
242 }
243
244
245
246
247
248
249 net_stream->in_free = 1;
250 zend_hash_index_del(&EG(regular_list), net_stream->rsrc_id);
251 net_stream->in_free = 0;
252
253 DBG_RETURN(net_stream);
254 }
255
256
257
258
259 static void
260 MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt)(MYSQLND_NET * const net,
261 const char * const scheme, const size_t scheme_len,
262 MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
263 {
264 php_stream * net_stream = net->data->m.get_stream(net TSRMLS_CC);
265 DBG_ENTER("mysqlnd_net::post_connect_set_opt");
266 if (net_stream) {
267 if (net->data->options.timeout_read) {
268 struct timeval tv;
269 DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->data->options.timeout_read);
270 tv.tv_sec = net->data->options.timeout_read;
271 tv.tv_usec = 0;
272 php_stream_set_option(net_stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
273 }
274
275 if (!memcmp(scheme, "tcp://", sizeof("tcp://") - 1)) {
276
277 mysqlnd_set_sock_no_delay(net_stream TSRMLS_CC);
278
279 mysqlnd_set_sock_keepalive(net_stream TSRMLS_CC);
280 }
281 }
282
283 DBG_VOID_RETURN;
284 }
285
286
287
288
289 static func_mysqlnd_net__open_stream
290 MYSQLND_METHOD(mysqlnd_net, get_open_stream)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
291 MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
292 {
293 func_mysqlnd_net__open_stream ret = NULL;
294 DBG_ENTER("mysqlnd_net::get_open_stream");
295 if (scheme_len > (sizeof("pipe://") - 1) && !memcmp(scheme, "pipe://", sizeof("pipe://") - 1)) {
296 ret = net->data->m.open_pipe;
297 } else if ((scheme_len > (sizeof("tcp://") - 1) && !memcmp(scheme, "tcp://", sizeof("tcp://") - 1))
298 ||
299 (scheme_len > (sizeof("unix://") - 1) && !memcmp(scheme, "unix://", sizeof("unix://") - 1)))
300 {
301 ret = net->data->m.open_tcp_or_unix;
302 }
303
304 if (!ret) {
305 SET_CLIENT_ERROR(*error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "No handler for this scheme");
306 }
307
308 DBG_RETURN(ret);
309 }
310
311
312
313
314 static enum_func_status
315 MYSQLND_METHOD(mysqlnd_net, connect_ex)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
316 const zend_bool persistent,
317 MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
318 {
319 enum_func_status ret = FAIL;
320 func_mysqlnd_net__open_stream open_stream = NULL;
321 DBG_ENTER("mysqlnd_net::connect_ex");
322
323 net->packet_no = net->compressed_envelope_packet_no = 0;
324
325 net->data->m.close_stream(net, conn_stats, error_info TSRMLS_CC);
326
327 open_stream = net->data->m.get_open_stream(net, scheme, scheme_len, error_info TSRMLS_CC);
328 if (open_stream) {
329 php_stream * net_stream = open_stream(net, scheme, scheme_len, persistent, conn_stats, error_info TSRMLS_CC);
330 if (net_stream) {
331 (void) net->data->m.set_stream(net, net_stream TSRMLS_CC);
332 net->data->m.post_connect_set_opt(net, scheme, scheme_len, conn_stats, error_info TSRMLS_CC);
333 ret = PASS;
334 }
335 }
336
337 DBG_RETURN(ret);
338 }
339
340
341
342
343 #define COPY_HEADER(T,A) do { \
344 *(((char *)(T))) = *(((char *)(A)));\
345 *(((char *)(T))+1) = *(((char *)(A))+1);\
346 *(((char *)(T))+2) = *(((char *)(A))+2);\
347 *(((char *)(T))+3) = *(((char *)(A))+3); } while (0)
348 #define STORE_HEADER_SIZE(safe_storage, buffer) COPY_HEADER((safe_storage), (buffer))
349 #define RESTORE_HEADER_SIZE(buffer, safe_storage) STORE_HEADER_SIZE((safe_storage), (buffer))
350
351
352
353
354
355
356
357
358
359
360
361
362
363 static size_t
364 MYSQLND_METHOD(mysqlnd_net, send_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
365 MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
366 {
367 zend_uchar safe_buf[((MYSQLND_HEADER_SIZE) + (sizeof(zend_uchar)) - 1) / (sizeof(zend_uchar))];
368 zend_uchar * safe_storage = safe_buf;
369 size_t bytes_sent, packets_sent = 1;
370 size_t left = count;
371 zend_uchar * p = (zend_uchar *) buffer;
372 zend_uchar * compress_buf = NULL;
373 size_t to_be_sent;
374
375 DBG_ENTER("mysqlnd_net::send_ex");
376 DBG_INF_FMT("count=" MYSQLND_SZ_T_SPEC " compression=%u", count, net->data->compressed);
377
378 if (net->data->compressed == TRUE) {
379 size_t comp_buf_size = MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE + MIN(left, MYSQLND_MAX_PACKET_SIZE);
380 DBG_INF_FMT("compress_buf_size="MYSQLND_SZ_T_SPEC, comp_buf_size);
381 compress_buf = mnd_emalloc(comp_buf_size);
382 }
383
384 do {
385 to_be_sent = MIN(left, MYSQLND_MAX_PACKET_SIZE);
386 DBG_INF_FMT("to_be_sent=%u", to_be_sent);
387 DBG_INF_FMT("packets_sent=%u", packets_sent);
388 DBG_INF_FMT("compressed_envelope_packet_no=%u", net->compressed_envelope_packet_no);
389 DBG_INF_FMT("packet_no=%u", net->packet_no);
390 #ifdef MYSQLND_COMPRESSION_ENABLED
391 if (net->data->compressed == TRUE) {
392
393 size_t tmp_complen = to_be_sent;
394 size_t payload_size;
395 zend_uchar * uncompressed_payload = p;
396
397 STORE_HEADER_SIZE(safe_storage, uncompressed_payload);
398 int3store(uncompressed_payload, to_be_sent);
399 int1store(uncompressed_payload + 3, net->packet_no);
400 if (PASS == net->data->m.encode((compress_buf + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE), &tmp_complen,
401 uncompressed_payload, to_be_sent + MYSQLND_HEADER_SIZE TSRMLS_CC))
402 {
403 int3store(compress_buf + MYSQLND_HEADER_SIZE, to_be_sent + MYSQLND_HEADER_SIZE);
404 payload_size = tmp_complen;
405 } else {
406 int3store(compress_buf + MYSQLND_HEADER_SIZE, 0);
407 memcpy(compress_buf + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, uncompressed_payload, to_be_sent + MYSQLND_HEADER_SIZE);
408 payload_size = to_be_sent + MYSQLND_HEADER_SIZE;
409 }
410 RESTORE_HEADER_SIZE(uncompressed_payload, safe_storage);
411
412 int3store(compress_buf, payload_size);
413 int1store(compress_buf + 3, net->packet_no);
414 DBG_INF_FMT("writing "MYSQLND_SZ_T_SPEC" bytes to the network", payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE);
415 bytes_sent = net->data->m.network_write_ex(net, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE,
416 conn_stats, error_info TSRMLS_CC);
417 net->compressed_envelope_packet_no++;
418 #if WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY
419 if (res == Z_OK) {
420 size_t decompressed_size = left + MYSQLND_HEADER_SIZE;
421 zend_uchar * decompressed_data = mnd_malloc(decompressed_size);
422 int error = net->data->m.decode(decompressed_data, decompressed_size,
423 compress_buf + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, payload_size);
424 if (error == Z_OK) {
425 int i;
426 DBG_INF("success decompressing");
427 for (i = 0 ; i < decompressed_size; i++) {
428 if (i && (i % 30 == 0)) {
429 printf("\n\t\t");
430 }
431 printf("%.2X ", (int)*((char*)&(decompressed_data[i])));
432 DBG_INF_FMT("%.2X ", (int)*((char*)&(decompressed_data[i])));
433 }
434 } else {
435 DBG_INF("error decompressing");
436 }
437 mnd_free(decompressed_data);
438 }
439 #endif
440 } else
441 #endif
442 {
443 DBG_INF("no compression");
444 STORE_HEADER_SIZE(safe_storage, p);
445 int3store(p, to_be_sent);
446 int1store(p + 3, net->packet_no);
447 bytes_sent = net->data->m.network_write_ex(net, p, to_be_sent + MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC);
448 RESTORE_HEADER_SIZE(p, safe_storage);
449 net->compressed_envelope_packet_no++;
450 }
451 net->packet_no++;
452
453 p += to_be_sent;
454 left -= to_be_sent;
455 packets_sent++;
456
457
458
459
460
461
462
463 } while (bytes_sent && (left > 0 || to_be_sent == MYSQLND_MAX_PACKET_SIZE));
464
465 DBG_INF_FMT("packet_size="MYSQLND_SZ_T_SPEC" packet_no=%u", left, net->packet_no);
466
467 MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats,
468 STAT_BYTES_SENT, count + packets_sent * MYSQLND_HEADER_SIZE,
469 STAT_PROTOCOL_OVERHEAD_OUT, packets_sent * MYSQLND_HEADER_SIZE,
470 STAT_PACKETS_SENT, packets_sent);
471
472 if (compress_buf) {
473 mnd_efree(compress_buf);
474 }
475
476
477 if (!bytes_sent) {
478 DBG_ERR_FMT("Can't %u send bytes", count);
479 SET_CLIENT_ERROR(*error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
480 }
481 DBG_RETURN(bytes_sent);
482 }
483
484
485
486 #ifdef MYSQLND_COMPRESSION_ENABLED
487
488 static zend_bool
489 php_mysqlnd_read_buffer_is_empty(MYSQLND_READ_BUFFER * buffer)
490 {
491 return buffer->len? FALSE:TRUE;
492 }
493
494
495
496
497 static void
498 php_mysqlnd_read_buffer_read(MYSQLND_READ_BUFFER * buffer, size_t count, zend_uchar * dest)
499 {
500 if (buffer->len >= count) {
501 memcpy(dest, buffer->data + buffer->offset, count);
502 buffer->offset += count;
503 buffer->len -= count;
504 }
505 }
506
507
508
509
510 static size_t
511 php_mysqlnd_read_buffer_bytes_left(MYSQLND_READ_BUFFER * buffer)
512 {
513 return buffer->len;
514 }
515
516
517
518
519 static void
520 php_mysqlnd_read_buffer_free(MYSQLND_READ_BUFFER ** buffer TSRMLS_DC)
521 {
522 DBG_ENTER("php_mysqlnd_read_buffer_free");
523 if (*buffer) {
524 mnd_efree((*buffer)->data);
525 mnd_efree(*buffer);
526 *buffer = NULL;
527 }
528 DBG_VOID_RETURN;
529 }
530
531
532
533
534 static MYSQLND_READ_BUFFER *
535 mysqlnd_create_read_buffer(size_t count TSRMLS_DC)
536 {
537 MYSQLND_READ_BUFFER * ret = mnd_emalloc(sizeof(MYSQLND_READ_BUFFER));
538 DBG_ENTER("mysqlnd_create_read_buffer");
539 ret->is_empty = php_mysqlnd_read_buffer_is_empty;
540 ret->read = php_mysqlnd_read_buffer_read;
541 ret->bytes_left = php_mysqlnd_read_buffer_bytes_left;
542 ret->free_buffer = php_mysqlnd_read_buffer_free;
543 ret->data = mnd_emalloc(count);
544 ret->size = ret->len = count;
545 ret->offset = 0;
546 DBG_RETURN(ret);
547 }
548
549
550
551
552 static enum_func_status
553 MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buffer)
554 (MYSQLND_NET * net, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
555 {
556 size_t decompressed_size;
557 enum_func_status retval = PASS;
558 zend_uchar * compressed_data = NULL;
559 zend_uchar comp_header[COMPRESSED_HEADER_SIZE];
560 DBG_ENTER("mysqlnd_net::read_compressed_packet_from_stream_and_fill_read_buffer");
561
562
563 if (FAIL == net->data->m.network_read_ex(net, comp_header, COMPRESSED_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) {
564 DBG_RETURN(FAIL);
565 }
566 decompressed_size = uint3korr(comp_header);
567
568
569
570
571 if (decompressed_size) {
572 compressed_data = mnd_emalloc(net_payload_size);
573 if (FAIL == net->data->m.network_read_ex(net, compressed_data, net_payload_size, conn_stats, error_info TSRMLS_CC)) {
574 retval = FAIL;
575 goto end;
576 }
577 net->uncompressed_data = mysqlnd_create_read_buffer(decompressed_size TSRMLS_CC);
578 retval = net->data->m.decode(net->uncompressed_data->data, decompressed_size, compressed_data, net_payload_size TSRMLS_CC);
579 if (FAIL == retval) {
580 goto end;
581 }
582 } else {
583 DBG_INF_FMT("The server decided not to compress the data. Our job is easy. Copying %u bytes", net_payload_size);
584 net->uncompressed_data = mysqlnd_create_read_buffer(net_payload_size TSRMLS_CC);
585 if (FAIL == net->data->m.network_read_ex(net, net->uncompressed_data->data, net_payload_size, conn_stats, error_info TSRMLS_CC)) {
586 retval = FAIL;
587 goto end;
588 }
589 }
590 end:
591 if (compressed_data) {
592 mnd_efree(compressed_data);
593 }
594 DBG_RETURN(retval);
595 }
596
597 #endif
598
599
600
601 static enum_func_status
602 MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncompressed_data, const size_t uncompressed_data_len,
603 const zend_uchar * const compressed_data, const size_t compressed_data_len TSRMLS_DC)
604 {
605 #ifdef MYSQLND_COMPRESSION_ENABLED
606 int error;
607 uLongf tmp_complen = uncompressed_data_len;
608 DBG_ENTER("mysqlnd_net::decode");
609 error = uncompress(uncompressed_data, &tmp_complen, compressed_data, compressed_data_len);
610
611 DBG_INF_FMT("compressed data: decomp_len=%lu compressed_size="MYSQLND_SZ_T_SPEC, tmp_complen, compressed_data_len);
612 if (error != Z_OK) {
613 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);
614 }
615 DBG_RETURN(error == Z_OK? PASS:FAIL);
616 #else
617 DBG_ENTER("mysqlnd_net::decode");
618 DBG_RETURN(FAIL);
619 #endif
620 }
621
622
623
624
625 static enum_func_status
626 MYSQLND_METHOD(mysqlnd_net, encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len,
627 const zend_uchar * const uncompressed_data, const size_t uncompressed_data_len TSRMLS_DC)
628 {
629 #ifdef MYSQLND_COMPRESSION_ENABLED
630 int error;
631 uLongf tmp_complen = *compress_buffer_len;
632 DBG_ENTER("mysqlnd_net::encode");
633 error = compress(compress_buffer, &tmp_complen, uncompressed_data, uncompressed_data_len);
634
635 if (error != Z_OK) {
636 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);
637 } else {
638 *compress_buffer_len = tmp_complen;
639 DBG_INF_FMT("compression successful. compressed size=%lu", tmp_complen);
640 }
641
642 DBG_RETURN(error == Z_OK? PASS:FAIL);
643 #else
644 DBG_ENTER("mysqlnd_net::encode");
645 DBG_RETURN(FAIL);
646 #endif
647 }
648
649
650
651
652 static enum_func_status
653 MYSQLND_METHOD(mysqlnd_net, receive_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
654 MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
655 {
656 size_t to_read = count;
657 zend_uchar * p = buffer;
658
659 DBG_ENTER("mysqlnd_net::receive_ex");
660 #ifdef MYSQLND_COMPRESSION_ENABLED
661 if (net->data->compressed) {
662 if (net->uncompressed_data) {
663 size_t to_read_from_buffer = MIN(net->uncompressed_data->bytes_left(net->uncompressed_data), to_read);
664 DBG_INF_FMT("reading "MYSQLND_SZ_T_SPEC" from uncompressed_data buffer", to_read_from_buffer);
665 if (to_read_from_buffer) {
666 net->uncompressed_data->read(net->uncompressed_data, to_read_from_buffer, (zend_uchar *) p);
667 p += to_read_from_buffer;
668 to_read -= to_read_from_buffer;
669 }
670 DBG_INF_FMT("left "MYSQLND_SZ_T_SPEC" to read", to_read);
671 if (TRUE == net->uncompressed_data->is_empty(net->uncompressed_data)) {
672
673 net->uncompressed_data->free_buffer(&net->uncompressed_data TSRMLS_CC);
674 }
675 }
676 if (to_read) {
677 zend_uchar net_header[MYSQLND_HEADER_SIZE];
678 size_t net_payload_size;
679 zend_uchar packet_no;
680
681 if (FAIL == net->data->m.network_read_ex(net, net_header, MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) {
682 DBG_RETURN(FAIL);
683 }
684 net_payload_size = uint3korr(net_header);
685 packet_no = uint1korr(net_header + 3);
686 if (net->compressed_envelope_packet_no != packet_no) {
687 DBG_ERR_FMT("Transport level: packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
688 net->compressed_envelope_packet_no, packet_no, net_payload_size);
689
690 php_error(E_WARNING, "Packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
691 net->compressed_envelope_packet_no, packet_no, net_payload_size);
692 DBG_RETURN(FAIL);
693 }
694 net->compressed_envelope_packet_no++;
695 #ifdef MYSQLND_DUMP_HEADER_N_BODY
696 DBG_INF_FMT("HEADER: hwd_packet_no=%u size=%3u", packet_no, (unsigned long) net_payload_size);
697 #endif
698
699 net->data->m.read_compressed_packet_from_stream_and_fill_read_buffer(net, net_payload_size, conn_stats, error_info TSRMLS_CC);
700
701
702
703
704
705
706
707 DBG_RETURN(net->data->m.receive_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC));
708 }
709 DBG_RETURN(PASS);
710 }
711 #endif
712 DBG_RETURN(net->data->m.network_read_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC));
713 }
714
715
716
717
718 static enum_func_status
719 MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND_NET * const net, enum mysqlnd_option option, const char * const value TSRMLS_DC)
720 {
721 DBG_ENTER("mysqlnd_net::set_client_option");
722 DBG_INF_FMT("option=%u", option);
723 switch (option) {
724 case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
725 DBG_INF("MYSQLND_OPT_NET_CMD_BUFFER_SIZE");
726 if (*(unsigned int*) value < MYSQLND_NET_CMD_BUFFER_MIN_SIZE) {
727 DBG_RETURN(FAIL);
728 }
729 net->cmd_buffer.length = *(unsigned int*) value;
730 DBG_INF_FMT("new_length="MYSQLND_SZ_T_SPEC, net->cmd_buffer.length);
731 if (!net->cmd_buffer.buffer) {
732 net->cmd_buffer.buffer = mnd_pemalloc(net->cmd_buffer.length, net->persistent);
733 } else {
734 net->cmd_buffer.buffer = mnd_perealloc(net->cmd_buffer.buffer, net->cmd_buffer.length, net->persistent);
735 }
736 break;
737 case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
738 DBG_INF("MYSQLND_OPT_NET_READ_BUFFER_SIZE");
739 net->data->options.net_read_buffer_size = *(unsigned int*) value;
740 DBG_INF_FMT("new_length="MYSQLND_SZ_T_SPEC, net->data->options.net_read_buffer_size);
741 break;
742 case MYSQL_OPT_CONNECT_TIMEOUT:
743 DBG_INF("MYSQL_OPT_CONNECT_TIMEOUT");
744 net->data->options.timeout_connect = *(unsigned int*) value;
745 break;
746 case MYSQLND_OPT_SSL_KEY:
747 {
748 zend_bool pers = net->persistent;
749 if (net->data->options.ssl_key) {
750 mnd_pefree(net->data->options.ssl_key, pers);
751 }
752 net->data->options.ssl_key = value? mnd_pestrdup(value, pers) : NULL;
753 break;
754 }
755 case MYSQLND_OPT_SSL_CERT:
756 {
757 zend_bool pers = net->persistent;
758 if (net->data->options.ssl_cert) {
759 mnd_pefree(net->data->options.ssl_cert, pers);
760 }
761 net->data->options.ssl_cert = value? mnd_pestrdup(value, pers) : NULL;
762 break;
763 }
764 case MYSQLND_OPT_SSL_CA:
765 {
766 zend_bool pers = net->persistent;
767 if (net->data->options.ssl_ca) {
768 mnd_pefree(net->data->options.ssl_ca, pers);
769 }
770 net->data->options.ssl_ca = value? mnd_pestrdup(value, pers) : NULL;
771 break;
772 }
773 case MYSQLND_OPT_SSL_CAPATH:
774 {
775 zend_bool pers = net->persistent;
776 if (net->data->options.ssl_capath) {
777 mnd_pefree(net->data->options.ssl_capath, pers);
778 }
779 net->data->options.ssl_capath = value? mnd_pestrdup(value, pers) : NULL;
780 break;
781 }
782 case MYSQLND_OPT_SSL_CIPHER:
783 {
784 zend_bool pers = net->persistent;
785 if (net->data->options.ssl_cipher) {
786 mnd_pefree(net->data->options.ssl_cipher, pers);
787 }
788 net->data->options.ssl_cipher = value? mnd_pestrdup(value, pers) : NULL;
789 break;
790 }
791 case MYSQLND_OPT_SSL_PASSPHRASE:
792 {
793 zend_bool pers = net->persistent;
794 if (net->data->options.ssl_passphrase) {
795 mnd_pefree(net->data->options.ssl_passphrase, pers);
796 }
797 net->data->options.ssl_passphrase = value? mnd_pestrdup(value, pers) : NULL;
798 break;
799 }
800 case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
801 {
802 enum mysqlnd_ssl_peer val = *((enum mysqlnd_ssl_peer *)value);
803 switch (val) {
804 case MYSQLND_SSL_PEER_VERIFY:
805 DBG_INF("MYSQLND_SSL_PEER_VERIFY");
806 break;
807 case MYSQLND_SSL_PEER_DONT_VERIFY:
808 DBG_INF("MYSQLND_SSL_PEER_DONT_VERIFY");
809 break;
810 case MYSQLND_SSL_PEER_DEFAULT:
811 DBG_INF("MYSQLND_SSL_PEER_DEFAULT");
812 val = MYSQLND_SSL_PEER_DEFAULT;
813 break;
814 default:
815 DBG_INF("default = MYSQLND_SSL_PEER_DEFAULT_ACTION");
816 val = MYSQLND_SSL_PEER_DEFAULT;
817 break;
818 }
819 net->data->options.ssl_verify_peer = val;
820 break;
821 }
822 case MYSQL_OPT_READ_TIMEOUT:
823 net->data->options.timeout_read = *(unsigned int*) value;
824 break;
825 #ifdef WHEN_SUPPORTED_BY_MYSQLI
826 case MYSQL_OPT_WRITE_TIMEOUT:
827 net->data->options.timeout_write = *(unsigned int*) value;
828 break;
829 #endif
830 case MYSQL_OPT_COMPRESS:
831 net->data->options.flags |= MYSQLND_NET_FLAG_USE_COMPRESSION;
832 break;
833 case MYSQL_SERVER_PUBLIC_KEY:
834 {
835 zend_bool pers = net->persistent;
836 if (net->data->options.sha256_server_public_key) {
837 mnd_pefree(net->data->options.sha256_server_public_key, pers);
838 }
839 net->data->options.sha256_server_public_key = value? mnd_pestrdup(value, pers) : NULL;
840 break;
841 }
842 default:
843 DBG_RETURN(FAIL);
844 }
845 DBG_RETURN(PASS);
846 }
847
848
849
850 size_t
851 MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data)(MYSQLND_NET * const net, enum php_mysqlnd_server_command cmd TSRMLS_DC)
852 {
853 #ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
854
855
856
857
858
859
860
861 char tmp_buf[256];
862 size_t skipped_bytes = 0;
863 int opt = PHP_STREAM_OPTION_BLOCKING;
864 php_stream * net_stream = net->data->get_stream(net TSRMLS_CC);
865 int was_blocked = net_stream->ops->set_option(net_stream, opt, 0, NULL TSRMLS_CC);
866
867 DBG_ENTER("mysqlnd_net::consume_uneaten_data");
868
869 if (PHP_STREAM_OPTION_RETURN_ERR != was_blocked) {
870
871 int bytes_consumed;
872
873 do {
874 skipped_bytes += (bytes_consumed = php_stream_read(net_stream, tmp_buf, sizeof(tmp_buf)));
875 } while (bytes_consumed == sizeof(tmp_buf));
876
877 if (was_blocked) {
878 net_stream->ops->set_option(net_stream, opt, 1, NULL TSRMLS_CC);
879 }
880
881 if (bytes_consumed) {
882 DBG_ERR_FMT("Skipped %u bytes. Last command %s hasn't consumed all the output from the server",
883 bytes_consumed, mysqlnd_command_to_text[net->last_command]);
884 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Skipped %u bytes. Last command %s hasn't "
885 "consumed all the output from the server",
886 bytes_consumed, mysqlnd_command_to_text[net->last_command]);
887 }
888 }
889 net->last_command = cmd;
890
891 DBG_RETURN(skipped_bytes);
892 #else
893 return 0;
894 #endif
895 }
896
897
898
899
900
901
902 static enum_func_status
903 MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
904 {
905 #ifdef MYSQLND_SSL_SUPPORTED
906 php_stream_context * context = php_stream_context_alloc(TSRMLS_C);
907 php_stream * net_stream = net->data->m.get_stream(net TSRMLS_CC);
908 zend_bool any_flag = FALSE;
909
910 DBG_ENTER("mysqlnd_net::enable_ssl");
911 if (!context) {
912 DBG_RETURN(FAIL);
913 }
914
915 if (net->data->options.ssl_key) {
916 zval key_zval;
917 ZVAL_STRING(&key_zval, net->data->options.ssl_key, 0);
918 php_stream_context_set_option(context, "ssl", "local_pk", &key_zval);
919 any_flag = TRUE;
920 }
921 if (net->data->options.ssl_cert) {
922 zval cert_zval;
923 ZVAL_STRING(&cert_zval, net->data->options.ssl_cert, 0);
924 php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval);
925 if (!net->data->options.ssl_key) {
926 php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval);
927 }
928 any_flag = TRUE;
929 }
930 if (net->data->options.ssl_ca) {
931 zval cafile_zval;
932 ZVAL_STRING(&cafile_zval, net->data->options.ssl_ca, 0);
933 php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval);
934 any_flag = TRUE;
935 }
936 if (net->data->options.ssl_capath) {
937 zval capath_zval;
938 ZVAL_STRING(&capath_zval, net->data->options.ssl_capath, 0);
939 php_stream_context_set_option(context, "ssl", "capath", &capath_zval);
940 any_flag = TRUE;
941 }
942 if (net->data->options.ssl_passphrase) {
943 zval passphrase_zval;
944 ZVAL_STRING(&passphrase_zval, net->data->options.ssl_passphrase, 0);
945 php_stream_context_set_option(context, "ssl", "passphrase", &passphrase_zval);
946 any_flag = TRUE;
947 }
948 if (net->data->options.ssl_cipher) {
949 zval cipher_zval;
950 ZVAL_STRING(&cipher_zval, net->data->options.ssl_cipher, 0);
951 php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval);
952 any_flag = TRUE;
953 }
954 {
955 zval verify_peer_zval;
956 zend_bool verify;
957
958 if (net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_DEFAULT) {
959 net->data->options.ssl_verify_peer = any_flag? MYSQLND_SSL_PEER_DEFAULT_ACTION:MYSQLND_SSL_PEER_DONT_VERIFY;
960 }
961
962 verify = net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_VERIFY? TRUE:FALSE;
963
964 DBG_INF_FMT("VERIFY=%d", verify);
965 ZVAL_BOOL(&verify_peer_zval, verify);
966 php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval);
967 php_stream_context_set_option(context, "ssl", "verify_peer_name", &verify_peer_zval);
968 if (net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_DONT_VERIFY) {
969 ZVAL_TRUE(&verify_peer_zval);
970 php_stream_context_set_option(context, "ssl", "allow_self_signed", &verify_peer_zval);
971 }
972 }
973
974 php_stream_context_set(net_stream, context);
975 if (php_stream_xport_crypto_setup(net_stream, STREAM_CRYPTO_METHOD_TLS_CLIENT, NULL TSRMLS_CC) < 0 ||
976 php_stream_xport_crypto_enable(net_stream, 1 TSRMLS_CC) < 0)
977 {
978 DBG_ERR("Cannot connect to MySQL by using SSL");
979 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot connect to MySQL by using SSL");
980 DBG_RETURN(FAIL);
981 }
982 net->data->ssl = TRUE;
983
984
985
986
987
988
989
990 php_stream_context_set(net_stream, NULL);
991
992 if (net->data->options.timeout_read) {
993 struct timeval tv;
994 DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->data->options.timeout_read);
995 tv.tv_sec = net->data->options.timeout_read;
996 tv.tv_usec = 0;
997 php_stream_set_option(net_stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
998 }
999
1000 DBG_RETURN(PASS);
1001 #else
1002 DBG_ENTER("mysqlnd_net::enable_ssl");
1003 DBG_INF("MYSQLND_SSL_SUPPORTED is not defined");
1004 DBG_RETURN(PASS);
1005 #endif
1006 }
1007
1008
1009
1010
1011 static enum_func_status
1012 MYSQLND_METHOD(mysqlnd_net, disable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
1013 {
1014 DBG_ENTER("mysqlnd_net::disable_ssl");
1015 DBG_RETURN(PASS);
1016 }
1017
1018
1019
1020
1021 static void
1022 MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC)
1023 {
1024 zend_bool pers = net->persistent;
1025 DBG_ENTER("mysqlnd_net::free_contents");
1026
1027 #ifdef MYSQLND_COMPRESSION_ENABLED
1028 if (net->uncompressed_data) {
1029 net->uncompressed_data->free_buffer(&net->uncompressed_data TSRMLS_CC);
1030 }
1031 #endif
1032 if (net->data->options.ssl_key) {
1033 mnd_pefree(net->data->options.ssl_key, pers);
1034 net->data->options.ssl_key = NULL;
1035 }
1036 if (net->data->options.ssl_cert) {
1037 mnd_pefree(net->data->options.ssl_cert, pers);
1038 net->data->options.ssl_cert = NULL;
1039 }
1040 if (net->data->options.ssl_ca) {
1041 mnd_pefree(net->data->options.ssl_ca, pers);
1042 net->data->options.ssl_ca = NULL;
1043 }
1044 if (net->data->options.ssl_capath) {
1045 mnd_pefree(net->data->options.ssl_capath, pers);
1046 net->data->options.ssl_capath = NULL;
1047 }
1048 if (net->data->options.ssl_cipher) {
1049 mnd_pefree(net->data->options.ssl_cipher, pers);
1050 net->data->options.ssl_cipher = NULL;
1051 }
1052 if (net->data->options.sha256_server_public_key) {
1053 mnd_pefree(net->data->options.sha256_server_public_key, pers);
1054 net->data->options.sha256_server_public_key = NULL;
1055 }
1056
1057 DBG_VOID_RETURN;
1058 }
1059
1060
1061
1062
1063 static void
1064 MYSQLND_METHOD(mysqlnd_net, close_stream)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
1065 {
1066 php_stream * net_stream;
1067 DBG_ENTER("mysqlnd_net::close_stream");
1068 if (net && (net_stream = net->data->m.get_stream(net TSRMLS_CC))) {
1069 zend_bool pers = net->persistent;
1070 DBG_INF_FMT("Freeing stream. abstract=%p", net_stream->abstract);
1071 if (pers) {
1072 if (EG(active)) {
1073 php_stream_free(net_stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
1074 } else {
1075
1076
1077
1078
1079 php_stream_free(net_stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR);
1080 }
1081 } else {
1082 php_stream_free(net_stream, PHP_STREAM_FREE_CLOSE);
1083 }
1084 (void) net->data->m.set_stream(net, NULL TSRMLS_CC);
1085 }
1086
1087 DBG_VOID_RETURN;
1088 }
1089
1090
1091
1092
1093 static enum_func_status
1094 MYSQLND_METHOD(mysqlnd_net, init)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
1095 {
1096 unsigned int buf_size;
1097 DBG_ENTER("mysqlnd_net::init");
1098
1099 buf_size = MYSQLND_G(net_cmd_buffer_size);
1100 net->data->m.set_client_option(net, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size TSRMLS_CC);
1101
1102 buf_size = MYSQLND_G(net_read_buffer_size);
1103 net->data->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC);
1104
1105 buf_size = MYSQLND_G(net_read_timeout);
1106 net->data->m.set_client_option(net, MYSQL_OPT_READ_TIMEOUT, (char *)&buf_size TSRMLS_CC);
1107
1108 DBG_RETURN(PASS);
1109 }
1110
1111
1112
1113
1114 static void
1115 MYSQLND_METHOD(mysqlnd_net, dtor)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
1116 {
1117 DBG_ENTER("mysqlnd_net::dtor");
1118 if (net) {
1119 net->data->m.free_contents(net TSRMLS_CC);
1120 net->data->m.close_stream(net, stats, error_info TSRMLS_CC);
1121
1122 if (net->cmd_buffer.buffer) {
1123 DBG_INF("Freeing cmd buffer");
1124 mnd_pefree(net->cmd_buffer.buffer, net->persistent);
1125 net->cmd_buffer.buffer = NULL;
1126 }
1127
1128 mnd_pefree(net->data, net->data->persistent);
1129 mnd_pefree(net, net->persistent);
1130 }
1131 DBG_VOID_RETURN;
1132 }
1133
1134
1135
1136
1137 static php_stream *
1138 MYSQLND_METHOD(mysqlnd_net, get_stream)(const MYSQLND_NET * const net TSRMLS_DC)
1139 {
1140 DBG_ENTER("mysqlnd_net::get_stream");
1141 DBG_INF_FMT("%p", net? net->data->stream:NULL);
1142 DBG_RETURN(net? net->data->stream:NULL);
1143 }
1144
1145
1146
1147
1148 static php_stream *
1149 MYSQLND_METHOD(mysqlnd_net, set_stream)(MYSQLND_NET * const net, php_stream * net_stream TSRMLS_DC)
1150 {
1151 php_stream * ret = NULL;
1152 DBG_ENTER("mysqlnd_net::set_stream");
1153 if (net) {
1154 net->data->stream = net_stream;
1155 ret = net->data->stream;
1156 }
1157 DBG_RETURN(ret);
1158 }
1159
1160
1161
1162 MYSQLND_CLASS_METHODS_START(mysqlnd_net)
1163 MYSQLND_METHOD(mysqlnd_net, init),
1164 MYSQLND_METHOD(mysqlnd_net, dtor),
1165 MYSQLND_METHOD(mysqlnd_net, connect_ex),
1166 MYSQLND_METHOD(mysqlnd_net, close_stream),
1167 MYSQLND_METHOD(mysqlnd_net, open_pipe),
1168 MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix),
1169 MYSQLND_METHOD(mysqlnd_net, get_stream),
1170 MYSQLND_METHOD(mysqlnd_net, set_stream),
1171 MYSQLND_METHOD(mysqlnd_net, get_open_stream),
1172 MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt),
1173 MYSQLND_METHOD(mysqlnd_net, set_client_option),
1174 MYSQLND_METHOD(mysqlnd_net, decode),
1175 MYSQLND_METHOD(mysqlnd_net, encode),
1176 MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data),
1177 MYSQLND_METHOD(mysqlnd_net, free_contents),
1178 MYSQLND_METHOD(mysqlnd_net, enable_ssl),
1179 MYSQLND_METHOD(mysqlnd_net, disable_ssl),
1180 MYSQLND_METHOD(mysqlnd_net, network_read_ex),
1181 MYSQLND_METHOD(mysqlnd_net, network_write_ex),
1182 MYSQLND_METHOD(mysqlnd_net, send_ex),
1183 MYSQLND_METHOD(mysqlnd_net, receive_ex),
1184 #ifdef MYSQLND_COMPRESSION_ENABLED
1185 MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buffer),
1186 #else
1187 NULL,
1188 #endif
1189 NULL,
1190 NULL,
1191 NULL,
1192 NULL,
1193 NULL
1194 MYSQLND_CLASS_METHODS_END;
1195
1196
1197
1198 PHPAPI MYSQLND_NET *
1199 mysqlnd_net_init(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
1200 {
1201 MYSQLND_NET * net;
1202 DBG_ENTER("mysqlnd_net_init");
1203 net = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_io_channel(persistent, stats, error_info TSRMLS_CC);
1204 DBG_RETURN(net);
1205 }
1206
1207
1208
1209
1210 PHPAPI void
1211 mysqlnd_net_free(MYSQLND_NET * const net, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
1212 {
1213 DBG_ENTER("mysqlnd_net_free");
1214 if (net) {
1215 net->data->m.dtor(net, stats, error_info TSRMLS_CC);
1216 }
1217 DBG_VOID_RETURN;
1218 }
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230