1 /** \file SocketHandler.cpp
3 ** \author grymse@alhem.net
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.
32 #pragma warning(disable:4786)
41 #include "SocketHandler.h"
42 #include "UdpSocket.h"
43 #include "ResolvSocket.h"
44 #include "ResolvServer.h"
45 #include "TcpSocket.h"
48 #include "SocketAddress.h"
50 #ifdef SOCKETS_NAMESPACE
51 namespace SOCKETS_NAMESPACE
{
55 #ifdef _DEBUGNOTDEFINED
56 #define DEB(x) x; fflush(stderr);
62 SocketHandler::SocketHandler(StdLog
*p
)
75 #ifdef ENABLE_RESOLVER
80 ,m_b_enable_pool(false)
82 #ifdef ENABLE_TRIGGERS
95 SocketHandler::SocketHandler(Mutex
& mutex
,StdLog
*p
)
108 #ifdef ENABLE_RESOLVER
113 ,m_b_enable_pool(false)
115 #ifdef ENABLE_TRIGGERS
116 ,m_next_trigger_id(0)
129 SocketHandler::~SocketHandler()
131 #ifdef ENABLE_RESOLVER
134 m_resolver
-> Quit();
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
;
145 DEB( fprintf(stderr
, " fd %d\n", p
-> GetSocket());)
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()
157 && !(m_slave
^ p
-> IsDetached())
161 p
-> SetErasedByHandler();
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
187 Mutex
& SocketHandler::GetMutex() const
194 void SocketHandler::SetSlave(bool x
)
200 bool SocketHandler::IsSlave()
207 void SocketHandler::RegStdLog(StdLog
*log
)
213 void SocketHandler::LogError(Socket
*p
,const std::string
& user_text
,int err
,const std::string
& sys_err
,loglevel_t t
)
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
);
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
);
239 m_add
[p
-> GetSocket()] = p
;
243 void SocketHandler::Get(SOCKET s
,bool& r
,bool& w
,bool& e
)
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");)
261 if (!FD_ISSET(s
, &m_rfds
))
272 if (!FD_ISSET(s
, &m_wfds
))
283 if (!FD_ISSET(s
, &m_efds
))
296 int SocketHandler::Select(long sec
,long usec
)
305 int SocketHandler::Select()
307 if (m_fds_callonconnect
.size() ||
309 (!m_slave
&& m_fds_detach
.size()) ||
311 m_fds_timeout
.size() ||
312 m_fds_retry
.size() ||
313 m_fds_close
.size() ||
316 return Select(0, 200000);
322 int SocketHandler::Select(struct timeval
*tsel
)
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
);
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
);
346 if (!p
-> CloseAndDelete())
348 StreamSocket
*scp
= dynamic_cast<StreamSocket
*>(p
);
349 if (scp
&& scp
-> Connecting()) // 'Open' called before adding socket
355 TcpSocket
*tcp
= dynamic_cast<TcpSocket
*>(p
);
356 bool bWrite
= tcp
? tcp
-> GetOutputLength() != 0 : false;
357 if (p
-> IsDisableRead())
359 Set(s
, false, bWrite
);
363 Set(s
, true, bWrite
);
366 m_maxsock
= (s
> m_maxsock
) ? s
: m_maxsock
;
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
376 if (!(m_slave
^ p
-> IsDetach()))
389 FD_COPY(&m_rfds
, &rfds
);
390 FD_COPY(&m_wfds
, &wfds
);
391 FD_COPY(&m_efds
, &efds
);
393 fd_set rfds
= m_rfds
;
394 fd_set wfds
= m_wfds
;
395 fd_set efds
= m_efds
;
401 n
= select( (int)(m_maxsock
+ 1),&rfds
,&wfds
,&efds
,tsel
);
406 n
= select( (int)(m_maxsock
+ 1),&rfds
,&wfds
,&efds
,tsel
);
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
));
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>");
426 for (SOCKET i
= 0; i
<= m_maxsock
; i
++)
432 if (FD_ISSET(i
, &m_rfds
))
437 if (FD_ISSET(i
, &m_wfds
))
442 if (FD_ISSET(i
, &m_efds
))
447 if (t
&& m_sockets
.find(i
) == m_sockets
.end())
449 fprintf(stderr
, "Bad fd in fd_set: %d\n", i
);
455 /// \todo rebuild fd_set's from active sockets list (m_sockets) here
465 for (socket_v::iterator it2
= m_fds
.begin(); it2
!= m_fds
.end() && n
; 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
476 if (p
-> IsSSLNegotiate())
488 LogError(NULL
, "GetSocket/handler/1", (int)i
, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING
);
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
500 if (p
-> IsSSLNegotiate())
512 LogError(NULL
, "GetSocket/handler/2", (int)i
, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING
);
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
;
526 LogError(NULL
, "GetSocket/handler/3", (int)i
, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING
);
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
++)
542 socket_m::iterator itmp
= m_sockets
.find(*it
);
543 if (itmp
!= m_sockets
.end()) // found
549 LogError(NULL
, "GetSocket/handler/4", (int)*it
, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING
);
554 // if (p -> CallOnConnect() && p -> Ready() )
556 p
-> SetConnected(); // moved here from inside if (tcp) check below
558 if (p
-> IsSSL()) // SSL Enabled socket
564 p
-> OnSocks4Connect();
568 TcpSocket
*tcp
= dynamic_cast<TcpSocket
*>(p
);
571 if (tcp
-> GetOutputLength())
576 #ifdef ENABLE_RECONNECT
577 if (tcp
&& tcp
-> IsReconnect())
582 // LogError(p, "Calling OnConnect", 0, "Because CallOnConnect", LOG_LEVEL_INFO);
586 // p -> SetCallOnConnect( false );
587 AddList(p
-> GetSocket(), LIST_CALLONCONNECT
, false);
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
++)
601 socket_m::iterator itmp
= m_sockets
.find(*it
);
602 if (itmp
!= m_sockets
.end()) // found
608 LogError(NULL
, "GetSocket/handler/5", (int)*it
, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING
);
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.
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());
627 // check Connecting - connection timeout - conditional event
628 if (m_fds_timeout
.size())
630 time_t tnow
= time(NULL
);
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
++)
639 socket_m::iterator itmp
= m_sockets
.find(*it
);
640 if (itmp
!= m_sockets
.end()) // found
646 itmp
= m_add
.find(*it
);
647 if (itmp
!= m_add
.end())
653 LogError(NULL
, "GetSocket/handler/6", (int)*it
, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING
);
659 if (p
-> Timeout(tnow
))
661 StreamSocket
*scp
= dynamic_cast<StreamSocket
*>(p
);
662 if (scp
&& scp
-> Connecting())
663 p
-> OnConnectTimeout();
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
++)
681 socket_m::iterator itmp
= m_sockets
.find(*it
);
682 if (itmp
!= m_sockets
.end()) // found
688 LogError(NULL
, "GetSocket/handler/7", (int)*it
, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING
);
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();
707 LogError(p
, "RetryClientConnect", 0, "no address", LOG_LEVEL_ERROR
);
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
++)
724 socket_m::iterator itmp
= m_sockets
.find(*it
);
725 if (itmp
!= m_sockets
.end()) // found
731 itmp
= m_add
.find(*it
);
732 if (itmp
!= m_add
.end())
738 LogError(NULL
, "GetSocket/handler/8", (int)*it
, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING
);
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() &&
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
))
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
);
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)
782 std::auto_ptr
<SocketAddress
> ad
= p
-> GetClientRemoteAddress();
789 LogError(p
, "Reconnect", 0, "no address", LOG_LEVEL_ERROR
);
791 tcp
-> ResetConnectionRetries();
793 m_fds_erase
.push_back(nn
);
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
);
805 if (p
-> Retain() && !p
-> Lost())
807 PoolSocket
*p2
= new PoolSocket(*this, p
);
808 p2
-> SetDeleteByHandler();
811 p
-> SetCloseAndDelete(false); // added - remove from m_fds_close
814 #endif // ENABLE_POOL
816 Set(p
-> GetSocket(),false,false,false);
817 DEB( fprintf(stderr
, "Close() before OnDelete\n");)
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();
840 for (socket_v::iterator it
= m_fds_detach
.begin(); it
!= m_fds_detach
.end(); it
++)
844 m_fds_detach
.erase(it
);
851 for (socket_v::iterator it
= m_fds
.begin(); it
!= m_fds
.end(); it
++)
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
872 if (p
-> ErasedByHandler()
874 && !(m_slave
^ p
-> IsDetached())
878 #ifdef ENABLE_TRIGGERS
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
;
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
;
894 dst
-> OnCancelled(id
);
897 m_trigger_src
.erase(m_trigger_src
.find(id
));
898 m_trigger_dst
.erase(m_trigger_dst
.find(id
));
910 m_fds_erase
.erase(it
);
913 // calculate max file descriptor for select() call
917 for (socket_v::iterator it
= m_fds
.begin(); it
!= m_fds
.end(); 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();
930 if (p
-> DeleteByHandler()
932 && !(m_slave
^ p
-> IsDetached())
936 p
-> SetErasedByHandler();
937 #ifdef ENABLE_TRIGGERS
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
;
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
;
953 dst
-> OnCancelled(id
);
956 m_trigger_src
.erase(m_trigger_src
.find(id
));
957 m_trigger_dst
.erase(m_trigger_dst
.find(id
));
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
;
983 bool SocketHandler::OkToAccept(Socket
*)
989 size_t SocketHandler::GetCount()
991 return m_sockets
.size() + m_add
.size() + m_delete
.size();
996 void SocketHandler::SetSocks4Host(ipaddr_t 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
;
1021 #ifdef ENABLE_RESOLVER
1022 int SocketHandler::Resolve(Socket
*p
,const std::string
& host
,port_t port
)
1025 ResolvSocket
*resolv
= new ResolvSocket(*this, p
, host
, port
);
1026 resolv
-> SetId(++m_resolv_id
);
1027 resolv
-> SetDeleteByHandler();
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
);
1035 return resolv
-> GetId();
1040 int SocketHandler::Resolve6(Socket
*p
,const std::string
& host
,port_t port
)
1043 ResolvSocket
*resolv
= new ResolvSocket(*this, p
, host
, port
, true);
1044 resolv
-> SetId(++m_resolv_id
);
1045 resolv
-> SetDeleteByHandler();
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
);
1053 return resolv
-> GetId();
1058 int SocketHandler::Resolve(Socket
*p
,ipaddr_t a
)
1061 ResolvSocket
*resolv
= new ResolvSocket(*this, p
, a
);
1062 resolv
-> SetId(++m_resolv_id
);
1063 resolv
-> SetDeleteByHandler();
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
);
1071 return resolv
-> GetId();
1076 int SocketHandler::Resolve(Socket
*p
,in6_addr
& a
)
1079 ResolvSocket
*resolv
= new ResolvSocket(*this, p
, a
);
1080 resolv
-> SetId(++m_resolv_id
);
1081 resolv
-> SetDeleteByHandler();
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
);
1089 return resolv
-> GetId();
1094 void SocketHandler::EnableResolver(port_t port
)
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
)
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
;
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
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
);
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
1180 void SocketHandler::EnablePool(bool x
)
1182 m_b_enable_pool
= x
;
1186 bool SocketHandler::PoolEnabled()
1188 return m_b_enable_pool
;
1193 void SocketHandler::Remove(Socket
*p
)
1195 if (p
-> ErasedByHandler())
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
);
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
);
1217 for (std::list
<Socket
*>::iterator it3
= m_delete
.begin(); it3
!= m_delete
.end(); it3
++)
1221 LogError(p
, "Remove", -3, "Socket destructor called while still in use", LOG_LEVEL_WARNING
);
1222 m_delete
.erase(it3
);
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");
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
++)
1248 if (m_sockets
.find(s
) != m_sockets
.end())
1250 if (m_add
.find(s
) != m_add
.end())
1253 for (std::list
<Socket
*>::iterator it
= m_delete
.begin(); it
!= m_delete
.end(); it
++)
1256 if (p
-> GetSocket() == s
)
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");)
1278 (which_one
== LIST_CALLONCONNECT
) ? m_fds_callonconnect
:
1279 #ifdef ENABLE_DETACH
1280 (which_one
== LIST_DETACH
) ? m_fds_detach
:
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
;
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");)
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");)
1304 for (socket_v::iterator it
= ref
.begin(); it
!= ref
.end(); it
++)
1306 if (*it
== s
) // already there
1315 for (socket_v::iterator it
= ref
.begin(); it
!= ref
.end(); it
++)
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
;
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;
1346 LogError(dst
, "Subscribe", id
, "Already subscribed", LOG_LEVEL_INFO
);
1349 LogError(dst
, "Subscribe", id
, "Trigger id not found", LOG_LEVEL_INFO
);
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
);
1364 LogError(dst
, "Unsubscribe", id
, "Not subscribed", LOG_LEVEL_INFO
);
1367 LogError(dst
, "Unsubscribe", id
, "Trigger id not found", LOG_LEVEL_INFO
);
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
;
1382 dst
-> OnTrigger(id
, data
);
1387 m_trigger_src
.erase(m_trigger_src
.find(id
));
1388 m_trigger_dst
.erase(m_trigger_dst
.find(id
));
1393 LogError(NULL
, "Trigger", id
, "Trigger id not found", LOG_LEVEL_INFO
);
1396 #endif // ENABLE_TRIGGERS
1399 #ifdef SOCKETS_NAMESPACE