00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023 #include "vio.h"
00024 #include <string.h>
00025 #include <drizzled/util/test.h>
00026 #include <sys/socket.h>
00027 #include <string.h>
00028 #include <sys/types.h>
00029 #include <netinet/tcp.h>
00030 #include <netinet/in.h>
00031 #include <sys/poll.h>
00032 #include <unistd.h>
00033 #include <fcntl.h>
00034 #include <netdb.h>
00035 #include <algorithm>
00036 #include <cstdlib>
00037 #include <cassert>
00038 #include <cstdio>
00039 #include <fcntl.h>
00040
00041 using namespace std;
00042
00043 namespace drizzle_plugin {
00044
00045 Vio::Vio(int nsd) :
00046 sd(nsd)
00047 {
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 fcntl(sd, F_SETFL, 0);
00059 fcntl_mode= fcntl(sd, F_GETFL);
00060 }
00061
00062 Vio::~Vio()
00063 {
00064 close();
00065 }
00066
00067 int Vio::close()
00068 {
00069 int r= 0;
00070 if (sd != -1)
00071 {
00072 assert(sd >= 0);
00073 if (shutdown(sd, SHUT_RDWR))
00074 r= -1;
00075 if (::close(sd))
00076 r= -1;
00077 sd= -1;
00078 }
00079 return r;
00080 }
00081
00082 size_t Vio::read(unsigned char* buf, size_t size)
00083 {
00084 return ::read(sd, buf, size);
00085 }
00086
00087 size_t Vio::write(const unsigned char* buf, size_t size)
00088 {
00089 return ::write(sd, buf, size);
00090 }
00091
00092 int Vio::blocking(bool set_blocking_mode, bool *old_mode)
00093 {
00094 int r=0;
00095
00096
00097 if (NULL != old_mode)
00098 *old_mode= drizzled::test(!(fcntl_mode & O_NONBLOCK));
00099
00100 if (sd >= 0)
00101 {
00102 int old_fcntl=fcntl_mode;
00103 if (set_blocking_mode)
00104 fcntl_mode &= ~O_NONBLOCK;
00105 else
00106 fcntl_mode |= O_NONBLOCK;
00107 if (old_fcntl != fcntl_mode)
00108 {
00109 r= fcntl(sd, F_SETFL, fcntl_mode);
00110 if (r == -1)
00111 {
00112 fcntl_mode= old_fcntl;
00113 }
00114 }
00115 }
00116
00117 return r;
00118 }
00119
00120 int Vio::fastsend()
00121 {
00122 int nodelay = 1;
00123 int error= setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
00124 if (error)
00125 perror("setsockopt");
00126 return error;
00127 }
00128
00129 int32_t Vio::keepalive(bool set_keep_alive)
00130 {
00131 uint32_t opt= set_keep_alive;
00132 int r= setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
00133 if (r)
00134 {
00135 perror("setsockopt");
00136 assert(false);
00137 }
00138 return r;
00139 }
00140
00141 bool Vio::should_retry() const
00142 {
00143 int en = errno;
00144 return en == EAGAIN || en == EINTR || en == EWOULDBLOCK;
00145 }
00146
00147 bool Vio::was_interrupted() const
00148 {
00149 int en= errno;
00150 return en == EAGAIN || en == EINTR || en == EWOULDBLOCK || en == ETIMEDOUT;
00151 }
00152
00153 bool Vio::peer_addr(char *buf, size_t buflen, uint16_t& port) const
00154 {
00155 char port_buf[NI_MAXSERV];
00156 sockaddr_storage remote;
00157 socklen_t al = sizeof(remote);
00158
00159 if (getpeername(sd, (sockaddr *) (&remote), &al) != 0)
00160 return true;
00161
00162 if (getnameinfo((struct sockaddr *)(&remote), al, buf, buflen, port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV))
00163 {
00164 return true;
00165 }
00166
00167 port= (uint16_t)strtol(port_buf, (char **)NULL, 10);
00168
00169 return false;
00170 }
00171
00172 void Vio::timeout(bool is_sndtimeo, int32_t t)
00173 {
00174 timeval wait_timeout;
00175 wait_timeout.tv_sec= t;
00176 wait_timeout.tv_usec= 0;
00177
00178 assert(t >= 0 && t <= INT32_MAX);
00179 assert(sd != -1);
00180 int error= setsockopt(sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO, &wait_timeout,
00181 (socklen_t)sizeof(struct timeval));
00182 if (error == -1 && errno != ENOPROTOOPT)
00183 {
00184 perror("setsockopt");
00185 assert(error == 0);
00186 }
00187 }
00188
00189 int Vio::get_errno() const
00190 {
00191 return errno;
00192 }
00193
00194 int Vio::get_fd() const
00195 {
00196 return sd;
00197 }
00198
00199 }