face: prevent creation of duplicate tcp/udp faces due to async calls
refs: #1680
Change-Id: I0e685d6bde1f6745902c86f782d41c9070aecb21
diff --git a/daemon/face/tcp-channel.cpp b/daemon/face/tcp-channel.cpp
index d058944..3986828 100644
--- a/daemon/face/tcp-channel.cpp
+++ b/daemon/face/tcp-channel.cpp
@@ -131,15 +131,32 @@
tcp::Endpoint remoteEndpoint = socket->remote_endpoint();
shared_ptr<Face> face;
- if (socket->local_endpoint().address().is_loopback())
- face = make_shared<TcpLocalFace>(socket, isOnDemand);
+
+ ChannelFaceMap::iterator faceMapPos = m_channelFaces.find(remoteEndpoint);
+ if (faceMapPos == m_channelFaces.end())
+ {
+ if (socket->local_endpoint().address().is_loopback())
+ face = make_shared<TcpLocalFace>(socket, isOnDemand);
+ else
+ face = make_shared<TcpFace>(socket, isOnDemand);
+
+ face->onFail += bind(&TcpChannel::afterFaceFailed, this, remoteEndpoint);
+
+ m_channelFaces[remoteEndpoint] = face;
+ }
else
- face = make_shared<TcpFace>(socket, isOnDemand);
+ {
+ // we've already created a a face for this endpoint, just reuse it
+ face = faceMapPos->second;
- face->onFail += bind(&TcpChannel::afterFaceFailed, this, remoteEndpoint);
+ boost::system::error_code error;
+ socket->shutdown(ip::tcp::socket::shutdown_both, error);
+ socket->close(error);
+ }
+ // Need to invoke the callback regardless of whether or not we have already created
+ // the face so that control responses and such can be sent.
onFaceCreated(face);
- m_channelFaces[remoteEndpoint] = face;
}
void
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index 99d01e3..684879a 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -180,11 +180,30 @@
{
udp::Endpoint remoteEndpoint = socket->remote_endpoint();
- shared_ptr<UdpFace> face = make_shared<UdpFace>(socket, isOnDemand);
- face->onFail += bind(&UdpChannel::afterFaceFailed, this, remoteEndpoint);
+ shared_ptr<UdpFace> face;
+ ChannelFaceMap::iterator faceMapPos = m_channelFaces.find(remoteEndpoint);
+ if (faceMapPos == m_channelFaces.end())
+ {
+ face = make_shared<UdpFace>(socket, isOnDemand);
+ face->onFail += bind(&UdpChannel::afterFaceFailed, this, remoteEndpoint);
+
+ m_channelFaces[remoteEndpoint] = face;
+ }
+ else
+ {
+ // we've already created a a face for this endpoint, just reuse it
+ face = faceMapPos->second;
+
+ boost::system::error_code error;
+ socket->shutdown(ip::udp::socket::shutdown_both, error);
+ socket->close(error);
+ }
+
+ // Need to invoke the callback regardless of whether or not we have already created
+ // the face so that control responses and such can be sent.
onFaceCreated(face);
- m_channelFaces[remoteEndpoint] = face;
+
return face;
}