MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vio.c
1 /* Copyright (c) 2000, 2012, 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 as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /*
17  Note that we can't have assertion on file descriptors; The reason for
18  this is that during mysql shutdown, another thread can close a file
19  we are working on. In this case we should just return read errors from
20  the file descriptior.
21 */
22 
23 #include "vio_priv.h"
24 
25 #ifdef _WIN32
26 
40 static int no_io_wait(Vio *vio __attribute__((unused)),
41  enum enum_vio_io_event event __attribute__((unused)),
42  int timeout __attribute__((unused)))
43 {
44  return 1;
45 }
46 
47 #endif
48 
49 static my_bool has_no_data(Vio *vio __attribute__((unused)))
50 {
51  return FALSE;
52 }
53 
54 /*
55  * Helper to fill most of the Vio* with defaults.
56  */
57 
58 static void vio_init(Vio *vio, enum enum_vio_type type,
59  my_socket sd, uint flags)
60 {
61  DBUG_ENTER("vio_init");
62  DBUG_PRINT("enter", ("type: %d sd: %d flags: %d", type, sd, flags));
63 
64 #ifndef HAVE_VIO_READ_BUFF
65  flags&= ~VIO_BUFFERED_READ;
66 #endif
67  memset(vio, 0, sizeof(*vio));
68  vio->type= type;
69  vio->mysql_socket= MYSQL_INVALID_SOCKET;
70  mysql_socket_setfd(&vio->mysql_socket, sd);
71  vio->localhost= flags & VIO_LOCALHOST;
72  vio->read_timeout= vio->write_timeout= -1;
73  if ((flags & VIO_BUFFERED_READ) &&
74  !(vio->read_buffer= (char*)my_malloc(VIO_READ_BUFFER_SIZE, MYF(MY_WME))))
75  flags&= ~VIO_BUFFERED_READ;
76 #ifdef _WIN32
77  if (type == VIO_TYPE_NAMEDPIPE)
78  {
79  vio->viodelete =vio_delete;
80  vio->vioerrno =vio_errno;
81  vio->read =vio_read_pipe;
82  vio->write =vio_write_pipe;
83  vio->fastsend =vio_fastsend;
84  vio->viokeepalive =vio_keepalive;
85  vio->should_retry =vio_should_retry;
86  vio->was_timeout =vio_was_timeout;
87  vio->vioshutdown =vio_shutdown_pipe;
88  vio->peer_addr =vio_peer_addr;
89  vio->io_wait =no_io_wait;
90  vio->is_connected =vio_is_connected_pipe;
91  vio->has_data =has_no_data;
92  DBUG_VOID_RETURN;
93  }
94 #endif
95 #ifdef HAVE_SMEM
96  if (type == VIO_TYPE_SHARED_MEMORY)
97  {
98  vio->viodelete =vio_delete_shared_memory;
99  vio->vioerrno =vio_errno;
100  vio->read =vio_read_shared_memory;
101  vio->write =vio_write_shared_memory;
102  vio->fastsend =vio_fastsend;
103  vio->viokeepalive =vio_keepalive;
104  vio->should_retry =vio_should_retry;
105  vio->was_timeout =vio_was_timeout;
106  vio->vioshutdown =vio_shutdown_shared_memory;
107  vio->peer_addr =vio_peer_addr;
108  vio->io_wait =no_io_wait;
109  vio->is_connected =vio_is_connected_shared_memory;
110  vio->has_data =has_no_data;
111  DBUG_VOID_RETURN;
112  }
113 #endif
114 #ifdef HAVE_OPENSSL
115  if (type == VIO_TYPE_SSL)
116  {
117  vio->viodelete =vio_ssl_delete;
118  vio->vioerrno =vio_errno;
119  vio->read =vio_ssl_read;
120  vio->write =vio_ssl_write;
121  vio->fastsend =vio_fastsend;
122  vio->viokeepalive =vio_keepalive;
123  vio->should_retry =vio_should_retry;
124  vio->was_timeout =vio_was_timeout;
125  vio->vioshutdown =vio_ssl_shutdown;
126  vio->peer_addr =vio_peer_addr;
127  vio->io_wait =vio_io_wait;
128  vio->is_connected =vio_is_connected;
129  vio->has_data =vio_ssl_has_data;
130  vio->timeout =vio_socket_timeout;
131  DBUG_VOID_RETURN;
132  }
133 #endif /* HAVE_OPENSSL */
134  vio->viodelete =vio_delete;
135  vio->vioerrno =vio_errno;
136  vio->read= (flags & VIO_BUFFERED_READ) ? vio_read_buff : vio_read;
137  vio->write =vio_write;
138  vio->fastsend =vio_fastsend;
139  vio->viokeepalive =vio_keepalive;
140  vio->should_retry =vio_should_retry;
141  vio->was_timeout =vio_was_timeout;
142  vio->vioshutdown =vio_shutdown;
143  vio->peer_addr =vio_peer_addr;
144  vio->io_wait =vio_io_wait;
145  vio->is_connected =vio_is_connected;
146  vio->timeout =vio_socket_timeout;
147  vio->has_data= (flags & VIO_BUFFERED_READ) ?
148  vio_buff_has_data : has_no_data;
149  DBUG_VOID_RETURN;
150 }
151 
152 
169 my_bool vio_reset(Vio* vio, enum enum_vio_type type,
170  my_socket sd, void *ssl __attribute__((unused)), uint flags)
171 {
172  int ret= FALSE;
173  Vio old_vio= *vio;
174  DBUG_ENTER("vio_reset");
175 
176  /* The only supported rebind is from a socket-based transport type. */
177  DBUG_ASSERT(vio->type == VIO_TYPE_TCPIP || vio->type == VIO_TYPE_SOCKET);
178 
179  /*
180  Will be reinitialized depending on the flags.
181  Nonetheless, already buffered inside the SSL layer.
182  */
183  my_free(vio->read_buffer);
184 
185  vio_init(vio, type, sd, flags);
186 
187  /* Preserve perfschema info for this connection */
188  vio->mysql_socket.m_psi= old_vio.mysql_socket.m_psi;
189 
190 #ifdef HAVE_OPENSSL
191  vio->ssl_arg= ssl;
192 #endif
193 
194  /*
195  Propagate the timeout values. Necessary to also propagate
196  the underlying proprieties associated with the timeout,
197  such as the socket blocking mode.
198  */
199  if (old_vio.read_timeout >= 0)
200  ret|= vio_timeout(vio, 0, old_vio.read_timeout);
201 
202  if (old_vio.write_timeout >= 0)
203  ret|= vio_timeout(vio, 1, old_vio.write_timeout);
204 
205  DBUG_RETURN(test(ret));
206 }
207 
208 
209 /* Create a new VIO for socket or TCP/IP connection. */
210 
211 Vio *mysql_socket_vio_new(MYSQL_SOCKET mysql_socket, enum enum_vio_type type, uint flags)
212 {
213  Vio *vio;
214  my_socket sd= mysql_socket_getfd(mysql_socket);
215  DBUG_ENTER("mysql_socket_vio_new");
216  DBUG_PRINT("enter", ("sd: %d", sd));
217  if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
218  {
219  vio_init(vio, type, sd, flags);
220  vio->mysql_socket= mysql_socket;
221  }
222  DBUG_RETURN(vio);
223 }
224 
225 /* Open the socket or TCP/IP connection and read the fnctl() status */
226 
227 Vio *vio_new(my_socket sd, enum enum_vio_type type, uint flags)
228 {
229  Vio *vio;
230  MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET;
231  DBUG_ENTER("vio_new");
232  DBUG_PRINT("enter", ("sd: %d", sd));
233 
234  mysql_socket_setfd(&mysql_socket, sd);
235  vio = mysql_socket_vio_new(mysql_socket, type, flags);
236 
237  DBUG_RETURN(vio);
238 }
239 
240 #ifdef _WIN32
241 
242 Vio *vio_new_win32pipe(HANDLE hPipe)
243 {
244  Vio *vio;
245  DBUG_ENTER("vio_new_handle");
246  if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
247  {
248  vio_init(vio, VIO_TYPE_NAMEDPIPE, 0, VIO_LOCALHOST);
249  /* Create an object for event notification. */
250  vio->overlapped.hEvent= CreateEvent(NULL, FALSE, FALSE, NULL);
251  if (vio->overlapped.hEvent == NULL)
252  {
253  my_free(vio);
254  DBUG_RETURN(NULL);
255  }
256  vio->hPipe= hPipe;
257  strmov(vio->desc, "named pipe");
258  }
259  DBUG_RETURN(vio);
260 }
261 
262 #ifdef HAVE_SMEM
263 Vio *vio_new_win32shared_memory(HANDLE handle_file_map, HANDLE handle_map,
264  HANDLE event_server_wrote, HANDLE event_server_read,
265  HANDLE event_client_wrote, HANDLE event_client_read,
266  HANDLE event_conn_closed)
267 {
268  Vio *vio;
269  DBUG_ENTER("vio_new_win32shared_memory");
270  if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
271  {
272  vio_init(vio, VIO_TYPE_SHARED_MEMORY, 0, VIO_LOCALHOST);
273  vio->handle_file_map= handle_file_map;
274  vio->handle_map= handle_map;
275  vio->event_server_wrote= event_server_wrote;
276  vio->event_server_read= event_server_read;
277  vio->event_client_wrote= event_client_wrote;
278  vio->event_client_read= event_client_read;
279  vio->event_conn_closed= event_conn_closed;
280  vio->shared_memory_remain= 0;
281  vio->shared_memory_pos= handle_map;
282  strmov(vio->desc, "shared memory");
283  }
284  DBUG_RETURN(vio);
285 }
286 #endif
287 #endif
288 
289 
306 int vio_timeout(Vio *vio, uint which, int timeout_sec)
307 {
308  int timeout_ms;
309  my_bool old_mode;
310 
311  /*
312  Vio timeouts are measured in milliseconds. Check for a possible
313  overflow. In case of overflow, set to infinite.
314  */
315  if (timeout_sec > INT_MAX/1000)
316  timeout_ms= -1;
317  else
318  timeout_ms= (int) (timeout_sec * 1000);
319 
320  /* Deduce the current timeout status mode. */
321  old_mode= vio->write_timeout < 0 && vio->read_timeout < 0;
322 
323  if (which)
324  vio->write_timeout= timeout_ms;
325  else
326  vio->read_timeout= timeout_ms;
327 
328  /* VIO-specific timeout handling. Might change the blocking mode. */
329  return vio->timeout ? vio->timeout(vio, which, old_mode) : 0;
330 }
331 
332 
333 void vio_delete(Vio* vio)
334 {
335  if (!vio)
336  return; /* It must be safe to delete null pointers. */
337 
338  if (vio->inactive == FALSE)
339  vio->vioshutdown(vio);
340  my_free(vio->read_buffer);
341  my_free(vio);
342 }
343 
344 
345 /*
346  Cleanup memory allocated by vio or the
347  components below it when application finish
348 
349 */
350 void vio_end(void)
351 {
352 #if defined(HAVE_YASSL)
353  yaSSL_CleanUp();
354 #elif defined(HAVE_OPENSSL)
355  // This one is needed on the client side
356  ERR_remove_state(0);
357  ERR_free_strings();
358  EVP_cleanup();
359  CRYPTO_cleanup_all_ex_data();
360 #endif
361 }