InspIRCd  4.0
inspsocket.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  * Copyright (C) 2020 Matt Schatz <[email protected]>
5  * Copyright (C) 2019 linuxdaemon <[email protected]>
6  * Copyright (C) 2013, 2015-2016 Attila Molnar <[email protected]>
7  * Copyright (C) 2012-2013, 2017-2019, 2021 Sadie Powell <[email protected]>
8  * Copyright (C) 2012 Robby <[email protected]elgie.be>
9  * Copyright (C) 2009 Uli Schlachter <[email protected]>
10  * Copyright (C) 2009 Daniel De Graaf <[email protected]>
11  * Copyright (C) 2007-2009 Robin Burchell <[email protected]>
12  * Copyright (C) 2007 Dennis Friis <[email protected]>
13  * Copyright (C) 2006, 2010 Craig Edwards <[email protected]>
14  * Copyright (C) 2006 Oliver Lupton <[email protected]>
15  *
16  * This file is part of InspIRCd. InspIRCd is free software: you can
17  * redistribute it and/or modify it under the terms of the GNU General Public
18  * License as published by the Free Software Foundation, version 2.
19  *
20  * This program is distributed in the hope that it will be useful, but WITHOUT
21  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
23  * details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program. If not, see <http://www.gnu.org/licenses/>.
27  */
28 
29 
30 #pragma once
31 
32 #include "timer.h"
33 
34 class IOHook;
35 
39 enum BufferedSocketState
40 {
42  I_DISCONNECTED,
44  I_CONNECTING,
46  I_CONNECTED,
48  I_ERROR
49 };
50 
54 enum BufferedSocketError
55 {
57  I_ERR_NONE,
59  I_ERR_DISCONNECT,
61  I_ERR_TIMEOUT,
63  I_ERR_SOCKET,
65  I_ERR_CONNECT,
67  I_ERR_BIND,
69  I_ERR_WRITE,
71  I_ERR_NOMOREFDS,
73  I_ERR_OTHER
74 };
75 
76 /* Required forward declarations */
77 class BufferedSocket;
78 
81 class CoreExport SocketTimeout : public Timer
82 {
83  private:
86  BufferedSocket* sock;
87 
90  int sfd;
91 
92  public:
98  SocketTimeout(int fd, BufferedSocket* thesock, unsigned long secs_from_now)
99  : Timer(secs_from_now)
100  , sock(thesock)
101  , sfd(fd)
102  {
103  }
104 
107  bool Tick(time_t now) override;
108 };
109 
114 class CoreExport StreamSocket : public EventHandler
115 {
116  public:
119  class SendQueue
120  {
121  public:
124  typedef std::string Element;
125 
128  typedef std::deque<Element> Container;
129 
132  typedef Container::const_iterator const_iterator;
133 
137  bool empty() const { return (nbytes == 0); }
138 
142  Container::size_type size() const { return data.size(); }
143 
147  size_t bytes() const { return nbytes; }
148 
152  const Element& front() const { return data.front(); }
153 
159  const_iterator begin() const { return data.begin(); }
160 
164  const_iterator end() const { return data.end(); }
165 
168  void pop_front()
169  {
170  nbytes -= data.front().length();
171  data.pop_front();
172  }
173 
177  void erase_front(Element::size_type n)
178  {
179  nbytes -= n;
180  data.front().erase(0, n);
181  }
182 
186  void push_front(const Element& newdata)
187  {
188  data.push_front(newdata);
189  nbytes += newdata.length();
190  }
191 
195  void push_back(const Element& newdata)
196  {
197  data.push_back(newdata);
198  nbytes += newdata.length();
199  }
200 
203  void clear()
204  {
205  data.clear();
206  nbytes = 0;
207  }
208 
209  void moveall(SendQueue& other)
210  {
211  nbytes += other.bytes();
212  data.insert(data.end(), other.data.begin(), other.data.end());
213  other.clear();
214  }
215 
216  private:
219  Container data;
220 
223  size_t nbytes = 0;
224  };
225 
227  enum Type
228  {
229  SS_UNKNOWN,
230  SS_USER
231  };
232 
233  private:
235  bool closeonempty = false;
236 
238  bool closing = false;
239 
241  IOHook* iohook = nullptr;
242 
245  SendQueue sendq;
246 
248  std::string error;
249 
253  void CheckError(BufferedSocketError err);
254 
257  void DoRead();
258 
263  void FlushSendQ(SendQueue& sq);
264 
269  long ReadToRecvQ(std::string& rq);
270 
279  long HookChainRead(IOHook* hook, std::string& rq);
280 
281  protected:
283  std::string recvq;
284 
285  public:
286  const Type type;
287  StreamSocket(Type sstype = SS_UNKNOWN)
288  : type(sstype)
289  {
290  }
291  IOHook* GetIOHook() const;
292  void AddIOHook(IOHook* hook);
293  void DelIOHook();
294 
296  void DoWrite();
297 
299  void OnEventHandlerRead() override;
300 
302  void OnEventHandlerWrite() override;
303 
307  void OnEventHandlerError(int errcode) override;
308 
310  void SetError(const std::string& err) { if (error.empty()) error = err; }
311 
313  const std::string& GetError() const { return error; }
314 
316  virtual void OnDataReady() = 0;
317 
319  virtual void OnError(BufferedSocketError e) = 0;
320 
325  virtual bool OnSetLocalEndPoint(const irc::sockets::sockaddrs& ep) { return true; }
326 
331  virtual bool OnSetRemoteEndPoint(const irc::sockets::sockaddrs& ep) { return true; }
332 
335  void WriteData(const std::string& data);
336 
338  size_t GetSendQSize() const;
339 
341  SendQueue& GetSendQ() { return sendq; }
342 
346  virtual void Close();
347 
349  void Close(bool writeblock);
350 
352  Cullable::Result Cull() override;
353 
358  IOHook* GetModHook(Module* mod) const;
359 
363  IOHook* GetLastHook() const;
364 };
374 class CoreExport BufferedSocket : public StreamSocket
375 {
376  public:
380 
386  BufferedSocketState state;
387 
388  BufferedSocket();
396  BufferedSocket(int newfd);
397 
398  ~BufferedSocket() override;
399 
408  void DoConnect(const irc::sockets::sockaddrs& dest, const irc::sockets::sockaddrs& bind, unsigned long maxtime);
409 
413  virtual void OnConnected();
414 
418  void OnDataReady() override = 0;
419 
429  virtual void OnTimeout();
430 
431  protected:
432  void OnEventHandlerWrite() override;
433  BufferedSocketError BeginConnect(const irc::sockets::sockaddrs& dest, const irc::sockets::sockaddrs& bind, unsigned long timeout);
434 };
435 
436 inline IOHook* StreamSocket::GetIOHook() const { return iohook; }
437 inline void StreamSocket::DelIOHook() { iohook = NULL; }
Definition: inspsocket.h:375
void OnDataReady() override=0
SocketTimeout * Timeout
Definition: inspsocket.h:379
BufferedSocketState state
Definition: inspsocket.h:386
Definition: cull.h:38
Definition: socketengine.h:154
Definition: iohook.h:70
Definition: modules.h:286
Definition: inspsocket.h:82
SocketTimeout(int fd, BufferedSocket *thesock, unsigned long secs_from_now)
Definition: inspsocket.h:98
Definition: inspsocket.h:120
Container::size_type size() const
Definition: inspsocket.h:142
const_iterator end() const
Definition: inspsocket.h:164
void erase_front(Element::size_type n)
Definition: inspsocket.h:177
const Element & front() const
Definition: inspsocket.h:152
Container::const_iterator const_iterator
Definition: inspsocket.h:132
bool empty() const
Definition: inspsocket.h:137
void clear()
Definition: inspsocket.h:203
void push_front(const Element &newdata)
Definition: inspsocket.h:186
const_iterator begin() const
Definition: inspsocket.h:159
size_t bytes() const
Definition: inspsocket.h:147
void push_back(const Element &newdata)
Definition: inspsocket.h:195
std::deque< Element > Container
Definition: inspsocket.h:128
std::string Element
Definition: inspsocket.h:124
void pop_front()
Definition: inspsocket.h:168
Definition: inspsocket.h:115
virtual bool OnSetLocalEndPoint(const irc::sockets::sockaddrs &ep)
Definition: inspsocket.h:325
Type
Definition: inspsocket.h:228
SendQueue & GetSendQ()
Definition: inspsocket.h:341
const std::string & GetError() const
Definition: inspsocket.h:313
void SetError(const std::string &err)
Definition: inspsocket.h:310
virtual void OnError(BufferedSocketError e)=0
std::string recvq
Definition: inspsocket.h:283
virtual void OnDataReady()=0
virtual bool OnSetRemoteEndPoint(const irc::sockets::sockaddrs &ep)
Definition: inspsocket.h:331
Definition: timer.h:42
virtual bool Tick(time_t TIME)=0
Definition: socket.h:63