Used a more uniform of logging and added a commandline parser.
[UnsignedByte.git] / src / Sockets / SocketHandler.cpp
blob531314ac50e9cd7b9bbc4c7c0763092283287454
1 /** \file SocketHandler.cpp
2 ** \date 2004-02-13
3 ** \author grymse@alhem.net
4 **/
5 /*
6 Copyright (C) 2004-2007 Anders Hedstrom
8 This library is made available under the terms of the GNU GPL.
10 If you would like to use this library in a closed-source application,
11 a separate license agreement is available. For information about
12 the closed-source license agreement for the C++ sockets library,
13 please visit http://www.alhem.net/Sockets/license.html and/or
14 email license@alhem.net.
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License
18 as published by the Free Software Foundation; either version 2
19 of the License, or (at your option) any later version.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef _WIN32
31 #ifndef __MINGW32__
32 #pragma warning(disable:4786)
33 #endif
34 #include <stdlib.h>
35 #else
36 #include <errno.h>
37 #endif
39 #include <exception>
41 #include "SocketHandler.h"
42 #include "UdpSocket.h"
43 #include "ResolvSocket.h"
44 #include "ResolvServer.h"
45 #include "TcpSocket.h"
46 #include "Mutex.h"
47 #include "Utility.h"
48 #include "SocketAddress.h"
50 #ifdef SOCKETS_NAMESPACE
51 namespace SOCKETS_NAMESPACE {
52 #endif
55 #ifdef _DEBUGNOTDEFINED
56 #define DEB(x) x; fflush(stderr);
57 #else
58 #define DEB(x)
59 #endif
62 SocketHandler::SocketHandler(StdLog *p)
63 :m_stdlog(p)
64 ,m_mutex(m_mutex)
65 ,m_b_use_mutex(false)
66 ,m_maxsock(0)
67 ,m_preverror(-1)
68 ,m_errcnt(0)
69 ,m_tlast(0)
70 #ifdef ENABLE_SOCKS4
71 ,m_socks4_host(0)
72 ,m_socks4_port(0)
73 ,m_bTryDirect(false)
74 #endif
75 #ifdef ENABLE_RESOLVER
76 ,m_resolv_id(0)
77 ,m_resolver(NULL)
78 #endif
79 #ifdef ENABLE_POOL
80 ,m_b_enable_pool(false)
81 #endif
82 #ifdef ENABLE_TRIGGERS
83 ,m_next_trigger_id(0)
84 #endif
85 #ifdef ENABLE_DETACH
86 ,m_slave(false)
87 #endif
89 FD_ZERO(&m_rfds);
90 FD_ZERO(&m_wfds);
91 FD_ZERO(&m_efds);
95 SocketHandler::SocketHandler(Mutex& mutex,StdLog *p)
96 :m_stdlog(p)
97 ,m_mutex(mutex)
98 ,m_b_use_mutex(true)
99 ,m_maxsock(0)
100 ,m_preverror(-1)
101 ,m_errcnt(0)
102 ,m_tlast(0)
103 #ifdef ENABLE_SOCKS4
104 ,m_socks4_host(0)
105 ,m_socks4_port(0)
106 ,m_bTryDirect(false)
107 #endif
108 #ifdef ENABLE_RESOLVER
109 ,m_resolv_id(0)
110 ,m_resolver(NULL)
111 #endif
112 #ifdef ENABLE_POOL
113 ,m_b_enable_pool(false)
114 #endif
115 #ifdef ENABLE_TRIGGERS
116 ,m_next_trigger_id(0)
117 #endif
118 #ifdef ENABLE_DETACH
119 ,m_slave(false)
120 #endif
122 m_mutex.Lock();
123 FD_ZERO(&m_rfds);
124 FD_ZERO(&m_wfds);
125 FD_ZERO(&m_efds);
129 SocketHandler::~SocketHandler()
131 #ifdef ENABLE_RESOLVER
132 if (m_resolver)
134 m_resolver -> Quit();
136 #endif
138 while (m_sockets.size())
140 DEB( fprintf(stderr, "Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());)
141 socket_m::iterator it = m_sockets.begin();
142 Socket *p = it -> second;
143 if (p)
145 DEB( fprintf(stderr, " fd %d\n", p -> GetSocket());)
146 p -> Close();
147 DEB( fprintf(stderr, " fd closed %d\n", p -> GetSocket());)
148 // p -> OnDelete(); // hey, I turn this back on. what's the worst that could happen??!!
149 // MinionSocket breaks, calling MinderHandler methods in OnDelete -
150 // MinderHandler is already gone when that happens...
152 // only delete socket when controlled
153 // ie master sockethandler can delete non-detached sockets
154 // and a slave sockethandler can only delete a detach socket
155 if (p -> DeleteByHandler()
156 #ifdef ENABLE_DETACH
157 && !(m_slave ^ p -> IsDetached())
158 #endif
161 p -> SetErasedByHandler();
162 delete p;
164 m_sockets.erase(it);
166 else
168 m_sockets.erase(it);
170 DEB( fprintf(stderr, "next\n");)
172 DEB( fprintf(stderr, "/Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());)
174 #ifdef ENABLE_RESOLVER
175 if (m_resolver)
177 delete m_resolver;
179 #endif
180 if (m_b_use_mutex)
182 m_mutex.Unlock();
187 Mutex& SocketHandler::GetMutex() const
189 return m_mutex;
193 #ifdef ENABLE_DETACH
194 void SocketHandler::SetSlave(bool x)
196 m_slave = x;
200 bool SocketHandler::IsSlave()
202 return m_slave;
204 #endif
207 void SocketHandler::RegStdLog(StdLog *log)
209 m_stdlog = log;
213 void SocketHandler::LogError(Socket *p,const std::string& user_text,int err,const std::string& sys_err,loglevel_t t)
215 if (m_stdlog)
217 m_stdlog -> error(this, p, user_text, err, sys_err, t);
222 void SocketHandler::Add(Socket *p)
224 if (p -> GetSocket() == INVALID_SOCKET)
226 LogError(p, "Add", -1, "Invalid socket", LOG_LEVEL_WARNING);
227 if (p -> CloseAndDelete())
229 m_delete.push_back(p);
231 return;
233 if (m_add.find(p -> GetSocket()) != m_add.end())
235 LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in add queue", LOG_LEVEL_FATAL);
236 m_delete.push_back(p);
237 return;
239 m_add[p -> GetSocket()] = p;
243 void SocketHandler::Get(SOCKET s,bool& r,bool& w,bool& e)
245 if (s >= 0)
247 r = FD_ISSET(s, &m_rfds) ? true : false;
248 w = FD_ISSET(s, &m_wfds) ? true : false;
249 e = FD_ISSET(s, &m_efds) ? true : false;
254 void SocketHandler::Set(SOCKET s,bool bRead,bool bWrite,bool bException)
256 DEB( fprintf(stderr, "Set(%d, %s, %s, %s)\n", s, bRead ? "true" : "false", bWrite ? "true" : "false", bException ? "true" : "false");)
257 if (s >= 0)
259 if (bRead)
261 if (!FD_ISSET(s, &m_rfds))
263 FD_SET(s, &m_rfds);
266 else
268 FD_CLR(s, &m_rfds);
270 if (bWrite)
272 if (!FD_ISSET(s, &m_wfds))
274 FD_SET(s, &m_wfds);
277 else
279 FD_CLR(s, &m_wfds);
281 if (bException)
283 if (!FD_ISSET(s, &m_efds))
285 FD_SET(s, &m_efds);
288 else
290 FD_CLR(s, &m_efds);
296 int SocketHandler::Select(long sec,long usec)
298 struct timeval tv;
299 tv.tv_sec = sec;
300 tv.tv_usec = usec;
301 return Select(&tv);
305 int SocketHandler::Select()
307 if (m_fds_callonconnect.size() ||
308 #ifdef ENABLE_DETACH
309 (!m_slave && m_fds_detach.size()) ||
310 #endif
311 m_fds_timeout.size() ||
312 m_fds_retry.size() ||
313 m_fds_close.size() ||
314 m_fds_erase.size())
316 return Select(0, 200000);
318 return Select(NULL);
322 int SocketHandler::Select(struct timeval *tsel)
324 size_t ignore = 0;
325 while (m_add.size() > ignore)
327 if (m_sockets.size() >= FD_SETSIZE)
329 LogError(NULL, "Select", (int)m_sockets.size(), "FD_SETSIZE reached", LOG_LEVEL_WARNING);
330 break;
332 socket_m::iterator it = m_add.begin();
333 SOCKET s = it -> first;
334 Socket *p = it -> second;
335 DEB( fprintf(stderr, "Trying to add fd %d, m_add.size() %d, ignore %d\n", (int)s, (int)m_add.size(), (int)ignore);)
337 if (m_sockets.find(p -> GetSocket()) != m_sockets.end())
339 LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in controlled queue", LOG_LEVEL_FATAL);
340 // %! it's a dup, don't add to delete queue, just ignore it
341 m_delete.push_back(p);
342 m_add.erase(it);
343 // ignore++;
344 continue;
346 if (!p -> CloseAndDelete())
348 StreamSocket *scp = dynamic_cast<StreamSocket *>(p);
349 if (scp && scp -> Connecting()) // 'Open' called before adding socket
351 Set(s,false,true);
353 else
355 TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
356 bool bWrite = tcp ? tcp -> GetOutputLength() != 0 : false;
357 if (p -> IsDisableRead())
359 Set(s, false, bWrite);
361 else
363 Set(s, true, bWrite);
366 m_maxsock = (s > m_maxsock) ? s : m_maxsock;
368 else
370 LogError(p, "Add", (int)p -> GetSocket(), "Trying to add socket with SetCloseAndDelete() true", LOG_LEVEL_WARNING);
372 // only add to m_fds (process fd_set events) if
373 // slave handler and detached/detaching socket
374 // master handler and non-detached socket
375 #ifdef ENABLE_DETACH
376 if (!(m_slave ^ p -> IsDetach()))
377 #endif
379 m_fds.push_back(s);
381 m_sockets[s] = p;
383 m_add.erase(it);
385 #ifdef MACOSX
386 fd_set rfds;
387 fd_set wfds;
388 fd_set efds;
389 FD_COPY(&m_rfds, &rfds);
390 FD_COPY(&m_wfds, &wfds);
391 FD_COPY(&m_efds, &efds);
392 #else
393 fd_set rfds = m_rfds;
394 fd_set wfds = m_wfds;
395 fd_set efds = m_efds;
396 #endif
397 int n;
398 if (m_b_use_mutex)
400 m_mutex.Unlock();
401 n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel);
402 m_mutex.Lock();
404 else
406 n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel);
408 if (n == -1)
411 EBADF An invalid file descriptor was given in one of the sets.
412 EINTR A non blocked signal was caught.
413 EINVAL n is negative. Or struct timeval contains bad time values (<0).
414 ENOMEM select was unable to allocate memory for internal tables.
416 if (Errno != m_preverror || m_errcnt++ % 10000 == 0)
418 LogError(NULL, "select", Errno, StrError(Errno));
419 #if 0
420 fprintf(stderr, "m_maxsock: %d\n", m_maxsock);
421 fprintf(stderr, "%s\n", Errno == EINVAL ? "EINVAL" :
422 Errno == EINTR ? "EINTR" :
423 Errno == EBADF ? "EBADF" :
424 Errno == ENOMEM ? "ENOMEM" : "<another>");
425 // test bad fd
426 for (SOCKET i = 0; i <= m_maxsock; i++)
428 bool t = false;
429 FD_ZERO(&rfds);
430 FD_ZERO(&wfds);
431 FD_ZERO(&efds);
432 if (FD_ISSET(i, &m_rfds))
434 FD_SET(i, &rfds);
435 t = true;
437 if (FD_ISSET(i, &m_wfds))
439 FD_SET(i, &wfds);
440 t = true;
442 if (FD_ISSET(i, &m_efds))
444 FD_SET(i, &efds);
445 t = true;
447 if (t && m_sockets.find(i) == m_sockets.end())
449 fprintf(stderr, "Bad fd in fd_set: %d\n", i);
452 #endif
453 m_preverror = Errno;
455 /// \todo rebuild fd_set's from active sockets list (m_sockets) here
457 else
458 if (!n)
460 m_preverror = -1;
462 else
463 if (n > 0)
465 for (socket_v::iterator it2 = m_fds.begin(); it2 != m_fds.end() && n; it2++)
467 SOCKET i = *it2;
468 if (FD_ISSET(i, &rfds))
470 socket_m::iterator itmp = m_sockets.find(i);
471 if (itmp != m_sockets.end()) // found
473 Socket *p = itmp -> second;
474 // new SSL negotiate method
475 #ifdef HAVE_OPENSSL
476 if (p -> IsSSLNegotiate())
478 p -> SSLNegotiate();
480 else
481 #endif
483 p -> OnRead();
486 else
488 LogError(NULL, "GetSocket/handler/1", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
490 n--;
492 if (FD_ISSET(i, &wfds))
494 socket_m::iterator itmp = m_sockets.find(i);
495 if (itmp != m_sockets.end()) // found
497 Socket *p = itmp -> second;
498 // new SSL negotiate method
499 #ifdef HAVE_OPENSSL
500 if (p -> IsSSLNegotiate())
502 p -> SSLNegotiate();
504 else
505 #endif
507 p -> OnWrite();
510 else
512 LogError(NULL, "GetSocket/handler/2", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
514 n--;
516 if (FD_ISSET(i, &efds))
518 socket_m::iterator itmp = m_sockets.find(i);
519 if (itmp != m_sockets.end()) // found
521 Socket *p = itmp -> second;
522 p -> OnException();
524 else
526 LogError(NULL, "GetSocket/handler/3", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
528 n--;
530 } // m_fds loop
531 m_preverror = -1;
532 } // if (n > 0)
534 // check CallOnConnect - EVENT
535 if (m_fds_callonconnect.size())
537 socket_v tmp = m_fds_callonconnect;
538 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
540 Socket *p = NULL;
542 socket_m::iterator itmp = m_sockets.find(*it);
543 if (itmp != m_sockets.end()) // found
545 p = itmp -> second;
547 else
549 LogError(NULL, "GetSocket/handler/4", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
552 if (p)
554 // if (p -> CallOnConnect() && p -> Ready() )
556 p -> SetConnected(); // moved here from inside if (tcp) check below
557 #ifdef HAVE_OPENSSL
558 if (p -> IsSSL()) // SSL Enabled socket
559 p -> OnSSLConnect();
560 else
561 #endif
562 #ifdef ENABLE_SOCKS4
563 if (p -> Socks4())
564 p -> OnSocks4Connect();
565 else
566 #endif
568 TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
569 if (tcp)
571 if (tcp -> GetOutputLength())
573 p -> OnWrite();
576 #ifdef ENABLE_RECONNECT
577 if (tcp && tcp -> IsReconnect())
578 p -> OnReconnect();
579 else
580 #endif
582 // LogError(p, "Calling OnConnect", 0, "Because CallOnConnect", LOG_LEVEL_INFO);
583 p -> OnConnect();
586 // p -> SetCallOnConnect( false );
587 AddList(p -> GetSocket(), LIST_CALLONCONNECT, false);
592 #ifdef ENABLE_DETACH
593 // check detach of socket if master handler - EVENT
594 if (!m_slave && m_fds_detach.size())
596 // %! why not using tmp list here??!?
597 for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++)
599 Socket *p = NULL;
601 socket_m::iterator itmp = m_sockets.find(*it);
602 if (itmp != m_sockets.end()) // found
604 p = itmp -> second;
606 else
608 LogError(NULL, "GetSocket/handler/5", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
611 if (p)
613 // if (p -> IsDetach())
615 Set(p -> GetSocket(), false, false, false);
616 // After DetachSocket(), all calls to Handler() will return a reference
617 // to the new slave SocketHandler running in the new thread.
618 p -> DetachSocket();
619 // Adding the file descriptor to m_fds_erase will now also remove the
620 // socket from the detach queue - tnx knightmad
621 m_fds_erase.push_back(p -> GetSocket());
626 #endif
627 // check Connecting - connection timeout - conditional event
628 if (m_fds_timeout.size())
630 time_t tnow = time(NULL);
631 if (tnow != m_tlast)
633 socket_v tmp = m_fds_timeout;
634 DEB( fprintf(stderr, "Checking %d socket(s) for timeout\n", tmp.size());)
635 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
637 Socket *p = NULL;
639 socket_m::iterator itmp = m_sockets.find(*it);
640 if (itmp != m_sockets.end()) // found
642 p = itmp -> second;
644 else
646 itmp = m_add.find(*it);
647 if (itmp != m_add.end())
649 p = itmp -> second;
651 else
653 LogError(NULL, "GetSocket/handler/6", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
657 if (p)
659 if (p -> Timeout(tnow))
661 StreamSocket *scp = dynamic_cast<StreamSocket *>(p);
662 if (scp && scp -> Connecting())
663 p -> OnConnectTimeout();
664 else
665 p -> OnTimeout();
666 p -> SetTimeout(0);
670 m_tlast = tnow;
671 } // tnow != tlast
673 // check retry client connect - EVENT
674 if (m_fds_retry.size())
676 socket_v tmp = m_fds_retry;
677 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
679 Socket *p = NULL;
681 socket_m::iterator itmp = m_sockets.find(*it);
682 if (itmp != m_sockets.end()) // found
684 p = itmp -> second;
686 else
688 LogError(NULL, "GetSocket/handler/7", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
691 if (p)
693 // if (p -> RetryClientConnect())
695 TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
696 SOCKET nn = *it; //(*it3).first;
697 tcp -> SetRetryClientConnect(false);
698 DEB( fprintf(stderr, "Close() before retry client connect\n");)
699 p -> Close(); // removes from m_fds_retry
700 std::auto_ptr<SocketAddress> ad = p -> GetClientRemoteAddress();
701 if (ad.get())
703 tcp -> Open(*ad);
705 else
707 LogError(p, "RetryClientConnect", 0, "no address", LOG_LEVEL_ERROR);
709 Add(p);
710 m_fds_erase.push_back(nn);
715 // check close and delete - conditional event
716 if (m_fds_close.size())
718 socket_v tmp = m_fds_close;
719 DEB( fprintf(stderr, "m_fds_close.size() == %d\n", (int)m_fds_close.size());)
720 for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
722 Socket *p = NULL;
724 socket_m::iterator itmp = m_sockets.find(*it);
725 if (itmp != m_sockets.end()) // found
727 p = itmp -> second;
729 else
731 itmp = m_add.find(*it);
732 if (itmp != m_add.end())
734 p = itmp -> second;
736 else
738 LogError(NULL, "GetSocket/handler/8", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
742 if (p)
744 // if (p -> CloseAndDelete() )
746 TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
747 // new graceful tcp - flush and close timeout 5s
748 if (tcp && p -> IsConnected() && tcp -> GetFlushBeforeClose() &&
749 #ifdef HAVE_OPENSSL
750 !tcp -> IsSSL() &&
751 #endif
752 p -> TimeSinceClose() < 5)
754 DEB( fprintf(stderr, " close(1)\n");)
755 if (tcp -> GetOutputLength())
757 LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Sending all data before closing", LOG_LEVEL_INFO);
759 else // shutdown write when output buffer is empty
760 if (!(tcp -> GetShutdown() & SHUT_WR))
762 SOCKET nn = *it;
763 if (nn != INVALID_SOCKET && shutdown(nn, SHUT_WR) == -1)
765 LogError(p, "graceful shutdown", Errno, StrError(Errno), LOG_LEVEL_ERROR);
767 tcp -> SetShutdown(SHUT_WR);
770 else
771 #ifdef ENABLE_RECONNECT
772 if (tcp && p -> IsConnected() && tcp -> Reconnect())
774 SOCKET nn = *it; //(*it3).first;
775 DEB( fprintf(stderr, " close(2) fd %d\n", nn);)
776 p -> SetCloseAndDelete(false);
777 tcp -> SetIsReconnect();
778 p -> SetConnected(false);
779 DEB( fprintf(stderr, "Close() before reconnect\n");)
780 p -> Close(); // dispose of old file descriptor (Open creates a new)
781 p -> OnDisconnect();
782 std::auto_ptr<SocketAddress> ad = p -> GetClientRemoteAddress();
783 if (ad.get())
785 tcp -> Open(*ad);
787 else
789 LogError(p, "Reconnect", 0, "no address", LOG_LEVEL_ERROR);
791 tcp -> ResetConnectionRetries();
792 Add(p);
793 m_fds_erase.push_back(nn);
795 else
796 #endif
798 SOCKET nn = *it; //(*it3).first;
799 DEB( fprintf(stderr, " close(3) fd %d GetSocket() %d\n", nn, p -> GetSocket());)
800 if (tcp && p -> IsConnected() && tcp -> GetOutputLength())
802 LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Closing socket while data still left to send", LOG_LEVEL_WARNING);
804 #ifdef ENABLE_POOL
805 if (p -> Retain() && !p -> Lost())
807 PoolSocket *p2 = new PoolSocket(*this, p);
808 p2 -> SetDeleteByHandler();
809 Add(p2);
811 p -> SetCloseAndDelete(false); // added - remove from m_fds_close
813 else
814 #endif // ENABLE_POOL
816 Set(p -> GetSocket(),false,false,false);
817 DEB( fprintf(stderr, "Close() before OnDelete\n");)
818 p -> Close();
820 p -> OnDelete();
821 if (p -> DeleteByHandler())
823 p -> SetErasedByHandler();
825 m_fds_erase.push_back(nn);
832 // check erased sockets
833 bool check_max_fd = false;
834 while (m_fds_erase.size())
836 socket_v::iterator it = m_fds_erase.begin();
837 SOCKET nn = *it;
838 #ifdef ENABLE_DETACH
840 for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++)
842 if (*it == nn)
844 m_fds_detach.erase(it);
845 break;
849 #endif
851 for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++)
853 if (*it == nn)
855 m_fds.erase(it);
856 break;
861 socket_m::iterator it = m_sockets.find(nn);
862 if (it != m_sockets.end())
864 Socket *p = it -> second;
865 /* Sometimes a SocketThread class can finish its run before the master
866 sockethandler gets here. In that case, the SocketThread has set the
867 'ErasedByHandler' flag on the socket which will make us end up with a
868 double delete on the socket instance.
869 The fix is to make sure that the master sockethandler only can delete
870 non-detached sockets, and a slave sockethandler only can delete
871 detach sockets. */
872 if (p -> ErasedByHandler()
873 #ifdef ENABLE_DETACH
874 && !(m_slave ^ p -> IsDetached())
875 #endif
878 #ifdef ENABLE_TRIGGERS
879 bool again = false;
882 again = false;
883 for (std::map<int, Socket *>::iterator it = m_trigger_src.begin(); it != m_trigger_src.end(); it++)
885 int id = it -> first;
886 Socket *src = it -> second;
887 if (src == p)
889 for (std::map<Socket *, bool>::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++)
891 Socket *dst = it -> first;
892 if (Valid(dst))
894 dst -> OnCancelled(id);
897 m_trigger_src.erase(m_trigger_src.find(id));
898 m_trigger_dst.erase(m_trigger_dst.find(id));
899 again = true;
900 break;
903 } while (again);
904 #endif
905 delete p;
907 m_sockets.erase(it);
910 m_fds_erase.erase(it);
911 check_max_fd = true;
913 // calculate max file descriptor for select() call
914 if (check_max_fd)
916 m_maxsock = 0;
917 for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++)
919 SOCKET s = *it;
920 m_maxsock = s > m_maxsock ? s : m_maxsock;
923 // remove Add's that fizzed
924 while (m_delete.size())
926 std::list<Socket *>::iterator it = m_delete.begin();
927 Socket *p = *it;
928 p -> OnDelete();
929 m_delete.erase(it);
930 if (p -> DeleteByHandler()
931 #ifdef ENABLE_DETACH
932 && !(m_slave ^ p -> IsDetached())
933 #endif
936 p -> SetErasedByHandler();
937 #ifdef ENABLE_TRIGGERS
938 bool again = false;
941 again = false;
942 for (std::map<int, Socket *>::iterator it = m_trigger_src.begin(); it != m_trigger_src.end(); it++)
944 int id = it -> first;
945 Socket *src = it -> second;
946 if (src == p)
948 for (std::map<Socket *, bool>::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++)
950 Socket *dst = it -> first;
951 if (Valid(dst))
953 dst -> OnCancelled(id);
956 m_trigger_src.erase(m_trigger_src.find(id));
957 m_trigger_dst.erase(m_trigger_dst.find(id));
958 again = true;
959 break;
962 } while (again);
963 #endif
964 delete p;
967 return n;
971 bool SocketHandler::Valid(Socket *p0)
973 for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
975 Socket *p = it -> second;
976 if (p0 == p)
977 return true;
979 return false;
983 bool SocketHandler::OkToAccept(Socket *)
985 return true;
989 size_t SocketHandler::GetCount()
991 return m_sockets.size() + m_add.size() + m_delete.size();
995 #ifdef ENABLE_SOCKS4
996 void SocketHandler::SetSocks4Host(ipaddr_t a)
998 m_socks4_host = a;
1002 void SocketHandler::SetSocks4Host(const std::string& host)
1004 Utility::u2ip(host, m_socks4_host);
1008 void SocketHandler::SetSocks4Port(port_t port)
1010 m_socks4_port = port;
1014 void SocketHandler::SetSocks4Userid(const std::string& id)
1016 m_socks4_userid = id;
1018 #endif
1021 #ifdef ENABLE_RESOLVER
1022 int SocketHandler::Resolve(Socket *p,const std::string& host,port_t port)
1024 // check cache
1025 ResolvSocket *resolv = new ResolvSocket(*this, p, host, port);
1026 resolv -> SetId(++m_resolv_id);
1027 resolv -> SetDeleteByHandler();
1028 ipaddr_t local;
1029 Utility::u2ip("127.0.0.1", local);
1030 if (!resolv -> Open(local, m_resolver_port))
1032 LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
1034 Add(resolv);
1035 return resolv -> GetId();
1039 #ifdef ENABLE_IPV6
1040 int SocketHandler::Resolve6(Socket *p,const std::string& host,port_t port)
1042 // check cache
1043 ResolvSocket *resolv = new ResolvSocket(*this, p, host, port, true);
1044 resolv -> SetId(++m_resolv_id);
1045 resolv -> SetDeleteByHandler();
1046 ipaddr_t local;
1047 Utility::u2ip("127.0.0.1", local);
1048 if (!resolv -> Open(local, m_resolver_port))
1050 LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
1052 Add(resolv);
1053 return resolv -> GetId();
1055 #endif
1058 int SocketHandler::Resolve(Socket *p,ipaddr_t a)
1060 // check cache
1061 ResolvSocket *resolv = new ResolvSocket(*this, p, a);
1062 resolv -> SetId(++m_resolv_id);
1063 resolv -> SetDeleteByHandler();
1064 ipaddr_t local;
1065 Utility::u2ip("127.0.0.1", local);
1066 if (!resolv -> Open(local, m_resolver_port))
1068 LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
1070 Add(resolv);
1071 return resolv -> GetId();
1075 #ifdef ENABLE_IPV6
1076 int SocketHandler::Resolve(Socket *p,in6_addr& a)
1078 // check cache
1079 ResolvSocket *resolv = new ResolvSocket(*this, p, a);
1080 resolv -> SetId(++m_resolv_id);
1081 resolv -> SetDeleteByHandler();
1082 ipaddr_t local;
1083 Utility::u2ip("127.0.0.1", local);
1084 if (!resolv -> Open(local, m_resolver_port))
1086 LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
1088 Add(resolv);
1089 return resolv -> GetId();
1091 #endif
1094 void SocketHandler::EnableResolver(port_t port)
1096 if (!m_resolver)
1098 m_resolver_port = port;
1099 m_resolver = new ResolvServer(port);
1104 bool SocketHandler::ResolverReady()
1106 return m_resolver ? m_resolver -> Ready() : false;
1108 #endif // ENABLE_RESOLVER
1111 #ifdef ENABLE_SOCKS4
1112 void SocketHandler::SetSocks4TryDirect(bool x)
1114 m_bTryDirect = x;
1118 ipaddr_t SocketHandler::GetSocks4Host()
1120 return m_socks4_host;
1124 port_t SocketHandler::GetSocks4Port()
1126 return m_socks4_port;
1130 const std::string& SocketHandler::GetSocks4Userid()
1132 return m_socks4_userid;
1136 bool SocketHandler::Socks4TryDirect()
1138 return m_bTryDirect;
1140 #endif
1143 #ifdef ENABLE_RESOLVER
1144 bool SocketHandler::ResolverEnabled()
1146 return m_resolver ? true : false;
1150 port_t SocketHandler::GetResolverPort()
1152 return m_resolver_port;
1154 #endif // ENABLE_RESOLVER
1157 #ifdef ENABLE_POOL
1158 ISocketHandler::PoolSocket *SocketHandler::FindConnection(int type,const std::string& protocol,SocketAddress& ad)
1160 for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end() && m_sockets.size(); it++)
1162 PoolSocket *pools = dynamic_cast<PoolSocket *>(it -> second);
1163 if (pools)
1165 if (pools -> GetSocketType() == type &&
1166 pools -> GetSocketProtocol() == protocol &&
1167 // %! pools -> GetClientRemoteAddress() &&
1168 *pools -> GetClientRemoteAddress() == ad)
1170 m_sockets.erase(it);
1171 pools -> SetRetain(); // avoid Close in Socket destructor
1172 return pools; // Caller is responsible that this socket is deleted
1176 return NULL;
1180 void SocketHandler::EnablePool(bool x)
1182 m_b_enable_pool = x;
1186 bool SocketHandler::PoolEnabled()
1188 return m_b_enable_pool;
1190 #endif
1193 void SocketHandler::Remove(Socket *p)
1195 if (p -> ErasedByHandler())
1197 return;
1199 for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
1201 if (it -> second == p)
1203 LogError(p, "Remove", -1, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
1204 m_sockets.erase(it);
1205 return;
1208 for (socket_m::iterator it2 = m_add.begin(); it2 != m_add.end(); it2++)
1210 if ((*it2).second == p)
1212 LogError(p, "Remove", -2, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
1213 m_add.erase(it2);
1214 return;
1217 for (std::list<Socket *>::iterator it3 = m_delete.begin(); it3 != m_delete.end(); it3++)
1219 if (*it3 == p)
1221 LogError(p, "Remove", -3, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
1222 m_delete.erase(it3);
1223 return;
1229 void SocketHandler::CheckSanity()
1231 CheckList(m_fds, "active sockets"); // active sockets
1232 CheckList(m_fds_erase, "sockets to be erased"); // should always be empty anyway
1233 CheckList(m_fds_callonconnect, "checklist CallOnConnect");
1234 #ifdef ENABLE_DETACH
1235 CheckList(m_fds_detach, "checklist Detach");
1236 #endif
1237 CheckList(m_fds_timeout, "checklist Timeout");
1238 CheckList(m_fds_retry, "checklist retry client connect");
1239 CheckList(m_fds_close, "checklist close and delete");
1243 void SocketHandler::CheckList(socket_v& ref,const std::string& listname)
1245 for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
1247 SOCKET s = *it;
1248 if (m_sockets.find(s) != m_sockets.end())
1249 continue;
1250 if (m_add.find(s) != m_add.end())
1251 continue;
1252 bool found = false;
1253 for (std::list<Socket *>::iterator it = m_delete.begin(); it != m_delete.end(); it++)
1255 Socket *p = *it;
1256 if (p -> GetSocket() == s)
1258 found = true;
1259 break;
1262 if (!found)
1264 fprintf(stderr, "CheckList failed for \"%s\": fd %d\n", listname.c_str(), s);
1270 void SocketHandler::AddList(SOCKET s,list_t which_one,bool add)
1272 if (s == INVALID_SOCKET)
1274 DEB( fprintf(stderr, "AddList: invalid_socket\n");)
1275 return;
1277 socket_v& ref =
1278 (which_one == LIST_CALLONCONNECT) ? m_fds_callonconnect :
1279 #ifdef ENABLE_DETACH
1280 (which_one == LIST_DETACH) ? m_fds_detach :
1281 #endif
1282 (which_one == LIST_TIMEOUT) ? m_fds_timeout :
1283 (which_one == LIST_RETRY) ? m_fds_retry :
1284 (which_one == LIST_CLOSE) ? m_fds_close : m_fds_close;
1285 if (add)
1287 #ifdef ENABLE_DETACH
1288 DEB( fprintf(stderr, "AddList; %5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" :
1289 (which_one == LIST_DETACH) ? "Detach" :
1290 (which_one == LIST_TIMEOUT) ? "Timeout" :
1291 (which_one == LIST_RETRY) ? "Retry" :
1292 (which_one == LIST_CLOSE) ? "Close" : "<undef>",
1293 add ? "Add" : "Remove");)
1294 #else
1295 DEB( fprintf(stderr, "AddList; %5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" :
1296 (which_one == LIST_TIMEOUT) ? "Timeout" :
1297 (which_one == LIST_RETRY) ? "Retry" :
1298 (which_one == LIST_CLOSE) ? "Close" : "<undef>",
1299 add ? "Add" : "Remove");)
1300 #endif
1302 if (add)
1304 for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
1306 if (*it == s) // already there
1308 return;
1311 ref.push_back(s);
1312 return;
1314 // remove
1315 for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
1317 if (*it == s)
1319 ref.erase(it);
1320 break;
1323 //DEB( fprintf(stderr, "/AddList\n");)
1327 #ifdef ENABLE_TRIGGERS
1328 int SocketHandler::TriggerID(Socket *src)
1330 int id = m_next_trigger_id++;
1331 m_trigger_src[id] = src;
1332 return id;
1336 bool SocketHandler::Subscribe(int id, Socket *dst)
1338 if (m_trigger_src.find(id) != m_trigger_src.end())
1340 std::map<Socket *, bool>::iterator it = m_trigger_dst[id].find(dst);
1341 if (it != m_trigger_dst[id].end())
1343 m_trigger_dst[id][dst] = true;
1344 return true;
1346 LogError(dst, "Subscribe", id, "Already subscribed", LOG_LEVEL_INFO);
1347 return false;
1349 LogError(dst, "Subscribe", id, "Trigger id not found", LOG_LEVEL_INFO);
1350 return false;
1354 bool SocketHandler::Unsubscribe(int id, Socket *dst)
1356 if (m_trigger_src.find(id) != m_trigger_src.end())
1358 std::map<Socket *, bool>::iterator it = m_trigger_dst[id].find(dst);
1359 if (it != m_trigger_dst[id].end())
1361 m_trigger_dst[id].erase(it);
1362 return true;
1364 LogError(dst, "Unsubscribe", id, "Not subscribed", LOG_LEVEL_INFO);
1365 return false;
1367 LogError(dst, "Unsubscribe", id, "Trigger id not found", LOG_LEVEL_INFO);
1368 return false;
1372 void SocketHandler::Trigger(int id, Socket::TriggerData& data, bool erase)
1374 if (m_trigger_src.find(id) != m_trigger_src.end())
1376 data.SetSource( m_trigger_src[id] );
1377 for (std::map<Socket *, bool>::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++)
1379 Socket *dst = it -> first;
1380 if (Valid(dst))
1382 dst -> OnTrigger(id, data);
1385 if (erase)
1387 m_trigger_src.erase(m_trigger_src.find(id));
1388 m_trigger_dst.erase(m_trigger_dst.find(id));
1391 else
1393 LogError(NULL, "Trigger", id, "Trigger id not found", LOG_LEVEL_INFO);
1396 #endif // ENABLE_TRIGGERS
1399 #ifdef SOCKETS_NAMESPACE
1401 #endif