1 /* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 22 23 #ifndef MYSQL_ASYNC_INCLUDED 24 #define MYSQL_ASYNC_INCLUDED 25 26 #include <mysql.h> 27 28 /** 29 @file mysql_async.h 30 31 Declarations for asynchronous client communication. 32 33 @note this file should not be included as part of packaging. 34 */ 35 36 /** 37 This enum is to represent different asynchronous operations like reading the 38 network, writing to network, idle state, or complete state. 39 */ 40 enum net_async_operation { 41 NET_ASYNC_OP_IDLE = 0, /**< default state */ 42 NET_ASYNC_OP_READING, /**< used by my_net_read calls */ 43 NET_ASYNC_OP_WRITING, /**< used by my_net_write calls */ 44 NET_ASYNC_OP_COMPLETE /**< network read or write is complete */ 45 }; 46 47 /** Reading a packet is a multi-step process, so we have a state machine. */ 48 enum net_async_read_packet_state { 49 NET_ASYNC_PACKET_READ_IDLE = 0, /**< default packet read state */ 50 NET_ASYNC_PACKET_READ_HEADER, /**< read packet header */ 51 NET_ASYNC_PACKET_READ_BODY, /**< read packet contents */ 52 NET_ASYNC_PACKET_READ_COMPLETE /**< state to define if packet is 53 completely read */ 54 }; 55 56 /** Different states when reading a query result. */ 57 enum net_read_query_result_status { 58 NET_ASYNC_READ_QUERY_RESULT_IDLE = 0, /**< default state */ 59 NET_ASYNC_READ_QUERY_RESULT_FIELD_COUNT, /**< read Ok or read field 60 count sent as part of 61 COM_QUERY */ 62 NET_ASYNC_READ_QUERY_RESULT_FIELD_INFO /**< read result of above 63 COM_* command */ 64 }; 65 66 /** Sending a command involves the write as well as reading the status. */ 67 enum net_send_command_status { 68 NET_ASYNC_SEND_COMMAND_IDLE = 0, /**< default send command state */ 69 NET_ASYNC_SEND_COMMAND_WRITE_COMMAND, /**< send COM_* command */ 70 NET_ASYNC_SEND_COMMAND_READ_STATUS /**< read result of above COM_* 71 command */ 72 }; 73 74 /** 75 Async operations are broadly classified into 3 phases: 76 Connection phase, phase of sending data to server (which is writing phase) 77 and reading data from server (which is reading phase). Below enum describes 78 the same 79 */ 80 enum net_async_block_state { 81 NET_NONBLOCKING_CONNECT = 0, 82 NET_NONBLOCKING_READ, 83 NET_NONBLOCKING_WRITE 84 }; 85 86 /** 87 Represents the packet to be sent on wire asynchronously. 88 */ 89 struct io_vec { 90 void *iov_base; /**< Starting address */ 91 size_t iov_len; /**< Number of bytes to transfer */ 92 }; 93 94 typedef struct NET_ASYNC { 95 /** 96 The position in buff we continue reads from when data is next 97 available 98 */ 99 unsigned char *cur_pos; 100 /** Blocking state */ 101 enum net_async_block_state async_blocking_state; 102 /** Our current operation */ 103 enum net_async_operation async_operation; 104 /** How many bytes we want to read */ 105 size_t async_bytes_wanted; 106 /** 107 Simple state to know if we're reading the first row, and 108 command/query statuses. 109 */ 110 bool read_rows_is_first_read; 111 enum net_send_command_status async_send_command_status; 112 enum net_read_query_result_status async_read_query_result_status; 113 114 /** State when waiting on an async read */ 115 enum net_async_read_packet_state async_packet_read_state; 116 /** Size of the packet we're currently reading */ 117 size_t async_packet_length; 118 119 /** 120 Headers and vector for our async writes; see net_serv.c for 121 detailed description. 122 */ 123 unsigned char *async_write_headers; 124 struct io_vec *async_write_vector; 125 size_t async_write_vector_size; 126 size_t async_write_vector_current; 127 128 /** 129 If the packet length is less than MAX_PACKET_LENGTH then use a static array 130 to hold the meta packet header. The array either holds the usual packet 131 header or a compressed meta packet header as following. The compressed 132 meta packet header is followwed by usual compresses packet heder that is 133 7 bytes in length. 134 135 136 Packet 137 138 Header 139 ~~~~~~~~~~~~~~~~~~~ 140 B1 B2 B3 : Packet length 141 B4 : Packet number 142 ~~~~~~~~~~~~~~~~~~~ 143 144 Payload 145 ~~~~~~~~~~~~~~~~~~~ 146 B5 : COM_COMMAND 147 ~~~~~~~~~~~~~~~~~~~ 148 149 Compressed Packet 150 151 Header 152 ~~~~~~~~~~~~~~~~~~~ 153 B1 B2 B3 : Compress packet length 154 B4 : Compress Packet Nunmber 155 00 00 00 : Indicates following payload is uncompressed 156 ~~~~~~~~~~~~~~~~~~~ 157 158 Payload 159 ~~~~~~~~~~~~~~~~~~~ 160 B8 B9 B10 : Packet size 161 B11 : Packet number 162 B12 : COM_COMMAND 163 ~~~~~~~~~~~~~~~~~~~ 164 */ 165 unsigned char inline_async_write_header[NET_HEADER_SIZE + COMP_HEADER_SIZE + 166 NET_HEADER_SIZE + 1]; 167 struct io_vec inline_async_write_vector[3]; 168 169 /** Keep track of compressed buffers */ 170 unsigned char **compressed_write_buffers; 171 /** Size of the compressed buffer */ 172 size_t compressed_buffers_size; 173 } NET_ASYNC; 174 175 struct NET_EXTENSION { 176 NET_ASYNC *net_async_context; 177 mysql_compress_context compress_ctx; 178 }; 179 180 NET_EXTENSION *net_extension_init(); 181 void net_extension_free(NET *); 182 183 #define NET_EXTENSION_PTR(N) \ 184 ((NET_EXTENSION *)((N)->extension ? (N)->extension : NULL)) 185 186 #define NET_ASYNC_DATA(M) \ 187 ((NET_EXTENSION_PTR(M)) ? (NET_EXTENSION_PTR(M)->net_async_context) : NULL) 188 189 /** 190 Asynchronous operations are broadly classified into 2 categories. 191 1. Connection 192 2. Query execution 193 This classification is defined in below enum 194 */ 195 enum mysql_async_operation_status { 196 ASYNC_OP_UNSET = 0, 197 ASYNC_OP_CONNECT, 198 ASYNC_OP_QUERY 199 }; 200 201 /** 202 Query execution in an asynchronous fashion is broadly divided into 3 states 203 which is described in below enum 204 */ 205 enum mysql_async_query_state_enum { 206 QUERY_IDLE = 0, 207 QUERY_SENDING, 208 QUERY_READING_RESULT 209 }; 210 211 typedef struct MYSQL_ASYNC { 212 /** Buffer storing the rows result for cli_read_rows_nonblocking */ 213 MYSQL_DATA *rows_result_buffer; 214 /** a pointer to keep track of the previous row of the current result row */ 215 MYSQL_ROWS **prev_row_ptr; 216 /** Context needed to track the state of a connection being established */ 217 struct mysql_async_connect *connect_context; 218 /** Status of the current async op */ 219 enum mysql_async_operation_status async_op_status; 220 /** Size of the current running async query */ 221 size_t async_query_length; 222 /** If a query is running, this is its state */ 223 enum mysql_async_query_state_enum async_query_state; 224 /** context needed to support metadata read operation */ 225 unsigned long *async_read_metadata_field_len; 226 MYSQL_FIELD *async_read_metadata_fields; 227 MYSQL_ROWS async_read_metadata_data; 228 unsigned int async_read_metadata_cur_field; 229 /** a pointer to keep track of the result sets */ 230 struct MYSQL_RES *async_store_result_result; 231 } MYSQL_ASYNC; 232 233 enum net_async_status my_net_write_nonblocking(NET *net, 234 const unsigned char *packet, 235 size_t len, bool *res); 236 enum net_async_status net_write_command_nonblocking( 237 NET *net, unsigned char command, const unsigned char *prefix, 238 size_t prefix_len, const unsigned char *packet, size_t packet_len, 239 bool *res); 240 enum net_async_status my_net_read_nonblocking(NET *net, unsigned long *len_ptr); 241 242 int mysql_get_socket_descriptor(MYSQL *mysql); 243 244 #endif /* MYSQL_ASYNC_INCLUDED */ 245