~drizzle-trunk/drizzle/development

971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
1
/* Copyright (C) 2000 MySQL AB
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
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
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
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
23
#include "config.h"
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
24
#include "vio.h"
25
#include <string.h>
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
26
#include <drizzled/util/test.h>
27
#include <sys/socket.h>
28
#include <string.h>
29
#include <sys/types.h>
30
#include <netinet/tcp.h>
31
#include <netinet/in.h>
32
#include <sys/poll.h>
33
#include <unistd.h>
34
#include <fcntl.h>
35
#include <netdb.h>
36
#include <algorithm>
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
37
#include <cstdlib>
38
#include <cassert>
39
#include <cstdio>
40
#include <fcntl.h>
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
41
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
42
using namespace std;
43
44
static void _vio_delete(Vio* vio)
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
45
{
46
  if (!vio)
47
    return; /* It must be safe to delete null pointers. */
48
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
49
  if (!vio->closed)
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
50
    vio->vioclose(vio);
51
  free((unsigned char*) vio);
52
}
53
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
54
static int _vio_errno(Vio *vio)
55
{
56
  (void)vio;
57
  return errno;
58
}
59
60
static size_t _vio_read(Vio * vio, unsigned char* buf, size_t size)
61
{
62
  size_t r;
63
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);
67
68
  return r;
69
}
70
71
static size_t _vio_write(Vio * vio, const unsigned char* buf, size_t size)
72
{
73
  size_t r;
74
75
  r = write(vio->sd, buf, size);
76
77
  return r;
78
}
79
80
static int _vio_blocking(Vio * vio, bool set_blocking_mode, bool *old_mode)
81
{
82
  int r=0;
83
84
  *old_mode= drizzled::test(!(vio->fcntl_mode & O_NONBLOCK));
85
86
  if (vio->sd >= 0)
87
  {
88
    int old_fcntl=vio->fcntl_mode;
89
    if (set_blocking_mode)
90
      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
91
    else
92
      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
93
    if (old_fcntl != vio->fcntl_mode)
94
    {
95
      r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
96
      if (r == -1)
97
      {
98
        vio->fcntl_mode= old_fcntl;
99
      }
100
    }
101
  }
102
103
  return r;
104
}
105
106
static int _vio_fastsend(Vio * vio)
107
{
108
  (void)vio;
109
  int nodelay = 1;
110
  int error;
111
112
  error= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
113
                    &nodelay, sizeof(nodelay));
114
  if (error != 0)
115
  {
116
    perror("setsockopt");
117
    assert(error == 0);
118
  }
119
120
  return error;
121
}
122
123
static int32_t _vio_keepalive(Vio* vio, bool set_keep_alive)
124
{
125
  int r= 0;
126
  uint32_t opt= 0;
127
128
  if (set_keep_alive)
129
    opt= 1;
130
131
  r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
132
  if (r != 0)
133
  {
134
    perror("setsockopt");
135
    assert(r == 0);
136
  }
137
138
  return r;
139
}
140
141
static bool _vio_should_retry(Vio * vio)
142
{
143
  (void)vio;
144
  int en = errno;
145
  return (en == EAGAIN || en == EINTR ||
146
	  en == EWOULDBLOCK);
147
}
148
149
static bool _vio_was_interrupted(Vio *vio)
150
{
151
  (void)vio;
152
  int en= errno;
153
  return (en == EAGAIN || en == EINTR ||
154
	  en == EWOULDBLOCK || en == ETIMEDOUT);
155
}
156
157
static int _vio_close(Vio * vio)
158
{
159
  int r=0;
160
 if (!vio->closed)
161
  {
162
    assert(vio->sd >= 0);
163
    if (shutdown(vio->sd, SHUT_RDWR))
164
      r= -1;
165
    if (close(vio->sd))
166
      r= -1;
167
  }
168
  vio->closed= true;
169
  vio->sd=   -1;
170
171
  return r;
172
}
173
174
static bool _vio_peer_addr(Vio *vio, char *buf, uint16_t *port, size_t buflen)
175
{
176
  int error;
177
  char port_buf[NI_MAXSERV];
178
  socklen_t addrLen = sizeof(vio->remote);
179
180
  if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
181
                  &addrLen) != 0)
182
  {
183
    return true;
184
  }
185
  vio->addrLen= (int)addrLen;
186
187
  if ((error= getnameinfo((struct sockaddr *)(&vio->remote),
188
                          addrLen,
189
                          buf, buflen,
190
                          port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
191
  {
192
    return true;
193
  }
194
195
  *port= (uint16_t)strtol(port_buf, (char **)NULL, 10);
196
197
  return false;
198
}
199
200
static void _vio_timeout(Vio *vio, bool is_sndtimeo, int32_t timeout)
201
{
202
  int error;
203
204
  /* POSIX specifies time as struct timeval. */
205
  struct timeval wait_timeout;
206
  wait_timeout.tv_sec= timeout;
207
  wait_timeout.tv_usec= 0;
208
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,
212
                    &wait_timeout,
213
                    (socklen_t)sizeof(struct timeval));
214
  if (error == -1 && errno != ENOPROTOOPT)
215
  {
216
    perror("setsockopt");
217
    assert(error == 0);
218
  }
219
}
220
221
/* Open the socket or TCP/IP connection and read the fnctl() status */
222
Vio *mysql_protocol_vio_new(int sd)
223
{
224
  Vio *vio = (Vio*) malloc(sizeof(Vio));
225
  if (vio == NULL)
226
    return NULL;
227
228
  memset(vio, 0, sizeof(*vio));
229
  vio->closed= false;
230
  vio->sd= sd;
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;
243
244
  /*
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
247
    things.
248
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
252
    block.
253
  */
254
  fcntl(sd, F_SETFL, 0);
255
  vio->fcntl_mode= fcntl(sd, F_GETFL);
256
257
  return vio;
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
258
}