anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

sockets.h (12733B)

      1 /*
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  *
      8  * Based on the original code of Epona by Lara.
      9  * Based on the original code of Services by Andy Church.
     10  */
     11 
     12 #ifndef SOCKETS_H
     13 #define SOCKETS_H
     14 
     15 #ifndef _WIN32
     16 #include <netinet/in.h>
     17 #include <sys/types.h>
     18 #include <sys/socket.h>
     19 #endif
     20 
     21 #include "anope.h"
     22 
     23 #define NET_BUFSIZE 65535
     24 
     25 /** A sockaddr union used to combine IPv4 and IPv6 sockaddrs
     26  */
     27 union CoreExport sockaddrs
     28 {
     29 	sockaddr sa;
     30 	sockaddr_in sa4;
     31 	sockaddr_in6 sa6;
     32 
     33 	/** Construct the object, sets everything to 0
     34 	 */
     35 	sockaddrs(const Anope::string &address = "");
     36 
     37 	/** Memset the object to 0
     38 	 */
     39 	void clear();
     40 
     41 	/** Get address family.
     42 	 */
     43 	int family() const;
     44 
     45 	/** Get the size of the sockaddr we represent
     46 	 * @return The size
     47 	 */
     48 	size_t size() const;
     49 
     50 	/** Get the port represented by this addr
     51 	 * @return The port, or -1 on fail
     52 	 */
     53 	int port() const;
     54 
     55 	/** Get the address represented by this addr
     56 	 * @return The address
     57 	 */
     58 	Anope::string addr() const;
     59 
     60 	/** Get the reverse address represented by this addr
     61 	 * @return The reverse address
     62 	 */
     63 	Anope::string reverse() const;
     64 
     65 	/* Is this address ipv6? */
     66 	bool ipv6() const;
     67 
     68 	/** Check if this sockaddr has data in it
     69 	 */
     70 	bool valid() const;
     71 
     72 	/** Compares with sockaddr with another. Compares address type, port, and address
     73 	 * @return true if they are the same
     74 	 */
     75 	bool operator==(const sockaddrs &other) const;
     76 	/* The same as above but not */
     77 	inline bool operator!=(const sockaddrs &other) const { return !(*this == other); }
     78 
     79 	/** The equivalent of inet_pton
     80 	 * @param type AF_INET or AF_INET6
     81 	 * @param address The address to place in the sockaddr structures
     82 	 * @param pport An option port to include in the  sockaddr structures
     83 	 * @throws A socket exception if given invalid IPs
     84 	 */
     85 	void pton(int type, const Anope::string &address, int pport = 0);
     86 
     87 	/** The equivalent of inet_ntop
     88 	 * @param type AF_INET or AF_INET6
     89 	 * @param address The in_addr or in_addr6 structure
     90 	 * @throws A socket exception if given an invalid structure
     91 	 */
     92 	void ntop(int type, const void *src);
     93 };
     94 
     95 class CoreExport cidr
     96 {
     97 	sockaddrs addr;
     98 	Anope::string cidr_ip;
     99 	unsigned short cidr_len;
    100  public:
    101 	cidr(const Anope::string &ip);
    102 	cidr(const Anope::string &ip, unsigned char len);
    103 	cidr(const sockaddrs &ip, unsigned char len);
    104 	Anope::string mask() const;
    105 	bool match(const sockaddrs &other);
    106 	bool valid() const;
    107 
    108 	bool operator<(const cidr &other) const;
    109 	bool operator==(const cidr &other) const;
    110 	bool operator!=(const cidr &other) const;
    111 
    112 	struct CoreExport hash
    113 	{
    114 		size_t operator()(const cidr &s) const;
    115 	};
    116 };
    117 
    118 class SocketException : public CoreException
    119 {
    120  public:
    121 	/** Constructor for socket exceptions
    122 	 * @param message Error message
    123 	 */
    124 	SocketException(const Anope::string &message) : CoreException(message) { }
    125 
    126 	/** Destructor
    127 	 * @throws Nothing
    128 	 */
    129 	virtual ~SocketException() throw() { }
    130 };
    131 
    132 enum SocketFlag
    133 {
    134 	SF_DEAD = 1,
    135 	SF_READABLE,
    136 	SF_WRITABLE,
    137 	SF_CONNECTING,
    138 	SF_CONNECTED,
    139 	SF_ACCEPTING,
    140 	SF_ACCEPTED,
    141 	SF_SIZE
    142 };
    143 
    144 class CoreExport SocketIO
    145 {
    146  public:
    147 	virtual ~SocketIO() { }
    148 
    149 	/** Receive something from the buffer
    150 	 * @param s The socket
    151 	 * @param buf The buf to read to
    152 	 * @param sz How much to read
    153 	 * @return Number of bytes received
    154 	 */
    155 	virtual int Recv(Socket *s, char *buf, size_t sz);
    156 
    157 	/** Write something to the socket
    158 	 * @param s The socket
    159 	 * @param buf The data to write
    160 	 * @param size The length of the data
    161 	 */
    162 	virtual int Send(Socket *s, const char *buf, size_t sz);
    163 	int Send(Socket *s, const Anope::string &buf);
    164 
    165 	/** Accept a connection from a socket
    166 	 * @param s The socket
    167 	 * @return The new socket
    168 	 */
    169 	virtual ClientSocket *Accept(ListenSocket *s);
    170 
    171 	/** Finished accepting a connection from a socket
    172 	 * @param s The socket
    173 	 * @return SF_ACCEPTED if accepted, SF_ACCEPTING if still in process, SF_DEAD on error
    174 	 */
    175 	virtual SocketFlag FinishAccept(ClientSocket *cs);
    176 
    177 	/** Bind a socket
    178 	 * @param s The socket
    179 	 * @param ip The IP to bind to
    180 	 * @param port The optional port to bind to
    181 	 */
    182 	virtual void Bind(Socket *s, const Anope::string &ip, int port = 0);
    183 
    184 	/** Connect the socket
    185 	 * @param s The socket
    186 	 * @param target IP to connect to
    187 	 * @param port to connect to
    188 	 */
    189 	virtual void Connect(ConnectionSocket *s, const Anope::string &target, int port);
    190 
    191 	/** Called to potentially finish a pending connection
    192 	 * @param s The socket
    193 	 * @return SF_CONNECTED on success, SF_CONNECTING if still pending, and SF_DEAD on error.
    194 	 */
    195 	virtual SocketFlag FinishConnect(ConnectionSocket *s);
    196 
    197 	/** Called when the socket is destructing
    198 	 */
    199 	virtual void Destroy() { }
    200 };
    201 
    202 class CoreExport Socket
    203 {
    204  protected:
    205 	/* Socket FD */
    206 	int sock;
    207 	/* Is this an IPv6 socket? */
    208 	bool ipv6;
    209 
    210  public:
    211 	std::bitset<SF_SIZE> flags;
    212 
    213 	/* Sockaddrs for bind() (if it's bound) */
    214 	sockaddrs bindaddr;
    215 
    216 	/* I/O functions used for this socket */
    217 	SocketIO *io;
    218 
    219 	/** Empty constructor, should not be called.
    220 	 */
    221 	Socket();
    222 
    223 	/** Constructor, possibly creates the socket and adds it to the engine
    224 	 * @param sock The socket to use, -1 if we need to create our own
    225 	 * @param ipv6 true if using ipv6
    226 	 * @param type The socket type, defaults to SOCK_STREAM
    227 	 */
    228 	Socket(int sock, bool ipv6 = false, int type = SOCK_STREAM);
    229 
    230 	/** Destructor, closes the socket and removes it from the engine
    231 	 */
    232 	virtual ~Socket();
    233 
    234 	/** Get the socket FD for this socket
    235 	 * @return the fd
    236 	 */
    237 	int GetFD() const;
    238 
    239 	/** Check if this socket is IPv6
    240 	 * @return true or false
    241 	 */
    242 	bool IsIPv6() const;
    243 
    244 	/** Mark a socket as (non)blocking
    245 	 * @param state true to enable blocking, false to disable blocking
    246 	 * @return true if the socket is now blocking
    247 	 */
    248 	bool SetBlocking(bool state);
    249 
    250 	/** Bind the socket to an ip and port
    251 	 * @param ip The ip
    252 	 * @param port The port
    253 	 */
    254 	void Bind(const Anope::string &ip, int port = 0);
    255 
    256 	/** Called when there either is a read or write event.
    257 	 * @return true to continue to call ProcessRead/ProcessWrite, false to not continue
    258 	 */
    259 	virtual bool Process();
    260 
    261 	/** Called when there is something to be received for this socket
    262 	 * @return true on success, false to drop this socket
    263 	 */
    264 	virtual bool ProcessRead();
    265 
    266 	/** Called when the socket is ready to be written to
    267 	 * @return true on success, false to drop this socket
    268 	 */
    269 	virtual bool ProcessWrite();
    270 
    271 	/** Called when there is an error for this socket
    272 	 * @return true on success, false to drop this socket
    273 	 */
    274 	virtual void ProcessError();
    275 };
    276 
    277 class CoreExport BufferedSocket : public virtual Socket
    278 {
    279  protected:
    280 	/* Things read from the socket */
    281 	Anope::string read_buffer;
    282 	/* Things to be written to the socket */
    283 	Anope::string write_buffer;
    284 	/* How much data was received from this socket on this recv() */
    285 	int recv_len;
    286 
    287  public:
    288 	BufferedSocket();
    289 	virtual ~BufferedSocket();
    290 
    291 	/** Called when there is something to be received for this socket
    292 	 * @return true on success, false to drop this socket
    293 	 */
    294 	bool ProcessRead() anope_override;
    295 
    296 	/** Called when the socket is ready to be written to
    297 	 * @return true on success, false to drop this socket
    298 	 */
    299 	bool ProcessWrite() anope_override;
    300 
    301 	/** Gets the new line from the input buffer, if any
    302 	 */
    303 	const Anope::string GetLine();
    304 
    305 	/** Write to the socket
    306 	* @param message The message
    307 	*/
    308  protected:
    309 	virtual void Write(const char *buffer, size_t l);
    310  public:
    311 	void Write(const char *message, ...);
    312 	void Write(const Anope::string &message);
    313 
    314 	/** Get the length of the read buffer
    315 	 * @return The length of the read buffer
    316 	 */
    317 	int ReadBufferLen() const;
    318 
    319 	/** Get the length of the write buffer
    320 	 * @return The length of the write buffer
    321 	 */
    322 	int WriteBufferLen() const;
    323 };
    324 
    325 class CoreExport BinarySocket : public virtual Socket
    326 {
    327  protected:
    328 	struct DataBlock
    329 	{
    330 		char *orig;
    331 		char *buf;
    332 		size_t len;
    333 
    334 		DataBlock(const char *b, size_t l);
    335 		~DataBlock();
    336 	};
    337 
    338 	/* Data to be written out */
    339 	std::deque<DataBlock *> write_buffer;
    340 
    341  public:
    342 	BinarySocket();
    343 	virtual ~BinarySocket();
    344 
    345 	/** Called when there is something to be received for this socket
    346 	 * @return true on success, false to drop this socket
    347 	 */
    348 	bool ProcessRead() anope_override;
    349 
    350 	/** Called when the socket is ready to be written to
    351 	 * @return true on success, false to drop this socket
    352 	 */
    353 	bool ProcessWrite() anope_override;
    354 
    355 	/** Write data to the socket
    356 	 * @param buffer The data to write
    357 	 * @param l The length of the data; if 0 then this function returns without doing anything
    358 	 */
    359 	virtual void Write(const char *buffer, size_t l);
    360 	void Write(const char *message, ...);
    361 	void Write(const Anope::string &message);
    362 
    363 	/** Called with data from the socket
    364 	 * @param buffer The data
    365 	 * @param l The length of buffer
    366 	 * @return true to continue reading, false to drop the socket
    367 	 */
    368 	virtual bool Read(const char *buffer, size_t l);
    369 };
    370 
    371 class CoreExport ListenSocket : public virtual Socket
    372 {
    373  public:
    374 	/** Constructor
    375 	 * @param bindip The IP to bind to
    376 	 * @param port The port to listen on
    377 	 * @param ipv6 true for ipv6
    378 	 */
    379 	ListenSocket(const Anope::string &bindip, int port, bool ipv6);
    380 	virtual ~ListenSocket();
    381 
    382 	/** Process what has come in from the connection
    383 	 * @return false to destroy this socket
    384 	 */
    385 	bool ProcessRead();
    386 
    387 	/** Called when a connection is accepted
    388 	 * @param fd The FD for the new connection
    389 	 * @param addr The sockaddr for where the connection came from
    390 	 * @return The new socket
    391 	 */
    392 	virtual ClientSocket *OnAccept(int fd, const sockaddrs &addr) = 0;
    393 };
    394 
    395 class CoreExport ConnectionSocket : public virtual Socket
    396 {
    397  public:
    398 	/* Sockaddrs for connection ip/port */
    399 	sockaddrs conaddr;
    400 
    401 	/** Connect the socket
    402 	 * @param TargetHost The target host to connect to
    403 	 * @param Port The target port to connect to
    404 	 */
    405 	void Connect(const Anope::string &TargetHost, int Port);
    406 
    407 	/** Called when there either is a read or write event.
    408 	 * Used to determine whether or not this socket is connected yet.
    409 	 * @return true to continue to call ProcessRead/ProcessWrite, false to not continue
    410 	 */
    411 	bool Process() anope_override;
    412 
    413 	/** Called when there is an error for this socket
    414 	 * @return true on success, false to drop this socket
    415 	 */
    416 	void ProcessError() anope_override;
    417 
    418 	/** Called on a successful connect
    419 	 */
    420 	virtual void OnConnect();
    421 
    422 	/** Called when a connection is not successful
    423 	 * @param error The error
    424 	 */
    425 	virtual void OnError(const Anope::string &error);
    426 };
    427 
    428 class CoreExport ClientSocket : public virtual Socket
    429 {
    430  public:
    431 	/* Listen socket this connection came from */
    432 	ListenSocket *ls;
    433 	/* Clients address */
    434 	sockaddrs clientaddr;
    435 
    436 	/** Constructor
    437 	 * @param ls Listen socket this connection is from
    438 	 * @param addr Address the connection came from
    439 	 */
    440 	ClientSocket(ListenSocket *ls, const sockaddrs &addr);
    441 
    442 	/** Called when there either is a read or write event.
    443 	 * Used to determine whether or not this socket is connected yet.
    444 	 * @return true to continue to call ProcessRead/ProcessWrite, false to not continue
    445 	 */
    446 	bool Process() anope_override;
    447 
    448 	/** Called when there is an error for this socket
    449 	 * @return true on success, false to drop this socket
    450 	 */
    451 	void ProcessError() anope_override;
    452 
    453 	/** Called when a client has been accepted() successfully.
    454 	 */
    455 	virtual void OnAccept();
    456 
    457 	/** Called when there was an error accepting the client
    458 	 */
    459 	virtual void OnError(const Anope::string &error);
    460 };
    461 
    462 class CoreExport Pipe : public Socket
    463 {
    464  public:
    465 	/** The FD of the write pipe
    466 	 * this->sock is the readfd
    467 	 */
    468 	int write_pipe;
    469 
    470 	Pipe();
    471 	~Pipe();
    472 
    473 	/** Called when data is to be read, reads the data then calls OnNotify
    474 	 */
    475 	bool ProcessRead() anope_override;
    476 
    477 	/** Write data to this pipe
    478 	 * @param data The data to write
    479 	 * @param sz The amount of data to wirite
    480 	 */
    481 	void Write(const char *data, size_t sz);
    482 	inline void Write(const Anope::string &data) { this->Write(data.c_str(), data.length() + 1); }
    483 
    484 	/** Read data from this pipe
    485 	 * @param data A buffer to read data into
    486 	 * @param sz The size of the buffer
    487 	 * @return The amount of data read
    488 	 */
    489 	int Read(char *data, size_t sz);
    490 
    491 	/** Mark the write end of this pipe (non)blocking
    492 	 * @param state true to enable blocking, false to disable blocking
    493 	 * @return true if the socket is now blocking
    494 	 */
    495 	bool SetWriteBlocking(bool state);
    496 
    497 	/** Called when this pipe needs to be woken up
    498 	 * Is the same as Write("\0", 1)
    499 	 */
    500 	void Notify();
    501 
    502 	/** Called after ProcessRead comes back from Notify(), overload to do something useful
    503 	 */
    504 	virtual void OnNotify() = 0;
    505 };
    506 
    507 extern CoreExport uint32_t TotalRead;
    508 extern CoreExport uint32_t TotalWritten;
    509 extern CoreExport SocketIO NormalSocketIO;
    510 
    511 #endif // SOCKET_H