]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/sstuff.hh
auth: switch circleci mssql image
[thirdparty/pdns.git] / pdns / sstuff.hh
index e7fb6ee9ab2fddf8bf1c299b5c0075af22fc1a6d..922315a5e21bc3aeeb2c1c4bd1c321b0d29030b1 100644 (file)
 #include "namespaces.hh"
 
 
-class NetworkError : public runtime_error
-{
-public:
-  NetworkError(const string& why="Network Error") : runtime_error(why.c_str())
-  {}
-  NetworkError(const char *why="Network Error") : runtime_error(why)
-  {}
-};
-
-
 typedef int ProtocolType; //!< Supported protocol types
 
 //! Representation of a Socket and many of the Berkeley functions available
 class Socket : public boost::noncopyable
 {
-  Socket(int fd)
+  Socket(int fd): d_socket(fd)
   {
-    d_socket = fd;
-    d_buflen=4096;
-    d_buffer=new char[d_buflen];
   }
 
 public:
   //! Construct a socket of specified address family and socket type.
   Socket(int af, int st, ProtocolType pt=0)
   {
-    if((d_socket=socket(af,st, pt))<0)
+    if((d_socket=socket(af, st, pt))<0)
       throw NetworkError(strerror(errno));
     setCloseOnExec(d_socket);
+  }
 
-    d_buflen=4096;
-    d_buffer=new char[d_buflen];
+  Socket(Socket&& rhs): d_buffer(std::move(rhs.d_buffer)), d_socket(rhs.d_socket)
+  {
+    rhs.d_socket = -1;
   }
 
   ~Socket()
   {
     try {
-      closesocket(d_socket);
+      if (d_socket != -1) {
+        closesocket(d_socket);
+      }
     }
     catch(const PDNSException& e) {
     }
-
-    delete[] d_buffer;
   }
 
   //! If the socket is capable of doing so, this function will wait for a connection
-  Socket *accept()
+  std::unique_ptr<Socket> accept()
   {
     struct sockaddr_in remote;
     socklen_t remlen=sizeof(remote);
     memset(&remote, 0, sizeof(remote));
-    int s=::accept(d_socket,(sockaddr *)&remote, &remlen);
+    int s=::accept(d_socket, reinterpret_cast<sockaddr *>(&remote), &remlen);
     if(s<0) {
       if(errno==EAGAIN)
-        return 0;
+        return nullptr;
 
       throw NetworkError("Accepting a connection: "+string(strerror(errno)));
     }
 
-    return new Socket(s);
+    return std::unique_ptr<Socket>(new Socket(s));
   }
 
   //! Get remote address
   bool getRemote(ComboAddress &remote) {
     socklen_t remotelen=sizeof(remote);
-    return (getpeername(d_socket, (struct sockaddr *)&remote, &remotelen) >= 0);
+    return (getpeername(d_socket, reinterpret_cast<struct sockaddr *>(&remote), &remotelen) >= 0);
   }
 
   //! Check remote address against netmaskgroup ng
-  bool acl(NetmaskGroup &ng)
+  bool acl(const NetmaskGroup &ng)
   {
     ComboAddress remote;
     if (getRemote(remote))
-      return ng.match((ComboAddress *) &remote);
+      return ng.match(remote);
 
     return false;
   }
@@ -125,6 +114,7 @@ public:
   {
     ::setNonBlocking(d_socket);
   }
+
   //! Set the socket to blocking
   void setBlocking()
   {
@@ -133,54 +123,28 @@ public:
 
   void setReuseAddr()
   {
-    int tmp = 1;
-    if (setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, static_cast<unsigned>(sizeof tmp))<0)
-      throw NetworkError(string("Setsockopt failed: ")+strerror(errno));
+    try {
+      ::setReuseAddr(d_socket);
+    } catch (const PDNSException &e) {
+      throw NetworkError(e.reason);
+    }
   }
 
   //! Bind the socket to a specified endpoint
-  void bind(const ComboAddress &local)
+  void bind(const ComboAddress &local, bool reuseaddr=true)
   {
     int tmp=1;
-    if(setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0)
+    if(reuseaddr && setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&tmp), sizeof tmp)<0)
       throw NetworkError(string("Setsockopt failed: ")+strerror(errno));
 
-    if(::bind(d_socket,(struct sockaddr *)&local, local.getSocklen())<0)
+    if(::bind(d_socket, reinterpret_cast<const struct sockaddr *>(&local), local.getSocklen())<0)
       throw NetworkError("While binding: "+string(strerror(errno)));
   }
 
-#if 0
-  //! Bind the socket to a specified endpoint
-  void bind(const ComboAddress &ep)
-  {
-    ComboAddress local;
-    memset(reinterpret_cast<char *>(&local),0,sizeof(local));
-    local.sin_family=d_family;
-    local.sin_addr.s_addr=ep.address.byte;
-    local.sin_port=htons(ep.port);
-    
-    bind(local);
-  }
-#endif
   //! Connect the socket to a specified endpoint
   void connect(const ComboAddress &ep, int timeout=0)
   {
-    if(::connect(d_socket,(struct sockaddr *)&ep, ep.getSocklen()) < 0) {
-      if(errno == EINPROGRESS) {
-        if (timeout > 0) {
-          /* if a timeout is provided, we wait until the connection has been established */
-          int res = waitForRWData(d_socket, false, timeout, 0);
-          if (res == 0) {
-            throw NetworkError("timeout while connecting to "+ep.toStringWithPort());
-          } else if (res < 0) {
-            throw NetworkError("while waiting to connect to "+ep.toStringWithPort()+": "+string(strerror(errno)));
-          }
-        }
-      }
-      else {
-        throw NetworkError("While connecting to "+ep.toStringWithPort()+": "+string(strerror(errno)));
-      }
-    }
+    SConnectWithTimeout(d_socket, ep, timeout);
   }
 
 
@@ -190,20 +154,22 @@ public:
       \param ep Will be filled with the origin of the datagram */
   void recvFrom(string &dgram, ComboAddress &ep)
   {
-    socklen_t remlen=sizeof(ep);
+    socklen_t remlen = sizeof(ep);
     ssize_t bytes;
-    if((bytes=recvfrom(d_socket, d_buffer, d_buflen, 0, (sockaddr *)&ep , &remlen)) <0)
+    d_buffer.resize(s_buflen);
+    if((bytes=recvfrom(d_socket, &d_buffer[0], s_buflen, 0, reinterpret_cast<sockaddr *>(&ep) , &remlen)) <0)
       throw NetworkError("After recvfrom: "+string(strerror(errno)));
     
-    dgram.assign(d_buffer,bytes);
+    dgram.assign(d_buffer, 0, static_cast<size_t>(bytes));
   }
 
   bool recvFromAsync(string &dgram, ComboAddress &ep)
   {
     struct sockaddr_in remote;
-    socklen_t remlen=sizeof(remote);
+    socklen_t remlen = sizeof(remote);
     ssize_t bytes;
-    if((bytes=recvfrom(d_socket, d_buffer, d_buflen, 0, (sockaddr *)&remote, &remlen))<0) {
+    d_buffer.resize(s_buflen);
+    if((bytes=recvfrom(d_socket, &d_buffer[0], s_buflen, 0, reinterpret_cast<sockaddr *>(&remote), &remlen))<0) {
       if(errno!=EAGAIN) {
         throw NetworkError("After async recvfrom: "+string(strerror(errno)));
       }
@@ -211,7 +177,7 @@ public:
         return false;
       }
     }
-    dgram.assign(d_buffer,bytes);
+    dgram.assign(d_buffer, 0, static_cast<size_t>(bytes));
     return true;
   }
 
@@ -219,7 +185,7 @@ public:
   //! For datagram sockets, send a datagram to a destination
   void sendTo(const char* msg, size_t len, const ComboAddress &ep)
   {
-    if(sendto(d_socket, msg, len, 0, (sockaddr *)&ep, ep.getSocklen())<0)
+    if(sendto(d_socket, msg, len, 0, reinterpret_cast<const sockaddr *>(&ep), ep.getSocklen())<0)
       throw NetworkError("After sendto: "+string(strerror(errno)));
   }
 
@@ -256,9 +222,9 @@ public:
         throw NetworkError("Writing to a socket: "+string(strerror(errno)));
       if(!res)
         throw NetworkError("EOF on socket");
-      toWrite-=(size_t)res;
-      ptr+=(size_t)res;
-    }while(toWrite);
+      toWrite -= static_cast<size_t>(res);
+      ptr += static_cast<size_t>(res);
+    } while(toWrite);
 
   }
 
@@ -298,7 +264,7 @@ public:
   void writenWithTimeout(const void *buffer, size_t n, int timeout)
   {
     size_t bytes=n;
-    const char *ptr = (char*)buffer;
+    const char *ptr = reinterpret_cast<const char*>(buffer);
     ssize_t ret;
     while(bytes) {
       ret=::write(d_socket, ptr, bytes);
@@ -318,8 +284,8 @@ public:
         throw NetworkError("Did not fulfill TCP write due to EOF");
       }
 
-      ptr += (size_t) ret;
-      bytes -= (size_t) ret;
+      ptr += static_cast<size_t>(ret);
+      bytes -= static_cast<size_t>(ret);
     }
   }
 
@@ -348,19 +314,20 @@ public:
   //! Reads a block of data from the socket to a string
   void read(string &data)
   {
-    ssize_t res=::recv(d_socket,d_buffer,d_buflen,0);
+    d_buffer.resize(s_buflen);
+    ssize_t res=::recv(d_socket, &d_buffer[0], s_buflen, 0);
     if(res<0) 
       throw NetworkError("Reading from a socket: "+string(strerror(errno)));
-    data.assign(d_buffer,res);
+    data.assign(d_buffer, 0, static_cast<size_t>(res));
   }
 
   //! Reads a block of data from the socket to a block of memory
   size_t read(char *buffer, size_t bytes)
   {
-    ssize_t res=::recv(d_socket,buffer,bytes,0);
+    ssize_t res=::recv(d_socket, buffer, bytes, 0);
     if(res<0) 
       throw NetworkError("Reading from a socket: "+string(strerror(errno)));
-    return (size_t) res;
+    return static_cast<size_t>(res);
   }
 
   ssize_t readWithTimeout(char* buffer, size_t n, int timeout)
@@ -389,9 +356,9 @@ public:
   }
   
 private:
-  char *d_buffer;
+  static const size_t s_buflen{4096};
+  std::string d_buffer;
   int d_socket;
-  size_t d_buflen;
 };