~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/client.c

Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
99
99
static void drizzle_close_free_options(DRIZZLE *drizzle);
100
100
static void drizzle_close_free(DRIZZLE *drizzle);
101
101
 
102
 
static int wait_for_data(my_socket fd, uint timeout);
 
102
static int wait_for_data(int fd, int32_t timeout);
 
103
int connect_with_timeout(int fd, const struct sockaddr *name, uint namelen, int32_t timeout);
103
104
 
104
105
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
105
106
 
108
109
char drizzle_server_last_error[DRIZZLE_ERRMSG_SIZE];
109
110
 
110
111
/****************************************************************************
111
 
  A modified version of connect().  my_connect() allows you to specify
 
112
  A modified version of connect().  connect_with_timeout() allows you to specify
112
113
  a timeout value, in seconds, that we should wait until we
113
114
  derermine we can't connect to a particular host.  If timeout is 0,
114
 
  my_connect() will behave exactly like connect().
 
115
  connect_with_timeout() will behave exactly like connect().
115
116
 
116
117
  Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
117
118
*****************************************************************************/
118
119
 
119
 
int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
120
 
         uint timeout)
 
120
 
 
121
int connect_with_timeout(int fd, const struct sockaddr *name, uint namelen, int32_t timeout)
121
122
{
122
123
  int flags, res, s_err;
123
124
 
144
145
  }
145
146
  if (res == 0)        /* Connected quickly! */
146
147
    return(0);
 
148
 
147
149
  return wait_for_data(fd, timeout);
148
150
}
149
151
 
155
157
  If not, we will use select()
156
158
*/
157
159
 
158
 
static int wait_for_data(my_socket fd, uint timeout)
 
160
static int wait_for_data(int fd, int32_t timeout)
159
161
{
160
 
#ifdef HAVE_POLL
161
162
  struct pollfd ufds;
162
163
  int res;
163
164
 
168
169
    errno= EINTR;
169
170
    return -1;
170
171
  }
171
 
  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
 
172
  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)) || (ufds.revents & POLLHUP))
172
173
    return -1;
173
174
  return 0;
174
 
#else
175
 
  SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
176
 
  fd_set sfds;
177
 
  struct timeval tv;
178
 
  time_t start_time, now_time;
179
 
  int res, s_err;
180
 
 
181
 
  if (fd >= FD_SETSIZE)        /* Check if wrong error */
182
 
    return 0;          /* Can't use timeout */
183
 
 
184
 
  /*
185
 
    Our connection is "in progress."  We can use the select() call to wait
186
 
    up to a specified period of time for the connection to suceed.
187
 
    If select() returns 0 (after waiting howevermany seconds), our socket
188
 
    never became writable (host is probably unreachable.)  Otherwise, if
189
 
    select() returns 1, then one of two conditions exist:
190
 
  
191
 
    1. An error occured.  We use getsockopt() to check for this.
192
 
    2. The connection was set up sucessfully: getsockopt() will
193
 
    return 0 as an error.
194
 
  
195
 
    Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
196
 
    who posted this method of timing out a connect() in
197
 
    comp.unix.programmer on August 15th, 1997.
198
 
  */
199
 
 
200
 
  FD_ZERO(&sfds);
201
 
  FD_SET(fd, &sfds);
202
 
  /*
203
 
    select could be interrupted by a signal, and if it is,
204
 
    the timeout should be adjusted and the select restarted
205
 
    to work around OSes that don't restart select and
206
 
    implementations of select that don't adjust tv upon
207
 
    failure to reflect the time remaining
208
 
   */
209
 
  start_time= my_time(0);
210
 
  for (;;)
211
 
  {
212
 
    tv.tv_sec = (long) timeout;
213
 
    tv.tv_usec = 0;
214
 
#if defined(HPUX10)
215
 
    if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
216
 
      break;
217
 
#else
218
 
    if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
219
 
      break;
220
 
#endif
221
 
    if (res == 0)          /* timeout */
222
 
      return -1;
223
 
    now_time= my_time(0);
224
 
    timeout-= (uint) (now_time - start_time);
225
 
    if (errno != EINTR || (int) timeout <= 0)
226
 
      return -1;
227
 
  }
228
 
 
229
 
  /*
230
 
    select() returned something more interesting than zero, let's
231
 
    see if we have any errors.  If the next two statements pass,
232
 
    we've got an open socket!
233
 
  */
234
 
 
235
 
  s_err=0;
236
 
  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
237
 
    return(-1);
238
 
 
239
 
  if (s_err)
240
 
  {            /* getsockopt could succeed */
241
 
    errno = s_err;
242
 
    return(-1);          /* but return an error... */
243
 
  }
244
 
  return (0);          /* ok */
245
 
#endif /* HAVE_POLL */
246
175
}
247
176
 
248
177
 
1341
1270
 
1342
1271
    memset(&hints, 0, sizeof(hints));
1343
1272
    hints.ai_socktype= SOCK_STREAM;
1344
 
    hints.ai_protocol= IPPROTO_TCP;
1345
 
    hints.ai_family= AF_UNSPEC;
 
1273
    /* OSX 10.5 was failing unless defined only as support IPV4 */
 
1274
#ifdef TARGET_OS_OSX
 
1275
    hints.ai_family= AF_INET;
 
1276
#endif
 
1277
 
1346
1278
 
1347
1279
    snprintf(port_buf, NI_MAXSERV, "%d", port);
1348
1280
    gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
1358
1290
    /* We only look at the first item (something to think about changing in the future) */
1359
1291
    t_res= res_lst;
1360
1292
    {
1361
 
      my_socket sock= socket(t_res->ai_family, t_res->ai_socktype,
 
1293
      int sock= socket(t_res->ai_family, t_res->ai_socktype,
1362
1294
                             t_res->ai_protocol);
1363
1295
      if (sock == SOCKET_ERROR)
1364
1296
      {
1377
1309
        goto error;
1378
1310
      }
1379
1311
 
1380
 
      if (my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
1381
 
                     drizzle->options.connect_timeout))
 
1312
      if (connect_with_timeout(sock, t_res->ai_addr, t_res->ai_addrlen, drizzle->options.connect_timeout))
1382
1313
      {
1383
1314
        set_drizzle_extended_error(drizzle, CR_CONN_HOST_ERROR, unknown_sqlstate,
1384
1315
                                 ER(CR_CONN_HOST_ERROR), host, socket_errno);