Stream::SocketPoll Class Referenceabstract

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

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

Public Member Functions

virtual void Die ()
 Make this provider go away.
 
void tidy ()
 Tidy up - close connections etc.
 
virtual endpoint_t GetEndpoint (bool inheriting)
 Get the endpoint ID.
 
virtual unsigned Events ()
 Get the events.
 
virtual int GetLocalAddress (struct sockaddr *laddr, socklen_t *lalenp, MSGstruct *msp)
 Get the local address.
 
virtual int GetPeerAddress (struct sockaddr *laddr, socklen_t *lalenp, MSGstruct *msp)
 Get the peer address.
 
virtual TLS_CipherSuite GetCipherSuite ()
 Get the cipher suite.
 
virtual X509 * GetPeerCertificate ()
 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)
 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.
 
virtual void Deliver (::Poll::pollmsg *msg)
 Deliver events to Poll provider.
 
virtual void Deliver (External *ext)
 Set external.
 
virtual void Deliver (ConnectRequest *req)
 connect
 
virtual void Deliver (ListenRequest *req)
 listen
 
virtual void Deliver (ConnectAccept *req)
 accept
 
virtual void Deliver (DisconnectRequest *req)
 disconnect
 
virtual void Deliver (DataRequest *req)
 send data
 
virtual void Deliver (ReadRequest *req)
 Read request.
 
virtual void Deliver (StartTLS *req)
 Start SSL/TLS on stream.
 
virtual void Deliver (StreamControl *option)
 Control stream.
 
virtual void Deliver (LengthFnxRequest *)
 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.
 
virtual ~User ()
 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 40 of file stream_socket_poll.C.

Constructor & Destructor Documentation

◆ ~SocketPoll()

virtual Stream::SocketPoll::~SocketPoll ( )
inlineprotectedvirtual

Definition at line 140 of file stream_socket_poll.C.

140 {
141 tidy ();
142 }
void tidy()
Tidy up - close connections etc.

◆ SocketPoll()

Stream::SocketPoll::SocketPoll ( )
inline

Definition at line 145 of file stream_socket_poll.C.

145 :
146 _poller (0),
147 _state (State_noconnect),
148 _rlen (0),
149 _rfill (false),
150 _rfull (false),
151 _wlen (0),
152 _ssl (0),
153 _hostname (0),
154 _emfile (0),
155 _noshut (false)
156 {
157 _event.Init (this);
158 _timer.Init (this);
159 }
void Init(C *rcvr)
Set the target.
Definition Syncmsg.h:48

Member Function Documentation

◆ Die()

virtual void Stream::SocketPoll::Die ( )
inlinevirtual

Make this provider go away.

Implements Stream::Provider.

Definition at line 162 of file stream_socket_poll.C.

162 {
163 delete this;
164 }

◆ tidy()

void Stream::SocketPoll::tidy ( )
inline

Tidy up - close connections etc.

Definition at line 167 of file stream_socket_poll.C.

167 {
168 SetUser (0);
169
170 if ( _ssl != 0 ) {
171 if ( _poller != 0 ) {
172 _poller->Deregister (this);
173 _poller = 0;
174 }
175
176 // This closes the socket
177 int err = SSL_get_error(_ssl, 0);
178 if (err != SSL_ERROR_NONE) {
179 // Report but clear and continue
180 LOG_DEBUG (("SocketPoll::tidy() - SSL error (%d)", err));
181 ERR_clear_error();
182 }
183 SSL_free (_ssl);
184 _ssl = 0;
185
186 _fd = INVALID_ENDPOINT;
187 _event.Cancel ();
188
189 } else if ( _fd != INVALID_ENDPOINT ) {
190 if ( _poller != 0 ) {
191 _poller->Deregister (this);
192 _poller = 0;
193 }
194
195 // This seems to be the way to close sockets cleanly
196 // on Windows. If you use SHUT_RDWR (aka SH_BOTH) the
197 // remote end can be reset.
198 if ( !_noshut )
199 shutdown (_fd, SHUT_WR);
200
201 closesocket (_fd);
202 _fd = INVALID_ENDPOINT;
203
204 _event.Cancel ();
205 }
206
207 _rbuf = _rptr = 0;
208 _rlen = 0;
209 _rfull = false;
210
211 _state = State_noconnect;
212 }
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()

virtual endpoint_t Stream::SocketPoll::GetEndpoint ( bool  inheriting)
inlinevirtual

Get the endpoint ID.

Implements Stream::Provider.

Definition at line 216 of file stream_socket_poll.C.

216 {
217 if ( inheriting ) {
218 _noshut = true;
219
220#ifdef IC_WIN32
221 if ( SetHandleInformation ((HANDLE)_fd,
222 HANDLE_FLAG_INHERIT,
223 HANDLE_FLAG_INHERIT) == 0 ) {
224 MSG_IOevent_Inherit_LOG();
225 }
226
227#elif defined (FD_CLOEXEC)
228 int flags = fcntl (_fd, F_GETFD, 0);
229
230 if ( flags >= 0 ) {
231 flags &= ~FD_CLOEXEC;
232 if ( fcntl (_fd, F_SETFD, flags) != 0 ) {
233 MSG_IOevent_Inherit_LOG ();
234 }
235 }
236#endif
237 }
238 return _fd;
239 }

References Poll::User::_fd.

◆ Events()

virtual unsigned Stream::SocketPoll::Events ( )
inlinevirtual

Get the events.

Implements Stream::Provider.

Definition at line 242 of file stream_socket_poll.C.

242 {
243 return _uevents;
244 }
unsigned _uevents
Provider's view of events.

References Poll::User::_uevents.

◆ GetLocalAddress()

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

Get the local address.

Implements Stream::Provider.

Definition at line 247 of file stream_socket_poll.C.

249 {
250
251 if ( _fd == INVALID_ENDPOINT ) {
252 MSG_IOevent_NotConnected_SET (msp);
253 return MSG_IOevent_NotConnected;
254 }
255
256#ifdef GETSOCKNAME_NEEDS_INTP
257 int lalen;
258#else
259 socklen_t lalen;
260#endif
261 lalen = *lalenp;
262 if ( getsockname (_fd, laddr, &lalen) != 0 ) {
263 *lalenp = lalen;
264 MSG_IOevent_IOerror_SET (msp, "getsockname");
265 return MSG_IOevent_IOerror;
266 }
267
268 // In case encapsulated IPv4 address
269 *lalenp = convert2ipv4 (laddr, lalen);
270 return 0;
271 }

References Poll::User::_fd.

◆ GetPeerAddress()

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

Get the peer address.

Implements Stream::Provider.

Definition at line 274 of file stream_socket_poll.C.

276 {
277
278 if ( _fd == INVALID_ENDPOINT ) {
279 MSG_IOevent_NotConnected_SET (msp);
280 return MSG_IOevent_NotConnected;
281 }
282
283#ifdef GETPEERNAME_NEEDS_INTP
284 int lalen;
285#else
286 socklen_t lalen;
287#endif
288 lalen = *lalenp;
289 if ( getpeername (_fd, laddr, &lalen) != 0 ) {
290 *lalenp = lalen;
291 MSG_IOevent_IOerror_SET (msp, "getpeername");
292 return MSG_IOevent_IOerror;
293 }
294
295 // In case encapsulated IPv4 address
296 *lalenp = convert2ipv4 (laddr, lalen);
297 return 0;
298 }

References Poll::User::_fd.

◆ GetCipherSuite()

virtual TLS_CipherSuite Stream::SocketPoll::GetCipherSuite ( )
inlinevirtual

Get the cipher suite.

Reimplemented from Stream::Provider.

Definition at line 301 of file stream_socket_poll.C.

301 {
302 if ( _state != State_tls || _ssl == 0 )
303 return TLS_NULL_WITH_NULL_NULL;
304
305 const SSL_CIPHER *cipher = SSL_get_current_cipher(_ssl);
306 return SSLTLS::cipher_id(cipher);
307 }

◆ GetPeerCertificate()

virtual X509 * Stream::SocketPoll::GetPeerCertificate ( )
inlinevirtual

Get the peer certificate.

Reimplemented from Stream::Provider.

Definition at line 310 of file stream_socket_poll.C.

310 {
311 if ( _state != State_tls || _ssl == 0 )
312 return 0;
313
314 return SSL_get_peer_certificate(_ssl);
315 }

◆ actualDeliver() [1/9]

void SocketPoll::actualDeliver ( time_t *  msg)

Handle timer event.

Definition at line 1219 of file stream_socket_poll.C.

1220{
1221 // Timer has expired after EMFILE, try again
1222 waitEvent (::Poll::Event_In);
1223}

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

◆ actualDeliver() [2/9]

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

Actual Deliver events to Poll provider.

Definition at line 1225 of file stream_socket_poll.C.

1226{
1227 if ( checkUser() ) return;
1228
1229 StatusIndication statusind (this);
1230
1231 LOG_DEBUG (("SocketPoll::actualDeliver (pollmsg = %x) state=%d",
1232 msg->events, _state));
1233
1234 // Poller is no longer listening for any events
1235 _pevents = 0;
1236
1237 if ( (msg->events & ::Poll::Event_Terminate) ) {
1238 // System terminating
1239 _uevents = 0;
1240
1241 // Close first, otherwise calls back to poller
1242 closesocket (_fd);
1243 _fd = INVALID_ENDPOINT;
1244 _poller = 0;
1245
1246 // Tell User
1247 MSG_IOevent_Terminating_SET (&statusind.msg);
1248 GetUser()->Deliver (&statusind);
1249
1250 return;
1251 }
1252
1253 if ( msg->events &
1254 (::Poll::Event_Err | ::Poll::Event_Hup | ::Poll::Event_Nval) ) {
1255
1256 // Don't want any events
1257 _uevents = 0;
1258
1259 // Get error from socket
1260 int eno;
1261#ifdef GETSOCKOPT_NEEDS_INTP
1262 int olen;
1263#else
1264 socklen_t olen;
1265#endif
1266 olen = sizeof eno;
1267
1268 /* Casting to (char *) is required for Windows */
1269 int rc = getsockopt (_fd, SOL_SOCKET, SO_ERROR, (char *)&eno, &olen);
1270
1271 const char *argv[1];
1272 argv[0] = "poll";
1273
1274 MSGsetv (&statusind.msg, MSG_IOevent_IOerror, 1, argv);
1275
1276 if ( rc == 0 ) {
1277 MSGstruct sockerr;
1278 MSGsetv (&sockerr,
1279 MSGID_BUILD(MSGLEVEL_ERROR, MSGID_SYSFAC, eno),
1280 0, 0);
1281 MSGappend (&statusind.msg, &sockerr);
1282 } else {
1283 MSGappendsyserror (&statusind.msg);
1284 }
1285
1286 GetUser()->Deliver (&statusind);
1287
1288 tidy ();
1289
1290 return;
1291 }
1292
1293 // Cancel desired events
1294 _uevents &= ~msg->events;
1295
1296 if ( msg->events & ::Poll::Event_In ) {
1297
1298 switch ( _state ) {
1299 case State_tls:
1300 doTLS();
1301 break;
1302
1303 case State_connected:
1304 LOG_DEBUG (("Read stuff: _rlen = %d", (int)_rlen));
1305 if ( _rlen != 0 ) {
1306 // Stuff to read. If does not complete, then wait again
1307 if ( !doRead () )
1308 waitEvent (::Poll::Event_In);
1309 }
1310 break;
1311
1312 case State_listening:
1313 doAccept ();
1314 break;
1315
1316 default:
1317 break;
1318 }
1319 }
1320
1321 if ( msg->events & ::Poll::Event_Out ) {
1322
1323 switch ( _state ) {
1324 case State_tls:
1325 doTLS();
1326 break;
1327
1328 case State_connected:
1329 if ( _wlen != 0 ) {
1330 // Stuff to write. If does not complete, then wait again
1331 if ( !doWrite () )
1332 waitEvent (::Poll::Event_Out);
1333 }
1334 break;
1335
1336 case State_connecting:
1337 _state = State_connected;
1338 MSG_IOevent_Connected_SET (&statusind.msg);
1339 GetUser()->Deliver (&statusind);
1340 break;
1341
1342 default:
1343 break;
1344 }
1345 }
1346
1347 if ( (_uevents & ~_pevents) && _poller )
1348 _poller->Control (this);
1349}
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 void Deliver(ConnectIndication *data)=0
Connection indication.

◆ actualDeliver() [3/9]

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

Set external.

Definition at line 1351 of file stream_socket_poll.C.

1352{
1353 if ( checkUser() ) return;
1354
1355 StatusIndication statusind (this);
1356
1357 LOG_DEBUG (("SocketPoll::actualDeliver (External)"));
1358
1359 if ( _state != State_noconnect ) {
1360 MSG_IOevent_NotConnected_SET (&statusind.msg);
1361 GetUser()->Deliver (&statusind);
1362 return;
1363 }
1364
1365 _fd = ext->fd;
1366
1367 if ( ext->listen ) {
1368 _state = State_listening;
1369
1370 waitEvent (::Poll::Event_In);
1371
1372 } else {
1373 _state = State_connected;
1374 }
1375}
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 1377 of file stream_socket_poll.C.

1378{
1379 if ( checkUser() ) return;
1380
1381 StatusIndication statusind (this);
1382
1383 LOG_DEBUG (("SocketPoll::actualDeliver (ConnectRequest)"));
1384
1385 if ( _state != State_noconnect ) {
1386 MSG_IOevent_NotConnected_SET (&statusind.msg);
1387 GetUser()->Deliver (&statusind);
1388 return;
1389 }
1390
1391 int family;
1392#if defined(AF_INET6) && defined(PF_INET6)
1393 struct sockaddr_in6 ipv6addr;
1394#endif
1395
1396 switch ( req->daddr->sa_family ) {
1397#if defined(AF_UNIX) && defined(PF_UNIX)
1398 case AF_UNIX:
1399 family = PF_UNIX;
1400 break;
1401#endif
1402
1403 case AF_INET:
1404 family = PF_INET;
1405 break;
1406
1407#if defined(AF_INET6) && defined(PF_INET6)
1408 case AF_INET6:
1409 family = PF_INET6;
1410 if ( req->dscp != 0 ) {
1411 // Set in the flowinfo in the socket address
1412 ipv6addr = * reinterpret_cast<const struct sockaddr_in6 *>
1413 (req->daddr);
1414
1415 // Note: IPv6 traffic class is offset 20 bits
1416 // and the Codepoint is the top 6 bits.
1417 ipv6addr.sin6_flowinfo = htonl (req->dscp << 22);
1418
1419 req->daddr = reinterpret_cast<struct sockaddr *>(&ipv6addr);
1420 }
1421 break;
1422#endif
1423
1424 default:
1425 MSG_IOevent_AddrType_SET (&statusind.msg, req->daddr->sa_family);
1426 GetUser()->Deliver (&statusind);
1427 return;
1428 }
1429
1430 endpoint_t fd = socket (family, SOCK_STREAM, 0);
1431
1432 if ( fd == INVALID_ENDPOINT ) {
1433 MSG_IOevent_IOerror_SET (&statusind.msg, "socket");
1434 GetUser()->Deliver (&statusind);
1435 return;
1436 }
1437
1438#ifdef IC_WIN32
1439 // Windows sockets are inherited by default
1440 if ( SetHandleInformation ((HANDLE)fd,
1441 HANDLE_FLAG_INHERIT, // mask of bits to change
1442 0) == 0 ) {
1443 MSG_IOevent_Inherit_LOG ();
1444 }
1445#elif defined (FD_CLOEXEC)
1446 (void) fcntl (fd, F_SETFD, FD_CLOEXEC);
1447#endif
1448
1449#ifdef O_NONBLOCK
1450 if ( fcntl (fd, F_SETFL, O_NONBLOCK) != 0 ) {
1451 MSG_IOevent_IOerror_SET (&statusind.msg, "fcntl");
1452 GetUser()->Deliver (&statusind);
1453 closesocket (fd);
1454 return;
1455 }
1456#elif defined (FIONBIO)
1457 char onoff = 1;
1458 if ( ioctl (fd, FIONBIO, &onoff) != 0 ) {
1459 MSG_IOevent_IOerror_SET (&statusind.msg, "ioctl");
1460 GetUser()->Deliver (&statusind);
1461 closesocket (fd);
1462 return;
1463 }
1464#else
1465# error Cannot set socket into non-blocking more
1466#endif
1467
1468#ifdef TCP_NODELAY
1469 // Always set this on by default
1470#ifdef IC_WIN32
1471 char nodelay = 1;
1472#else
1473 int nodelay = 1;
1474#endif
1475
1476 // But ignore failure
1477 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof nodelay);
1478#endif
1479
1480 // Always set keepalives (and ignore failure)
1481#ifdef IC_WIN32
1482 char keepalive = 1;
1483#else
1484 int keepalive = 1;
1485#endif
1486 setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE,
1487 (char *)&keepalive, sizeof keepalive);
1488
1489
1490 // Set the traffic class
1491 if ( req->dscp != 0 && !setTrafficClass (fd, family, req->dscp) ) {
1492 MSG_IOevent_IOerror_SET (&statusind.msg, "traffic class");
1493 GetUser()->Deliver (&statusind);
1494 closesocket (fd);
1495 return;
1496 }
1497
1498 // Bind to the local address here, if required */
1499 if ((req->saddr) && (bind(fd, req->saddr, req->salen) == -1)) {
1500 MSG_IOevent_IOerror_SET (&statusind.msg, "bind calling address");
1501 GetUser()->Deliver (&statusind);
1502 closesocket (fd);
1503 return;
1504 }
1505
1506 if ( connect (fd, req->daddr, req->dalen) != 0 ) {
1507 isode_set_errno();
1508 if ( errno == EINPROGRESS || wouldBlock () ) {
1509 // Connect is async, need to wait
1510 _fd = fd;
1511 _state = State_connecting;
1512
1513 // Connected state indicated by socket becoming writable
1514 waitEvent (::Poll::Event_Out);
1515 } else {
1516 // Must be error in connect
1517 MSG_IOevent_IOerror_SET (&statusind.msg, "connect");
1518 GetUser()->Deliver (&statusind);
1519 closesocket (fd);
1520 }
1521
1522 } else {
1523 // Immediate connection
1524
1525 _fd = fd;
1526 _state = State_connected;
1527
1528 MSG_IOevent_Connected_SET (&statusind.msg);
1529 GetUser()->Deliver (&statusind);
1530 }
1531}
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 1559 of file stream_socket_poll.C.

1560{
1561 if ( checkUser() ) return;
1562
1563 StatusIndication statusind (this);
1564
1565 LOG_DEBUG (("SocketPoll::actualDeliver (ListenRequest)"));
1566
1567 if ( _state != State_noconnect ) {
1568 MSG_IOevent_NotConnected_SET (&statusind.msg);
1569
1570 GetUser()->Deliver (&statusind);
1571
1572 return;
1573 }
1574
1575 int family;
1576
1577 switch ( req->laddr->sa_family ) {
1578#ifdef AF_UNIX
1579 case AF_UNIX:
1580 family = PF_UNIX;
1581 break;
1582#endif
1583
1584 case AF_INET:
1585 family = PF_INET;
1586 break;
1587
1588#if defined(AF_INET6) && defined(PF_INET6)
1589 case AF_INET6:
1590 family = PF_INET6;
1591 break;
1592#endif
1593
1594 default:
1595 MSG_IOevent_AddrType_SET (&statusind.msg, req->laddr->sa_family);
1596 GetUser()->Deliver (&statusind);
1597 return;
1598 }
1599
1600 endpoint_t fd = socket (family, SOCK_STREAM, 0);
1601
1602 if ( fd == INVALID_ENDPOINT ) {
1603 MSG_IOevent_IOerror_SET (&statusind.msg, "socket");
1604 GetUser()->Deliver (&statusind);
1605 return;
1606 }
1607
1608#if defined(PF_INET6) && defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6)
1609 if ( family == PF_INET6 ) {
1610 int v6only = 1;
1611
1612 if ( setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY,
1613 (char *)&v6only, sizeof v6only) != 0 ) {
1614 MSG_IOevent_IOerror_SET (&statusind.msg, "setsockopt");
1615 GetUser()->Deliver (&statusind);
1616 closesocket (fd);
1617 return;
1618 }
1619 }
1620#endif
1621
1622#if !defined(IC_WIN32) && defined(SO_REUSEADDR)
1623 int onoff = 1;
1624
1625 if ( setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
1626 (char *)&onoff, sizeof onoff) != 0 ) {
1627 MSG_IOevent_IOerror_SET (&statusind.msg, "setsockopt");
1628 GetUser()->Deliver (&statusind);
1629 closesocket (fd);
1630 return;
1631 }
1632#endif
1633
1634 if ( bind (fd, req->laddr, req->lalen ) != 0 ) {
1635 MSG_IOevent_IOerror_SET (&statusind.msg, "bind");
1636 GetUser()->Deliver (&statusind);
1637 closesocket (fd);
1638 return;
1639 }
1640
1641#ifdef IC_WIN32
1642 // Windows sockets are inherited by default
1643 if ( SetHandleInformation ((HANDLE)fd,
1644 HANDLE_FLAG_INHERIT, // mask of bits to change
1645 0) == 0 ) {
1646 MSG_IOevent_Inherit_LOG ();
1647 }
1648#elif defined (FD_CLOEXEC)
1649 (void) fcntl (fd, F_SETFD, FD_CLOEXEC);
1650#endif
1651
1652#ifdef O_NONBLOCK
1653 if ( fcntl (fd, F_SETFL, O_NONBLOCK) != 0 ) {
1654 MSG_IOevent_IOerror_SET (&statusind.msg, "fcntl");
1655 GetUser()->Deliver (&statusind);
1656 closesocket (fd);
1657 return;
1658 }
1659#elif defined (FIONBIO)
1660 char con = 1;
1661 if ( ioctl (fd, FIONBIO, &con) != 0 ) {
1662 MSG_IOevent_IOerror_SET (&statusind.msg, "ioctl");
1663 GetUser()->Deliver (&statusind);
1664 closesocket (fd);
1665 return;
1666 }
1667#else
1668# error Cannot set socket into non-blocking more
1669#endif
1670
1671 if ( listen (fd, req->backlog ? req->backlog : SOMAXCONN) != 0 ) {
1672 MSG_IOevent_IOerror_SET(&statusind.msg, "listen");
1673 GetUser()->Deliver (&statusind);
1674 closesocket (fd);
1675 return;
1676 }
1677
1678 // Listening
1679 _fd = fd;
1680 _state = State_listening;
1681
1682 // Listen events are 'In' events
1683 waitEvent (::Poll::Event_In);
1684}
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 1743 of file stream_socket_poll.C.

1744{
1745 if ( checkUser() ) return;
1746
1747 StatusIndication statusind (this);
1748
1749 LOG_DEBUG (("SocketPoll::actualDeliver (DataRequest) state=%d _wlen=%ld",
1750 _state, (long)_wlen));
1751
1752 switch ( _state ) {
1753 case State_connected:
1754 case State_tls:
1755 if ( _fd != INVALID_ENDPOINT )
1756 break;
1757 BOOST_FALLTHROUGH;
1758
1759 default:
1760 MSG_IOevent_NotConnected_SET (&statusind.msg);
1761 GetUser()->Deliver (&statusind);
1762 return;
1763 }
1764
1765 // Note: should not attempt to write zero bytes
1766 if ( req->buf == 0 || req->len == 0 ) {
1767 MSG_IOevent_InvalidParameter_SET (&statusind.msg,
1768 req->buf == NULL ?
1769 "buffer pointer" :
1770 "zero length");
1771
1772 GetUser()->Deliver (&statusind);
1773
1774 return;
1775 }
1776
1777 if ( _wlen != 0 ) {
1778 ReleaseBuf release;
1779
1780 release.buf = req->buf;
1781 release.len = -1;
1782
1783 GetUser()->Deliver (&release);
1784
1785 MSG_IOevent_DupWrite_SET (&statusind.msg);
1786
1787 GetUser()->Deliver (&statusind);
1788
1789 return;
1790 }
1791
1792 _wbuf = _wptr = req->buf;
1793 _wlen = req->len;
1794
1795 if ( _state == State_connected ) {
1796 if ( !doWrite () ) {
1797 // Write blocked, tell poller we want to know when can write
1798 waitEvent (::Poll::Event_Out);
1799 }
1800
1801 } else {
1802 doTLS();
1803 }
1804}
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 1806 of file stream_socket_poll.C.

1807{
1808 if ( checkUser() ) return;
1809
1810 DataIndication dataind;
1811 StatusIndication statusind (this);
1812
1813 LOG_DEBUG (("SocketPoll::actualDeliver (ReadRequest)"));
1814
1815 switch ( _state ) {
1816 case State_connected:
1817 case State_tls:
1818 if ( _fd != INVALID_ENDPOINT )
1819 break;
1820 BOOST_FALLTHROUGH;
1821
1822 default:
1823 MSG_IOevent_NotConnected_SET (&statusind.msg);
1824 GetUser()->Deliver (&statusind);
1825 return;
1826 }
1827
1828 if ( req->buf == 0 || req->len == 0 ) {
1829 MSG_IOevent_InvalidParameter_SET (&statusind.msg,
1830 req->buf == NULL ?
1831 "buffer pointer" :
1832 "zero length");
1833
1834 GetUser()->Deliver (&statusind);
1835
1836 return;
1837 }
1838
1839 if ( _rlen != 0 ) {
1840 dataind.buf = req->buf;
1841 dataind.len = -1;
1842
1843 GetUser()->Deliver (&dataind);
1844
1845 MSG_IOevent_DupRead_SET (&statusind.msg);
1846
1847 GetUser()->Deliver (&statusind);
1848
1849 return;
1850 }
1851
1852 _rbuf = _rptr = req->buf;
1853 _rlen = req->len;
1854 _rfill = req->fill;
1855
1856 LOG_DEBUG (("ReadRequest: _rbuf=%p _rlen=%d _rfill=%d",
1857 _rbuf, (int)_rlen, _rfill));
1858
1859 if ( _state == State_connected ) {
1860 // If the previous read filled the provided buffer, then
1861 // we attempt a read at this point. There may be more data
1862 // already buffered in the OS
1863
1864 if ( _rfull && doRead () )
1865 return;
1866
1867 // tell poller we are interested in read events
1868 waitEvent (::Poll::Event_In);
1869
1870 } else {
1871 doTLS();
1872 }
1873}
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 1875 of file stream_socket_poll.C.

1876{
1877 if ( checkUser() ) return;
1878
1879 LOG_DEBUG (("SocketPoll::actualDeliver (StartTLS)"));
1880
1881 StatusIndication statusind (this);
1882
1883 switch ( _state ) {
1884 case State_tls:
1885 MSG_IOevent_SSLalready_SET (&statusind.msg);
1886 GetUser()->Deliver (&statusind);
1887 return;
1888
1889 case State_connected:
1890 if ( _fd != INVALID_ENDPOINT )
1891 break;
1892 BOOST_FALLTHROUGH;
1893
1894 default:
1895 MSG_IOevent_NotConnected_SET (&statusind.msg);
1896 GetUser()->Deliver (&statusind);
1897 return;
1898 }
1899
1900 // Only check hostname of server
1901 _hostname = req->client ? req->hostname : 0;
1902
1903 SSLTLS::OpenSSLContext *sslctx =
1904 dynamic_cast<SSLTLS::OpenSSLContext *>(req->context);
1905
1906 _ssl = sslctx ? sslctx->GetSSL(_choice) : NULL;
1907 if (!_ssl) {
1908 MSG_IOevent_SSLerror_SET (&statusind.msg, "SSL_new", "this returned NULL. No ID configured?");
1909 GetUser()->Deliver (&statusind);
1910 return;
1911 }
1912
1913 // Check for any OpenSSL error set during previous use of this thread
1914 int err = SSL_get_error(_ssl, 0);
1915 if (err != SSL_ERROR_NONE) {
1916 // Report but clear and continue
1917 LOG_DEBUG (("SocketPoll::actualDeliver(StartTLS) - SSL error code %d", err));
1918 ERR_clear_error();
1919 }
1920
1921 BIO *bio = BIO_new_socket (_fd, TRUE);
1922
1923 SSL_set_bio(_ssl, bio, bio);
1924
1925 if ( req->client )
1926 SSL_set_connect_state (_ssl);
1927 else
1928 SSL_set_accept_state (_ssl);
1929
1930 _state = State_tls;
1931 _tlsstate = TLS_handshake;
1932
1933 doTLS();
1934}
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 1936 of file stream_socket_poll.C.

1937{
1938 if ( checkUser() ) return;
1939
1940 LOG_DEBUG (("SocketPoll::actualDeliver (StreamControl)"));
1941
1942 StatusIndication statusind (this);
1943
1944 if ( _fd == INVALID_ENDPOINT ) {
1945 MSG_IOevent_NotConnected_SET (&statusind.msg);
1946 GetUser()->Deliver (&statusind);
1947 return;
1948 }
1949
1950 int level;
1951 int name;
1952
1953 switch ( option->option ) {
1954#if defined(TCP_NODELAY)
1955 case StreamControlNoDelay:
1956 level = IPPROTO_TCP;
1957 name = TCP_NODELAY;
1958 break;
1959#endif
1960
1962 level = SOL_SOCKET;
1963 name = SO_KEEPALIVE;
1964 break;
1965
1966#if defined(IP_TOS)
1967 case StreamControlTOS:
1968#ifdef SOL_IP
1969 level = SOL_IP;
1970#else
1971 level = IPPROTO_IP;
1972#endif
1973 name = IP_TOS;
1974 break;
1975#endif
1976
1977 default:
1978 MSG_IOevent_UnknownStreamOpt_SET (&statusind.msg, option->option);
1979 GetUser()->Deliver (&statusind);
1980 return;
1981 }
1982
1983 int rc = setsockopt (_fd, level, name, (char *)&option->value, sizeof option->value);
1984 if ( rc != 0 ) {
1985 MSG_IOevent_IOerror_SET (&statusind.msg, "setsockopt");
1986 GetUser()->Deliver (&statusind);
1987 tidy ();
1988 }
1989}
@ 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 359 of file stream_socket_poll.C.

359 {
360 actualDeliver (msg);
361 }
void actualDeliver(time_t *msg)
Handle timer event.

References actualDeliver().

◆ Deliver() [2/12]

virtual void Stream::SocketPoll::Deliver ( ::Poll::pollmsg msg)
inlinevirtual

Deliver events to Poll provider.

Definition at line 366 of file stream_socket_poll.C.

366 {
367 actualDeliver (msg);
368 }

References actualDeliver().

◆ Deliver() [3/12]

virtual void Stream::SocketPoll::Deliver ( External ext)
inlinevirtual

Set external.

Implements Stream::Provider.

Definition at line 372 of file stream_socket_poll.C.

372 {
373 actualDeliver (ext);
374 }

References actualDeliver().

◆ Deliver() [4/12]

virtual void Stream::SocketPoll::Deliver ( ConnectRequest req)
inlinevirtual

connect

Implements Stream::Provider.

Definition at line 377 of file stream_socket_poll.C.

377 {
378 actualDeliver (req);
379 }

References actualDeliver().

◆ Deliver() [5/12]

virtual void Stream::SocketPoll::Deliver ( ListenRequest req)
inlinevirtual

listen

Implements Stream::Provider.

Definition at line 382 of file stream_socket_poll.C.

382 {
383 actualDeliver (req);
384 }

References actualDeliver().

◆ Deliver() [6/12]

virtual void Stream::SocketPoll::Deliver ( ConnectAccept req)
inlinevirtual

accept

Implements Stream::Provider.

Definition at line 387 of file stream_socket_poll.C.

387 {
388 actualDeliver (req);
389 }

References actualDeliver().

◆ Deliver() [7/12]

virtual void Stream::SocketPoll::Deliver ( DisconnectRequest req)
inlinevirtual

disconnect

Implements Stream::Provider.

Definition at line 392 of file stream_socket_poll.C.

392 {
393 actualDeliver (req);
394 }

References actualDeliver().

◆ Deliver() [8/12]

virtual void Stream::SocketPoll::Deliver ( DataRequest req)
inlinevirtual

send data

Implements Stream::Provider.

Definition at line 397 of file stream_socket_poll.C.

397 {
398 actualDeliver (req);
399 }

References actualDeliver().

◆ Deliver() [9/12]

virtual void Stream::SocketPoll::Deliver ( ReadRequest req)
inlinevirtual

Read request.

Implements Stream::Provider.

Definition at line 402 of file stream_socket_poll.C.

402 {
403 actualDeliver (req);
404 }

References actualDeliver().

◆ Deliver() [10/12]

virtual void Stream::SocketPoll::Deliver ( StartTLS req)
inlinevirtual

Start SSL/TLS on stream.

Implements Stream::Provider.

Definition at line 407 of file stream_socket_poll.C.

407 {
408 actualDeliver (req);
409 }

References actualDeliver().

◆ Deliver() [11/12]

virtual void Stream::SocketPoll::Deliver ( StreamControl option)
inlinevirtual

Control stream.

Implements Stream::Provider.

Definition at line 412 of file stream_socket_poll.C.

412 {
413 actualDeliver (option);
414 }

References actualDeliver().

◆ Deliver() [12/12]

virtual void Stream::SocketPoll::Deliver ( LengthFnxRequest )
inlinevirtual

Set length function.

Implements Stream::Provider.

Definition at line 417 of file stream_socket_poll.C.

417 {
418 // Don't bother to synchronize this
419 }

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

All rights reserved © 2002 - 2024 Isode Ltd.