version 1.41.2.2, 2006/07/28 23:52:18
|
version 1.60, 2015/06/10 12:36:02
|
|
|
//%2006//////////////////////////////////////////////////////////////////////// |
//%LICENSE//////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development |
// Licensed to The Open Group (TOG) under one or more contributor license |
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. |
// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with |
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.; |
// this work for additional information regarding copyright ownership. |
// IBM Corp.; EMC Corporation, The Open Group. |
// Each contributor licenses this file to you under the OpenPegasus Open |
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; |
// Source License; you may not use this file except in compliance with the |
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. |
// License. |
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
// |
// EMC Corporation; VERITAS Software Corporation; The Open Group. |
// Permission is hereby granted, free of charge, to any person obtaining a |
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
// copy of this software and associated documentation files (the "Software"), |
// EMC Corporation; Symantec Corporation; The Open Group. |
// to deal in the Software without restriction, including without limitation |
// |
// the rights to use, copy, modify, merge, publish, distribute, sublicense, |
// Permission is hereby granted, free of charge, to any person obtaining a copy |
// and/or sell copies of the Software, and to permit persons to whom the |
// of this software and associated documentation files (the "Software"), to |
// Software is furnished to do so, subject to the following conditions: |
// deal in the Software without restriction, including without limitation the |
// |
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
// The above copyright notice and this permission notice shall be included |
// sell copies of the Software, and to permit persons to whom the Software is |
// in all copies or substantial portions of the Software. |
// furnished to do so, subject to the following conditions: |
// |
// |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN |
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED |
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT |
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
// |
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
////////////////////////////////////////////////////////////////////////// |
// |
|
//============================================================================== |
|
// |
|
// Author: Dong Xiang, EMC Corporation (xiang_dong@emc.com) |
|
// |
|
// Modified By: Dan Gorey (djgorey@us.ibm.com) |
|
// Amit K Arora, IBM (amita@in.ibm.com) for PEP#183 |
|
// Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
|
// David Dillard, VERITAS Software Corp. |
|
// (david.dillard@veritas.com) |
|
// Vijay Eli, IBM (vijay.eli@in.ibm.com) for bug#3425 |
|
// Aruran, IBM (ashanmug@in.ibm.com) for Bug# 3604 |
|
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
|
|
#include <Pegasus/Common/SSLContext.h> | #include <Pegasus/Common/SSLContext.h> |
#include <Pegasus/Common/Monitor.h> | #include <Pegasus/Common/Monitor.h> |
#include <Pegasus/Common/HTTPAcceptor.h> | #include <Pegasus/Common/HTTPAcceptor.h> |
|
#include <Pegasus/Common/HostAddress.h> |
#include <Pegasus/Common/PegasusVersion.h> | #include <Pegasus/Common/PegasusVersion.h> |
#include <Pegasus/Common/MessageLoader.h> | #include <Pegasus/Common/MessageLoader.h> |
|
#include <Pegasus/Common/Time.h> |
#include <Pegasus/ExportServer/CIMExportResponseEncoder.h> | #include <Pegasus/ExportServer/CIMExportResponseEncoder.h> |
#include <Pegasus/ExportServer/CIMExportRequestDecoder.h> | #include <Pegasus/ExportServer/CIMExportRequestDecoder.h> |
#include <Pegasus/Consumer/CIMIndicationConsumer.h> | #include <Pegasus/Consumer/CIMIndicationConsumer.h> |
|
|
class CIMListenerService | class CIMListenerService |
{ | { |
public: | public: |
|
CIMListenerService( |
|
const String &listenAddress, |
|
Uint32 portNumber, |
|
SSLContext * sslContext = NULL); |
CIMListenerService(Uint32 portNumber, SSLContext * sslContext = NULL); | CIMListenerService(Uint32 portNumber, SSLContext * sslContext = NULL); |
CIMListenerService(CIMListenerService & svc); | CIMListenerService(CIMListenerService & svc); |
~CIMListenerService(); | ~CIMListenerService(); |
|
|
*/ | */ |
void setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher); | void setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher); |
| |
|
/** Returns the bind address. |
|
*/ |
|
String getListenAddress() const; |
|
|
/** Returns the port number being used. | /** Returns the port number being used. |
*/ | */ |
Uint32 getPortNumber() const; | Uint32 getPortNumber() const; |
|
|
_listener_routine(void *param); | _listener_routine(void *param); |
| |
private: | private: |
|
String _listenAddress; |
Uint32 _portNumber; | Uint32 _portNumber; |
SSLContext *_sslContext; | SSLContext *_sslContext; |
|
ReadWriteSem _sslContextObjectLock; |
Monitor *_monitor; | Monitor *_monitor; |
Mutex _monitorMutex; | Mutex _monitorMutex; |
HTTPAcceptor *_acceptor; |
HTTPAcceptor *_ip6Acceptor; |
|
HTTPAcceptor *_ip4Acceptor; |
Boolean _dieNow; | Boolean _dieNow; |
CIMListenerIndicationDispatcher *_dispatcher; | CIMListenerIndicationDispatcher *_dispatcher; |
CIMExportResponseEncoder *_responseEncoder; | CIMExportResponseEncoder *_responseEncoder; |
|
|
}; | }; |
| |
CIMListenerService::CIMListenerService( | CIMListenerService::CIMListenerService( |
|
const String &listenAddress, |
|
Uint32 portNumber, |
|
SSLContext * sslContext) |
|
: |
|
_listenAddress(listenAddress), |
|
_portNumber(portNumber), |
|
_sslContext(sslContext), |
|
_monitor(NULL), |
|
_ip6Acceptor(NULL), |
|
_ip4Acceptor(NULL), |
|
_dieNow(false), |
|
_dispatcher(NULL), |
|
_responseEncoder(NULL), |
|
_requestDecoder(NULL) |
|
{ |
|
} |
|
|
|
CIMListenerService::CIMListenerService( |
Uint32 portNumber, | Uint32 portNumber, |
SSLContext * sslContext) | SSLContext * sslContext) |
: | : |
|
_listenAddress(), |
_portNumber(portNumber), | _portNumber(portNumber), |
_sslContext(sslContext), | _sslContext(sslContext), |
_monitor(NULL), | _monitor(NULL), |
_acceptor(NULL), |
_ip6Acceptor(NULL), |
|
_ip4Acceptor(NULL), |
_dieNow(false), | _dieNow(false), |
_dispatcher(NULL), | _dispatcher(NULL), |
_responseEncoder(NULL), | _responseEncoder(NULL), |
|
|
} | } |
| |
CIMListenerService::CIMListenerService(CIMListenerService & svc) : | CIMListenerService::CIMListenerService(CIMListenerService & svc) : |
|
_listenAddress(svc._listenAddress), |
_portNumber(svc._portNumber), | _portNumber(svc._portNumber), |
_sslContext(svc._sslContext), | _sslContext(svc._sslContext), |
_monitor(NULL), | _monitor(NULL), |
_acceptor(NULL), |
_ip6Acceptor(NULL), |
|
_ip4Acceptor(NULL), |
_dieNow(svc._dieNow), | _dieNow(svc._dieNow), |
_dispatcher(NULL), | _dispatcher(NULL), |
_responseEncoder(NULL), | _responseEncoder(NULL), |
|
|
{ | { |
delete _responseEncoder; | delete _responseEncoder; |
delete _requestDecoder; | delete _requestDecoder; |
delete _acceptor; |
delete _ip6Acceptor; |
|
delete _ip4Acceptor; |
delete _monitor; | delete _monitor; |
} | } |
| |
|
|
_dispatcher, _responseEncoder->getQueueId()); | _dispatcher, _responseEncoder->getQueueId()); |
} | } |
| |
if (NULL == _acceptor) |
HostAddress listenAddress; |
|
Boolean listenAddressEmpty = _listenAddress == String::EMPTY; |
|
if (!listenAddressEmpty) |
|
listenAddress.setHostAddress(_listenAddress); |
|
|
|
#ifdef PEGASUS_ENABLE_IPV6 |
|
if (System::isIPv6StackActive() && |
|
(listenAddressEmpty || |
|
(listenAddress.isValid() && |
|
listenAddress.getAddressType() == HostAddress::AT_IPV6))) |
|
{ |
|
if (NULL == _ip6Acceptor) |
|
{ |
|
if (NULL == _sslContext) |
|
{ |
|
_ip6Acceptor = new HTTPAcceptor( |
|
_monitor, _requestDecoder, |
|
HTTPAcceptor::IPV6_CONNECTION, |
|
_portNumber, 0, 0, |
|
listenAddressEmpty ? 0 : &listenAddress); |
|
} |
|
else |
{ | { |
_acceptor = new HTTPAcceptor( |
_ip6Acceptor = new HTTPAcceptor( |
_monitor, _requestDecoder, false, _portNumber, _sslContext, false); |
_monitor, _requestDecoder, |
|
HTTPAcceptor::IPV6_CONNECTION, |
|
_portNumber, _sslContext, &_sslContextObjectLock, |
|
listenAddressEmpty ? 0 : &listenAddress); |
|
} |
|
} |
|
} |
|
#ifndef PEGASUS_OS_TYPE_WINDOWS |
|
else |
|
#endif |
|
#endif |
|
if (NULL == _ip4Acceptor) |
|
{ |
|
if (NULL == _sslContext) |
|
{ |
|
_ip4Acceptor = new HTTPAcceptor( |
|
_monitor, _requestDecoder, |
|
HTTPAcceptor::IPV4_CONNECTION, |
|
_portNumber, 0, 0, |
|
listenAddressEmpty ? 0 : &listenAddress); |
|
} |
|
else |
|
{ |
|
_ip4Acceptor = new HTTPAcceptor( |
|
_monitor, _requestDecoder, |
|
HTTPAcceptor::IPV4_CONNECTION, |
|
_portNumber, _sslContext, &_sslContextObjectLock, |
|
listenAddressEmpty ? 0 : &listenAddress); |
|
} |
} | } |
|
|
bind(); | bind(); |
| |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
|
|
| |
void CIMListenerService::bind() | void CIMListenerService::bind() |
{ | { |
if (_acceptor != NULL) |
if (_ip6Acceptor != NULL) |
|
{ |
|
_ip6Acceptor->bind(); |
|
|
|
Logger::put( |
|
Logger::STANDARD_LOG, |
|
System::CIMLISTENER, |
|
Logger::INFORMATION, |
|
"IPV6, Listening on HTTP port $0.", |
|
_portNumber); |
|
} |
|
if (_ip4Acceptor != NULL) |
{ | { |
_acceptor->bind(); |
_ip4Acceptor->bind(); |
| |
Logger::put( | Logger::put( |
Logger::STANDARD_LOG, | Logger::STANDARD_LOG, |
System::CIMLISTENER, | System::CIMLISTENER, |
Logger::INFORMATION, | Logger::INFORMATION, |
"Listening on HTTP port $0.", |
"IPV4, Listening on HTTP for port $0.", |
_portNumber); | _portNumber); |
} | } |
} | } |
| |
void CIMListenerService::runForever() | void CIMListenerService::runForever() |
{ | { |
static int modulator = 0; |
|
|
|
if (!_dieNow) | if (!_dieNow) |
{ | { |
if (false == _monitor->run(500000)) |
_monitor->run(500000); |
|
static struct timeval lastIdleCleanupTime = {0, 0}; |
|
struct timeval now; |
|
Time::gettimeofday(&now); |
|
if (now.tv_sec - lastIdleCleanupTime.tv_sec > 300) |
{ | { |
modulator++; |
lastIdleCleanupTime.tv_sec = now.tv_sec; |
try | try |
{ | { |
MessageQueueService::get_thread_pool()->cleanupIdleThreads(); | MessageQueueService::get_thread_pool()->cleanupIdleThreads(); |
|
|
void CIMListenerService::resume() | void CIMListenerService::resume() |
{ | { |
PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::resume()"); | PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::resume()"); |
|
if (_ip6Acceptor != NULL) |
if (_acceptor != NULL) |
{ |
_acceptor->reopenConnectionSocket(); |
_ip6Acceptor->reopenConnectionSocket(); |
|
} |
|
if (_ip4Acceptor != NULL) |
|
{ |
|
_ip4Acceptor->reopenConnectionSocket(); |
|
} |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
} | } |
| |
|
|
| |
// tell Monitor to stop listening for client connections | // tell Monitor to stop listening for client connections |
_monitor->stopListeningForConnections(true); | _monitor->stopListeningForConnections(true); |
|
if (_ip6Acceptor != NULL) |
if (_acceptor != NULL) |
{ |
_acceptor->closeConnectionSocket(); |
_ip6Acceptor->closeConnectionSocket(); |
|
} |
|
if (_ip4Acceptor != NULL) |
|
{ |
|
_ip4Acceptor->closeConnectionSocket(); |
|
} |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
} | } |
| |
Uint32 CIMListenerService::getOutstandingRequestCount() | Uint32 CIMListenerService::getOutstandingRequestCount() |
{ | { |
return _acceptor->getOutstandingRequestCount(); |
Uint32 cnt = 0; |
|
|
|
if (_ip6Acceptor) |
|
{ |
|
cnt = _ip6Acceptor->getOutstandingRequestCount(); |
|
} |
|
|
|
if (_ip4Acceptor) |
|
{ |
|
cnt += _ip4Acceptor->getOutstandingRequestCount(); |
|
} |
|
|
|
return cnt; |
} | } |
| |
CIMListenerIndicationDispatcher* | CIMListenerIndicationDispatcher* |
|
|
_dispatcher = dispatcher; | _dispatcher = dispatcher; |
} | } |
| |
|
String CIMListenerService::getListenAddress() const |
|
{ |
|
bool listenAddressEmpty = _listenAddress == String::EMPTY; |
|
|
|
if (listenAddressEmpty && _ip6Acceptor != 0) |
|
return _ip6Acceptor->getListenAddress(); |
|
else if (listenAddressEmpty && _ip4Acceptor != 0) |
|
return _ip4Acceptor->getListenAddress(); |
|
|
|
return _listenAddress; |
|
} |
|
|
Uint32 CIMListenerService::getPortNumber() const | Uint32 CIMListenerService::getPortNumber() const |
{ | { |
Uint32 portNumber = _portNumber; | Uint32 portNumber = _portNumber; |
| |
if ((portNumber == 0) && (_acceptor != 0)) |
if ((portNumber == 0) && (_ip6Acceptor != 0)) |
{ | { |
portNumber = _acceptor->getPortNumber(); |
portNumber = _ip6Acceptor->getPortNumber(); |
|
} |
|
else if ((portNumber == 0) && (_ip4Acceptor != 0)) |
|
{ |
|
portNumber = _ip4Acceptor->getPortNumber(); |
} | } |
| |
return (portNumber); | return (portNumber); |
|
|
// svc->init(); bug 1394 | // svc->init(); bug 1394 |
while (!svc->terminated()) | while (!svc->terminated()) |
{ | { |
#if defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU) |
#if defined(PEGASUS_OS_DARWIN) |
pthread_testcancel(); | pthread_testcancel(); |
#endif | #endif |
svc->runForever(); | svc->runForever(); |
|
|
} | } |
catch(...) | catch(...) |
{ | { |
Tracer::trace(TRC_SERVER, Tracer::LEVEL2, |
PEG_TRACE_CSTRING(TRC_SERVER, Tracer::LEVEL1, |
"Unknown exception thrown in _listener_routine."); | "Unknown exception thrown in _listener_routine."); |
} | } |
| |
|
|
class CIMListenerRep | class CIMListenerRep |
{ | { |
public: | public: |
|
CIMListenerRep( |
|
const String &listenAddress, |
|
Uint32 portNumber, |
|
SSLContext* sslContext = NULL); |
CIMListenerRep(Uint32 portNumber, SSLContext * sslContext = NULL); | CIMListenerRep(Uint32 portNumber, SSLContext * sslContext = NULL); |
~CIMListenerRep(); | ~CIMListenerRep(); |
| |
|
String getListenAddress() const; |
Uint32 getPortNumber() const; | Uint32 getPortNumber() const; |
| |
SSLContext *getSSLContext() const; | SSLContext *getSSLContext() const; |
|
|
private: | private: |
Boolean waitForPendingRequests(Uint32 shutdownTimeout); | Boolean waitForPendingRequests(Uint32 shutdownTimeout); |
| |
|
String _listenAddress; |
Uint32 _portNumber; | Uint32 _portNumber; |
SSLContext *_sslContext; | SSLContext *_sslContext; |
| |
|
|
}; | }; |
| |
CIMListenerRep::CIMListenerRep( | CIMListenerRep::CIMListenerRep( |
|
const String &listenAddress, |
Uint32 portNumber, | Uint32 portNumber, |
SSLContext * sslContext) | SSLContext * sslContext) |
: | : |
|
_listenAddress(listenAddress), |
_portNumber(portNumber), | _portNumber(portNumber), |
_sslContext(sslContext), | _sslContext(sslContext), |
_dispatcher(new CIMListenerIndicationDispatcher()), | _dispatcher(new CIMListenerIndicationDispatcher()), |
|
|
{ | { |
} | } |
| |
CIMListenerRep::~CIMListenerRep() |
CIMListenerRep::CIMListenerRep( |
{ |
Uint32 portNumber, |
// if port is alive, clean up the port |
SSLContext * sslContext) |
if (_thread_pool != 0) |
: |
|
_listenAddress(), |
|
_portNumber(portNumber), |
|
_sslContext(sslContext), |
|
_dispatcher(new CIMListenerIndicationDispatcher()), |
|
_thread_pool(NULL), |
|
_svc(NULL), |
|
_listener_sem(NULL) |
{ | { |
// Block incoming export requests and unbind the port |
|
_svc->stopClientConnection(); |
|
|
|
// Wait until pending export requests in the server are done. |
|
waitForPendingRequests(10); |
|
|
|
// Shutdown the CIMListenerService |
|
_svc->shutdown(); |
|
} | } |
| |
|
CIMListenerRep::~CIMListenerRep() |
|
{ |
|
stop(); |
|
|
delete _sslContext; | delete _sslContext; |
delete _dispatcher; | delete _dispatcher; |
delete _thread_pool; | delete _thread_pool; |
|
|
// don't delete _svc, this is deleted by _listener_routine | // don't delete _svc, this is deleted by _listener_routine |
} | } |
| |
|
String CIMListenerRep::getListenAddress() const |
|
{ |
|
return !_svc ? _listenAddress : _svc->getListenAddress(); |
|
} |
|
|
Uint32 CIMListenerRep::getPortNumber() const | Uint32 CIMListenerRep::getPortNumber() const |
{ | { |
Uint32 portNumber; | Uint32 portNumber; |
|
|
if (_thread_pool == 0) | if (_thread_pool == 0) |
{ | { |
AutoPtr < CIMListenerService > | AutoPtr < CIMListenerService > |
svc(new CIMListenerService(_portNumber, _sslContext)); |
svc(new CIMListenerService(_listenAddress, _portNumber, |
|
_sslContext)); |
| |
svc->setIndicationDispatcher(_dispatcher); | svc->setIndicationDispatcher(_dispatcher); |
svc->init(); | svc->init(); |
|
|
svc.get(), CIMListenerService::_listener_routine, sem.get()) | svc.get(), CIMListenerService::_listener_routine, sem.get()) |
!= PEGASUS_THREAD_OK) | != PEGASUS_THREAD_OK) |
{ | { |
Logger::put( |
PEG_TRACE_CSTRING( |
Logger::STANDARD_LOG, System::CIMSERVER, |
|
Logger::TRACE, |
|
"Not enough threads to start CIMListernerService."); |
|
|
|
Tracer::trace( |
|
TRC_SERVER, | TRC_SERVER, |
Tracer::LEVEL2, |
Tracer::LEVEL1, |
"Could not allocate thread for " | "Could not allocate thread for " |
"CIMListenerService::_listener_routine."); | "CIMListenerService::_listener_routine."); |
throw | throw |
|
|
// The thread could be delivering an export, so give it 3sec. | // The thread could be delivering an export, so give it 3sec. |
// Note that _listener_routine deletes the CIMListenerService, | // Note that _listener_routine deletes the CIMListenerService, |
// so no need to delete _svc. | // so no need to delete _svc. |
try |
if (!_listener_sem->time_wait(3000)) |
{ |
|
_listener_sem->time_wait(3000); |
|
} |
|
catch(const TimeOut &) |
|
{ | { |
// No need to do anything, the thread pool will be deleted below | // No need to do anything, the thread pool will be deleted below |
// to cancel the _listener_routine thread if it is still running. | // to cancel the _listener_routine thread if it is still running. |
|
|
///////////////////////////////////////////////////////////////////////////// | ///////////////////////////////////////////////////////////////////////////// |
| |
CIMListener::CIMListener( | CIMListener::CIMListener( |
|
const String &listenAddress, |
|
Uint32 portNumber, |
|
SSLContext* sslContext) |
|
: |
|
_rep(new CIMListenerRep(listenAddress, portNumber, sslContext)) |
|
{ |
|
} |
|
|
|
CIMListener::CIMListener( |
Uint32 portNumber, | Uint32 portNumber, |
SSLContext * sslContext) | SSLContext * sslContext) |
: | : |
|
|
_rep = NULL; | _rep = NULL; |
} | } |
| |
|
String CIMListener::getListenAddress() const |
|
{ |
|
return static_cast < CIMListenerRep * >(_rep)->getListenAddress(); |
|
} |
|
|
Uint32 CIMListener::getPortNumber() const | Uint32 CIMListener::getPortNumber() const |
{ | { |
return static_cast < CIMListenerRep * >(_rep)->getPortNumber(); | return static_cast < CIMListenerRep * >(_rep)->getPortNumber(); |