~mysql/mysql-server/mysql-6.0

« back to all changes in this revision

Viewing changes to client/violite.c

  • Committer: bk at mysql
  • Date: 2000-07-31 19:29:14 UTC
  • Revision ID: sp1r-bk@work.mysql.com-20000731192914-08846
Import changeset

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
 
2
   
 
3
   This library is free software; you can redistribute it and/or
 
4
   modify it under the terms of the GNU Library General Public
 
5
   License as published by the Free Software Foundation; either
 
6
   version 2 of the License, or (at your option) any later version.
 
7
   
 
8
   This library is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
   Library General Public License for more details.
 
12
   
 
13
   You should have received a copy of the GNU Library General Public
 
14
   License along with this library; if not, write to the Free
 
15
   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 
16
   MA 02111-1307, USA */
 
17
 
 
18
#include <global.h>
 
19
 
 
20
#ifndef HAVE_VIO                        /* is Vio suppored by the Vio lib ? */
 
21
 
 
22
#include <errno.h>
 
23
#include <assert.h>
 
24
#include <violite.h>
 
25
#include <my_sys.h>
 
26
#include <my_net.h>
 
27
#include <m_string.h>
 
28
 
 
29
#if defined(__EMX__)
 
30
#include <sys/ioctl.h>
 
31
#define ioctlsocket(A,B,C) ioctl((A),(B),(void *)(C),sizeof(*(C)))
 
32
#undef HAVE_FCNTL
 
33
#endif                          /* defined(__EMX__) */
 
34
 
 
35
#if defined(MSDOS) || defined(__WIN__)
 
36
#ifdef __WIN__
 
37
#undef errno
 
38
#undef EINTR
 
39
#undef EAGAIN
 
40
#define errno WSAGetLastError()
 
41
#define EINTR  WSAEINTR
 
42
#define EAGAIN WSAEINPROGRESS
 
43
#endif /* __WIN__ */
 
44
#define O_NONBLOCK 1    /* For emulation of fcntl() */
 
45
#endif
 
46
#ifndef EWOULDBLOCK
 
47
#define EWOULDBLOCK EAGAIN
 
48
#endif
 
49
 
 
50
#ifndef __WIN__
 
51
#define HANDLE void *
 
52
#endif
 
53
 
 
54
struct st_vio
 
55
{
 
56
  my_socket             sd;             /* my_socket - real or imaginary */
 
57
  HANDLE hPipe;
 
58
  my_bool               localhost;      /* Are we from localhost? */
 
59
  int                   fcntl_mode;     /* Buffered fcntl(sd,F_GETFL) */
 
60
  my_bool               fcntl_set;      /* Have we done any fcntl yet?*/
 
61
  struct sockaddr_in    local;          /* Local internet address */
 
62
  struct sockaddr_in    remote;         /* Remote internet address */
 
63
  enum enum_vio_type    type;           /* Type of connection */
 
64
  char                  desc[30];       /* String description */
 
65
};
 
66
 
 
67
typedef void *vio_ptr;
 
68
typedef char *vio_cstring;
 
69
 
 
70
/*
 
71
 * Helper to fill most of the Vio* with defaults.
 
72
 */
 
73
 
 
74
static void vio_reset(Vio* vio, enum enum_vio_type type,
 
75
                      my_socket sd, HANDLE hPipe,
 
76
                      my_bool localhost)
 
77
{
 
78
  bzero((char*) vio, sizeof(*vio));
 
79
  vio->type     = type;
 
80
  vio->sd       = sd;
 
81
  vio->hPipe    = hPipe;
 
82
  vio->localhost= localhost;
 
83
}
 
84
 
 
85
Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
 
86
{
 
87
  Vio *vio;
 
88
  DBUG_ENTER("vio_new");
 
89
  DBUG_PRINT("enter", ("sd=%d", sd));
 
90
  if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
 
91
  {
 
92
    vio_reset(vio, type, sd, 0, localhost);
 
93
    sprintf(vio->desc, "socket (%d)", vio->sd);
 
94
  }
 
95
  DBUG_RETURN(vio);
 
96
}
 
97
 
 
98
 
 
99
#ifdef __WIN__
 
100
 
 
101
Vio *vio_new_win32pipe(HANDLE hPipe)
 
102
{
 
103
  Vio *vio;
 
104
  DBUG_ENTER("vio_new_handle");
 
105
  if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
 
106
  {
 
107
    vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE);
 
108
    strmov(vio->desc, "named pipe");
 
109
  }
 
110
  DBUG_RETURN(vio);
 
111
}
 
112
 
 
113
#endif
 
114
 
 
115
void vio_delete(Vio * vio)
 
116
{
 
117
  /* It must be safe to delete null pointers. */
 
118
  /* This matches the semantics of C++'s delete operator. */
 
119
  if (vio)
 
120
  {
 
121
    vio_close(vio);
 
122
    my_free((gptr) vio,MYF(0));
 
123
  }
 
124
}
 
125
 
 
126
int vio_errno(Vio *vio)
 
127
{
 
128
  return errno;                 /* On Win32 this mapped to WSAGetLastError() */
 
129
}
 
130
 
 
131
 
 
132
int vio_read(Vio * vio, gptr buf, int size)
 
133
{
 
134
  int r;
 
135
  DBUG_ENTER("vio_read");
 
136
  DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
 
137
  assert(vio->sd >= 0);
 
138
#ifdef __WIN__
 
139
  if (vio->type == VIO_TYPE_NAMEDPIPE)
 
140
  {
 
141
    DWORD length;
 
142
    if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
 
143
      DBUG_RETURN(-1);
 
144
    DBUG_RETURN(length);
 
145
  }
 
146
  r = recv(vio->sd, buf, size,0);
 
147
#else
 
148
  errno=0;                                      /* For linux */
 
149
  r = read(vio->sd, buf, size);
 
150
#endif /* __WIN__ */
 
151
#ifndef DBUG_OFF
 
152
  if (r < 0)
 
153
  {
 
154
    DBUG_PRINT("error", ("Got error %d during read",errno));
 
155
  }
 
156
#endif /* DBUG_OFF */
 
157
  DBUG_PRINT("exit", ("%d", r));
 
158
  DBUG_RETURN(r);
 
159
}
 
160
 
 
161
 
 
162
int vio_write(Vio * vio, const gptr buf, int size)
 
163
{
 
164
  int r;
 
165
  DBUG_ENTER("vio_write");
 
166
  DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
 
167
  assert(vio->sd >= 0);
 
168
#ifdef __WIN__
 
169
  if ( vio->type == VIO_TYPE_NAMEDPIPE)
 
170
  {
 
171
    DWORD length;
 
172
    if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
 
173
      DBUG_RETURN(-1);
 
174
    DBUG_RETURN(length);
 
175
  }
 
176
  r = send(vio->sd, buf, size,0);
 
177
#else
 
178
  r = write(vio->sd, buf, size);
 
179
#endif /* __WIN__ */
 
180
#ifndef DBUG_OFF
 
181
  if (r < 0)
 
182
  {
 
183
    DBUG_PRINT("error", ("Got error on write: %d",errno));
 
184
  }
 
185
#endif /* DBUG_OFF */
 
186
  DBUG_PRINT("exit", ("%d", r));
 
187
  DBUG_RETURN(r);
 
188
}
 
189
 
 
190
 
 
191
int vio_blocking(Vio * vio, my_bool set_blocking_mode)
 
192
{
 
193
  int r=0;
 
194
  DBUG_ENTER("vio_blocking");
 
195
  DBUG_PRINT("enter", ("set_blocking_mode: %d", (int) set_blocking_mode));
 
196
 
 
197
#if !defined(___WIN__) && !defined(__EMX__)
 
198
#if !defined(NO_FCNTL_NONBLOCK)
 
199
 
 
200
  if (vio->sd >= 0)
 
201
  {
 
202
    int old_fcntl=vio->fcntl_mode;
 
203
    if (!vio->fcntl_set)
 
204
    {
 
205
      vio->fcntl_set = TRUE;
 
206
      old_fcntl=vio->fcntl_mode = fcntl(vio->sd, F_GETFL);
 
207
    }
 
208
    if (set_blocking_mode)
 
209
      vio->fcntl_mode &= ~O_NONBLOCK; //clear bit
 
210
    else
 
211
      vio->fcntl_mode |= O_NONBLOCK; //set bit
 
212
    if (old_fcntl != vio->fcntl_mode)
 
213
      r = fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
 
214
  }
 
215
#endif /* !defined(NO_FCNTL_NONBLOCK) */
 
216
#else /* !defined(__WIN__) && !defined(__EMX__) */
 
217
#ifndef __EMX__
 
218
  if (vio->type != VIO_TYPE_NAMEDPIPE)  
 
219
#endif
 
220
  { 
 
221
    ulong arg;
 
222
    int old_fcntl=vio->fcntl_mode;
 
223
    if (!vio->fcntl_set)
 
224
    {
 
225
      vio->fcntl_set = TRUE;
 
226
      old_fnctl=vio->fcntl_mode=0;
 
227
    }
 
228
    if (set_blocking_mode)
 
229
    {
 
230
      arg = 0;
 
231
      vio->fcntl_mode &= ~O_NONBLOCK; //clear bit
 
232
    }
 
233
    else
 
234
    {
 
235
      arg = 1;
 
236
      vio->fcntl_mode |= O_NONBLOCK; //set bit
 
237
    }
 
238
    if (old_fcntl != vio->fcntl_mode)
 
239
      r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg));
 
240
  }
 
241
#endif /* !defined(__WIN__) && !defined(__EMX__) */
 
242
  DBUG_RETURN(r);
 
243
}
 
244
 
 
245
my_bool
 
246
vio_is_blocking(Vio * vio)
 
247
{
 
248
  my_bool r;
 
249
  DBUG_ENTER("vio_is_blocking");
 
250
  r = !(vio->fcntl_mode & O_NONBLOCK);
 
251
  DBUG_PRINT("exit", ("%d", (int) r));
 
252
  DBUG_RETURN(r);
 
253
}
 
254
 
 
255
 
 
256
int vio_fastsend(Vio * vio, my_bool onoff)
 
257
{
 
258
  int r=0;
 
259
  DBUG_ENTER("vio_fastsend");
 
260
  DBUG_PRINT("enter", ("onoff:%d", (int) onoff));
 
261
  assert(vio->sd >= 0);
 
262
 
 
263
#ifdef IPTOS_THROUGHPUT
 
264
  {
 
265
#ifndef __EMX__
 
266
    int tos = IPTOS_THROUGHPUT;
 
267
    if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)))
 
268
#endif                          /* !__EMX__ */
 
269
    {
 
270
      int nodelay = 1;
 
271
      if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay,
 
272
                     sizeof(nodelay))) {
 
273
        DBUG_PRINT("warning",
 
274
                   ("Couldn't set socket option for fast send"));
 
275
        r= -1;
 
276
      }
 
277
    }
 
278
  }
 
279
#endif  /* IPTOS_THROUGHPUT */
 
280
  DBUG_PRINT("exit", ("%d", r));
 
281
  DBUG_RETURN(r);
 
282
}
 
283
 
 
284
int vio_keepalive(Vio* vio, my_bool set_keep_alive)
 
285
{
 
286
  int r=0;
 
287
  uint opt = 0;
 
288
  DBUG_ENTER("vio_keepalive");
 
289
  DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
 
290
                       set_keep_alive));
 
291
  if (vio->type != VIO_TYPE_NAMEDPIPE)
 
292
  {
 
293
    assert(vio->sd >= 0);
 
294
    if (set_keep_alive)
 
295
      opt = 1;
 
296
    r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
 
297
                   sizeof(opt));
 
298
  }
 
299
  DBUG_RETURN(r);
 
300
}
 
301
 
 
302
 
 
303
my_bool
 
304
vio_should_retry(Vio * vio)
 
305
{
 
306
  int en = errno;
 
307
  return en == EAGAIN || en == EINTR || en == EWOULDBLOCK;
 
308
}
 
309
 
 
310
 
 
311
int vio_close(Vio * vio)
 
312
{
 
313
  int r;
 
314
  DBUG_ENTER("vio_close");
 
315
  assert(vio->sd >= 0);                 /* Vill also work on PIPE:s */
 
316
#ifdef __WIN__
 
317
  if (vio->type == VIO_TYPE_NAMEDPIPE)
 
318
  {
 
319
#if defined(__NT__) && defined(MYSQL_SERVER)
 
320
    CancelIO(vio->hPipe);
 
321
    DisconnectNamedPipe(vio->hPipe);
 
322
#endif
 
323
    r=CloseHandle(vio->hPipe);
 
324
  }
 
325
  else
 
326
#endif /* __WIN__ */
 
327
  {
 
328
    r=0;
 
329
    if (shutdown(vio->sd,2))
 
330
      r= -1;
 
331
    if (closesocket(vio->sd))
 
332
      r= -1;
 
333
  }
 
334
  if (r)
 
335
  {
 
336
    DBUG_PRINT("error", ("close() failed, error: %d",errno));
 
337
    /* FIXME: error handling (not critical for MySQL) */
 
338
  }
 
339
  vio_reset(vio,VIO_CLOSED,-1,0,TRUE);          /* For debugging */
 
340
  DBUG_RETURN(r);
 
341
}
 
342
 
 
343
 
 
344
const char *vio_description(Vio * vio)
 
345
{
 
346
  return vio->desc;
 
347
}
 
348
 
 
349
enum enum_vio_type vio_type(Vio* vio)
 
350
{
 
351
  return vio->type;
 
352
}
 
353
 
 
354
my_socket vio_fd(Vio* vio)
 
355
{
 
356
  return vio->sd;
 
357
}
 
358
 
 
359
 
 
360
my_bool vio_peer_addr(Vio * vio, char *buf)
 
361
{
 
362
  DBUG_ENTER("vio_peer_addr");
 
363
  DBUG_PRINT("enter", ("sd=%d", vio->sd));
 
364
  if (vio->localhost)
 
365
  {
 
366
    strmov(buf,"127.0.0.1");
 
367
  }
 
368
  else
 
369
  {
 
370
    size_socket addrLen = sizeof(struct sockaddr);
 
371
    if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)),
 
372
                    &addrLen) != 0)
 
373
    {
 
374
      DBUG_PRINT("exit", ("getpeername, error: %d", errno));
 
375
      DBUG_RETURN(1);
 
376
    }
 
377
    my_inet_ntoa(vio->remote.sin_addr,buf);
 
378
  }
 
379
  DBUG_PRINT("exit", ("addr=%s", buf));
 
380
  DBUG_RETURN(0);
 
381
}
 
382
 
 
383
 
 
384
void vio_in_addr(Vio *vio, struct in_addr *in)
 
385
{
 
386
  DBUG_ENTER("vio_in_addr");
 
387
  if (vio->localhost)
 
388
    bzero((char*) in, sizeof(*in));     /* This should never be executed */
 
389
  else
 
390
    *in=vio->remote.sin_addr;
 
391
  DBUG_VOID_RETURN;
 
392
}
 
393
 
 
394
#endif /* HAVE_VIO */