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