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