Stream::SocketPoll Class Referenceabstract

Stream provider using sockets and using poll. More...

Inheritance diagram for Stream::SocketPoll:
Stream::Provider Poll::User

Public Member Functions

void Die () override
 Make this provider go away.
 
void tidy ()
 Tidy up - close connections etc.
 
endpoint_t GetEndpoint (bool inheriting) override
 Get the endpoint ID.
 
unsigned Events () override
 Get the events.
 
int GetLocalAddress (struct sockaddr *laddr, socklen_t *lalenp, MSGstruct *msp) override
 Get the local address.
 
int GetPeerAddress (struct sockaddr *laddr, socklen_t *lalenp, MSGstruct *msp) override
 Get the peer address.
 
TLS_CipherSuite GetCipherSuite () override
 Get the cipher suite.
 
X509 * GetPeerCertificate () override
 Get the peer certificate.
 
virtual SocketPollClone ()=0
 Make another provider like this one.
 
void actualDeliver (time_t *msg)
 Handle timer event.
 
void actualDeliver (::Poll::pollmsg *msg) override
 Actual Deliver events to Poll provider.
 
void actualDeliver (External *ext)
 Set external.
 
void actualDeliver (ConnectRequest *req)
 connect
 
void actualDeliver (ListenRequest *req)
 listen
 
void actualDeliver (ConnectAccept *req)
 accept
 
void actualDeliver (DisconnectRequest *req)
 disconnect
 
void actualDeliver (DataRequest *req)
 send data
 
void actualDeliver (ReadRequest *req)
 ReadRequest.
 
void actualDeliver (StartTLS *req)
 Start SSL/TLS on stream.
 
void actualDeliver (StreamControl *option)
 Control stream.
 
virtual void Deliver (time_t *msg)
 Handle timer event.
 
void Deliver (::Poll::pollmsg *msg) override
 Deliver events to Poll provider.
 
void Deliver (External *ext) override
 Set external.
 
void Deliver (ConnectRequest *req) override
 connect
 
void Deliver (ListenRequest *req) override
 listen
 
void Deliver (ConnectAccept *req) override
 accept
 
void Deliver (DisconnectRequest *req) override
 disconnect
 
void Deliver (DataRequest *req) override
 send data
 
void Deliver (ReadRequest *req) override
 Read request.
 
void Deliver (StartTLS *req) override
 Start SSL/TLS on stream.
 
void Deliver (StreamControl *option) override
 Control stream.
 
void Deliver (LengthFnxRequest *) override
 Set length function.
 
- Public Member Functions inherited from Stream::Provider
 Provider ()
 The user of this provider.
 
virtual ~Provider ()
 Destructor should be virtual.
 
void SetUser (User *u)
 set the user
 
UserGetUser ()
 get the user
 
- Public Member Functions inherited from Poll::User
 User ()
 User's view of events.
 
 ~User () override
 Destructor is virtual.
 
virtual void Deliver (pollmsg *msg)=0
 Deliver events to Poll user.
 
virtual void actualDeliver (pollmsg *msg)=0
 Deliver events to Poll user.
 

Additional Inherited Members

- Static Public Member Functions inherited from Stream::Provider
static EVENTSVC_DLL ProviderProviderFactory (const char *type, MSGstruct *msp)
 Factory method for Stream provider.
 
- Data Fields inherited from Poll::User
UserEvent _event
 
endpoint_t _fd
 Event to User.
 
unsigned _pevents
 FD for this user.
 
unsigned _uevents
 Provider's view of events.
 

Detailed Description

Stream provider using sockets and using poll.

Definition at line 67 of file stream_socket_poll.C.

Constructor & Destructor Documentation

◆ ~SocketPoll()

Stream::SocketPoll::~SocketPoll ( )
inlineoverrideprotected

Definition at line 183 of file stream_socket_poll.C.

183 {
184 tidy ();
185 }
void tidy()
Tidy up - close connections etc.

◆ SocketPoll()

Stream::SocketPoll::SocketPoll ( )
inline

Definition at line 188 of file stream_socket_poll.C.

188 :
189 _poller (0),
190 _state (State_noconnect),
191 _rlen (0),
192 _rfill (false),
193 _rfull (false),
194 _wlen (0),
195 _ssl (0),
196 _hostname (0),
197 _emfile (0),
198 _noshut (false)
199 {
200 _event.Init (this);
201 _timer.Init (this);
202 }
void Init(C *rcvr)
Set the target.
Definition Syncmsg.h:48

Member Function Documentation

◆ Die()

void Stream::SocketPoll::Die ( )
inlineoverridevirtual

Make this provider go away.

Implements Stream::Provider.

Definition at line 205 of file stream_socket_poll.C.

205 {
206 delete this;
207 }

◆ tidy()

void Stream::SocketPoll::tidy ( )
inline

Tidy up - close connections etc.

Definition at line 210 of file stream_socket_poll.C.

210 {
211 SetUser (0);
212
213 if ( _ssl != 0 ) {
214 if ( _poller != 0 ) {
215 _poller->Deregister (this);
216 _poller = 0;
217 }
218
219 // This closes the socket
220 int err = SSL_get_error(_ssl, 0);
221 if (err != SSL_ERROR_NONE) {
222 // Report but clear and continue
223 LOG_DEBUG (("SocketPoll::tidy() - SSL error (%d)", err));
224 ERR_clear_error();
225 }
226 SSL_free (_ssl);
227 _ssl = 0;
228
229 _fd = INVALID_ENDPOINT;
230 _event.Cancel ();
231
232 } else if ( _fd != INVALID_ENDPOINT ) {
233 if ( _poller != 0 ) {
234 _poller->Deregister (this);
235 _poller = 0;
236 }
237
238 // This seems to be the way to close sockets cleanly
239 // on Windows. If you use SHUT_RDWR (aka SH_BOTH) the
240 // remote end can be reset.
241 if ( !_noshut )
242 shutdown (_fd, SHUT_WR);
243
244 closesocket (_fd);
245 _fd = INVALID_ENDPOINT;
246
247 _event.Cancel ();
248 }
249
250 _rbuf = _rptr = 0;
251 _rlen = 0;
252 _rfull = false;
253
254 _state = State_noconnect;
255 }
virtual void Deregister(User *user)=0
Deregister endpoint.
endpoint_t _fd
Event to User.
void SetUser(User *u)
set the user

References Poll::User::_fd, Poll::Provider::Deregister(), and Stream::Provider::SetUser().

◆ GetEndpoint()

endpoint_t Stream::SocketPoll::GetEndpoint ( bool  inheriting)
inlineoverridevirtual

Get the endpoint ID.

Implements Stream::Provider.

Definition at line 259 of file stream_socket_poll.C.

259 {
260 if ( inheriting ) {
261 _noshut = true;
262
263#ifdef IC_WIN32
264 if ( SetHandleInformation ((HANDLE)_fd,
265 HANDLE_FLAG_INHERIT,
266 HANDLE_FLAG_INHERIT) == 0 ) {
267 MSG_IOevent_Inherit_LOG();
268 }
269
270#elif defined (FD_CLOEXEC)
271 int flags = fcntl (_fd, F_GETFD, 0);
272
273 if ( flags >= 0 ) {
274 flags &= ~FD_CLOEXEC;
275 if ( fcntl (_fd, F_SETFD, flags) != 0 ) {
276 MSG_IOevent_Inherit_LOG ();
277 }
278 }
279#endif
280 }
281 return _fd;
282 }

References Poll::User::_fd.

◆ Events()

unsigned Stream::SocketPoll::Events ( )
inlineoverridevirtual

Get the events.

Implements Stream::Provider.

Definition at line 285 of file stream_socket_poll.C.

285 {
286 return _uevents;
287 }
unsigned _uevents
Provider's view of events.

References Poll::User::_uevents.

◆ GetLocalAddress()

int Stream::SocketPoll::GetLocalAddress ( struct sockaddr *  laddr,
socklen_t *  lalenp,
MSGstruct *  msp 
)
inlineoverridevirtual

Get the local address.

Implements Stream::Provider.

Definition at line 290 of file stream_socket_poll.C.

292 {
293
294 if ( _fd == INVALID_ENDPOINT ) {
295 MSG_IOevent_NotConnected_SET (msp);
296 return MSG_IOevent_NotConnected;
297 }
298
299#ifdef GETSOCKNAME_NEEDS_INTP
300 int lalen;
301#else
302 socklen_t lalen;
303#endif
304 lalen = *lalenp;
305 if ( getsockname (_fd, laddr, &lalen) != 0 ) {
306 *lalenp = lalen;
307 MSG_IOevent_IOerror_SET (msp, "getsockname");
308 return MSG_IOevent_IOerror;
309 }
310
311 // In case encapsulated IPv4 address
312 *lalenp = convert2ipv4 (laddr, lalen);
313 return 0;
314 }

References Poll::User::_fd.

◆ GetPeerAddress()

int Stream::SocketPoll::GetPeerAddress ( struct sockaddr *  laddr,
socklen_t *  lalenp,
MSGstruct *  msp 
)
inlineoverridevirtual

Get the peer address.

Implements Stream::Provider.

Definition at line 317 of file stream_socket_poll.C.

319 {
320
321 if ( _fd == INVALID_ENDPOINT ) {
322 MSG_IOevent_NotConnected_SET (msp);
323 return MSG_IOevent_NotConnected;
324 }
325
326#ifdef GETPEERNAME_NEEDS_INTP
327 int lalen;
328#else
329 socklen_t lalen;
330#endif
331 lalen = *lalenp;
332 if ( getpeername (_fd, laddr, &lalen) != 0 ) {
333 *lalenp = lalen;
334 MSG_IOevent_IOerror_SET (msp, "getpeername");
335 return MSG_IOevent_IOerror;
336 }
337
338 // In case encapsulated IPv4 address
339 *lalenp = convert2ipv4 (laddr, lalen);
340 return 0;
341 }

References Poll::User::_fd.

◆ GetCipherSuite()

TLS_CipherSuite Stream::SocketPoll::GetCipherSuite ( )
inlineoverridevirtual

Get the cipher suite.

Reimplemented from Stream::Provider.

Definition at line 344 of file stream_socket_poll.C.

344 {
345 if ( _state != State_tls || _ssl == 0 )
346 return TLS_NULL_WITH_NULL_NULL;
347
348 const SSL_CIPHER *cipher = SSL_get_current_cipher(_ssl);
349 return SSLTLS::cipher_id(cipher);
350 }

◆ GetPeerCertificate()

X509 * Stream::SocketPoll::GetPeerCertificate ( )
inlineoverridevirtual

Get the peer certificate.

Reimplemented from Stream::Provider.

Definition at line 353 of file stream_socket_poll.C.

353 {
354 if ( _state != State_tls || _ssl == 0 )
355 return 0;
356
357 return SSL_get_peer_certificate(_ssl);
358 }

◆ actualDeliver() [1/9]

void SocketPoll::actualDeliver ( time_t *  msg)

Handle timer event.

Definition at line 1541 of file stream_socket_poll.C.

1542{
1543 // Timer has expired after EMFILE, try again
1544 waitEvent (::Poll::Event_In);
1545}

Referenced by Deliver(), Deliver(), Deliver(), Deliver(), Deliver(), Deliver(), Deliver(), Deliver(), Deliver(), Deliver(), and Deliver().

◆ actualDeliver() [2/9]

void SocketPoll::actualDeliver ( ::Poll::pollmsg msg)
override

Actual Deliver events to Poll provider.

Definition at line 1547 of file stream_socket_poll.C.

1548{
1549 if ( checkUser() ) return;
1550
1551 StatusIndication statusind (this);
1552
1553 LOG_DEBUG (("SocketPoll::actualDeliver (pollmsg = %x) state=%d",
1554 msg->events, _state));
1555
1556 // Poller is no longer listening for any events
1557 _pevents = 0;
1558
1559 if ( (msg->events & ::Poll::Event_Terminate) ) {
1560 // System terminating
1561 _uevents = 0;
1562
1563 // Close first, otherwise calls back to poller
1564 closesocket (_fd);
1565 _fd = INVALID_ENDPOINT;
1566 _poller = 0;
1567
1568 // Tell User
1569 MSG_IOevent_Terminating_SET (&statusind.msg);
1570 GetUser()->Deliver (&statusind);
1571
1572 return;
1573 }
1574
1575 if ( msg->events &
1576 (::Poll::Event_Err | ::Poll::Event_Hup | ::Poll::Event_Nval) ) {
1577
1578 // Don't want any events
1579 _uevents = 0;
1580
1581 // Get error from socket
1582 int eno;
1583#ifdef GETSOCKOPT_NEEDS_INTP
1584 int olen;
1585#else
1586 socklen_t olen;
1587#endif
1588 olen = sizeof eno;
1589
1590 /* Casting to (char *) is required for Windows */
1591 int rc = getsockopt (_fd, SOL_SOCKET, SO_ERROR, (char *)&eno, &olen);
1592
1593 const char *argv[1];
1594 argv[0] = "poll";
1595
1596 MSGsetv (&statusind.msg, MSG_IOevent_IOerror, 1, argv);
1597
1598 if ( rc == 0 ) {
1599 MSGstruct sockerr;
1600 MSGsetv (&sockerr,
1601 MSGID_BUILD(MSGLEVEL_ERROR, MSGID_SYSFAC, eno),
1602 0, 0);
1603 MSGappend (&statusind.msg, &sockerr);
1604 } else {
1605 MSGappendsyserror (&statusind.msg);
1606 }
1607
1608 GetUser()->Deliver (&statusind);
1609
1610 tidy ();
1611
1612 return;
1613 }
1614
1615 // Cancel desired events
1616 _uevents &= ~msg->events;
1617
1618 if ( msg->events & ::Poll::Event_In ) {
1619
1620 switch ( _state ) {
1621 case State_tls:
1622 doTLS();
1623 break;
1624
1625 case State_need_proxy:
1626 if ( !doProxy() )
1627 waitEvent (::Poll::Event_In);
1628 break;
1629 case State_connected:
1630 LOG_DEBUG (("Read stuff: _rlen = %d", (int)_rlen));
1631 if ( _rlen != 0 ) {
1632 // Stuff to read. If does not complete, then wait again
1633 if ( !doRead () )
1634 waitEvent (::Poll::Event_In);
1635 }
1636 break;
1637
1638 case State_listening:
1639 doAccept ();
1640 break;
1641
1642 default:
1643 break;
1644 }
1645 }
1646
1647 if ( msg->events & ::Poll::Event_Out ) {
1648
1649 switch ( _state ) {
1650 case State_tls:
1651 doTLS();
1652 break;
1653
1654 case State_need_proxy:
1655 // Unexpected state at this point, fall through to connected
1656 LOG_DEBUG (("Need proxy state seen when writing"));
1657 FALLTHROUGH;
1658 case State_connected:
1659 if ( _wlen != 0 ) {
1660 // Stuff to write. If does not complete, then wait again
1661 if ( !doWrite () )
1662 waitEvent (::Poll::Event_Out);
1663 }
1664 break;
1665
1666 case State_connecting:
1667 _state = GetUser()->Proxy() ? State_need_proxy : State_connected;
1668 MSG_IOevent_Connected_SET (&statusind.msg);
1669 GetUser()->Deliver (&statusind);
1670 break;
1671
1672 default:
1673 break;
1674 }
1675 }
1676
1677 if ( (_uevents & ~_pevents) && _poller )
1678 _poller->Control (this);
1679}
virtual void Control(User *user)=0
Set the events which are interesting for end point.
unsigned _pevents
FD for this user.
User * GetUser()
get the user
virtual bool Proxy()
Provider expects a PROXY header.
virtual void Deliver(ConnectIndication *data)=0
Connection indication.

◆ actualDeliver() [3/9]

void SocketPoll::actualDeliver ( Stream::External ext)

Set external.

Definition at line 1681 of file stream_socket_poll.C.

1682{
1683 if ( checkUser() ) return;
1684
1685 StatusIndication statusind (this);
1686
1687 LOG_DEBUG (("SocketPoll::actualDeliver (External)"));
1688
1689 if ( _state != State_noconnect ) {
1690 MSG_IOevent_NotConnected_SET (&statusind.msg);
1691 GetUser()->Deliver (&statusind);
1692 return;
1693 }
1694
1695 _fd = ext->fd;
1696
1697 if ( ext->listen ) {
1698 _state = State_listening;
1699
1700 waitEvent (::Poll::Event_In);
1701
1702 } else {
1703 _state = GetUser()->Proxy() ? State_need_proxy : State_connected;
1704 }
1705}
bool listen
The network endpoint from some external source.

References Stream::External::listen.

◆ actualDeliver() [4/9]

void SocketPoll::actualDeliver ( Stream::ConnectRequest req)

connect

Definition at line 1707 of file stream_socket_poll.C.

1708{
1709 if ( checkUser() ) return;
1710
1711 StatusIndication statusind (this);
1712
1713 LOG_DEBUG (("SocketPoll::actualDeliver (ConnectRequest)"));
1714
1715 if ( _state != State_noconnect ) {
1716 MSG_IOevent_NotConnected_SET (&statusind.msg);
1717 GetUser()->Deliver (&statusind);
1718 return;
1719 }
1720
1721 int family;
1722#if defined(AF_INET6) && defined(PF_INET6)
1723 struct sockaddr_in6 ipv6addr;
1724#endif
1725
1726 switch ( req->daddr->sa_family ) {
1727#if defined(AF_UNIX) && defined(PF_UNIX)
1728 case AF_UNIX:
1729 family = PF_UNIX;
1730 break;
1731#endif
1732
1733 case AF_INET:
1734 family = PF_INET;
1735 break;
1736
1737#if defined(AF_INET6) && defined(PF_INET6)
1738 case AF_INET6:
1739 family = PF_INET6;
1740 if ( req->dscp != 0 ) {
1741 // Set in the flowinfo in the socket address
1742 ipv6addr = * reinterpret_cast<const struct sockaddr_in6 *>
1743 (req->daddr);
1744
1745 // Note: IPv6 traffic class is offset 20 bits
1746 // and the Codepoint is the top 6 bits.
1747 ipv6addr.sin6_flowinfo = htonl (req->dscp << 22);
1748
1749 req->daddr = reinterpret_cast<struct sockaddr *>(&ipv6addr);
1750 }
1751 break;
1752#endif
1753
1754 default:
1755 MSG_IOevent_AddrType_SET (&statusind.msg, req->daddr->sa_family);
1756 GetUser()->Deliver (&statusind);
1757 return;
1758 }
1759
1760 endpoint_t fd = socket (family, SOCK_STREAM, 0);
1761
1762 if ( fd == INVALID_ENDPOINT ) {
1763 MSG_IOevent_IOerror_SET (&statusind.msg, "socket");
1764 GetUser()->Deliver (&statusind);
1765 return;
1766 }
1767
1768#ifdef IC_WIN32
1769 // Windows sockets are inherited by default
1770 if ( SetHandleInformation ((HANDLE)fd,
1771 HANDLE_FLAG_INHERIT, // mask of bits to change
1772 0) == 0 ) {
1773 MSG_IOevent_Inherit_LOG ();
1774 }
1775#elif defined (FD_CLOEXEC)
1776 (void) fcntl (fd, F_SETFD, FD_CLOEXEC);
1777#endif
1778
1779#ifdef O_NONBLOCK
1780 if ( fcntl (fd, F_SETFL, O_NONBLOCK) != 0 ) {
1781 MSG_IOevent_IOerror_SET (&statusind.msg, "fcntl");
1782 GetUser()->Deliver (&statusind);
1783 closesocket (fd);
1784 return;
1785 }
1786#elif defined (FIONBIO)
1787 char onoff = 1;
1788 if ( ioctl (fd, FIONBIO, &onoff) != 0 ) {
1789 MSG_IOevent_IOerror_SET (&statusind.msg, "ioctl");
1790 GetUser()->Deliver (&statusind);
1791 closesocket (fd);
1792 return;
1793 }
1794#else
1795# error Cannot set socket into non-blocking more
1796#endif
1797
1798#ifdef TCP_NODELAY
1799 // Always set this on by default
1800#ifdef IC_WIN32
1801 char nodelay = 1;
1802#else
1803 int nodelay = 1;
1804#endif
1805
1806 // But ignore failure
1807 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof nodelay);
1808#endif
1809
1810 // Always set keepalives (and ignore failure)
1811#ifdef IC_WIN32
1812 char keepalive = 1;
1813#else
1814 int keepalive = 1;
1815#endif
1816 setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE,
1817 (char *)&keepalive, sizeof keepalive);
1818
1819 // Set the traffic class
1820 if ( req->dscp != 0 && !setTrafficClass (fd, family, req->dscp) ) {
1821 MSG_IOevent_IOerror_SET (&statusind.msg, "traffic class");
1822 GetUser()->Deliver (&statusind);
1823 closesocket (fd);
1824 return;
1825 }
1826
1827 // Bind to the local address here, if required */
1828 if ((req->saddr) && (bind(fd, req->saddr, req->salen) == -1)) {
1829 MSG_IOevent_IOerror_SET (&statusind.msg, "bind calling address");
1830 GetUser()->Deliver (&statusind);
1831 closesocket (fd);
1832 return;
1833 }
1834
1835 if ( connect (fd, req->daddr, req->dalen) != 0 ) {
1836 isode_set_errno();
1837 if ( errno == EINPROGRESS || wouldBlock () ) {
1838 // Connect is async, need to wait
1839 _fd = fd;
1840 _state = State_connecting;
1841
1842 // Connected state indicated by socket becoming writable
1843 waitEvent (::Poll::Event_Out);
1844 } else {
1845 // Must be error in connect
1846 MSG_IOevent_IOerror_SET (&statusind.msg, "connect");
1847 GetUser()->Deliver (&statusind);
1848 closesocket (fd);
1849 }
1850
1851 } else {
1852 // Immediate connection
1853
1854 _fd = fd;
1855 _state = GetUser()->Proxy() ? State_need_proxy : State_connected;
1856
1857 MSG_IOevent_Connected_SET (&statusind.msg);
1858 GetUser()->Deliver (&statusind);
1859 }
1860}
unsigned dscp
Length of Source address.
socklen_t dalen
Destination address.
const struct sockaddr * saddr
Length of destination address.
socklen_t salen
Optional Source address.

References Stream::ConnectRequest::dalen, Stream::ConnectRequest::dscp, Stream::ConnectRequest::saddr, and Stream::ConnectRequest::salen.

◆ actualDeliver() [5/9]

void SocketPoll::actualDeliver ( Stream::ListenRequest req)

listen

Definition at line 1888 of file stream_socket_poll.C.

1889{
1890 if ( checkUser() ) return;
1891
1892 StatusIndication statusind (this);
1893
1894 LOG_DEBUG (("SocketPoll::actualDeliver (ListenRequest)"));
1895
1896 if ( _state != State_noconnect ) {
1897 MSG_IOevent_NotConnected_SET (&statusind.msg);
1898
1899 GetUser()->Deliver (&statusind);
1900
1901 return;
1902 }
1903
1904 int family;
1905
1906 switch ( req->laddr->sa_family ) {
1907#ifdef AF_UNIX
1908 case AF_UNIX:
1909 family = PF_UNIX;
1910 break;
1911#endif
1912
1913 case AF_INET:
1914 family = PF_INET;
1915 break;
1916
1917#if defined(AF_INET6) && defined(PF_INET6)
1918 case AF_INET6:
1919 family = PF_INET6;
1920 break;
1921#endif
1922
1923 default:
1924 MSG_IOevent_AddrType_SET (&statusind.msg, req->laddr->sa_family);
1925 GetUser()->Deliver (&statusind);
1926 return;
1927 }
1928
1929 endpoint_t fd = socket (family, SOCK_STREAM, 0);
1930
1931 if ( fd == INVALID_ENDPOINT ) {
1932 MSG_IOevent_IOerror_SET (&statusind.msg, "socket");
1933 GetUser()->Deliver (&statusind);
1934 return;
1935 }
1936
1937#if defined(PF_INET6) && defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6)
1938 if ( family == PF_INET6 ) {
1939 int v6only = 1;
1940
1941 if ( setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY,
1942 (char *)&v6only, sizeof v6only) != 0 ) {
1943 MSG_IOevent_IOerror_SET (&statusind.msg, "setsockopt");
1944 GetUser()->Deliver (&statusind);
1945 closesocket (fd);
1946 return;
1947 }
1948 }
1949#endif
1950
1951#if !defined(IC_WIN32) && defined(SO_REUSEADDR)
1952 int onoff = 1;
1953
1954 if ( setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
1955 (char *)&onoff, sizeof onoff) != 0 ) {
1956 MSG_IOevent_IOerror_SET (&statusind.msg, "setsockopt");
1957 GetUser()->Deliver (&statusind);
1958 closesocket (fd);
1959 return;
1960 }
1961#endif
1962
1963 if ( bind (fd, req->laddr, req->lalen ) != 0 ) {
1964 MSG_IOevent_IOerror_SET (&statusind.msg, "bind");
1965 GetUser()->Deliver (&statusind);
1966 closesocket (fd);
1967 return;
1968 }
1969
1970#ifdef IC_WIN32
1971 // Windows sockets are inherited by default
1972 if ( SetHandleInformation ((HANDLE)fd,
1973 HANDLE_FLAG_INHERIT, // mask of bits to change
1974 0) == 0 ) {
1975 MSG_IOevent_Inherit_LOG ();
1976 }
1977#elif defined (FD_CLOEXEC)
1978 (void) fcntl (fd, F_SETFD, FD_CLOEXEC);
1979#endif
1980
1981#ifdef O_NONBLOCK
1982 if ( fcntl (fd, F_SETFL, O_NONBLOCK) != 0 ) {
1983 MSG_IOevent_IOerror_SET (&statusind.msg, "fcntl");
1984 GetUser()->Deliver (&statusind);
1985 closesocket (fd);
1986 return;
1987 }
1988#elif defined (FIONBIO)
1989 char con = 1;
1990 if ( ioctl (fd, FIONBIO, &con) != 0 ) {
1991 MSG_IOevent_IOerror_SET (&statusind.msg, "ioctl");
1992 GetUser()->Deliver (&statusind);
1993 closesocket (fd);
1994 return;
1995 }
1996#else
1997# error Cannot set socket into non-blocking more
1998#endif
1999
2000 if ( listen (fd, req->backlog ? req->backlog : SOMAXCONN) != 0 ) {
2001 MSG_IOevent_IOerror_SET(&statusind.msg, "listen");
2002 GetUser()->Deliver (&statusind);
2003 closesocket (fd);
2004 return;
2005 }
2006
2007 // Listening
2008 _fd = fd;
2009 _state = State_listening;
2010
2011 // Listen events are 'In' events
2012 waitEvent (::Poll::Event_In);
2013}
socklen_t lalen
Listen address.
int backlog
Length of listen address.

References Stream::ListenRequest::backlog, and Stream::ListenRequest::lalen.

◆ actualDeliver() [6/9]

void SocketPoll::actualDeliver ( Stream::DataRequest req)

send data

Definition at line 2073 of file stream_socket_poll.C.

2074{
2075 if ( checkUser() ) return;
2076
2077 StatusIndication statusind (this);
2078
2079 LOG_DEBUG (("SocketPoll::actualDeliver (DataRequest) state=%d _wlen=%ld",
2080 _state, (long)_wlen));
2081
2082 switch ( _state ) {
2083 case State_need_proxy:
2084 case State_connected:
2085 case State_tls:
2086 if ( _fd != INVALID_ENDPOINT )
2087 break;
2088 BOOST_FALLTHROUGH;
2089
2090 default:
2091 MSG_IOevent_NotConnected_SET (&statusind.msg);
2092 GetUser()->Deliver (&statusind);
2093 return;
2094 }
2095
2096 // Note: should not attempt to write zero bytes
2097 if ( req->buf == 0 || req->len == 0 ) {
2098 MSG_IOevent_InvalidParameter_SET (&statusind.msg,
2099 req->buf == NULL ?
2100 "buffer pointer" :
2101 "zero length");
2102
2103 GetUser()->Deliver (&statusind);
2104
2105 return;
2106 }
2107
2108 if ( _wlen != 0 ) {
2109 ReleaseBuf release;
2110
2111 release.buf = req->buf;
2112 release.len = -1;
2113
2114 GetUser()->Deliver (&release);
2115
2116 MSG_IOevent_DupWrite_SET (&statusind.msg);
2117
2118 GetUser()->Deliver (&statusind);
2119
2120 return;
2121 }
2122
2123 _wbuf = _wptr = req->buf;
2124 _wlen = req->len;
2125
2126 if ( _state == State_connected || _state == State_need_proxy ) {
2127 if (_state == State_need_proxy) {
2128 LOG_DEBUG (("Need proxy state seen when writing"));
2129 }
2130 if ( !doWrite () ) {
2131 // Write blocked, tell poller we want to know when can write
2132 waitEvent (::Poll::Event_Out);
2133 }
2134
2135 } else {
2136 doTLS();
2137 }
2138}
size_t len
Pointer to data to be transferred.

References Stream::DataRequest::len, and Stream::ReleaseBuf::len.

◆ actualDeliver() [7/9]

void SocketPoll::actualDeliver ( Stream::ReadRequest req)

ReadRequest.

Definition at line 2140 of file stream_socket_poll.C.

2141{
2142 if ( checkUser() ) return;
2143
2144 DataIndication dataind;
2145 StatusIndication statusind (this);
2146
2147 LOG_DEBUG (("SocketPoll::actualDeliver (ReadRequest)"));
2148
2149 switch ( _state ) {
2150 case State_need_proxy:
2151 case State_connected:
2152 case State_tls:
2153 if ( _fd != INVALID_ENDPOINT )
2154 break;
2155 BOOST_FALLTHROUGH;
2156
2157 default:
2158 MSG_IOevent_NotConnected_SET (&statusind.msg);
2159 GetUser()->Deliver (&statusind);
2160 return;
2161 }
2162
2163 if ( req->buf == 0 || req->len == 0 ) {
2164 MSG_IOevent_InvalidParameter_SET (&statusind.msg,
2165 req->buf == NULL ?
2166 "buffer pointer" :
2167 "zero length");
2168
2169 GetUser()->Deliver (&statusind);
2170
2171 return;
2172 }
2173
2174 if ( _rlen != 0 ) {
2175 dataind.buf = req->buf;
2176 dataind.len = -1;
2177
2178 GetUser()->Deliver (&dataind);
2179
2180 MSG_IOevent_DupRead_SET (&statusind.msg);
2181
2182 GetUser()->Deliver (&statusind);
2183
2184 return;
2185 }
2186
2187 _rbuf = _rptr = req->buf;
2188 _rlen = req->len;
2189 _rfill = req->fill;
2190
2191 LOG_DEBUG (("ReadRequest: _rbuf=%p _rlen=%d _rfill=%d",
2192 _rbuf, (int)_rlen, _rfill));
2193
2194 if ( _state == State_connected || _state == State_need_proxy ) {
2195 // If the previous read filled the provided buffer, then
2196 // we attempt a read at this point. There may be more data
2197 // already buffered in the OS
2198
2199 if ( _rfull
2200 && ((_state == State_connected && doRead () )
2201 || (_state == State_need_proxy && doProxy() )) )
2202 return;
2203
2204 // tell poller we are interested in read events
2205 waitEvent (::Poll::Event_In);
2206
2207 } else {
2208 doTLS();
2209 }
2210}
bool fill
Length of data read.
size_t len
Address of data.

References Stream::ReadRequest::fill, Stream::ReadRequest::len, and Stream::DataIndication::len.

◆ actualDeliver() [8/9]

void SocketPoll::actualDeliver ( Stream::StartTLS req)

Start SSL/TLS on stream.

Definition at line 2212 of file stream_socket_poll.C.

2213{
2214 if ( checkUser() ) return;
2215
2216 LOG_DEBUG (("SocketPoll::actualDeliver (StartTLS)"));
2217
2218 StatusIndication statusind (this);
2219
2220 switch ( _state ) {
2221 case State_tls:
2222 MSG_IOevent_SSLalready_SET (&statusind.msg);
2223 GetUser()->Deliver (&statusind);
2224 return;
2225
2226 case State_connected:
2227 if ( _fd != INVALID_ENDPOINT )
2228 break;
2229 BOOST_FALLTHROUGH;
2230
2231 default:
2232 MSG_IOevent_NotConnected_SET (&statusind.msg);
2233 GetUser()->Deliver (&statusind);
2234 return;
2235 }
2236
2237 // Only check hostname of server
2238 _hostname = req->client ? req->hostname : 0;
2239
2240 SSLTLS::OpenSSLContext *sslctx =
2241 dynamic_cast<SSLTLS::OpenSSLContext *>(req->context);
2242
2243 _ssl = sslctx ? sslctx->GetSSL(_choice) : NULL;
2244 if (!_ssl) {
2245 MSG_IOevent_SSLerror_SET (&statusind.msg, "SSL_new", "this returned NULL. No ID configured?");
2246 GetUser()->Deliver (&statusind);
2247 return;
2248 }
2249
2250 // Check for any OpenSSL error set during previous use of this thread
2251 int err = SSL_get_error(_ssl, 0);
2252 if (err != SSL_ERROR_NONE) {
2253 // Report but clear and continue
2254 LOG_DEBUG (("SocketPoll::actualDeliver(StartTLS) - SSL error code %d", err));
2255 ERR_clear_error();
2256 }
2257
2258 BIO *bio = BIO_new_socket (_fd, TRUE);
2259
2260 SSL_set_bio(_ssl, bio, bio);
2261
2262 if ( req->client )
2263 SSL_set_connect_state (_ssl);
2264 else
2265 SSL_set_accept_state (_ssl);
2266
2267 _state = State_tls;
2268 _tlsstate = TLS_handshake;
2269
2270 doTLS();
2271}
const char * hostname
The context for SSL.
bool client
Hostname to check (can be NULL)

References Stream::StartTLS::client, and Stream::StartTLS::hostname.

◆ actualDeliver() [9/9]

void SocketPoll::actualDeliver ( Stream::StreamControl option)

Control stream.

Definition at line 2273 of file stream_socket_poll.C.

2274{
2275 if ( checkUser() ) return;
2276
2277 LOG_DEBUG (("SocketPoll::actualDeliver (StreamControl)"));
2278
2279 StatusIndication statusind (this);
2280
2281 if ( _fd == INVALID_ENDPOINT ) {
2282 MSG_IOevent_NotConnected_SET (&statusind.msg);
2283 GetUser()->Deliver (&statusind);
2284 return;
2285 }
2286
2287 int level;
2288 int name;
2289
2290 switch ( option->option ) {
2291#if defined(TCP_NODELAY)
2292 case StreamControlNoDelay:
2293 level = IPPROTO_TCP;
2294 name = TCP_NODELAY;
2295 break;
2296#endif
2297
2299 level = SOL_SOCKET;
2300 name = SO_KEEPALIVE;
2301 break;
2302
2303#if defined(IP_TOS)
2304 case StreamControlTOS:
2305#ifdef SOL_IP
2306 level = SOL_IP;
2307#else
2308 level = IPPROTO_IP;
2309#endif
2310 name = IP_TOS;
2311 break;
2312#endif
2313
2314 default:
2315 MSG_IOevent_UnknownStreamOpt_SET (&statusind.msg, option->option);
2316 GetUser()->Deliver (&statusind);
2317 return;
2318 }
2319
2320 int rc = setsockopt (_fd, level, name, (char *)&option->value, sizeof option->value);
2321 if ( rc != 0 ) {
2322 MSG_IOevent_IOerror_SET (&statusind.msg, "setsockopt");
2323 GetUser()->Deliver (&statusind);
2324 tidy ();
2325 }
2326}
@ StreamControlTOS
Keep alive flag.
@ StreamControlKeepAlive
No delay flag.
int value
Option whose value is to be set.

References Stream::StreamControlKeepAlive, Stream::StreamControlTOS, and Stream::StreamControl::value.

◆ Deliver() [1/12]

virtual void Stream::SocketPoll::Deliver ( time_t *  msg)
inlinevirtual

Handle timer event.

Definition at line 402 of file stream_socket_poll.C.

402 {
403 actualDeliver (msg);
404 }
void actualDeliver(time_t *msg)
Handle timer event.

References actualDeliver().

◆ Deliver() [2/12]

void Stream::SocketPoll::Deliver ( ::Poll::pollmsg msg)
inlineoverride

Deliver events to Poll provider.

Definition at line 409 of file stream_socket_poll.C.

409 {
410 actualDeliver (msg);
411 }

References actualDeliver().

◆ Deliver() [3/12]

void Stream::SocketPoll::Deliver ( External ext)
inlineoverridevirtual

Set external.

Implements Stream::Provider.

Definition at line 415 of file stream_socket_poll.C.

415 {
416 actualDeliver (ext);
417 }

References actualDeliver().

◆ Deliver() [4/12]

void Stream::SocketPoll::Deliver ( ConnectRequest req)
inlineoverridevirtual

connect

Implements Stream::Provider.

Definition at line 420 of file stream_socket_poll.C.

420 {
421 actualDeliver (req);
422 }

References actualDeliver().

◆ Deliver() [5/12]

void Stream::SocketPoll::Deliver ( ListenRequest req)
inlineoverridevirtual

listen

Implements Stream::Provider.

Definition at line 425 of file stream_socket_poll.C.

425 {
426 actualDeliver (req);
427 }

References actualDeliver().

◆ Deliver() [6/12]

void Stream::SocketPoll::Deliver ( ConnectAccept req)
inlineoverridevirtual

accept

Implements Stream::Provider.

Definition at line 430 of file stream_socket_poll.C.

430 {
431 actualDeliver (req);
432 }

References actualDeliver().

◆ Deliver() [7/12]

void Stream::SocketPoll::Deliver ( DisconnectRequest req)
inlineoverridevirtual

disconnect

Implements Stream::Provider.

Definition at line 435 of file stream_socket_poll.C.

435 {
436 actualDeliver (req);
437 }

References actualDeliver().

◆ Deliver() [8/12]

void Stream::SocketPoll::Deliver ( DataRequest req)
inlineoverridevirtual

send data

Implements Stream::Provider.

Definition at line 440 of file stream_socket_poll.C.

440 {
441 actualDeliver (req);
442 }

References actualDeliver().

◆ Deliver() [9/12]

void Stream::SocketPoll::Deliver ( ReadRequest req)
inlineoverridevirtual

Read request.

Implements Stream::Provider.

Definition at line 445 of file stream_socket_poll.C.

445 {
446 actualDeliver (req);
447 }

References actualDeliver().

◆ Deliver() [10/12]

void Stream::SocketPoll::Deliver ( StartTLS req)
inlineoverridevirtual

Start SSL/TLS on stream.

Implements Stream::Provider.

Definition at line 450 of file stream_socket_poll.C.

450 {
451 actualDeliver (req);
452 }

References actualDeliver().

◆ Deliver() [11/12]

void Stream::SocketPoll::Deliver ( StreamControl option)
inlineoverridevirtual

Control stream.

Implements Stream::Provider.

Definition at line 455 of file stream_socket_poll.C.

455 {
456 actualDeliver (option);
457 }

References actualDeliver().

◆ Deliver() [12/12]

void Stream::SocketPoll::Deliver ( LengthFnxRequest )
inlineoverridevirtual

Set length function.

Implements Stream::Provider.

Definition at line 460 of file stream_socket_poll.C.

460 {
461 // Don't bother to synchronize this
462 }

The documentation for this class was generated from the following file:

All rights reserved © 2002 - 2024 Isode Ltd.