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

Last change on this file since 31874 was 31874, checked in by brainslayer, 6 weeks ago

update php

File size: 49.1 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_auth.h"
25#include "mysqlnd_wireprotocol.h"
26#include "mysqlnd_statistics.h"
27#include "mysqlnd_debug.h"
28
29
30struct st_mysqlnd_protocol_no_params_command
31{
32        struct st_mysqlnd_protocol_command parent;
33        struct st_mysqlnd_protocol_no_params_command_context
34        {
35                MYSQLND_CONN_DATA * conn;
36        } context;
37};
38
39/* {{{ mysqlnd_com_no_params_free_command */
40static void
41mysqlnd_com_no_params_free_command(void * command)
42{
43        DBG_ENTER("mysqlnd_com_no_params_free_command");
44        mnd_efree(command);
45        DBG_VOID_RETURN;
46}
47/* }}} */
48
49
50/************************** COM_SET_OPTION ******************************************/
51struct st_mysqlnd_protocol_com_set_option_command
52{
53        struct st_mysqlnd_protocol_command parent;
54        struct st_mysqlnd_com_set_option_context
55        {
56                MYSQLND_CONN_DATA * conn;
57                enum_mysqlnd_server_option option;
58        } context;
59};
60
61
62/* {{{ mysqlnd_com_set_option_run */
63enum_func_status
64mysqlnd_com_set_option_run(void *cmd)
65{
66        struct st_mysqlnd_protocol_com_set_option_command * command = (struct st_mysqlnd_protocol_com_set_option_command *) cmd;
67        zend_uchar buffer[2];
68        enum_func_status ret = FAIL;
69        MYSQLND_CONN_DATA * conn = command->context.conn;
70        enum_mysqlnd_server_option option = command->context.option;
71        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
72        func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
73
74        DBG_ENTER("mysqlnd_com_set_option_run");
75        int2store(buffer, (unsigned int) option);
76
77        ret = send_command(conn->payload_decoder_factory, COM_SET_OPTION, buffer, sizeof(buffer), FALSE,
78                                           &conn->state,
79                                           conn->error_info,
80                                           conn->upsert_status,
81                                           conn->stats,
82                                           conn->m->send_close,
83                                           conn);
84        if (PASS == ret) {
85                ret = send_command_handle_response(conn->payload_decoder_factory, PROT_EOF_PACKET, FALSE, COM_SET_OPTION, TRUE,
86                                                   conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
87        }
88        DBG_RETURN(ret);
89}
90/* }}} */
91
92
93/* {{{ mysqlnd_com_set_option_create_command */
94static struct st_mysqlnd_protocol_command *
95mysqlnd_com_set_option_create_command(va_list args)
96{
97        struct st_mysqlnd_protocol_com_set_option_command * command;
98        DBG_ENTER("mysqlnd_com_set_option_create_command");
99        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_set_option_command));
100        if (command) {
101                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
102                command->context.option = va_arg(args, enum_mysqlnd_server_option);
103
104                command->parent.free_command = mysqlnd_com_no_params_free_command;
105                command->parent.run = mysqlnd_com_set_option_run;
106        }
107
108        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
109}
110/* }}} */
111
112
113/************************** COM_DEBUG ******************************************/
114/* {{{ mysqlnd_com_debug_run */
115static enum_func_status
116mysqlnd_com_debug_run(void *cmd)
117{
118        struct st_mysqlnd_protocol_no_params_command * command = (struct st_mysqlnd_protocol_no_params_command *) cmd;
119        enum_func_status ret = FAIL;
120        MYSQLND_CONN_DATA * conn = command->context.conn;
121        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
122        func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
123
124        DBG_ENTER("mysqlnd_com_debug_run");
125
126        ret = send_command(conn->payload_decoder_factory, COM_DEBUG, NULL, 0, FALSE,
127                                           &conn->state,
128                                           conn->error_info,
129                                           conn->upsert_status,
130                                           conn->stats,
131                                           conn->m->send_close,
132                                           conn);
133        if (PASS == ret) {
134                ret = send_command_handle_response(conn->payload_decoder_factory, PROT_EOF_PACKET, FALSE, COM_DEBUG, TRUE,
135                                                                                   conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
136        }
137
138        DBG_RETURN(ret);
139}
140/* }}} */
141
142
143/* {{{ mysqlnd_com_debug_create_command */
144static struct st_mysqlnd_protocol_command *
145mysqlnd_com_debug_create_command(va_list args)
146{
147        struct st_mysqlnd_protocol_no_params_command * command;
148        DBG_ENTER("mysqlnd_com_debug_create_command");
149        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_no_params_command));
150        if (command) {
151                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
152                command->parent.free_command = mysqlnd_com_no_params_free_command;
153
154                command->parent.run = mysqlnd_com_debug_run;
155        }
156
157        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
158}
159/* }}} */
160
161
162/************************** COM_INIT_DB ******************************************/
163struct st_mysqlnd_protocol_com_init_db_command
164{
165        struct st_mysqlnd_protocol_command parent;
166        struct st_mysqlnd_com_init_db_context
167        {
168                MYSQLND_CONN_DATA * conn;
169                MYSQLND_CSTRING db;
170        } context;
171};
172
173
174/* {{{ mysqlnd_com_init_db_run */
175static enum_func_status
176mysqlnd_com_init_db_run(void *cmd)
177{
178        struct st_mysqlnd_protocol_com_init_db_command * command = (struct st_mysqlnd_protocol_com_init_db_command *) cmd;
179        enum_func_status ret = FAIL;
180        MYSQLND_CONN_DATA * conn = command->context.conn;
181        const MYSQLND_CSTRING db = command->context.db;
182        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
183        func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
184
185        DBG_ENTER("mysqlnd_com_init_db_run");
186
187        ret = send_command(conn->payload_decoder_factory, COM_INIT_DB, (zend_uchar*) command->context.db.s, command->context.db.l, FALSE,
188                                           &conn->state,
189                                           conn->error_info,
190                                           conn->upsert_status,
191                                           conn->stats,
192                                           conn->m->send_close,
193                                           conn);
194        if (PASS == ret) {
195                ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, FALSE, COM_INIT_DB, TRUE,
196                                                                                   conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
197        }
198
199        /*
200          The server sends 0 but libmysql doesn't read it and has established
201          a protocol of giving back -1. Thus we have to follow it :(
202        */
203        UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
204        if (ret == PASS) {
205                if (conn->connect_or_select_db.s) {
206                        mnd_pefree(conn->connect_or_select_db.s, conn->persistent);
207                }
208                conn->connect_or_select_db.s = mnd_pestrndup(db.s, db.l, conn->persistent);
209                conn->connect_or_select_db.l = db.l;
210                if (!conn->connect_or_select_db.s) {
211                        /* OOM */
212                        SET_OOM_ERROR(conn->error_info);
213                        ret = FAIL;
214                }
215        }
216
217        DBG_RETURN(ret);
218}
219/* }}} */
220
221
222/* {{{ mysqlnd_com_init_db_create_command */
223static struct st_mysqlnd_protocol_command *
224mysqlnd_com_init_db_create_command(va_list args)
225{
226        struct st_mysqlnd_protocol_com_init_db_command * command;
227        DBG_ENTER("mysqlnd_com_init_db_create_command");
228        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_init_db_command));
229        if (command) {
230                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
231                command->context.db = va_arg(args, MYSQLND_CSTRING);
232
233                command->parent.free_command = mysqlnd_com_no_params_free_command;
234                command->parent.run = mysqlnd_com_init_db_run;
235        }
236
237        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
238}
239/* }}} */
240
241
242/************************** COM_PING ******************************************/
243/* {{{ mysqlnd_com_ping_run */
244static enum_func_status
245mysqlnd_com_ping_run(void *cmd)
246{
247        struct st_mysqlnd_protocol_no_params_command * command = (struct st_mysqlnd_protocol_no_params_command *) cmd;
248        enum_func_status ret = FAIL;
249        MYSQLND_CONN_DATA * conn = command->context.conn;
250        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
251        func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
252
253        DBG_ENTER("mysqlnd_com_ping_run");
254
255        ret = send_command(conn->payload_decoder_factory, COM_PING, NULL, 0, TRUE,
256                                           &conn->state,
257                                           conn->error_info,
258                                           conn->upsert_status,
259                                           conn->stats,
260                                           conn->m->send_close,
261                                           conn);
262        if (PASS == ret) {
263                ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, TRUE, COM_PING, TRUE,
264                                                                                   conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
265        }
266        /*
267          The server sends 0 but libmysql doesn't read it and has established
268          a protocol of giving back -1. Thus we have to follow it :(
269        */
270        UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
271
272        DBG_RETURN(ret);
273}
274/* }}} */
275
276
277/* {{{ mysqlnd_com_ping_create_command */
278static struct st_mysqlnd_protocol_command *
279mysqlnd_com_ping_create_command(va_list args)
280{
281        struct st_mysqlnd_protocol_no_params_command * command;
282        DBG_ENTER("mysqlnd_com_ping_create_command");
283        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_no_params_command));
284        if (command) {
285                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
286                command->parent.free_command = mysqlnd_com_no_params_free_command;
287
288                command->parent.run = mysqlnd_com_ping_run;
289        }
290
291        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
292}
293/* }}} */
294
295
296/************************** COM_STATISTICS ******************************************/
297struct st_mysqlnd_protocol_com_statistics_command
298{
299        struct st_mysqlnd_protocol_command parent;
300        struct st_mysqlnd_com_statistics_context
301        {
302                MYSQLND_CONN_DATA * conn;
303                zend_string ** message;
304        } context;
305};
306
307
308/* {{{ mysqlnd_com_statistics_run */
309static enum_func_status
310mysqlnd_com_statistics_run(void *cmd)
311{
312        struct st_mysqlnd_protocol_com_statistics_command * command = (struct st_mysqlnd_protocol_com_statistics_command *) cmd;
313        enum_func_status ret = FAIL;
314        MYSQLND_CONN_DATA * conn = command->context.conn;
315        zend_string **message = command->context.message;
316        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
317
318        DBG_ENTER("mysqlnd_com_statistics_run");
319
320        ret = send_command(conn->payload_decoder_factory, COM_STATISTICS, NULL, 0, FALSE,
321                                           &conn->state,
322                                           conn->error_info,
323                                           conn->upsert_status,
324                                           conn->stats,
325                                           conn->m->send_close,
326                                           conn);
327
328        if (PASS == ret) {
329                MYSQLND_PACKET_STATS * stats_header = conn->payload_decoder_factory->m.get_stats_packet(conn->payload_decoder_factory, FALSE);
330                if (!stats_header) {
331                        SET_OOM_ERROR(conn->error_info);
332                } else {
333                        if (PASS == (ret = PACKET_READ(stats_header))) {
334                                /* will be freed by Zend, thus don't use the mnd_ allocator */
335                                *message = zend_string_init(stats_header->message.s, stats_header->message.l, 0);
336                                DBG_INF(ZSTR_VAL(*message));
337                        }
338                        PACKET_FREE(stats_header);
339                }
340        }
341
342        DBG_RETURN(ret);
343}
344/* }}} */
345
346
347/* {{{ mysqlnd_com_statistics_create_command */
348static struct st_mysqlnd_protocol_command *
349mysqlnd_com_statistics_create_command(va_list args)
350{
351        struct st_mysqlnd_protocol_com_statistics_command * command;
352        DBG_ENTER("mysqlnd_com_statistics_create_command");
353        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_statistics_command));
354        if (command) {
355                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
356                command->context.message = va_arg(args, zend_string **);
357
358                command->parent.free_command = mysqlnd_com_no_params_free_command;
359                command->parent.run = mysqlnd_com_statistics_run;
360        }
361
362        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
363}
364/* }}} */
365
366/************************** COM_PROCESS_KILL ******************************************/
367struct st_mysqlnd_protocol_com_process_kill_command
368{
369        struct st_mysqlnd_protocol_command parent;
370        struct st_mysqlnd_com_process_kill_context
371        {
372                MYSQLND_CONN_DATA * conn;
373                unsigned int process_id;
374                zend_bool read_response;
375        } context;
376};
377
378
379/* {{{ mysqlnd_com_process_kill_run */
380enum_func_status
381mysqlnd_com_process_kill_run(void *cmd)
382{
383        struct st_mysqlnd_protocol_com_process_kill_command * command = (struct st_mysqlnd_protocol_com_process_kill_command *) cmd;
384        zend_uchar buff[4];
385        enum_func_status ret = FAIL;
386        MYSQLND_CONN_DATA * conn = command->context.conn;
387        zend_bool read_response = command->context.read_response;
388        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
389        func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
390
391        DBG_ENTER("mysqlnd_com_process_kill_run");
392        int4store(buff, command->context.process_id);
393
394        ret = send_command(conn->payload_decoder_factory, COM_PROCESS_KILL, buff, 4, FALSE,
395                                           &conn->state,
396                                           conn->error_info,
397                                           conn->upsert_status,
398                                           conn->stats,
399                                           conn->m->send_close,
400                                           conn);
401        if (PASS == ret && read_response) {
402                ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, FALSE, COM_PROCESS_KILL, TRUE,
403                                                                                   conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
404        }
405
406        if (read_response) {
407                /*
408                  The server sends 0 but libmysql doesn't read it and has established
409                  a protocol of giving back -1. Thus we have to follow it :(
410                */
411                UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
412        } else if (PASS == ret) {
413                SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
414                conn->m->send_close(conn);
415        }
416
417        DBG_RETURN(ret);
418}
419/* }}} */
420
421
422/* {{{ mysqlnd_com_process_kill_create_command */
423static struct st_mysqlnd_protocol_command *
424mysqlnd_com_process_kill_create_command(va_list args)
425{
426        struct st_mysqlnd_protocol_com_process_kill_command * command;
427        DBG_ENTER("mysqlnd_com_process_kill_create_command");
428        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_process_kill_command));
429        if (command) {
430                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
431                command->context.process_id = va_arg(args, unsigned int);
432                command->context.read_response = va_arg(args, unsigned int)? TRUE:FALSE;
433
434                command->parent.free_command = mysqlnd_com_no_params_free_command;
435                command->parent.run = mysqlnd_com_process_kill_run;
436        }
437
438        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
439}
440/* }}} */
441
442/************************** COM_REFRESH ******************************************/
443struct st_mysqlnd_protocol_com_refresh_command
444{
445        struct st_mysqlnd_protocol_command parent;
446        struct st_mysqlnd_com_refresh_context
447        {
448                MYSQLND_CONN_DATA * conn;
449                uint8_t options;
450        } context;
451};
452
453
454/* {{{ mysqlnd_com_refresh_run */
455enum_func_status
456mysqlnd_com_refresh_run(void *cmd)
457{
458        struct st_mysqlnd_protocol_com_refresh_command * command = (struct st_mysqlnd_protocol_com_refresh_command *) cmd;
459        zend_uchar bits[1];
460        enum_func_status ret = FAIL;
461        MYSQLND_CONN_DATA * conn = command->context.conn;
462        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
463        func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
464
465        DBG_ENTER("mysqlnd_com_refresh_run");
466        int1store(bits, command->context.options);
467
468        ret = send_command(conn->payload_decoder_factory, COM_REFRESH, bits, 1, FALSE,
469                                           &conn->state,
470                                           conn->error_info,
471                                           conn->upsert_status,
472                                           conn->stats,
473                                           conn->m->send_close,
474                                           conn);
475        if (PASS == ret) {
476                ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, FALSE, COM_REFRESH, TRUE,
477                                                                                   conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
478        }
479
480        DBG_RETURN(ret);
481}
482/* }}} */
483
484
485/* {{{ mysqlnd_com_refresh_create_command */
486static struct st_mysqlnd_protocol_command *
487mysqlnd_com_refresh_create_command(va_list args)
488{
489        struct st_mysqlnd_protocol_com_refresh_command * command;
490        DBG_ENTER("mysqlnd_com_refresh_create_command");
491        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_refresh_command));
492        if (command) {
493                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
494                command->context.options = va_arg(args, unsigned int);
495
496                command->parent.free_command = mysqlnd_com_no_params_free_command;
497                command->parent.run = mysqlnd_com_refresh_run;
498        }
499
500        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
501}
502/* }}} */
503
504
505/************************** COM_SHUTDOWN ******************************************/
506struct st_mysqlnd_protocol_com_shutdown_command
507{
508        struct st_mysqlnd_protocol_command parent;
509        struct st_mysqlnd_com_shutdown_context
510        {
511                MYSQLND_CONN_DATA * conn;
512                uint8_t level;
513        } context;
514};
515
516
517/* {{{ mysqlnd_com_shutdown_run */
518enum_func_status
519mysqlnd_com_shutdown_run(void *cmd)
520{
521        struct st_mysqlnd_protocol_com_shutdown_command * command = (struct st_mysqlnd_protocol_com_shutdown_command *) cmd;
522        zend_uchar bits[1];
523        enum_func_status ret = FAIL;
524        MYSQLND_CONN_DATA * conn = command->context.conn;
525        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
526        func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
527
528        DBG_ENTER("mysqlnd_com_shutdown_run");
529        int1store(bits, command->context.level);
530
531        ret = send_command(conn->payload_decoder_factory, COM_SHUTDOWN, bits, 1, FALSE,
532                                           &conn->state,
533                                           conn->error_info,
534                                           conn->upsert_status,
535                                           conn->stats,
536                                           conn->m->send_close,
537                                           conn);
538        if (PASS == ret) {
539                ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, FALSE, COM_SHUTDOWN, TRUE,
540                                                                                   conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
541        }
542
543        DBG_RETURN(ret);
544}
545/* }}} */
546
547
548/* {{{ mysqlnd_com_shutdown_create_command */
549static struct st_mysqlnd_protocol_command *
550mysqlnd_com_shutdown_create_command(va_list args)
551{
552        struct st_mysqlnd_protocol_com_shutdown_command * command;
553        DBG_ENTER("mysqlnd_com_shutdown_create_command");
554        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_shutdown_command));
555        if (command) {
556                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
557                command->context.level = va_arg(args, unsigned int);
558
559                command->parent.free_command = mysqlnd_com_no_params_free_command;
560                command->parent.run = mysqlnd_com_shutdown_run;
561        }
562
563        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
564}
565/* }}} */
566
567
568/************************** COM_QUIT ******************************************/
569struct st_mysqlnd_protocol_com_quit_command
570{
571        struct st_mysqlnd_protocol_command parent;
572        struct st_mysqlnd_com_quit_context
573        {
574                MYSQLND_CONN_DATA * conn;
575        } context;
576};
577
578
579/* {{{ mysqlnd_com_quit_run */
580enum_func_status
581mysqlnd_com_quit_run(void *cmd)
582{
583        struct st_mysqlnd_protocol_com_quit_command * command = (struct st_mysqlnd_protocol_com_quit_command *) cmd;
584        enum_func_status ret = FAIL;
585        MYSQLND_CONN_DATA * conn = command->context.conn;
586        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
587
588        DBG_ENTER("mysqlnd_com_quit_run");
589
590        ret = send_command(conn->payload_decoder_factory, COM_QUIT, NULL, 0, TRUE,
591                                           &conn->state,
592                                           conn->error_info,
593                                           conn->upsert_status,
594                                           conn->stats,
595                                           conn->m->send_close,
596                                           conn);
597
598        DBG_RETURN(ret);
599}
600/* }}} */
601
602
603/* {{{ mysqlnd_com_quit_create_command */
604static struct st_mysqlnd_protocol_command *
605mysqlnd_com_quit_create_command(va_list args)
606{
607        struct st_mysqlnd_protocol_com_quit_command * command;
608        DBG_ENTER("mysqlnd_com_quit_create_command");
609        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_quit_command));
610        if (command) {
611                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
612
613                command->parent.free_command = mysqlnd_com_no_params_free_command;
614                command->parent.run = mysqlnd_com_quit_run;
615        }
616
617        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
618}
619/* }}} */
620
621/************************** COM_QUERY ******************************************/
622struct st_mysqlnd_protocol_com_query_command
623{
624        struct st_mysqlnd_protocol_command parent;
625        struct st_mysqlnd_com_query_context
626        {
627                MYSQLND_CONN_DATA * conn;
628                MYSQLND_CSTRING query;
629        } context;
630};
631
632
633/* {{{ mysqlnd_com_query_run */
634static enum_func_status
635mysqlnd_com_query_run(void *cmd)
636{
637        struct st_mysqlnd_protocol_com_query_command * command = (struct st_mysqlnd_protocol_com_query_command *) cmd;
638        enum_func_status ret = FAIL;
639        MYSQLND_CONN_DATA * conn = command->context.conn;
640        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
641
642        DBG_ENTER("mysqlnd_com_query_run");
643
644        ret = send_command(conn->payload_decoder_factory, COM_QUERY, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE,
645                                           &conn->state,
646                                           conn->error_info,
647                                           conn->upsert_status,
648                                           conn->stats,
649                                           conn->m->send_close,
650                                           conn);
651
652        if (PASS == ret) {
653                SET_CONNECTION_STATE(&conn->state, CONN_QUERY_SENT);
654        }
655
656        DBG_RETURN(ret);
657}
658/* }}} */
659
660
661/* {{{ mysqlnd_com_query_create_command */
662static struct st_mysqlnd_protocol_command *
663mysqlnd_com_query_create_command(va_list args)
664{
665        struct st_mysqlnd_protocol_com_query_command * command;
666        DBG_ENTER("mysqlnd_com_query_create_command");
667        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_query_command));
668        if (command) {
669                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
670                command->context.query = va_arg(args, MYSQLND_CSTRING);
671
672                command->parent.free_command = mysqlnd_com_no_params_free_command;
673                command->parent.run = mysqlnd_com_query_run;
674        }
675
676        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
677}
678/* }}} */
679
680/************************** COM_CHANGE_USER ******************************************/
681struct st_mysqlnd_protocol_com_change_user_command
682{
683        struct st_mysqlnd_protocol_command parent;
684        struct st_mysqlnd_com_change_user_context
685        {
686                MYSQLND_CONN_DATA * conn;
687                MYSQLND_CSTRING payload;
688                zend_bool silent;
689        } context;
690};
691
692
693/* {{{ mysqlnd_com_change_user_run */
694static enum_func_status
695mysqlnd_com_change_user_run(void *cmd)
696{
697        struct st_mysqlnd_protocol_com_change_user_command * command = (struct st_mysqlnd_protocol_com_change_user_command *) cmd;
698        enum_func_status ret = FAIL;
699        MYSQLND_CONN_DATA * conn = command->context.conn;
700        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
701
702        DBG_ENTER("mysqlnd_com_change_user_run");
703
704        ret = send_command(conn->payload_decoder_factory, COM_CHANGE_USER, (zend_uchar*) command->context.payload.s, command->context.payload.l, command->context.silent,
705                                           &conn->state,
706                                           conn->error_info,
707                                           conn->upsert_status,
708                                           conn->stats,
709                                           conn->m->send_close,
710                                           conn);
711
712        DBG_RETURN(ret);
713}
714/* }}} */
715
716
717/* {{{ mysqlnd_com_change_user_create_command */
718static struct st_mysqlnd_protocol_command *
719mysqlnd_com_change_user_create_command(va_list args)
720{
721        struct st_mysqlnd_protocol_com_change_user_command * command;
722        DBG_ENTER("mysqlnd_com_change_user_create_command");
723        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_change_user_command));
724        if (command) {
725                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
726                command->context.payload = va_arg(args, MYSQLND_CSTRING);
727                command->context.silent = va_arg(args, unsigned int);
728
729                command->parent.free_command = mysqlnd_com_no_params_free_command;
730                command->parent.run = mysqlnd_com_change_user_run;
731        }
732
733        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
734}
735/* }}} */
736
737
738/************************** COM_REAP_RESULT ******************************************/
739struct st_mysqlnd_protocol_com_reap_result_command
740{
741        struct st_mysqlnd_protocol_command parent;
742        struct st_mysqlnd_com_reap_result_context
743        {
744                MYSQLND_CONN_DATA * conn;
745        } context;
746};
747
748
749/* {{{ mysqlnd_com_reap_result_run */
750static enum_func_status
751mysqlnd_com_reap_result_run(void *cmd)
752{
753        struct st_mysqlnd_protocol_com_reap_result_command * command = (struct st_mysqlnd_protocol_com_reap_result_command *) cmd;
754        enum_func_status ret = FAIL;
755        MYSQLND_CONN_DATA * conn = command->context.conn;
756        const enum_mysqlnd_connection_state state = GET_CONNECTION_STATE(&conn->state);
757
758        DBG_ENTER("mysqlnd_com_reap_result_run");
759        if (state <= CONN_READY || state == CONN_QUIT_SENT) {
760                php_error_docref(NULL, E_WARNING, "Connection not opened, clear or has been closed");
761                DBG_ERR_FMT("Connection not opened, clear or has been closed. State=%u", state);
762                DBG_RETURN(ret);
763        }
764        ret = conn->m->query_read_result_set_header(conn, NULL);
765
766        DBG_RETURN(ret);
767}
768/* }}} */
769
770
771/* {{{ mysqlnd_com_reap_result_create_command */
772static struct st_mysqlnd_protocol_command *
773mysqlnd_com_reap_result_create_command(va_list args)
774{
775        struct st_mysqlnd_protocol_com_reap_result_command * command;
776        DBG_ENTER("mysqlnd_com_reap_result_create_command");
777        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_reap_result_command));
778        if (command) {
779                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
780
781                command->parent.free_command = mysqlnd_com_no_params_free_command;
782                command->parent.run = mysqlnd_com_reap_result_run;
783        }
784
785        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
786}
787/* }}} */
788
789
790/************************** COM_STMT_PREPARE ******************************************/
791struct st_mysqlnd_protocol_com_stmt_prepare_command
792{
793        struct st_mysqlnd_protocol_command parent;
794        struct st_mysqlnd_com_stmt_prepare_context
795        {
796                MYSQLND_CONN_DATA * conn;
797                MYSQLND_CSTRING query;
798        } context;
799};
800
801
802/* {{{ mysqlnd_com_stmt_prepare_run */
803static enum_func_status
804mysqlnd_com_stmt_prepare_run(void *cmd)
805{
806        struct st_mysqlnd_protocol_com_stmt_prepare_command * command = (struct st_mysqlnd_protocol_com_stmt_prepare_command *) cmd;
807        enum_func_status ret = FAIL;
808        MYSQLND_CONN_DATA * conn = command->context.conn;
809        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
810
811        DBG_ENTER("mysqlnd_com_stmt_prepare_run");
812
813        ret = send_command(conn->payload_decoder_factory, COM_STMT_PREPARE, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE,
814                                           &conn->state,
815                                           conn->error_info,
816                                           conn->upsert_status,
817                                           conn->stats,
818                                           conn->m->send_close,
819                                           conn);
820
821        DBG_RETURN(ret);
822}
823/* }}} */
824
825
826/* {{{ mysqlnd_com_stmt_prepare_create_command */
827static struct st_mysqlnd_protocol_command *
828mysqlnd_com_stmt_prepare_create_command(va_list args)
829{
830        struct st_mysqlnd_protocol_com_stmt_prepare_command * command;
831        DBG_ENTER("mysqlnd_com_stmt_prepare_create_command");
832        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_prepare_command));
833        if (command) {
834                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
835                command->context.query = va_arg(args, MYSQLND_CSTRING);
836
837                command->parent.free_command = mysqlnd_com_no_params_free_command;
838                command->parent.run = mysqlnd_com_stmt_prepare_run;
839        }
840
841        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
842}
843/* }}} */
844
845
846/************************** COM_STMT_EXECUTE ******************************************/
847struct st_mysqlnd_protocol_com_stmt_execute_command
848{
849        struct st_mysqlnd_protocol_command parent;
850        struct st_mysqlnd_com_stmt_execute_context
851        {
852                MYSQLND_CONN_DATA * conn;
853                MYSQLND_CSTRING payload;
854        } context;
855};
856
857
858/* {{{ mysqlnd_com_stmt_execute_run */
859static enum_func_status
860mysqlnd_com_stmt_execute_run(void *cmd)
861{
862        struct st_mysqlnd_protocol_com_stmt_execute_command * command = (struct st_mysqlnd_protocol_com_stmt_execute_command *) cmd;
863        enum_func_status ret = FAIL;
864        MYSQLND_CONN_DATA * conn = command->context.conn;
865        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
866
867        DBG_ENTER("mysqlnd_com_stmt_execute_run");
868
869        ret = send_command(conn->payload_decoder_factory, COM_STMT_EXECUTE, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
870                                           &conn->state,
871                                           conn->error_info,
872                                           conn->upsert_status,
873                                           conn->stats,
874                                           conn->m->send_close,
875                                           conn);
876
877        DBG_RETURN(ret);
878}
879/* }}} */
880
881
882/* {{{ mysqlnd_com_stmt_execute_create_command */
883static struct st_mysqlnd_protocol_command *
884mysqlnd_com_stmt_execute_create_command(va_list args)
885{
886        struct st_mysqlnd_protocol_com_stmt_execute_command * command;
887        DBG_ENTER("mysqlnd_com_stmt_execute_create_command");
888        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_execute_command));
889        if (command) {
890                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
891                command->context.payload = va_arg(args, MYSQLND_CSTRING);
892
893                command->parent.free_command = mysqlnd_com_no_params_free_command;
894                command->parent.run = mysqlnd_com_stmt_execute_run;
895        }
896
897        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
898}
899/* }}} */
900
901
902/************************** COM_STMT_FETCH ******************************************/
903struct st_mysqlnd_protocol_com_stmt_fetch_command
904{
905        struct st_mysqlnd_protocol_command parent;
906        struct st_mysqlnd_com_stmt_fetch_context
907        {
908                MYSQLND_CONN_DATA * conn;
909                MYSQLND_CSTRING payload;
910        } context;
911};
912
913
914/* {{{ mysqlnd_com_stmt_fetch_run */
915static enum_func_status
916mysqlnd_com_stmt_fetch_run(void *cmd)
917{
918        struct st_mysqlnd_protocol_com_stmt_fetch_command * command = (struct st_mysqlnd_protocol_com_stmt_fetch_command *) cmd;
919        enum_func_status ret = FAIL;
920        MYSQLND_CONN_DATA * conn = command->context.conn;
921        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
922
923        DBG_ENTER("mysqlnd_com_stmt_fetch_run");
924
925        ret = send_command(conn->payload_decoder_factory, COM_STMT_FETCH, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
926                                           &conn->state,
927                                           conn->error_info,
928                                           conn->upsert_status,
929                                           conn->stats,
930                                           conn->m->send_close,
931                                           conn);
932
933        DBG_RETURN(ret);
934}
935/* }}} */
936
937
938/* {{{ mysqlnd_com_stmt_fetch_create_command */
939static struct st_mysqlnd_protocol_command *
940mysqlnd_com_stmt_fetch_create_command(va_list args)
941{
942        struct st_mysqlnd_protocol_com_stmt_fetch_command * command;
943        DBG_ENTER("mysqlnd_com_stmt_fetch_create_command");
944        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_fetch_command));
945        if (command) {
946                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
947                command->context.payload = va_arg(args, MYSQLND_CSTRING);
948
949                command->parent.free_command = mysqlnd_com_no_params_free_command;
950                command->parent.run = mysqlnd_com_stmt_fetch_run;
951        }
952
953        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
954}
955/* }}} */
956
957
958/************************** COM_STMT_RESET ******************************************/
959struct st_mysqlnd_protocol_com_stmt_reset_command
960{
961        struct st_mysqlnd_protocol_command parent;
962        struct st_mysqlnd_com_stmt_reset_context
963        {
964                MYSQLND_CONN_DATA * conn;
965                zend_ulong stmt_id;
966        } context;
967};
968
969
970/* {{{ mysqlnd_com_stmt_reset_run */
971static enum_func_status
972mysqlnd_com_stmt_reset_run(void *cmd)
973{
974        zend_uchar cmd_buf[MYSQLND_STMT_ID_LENGTH /* statement id */];
975        struct st_mysqlnd_protocol_com_stmt_reset_command * command = (struct st_mysqlnd_protocol_com_stmt_reset_command *) cmd;
976        enum_func_status ret = FAIL;
977        MYSQLND_CONN_DATA * conn = command->context.conn;
978        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
979        func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
980
981        DBG_ENTER("mysqlnd_com_stmt_reset_run");
982
983        int4store(cmd_buf, command->context.stmt_id);
984        ret = send_command(conn->payload_decoder_factory, COM_STMT_RESET, cmd_buf, sizeof(cmd_buf), FALSE,
985                                           &conn->state,
986                                           conn->error_info,
987                                           conn->upsert_status,
988                                           conn->stats,
989                                           conn->m->send_close,
990                                           conn);
991        if (PASS == ret) {
992                ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, FALSE, COM_STMT_RESET, TRUE,
993                                                                                   conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
994        }
995
996        DBG_RETURN(ret);
997}
998/* }}} */
999
1000
1001/* {{{ mysqlnd_com_stmt_reset_create_command */
1002static struct st_mysqlnd_protocol_command *
1003mysqlnd_com_stmt_reset_create_command(va_list args)
1004{
1005        struct st_mysqlnd_protocol_com_stmt_reset_command * command;
1006        DBG_ENTER("mysqlnd_com_stmt_reset_create_command");
1007        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_reset_command));
1008        if (command) {
1009                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
1010                command->context.stmt_id = va_arg(args, size_t);
1011
1012                command->parent.free_command = mysqlnd_com_no_params_free_command;
1013                command->parent.run = mysqlnd_com_stmt_reset_run;
1014        }
1015
1016        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
1017}
1018/* }}} */
1019
1020
1021/************************** COM_STMT_SEND_LONG_DATA ******************************************/
1022struct st_mysqlnd_protocol_com_stmt_send_long_data_command
1023{
1024        struct st_mysqlnd_protocol_command parent;
1025        struct st_mysqlnd_com_stmt_send_long_data_context
1026        {
1027                MYSQLND_CONN_DATA * conn;
1028                MYSQLND_CSTRING payload;
1029        } context;
1030};
1031
1032
1033/* {{{ mysqlnd_com_stmt_send_long_data_run */
1034static enum_func_status
1035mysqlnd_com_stmt_send_long_data_run(void *cmd)
1036{
1037        struct st_mysqlnd_protocol_com_stmt_send_long_data_command * command = (struct st_mysqlnd_protocol_com_stmt_send_long_data_command *) cmd;
1038        enum_func_status ret = FAIL;
1039        MYSQLND_CONN_DATA * conn = command->context.conn;
1040        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
1041
1042        DBG_ENTER("mysqlnd_com_stmt_send_long_data_run");
1043
1044        ret = send_command(conn->payload_decoder_factory, COM_STMT_SEND_LONG_DATA, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
1045                                           &conn->state,
1046                                           conn->error_info,
1047                                           conn->upsert_status,
1048                                           conn->stats,
1049                                           conn->m->send_close,
1050                                           conn);
1051
1052        DBG_RETURN(ret);
1053}
1054/* }}} */
1055
1056
1057/* {{{ mysqlnd_com_stmt_send_long_data_create_command */
1058static struct st_mysqlnd_protocol_command *
1059mysqlnd_com_stmt_send_long_data_create_command(va_list args)
1060{
1061        struct st_mysqlnd_protocol_com_stmt_send_long_data_command * command;
1062        DBG_ENTER("mysqlnd_com_stmt_send_long_data_create_command");
1063        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_send_long_data_command));
1064        if (command) {
1065                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
1066                command->context.payload = va_arg(args, MYSQLND_CSTRING);
1067
1068                command->parent.free_command = mysqlnd_com_no_params_free_command;
1069                command->parent.run = mysqlnd_com_stmt_send_long_data_run;
1070        }
1071
1072        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
1073}
1074/* }}} */
1075
1076
1077/************************** COM_STMT_CLOSE ******************************************/
1078struct st_mysqlnd_protocol_com_stmt_close_command
1079{
1080        struct st_mysqlnd_protocol_command parent;
1081        struct st_mysqlnd_com_stmt_close_context
1082        {
1083                MYSQLND_CONN_DATA * conn;
1084                zend_ulong stmt_id;
1085        } context;
1086};
1087
1088
1089/* {{{ mysqlnd_com_stmt_close_run */
1090static enum_func_status
1091mysqlnd_com_stmt_close_run(void *cmd)
1092{
1093        zend_uchar cmd_buf[MYSQLND_STMT_ID_LENGTH /* statement id */];
1094        struct st_mysqlnd_protocol_com_stmt_close_command * command = (struct st_mysqlnd_protocol_com_stmt_close_command *) cmd;
1095        enum_func_status ret = FAIL;
1096        MYSQLND_CONN_DATA * conn = command->context.conn;
1097        func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
1098
1099        DBG_ENTER("mysqlnd_com_stmt_close_run");
1100
1101        int4store(cmd_buf, command->context.stmt_id);
1102        ret = send_command(conn->payload_decoder_factory, COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf), FALSE,
1103                                           &conn->state,
1104                                           conn->error_info,
1105                                           conn->upsert_status,
1106                                           conn->stats,
1107                                           conn->m->send_close,
1108                                           conn);
1109
1110        DBG_RETURN(ret);
1111}
1112/* }}} */
1113
1114
1115/* {{{ mysqlnd_com_stmt_close_create_command */
1116static struct st_mysqlnd_protocol_command *
1117mysqlnd_com_stmt_close_create_command(va_list args)
1118{
1119        struct st_mysqlnd_protocol_com_stmt_close_command * command;
1120        DBG_ENTER("mysqlnd_com_stmt_close_create_command");
1121        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_close_command));
1122        if (command) {
1123                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
1124                command->context.stmt_id = va_arg(args, size_t);
1125
1126                command->parent.free_command = mysqlnd_com_no_params_free_command;
1127                command->parent.run = mysqlnd_com_stmt_close_run;
1128        }
1129
1130        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
1131}
1132/* }}} */
1133
1134
1135
1136/************************** COM_ENABLE_SSL ******************************************/
1137struct st_mysqlnd_protocol_com_enable_ssl_command
1138{
1139        struct st_mysqlnd_protocol_command parent;
1140        struct st_mysqlnd_com_enable_ssl_context
1141        {
1142                MYSQLND_CONN_DATA * conn;
1143                size_t client_capabilities;
1144                size_t server_capabilities;
1145                unsigned int charset_no;
1146        } context;
1147};
1148
1149
1150/* {{{ mysqlnd_com_enable_ssl_run */
1151static enum_func_status
1152mysqlnd_com_enable_ssl_run(void *cmd)
1153{
1154        struct st_mysqlnd_protocol_com_enable_ssl_command * command = (struct st_mysqlnd_protocol_com_enable_ssl_command *) cmd;
1155        enum_func_status ret = FAIL;
1156        MYSQLND_CONN_DATA * conn = command->context.conn;
1157        MYSQLND_PACKET_AUTH * auth_packet;
1158        size_t client_capabilities = command->context.client_capabilities;
1159        size_t server_capabilities = command->context.server_capabilities;
1160
1161        DBG_ENTER("mysqlnd_com_enable_ssl_run");
1162        DBG_INF_FMT("client_capability_flags=%lu", client_capabilities);
1163        DBG_INF_FMT("CLIENT_LONG_PASSWORD=      %d", client_capabilities & CLIENT_LONG_PASSWORD? 1:0);
1164        DBG_INF_FMT("CLIENT_FOUND_ROWS=         %d", client_capabilities & CLIENT_FOUND_ROWS? 1:0);
1165        DBG_INF_FMT("CLIENT_LONG_FLAG=          %d", client_capabilities & CLIENT_LONG_FLAG? 1:0);
1166        DBG_INF_FMT("CLIENT_NO_SCHEMA=          %d", client_capabilities & CLIENT_NO_SCHEMA? 1:0);
1167        DBG_INF_FMT("CLIENT_COMPRESS=           %d", client_capabilities & CLIENT_COMPRESS? 1:0);
1168        DBG_INF_FMT("CLIENT_ODBC=                       %d", client_capabilities & CLIENT_ODBC? 1:0);
1169        DBG_INF_FMT("CLIENT_LOCAL_FILES=        %d", client_capabilities & CLIENT_LOCAL_FILES? 1:0);
1170        DBG_INF_FMT("CLIENT_IGNORE_SPACE=       %d", client_capabilities & CLIENT_IGNORE_SPACE? 1:0);
1171        DBG_INF_FMT("CLIENT_PROTOCOL_41=        %d", client_capabilities & CLIENT_PROTOCOL_41? 1:0);
1172        DBG_INF_FMT("CLIENT_INTERACTIVE=        %d", client_capabilities & CLIENT_INTERACTIVE? 1:0);
1173        DBG_INF_FMT("CLIENT_SSL=                        %d", client_capabilities & CLIENT_SSL? 1:0);
1174        DBG_INF_FMT("CLIENT_IGNORE_SIGPIPE=     %d", client_capabilities & CLIENT_IGNORE_SIGPIPE? 1:0);
1175        DBG_INF_FMT("CLIENT_TRANSACTIONS=       %d", client_capabilities & CLIENT_TRANSACTIONS? 1:0);
1176        DBG_INF_FMT("CLIENT_RESERVED=           %d", client_capabilities & CLIENT_RESERVED? 1:0);
1177        DBG_INF_FMT("CLIENT_SECURE_CONNECTION=%d", client_capabilities & CLIENT_SECURE_CONNECTION? 1:0);
1178        DBG_INF_FMT("CLIENT_MULTI_STATEMENTS=%d", client_capabilities & CLIENT_MULTI_STATEMENTS? 1:0);
1179        DBG_INF_FMT("CLIENT_MULTI_RESULTS=      %d", client_capabilities & CLIENT_MULTI_RESULTS? 1:0);
1180        DBG_INF_FMT("CLIENT_PS_MULTI_RESULTS=%d", client_capabilities & CLIENT_PS_MULTI_RESULTS? 1:0);
1181        DBG_INF_FMT("CLIENT_CONNECT_ATTRS=      %d", client_capabilities & CLIENT_PLUGIN_AUTH? 1:0);
1182        DBG_INF_FMT("CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA=     %d", client_capabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA? 1:0);
1183        DBG_INF_FMT("CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS=       %d", client_capabilities & CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS? 1:0);
1184        DBG_INF_FMT("CLIENT_SESSION_TRACK=              %d", client_capabilities & CLIENT_SESSION_TRACK? 1:0);
1185        DBG_INF_FMT("CLIENT_SSL_VERIFY_SERVER_CERT=     %d", client_capabilities & CLIENT_SSL_VERIFY_SERVER_CERT? 1:0);
1186        DBG_INF_FMT("CLIENT_REMEMBER_OPTIONS=           %d", client_capabilities & CLIENT_REMEMBER_OPTIONS? 1:0);
1187
1188        auth_packet = conn->payload_decoder_factory->m.get_auth_packet(conn->payload_decoder_factory, FALSE);
1189        if (!auth_packet) {
1190                SET_OOM_ERROR(conn->error_info);
1191                goto end;
1192        }
1193        auth_packet->client_flags = client_capabilities;
1194        auth_packet->max_packet_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
1195
1196        auth_packet->charset_no = command->context.charset_no;
1197
1198#ifdef MYSQLND_SSL_SUPPORTED
1199        if (client_capabilities & CLIENT_SSL) {
1200                const zend_bool server_has_ssl = (server_capabilities & CLIENT_SSL)? TRUE:FALSE;
1201                if (server_has_ssl == FALSE) {
1202                        goto close_conn;
1203                } else {
1204                        enum mysqlnd_ssl_peer verify = client_capabilities & CLIENT_SSL_VERIFY_SERVER_CERT?
1205                                                                                                MYSQLND_SSL_PEER_VERIFY:
1206                                                                                                (client_capabilities & CLIENT_SSL_DONT_VERIFY_SERVER_CERT?
1207                                                                                                        MYSQLND_SSL_PEER_DONT_VERIFY:
1208                                                                                                        MYSQLND_SSL_PEER_DEFAULT);
1209                        DBG_INF("Switching to SSL");
1210                        if (!PACKET_WRITE(auth_packet)) {
1211                                goto close_conn;
1212                        }
1213
1214                        conn->vio->data->m.set_client_option(conn->vio, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify);
1215
1216                        if (FAIL == conn->vio->data->m.enable_ssl(conn->vio)) {
1217                                goto end;
1218                        }
1219                }
1220        }
1221#else
1222        auth_packet->client_flags &= ~CLIENT_SSL;
1223        if (!PACKET_WRITE(auth_packet)) {
1224                goto close_conn;
1225        }
1226#endif
1227        ret = PASS;
1228end:
1229        PACKET_FREE(auth_packet);
1230        DBG_RETURN(ret);
1231
1232close_conn:
1233        SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
1234        conn->m->send_close(conn);
1235        SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
1236        PACKET_FREE(auth_packet);
1237        DBG_RETURN(ret);
1238}
1239/* }}} */
1240
1241
1242/* {{{ mysqlnd_com_enable_ssl_create_command */
1243static struct st_mysqlnd_protocol_command *
1244mysqlnd_com_enable_ssl_create_command(va_list args)
1245{
1246        struct st_mysqlnd_protocol_com_enable_ssl_command * command;
1247        DBG_ENTER("mysqlnd_com_enable_ssl_create_command");
1248        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_enable_ssl_command));
1249        if (command) {
1250                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
1251                command->context.client_capabilities = va_arg(args, size_t);
1252                command->context.server_capabilities = va_arg(args, size_t);
1253                command->context.charset_no = va_arg(args, unsigned int);
1254
1255                command->parent.free_command = mysqlnd_com_no_params_free_command;
1256                command->parent.run = mysqlnd_com_enable_ssl_run;
1257        }
1258
1259        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
1260}
1261/* }}} */
1262
1263/************************** COM_READ_HANDSHAKE ******************************************/
1264struct st_mysqlnd_protocol_com_handshake_command
1265{
1266        struct st_mysqlnd_protocol_command parent;
1267        struct st_mysqlnd_com_handshake_context
1268        {
1269                MYSQLND_CONN_DATA * conn;
1270                MYSQLND_CSTRING user;
1271                MYSQLND_CSTRING passwd;
1272                MYSQLND_CSTRING database;
1273                size_t client_flags;
1274        } context;
1275};
1276
1277
1278/* {{{ mysqlnd_com_handshake_run */
1279static enum_func_status
1280mysqlnd_com_handshake_run(void *cmd)
1281{
1282        struct st_mysqlnd_protocol_com_handshake_command * command = (struct st_mysqlnd_protocol_com_handshake_command *) cmd;
1283        const char * user = command->context.user.s;
1284
1285        const char * passwd = command->context.passwd.s;
1286        size_t passwd_len = command->context.passwd.l;
1287
1288        const char * db = command->context.database.s;
1289        size_t db_len = command->context.database.l;
1290
1291        size_t mysql_flags =  command->context.client_flags;
1292
1293        MYSQLND_CONN_DATA * conn = command->context.conn;
1294        MYSQLND_PACKET_GREET * greet_packet;
1295
1296        DBG_ENTER("mysqlnd_conn_data::connect_handshake");
1297        DBG_INF_FMT("stream=%p", conn->vio->data->m.get_stream(conn->vio));
1298        DBG_INF_FMT("[user=%s] [db=%s:%d] [flags=%llu]", user, db, db_len, mysql_flags);
1299
1300        greet_packet = conn->payload_decoder_factory->m.get_greet_packet(conn->payload_decoder_factory, FALSE);
1301        if (!greet_packet) {
1302                SET_OOM_ERROR(conn->error_info);
1303                DBG_RETURN(FAIL); /* OOM */
1304        }
1305
1306        if (FAIL == PACKET_READ(greet_packet)) {
1307                DBG_ERR("Error while reading greeting packet");
1308                php_error_docref(NULL, E_WARNING, "Error while reading greeting packet. PID=%d", getpid());
1309                goto err;
1310        } else if (greet_packet->error_no) {
1311                DBG_ERR_FMT("errorno=%u error=%s", greet_packet->error_no, greet_packet->error);
1312                SET_CLIENT_ERROR(conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error);
1313                goto err;
1314        } else if (greet_packet->pre41) {
1315                DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", greet_packet->server_version);
1316                php_error_docref(NULL, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 "
1317                                                " is not supported. Server is %-.32s", greet_packet->server_version);
1318                SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
1319                                                 "Connecting to 3.22, 3.23 & 4.0 servers is not supported");
1320                goto err;
1321        }
1322
1323        conn->thread_id                 = greet_packet->thread_id;
1324        conn->protocol_version  = greet_packet->protocol_version;
1325        conn->server_version    = mnd_pestrdup(greet_packet->server_version, conn->persistent);
1326
1327        conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no);
1328        if (!conn->greet_charset) {
1329                php_error_docref(NULL, E_WARNING,
1330                        "Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no);
1331                SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
1332                        "Server sent charset unknown to the client. Please, report to the developers");
1333                goto err;
1334        }
1335
1336        conn->server_capabilities       = greet_packet->server_capabilities;
1337
1338        if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
1339                                                                                                   greet_packet->authentication_plugin_data, greet_packet->auth_protocol,
1340                                                                                                   greet_packet->charset_no, greet_packet->server_capabilities,
1341                                                                                                   conn->options, mysql_flags))
1342        {
1343                goto err;
1344        }
1345
1346        UPSERT_STATUS_RESET(conn->upsert_status);
1347        UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, greet_packet->server_status);
1348
1349        PACKET_FREE(greet_packet);
1350        DBG_RETURN(PASS);
1351err:
1352        conn->server_capabilities = 0;
1353        PACKET_FREE(greet_packet);
1354        DBG_RETURN(FAIL);
1355}
1356/* }}} */
1357
1358
1359/* {{{ mysqlnd_com_handshake_create_command */
1360static struct st_mysqlnd_protocol_command *
1361mysqlnd_com_handshake_create_command(va_list args)
1362{
1363        struct st_mysqlnd_protocol_com_handshake_command * command;
1364        DBG_ENTER("mysqlnd_com_handshake_create_command");
1365        command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_handshake_command));
1366        if (command) {
1367                command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
1368                command->context.user = *va_arg(args, const MYSQLND_CSTRING *);
1369                command->context.passwd = *va_arg(args, const MYSQLND_CSTRING *);
1370                command->context.database = *va_arg(args, const MYSQLND_CSTRING *);
1371                command->context.client_flags = va_arg(args, size_t);
1372
1373                command->parent.free_command = mysqlnd_com_no_params_free_command;
1374                command->parent.run = mysqlnd_com_handshake_run;
1375        }
1376
1377        DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
1378}
1379/* }}} */
1380
1381
1382
1383/* {{{ mysqlnd_get_command */
1384static struct st_mysqlnd_protocol_command *
1385mysqlnd_get_command(enum php_mysqlnd_server_command command, ...)
1386{
1387        struct st_mysqlnd_protocol_command * ret;
1388        va_list args;
1389        DBG_ENTER("mysqlnd_get_command");
1390
1391        va_start(args, command);
1392        switch (command) {
1393                case COM_SET_OPTION:
1394                        ret = mysqlnd_com_set_option_create_command(args);
1395                        break;
1396                case COM_DEBUG:
1397                        ret = mysqlnd_com_debug_create_command(args);
1398                        break;
1399                case COM_INIT_DB:
1400                        ret = mysqlnd_com_init_db_create_command(args);
1401                        break;
1402                case COM_PING:
1403                        ret = mysqlnd_com_ping_create_command(args);
1404                        break;
1405                case COM_STATISTICS:
1406                        ret = mysqlnd_com_statistics_create_command(args);
1407                        break;
1408                case COM_PROCESS_KILL:
1409                        ret = mysqlnd_com_process_kill_create_command(args);
1410                        break;
1411                case COM_REFRESH:
1412                        ret = mysqlnd_com_refresh_create_command(args);
1413                        break;
1414                case COM_SHUTDOWN:
1415                        ret = mysqlnd_com_shutdown_create_command(args);
1416                        break;
1417                case COM_QUIT:
1418                        ret = mysqlnd_com_quit_create_command(args);
1419                        break;
1420                case COM_QUERY:
1421                        ret = mysqlnd_com_query_create_command(args);
1422                        break;
1423                case COM_REAP_RESULT:
1424                        ret = mysqlnd_com_reap_result_create_command(args);
1425                        break;
1426                case COM_CHANGE_USER:
1427                        ret = mysqlnd_com_change_user_create_command(args);
1428                        break;
1429                case COM_STMT_PREPARE:
1430                        ret = mysqlnd_com_stmt_prepare_create_command(args);
1431                        break;
1432                case COM_STMT_EXECUTE:
1433                        ret = mysqlnd_com_stmt_execute_create_command(args);
1434                        break;
1435                case COM_STMT_FETCH:
1436                        ret = mysqlnd_com_stmt_fetch_create_command(args);
1437                        break;
1438                case COM_STMT_RESET:
1439                        ret = mysqlnd_com_stmt_reset_create_command(args);
1440                        break;
1441                case COM_STMT_SEND_LONG_DATA:
1442                        ret = mysqlnd_com_stmt_send_long_data_create_command(args);
1443                        break;
1444                case COM_STMT_CLOSE:
1445                        ret = mysqlnd_com_stmt_close_create_command(args);
1446                        break;
1447                case COM_ENABLE_SSL:
1448                        ret = mysqlnd_com_enable_ssl_create_command(args);
1449                        break;
1450                case COM_HANDSHAKE:
1451                        ret = mysqlnd_com_handshake_create_command(args);
1452                        break;
1453                default:
1454                        break;
1455        }
1456        va_end(args);
1457        DBG_RETURN(ret);
1458}
1459/* }}} */
1460
1461func_mysqlnd__command_factory mysqlnd_command_factory = mysqlnd_get_command;
1462
1463/*
1464 * Local variables:
1465 * tab-width: 4
1466 * c-basic-offset: 4
1467 * End:
1468 * vim600: noet sw=4 ts=4 fdm=marker
1469 * vim<600: noet sw=4 ts=4
1470 */
Note: See TracBrowser for help on using the repository browser.