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
00046 Vio::Vio(int nsd) :
00047 closed(false),
00048 sd(nsd),
00049 fcntl_mode(0),
00050 local(),
00051 remote(),
00052 read_pos(NULL),
00053 read_end(NULL)
00054 {
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 fcntl(sd, F_SETFL, 0);
00066 fcntl_mode= fcntl(sd, F_GETFL);
00067 }
00068
00069 Vio::~Vio()
00070 {
00071 if (!closed)
00072 close();
00073 }
00074
00075 int Vio::close()
00076 {
00077 int r=0;
00078 if (!closed)
00079 {
00080 assert(sd >= 0);
00081 if (shutdown(sd, SHUT_RDWR))
00082 r= -1;
00083 if (::close(sd))
00084 r= -1;
00085 }
00086 closed= true;
00087 sd= -1;
00088
00089 return r;
00090 }
00091
00092 size_t Vio::read(unsigned char* buf, size_t size)
00093 {
00094 size_t r;
00095
00096
00097 assert(read_end == read_pos);
00098 r= ::read(sd, buf, size);
00099
00100 return r;
00101 }
00102
00103 size_t Vio::write(const unsigned char* buf, size_t size)
00104 {
00105 size_t r;
00106
00107 r = ::write(sd, buf, size);
00108
00109 return r;
00110 }
00111
00112 int Vio::blocking(bool set_blocking_mode, bool *old_mode)
00113 {
00114 int r=0;
00115
00116
00117 if (NULL != old_mode)
00118 *old_mode= drizzled::test(!(fcntl_mode & O_NONBLOCK));
00119
00120 if (sd >= 0)
00121 {
00122 int old_fcntl=fcntl_mode;
00123 if (set_blocking_mode)
00124 fcntl_mode &= ~O_NONBLOCK;
00125 else
00126 fcntl_mode |= O_NONBLOCK;
00127 if (old_fcntl != fcntl_mode)
00128 {
00129 r= fcntl(sd, F_SETFL, fcntl_mode);
00130 if (r == -1)
00131 {
00132 fcntl_mode= old_fcntl;
00133 }
00134 }
00135 }
00136
00137 return r;
00138 }
00139
00140 int Vio::fastsend()
00141 {
00142 int nodelay = 1;
00143 int error;
00144
00145 error= setsockopt(sd, IPPROTO_TCP, TCP_NODELAY,
00146 &nodelay, sizeof(nodelay));
00147 if (error != 0)
00148 {
00149 perror("setsockopt");
00150 }
00151
00152 return error;
00153 }
00154
00155 int32_t Vio::keepalive(bool set_keep_alive)
00156 {
00157 int r= 0;
00158 uint32_t opt= 0;
00159
00160 if (set_keep_alive)
00161 opt= 1;
00162
00163 r= setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
00164 if (r != 0)
00165 {
00166 perror("setsockopt");
00167 assert(r == 0);
00168 }
00169
00170 return r;
00171 }
00172
00173 bool Vio::should_retry() const
00174 {
00175 int en = errno;
00176 return (en == EAGAIN || en == EINTR ||
00177 en == EWOULDBLOCK);
00178 }
00179
00180 bool Vio::was_interrupted() const
00181 {
00182 int en= errno;
00183 return (en == EAGAIN || en == EINTR ||
00184 en == EWOULDBLOCK || en == ETIMEDOUT);
00185 }
00186
00187 bool Vio::peer_addr(char *buf, uint16_t *port, size_t buflen) const
00188 {
00189 int error;
00190 char port_buf[NI_MAXSERV];
00191 socklen_t al = sizeof(remote);
00192
00193 if (getpeername(sd, (struct sockaddr *) (&remote),
00194 &al) != 0)
00195 {
00196 return true;
00197 }
00198
00199 if ((error= getnameinfo((struct sockaddr *)(&remote),
00200 al,
00201 buf, buflen,
00202 port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
00203 {
00204 return true;
00205 }
00206
00207 *port= (uint16_t)strtol(port_buf, (char **)NULL, 10);
00208
00209 return false;
00210 }
00211
00212 void Vio::timeout(bool is_sndtimeo, int32_t t)
00213 {
00214 int error;
00215
00216
00217 struct timeval wait_timeout;
00218 wait_timeout.tv_sec= t;
00219 wait_timeout.tv_usec= 0;
00220
00221 assert(t >= 0 && t <= INT32_MAX);
00222 assert(sd != -1);
00223 error= setsockopt(sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
00224 &wait_timeout,
00225 (socklen_t)sizeof(struct timeval));
00226 if (error == -1 && errno != ENOPROTOOPT)
00227 {
00228 perror("setsockopt");
00229 assert(error == 0);
00230 }
00231 }
00232
00233 int Vio::get_errno() const
00234 {
00235 return errno;
00236 }
00237
00238 int Vio::get_fd() const
00239 {
00240 return sd;
00241 }
00242
00243
00244 char *Vio::get_read_pos() const
00245 {
00246 return read_pos;
00247 }
00248
00249 char *Vio::get_read_end() const
00250 {
00251 return read_end;
00252 }
00253
00254 }