source: src/router/php7/ext/mysqlnd/mysqlnd_protocol_frame_codec.c @ 31874

Last change on this file since 31874 was 31874, checked in by brainslayer, 3 months ago

update php

File size: 18.4 KB
Line 
1/*
2  +----------------------------------------------------------------------+
3  | PHP Version 7                                                        |
4  +----------------------------------------------------------------------+
5  | Copyright (c) 2006-2017 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: Andrey Hristov <andrey@php.net>                             |
16  |          Ulf Wendel <uw@php.net>                                     |
17  +----------------------------------------------------------------------+
18*/
19
20#include "php.h"
21#include "mysqlnd.h"
22#include "mysqlnd_connection.h"
23#include "mysqlnd_priv.h"
24#include "mysqlnd_read_buffer.h"
25#include "mysqlnd_wireprotocol.h"
26#include "mysqlnd_statistics.h"
27#include "mysqlnd_debug.h"
28#ifdef MYSQLND_COMPRESSION_ENABLED
29#include <zlib.h>
30#endif
31
32
33/* {{{ mysqlnd_pfc::reset */
34static enum_func_status
35MYSQLND_METHOD(mysqlnd_pfc, reset)(MYSQLND_PFC * const pfc, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info)
36{
37        DBG_ENTER("mysqlnd_pfc::reset");
38        pfc->data->packet_no = pfc->data->compressed_envelope_packet_no = 0;
39        DBG_RETURN(PASS);
40}
41/* }}} */
42
43
44/* We assume that MYSQLND_HEADER_SIZE is 4 bytes !! */
45#define COPY_HEADER(T,A)  do { \
46                *(((char *)(T)))   = *(((char *)(A)));\
47                *(((char *)(T))+1) = *(((char *)(A))+1);\
48                *(((char *)(T))+2) = *(((char *)(A))+2);\
49                *(((char *)(T))+3) = *(((char *)(A))+3); } while (0)
50#define STORE_HEADER_SIZE(safe_storage, buffer)  COPY_HEADER((safe_storage), (buffer))
51#define RESTORE_HEADER_SIZE(buffer, safe_storage) STORE_HEADER_SIZE((safe_storage), (buffer))
52
53
54/* {{{ mysqlnd_pfc::send */
55/*
56  IMPORTANT : It's expected that buffer has place in the beginning for MYSQLND_HEADER_SIZE !!!!
57                          This is done for performance reasons in the caller of this function.
58                          Otherwise we will have to do send two TCP packets, or do new alloc and memcpy.
59                          Neither are quick, thus the clients of this function are obligated to do
60                          what they are asked for.
61
62  `count` is actually the length of the payload data. Thus :
63  count + MYSQLND_HEADER_SIZE = sizeof(buffer) (not the pointer but the actual buffer)
64*/
65static size_t
66MYSQLND_METHOD(mysqlnd_pfc, send)(MYSQLND_PFC * const pfc, MYSQLND_VIO * const vio, zend_uchar * const buffer, const size_t count,
67                                                                  MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info)
68{
69        zend_uchar safe_buf[((MYSQLND_HEADER_SIZE) + (sizeof(zend_uchar)) - 1) / (sizeof(zend_uchar))];
70        zend_uchar * safe_storage = safe_buf;
71        size_t bytes_sent, packets_sent = 1;
72        size_t left = count;
73        zend_uchar * p = (zend_uchar *) buffer;
74        zend_uchar * compress_buf = NULL;
75        size_t to_be_sent;
76
77        DBG_ENTER("mysqlnd_pfc::send");
78        DBG_INF_FMT("count=" MYSQLND_SZ_T_SPEC " compression=%u", count, pfc->data->compressed);
79
80        if (pfc->data->compressed == TRUE) {
81                size_t comp_buf_size = MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE + MIN(left, MYSQLND_MAX_PACKET_SIZE);
82                DBG_INF_FMT("compress_buf_size="MYSQLND_SZ_T_SPEC, comp_buf_size);
83                compress_buf = mnd_emalloc(comp_buf_size);
84        }
85
86        do {
87                to_be_sent = MIN(left, MYSQLND_MAX_PACKET_SIZE);
88                DBG_INF_FMT("to_be_sent=%u", to_be_sent);
89                DBG_INF_FMT("packets_sent=%u", packets_sent);
90                DBG_INF_FMT("compressed_envelope_packet_no=%u", pfc->data->compressed_envelope_packet_no);
91                DBG_INF_FMT("packet_no=%u", pfc->data->packet_no);
92#ifdef MYSQLND_COMPRESSION_ENABLED
93                if (pfc->data->compressed == TRUE) {
94                        /* here we need to compress the data and then write it, first comes the compressed header */
95                        size_t tmp_complen = to_be_sent;
96                        size_t payload_size;
97                        zend_uchar * uncompressed_payload = p; /* should include the header */
98
99                        STORE_HEADER_SIZE(safe_storage, uncompressed_payload);
100                        int3store(uncompressed_payload, to_be_sent);
101                        int1store(uncompressed_payload + 3, pfc->data->packet_no);
102                        if (PASS == pfc->data->m.encode((compress_buf + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE), &tmp_complen,
103                                                                           uncompressed_payload, to_be_sent + MYSQLND_HEADER_SIZE))
104                        {
105                                int3store(compress_buf + MYSQLND_HEADER_SIZE, to_be_sent + MYSQLND_HEADER_SIZE);
106                                payload_size = tmp_complen;
107                        } else {
108                                int3store(compress_buf + MYSQLND_HEADER_SIZE, 0);
109                                memcpy(compress_buf + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, uncompressed_payload, to_be_sent + MYSQLND_HEADER_SIZE);
110                                payload_size = to_be_sent + MYSQLND_HEADER_SIZE;
111                        }
112                        RESTORE_HEADER_SIZE(uncompressed_payload, safe_storage);
113
114                        int3store(compress_buf, payload_size);
115                        int1store(compress_buf + 3, pfc->data->packet_no);
116                        DBG_INF_FMT("writing "MYSQLND_SZ_T_SPEC" bytes to the network", payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE);
117                        bytes_sent = vio->data->m.network_write(vio, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, conn_stats, error_info);
118                        pfc->data->compressed_envelope_packet_no++;
119  #if WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY
120                        if (res == Z_OK) {
121                                size_t decompressed_size = left + MYSQLND_HEADER_SIZE;
122                                zend_uchar * decompressed_data = mnd_malloc(decompressed_size);
123                                int error = pfc->data->m.decode(decompressed_data, decompressed_size,
124                                                                                                compress_buf + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, payload_size);
125                                if (error == Z_OK) {
126                                        int i;
127                                        DBG_INF("success decompressing");
128                                        for (i = 0 ; i < decompressed_size; i++) {
129                                                if (i && (i % 30 == 0)) {
130                                                        printf("\n\t\t");
131                                                }
132                                                printf("%.2X ", (int)*((char*)&(decompressed_data[i])));
133                                                DBG_INF_FMT("%.2X ", (int)*((char*)&(decompressed_data[i])));
134                                        }
135                                } else {
136                                        DBG_INF("error decompressing");
137                                }
138                                mnd_free(decompressed_data);
139                        }
140  #endif /* WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY */
141                } else
142#endif /* MYSQLND_COMPRESSION_ENABLED */
143                {
144                        DBG_INF("no compression");
145                        STORE_HEADER_SIZE(safe_storage, p);
146                        int3store(p, to_be_sent);
147                        int1store(p + 3, pfc->data->packet_no);
148                        bytes_sent = vio->data->m.network_write(vio, p, to_be_sent + MYSQLND_HEADER_SIZE, conn_stats, error_info);
149                        RESTORE_HEADER_SIZE(p, safe_storage);
150                        pfc->data->compressed_envelope_packet_no++;
151                }
152                pfc->data->packet_no++;
153
154                p += to_be_sent;
155                left -= to_be_sent;
156                packets_sent++;
157                /*
158                  if left is 0 then there is nothing more to send, but if the last packet was exactly
159                  with the size MYSQLND_MAX_PACKET_SIZE we need to send additional packet, which has
160                  empty payload. Thus if left == 0 we check for to_be_sent being the max size. If it is
161                  indeed it then loop once more, then to_be_sent will become 0, left will stay 0. Empty
162                  packet will be sent and this loop will end.
163                */
164        } while (bytes_sent && (left > 0 || to_be_sent == MYSQLND_MAX_PACKET_SIZE));
165
166        DBG_INF_FMT("packet_size="MYSQLND_SZ_T_SPEC" packet_no=%u", left, pfc->data->packet_no);
167
168        MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats,
169                        STAT_BYTES_SENT, count + packets_sent * MYSQLND_HEADER_SIZE,
170                        STAT_PROTOCOL_OVERHEAD_OUT, packets_sent * MYSQLND_HEADER_SIZE,
171                        STAT_PACKETS_SENT, packets_sent);
172
173        if (compress_buf) {
174                mnd_efree(compress_buf);
175        }
176
177        /* Even for zero size payload we have to send a packet */
178        if (!bytes_sent) {
179                DBG_ERR_FMT("Can't %u send bytes", count);
180                SET_CLIENT_ERROR(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
181        }
182        DBG_RETURN(bytes_sent);
183}
184/* }}} */
185
186
187#ifdef MYSQLND_COMPRESSION_ENABLED
188
189/* {{{ mysqlnd_pfc::read_compressed_packet_from_stream_and_fill_read_buffer */
190static enum_func_status
191MYSQLND_METHOD(mysqlnd_pfc, read_compressed_packet_from_stream_and_fill_read_buffer)
192                (MYSQLND_PFC * pfc, MYSQLND_VIO * vio, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info)
193{
194        size_t decompressed_size;
195        enum_func_status retval = PASS;
196        zend_uchar * compressed_data = NULL;
197        zend_uchar comp_header[COMPRESSED_HEADER_SIZE];
198        DBG_ENTER("mysqlnd_pfc::read_compressed_packet_from_stream_and_fill_read_buffer");
199
200        /* Read the compressed header */
201        if (FAIL == vio->data->m.network_read(vio, comp_header, COMPRESSED_HEADER_SIZE, conn_stats, error_info)) {
202                DBG_RETURN(FAIL);
203        }
204        decompressed_size = uint3korr(comp_header);
205
206        /* When decompressed_size is 0, then the data is not compressed, and we have wasted 3 bytes */
207        /* we need to decompress the data */
208
209        if (decompressed_size) {
210                compressed_data = mnd_emalloc(net_payload_size);
211                if (FAIL == vio->data->m.network_read(vio, compressed_data, net_payload_size, conn_stats, error_info)) {
212                        retval = FAIL;
213                        goto end;
214                }
215                pfc->data->uncompressed_data = mysqlnd_create_read_buffer(decompressed_size);
216                retval = pfc->data->m.decode(pfc->data->uncompressed_data->data, decompressed_size, compressed_data, net_payload_size);
217                if (FAIL == retval) {
218                        goto end;
219                }
220        } else {
221                DBG_INF_FMT("The server decided not to compress the data. Our job is easy. Copying %u bytes", net_payload_size);
222                pfc->data->uncompressed_data = mysqlnd_create_read_buffer(net_payload_size);
223                if (FAIL == vio->data->m.network_read(vio, pfc->data->uncompressed_data->data, net_payload_size, conn_stats, error_info)) {
224                        retval = FAIL;
225                        goto end;
226                }
227        }
228end:
229        if (compressed_data) {
230                mnd_efree(compressed_data);
231        }
232        DBG_RETURN(retval);
233}
234/* }}} */
235#endif /* MYSQLND_COMPRESSION_ENABLED */
236
237
238/* {{{ mysqlnd_pfc::decode */
239static enum_func_status
240MYSQLND_METHOD(mysqlnd_pfc, decode)(zend_uchar * uncompressed_data, const size_t uncompressed_data_len,
241                                                                        const zend_uchar * const compressed_data, const size_t compressed_data_len)
242{
243#ifdef MYSQLND_COMPRESSION_ENABLED
244        int error;
245        uLongf tmp_complen = uncompressed_data_len;
246        DBG_ENTER("mysqlnd_pfc::decode");
247        error = uncompress(uncompressed_data, &tmp_complen, compressed_data, compressed_data_len);
248
249        DBG_INF_FMT("compressed data: decomp_len=%lu compressed_size="MYSQLND_SZ_T_SPEC, tmp_complen, compressed_data_len);
250        if (error != Z_OK) {
251                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);
252        }
253        DBG_RETURN(error == Z_OK? PASS:FAIL);
254#else
255        DBG_ENTER("mysqlnd_pfc::decode");
256        DBG_RETURN(FAIL);
257#endif
258}
259/* }}} */
260
261
262/* {{{ mysqlnd_pfc::encode */
263static enum_func_status
264MYSQLND_METHOD(mysqlnd_pfc, encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len,
265                                                                        const zend_uchar * const uncompressed_data, const size_t uncompressed_data_len)
266{
267#ifdef MYSQLND_COMPRESSION_ENABLED
268        int error;
269        uLongf tmp_complen = *compress_buffer_len;
270        DBG_ENTER("mysqlnd_pfc::encode");
271        error = compress(compress_buffer, &tmp_complen, uncompressed_data, uncompressed_data_len);
272
273        if (error != Z_OK) {
274                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);
275        } else {
276                *compress_buffer_len = tmp_complen;
277                DBG_INF_FMT("compression successful. compressed size=%lu", tmp_complen);
278        }
279
280        DBG_RETURN(error == Z_OK? PASS:FAIL);
281#else
282        DBG_ENTER("mysqlnd_pfc::encode");
283        DBG_RETURN(FAIL);
284#endif
285}
286/* }}} */
287
288
289/* {{{ mysqlnd_pfc::receive */
290static enum_func_status
291MYSQLND_METHOD(mysqlnd_pfc, receive)(MYSQLND_PFC * const pfc, MYSQLND_VIO * const vio, zend_uchar * const buffer, const size_t count,
292                                                                         MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info)
293{
294        size_t to_read = count;
295        zend_uchar * p = buffer;
296
297        DBG_ENTER("mysqlnd_pfc::receive");
298#ifdef MYSQLND_COMPRESSION_ENABLED
299        if (pfc->data->compressed) {
300                if (pfc->data->uncompressed_data) {
301                        size_t to_read_from_buffer = MIN(pfc->data->uncompressed_data->bytes_left(pfc->data->uncompressed_data), to_read);
302                        DBG_INF_FMT("reading "MYSQLND_SZ_T_SPEC" from uncompressed_data buffer", to_read_from_buffer);
303                        if (to_read_from_buffer) {
304                                pfc->data->uncompressed_data->read(pfc->data->uncompressed_data, to_read_from_buffer, (zend_uchar *) p);
305                                p += to_read_from_buffer;
306                                to_read -= to_read_from_buffer;
307                        }
308                        DBG_INF_FMT("left "MYSQLND_SZ_T_SPEC" to read", to_read);
309                        if (TRUE == pfc->data->uncompressed_data->is_empty(pfc->data->uncompressed_data)) {
310                                /* Everything was consumed. This should never happen here, but for security */
311                                pfc->data->uncompressed_data->free_buffer(&pfc->data->uncompressed_data);
312                        }
313                }
314                if (to_read) {
315                        zend_uchar net_header[MYSQLND_HEADER_SIZE];
316                        size_t net_payload_size;
317                        zend_uchar packet_no;
318
319                        if (FAIL == vio->data->m.network_read(vio, net_header, MYSQLND_HEADER_SIZE, conn_stats, error_info)) {
320                                DBG_RETURN(FAIL);
321                        }
322                        net_payload_size = uint3korr(net_header);
323                        packet_no = uint1korr(net_header + 3);
324                        if (pfc->data->compressed_envelope_packet_no != packet_no) {
325                                DBG_ERR_FMT("Transport level: packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
326                                                        pfc->data->compressed_envelope_packet_no, packet_no, net_payload_size);
327
328                                php_error(E_WARNING, "Packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
329                                                  pfc->data->compressed_envelope_packet_no, packet_no, net_payload_size);
330                                DBG_RETURN(FAIL);
331                        }
332                        pfc->data->compressed_envelope_packet_no++;
333#ifdef MYSQLND_DUMP_HEADER_N_BODY
334                        DBG_INF_FMT("HEADER: hwd_packet_no=%u size=%3u", packet_no, (zend_ulong) net_payload_size);
335#endif
336                        /* Now let's read from the wire, decompress it and fill the read buffer */
337                        pfc->data->m.read_compressed_packet_from_stream_and_fill_read_buffer(pfc, vio, net_payload_size, conn_stats, error_info);
338
339                        /*
340                          Now a bit of recursion - read from the read buffer,
341                          if the data which we have just read from the wire
342                          is not enough, then the recursive call will try to
343                          satisfy it until it is satisfied.
344                        */
345                        DBG_RETURN(pfc->data->m.receive(pfc, vio, p, to_read, conn_stats, error_info));
346                }
347                DBG_RETURN(PASS);
348        }
349#endif /* MYSQLND_COMPRESSION_ENABLED */
350        DBG_RETURN(vio->data->m.network_read(vio, p, to_read, conn_stats, error_info));
351}
352/* }}} */
353
354
355/* {{{ mysqlnd_pfc::set_client_option */
356static enum_func_status
357MYSQLND_METHOD(mysqlnd_pfc, set_client_option)(MYSQLND_PFC * const pfc, enum_mysqlnd_client_option option, const char * const value)
358{
359        DBG_ENTER("mysqlnd_pfc::set_client_option");
360        DBG_INF_FMT("option=%u", option);
361        switch (option) {
362                case MYSQL_OPT_COMPRESS:
363                        pfc->data->flags |= MYSQLND_PROTOCOL_FLAG_USE_COMPRESSION;
364                        break;
365                case MYSQL_SERVER_PUBLIC_KEY: {
366                        const zend_bool pers = pfc->persistent;
367                        if (pfc->data->sha256_server_public_key) {
368                                mnd_pefree(pfc->data->sha256_server_public_key, pers);
369                        }
370                        pfc->data->sha256_server_public_key = value? mnd_pestrdup(value, pers) : NULL;
371                        break;
372                case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
373                        DBG_INF("MYSQLND_OPT_NET_CMD_BUFFER_SIZE");
374                        if (*(unsigned int*) value < MYSQLND_NET_CMD_BUFFER_MIN_SIZE) {
375                                DBG_RETURN(FAIL);
376                        }
377                        pfc->cmd_buffer.length = *(unsigned int*) value;
378                        DBG_INF_FMT("new_length="MYSQLND_SZ_T_SPEC, pfc->cmd_buffer.length);
379                        if (!pfc->cmd_buffer.buffer) {
380                                pfc->cmd_buffer.buffer = mnd_pemalloc(pfc->cmd_buffer.length, pfc->persistent);
381                        } else {
382                                pfc->cmd_buffer.buffer = mnd_perealloc(pfc->cmd_buffer.buffer, pfc->cmd_buffer.length, pfc->persistent);
383                        }
384                        break;
385                }
386                default:
387                        DBG_RETURN(FAIL);
388        }
389        DBG_RETURN(PASS);
390}
391/* }}} */
392
393
394/* {{{ mysqlnd_pfc::free_contents */
395static void
396MYSQLND_METHOD(mysqlnd_pfc, free_contents)(MYSQLND_PFC * pfc)
397{
398        DBG_ENTER("mysqlnd_pfc::free_contents");
399
400#ifdef MYSQLND_COMPRESSION_ENABLED
401        if (pfc->data->uncompressed_data) {
402                pfc->data->uncompressed_data->free_buffer(&pfc->data->uncompressed_data);
403        }
404#endif
405        if (pfc->data->sha256_server_public_key) {
406                mnd_pefree(pfc->data->sha256_server_public_key, pfc->persistent);
407                pfc->data->sha256_server_public_key = NULL;
408        }
409
410        DBG_VOID_RETURN;
411}
412/* }}} */
413
414
415/* {{{ mysqlnd_pfc::init */
416static enum_func_status
417MYSQLND_METHOD(mysqlnd_pfc, init)(MYSQLND_PFC * const pfc, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info)
418{
419        unsigned int buf_size;
420        DBG_ENTER("mysqlnd_pfc::init");
421
422        buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/
423        pfc->data->m.set_client_option(pfc, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size);
424
425        DBG_RETURN(PASS);
426}
427/* }}} */
428
429
430/* {{{ mysqlnd_pfc::dtor */
431static void
432MYSQLND_METHOD(mysqlnd_pfc, dtor)(MYSQLND_PFC * const pfc, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info)
433{
434        DBG_ENTER("mysqlnd_pfc::dtor");
435        if (pfc) {
436                pfc->data->m.free_contents(pfc);
437
438                if (pfc->cmd_buffer.buffer) {
439                        DBG_INF("Freeing cmd buffer");
440                        mnd_pefree(pfc->cmd_buffer.buffer, pfc->persistent);
441                        pfc->cmd_buffer.buffer = NULL;
442                }
443
444                mnd_pefree(pfc->data, pfc->data->persistent);
445                mnd_pefree(pfc, pfc->persistent);
446        }
447        DBG_VOID_RETURN;
448}
449/* }}} */
450
451
452MYSQLND_CLASS_METHODS_START(mysqlnd_protocol_packet_frame_codec)
453        MYSQLND_METHOD(mysqlnd_pfc, init),
454        MYSQLND_METHOD(mysqlnd_pfc, dtor),
455        MYSQLND_METHOD(mysqlnd_pfc, reset),
456
457        MYSQLND_METHOD(mysqlnd_pfc, set_client_option),
458
459        MYSQLND_METHOD(mysqlnd_pfc, decode),
460        MYSQLND_METHOD(mysqlnd_pfc, encode),
461
462        MYSQLND_METHOD(mysqlnd_pfc, send),
463        MYSQLND_METHOD(mysqlnd_pfc, receive),
464
465#ifdef MYSQLND_COMPRESSION_ENABLED
466        MYSQLND_METHOD(mysqlnd_pfc, read_compressed_packet_from_stream_and_fill_read_buffer),
467#else
468        NULL,
469#endif
470
471        MYSQLND_METHOD(mysqlnd_pfc, free_contents),
472MYSQLND_CLASS_METHODS_END;
473
474
475/* {{{ mysqlnd_pfc_init */
476PHPAPI MYSQLND_PFC *
477mysqlnd_pfc_init(const zend_bool persistent, MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) *object_factory, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info)
478{
479        MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) *factory = object_factory? object_factory : &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory);
480        MYSQLND_PFC * pfc;
481        DBG_ENTER("mysqlnd_pfc_init");
482        pfc = factory->get_protocol_frame_codec(persistent, stats, error_info);
483        DBG_RETURN(pfc);
484}
485/* }}} */
486
487
488/* {{{ mysqlnd_pfc_free */
489PHPAPI void
490mysqlnd_pfc_free(MYSQLND_PFC * const pfc, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info)
491{
492        DBG_ENTER("mysqlnd_pfc_free");
493        if (pfc) {
494                pfc->data->m.dtor(pfc, stats, error_info);
495        }
496        DBG_VOID_RETURN;
497}
498/* }}} */
499
500
501/*
502 * Local variables:
503 * tab-width: 4
504 * c-basic-offset: 4
505 * End:
506 * vim600: noet sw=4 ts=4 fdm=marker
507 * vim<600: noet sw=4 ts=4
508 */
Note: See TracBrowser for help on using the repository browser.