~brianaker/libdrizzle/yet-more-build-updates-mingw

« back to all changes in this revision

Viewing changes to libdrizzle/conn.cc

  • Committer: Continuous Integration
  • Date: 2012-12-30 09:12:02 UTC
  • mfrom: (71.1.2 5.1-trunk)
  • Revision ID: ci@drizzle.org-20121230091202-i35q0ord9mtb08ek
Merge lp:~brianaker/libdrizzle/non-block-fix Build: jenkins-Libdrizzle-21

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
 */
64
64
static drizzle_return_t _setsockopt(drizzle_st *con);
65
65
 
 
66
static void __closesocket(int& fd)
 
67
{
 
68
  if (fd != -1)
 
69
  {
 
70
    (void)shutdown(fd, SHUT_RDWR);
 
71
    (void)closesocket(fd);
 
72
    fd= -1;
 
73
  }
 
74
}
 
75
 
66
76
static bool connect_poll(drizzle_st *con)
67
77
{
68
78
  struct pollfd fds[1];
69
79
  fds[0].fd= con->fd;
70
 
  fds[0].events= POLLOUT;
 
80
  fds[0].events= POLLIN;
71
81
 
72
 
  size_t loop_max= 5;
 
82
  size_t loop_max= 5; // This should only be used for EINTR
73
83
  while (--loop_max) // Should only loop on cases of ERESTART or EINTR
74
84
  {
75
85
    int error= poll(fds, 1, con->timeout);
76
 
    switch (error)
 
86
    if (error == 1)
77
87
    {
78
 
    case 1:
 
88
      if (fds[0].revents & (POLLIN))
 
89
      {
 
90
        drizzle_log_crazy(con, "poll(POLLIN)");
 
91
        return true;
 
92
      }
 
93
 
 
94
      if (fds[0].revents & (POLLOUT))
 
95
      {
 
96
        drizzle_log_crazy(con, "poll(POLLOUT)");
 
97
        return true;
 
98
      }
 
99
 
 
100
      if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL))
79
101
      {
80
102
        int err;
81
103
        socklen_t len= sizeof (err);
89
111
            return true;
90
112
          }
91
113
          errno= err;
 
114
          perror("poll()");
92
115
        }
93
116
 
94
117
        // "getsockopt() failed"
95
118
        return false;
96
119
      }
97
120
 
98
 
    case 0:
99
 
      {
100
 
        // "timeout occurred while trying to connect"
101
 
        return false;
102
 
      }
103
 
 
104
 
    default: // A real error occurred and we need to completely bail
105
 
      switch (get_socket_errno())
106
 
      {
 
121
      assert(0);
 
122
 
 
123
      return false;
 
124
    }
 
125
    else if (error == 0)
 
126
    {
 
127
      // "timeout occurred while trying to connect"
 
128
      drizzle_log_crazy(con, "poll(TIMEOUT) %d", con->timeout);
 
129
      return false;
 
130
    }
 
131
 
 
132
    perror("poll2()");
 
133
    switch (get_socket_errno())
 
134
    {
107
135
#ifdef TARGET_OS_LINUX
108
 
      case ERESTART:
 
136
    case ERESTART:
109
137
#endif
110
 
      case EINTR:
111
 
        continue;
112
 
 
113
 
      case EFAULT:
114
 
      case ENOMEM:
115
 
        // "poll() failure"
116
 
        return false;
117
 
 
118
 
      case EINVAL:
119
 
        // "RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid"
120
 
        return false;
121
 
 
122
 
      default: // This should not happen
123
 
        if (fds[0].revents & POLLERR)
124
 
        {
125
 
          int err;
126
 
          socklen_t len= sizeof (err);
127
 
          (void)getsockopt(con->fd, SOL_SOCKET, SO_ERROR, &err, &len);
128
 
          errno= err;
129
 
        }
130
 
        else
131
 
        {
132
 
          errno= get_socket_errno();
133
 
        }
134
 
 
135
 
        //"socket error occurred");
136
 
        return false;
137
 
      }
 
138
    case EINTR:
 
139
      continue;
 
140
 
 
141
    case EFAULT:
 
142
    case ENOMEM:
 
143
      // "poll() failure"
 
144
      break;
 
145
 
 
146
    case EINVAL:
 
147
      // "RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid"
 
148
      break;
 
149
 
 
150
    default:
 
151
      break;
138
152
    }
 
153
 
 
154
    //"socket error occurred");
 
155
    return false;
139
156
  }
140
157
 
141
158
  // This should only be possible from ERESTART or EINTR; 
171
188
    return;
172
189
  }
173
190
 
174
 
  (void)closesocket(con->fd);
175
 
  con->fd= -1;
 
191
  __closesocket(con->fd);
176
192
 
177
193
  con->options = (drizzle_options_t)((int)con->options & (int)~DRIZZLE_CON_READY);
178
194
  con->packet_number= 0;
585
601
 
586
602
drizzle_return_t drizzle_quit(drizzle_st *con)
587
603
{
588
 
  drizzle_return_t ret;
589
 
  drizzle_result_st *result;
590
 
  result= drizzle_command_write(con, NULL, DRIZZLE_COMMAND_QUIT, NULL, 0,
591
 
                                   0, &ret);
592
 
  drizzle_result_free(result);
593
 
  drizzle_free(con);
594
 
  return ret;
 
604
  if (con)
 
605
  {
 
606
    drizzle_log_crazy(con, "shutting down the connection");
 
607
    con->flags.is_shutdown= true;
 
608
    drizzle_return_t ret;
 
609
    drizzle_result_st *result;
 
610
    result= drizzle_command_write(con, NULL, DRIZZLE_COMMAND_QUIT, NULL, 0, 0, &ret);
 
611
    drizzle_result_free(result);
 
612
    drizzle_free(con);
 
613
 
 
614
    if (ret == DRIZZLE_RETURN_LOST_CONNECTION)
 
615
    {
 
616
      return DRIZZLE_RETURN_OK;
 
617
    }
 
618
 
 
619
    return ret;
 
620
  }
 
621
 
 
622
  return DRIZZLE_RETURN_INVALID_ARGUMENT;
595
623
}
596
624
 
597
625
drizzle_result_st *drizzle_select_db(drizzle_st *con,
774
802
  const char *host;
775
803
  char port[NI_MAXSERV];
776
804
  struct addrinfo ai;
777
 
  int ret;
778
805
 
779
806
  if (con == NULL)
780
807
  {
786
813
  switch (con->socket_type)
787
814
  {
788
815
  case DRIZZLE_CON_SOCKET_TCP:
789
 
    tcp= &(con->socket.tcp);
790
 
 
791
 
    if (tcp->addrinfo != NULL)
792
 
    {
793
 
      freeaddrinfo(tcp->addrinfo);
794
 
      tcp->addrinfo= NULL;
795
 
    }
796
 
 
797
 
    if (tcp->port != 0)
798
 
    {
799
 
      snprintf(port, NI_MAXSERV, "%u", tcp->port);
800
 
    }
801
 
    else
802
 
    {
803
 
      snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
804
 
    }
805
 
    port[NI_MAXSERV-1]= 0;
806
 
 
807
 
    memset(&ai, 0, sizeof(struct addrinfo));
808
 
    ai.ai_socktype= SOCK_STREAM;
809
 
    ai.ai_protocol= IPPROTO_TCP;
810
 
    ai.ai_flags = AI_PASSIVE;
811
 
    ai.ai_family = AF_UNSPEC;
812
 
 
813
 
    if (tcp->host == NULL)
814
 
    {
815
 
      host= DRIZZLE_DEFAULT_TCP_HOST;
816
 
    }
817
 
    else
818
 
    {
819
 
      host= tcp->host;
820
 
    }
821
 
 
822
 
    ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
823
 
    if (ret != 0)
824
 
    {
825
 
      drizzle_set_error(con, "drizzle_state_addrinfo", "getaddrinfo:%s", gai_strerror(ret));
826
 
      return DRIZZLE_RETURN_GETADDRINFO;
827
 
    }
828
 
 
829
 
    con->addrinfo_next= tcp->addrinfo;
 
816
    {
 
817
      tcp= &(con->socket.tcp);
 
818
 
 
819
      if (tcp->addrinfo != NULL)
 
820
      {
 
821
        freeaddrinfo(tcp->addrinfo);
 
822
        tcp->addrinfo= NULL;
 
823
      }
 
824
 
 
825
      if (tcp->port != 0)
 
826
      {
 
827
        snprintf(port, NI_MAXSERV, "%u", tcp->port);
 
828
      }
 
829
      else
 
830
      {
 
831
        snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
 
832
      }
 
833
      port[NI_MAXSERV-1]= 0;
 
834
 
 
835
      memset(&ai, 0, sizeof(struct addrinfo));
 
836
      ai.ai_socktype= SOCK_STREAM;
 
837
      ai.ai_protocol= IPPROTO_TCP;
 
838
      ai.ai_family= AF_UNSPEC;
 
839
 
 
840
      if (tcp->host == NULL)
 
841
      {
 
842
        host= DRIZZLE_DEFAULT_TCP_HOST;
 
843
      }
 
844
      else
 
845
      {
 
846
        host= tcp->host;
 
847
      }
 
848
 
 
849
      drizzle_log_crazy(con, "host=%s port=%s", host, port);
 
850
      int ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
 
851
      if (ret != 0)
 
852
      {
 
853
        drizzle_set_error(con, "drizzle_state_addrinfo", "getaddrinfo:%s", gai_strerror(ret));
 
854
        return DRIZZLE_RETURN_GETADDRINFO;
 
855
      }
 
856
 
 
857
      con->addrinfo_next= tcp->addrinfo;
 
858
    }
830
859
 
831
860
    break;
832
861
 
850
879
 
851
880
  drizzle_log_debug(con, "drizzle_state_connect");
852
881
 
853
 
  if (con->fd != -1)
854
 
  {
855
 
    (void)closesocket(con->fd);
856
 
    con->fd= -1;
857
 
  }
 
882
  __closesocket(con->fd);
858
883
 
859
884
  if (con->socket_type == DRIZZLE_CON_SOCKET_UDS)
860
885
  {
927
952
 
928
953
    while (1)
929
954
    {
930
 
      int ret;
931
 
      ret= connect(con->fd, con->addrinfo_next->ai_addr,
932
 
                   con->addrinfo_next->ai_addrlen);
 
955
      int ret= connect(con->fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
933
956
 
934
957
#ifdef _WIN32
935
958
      errno = WSAGetLastError();
1080
1103
  drizzle_log_debug(con, "drizzle_state_read");
1081
1104
 
1082
1105
  if (con->buffer_size == 0)
 
1106
  {
1083
1107
    con->buffer_ptr= con->buffer;
 
1108
  }
1084
1109
  else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
1085
1110
  {
1086
1111
    memmove(con->buffer, con->buffer_ptr, con->buffer_size);
1095
1120
     * returns EAGAIN. This improves performance. */
1096
1121
    ret= drizzle_set_events(con, POLLIN);
1097
1122
    if (ret != DRIZZLE_RETURN_OK)
 
1123
    {
1098
1124
      return ret;
 
1125
    }
 
1126
 
1099
1127
    return DRIZZLE_RETURN_IO_WAIT;
1100
1128
  }
1101
1129
 
1102
1130
  while (1)
1103
1131
  {
1104
 
    size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE -
1105
 
        ((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
 
1132
    size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE - ((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
 
1133
 
1106
1134
#ifdef USE_OPENSSL
1107
1135
    if (con->ssl_state == DRIZZLE_SSL_STATE_HANDSHAKE_COMPLETE)
 
1136
    {
1108
1137
      read_size= SSL_read(con->ssl, (char*)con->buffer_ptr + con->buffer_size, available_buffer);
 
1138
    }
1109
1139
    else
1110
1140
#endif
 
1141
    {
1111
1142
      read_size= recv(con->fd, (char *)con->buffer_ptr + con->buffer_size, available_buffer, MSG_NOSIGNAL);
 
1143
    }
1112
1144
#ifdef _WIN32
1113
 
    errno = WSAGetLastError();
1114
 
    switch(errno) {
1115
 
    case WSAENOTCONN:
1116
 
    case WSAEWOULDBLOCK:
1117
 
      errno= EAGAIN;
1118
 
      break;
1119
 
    case WSAEINVAL:
1120
 
    case WSAEALREADY:
1121
 
      errno= EINPROGRESS;
1122
 
      break;
1123
 
    case WSAECONNREFUSED:
1124
 
      errno= ECONNREFUSED;
1125
 
      break;
1126
 
    case WSAENETUNREACH:
1127
 
      errno= ENETUNREACH;
1128
 
      break;
1129
 
    case WSAETIMEDOUT:
1130
 
      errno= ETIMEDOUT;
1131
 
      break;
1132
 
    case WSAECONNRESET:
1133
 
      errno= ECONNRESET;
1134
 
      break;
1135
 
    case WSAEADDRINUSE:
1136
 
      errno= EADDRINUSE;
1137
 
      break;
1138
 
    case WSAEOPNOTSUPP:
1139
 
      errno= EOPNOTSUPP;
1140
 
      break;
1141
 
    case WSAENOPROTOOPT:
1142
 
      errno= ENOPROTOOPT;
1143
 
      break;
1144
 
    default:
1145
 
      break;
 
1145
    if (_WIN32)
 
1146
    {
 
1147
      errno= WSAGetLastError();
 
1148
      switch (errno)
 
1149
      {
 
1150
      case WSAENOTCONN:
 
1151
      case WSAEWOULDBLOCK:
 
1152
        errno= EAGAIN;
 
1153
        break;
 
1154
      case WSAEINVAL:
 
1155
      case WSAEALREADY:
 
1156
        errno= EINPROGRESS;
 
1157
        break;
 
1158
      case WSAECONNREFUSED:
 
1159
        errno= ECONNREFUSED;
 
1160
        break;
 
1161
      case WSAENETUNREACH:
 
1162
        errno= ENETUNREACH;
 
1163
        break;
 
1164
      case WSAETIMEDOUT:
 
1165
        errno= ETIMEDOUT;
 
1166
        break;
 
1167
      case WSAECONNRESET:
 
1168
        errno= ECONNRESET;
 
1169
        break;
 
1170
      case WSAEADDRINUSE:
 
1171
        errno= EADDRINUSE;
 
1172
        break;
 
1173
      case WSAEOPNOTSUPP:
 
1174
        errno= EOPNOTSUPP;
 
1175
        break;
 
1176
      case WSAENOPROTOOPT:
 
1177
        errno= ENOPROTOOPT;
 
1178
        break;
 
1179
      default:
 
1180
        break;
 
1181
      }
1146
1182
    }
1147
1183
#endif /* _WIN32 */     
1148
 
    drizzle_log_crazy(con, "read fd=%d return=%zd ssl= %d errno=%s",
 
1184
 
 
1185
    drizzle_log_crazy(con, "read fd=%d recv=%zd ssl= %d errno=%s",
1149
1186
                      con->fd, read_size, 
1150
1187
                      (con->ssl_state == DRIZZLE_SSL_STATE_HANDSHAKE_COMPLETE) ? 1 : 0,
1151
1188
                      strerror(errno));
1152
1189
 
1153
1190
    if (read_size == 0)
1154
1191
    {
1155
 
      drizzle_set_error(con, __func__,
1156
 
                        "%s:%d lost connection to server (EOF)", __FILE__, __LINE__);
 
1192
      if (con->flags.is_shutdown == false)
 
1193
      {
 
1194
        drizzle_set_error(con, __func__,
 
1195
                          "%s:%d lost connection to server (EOF)", __FILE__, __LINE__);
 
1196
      }
 
1197
 
1157
1198
      return DRIZZLE_RETURN_LOST_CONNECTION;
1158
1199
    }
1159
1200
    else if (read_size == -1)
1160
1201
    {
1161
 
      if (errno == EAGAIN)
1162
 
      {
1163
 
        /* clear the read ready flag */
1164
 
        con->revents&= ~POLLIN;
1165
 
        ret= drizzle_set_events(con, POLLIN);
1166
 
        if (ret != DRIZZLE_RETURN_OK)
1167
 
          return ret;
1168
 
 
1169
 
        if (con->options & DRIZZLE_CON_OPTIONS_NON_BLOCKING)
1170
 
          return DRIZZLE_RETURN_IO_WAIT;
1171
 
 
1172
 
        ret= drizzle_wait(con);
1173
 
        if (ret != DRIZZLE_RETURN_OK)
1174
 
          return ret;
1175
 
 
1176
 
        continue;
1177
 
      }
1178
 
      else if (errno == ECONNREFUSED)
1179
 
      {
1180
 
        con->revents= 0;
1181
 
        drizzle_state_pop(con);
1182
 
        drizzle_state_push(con, drizzle_state_connect);
1183
 
        con->addrinfo_next= con->addrinfo_next->ai_next;
1184
 
        return DRIZZLE_RETURN_OK;
1185
 
      }
1186
 
      else if (errno == EINTR)
1187
 
      {
1188
 
        continue;
1189
 
      }
1190
 
      else if (errno == EPIPE || errno == ECONNRESET)
1191
 
      {
1192
 
        drizzle_set_error(con, __func__,
1193
 
                          "%s:%d lost connection to server (%s)",
1194
 
                          __FILE__, __LINE__, strerror(errno));
1195
 
        return DRIZZLE_RETURN_LOST_CONNECTION;
1196
 
      }
1197
 
 
1198
 
      drizzle_set_error(con, __func__, "read:%s", strerror(errno));
 
1202
      // switch (get_socket_errno())
 
1203
      switch (errno)
 
1204
      {
 
1205
      case EAGAIN:
 
1206
#if EWOULDBLOCK != EAGAIN
 
1207
      case EWOULDBLOCK:
 
1208
#endif
 
1209
        {
 
1210
          /* clear the read ready flag */
 
1211
          con->revents&= ~POLLIN;
 
1212
          ret= drizzle_set_events(con, POLLIN);
 
1213
          if (ret != DRIZZLE_RETURN_OK)
 
1214
          {
 
1215
            return ret;
 
1216
          }
 
1217
 
 
1218
          if (con->options & DRIZZLE_CON_OPTIONS_NON_BLOCKING)
 
1219
          {
 
1220
            return DRIZZLE_RETURN_IO_WAIT;
 
1221
          }
 
1222
 
 
1223
          ret= drizzle_wait(con);
 
1224
          if (ret != DRIZZLE_RETURN_OK)
 
1225
          {
 
1226
            return ret;
 
1227
          }
 
1228
 
 
1229
          continue;
 
1230
        }
 
1231
      case ECONNREFUSED:
 
1232
        {
 
1233
          con->revents= 0;
 
1234
          drizzle_state_pop(con);
 
1235
          drizzle_state_push(con, drizzle_state_connect);
 
1236
          con->addrinfo_next= con->addrinfo_next->ai_next;
 
1237
          return DRIZZLE_RETURN_OK;
 
1238
        }
 
1239
 
 
1240
      case EINTR:
 
1241
        continue;
 
1242
 
 
1243
      case EINVAL:
 
1244
        {
 
1245
          drizzle_log_crazy(con, "EINVAL fd=%d buffer=%p available_buffer=%zd",
 
1246
                            con->fd, (char *)con->buffer_ptr + con->buffer_size, available_buffer);
 
1247
        }
 
1248
        break;
 
1249
 
 
1250
      case EPIPE:
 
1251
      case ECONNRESET:
 
1252
        {
 
1253
          drizzle_set_error(con, __func__,
 
1254
                            "%s:%d lost connection to server (%s)",
 
1255
                            __FILE__, __LINE__, strerror(errno));
 
1256
          return DRIZZLE_RETURN_LOST_CONNECTION;
 
1257
        }
 
1258
      }
 
1259
 
 
1260
      drizzle_set_error(con, __func__, "recv:%s", strerror(errno));
1199
1261
      con->last_errno= errno;
1200
1262
      return DRIZZLE_RETURN_ERRNO;
1201
1263
    }
1230
1292
  {
1231
1293
#ifdef USE_OPENSSL
1232
1294
    if (con->ssl_state == DRIZZLE_SSL_STATE_HANDSHAKE_COMPLETE)
 
1295
    {
1233
1296
      write_size= SSL_write(con->ssl, con->buffer_ptr, con->buffer_size);
 
1297
    }
1234
1298
    else
1235
1299
#endif      
1236
 
      write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, MSG_NOSIGNAL);
 
1300
    {
 
1301
      write_size= send(con->fd,(char *) con->buffer_ptr, con->buffer_size, MSG_NOSIGNAL);
 
1302
    }
1237
1303
 
1238
1304
#ifdef _WIN32
1239
1305
    errno = WSAGetLastError();
1313
1379
        return DRIZZLE_RETURN_LOST_CONNECTION;
1314
1380
      }
1315
1381
 
1316
 
      drizzle_set_error(con, "drizzle_state_write", "write:%s", strerror(errno));
 
1382
      drizzle_set_error(con, "drizzle_state_write", "send: %s", strerror(errno));
1317
1383
      con->last_errno= errno;
1318
1384
      return DRIZZLE_RETURN_ERRNO;
1319
1385
    }