20
20
the file descriptior.
23
24
#include "config.h"
25
26
#include <string.h>
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)
34
* Helper to fill most of the Vio* with defaults.
37
static void drizzleclient_vio_init(Vio* vio, enum enum_vio_type type,
38
int sd, uint32_t flags)
40
memset(vio, 0, sizeof(*vio));
43
if ((flags & VIO_BUFFERED_READ) &&
44
!(vio->read_buffer= (char*)malloc(VIO_READ_BUFFER_SIZE)))
45
flags&= ~VIO_BUFFERED_READ;
47
vio->viodelete =drizzleclient_vio_delete;
48
vio->vioerrno =drizzleclient_vio_errno;
49
vio->read= (flags & VIO_BUFFERED_READ) ? drizzleclient_vio_read_buff : drizzleclient_vio_read;
50
vio->write =drizzleclient_vio_write;
51
vio->fastsend =drizzleclient_vio_fastsend;
52
vio->viokeepalive =drizzleclient_vio_keepalive;
53
vio->should_retry =drizzleclient_vio_should_retry;
54
vio->was_interrupted=drizzleclient_vio_was_interrupted;
55
vio->vioclose =drizzleclient_vio_close;
56
vio->peer_addr =drizzleclient_vio_peer_addr;
57
vio->vioblocking =drizzleclient_vio_blocking;
58
vio->is_blocking =drizzleclient_vio_is_blocking;
59
vio->timeout =drizzleclient_vio_timeout;
64
/* Reset initialized VIO to use with another transport type */
66
void drizzleclient_vio_reset(Vio* vio, enum enum_vio_type type,
67
int sd, uint32_t flags)
69
free(vio->read_buffer);
70
drizzleclient_vio_init(vio, type, sd, flags);
74
/* Open the socket or TCP/IP connection and read the fnctl() status */
76
Vio *drizzleclient_vio_new(int sd, enum enum_vio_type type, uint32_t flags)
78
Vio *vio = (Vio*) malloc(sizeof(Vio));
82
drizzleclient_vio_init(vio, type, sd, flags);
83
sprintf(vio->desc, "TCP/IP (%d)", vio->sd);
85
We call fcntl() to set the flags and then immediately read them back
86
to make sure that we and the system are in agreement on the state of
89
An example of why we need to do this is FreeBSD (and apparently some
90
other BSD-derived systems, like Mac OS X), where the system sometimes
91
reports that the socket is set for non-blocking when it really will
94
fcntl(sd, F_SETFL, 0);
95
vio->fcntl_mode= fcntl(sd, F_GETFL);
101
void drizzleclient_vio_delete(Vio* vio)
47
104
return; /* It must be safe to delete null pointers. */
106
if (vio->type != VIO_CLOSED)
50
107
vio->vioclose(vio);
108
free((unsigned char*) vio->read_buffer);
51
109
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);
114
Cleanup memory allocated by vio or the
115
components below it when application finish
118
void drizzleclient_vio_end(void)