]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - include/socketengine.h
Switch <stdint.h> test to use a test file too.
[user/henk/code/inspircd.git] / include / socketengine.h
index 9c45bcf21fd42a48321a0032ae712a28bf48ab24..37b7d637350b833e46d38f13d932f253008f36d6 100644 (file)
@@ -1,23 +1,33 @@
-/*       +------------------------------------+
- *       | Inspire Internet Relay Chat Daemon |
- *       +------------------------------------+
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
  *
- *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
+ *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
+ *   Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net>
+ *   Copyright (C) 2005-2007 Craig Edwards <craigedwards@brainbox.cc>
+ *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
  *
- * This program is free but copyrighted software; see
- *            the file COPYING for details.
+ * This file is part of InspIRCd.  InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
  *
- * ---------------------------------------------------
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __SOCKETENGINE__
-#define __SOCKETENGINE__
+
+#ifndef SOCKETENGINE_H
+#define SOCKETENGINE_H
 
 #include <vector>
 #include <string>
 #include <map>
 #include "inspircd_config.h"
+#include "socket.h"
 #include "base.h"
 
 /** Types of event an EventHandler may receive.
@@ -62,7 +72,7 @@ enum EventMask
         * it may not require a system call to transition from FD_WANT_FAST_READ
         */
        FD_WANT_EDGE_READ = 0x8,
-       
+
        /** Mask for all read events */
        FD_WANT_READ_MASK = 0x0F,
 
@@ -71,8 +81,10 @@ enum EventMask
        FD_WANT_NO_WRITE = 0x10,
        /** Give a write event at all times when writes will not block.
         *
-        * You probably don't need to use this state; try your write first, and
-        * then use FD_WANT_FAST_WRITE.
+        * You probably shouldn't use this state; if it's likely that the write
+        * will not block, try it first, then use FD_WANT_FAST_WRITE if it
+        * fails. If it's likely to block (or you are using polling-style reads)
+        * then use FD_WANT_SINGLE_WRITE.
         */
        FD_WANT_POLL_WRITE = 0x20,
        /** Give a write event when writes don't block any more
@@ -95,19 +107,23 @@ enum EventMask
         * FD_WANT_FAST_WRITE when writing data to a mostly-unblocked socket.
         */
        FD_WANT_EDGE_WRITE = 0x80,
+       /** Request a one-shot poll-style write notification. The socket will
+        * return to the FD_WANT_NO_WRITE state before HandleEvent is called.
+        */
+       FD_WANT_SINGLE_WRITE = 0x100,
 
        /** Mask for all write events */
-       FD_WANT_WRITE_MASK = 0xF0,
+       FD_WANT_WRITE_MASK = 0x1F0,
 
        /** Add a trial read. During the next DispatchEvents invocation, this
         * will call HandleEvent with EVENT_READ unless reads are known to be
-        * blocking. Useful for edge-triggered reads; does nothing if
-        * FD_READ_WILL_BLOCK has been set on this EventHandler.
+        * blocking.
         */
-       FD_ADD_TRIAL_READ  = 0x100,
+       FD_ADD_TRIAL_READ  = 0x1000,
        /** Assert that reads are known to block. This cancels FD_ADD_TRIAL_READ.
+        * Reset by SE before running EVENT_READ
         */
-       FD_READ_WILL_BLOCK = 0x200,
+       FD_READ_WILL_BLOCK = 0x2000,
 
        /** Add a trial write. During the next DispatchEvents invocation, this
         * will call HandleEvent with EVENT_WRITE unless writes are known to be
@@ -117,20 +133,16 @@ enum EventMask
         * send() syscall, or to ensure that writes are blocking when attempting
         * to use FD_WANT_FAST_WRITE.
         */
-       FD_ADD_TRIAL_WRITE = 0x1000,
+       FD_ADD_TRIAL_WRITE = 0x4000,
        /** Assert that writes are known to block. This cancels FD_ADD_TRIAL_WRITE.
+        * Reset by SE before running EVENT_WRITE
         */
-       FD_WRITE_WILL_BLOCK = 0x2000, 
+       FD_WRITE_WILL_BLOCK = 0x8000, 
 
-       /** Mask for trial read/write items */
-       FD_TRIAL_NOTE_MASK = 0x1100,
-       /** Mask for read/write blocking notifications */
-       FD_BLOCK_NOTE_MASK = 0x2200
+       /** Mask for trial read/trial write */
+       FD_TRIAL_NOTE_MASK = 0x5000
 };
 
-class InspIRCd;
-class Module;
-
 /** This class is a basic I/O handler class.
  * Any object which wishes to receive basic I/O events
  * from the socketengine must derive from this class and
@@ -149,7 +161,7 @@ class Module;
  * must have a file descriptor. What this file descriptor
  * is actually attached to is completely up to you.
  */
-class CoreExport EventHandler : public Extensible
+class CoreExport EventHandler : public classbase
 {
  private:
        /** Private state maintained by socket engine */
@@ -190,7 +202,9 @@ class CoreExport EventHandler : public Extensible
         * class, and it will be called whenever read or write
         * events are received.
         * @param et either one of EVENT_READ for read events,
-        * and EVENT_WRITE for write events.
+        * EVENT_WRITE for write events and EVENT_ERROR for
+        * error events.
+        * @param errornum The error code which goes with an EVENT_ERROR.
         */
        virtual void HandleEvent(EventType et, int errornum = 0) = 0;
 
@@ -240,10 +254,10 @@ class CoreExport SocketEngine
        void SetEventMask(EventHandler* eh, int value);
 public:
 
-       double TotalEvents;
-       double ReadEvents;
-       double WriteEvents;
-       double ErrorEvents;
+       unsigned long TotalEvents;
+       unsigned long ReadEvents;
+       unsigned long WriteEvents;
+       unsigned long ErrorEvents;
 
        /** Constructor.
         * The constructor transparently initializes
@@ -299,18 +313,9 @@ public:
         * and false if it failed. This does not free the
         * EventHandler pointer using delete, if this is
         * required you must do this yourself.
-        * Note on forcing deletes. DO NOT DO THIS! This is
-        * extremely dangerous and will most likely render the
-        * socketengine dead. This was added only for handling
-        * very rare cases where broken 3rd party libs destroys
-        * the OS socket beyond our control. If you can't explain
-        * in minute details why forcing is absolutely necessary
-        * then you don't need it. That was a NO!
         * @param eh The event handler object to remove
-        * @param force *DANGEROUS* See method description!
-        * @return True if the event handler was removed
         */
-       virtual bool DelFd(EventHandler* eh, bool force = false) = 0;
+       virtual void DelFd(EventHandler* eh) = 0;
 
        /** Returns true if a file descriptor exists in
         * the socket engine's list.
@@ -355,102 +360,120 @@ public:
        /** Abstraction for BSD sockets accept(2).
         * This function should emulate its namesake system call exactly.
         * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
+        * @param addr The client IP address and port
+        * @param addrlen The size of the sockaddr parameter.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen);
+       int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen);
 
        /** Abstraction for BSD sockets close(2).
         * This function should emulate its namesake system call exactly.
         * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int Close(EventHandler* fd);
+       int Close(EventHandler* fd);
 
        /** Abstraction for BSD sockets close(2).
         * This function should emulate its namesake system call exactly.
         * This function should emulate its namesake system call exactly.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int Close(int fd);
+       int Close(int fd);
 
        /** Abstraction for BSD sockets send(2).
         * This function should emulate its namesake system call exactly.
         * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
+        * @param buf The buffer in which the data that is sent is stored.
+        * @param len The size of the buffer.
+        * @param flags A flag value that controls the sending of the data.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int Send(EventHandler* fd, const void *buf, size_t len, int flags);
+       int Send(EventHandler* fd, const void *buf, size_t len, int flags);
 
        /** Abstraction for BSD sockets recv(2).
         * This function should emulate its namesake system call exactly.
         * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
+        * @param buf The buffer in which the data that is read is stored.
+        * @param len The size of the buffer.
+        * @param flags A flag value that controls the reception of the data.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int Recv(EventHandler* fd, void *buf, size_t len, int flags);
+       int Recv(EventHandler* fd, void *buf, size_t len, int flags);
 
        /** Abstraction for BSD sockets recvfrom(2).
         * This function should emulate its namesake system call exactly.
         * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
+        * @param buf The buffer in which the data that is read is stored.
+        * @param len The size of the buffer.
+        * @param flags A flag value that controls the reception of the data.
+        * @param from The remote IP address and port.
+        * @param fromlen The size of the from parameter.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen);
+       int RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen);
 
        /** Abstraction for BSD sockets sendto(2).
         * This function should emulate its namesake system call exactly.
         * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
+        * @param buf The buffer in which the data that is sent is stored.
+        * @param len The size of the buffer.
+        * @param flags A flag value that controls the sending of the data.
+        * @param to The remote IP address and port.    
+        * @param tolen The size of the to parameter.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int SendTo(EventHandler* fd, const void *buf, size_t len, int flags, const sockaddr *to, socklen_t tolen);
+       int SendTo(EventHandler* fd, const void *buf, size_t len, int flags, const sockaddr *to, socklen_t tolen);
 
        /** Abstraction for BSD sockets connect(2).
         * This function should emulate its namesake system call exactly.
         * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
+        * @param serv_addr The server IP address and port.
+        * @param addrlen The size of the sockaddr parameter.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int Connect(EventHandler* fd, const sockaddr *serv_addr, socklen_t addrlen);
+       int Connect(EventHandler* fd, const sockaddr *serv_addr, socklen_t addrlen);
 
        /** Make a file descriptor blocking.
         * @param fd a file descriptor to set to blocking mode
         * @return 0 on success, -1 on failure, errno is set appropriately.
         */
-       virtual int Blocking(int fd);
+       int Blocking(int fd);
 
        /** Make a file descriptor nonblocking.
         * @param fd A file descriptor to set to nonblocking mode
         * @return 0 on success, -1 on failure, errno is set appropriately.
         */
-       virtual int NonBlocking(int fd);
+       int NonBlocking(int fd);
 
        /** Abstraction for BSD sockets shutdown(2).
         * This function should emulate its namesake system call exactly.
         * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
+        * @param how What part of the socket to shut down
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int Shutdown(EventHandler* fd, int how);
+       int Shutdown(EventHandler* fd, int how);
 
        /** Abstraction for BSD sockets shutdown(2).
         * This function should emulate its namesake system call exactly.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int Shutdown(int fd, int how);
+       int Shutdown(int fd, int how);
 
        /** Abstraction for BSD sockets bind(2).
         * This function should emulate its namesake system call exactly.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int Bind(int fd, const sockaddr *my_addr, socklen_t addrlen);
+       int Bind(int fd, const irc::sockets::sockaddrs& addr);
 
        /** Abstraction for BSD sockets listen(2).
         * This function should emulate its namesake system call exactly.
         * @return This method should return exactly the same values as the system call it emulates.
         */
-       virtual int Listen(int sockfd, int backlog);
+       int Listen(int sockfd, int backlog);
 
-       /** Abstraction for BSD sockets getsockname(2).
-        * This function should emulate its namesake system call exactly.
-        * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
-        * @return This method should return exactly the same values as the system call it emulates.
+       /** Set SO_REUSEADDR and SO_LINGER on this file descriptor
         */
-       virtual int GetSockName(EventHandler* fd, sockaddr *name, socklen_t* namelen);
+       void SetReuse(int sockfd);
 
        /** This function is called immediately after fork().
         * Some socket engines (notably kqueue) cannot have their
@@ -466,7 +489,35 @@ public:
        /** Get data transfer statistics, kilobits per second in and out and total.
         */
        void GetStats(float &kbitpersec_in, float &kbitpersec_out, float &kbitpersec_total);
+
+       /** Should we ignore the error in errno?
+        * Checks EAGAIN and WSAEWOULDBLOCK
+        */
+       static bool IgnoreError();
+
+       /** Return the last socket related error. strrerror(errno) on *nix
+        */
+       static std::string LastError();
+
+       /** Returns the error for the given error num, strerror(errnum) on *nix
+        */
+       static std::string GetError(int errnum);
 };
 
+inline bool SocketEngine::IgnoreError()
+{
+       if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+               return true;
+
+#ifdef _WIN32
+       if (WSAGetLastError() == WSAEWOULDBLOCK)
+               return true;
+#endif
+
+       return false;
+}
+
+SocketEngine* CreateSocketEngine();
+
 #endif