Line data Source code
1 :
2 : /* Copyright (c) 2005-2014, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2010, Daniel Nachbaur <danielnachbaur@gmail.com>
4 : *
5 : * This file is part of Collage <https://github.com/Eyescale/Collage>
6 : *
7 : * This library is free software; you can redistribute it and/or modify it under
8 : * the terms of the GNU Lesser General Public License version 2.1 as published
9 : * by the Free Software Foundation.
10 : *
11 : * This library is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 : * details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public License
17 : * along with this library; if not, write to the Free Software Foundation, Inc.,
18 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : */
20 :
21 : #include "socketConnection.h"
22 :
23 : #include "connectionDescription.h"
24 : #include "exception.h"
25 : #include "global.h"
26 :
27 : #include <lunchbox/os.h>
28 : #include <lunchbox/log.h>
29 : #include <lunchbox/sleep.h>
30 : #include <co/exception.h>
31 :
32 : #include <limits>
33 : #include <sstream>
34 : #include <string.h>
35 : #include <sys/types.h>
36 :
37 : #ifdef _WIN32
38 : # include <mswsock.h>
39 : # include <winsock2.h>
40 : # include <ws2tcpip.h>
41 : # define CO_RECV_TIMEOUT 250 /*ms*/
42 : #else
43 : # include <arpa/inet.h>
44 : # include <netdb.h>
45 : # include <netinet/tcp.h>
46 : # include <sys/errno.h>
47 : # include <sys/socket.h>
48 : #endif
49 :
50 : namespace co
51 : {
52 145 : SocketConnection::SocketConnection()
53 : #ifdef _WIN32
54 : : _overlappedAcceptData( 0 )
55 : , _overlappedSocket( INVALID_SOCKET )
56 : , _overlappedDone( 0 )
57 : #endif
58 : {
59 : #ifdef _WIN32
60 : memset( &_overlappedRead, 0, sizeof( _overlappedRead ));
61 : memset( &_overlappedWrite, 0, sizeof( _overlappedWrite ));
62 : #endif
63 :
64 290 : ConnectionDescriptionPtr description = _getDescription();
65 145 : description->type = CONNECTIONTYPE_TCPIP;
66 145 : description->bandwidth = 102400; // 100MB/s
67 :
68 145 : LBVERB << "New SocketConnection @" << (void*)this << std::endl;
69 145 : }
70 :
71 435 : SocketConnection::~SocketConnection()
72 : {
73 145 : _close();
74 290 : }
75 :
76 : namespace
77 : {
78 51 : std::string getHostName( const sockaddr_in& address )
79 : {
80 : char hostname[NI_MAXHOST];
81 51 : if( getnameinfo( (sockaddr*)&address.sin_addr, sizeof(sockaddr_in),
82 : hostname, sizeof(hostname), 0, 0, 0 ) == 0 )
83 : {
84 0 : return std::string( hostname );
85 : }
86 51 : if( address.sin_addr.s_addr == htonl( INADDR_ANY ))
87 29 : return "*";
88 22 : return std::string();
89 : }
90 :
91 98 : bool _parseAddress( ConstConnectionDescriptionPtr description,
92 : sockaddr_in& address )
93 : {
94 98 : address.sin_family = AF_INET;
95 98 : address.sin_addr.s_addr = htonl( INADDR_ANY );
96 98 : address.sin_port = htons( description->port );
97 98 : memset( &(address.sin_zero), 0, 8 ); // zero the rest
98 :
99 98 : const std::string& hostname = description->getHostname();
100 98 : if( !hostname.empty( ))
101 : {
102 : addrinfo hints;
103 69 : memset( &hints, 0, sizeof(hints));
104 69 : hints.ai_flags = 0;
105 69 : hints.ai_family = AF_INET;
106 69 : hints.ai_socktype = SOCK_STREAM;
107 69 : addrinfo* info = 0;
108 :
109 69 : if( getaddrinfo( hostname.c_str(), NULL, &hints, &info ) == 0 )
110 : {
111 69 : address.sin_addr.s_addr = ((sockaddr_in *)(info->ai_addr))->sin_addr.s_addr;
112 69 : freeaddrinfo( info );
113 : }
114 : else
115 : {
116 0 : LBWARN << "Can't resolve host " << hostname << std::endl;
117 0 : return false;
118 : }
119 : }
120 :
121 196 : LBVERB << "Address " << getHostName( address ) << ":"
122 294 : << ntohs( address.sin_port ) << std::endl;
123 98 : return true;
124 : }
125 : }
126 :
127 : //----------------------------------------------------------------------
128 : // connect
129 : //----------------------------------------------------------------------
130 47 : bool SocketConnection::connect()
131 : {
132 94 : ConnectionDescriptionPtr description = _getDescription();
133 47 : LBASSERT( description->type == CONNECTIONTYPE_TCPIP );
134 47 : if( !isClosed( ))
135 0 : return false;
136 :
137 47 : if( description->port == 0 )
138 0 : return false;
139 :
140 47 : if( description->getHostname().empty( ))
141 25 : description->setHostname( "127.0.0.1" );
142 :
143 : sockaddr_in address;
144 47 : if( !_parseAddress( description, address ))
145 : {
146 0 : LBWARN << "Can't parse connection parameters" << std::endl;
147 0 : return false;
148 : }
149 :
150 47 : _setState( STATE_CONNECTING );
151 :
152 47 : if( !_createSocket( ))
153 0 : return false;
154 :
155 47 : if( address.sin_addr.s_addr == 0 )
156 : {
157 0 : LBWARN << "Refuse to connect to 0.0.0.0" << std::endl;
158 0 : close();
159 0 : return false;
160 : }
161 :
162 : #ifdef _WIN32
163 : const bool connected = WSAConnect( _readFD, (sockaddr*)&address,
164 : sizeof( address ), 0, 0, 0, 0 ) == 0;
165 : #else
166 47 : int nTries = 10;
167 47 : while( nTries-- )
168 : {
169 47 : const bool connected = (::connect( _readFD, (sockaddr*)&address,
170 47 : sizeof( address )) == 0);
171 47 : if( connected )
172 47 : break;
173 :
174 0 : switch( errno )
175 : {
176 : case EINTR: // Happens sometimes, but looks harmless
177 0 : LBDEBUG << "connect: " << lunchbox::sysError << ", retrying"
178 0 : << std::endl;
179 0 : lunchbox::sleep( 5 /*ms*/ );
180 0 : break;
181 :
182 : default:
183 0 : nTries = 0;
184 0 : break;
185 : }
186 : }
187 47 : const bool connected = nTries > 0;
188 : #endif
189 :
190 47 : if( !connected )
191 : {
192 0 : LBDEBUG << "Could not connect to '" << description->getHostname() << ":"
193 0 : << description->port << "': " << lunchbox::sysError << std::endl;
194 0 : close();
195 0 : return false;
196 : }
197 :
198 47 : _initAIORead();
199 47 : _setState( STATE_CONNECTED );
200 47 : LBDEBUG << "Connected " << description->toString() << std::endl;
201 47 : return true;
202 : }
203 :
204 289 : void SocketConnection::_close()
205 : {
206 289 : if( isClosed( ))
207 144 : return;
208 :
209 145 : if( isListening( ))
210 51 : _exitAIOAccept();
211 94 : else if( isConnected( ))
212 94 : _exitAIORead();
213 :
214 145 : LBASSERT( _readFD > 0 );
215 :
216 : #ifdef _WIN32
217 : const bool closed = ( ::closesocket(_readFD) == 0 );
218 : #else
219 145 : const bool closed = ( ::close(_readFD) == 0 );
220 : #endif
221 :
222 145 : if( !closed )
223 0 : LBWARN << "Could not close socket: " << lunchbox::sysError
224 0 : << std::endl;
225 :
226 145 : _readFD = INVALID_SOCKET;
227 145 : _writeFD = INVALID_SOCKET;
228 145 : _setState( STATE_CLOSED );
229 : }
230 :
231 : //----------------------------------------------------------------------
232 : // Async IO handles
233 : //----------------------------------------------------------------------
234 : #ifdef _WIN32
235 : void SocketConnection::_initAIORead()
236 : {
237 : _overlappedRead.hEvent = CreateEvent( 0, FALSE, FALSE, 0 );
238 : LBASSERT( _overlappedRead.hEvent );
239 :
240 : _overlappedWrite.hEvent = CreateEvent( 0, FALSE, FALSE, 0 );
241 : LBASSERT( _overlappedWrite.hEvent );
242 : if( !_overlappedRead.hEvent )
243 : LBERROR << "Can't create event for AIO notification: "
244 : << lunchbox::sysError << std::endl;
245 : }
246 :
247 : void SocketConnection::_initAIOAccept()
248 : {
249 : _initAIORead();
250 : _overlappedAcceptData = malloc( 2*( sizeof( sockaddr_in ) + 16 ));
251 : }
252 :
253 : void SocketConnection::_exitAIOAccept()
254 : {
255 : if( _overlappedAcceptData )
256 : {
257 : free( _overlappedAcceptData );
258 : _overlappedAcceptData = 0;
259 : }
260 :
261 : _exitAIORead();
262 : }
263 : void SocketConnection::_exitAIORead()
264 : {
265 : if( _overlappedRead.hEvent )
266 : {
267 : CloseHandle( _overlappedRead.hEvent );
268 : _overlappedRead.hEvent = 0;
269 : }
270 :
271 : if( _overlappedWrite.hEvent )
272 : {
273 : CloseHandle( _overlappedWrite.hEvent );
274 : _overlappedWrite.hEvent = 0;
275 : }
276 : }
277 : #else
278 51 : void SocketConnection::_initAIOAccept(){ /* NOP */ }
279 51 : void SocketConnection::_exitAIOAccept(){ /* NOP */ }
280 47 : void SocketConnection::_initAIORead(){ /* NOP */ }
281 94 : void SocketConnection::_exitAIORead(){ /* NOP */ }
282 : #endif
283 :
284 : //----------------------------------------------------------------------
285 : // accept
286 : //----------------------------------------------------------------------
287 : #ifdef _WIN32
288 : void SocketConnection::acceptNB()
289 : {
290 : LBASSERT( isListening() );
291 :
292 : // Create new accept socket
293 : const DWORD flags = WSA_FLAG_OVERLAPPED;
294 :
295 : LBASSERT( _overlappedAcceptData );
296 : LBASSERT( _overlappedSocket == INVALID_SOCKET );
297 : _overlappedSocket = WSASocketW( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0,
298 : flags );
299 :
300 : if( _overlappedSocket == INVALID_SOCKET )
301 : {
302 : LBERROR << "Could not create accept socket: " << lunchbox::sysError
303 : << ", closing listening socket" << std::endl;
304 : close();
305 : return;
306 : }
307 :
308 : const int on = 1;
309 : setsockopt( _overlappedSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
310 : reinterpret_cast<const char*>( &on ), sizeof( on ));
311 :
312 : // Start accept
313 : ResetEvent( _overlappedRead.hEvent );
314 : DWORD got;
315 : if( !AcceptEx( _readFD, _overlappedSocket, _overlappedAcceptData, 0,
316 : sizeof( sockaddr_in ) + 16, sizeof( sockaddr_in ) + 16,
317 : &got, &_overlappedRead ) &&
318 : GetLastError() != WSA_IO_PENDING )
319 : {
320 : LBERROR << "Could not start accept operation: "
321 : << lunchbox::sysError << ", closing connection" << std::endl;
322 : close();
323 : }
324 : }
325 :
326 : ConnectionPtr SocketConnection::acceptSync()
327 : {
328 : LB_TS_THREAD( _recvThread );
329 : if( !isListening( ))
330 : return 0;
331 :
332 : LBASSERT( _overlappedAcceptData );
333 : LBASSERT( _overlappedSocket != INVALID_SOCKET );
334 : if( _overlappedSocket == INVALID_SOCKET )
335 : return 0;
336 :
337 : // complete accept
338 : DWORD got = 0;
339 : DWORD flags = 0;
340 :
341 : if( !WSAGetOverlappedResult( _readFD, &_overlappedRead, &got, TRUE,
342 : &flags ))
343 : {
344 : LBWARN << "Accept completion failed: " << lunchbox::sysError
345 : << ", closing socket" << std::endl;
346 : close();
347 : return 0;
348 : }
349 :
350 : sockaddr_in* local = 0;
351 : sockaddr_in* remote = 0;
352 : int localLen = 0;
353 : int remoteLen = 0;
354 : GetAcceptExSockaddrs( _overlappedAcceptData, 0, sizeof( sockaddr_in ) + 16,
355 : sizeof( sockaddr_in ) + 16, (sockaddr**)&local,
356 : &localLen, (sockaddr**)&remote, &remoteLen );
357 : _tuneSocket( _overlappedSocket );
358 :
359 : ConstConnectionDescriptionPtr description = getDescription();
360 : SocketConnection* newConnection = new SocketConnection;
361 : ConnectionPtr connection( newConnection ); // to keep ref-counting correct
362 :
363 : newConnection->_readFD = _overlappedSocket;
364 : newConnection->_writeFD = _overlappedSocket;
365 :
366 : #ifndef _WIN32
367 : //fcntl( _overlappedSocket, F_SETFL, O_NONBLOCK );
368 : #endif
369 :
370 : newConnection->_initAIORead();
371 : _overlappedSocket = INVALID_SOCKET;
372 :
373 : newConnection->_setState( STATE_CONNECTED );
374 : ConnectionDescriptionPtr newDescription = newConnection->_getDescription();
375 : newDescription->bandwidth = description->bandwidth;
376 : newDescription->port = ntohs( remote->sin_port );
377 : newDescription->setHostname( getHostName( *remote ));
378 :
379 : LBDEBUG << "accepted connection from " << newDescription->getHostname()
380 : << ":" << newDescription->port << std::endl;
381 : return connection;
382 : }
383 :
384 : #else // !_WIN32
385 :
386 94 : void SocketConnection::acceptNB(){ /* NOP */ }
387 :
388 47 : ConnectionPtr SocketConnection::acceptSync()
389 : {
390 47 : if( !isListening( ))
391 0 : return 0;
392 :
393 : sockaddr_in newAddress;
394 47 : socklen_t newAddressLen = sizeof( newAddress );
395 :
396 : Socket fd;
397 47 : unsigned nTries = 1000;
398 47 : do
399 47 : fd = ::accept( _readFD, (sockaddr*)&newAddress, &newAddressLen );
400 47 : while( fd == INVALID_SOCKET && errno == EINTR && --nTries );
401 :
402 47 : if( fd == INVALID_SOCKET )
403 : {
404 0 : LBWARN << "accept failed: " << lunchbox::sysError << std::endl;
405 0 : return 0;
406 : }
407 :
408 47 : _tuneSocket( fd );
409 :
410 94 : ConstConnectionDescriptionPtr description = getDescription();
411 47 : SocketConnection* newConnection = new SocketConnection;
412 :
413 47 : newConnection->_readFD = fd;
414 47 : newConnection->_writeFD = fd;
415 47 : newConnection->_setState( STATE_CONNECTED );
416 94 : ConnectionDescriptionPtr newDescription = newConnection->_getDescription();
417 47 : newDescription->bandwidth = description->bandwidth;
418 47 : newDescription->port = ntohs( newAddress.sin_port );
419 47 : newDescription->setHostname( inet_ntoa( newAddress.sin_addr ));
420 :
421 47 : LBDEBUG << "Accepted " << newDescription->toString() << std::endl;
422 47 : return newConnection;
423 : }
424 :
425 : #endif // !_WIN32
426 :
427 :
428 :
429 : #ifdef _WIN32
430 : //----------------------------------------------------------------------
431 : // read
432 : //----------------------------------------------------------------------
433 : void SocketConnection::readNB( void* buffer, const uint64_t bytes )
434 : {
435 : if( isClosed() )
436 : return;
437 :
438 : WSABUF wsaBuffer = { LB_MIN( bytes, 65535 ),
439 : reinterpret_cast< char* >( buffer ) };
440 : DWORD flags = 0;
441 :
442 : ResetEvent( _overlappedRead.hEvent );
443 : _overlappedDone = 0;
444 : const int result = WSARecv( _readFD, &wsaBuffer, 1, &_overlappedDone,
445 : &flags, &_overlappedRead, 0 );
446 : if( result == 0 ) // got data already
447 : {
448 : if( _overlappedDone == 0 ) // socket closed
449 : {
450 : LBDEBUG << "Got EOF, closing connection" << std::endl;
451 : close();
452 : }
453 : SetEvent( _overlappedRead.hEvent );
454 : }
455 : else if( GetLastError() != WSA_IO_PENDING )
456 : {
457 : LBWARN << "Could not start overlapped receive: " << lunchbox::sysError
458 : << ", closing connection" << std::endl;
459 : close();
460 : }
461 : }
462 :
463 : int64_t SocketConnection::readSync( void* buffer, const uint64_t bytes,
464 : const bool block )
465 : {
466 : LB_TS_THREAD( _recvThread );
467 :
468 : if( _readFD == INVALID_SOCKET )
469 : {
470 : LBERROR << "Invalid read handle" << std::endl;
471 : return READ_ERROR;
472 : }
473 :
474 : if( _overlappedDone > 0 )
475 : return _overlappedDone;
476 :
477 : DWORD got = 0;
478 : DWORD flags = 0;
479 : DWORD startTime = 0;
480 :
481 : while( true )
482 : {
483 : if( WSAGetOverlappedResult( _readFD, &_overlappedRead, &got, block,
484 : &flags ))
485 : return got;
486 :
487 : const int err = WSAGetLastError();
488 : if( err == ERROR_SUCCESS || got > 0 )
489 : {
490 : LBWARN << "Got " << lunchbox::sysError << " with " << got
491 : << " bytes on " << getDescription() << std::endl;
492 : return got;
493 : }
494 :
495 : if( startTime == 0 )
496 : startTime = GetTickCount();
497 :
498 : switch( err )
499 : {
500 : case WSA_IO_INCOMPLETE:
501 : return READ_TIMEOUT;
502 :
503 : case WSASYSCALLFAILURE: // happens sometimes!?
504 : case WSA_IO_PENDING:
505 : if( GetTickCount() - startTime > CO_RECV_TIMEOUT ) // timeout
506 : {
507 : LBWARN << "Error timeout " << std::endl;
508 : return READ_ERROR;
509 : }
510 :
511 : LBWARN << "WSAGetOverlappedResult error loop"
512 : << std::endl;
513 : // one millisecond to recover
514 : lunchbox::sleep( 1 );
515 : break;
516 :
517 : default:
518 : LBWARN << "Got " << lunchbox::sysError
519 : << ", closing connection" << std::endl;
520 : close();
521 : return READ_ERROR;
522 : }
523 : }
524 : }
525 :
526 : int64_t SocketConnection::write( const void* buffer, const uint64_t bytes )
527 : {
528 : if( !isConnected() || _writeFD == INVALID_SOCKET )
529 : return -1;
530 :
531 : DWORD wrote;
532 : WSABUF wsaBuffer =
533 : {
534 : LB_MIN( bytes, 65535 ),
535 : const_cast<char*>( static_cast< const char* >( buffer ))
536 : };
537 :
538 : ResetEvent( _overlappedWrite.hEvent );
539 : if( WSASend(_writeFD, &wsaBuffer, 1, &wrote, 0, &_overlappedWrite, 0 ) == 0 )
540 : // ok
541 : return wrote;
542 :
543 : if( WSAGetLastError() != WSA_IO_PENDING )
544 : return -1;
545 :
546 : const DWORD err = WaitForSingleObject( _overlappedWrite.hEvent, INFINITE );
547 : switch( err )
548 : {
549 : case WAIT_FAILED:
550 : case WAIT_ABANDONED:
551 : {
552 : LBWARN << "Write error" << lunchbox::sysError << std::endl;
553 : return -1;
554 : }
555 :
556 : default:
557 : LBWARN << "Unhandled write error " << err << ": " << lunchbox::sysError
558 : << std::endl;
559 : // no break;
560 : case WAIT_OBJECT_0:
561 : break;
562 : }
563 :
564 : DWORD got = 0;
565 : DWORD flags = 0;
566 : if( WSAGetOverlappedResult( _writeFD, &_overlappedWrite, &got, false,
567 : &flags ))
568 : {
569 : return got;
570 : }
571 :
572 : switch( WSAGetLastError() )
573 : {
574 : case WSA_IO_INCOMPLETE:
575 : throw Exception( Exception::TIMEOUT_WRITE );
576 :
577 : default:
578 : {
579 : LBWARN << "Write error : " << lunchbox::sysError << std::endl;
580 : return -1;
581 : }
582 : }
583 :
584 : LBUNREACHABLE;
585 : return -1;
586 : }
587 : #endif // _WIN32
588 :
589 98 : bool SocketConnection::_createSocket()
590 : {
591 196 : ConstConnectionDescriptionPtr description = getDescription();
592 : #ifdef _WIN32
593 : const DWORD flags = WSA_FLAG_OVERLAPPED;
594 : const SOCKET fd = WSASocketW( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0,
595 : flags );
596 : #else
597 98 : const Socket fd = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
598 : #endif
599 :
600 98 : if( fd == INVALID_SOCKET )
601 : {
602 0 : LBERROR << "Could not create socket: "
603 0 : << lunchbox::sysError << std::endl;
604 0 : return false;
605 : }
606 :
607 98 : _tuneSocket( fd );
608 :
609 98 : _readFD = fd;
610 98 : _writeFD = fd; // TCP/IP sockets are bidirectional
611 :
612 98 : return true;
613 : }
614 :
615 145 : void SocketConnection::_tuneSocket( const Socket fd )
616 : {
617 145 : const int on = 1;
618 : setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
619 145 : reinterpret_cast<const char*>( &on ), sizeof( on ));
620 : setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
621 145 : reinterpret_cast<const char*>( &on ), sizeof( on ));
622 :
623 : #ifdef _WIN32
624 : const int size = 128768;
625 : setsockopt( fd, SOL_SOCKET, SO_RCVBUF,
626 : reinterpret_cast<const char*>( &size ), sizeof( size ));
627 : setsockopt( fd, SOL_SOCKET, SO_SNDBUF,
628 : reinterpret_cast<const char*>( &size ), sizeof( size ));
629 : #endif
630 145 : }
631 :
632 : //----------------------------------------------------------------------
633 : // listen
634 : //----------------------------------------------------------------------
635 51 : bool SocketConnection::listen()
636 : {
637 102 : ConnectionDescriptionPtr description = _getDescription();
638 51 : LBASSERT( description->type == CONNECTIONTYPE_TCPIP );
639 :
640 51 : if( !isClosed( ))
641 0 : return false;
642 :
643 51 : _setState( STATE_CONNECTING );
644 :
645 : sockaddr_in address;
646 51 : const size_t size = sizeof( sockaddr_in );
647 :
648 51 : if( !_parseAddress( description, address ))
649 : {
650 0 : LBWARN << "Can't parse connection parameters" << std::endl;
651 0 : return false;
652 : }
653 :
654 51 : if( !_createSocket())
655 0 : return false;
656 :
657 51 : const bool bound = (::bind( _readFD, (sockaddr *)&address, size ) == 0);
658 :
659 51 : if( !bound )
660 : {
661 0 : LBWARN << "Could not bind socket " << _readFD << ": "
662 0 : << lunchbox::sysError << " to " << getHostName( address )
663 0 : << ":" << ntohs( address.sin_port ) << " AF "
664 0 : << (int)address.sin_family << std::endl;
665 :
666 0 : close();
667 0 : return false;
668 : }
669 :
670 51 : if( ::listen( _readFD, SOMAXCONN ) != 0 )
671 : {
672 0 : LBWARN << "Could not listen on socket: " << lunchbox::sysError
673 0 : << std::endl;
674 0 : close();
675 0 : return false;
676 : }
677 :
678 : // get socket parameters
679 51 : socklen_t used = size;
680 51 : getsockname( _readFD, (struct sockaddr *)&address, &used );
681 51 : description->port = ntohs( address.sin_port );
682 :
683 102 : std::string hostname = description->getHostname();
684 51 : if( hostname.empty( ))
685 : {
686 29 : if( address.sin_addr.s_addr == INADDR_ANY )
687 : {
688 29 : char cHostname[256] = {0};
689 29 : gethostname( cHostname, 256 );
690 29 : hostname = cHostname;
691 :
692 29 : description->setHostname( hostname );
693 : }
694 : else
695 0 : description->setHostname( getHostName( address ));
696 : }
697 :
698 51 : _initAIOAccept();
699 51 : _setState( STATE_LISTENING );
700 :
701 204 : LBDEBUG << "Listening on " << description->getHostname() << "["
702 153 : << getHostName( address ) << "]:" << description->port
703 255 : << " (" << description->toString() << ")" << std::endl;
704 :
705 51 : return true;
706 : }
707 :
708 0 : uint16_t SocketConnection::_getPort() const
709 : {
710 : sockaddr_in address;
711 0 : socklen_t used = sizeof( address );
712 0 : getsockname( _readFD, (struct sockaddr *) &address, &used );
713 0 : return ntohs(address.sin_port);
714 : }
715 :
716 66 : }
|