1
/* Copyright (C) 2000 MySQL AB
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
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
26
#include <drizzled/util/test.h>
27
#include <sys/socket.h>
29
#include <sys/types.h>
30
#include <netinet/tcp.h>
31
#include <netinet/in.h>
44
static void _vio_delete(Vio* vio)
47
return; /* It must be safe to delete null pointers. */
51
free((unsigned char*) vio);
54
static int _vio_errno(Vio *vio)
60
static size_t _vio_read(Vio * vio, unsigned char* buf, size_t size)
64
/* Ensure nobody uses vio_read_buff and vio_read simultaneously */
65
assert(vio->read_end == vio->read_pos);
66
r= read(vio->sd, buf, size);
71
static size_t _vio_write(Vio * vio, const unsigned char* buf, size_t size)
75
r = write(vio->sd, buf, size);
80
static int _vio_blocking(Vio * vio, bool set_blocking_mode, bool *old_mode)
84
*old_mode= drizzled::test(!(vio->fcntl_mode & O_NONBLOCK));
88
int old_fcntl=vio->fcntl_mode;
89
if (set_blocking_mode)
90
vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
92
vio->fcntl_mode |= O_NONBLOCK; /* set bit */
93
if (old_fcntl != vio->fcntl_mode)
95
r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
98
vio->fcntl_mode= old_fcntl;
106
static int _vio_fastsend(Vio * vio)
112
error= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
113
&nodelay, sizeof(nodelay));
116
perror("setsockopt");
123
static int32_t _vio_keepalive(Vio* vio, bool set_keep_alive)
131
r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
134
perror("setsockopt");
141
static bool _vio_should_retry(Vio * vio)
145
return (en == EAGAIN || en == EINTR ||
149
static bool _vio_was_interrupted(Vio *vio)
153
return (en == EAGAIN || en == EINTR ||
154
en == EWOULDBLOCK || en == ETIMEDOUT);
157
static int _vio_close(Vio * vio)
162
assert(vio->sd >= 0);
163
if (shutdown(vio->sd, SHUT_RDWR))
174
static bool _vio_peer_addr(Vio *vio, char *buf, uint16_t *port, size_t buflen)
177
char port_buf[NI_MAXSERV];
178
socklen_t addrLen = sizeof(vio->remote);
180
if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
185
vio->addrLen= (int)addrLen;
187
if ((error= getnameinfo((struct sockaddr *)(&vio->remote),
190
port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
195
*port= (uint16_t)strtol(port_buf, (char **)NULL, 10);
200
static void _vio_timeout(Vio *vio, bool is_sndtimeo, int32_t timeout)
204
/* POSIX specifies time as struct timeval. */
205
struct timeval wait_timeout;
206
wait_timeout.tv_sec= timeout;
207
wait_timeout.tv_usec= 0;
209
assert(timeout >= 0 && timeout <= INT32_MAX);
210
assert(vio->sd != -1);
211
error= setsockopt(vio->sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
213
(socklen_t)sizeof(struct timeval));
214
if (error == -1 && errno != ENOPROTOOPT)
216
perror("setsockopt");
221
/* Open the socket or TCP/IP connection and read the fnctl() status */
222
Vio *mysql_protocol_vio_new(int sd)
224
Vio *vio = (Vio*) malloc(sizeof(Vio));
228
memset(vio, 0, sizeof(*vio));
231
vio->viodelete= _vio_delete;
232
vio->vioerrno= _vio_errno;
233
vio->read= _vio_read;
234
vio->write= _vio_write;
235
vio->fastsend= _vio_fastsend;
236
vio->viokeepalive= _vio_keepalive;
237
vio->should_retry= _vio_should_retry;
238
vio->was_interrupted= _vio_was_interrupted;
239
vio->vioclose= _vio_close;
240
vio->peer_addr= _vio_peer_addr;
241
vio->vioblocking= _vio_blocking;
242
vio->timeout= _vio_timeout;
245
We call fcntl() to set the flags and then immediately read them back
246
to make sure that we and the system are in agreement on the state of
249
An example of why we need to do this is FreeBSD (and apparently some
250
other BSD-derived systems, like Mac OS X), where the system sometimes
251
reports that the socket is set for non-blocking when it really will
254
fcntl(sd, F_SETFL, 0);
255
vio->fcntl_mode= fcntl(sd, F_GETFL);