~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to vio/viosocket.c

Merged in from trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
*/
22
22
 
23
23
#include "vio_priv.h"
24
 
#include <sys/socket.h>
25
24
 
26
25
int vio_errno(Vio *vio __attribute__((unused)))
27
26
{
28
 
  return errno;
 
27
  return socket_errno;          /* On Win32 this mapped to WSAGetLastError() */
29
28
}
30
29
 
31
30
 
32
 
size_t vio_read(Vio * vio, unsigned char* buf, size_t size)
 
31
size_t vio_read(Vio * vio, uchar* buf, size_t size)
33
32
{
34
33
  size_t r;
35
34
 
36
35
  /* Ensure nobody uses vio_read_buff and vio_read simultaneously */
37
36
  assert(vio->read_end == vio->read_pos);
38
 
  r= read(vio->sd, buf, size);
39
 
 
 
37
  errno=0;                                      /* For linux */
 
38
  r = read(vio->sd, buf, size);
40
39
  return r;
41
40
}
42
41
 
46
45
  reduce number of syscalls.
47
46
*/
48
47
 
49
 
size_t vio_read_buff(Vio *vio, unsigned char* buf, size_t size)
 
48
size_t vio_read_buff(Vio *vio, uchar* buf, size_t size)
50
49
{
51
50
  size_t rc;
52
51
#define VIO_UNBUFFERED_READ_MIN_SIZE 2048
53
52
 
54
53
  if (vio->read_pos < vio->read_end)
55
54
  {
56
 
    rc= cmin((size_t) (vio->read_end - vio->read_pos), size);
 
55
    rc= min((size_t) (vio->read_end - vio->read_pos), size);
57
56
    memcpy(buf, vio->read_pos, rc);
58
57
    vio->read_pos+= rc;
59
58
    /*
64
63
  }
65
64
  else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
66
65
  {
67
 
    rc= vio_read(vio, (unsigned char*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
 
66
    rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
68
67
    if (rc != 0 && rc != (size_t) -1)
69
68
    {
70
69
      if (rc > size)
84
83
}
85
84
 
86
85
 
87
 
size_t vio_write(Vio * vio, const unsigned char* buf, size_t size)
 
86
size_t vio_write(Vio * vio, const uchar* buf, size_t size)
88
87
{
89
88
  size_t r;
90
89
 
93
92
  return r;
94
93
}
95
94
 
96
 
int vio_blocking(Vio * vio, bool set_blocking_mode, bool *old_mode)
 
95
int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
 
96
                 my_bool *old_mode)
97
97
{
98
98
  int r=0;
99
99
 
100
100
  *old_mode= test(!(vio->fcntl_mode & O_NONBLOCK));
101
101
 
 
102
#if !defined(NO_FCNTL_NONBLOCK)
102
103
  if (vio->sd >= 0)
103
104
  {
104
105
    int old_fcntl=vio->fcntl_mode;
115
116
      }
116
117
    }
117
118
  }
118
 
 
 
119
#else
 
120
  r= set_blocking_mode ? 0 : 1;
 
121
#endif /* !defined(NO_FCNTL_NONBLOCK) */
119
122
  return r;
120
123
}
121
124
 
122
 
bool
 
125
my_bool
123
126
vio_is_blocking(Vio * vio)
124
127
{
125
 
  bool r;
 
128
  my_bool r;
126
129
  r = !(vio->fcntl_mode & O_NONBLOCK);
127
130
 
128
131
  return r;
131
134
 
132
135
int vio_fastsend(Vio * vio __attribute__((unused)))
133
136
{
134
 
  int nodelay = 1;
135
 
  int error;
136
 
 
137
 
  error= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
138
 
                    &nodelay, sizeof(nodelay));
139
 
  if (error != 0)
140
 
  {
141
 
    perror("setsockopt");
142
 
    assert(error == 0);
143
 
  }
144
 
 
145
 
  return error;
 
137
  int r=0;
 
138
 
 
139
#if defined(IPTOS_THROUGHPUT)
 
140
  {
 
141
    int tos = IPTOS_THROUGHPUT;
 
142
    r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos));
 
143
  }
 
144
#endif                                    /* IPTOS_THROUGHPUT */
 
145
  if (!r)
 
146
  {
 
147
    int nodelay = 1;
 
148
 
 
149
    r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
 
150
                  IF_WIN(const char*, void*) &nodelay,
 
151
                  sizeof(nodelay));
 
152
 
 
153
  }
 
154
  if (r)
 
155
  {
 
156
    r= -1;
 
157
  }
 
158
 
 
159
  return r;
146
160
}
147
161
 
148
 
int32_t vio_keepalive(Vio* vio, bool set_keep_alive)
 
162
int vio_keepalive(Vio* vio, my_bool set_keep_alive)
149
163
{
150
164
  int r= 0;
151
 
  uint32_t opt= 0;
152
 
 
153
 
  if (set_keep_alive)
154
 
    opt= 1;
155
 
 
156
 
  r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
157
 
  if (r != 0)
 
165
  uint opt= 0;
 
166
 
 
167
  if (vio->type != VIO_TYPE_NAMEDPIPE)
158
168
  {
159
 
    perror("setsockopt");
160
 
    assert(r == 0);
 
169
    if (set_keep_alive)
 
170
      opt= 1;
 
171
    r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
 
172
                  sizeof(opt));
161
173
  }
162
174
 
163
175
  return r;
164
176
}
165
177
 
166
178
 
167
 
bool
 
179
my_bool
168
180
vio_should_retry(Vio * vio __attribute__((unused)))
169
181
{
170
 
  int en = errno;
171
 
  return (en == EAGAIN || en == EINTR ||
172
 
          en == EWOULDBLOCK);
 
182
  int en = socket_errno;
 
183
  return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
 
184
          en == SOCKET_EWOULDBLOCK);
173
185
}
174
186
 
175
187
 
176
 
bool
 
188
my_bool
177
189
vio_was_interrupted(Vio *vio __attribute__((unused)))
178
190
{
179
 
  int en= errno;
180
 
  return (en == EAGAIN || en == EINTR ||
181
 
          en == EWOULDBLOCK || en == ETIMEDOUT);
 
191
  int en= socket_errno;
 
192
  return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
 
193
          en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
182
194
}
183
195
 
184
196
 
190
202
    assert(vio->sd >= 0);
191
203
    if (shutdown(vio->sd, SHUT_RDWR))
192
204
      r= -1;
193
 
    if (close(vio->sd))
 
205
    if (closesocket(vio->sd))
194
206
      r= -1;
195
207
  }
196
208
  vio->type= VIO_CLOSED;
210
222
  return vio->type;
211
223
}
212
224
 
213
 
int vio_fd(Vio* vio)
 
225
my_socket vio_fd(Vio* vio)
214
226
{
215
227
  return vio->sd;
216
228
}
217
229
 
218
 
bool vio_peer_addr(Vio *vio, char *buf, uint16_t *port, size_t buflen)
 
230
my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen)
219
231
{
220
 
  int error;
221
 
  char port_buf[NI_MAXSERV];
222
 
  socklen_t addrLen = sizeof(vio->remote);
223
 
 
224
 
  if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
225
 
                  &addrLen) != 0)
226
 
  {
227
 
    return true;
228
 
  }
229
 
  vio->addrLen= (int)addrLen;
230
 
 
231
 
  if ((error= getnameinfo((struct sockaddr *)(&vio->remote), 
232
 
                          addrLen,
233
 
                          buf, buflen,
234
 
                          port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
235
 
  {
236
 
    return true;
237
 
  }
238
 
 
239
 
  *port= (uint16_t)strtol(port_buf, (char **)NULL, 10);
 
232
  if (vio->localhost)
 
233
  {
 
234
    strmov(buf, "127.0.0.1");
 
235
    *port= 0;
 
236
  }
 
237
  else
 
238
  {
 
239
    int error;
 
240
    char port_buf[NI_MAXSERV];
 
241
    size_socket addrLen = sizeof(vio->remote);
 
242
    if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
 
243
                    &addrLen) != 0)
 
244
    {
 
245
      return true;
 
246
    }
 
247
    vio->addrLen= (int)addrLen;
 
248
 
 
249
    if ((error= getnameinfo((struct sockaddr *)(&vio->remote), 
 
250
                            addrLen,
 
251
                            buf, buflen,
 
252
                            port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
 
253
    {
 
254
      return true;
 
255
    }
 
256
 
 
257
    *port= (uint16)strtol(port_buf, (char **)NULL, 10);
 
258
 
 
259
    /*
 
260
      A lot of users do not have IPv6 loopback resolving to localhost
 
261
      correctly setup. Should this exist? No. If we do not do it though
 
262
      we will be getting a lot of support questions from users who
 
263
      have bad setups. This code should be removed by say... 2012.
 
264
        -Brian
 
265
    */
 
266
    if (!memcmp(buf, "::ffff:127.0.0.1", sizeof("::ffff:127.0.0.1")))
 
267
      strmov(buf, "127.0.0.1");
 
268
  }
240
269
 
241
270
  return false;
242
271
}
244
273
 
245
274
/* Return 0 if there is data to be read */
246
275
 
247
 
bool vio_poll_read(Vio *vio, int32_t timeout)
 
276
my_bool vio_poll_read(Vio *vio,uint timeout)
248
277
{
 
278
#if defined(HAVE_POLL)
249
279
  struct pollfd fds;
250
280
  int res;
251
281
 
257
287
    return res < 0 ? false : true;              /* Don't return 1 on errors */
258
288
  }
259
289
  return (fds.revents & (POLLIN | POLLERR | POLLHUP) ? false : true);
 
290
#else
 
291
  return 0;
 
292
#endif
260
293
}
261
294
 
262
295
 
263
 
bool vio_peek_read(Vio *vio, uint32_t *bytes)
 
296
my_bool vio_peek_read(Vio *vio, uint *bytes)
264
297
{
 
298
#if FIONREAD_IN_SYS_IOCTL
 
299
  int len;
 
300
  if (ioctl(vio->sd, FIONREAD, &len) < 0)
 
301
    return TRUE;
 
302
  *bytes= len;
 
303
  return FALSE;
 
304
#else
265
305
  char buf[1024];
266
306
  ssize_t res= recv(vio->sd, &buf, sizeof(buf), MSG_PEEK);
267
 
 
268
307
  if (res < 0)
269
 
    return true;
270
 
  *bytes= (uint32_t)res;
271
 
  return false;
 
308
    return TRUE;
 
309
  *bytes= res;
 
310
  return FALSE;
 
311
#endif
272
312
}
273
313
 
274
 
void vio_timeout(Vio *vio, bool is_sndtimeo, int32_t timeout)
 
314
void vio_timeout(Vio *vio, uint which, uint timeout)
275
315
{
276
 
  int error;
 
316
#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
 
317
  int r;
277
318
 
 
319
  {
278
320
  /* POSIX specifies time as struct timeval. */
279
321
  struct timeval wait_timeout;
280
322
  wait_timeout.tv_sec= timeout;
281
323
  wait_timeout.tv_usec= 0;
282
324
 
283
 
  assert(timeout >= 0 && timeout <= INT32_MAX);
284
 
  assert(vio->sd != -1);
285
 
  error= setsockopt(vio->sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
286
 
                    &wait_timeout,
287
 
                    (socklen_t)sizeof(struct timeval));
288
 
  if (error != 0)
289
 
  {
290
 
    perror("setsockopt");
291
 
    assert(error == 0);
 
325
  r= setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO,
 
326
                IF_WIN(const char*, const void*)&wait_timeout,
 
327
                sizeof(wait_timeout));
 
328
 
292
329
  }
 
330
#else
 
331
/*
 
332
  Platforms not suporting setting of socket timeout should either use
 
333
  thr_alarm or just run without read/write timeout(s)
 
334
*/
 
335
#endif
293
336
}