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