1477 lines
44 KiB
C++
1477 lines
44 KiB
C++
#include "precomp.h"
|
||
DEBUG_FILEZONE(ZONE_T120_MCSNC);
|
||
/*
|
||
* privchnl.cpp
|
||
*
|
||
* Copyright (c) 1993 - 1995 by DataBeam Corporation, Lexington, KY
|
||
*
|
||
* Abstract:
|
||
* This is the implementation file for the PrivateChannel class. It
|
||
* contains the code that distinguishes this class from that of its parent,
|
||
* Channel.
|
||
*
|
||
* This class maintains an authorized user list, and includes the code
|
||
* necessary to use that list. No user will be allowed to join or send
|
||
* data on a private channel unless they are either the channel manager
|
||
* or an admitted user.
|
||
*
|
||
* Private Instance Variables:
|
||
* m_uidChannelManager
|
||
* This is the User ID of the user that convened the private channel.
|
||
* Only this user is allowed to manipulate the authorized user list.
|
||
* When a private channel becomes invalid (as the result of a channel
|
||
* disband request or indication), this value will be set to 0.
|
||
* m_AuthorizedUserList
|
||
* This is a collection containing the user IDs of those users that
|
||
* have been admitted to the private channel by the channel manager.
|
||
* Other than the manager, these are the only users that are allowed
|
||
* to join or send data on the channel. When a private channel becomes
|
||
* invalid (as the result of a channel disband request or indication),
|
||
* this list will be cleared.
|
||
* m_fDisbandRequestPending
|
||
* This is a boolean flag that gets set when a disband request is
|
||
* forwarded upward to the top provider. This prevents this channel
|
||
* from issuing a disband indication to the channel manager when it
|
||
* comes back down the tree from the top provider.
|
||
*
|
||
* Private Member Functions:
|
||
* ValidateUserID
|
||
* This member function is called to verify that a specified user ID
|
||
* corresponds to a valid user in the sub-tree of the local provider.
|
||
* BuildAttachmentLists
|
||
* This member function is called to build two lists of attachments
|
||
* from a master user ID list. The first list contains all local
|
||
* attachments whose user ID is in the specified list. The second
|
||
* list contains all remote attachments whose user ID is in the
|
||
* specified list. These lists are used to issue various indications
|
||
* to specified users without sending any to the same attachment.
|
||
* BuildUserIDList
|
||
* This member function is called to build a list of users that lie
|
||
* in the direction of a specified attachment. These lists are
|
||
* sent along with PDUs that require them.
|
||
*
|
||
* Caveats:
|
||
* None.
|
||
*
|
||
* Author:
|
||
* James P. Galvin, Jr.
|
||
*/
|
||
|
||
/*
|
||
* External Interfaces
|
||
*/
|
||
|
||
#include "privchnl.h"
|
||
|
||
|
||
/*
|
||
* PrivateChannel ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This is the primary constructor for PrivateChannel objects. It creates
|
||
* an object with all instance variable initialized, but with no
|
||
* attachments (i.e. no users are joined to the channel automatically).
|
||
*
|
||
* Note that most instance variable initialization is done by invoking the
|
||
* equivalent constructor in the base class.
|
||
*
|
||
* Upon successful completion, a channel convene confirm is automatically
|
||
* issued to the channel manager, if the channel manager is in the sub-tree
|
||
* of this provider. Note that if the channel manager is NOT in this
|
||
* sub-tree, then this private channel object was probably created as the
|
||
* result of a channel admit indication, and no channel convene confirm
|
||
* will be issued.
|
||
*/
|
||
PrivateChannel::PrivateChannel (
|
||
ChannelID channel_id,
|
||
UserID channel_manager,
|
||
PDomain local_provider,
|
||
PConnection top_provider,
|
||
CChannelList2 *channel_list,
|
||
CAttachmentList *attachment_list)
|
||
:
|
||
Channel(channel_id, local_provider, top_provider, channel_list, attachment_list),
|
||
m_AuthorizedUserList(),
|
||
m_uidChannelManager(channel_manager),
|
||
m_fDisbandRequestPending(FALSE)
|
||
{
|
||
/*
|
||
* Check to see if the channel manager lies in the sub-tree of this
|
||
* provider. If so, then this object was created as the result of a
|
||
* channel convene request or confirm, and it is necessary to issue the
|
||
* confirm toward that user. If not, then this object was created as the
|
||
* result of a channel admit indication, and it is not necessary to send
|
||
* the channel convene confirm.
|
||
*/
|
||
if (ValidateUserID(m_uidChannelManager))
|
||
{
|
||
PChannel lpChannel;
|
||
/*
|
||
* Determine which attachment leads to the channel manager by asking
|
||
* the channel object corresponding to it. Then issue the confirm
|
||
* to that attachment.
|
||
*/
|
||
if (NULL != (lpChannel = m_pChannelList2->Find(m_uidChannelManager)))
|
||
{
|
||
CAttachment *pAtt = lpChannel->GetAttachment();
|
||
if (pAtt)
|
||
{
|
||
pAtt->ChannelConveneConfirm(RESULT_SUCCESSFUL,
|
||
m_uidChannelManager, channel_id);
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("PrivateChannel::PrivateChannel: null attachment"));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* PrivateChannel ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This is a secondary constructor that is only used during merge
|
||
* operations. The intent of this constructor is to create an equivalent
|
||
* object without issuing any of the confirms.
|
||
*
|
||
* Note that the additional constructor allows for the creator to specify
|
||
* that there is an attachment already joined to the channel upon creation.
|
||
*/
|
||
PrivateChannel::PrivateChannel (
|
||
ChannelID channel_id,
|
||
UserID channel_manager,
|
||
PDomain local_provider,
|
||
PConnection top_provider,
|
||
CChannelList2 *channel_list,
|
||
CAttachmentList *attachment_list,
|
||
CUidList *admitted_list,
|
||
PConnection pConn)
|
||
:
|
||
Channel(channel_id, local_provider, top_provider, channel_list, attachment_list, pConn),
|
||
m_AuthorizedUserList(),
|
||
m_uidChannelManager(channel_manager),
|
||
m_fDisbandRequestPending(FALSE)
|
||
{
|
||
UserID uid;
|
||
|
||
/*
|
||
* Copy the initial contents of the admitted list into the authorized
|
||
* user list.
|
||
*/
|
||
admitted_list->Reset();
|
||
while (NULL != (uid = admitted_list->Iterate()))
|
||
{
|
||
m_AuthorizedUserList.Append(uid);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* ~PrivateChannel ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This destructor walks through the admitted list, sending expel
|
||
* indications to any admitted users that are locally attached. If the
|
||
* channel manager is locally attached, and this channel is being deleted
|
||
* a reason other than a previous disband request, then a disband
|
||
* indication will be sent to the channel manager.
|
||
*/
|
||
PrivateChannel::~PrivateChannel ()
|
||
{
|
||
CAttachmentList local_attachment_list;
|
||
CAttachmentList remote_attachment_list;
|
||
CAttachment *pAtt;
|
||
CUidList user_id_list;
|
||
|
||
/*
|
||
* Assemble lists of the attachments that lead to authorized users in
|
||
* the sub-tree of this provider.
|
||
*/
|
||
BuildAttachmentLists (&m_AuthorizedUserList, &local_attachment_list,
|
||
&remote_attachment_list);
|
||
|
||
/*
|
||
* For each local attachment, issue a channel expel indication letting the
|
||
* user know that the channel is no longer valid.
|
||
*/
|
||
local_attachment_list.Reset();
|
||
while (NULL != (pAtt = local_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of the users
|
||
* that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&m_AuthorizedUserList, pAtt, &user_id_list);
|
||
|
||
/*
|
||
* Send the indication.
|
||
*/
|
||
pAtt->ChannelExpelIndication(Channel_ID, &user_id_list);
|
||
}
|
||
|
||
/*
|
||
* If the channel manager is a locally attached user, then send it a
|
||
* ChannelDisbandIndication informing it that the channel is no longer
|
||
* valid.
|
||
*/
|
||
if ((m_fDisbandRequestPending == FALSE) && ValidateUserID(m_uidChannelManager))
|
||
{
|
||
PChannel lpChannel;
|
||
|
||
if (NULL != (lpChannel = m_pChannelList2->Find(m_uidChannelManager)))
|
||
{
|
||
CAttachment *pAtt = lpChannel->GetAttachment();
|
||
if (m_pAttachmentList->Find(pAtt) && pAtt->IsUserAttachment())
|
||
{
|
||
PUser pUser = (PUser) pAtt;
|
||
pUser->ChannelDisbandIndication(Channel_ID);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Clear the lists associated with this object. Note that this also
|
||
* prevents the base class destructor from issuing ChannelLeaveIndications
|
||
* to any local attachments in the joined attachment list (which would be
|
||
* inappropriate).
|
||
*/
|
||
m_AuthorizedUserList.Clear();
|
||
m_JoinedAttachmentList.Clear();
|
||
}
|
||
|
||
/*
|
||
* Channel_Type GetChannelType ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* Objects of this class are always private channels, so simply return
|
||
* PRIVATE_CHANNEL.
|
||
*/
|
||
Channel_Type PrivateChannel::GetChannelType ()
|
||
{
|
||
return (PRIVATE_CHANNEL);
|
||
}
|
||
|
||
/*
|
||
* BOOL IsValid ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* By convention, if the m_uidChannelManager is in the sub-tree of this
|
||
* provider OR if there are any users in the authorized user list, then
|
||
* the private channel is valid. Otherwise it is not, and can be deleted
|
||
* by the domain object.
|
||
*/
|
||
BOOL PrivateChannel::IsValid ()
|
||
{
|
||
UserID uid;
|
||
CUidList deletion_list;
|
||
|
||
/*
|
||
* Loop through the authorized user list making a list of those entries
|
||
* that are no longer valid.
|
||
*/
|
||
m_AuthorizedUserList.Reset();
|
||
while (NULL != (uid = m_AuthorizedUserList.Iterate()))
|
||
{
|
||
if (ValidateUserID(uid) == FALSE)
|
||
deletion_list.Append(uid);
|
||
}
|
||
|
||
/*
|
||
* Loop through the deletion list created above, deleting those user IDs
|
||
* that are no longer valid.
|
||
*/
|
||
deletion_list.Reset();
|
||
while (NULL != (uid = deletion_list.Iterate()))
|
||
{
|
||
m_AuthorizedUserList.Remove(uid);
|
||
}
|
||
|
||
/*
|
||
* If this is the Top Provider, then the channel manager should ALWAYS be
|
||
* in the sub-tree. If it is not, then this indicates that the channel
|
||
* manager has detached (willingly or otherwise). When this happens it
|
||
* is necessary to simulate a channel disband request (only if there are
|
||
* other admitted users who need to receive a channel expel indication).
|
||
*/
|
||
if ((m_pConnToTopProvider == NULL) &&
|
||
(ValidateUserID(m_uidChannelManager) == FALSE) &&
|
||
(m_AuthorizedUserList.IsEmpty() == FALSE))
|
||
{
|
||
TRACE_OUT (("PrivateChannel::IsValid: "
|
||
"simulating ChannelDisbandRequest"));
|
||
ChannelDisbandRequest(NULL, m_uidChannelManager, Channel_ID);
|
||
}
|
||
|
||
/*
|
||
* Check to see if the channel manager is in the sub-tree of this provider
|
||
* or if the authorized user list is not empty. If either is TRUE, then
|
||
* then the channel is still valid.
|
||
*/
|
||
return (ValidateUserID(m_uidChannelManager) || (m_AuthorizedUserList.IsEmpty() == FALSE));
|
||
}
|
||
|
||
/*
|
||
* CAttachment *GetAttachment ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* Return a pointer to the attachment leading to the channel manager.
|
||
*/
|
||
CAttachment *PrivateChannel::GetAttachment(void)
|
||
{
|
||
if (ValidateUserID(m_uidChannelManager))
|
||
{
|
||
PChannel lpChannel;
|
||
if (NULL != (lpChannel = m_pChannelList2->Find(m_uidChannelManager)))
|
||
{
|
||
return lpChannel->GetAttachment();
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
/*
|
||
* Void IssueMergeRequest ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* Issue a merge request for the information contained in this
|
||
* PrivateChannel object.
|
||
*/
|
||
Void PrivateChannel::IssueMergeRequest ()
|
||
{
|
||
ChannelAttributes channel_attributes;
|
||
CChannelAttributesList merge_channel_list;
|
||
CChannelIDList purge_channel_list;
|
||
|
||
if (m_pConnToTopProvider != NULL)
|
||
{
|
||
/*
|
||
* Fill in the fields of the channel attributes structure so that it
|
||
* accurately describes this channel. Then put the structure into the
|
||
* merge channel list.
|
||
*/
|
||
channel_attributes.channel_type = PRIVATE_CHANNEL;
|
||
if (m_JoinedAttachmentList.IsEmpty() )
|
||
channel_attributes.u.private_channel_attributes.joined = FALSE;
|
||
else
|
||
channel_attributes.u.private_channel_attributes.joined = TRUE;
|
||
channel_attributes.u.private_channel_attributes.channel_id = Channel_ID;
|
||
channel_attributes.u.private_channel_attributes.channel_manager = m_uidChannelManager;
|
||
channel_attributes.u.private_channel_attributes.admitted_list = &m_AuthorizedUserList;
|
||
|
||
merge_channel_list.Append(&channel_attributes);
|
||
|
||
/*
|
||
* Send the merge request to the indicated provider.
|
||
*/
|
||
m_pConnToTopProvider->MergeChannelsRequest(&merge_channel_list, &purge_channel_list);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Void ChannelJoinRequest ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This function overrides the base class implementation. The main
|
||
* difference is that this implementation only allows a user to join
|
||
* the private channel if it is either the channel manager or in the
|
||
* authorized user list.
|
||
*/
|
||
Void PrivateChannel::ChannelJoinRequest (
|
||
CAttachment *pOrigAtt,
|
||
UserID uidInitiator,
|
||
ChannelID channel_id)
|
||
{
|
||
/*
|
||
* See if the requesting user is either the channel manager or in the
|
||
* authorized user list.
|
||
*/
|
||
if ((uidInitiator == m_uidChannelManager) || m_AuthorizedUserList.Find(uidInitiator))
|
||
{
|
||
/*
|
||
* See if anyone is currently joined to the channel in this sub-tree
|
||
*/
|
||
if (m_JoinedAttachmentList.IsEmpty())
|
||
{
|
||
/*
|
||
* If this is the Top Provider, then this request can be handled
|
||
* locally.
|
||
*/
|
||
if (IsTopProvider())
|
||
{
|
||
/*
|
||
* There is no one in this sub-tree joined to the channel. It
|
||
* will therefore be necessary to add the originator to the
|
||
* attachment list.
|
||
*/
|
||
TRACE_OUT (("PrivateChannel::ChannelJoinRequest: "
|
||
"user %04X joining private channel = %04X",
|
||
(UINT) uidInitiator, (UINT) Channel_ID));
|
||
m_JoinedAttachmentList.Append(pOrigAtt);
|
||
|
||
/*
|
||
* Send a ChannelJoinConfirm downward to the originator.
|
||
*/
|
||
pOrigAtt->ChannelJoinConfirm(RESULT_SUCCESSFUL, uidInitiator, channel_id, Channel_ID);
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* This is not the Top Provider. Forward the join request
|
||
* upward to the Top Provider.
|
||
*/
|
||
TRACE_OUT (("PrivateChannel::ChannelJoinRequest: "
|
||
"forwarding join request to Top Provider"));
|
||
m_pConnToTopProvider->ChannelJoinRequest(uidInitiator, Channel_ID);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* There is at least one attachment joined to the channel, which means
|
||
* that we do not have to forward the join request upward (even if
|
||
* this is not the Top Provider). Now check to see if the requesting
|
||
* originator is already joined to the channel.
|
||
*/
|
||
else if (m_JoinedAttachmentList.Find(pOrigAtt) == FALSE)
|
||
{
|
||
/*
|
||
* The originator is not yet joined to the channel, so add it to
|
||
* the channel.
|
||
*/
|
||
TRACE_OUT (("PrivateChannel::ChannelJoinRequest: "
|
||
"user %04X joining private channel = %04X",
|
||
(UINT) uidInitiator, (UINT) Channel_ID));
|
||
m_JoinedAttachmentList.Append(pOrigAtt);
|
||
|
||
/*
|
||
* Send a ChannelJoinConfirm downward to the originator.
|
||
*/
|
||
pOrigAtt->ChannelJoinConfirm(RESULT_SUCCESSFUL, uidInitiator, channel_id, Channel_ID);
|
||
}
|
||
|
||
else
|
||
{
|
||
/*
|
||
* The originator is already joined to the channel. Go ahead and
|
||
* issue a successful channel join confirm.
|
||
*/
|
||
WARNING_OUT (("PrivateChannel::ChannelJoinRequest: "
|
||
"already joined to channel"));
|
||
pOrigAtt->ChannelJoinConfirm(RESULT_SUCCESSFUL, uidInitiator, channel_id, Channel_ID);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* Someone is trying to join a private channel that they are not
|
||
* admitted to. Reject the request without further processing.
|
||
*/
|
||
WARNING_OUT (("PrivateChannel::ChannelJoinRequest: "
|
||
"rejecting attempt to join private channel"));
|
||
pOrigAtt->ChannelJoinConfirm(RESULT_NOT_ADMITTED, uidInitiator, channel_id, 0);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Void ChannelDisbandRequest ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This MCS command is initially sent by a user that wishes to disband a
|
||
* private channel that it previously created. If the requesting user is
|
||
* the private channel manager, then the request will be processed. If
|
||
* this is not the Top Provider, the request will be forwarded upward.
|
||
*/
|
||
Void PrivateChannel::ChannelDisbandRequest (
|
||
CAttachment *,
|
||
UserID uidInitiator,
|
||
ChannelID)
|
||
{
|
||
CUidList user_id_list;
|
||
|
||
/*
|
||
* Check to see if the requesting user is the channel manager. Only
|
||
* process the request if it is.
|
||
*/
|
||
if (uidInitiator == m_uidChannelManager)
|
||
{
|
||
/*
|
||
* See if this is the Top Provider. If it is, then the request can
|
||
* be processed locally. Otherwise, pass the request upward toward
|
||
* the Top Provider.
|
||
*/
|
||
if (IsTopProvider())
|
||
{
|
||
CAttachmentList local_attachment_list;
|
||
CAttachmentList remote_attachment_list;
|
||
CAttachment *pAtt;
|
||
|
||
TRACE_OUT (("PrivateChannel::ChannelDisbandRequest: "
|
||
"disbanding channel = %04X", Channel_ID));
|
||
|
||
/*
|
||
* Go construct lists of the current unique local and remote
|
||
* attachments. These lists will be used to transmit the proper
|
||
* channel expel and channel disband indications.
|
||
*/
|
||
BuildAttachmentLists (&m_AuthorizedUserList, &local_attachment_list,
|
||
&remote_attachment_list);
|
||
|
||
/*
|
||
* It is also necessary to send the disband indication to the
|
||
* channel manager, if it is valid and in the sub-tree of this
|
||
* provider. Determine what attachment leads to the channel
|
||
* manager, and make sure that attachment is in the remote
|
||
* attachment list, if valid.
|
||
*/
|
||
if (ValidateUserID(m_uidChannelManager))
|
||
{
|
||
PChannel lpChannel;
|
||
if (NULL != (lpChannel = m_pChannelList2->Find(m_uidChannelManager)))
|
||
{
|
||
pAtt = lpChannel->GetAttachment();
|
||
if (m_pAttachmentList->Find(pAtt) && pAtt->IsConnAttachment())
|
||
{
|
||
if (remote_attachment_list.Find(pAtt) == FALSE)
|
||
{
|
||
remote_attachment_list.Append(pAtt);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("PrivateChannel::ChannelDisbandRequest: can't locate channel"));
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Loop through the local attachment list sending channel expel
|
||
* indications to each attachment contained therein.
|
||
*/
|
||
local_attachment_list.Reset();
|
||
while (NULL != (pAtt = local_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of
|
||
* the users that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&m_AuthorizedUserList, pAtt, &user_id_list);
|
||
|
||
/*
|
||
* Send the expel indication to the locally attached user.
|
||
*/
|
||
pAtt->ChannelExpelIndication(Channel_ID, &user_id_list);
|
||
}
|
||
|
||
/*
|
||
* Loop through the remote attachment list sending channel disband
|
||
* indications to each attachment contained therein.
|
||
*/
|
||
remote_attachment_list.Reset();
|
||
while (NULL != (pAtt = remote_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Send the disband indication to the remotely attached
|
||
* provider.
|
||
*/
|
||
pAtt->ChannelDisbandIndication(Channel_ID);
|
||
}
|
||
|
||
/*
|
||
* Set m_uidChannelManager to 0 and clear the authorized user list as
|
||
* an indicator that this private channel object is no longer
|
||
* valid, and cannot be used. The next time the domain object
|
||
* calls IsValid, it will return FALSE allowing the domain object
|
||
* to delete this object.
|
||
*/
|
||
m_uidChannelManager = 0;
|
||
m_AuthorizedUserList.Clear();
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* Set a flag indicating that a disband request has been sent
|
||
* upward. This flag will be used to prevent a disband indication
|
||
* from being sent to the channel manager as it flows back down
|
||
* the domain tree.
|
||
*/
|
||
m_fDisbandRequestPending = TRUE;
|
||
|
||
/*
|
||
* This is not the Top Provider, so forward the request toward
|
||
* the Top Provider. This will result in a channel disband
|
||
* indication at a future time.
|
||
*/
|
||
TRACE_OUT (("PrivateChannel::ChannelDisbandRequest: "
|
||
"forwarding request to Top Provider"));
|
||
m_pConnToTopProvider->ChannelDisbandRequest(uidInitiator, Channel_ID);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* Someone is trying to disband a private channel that they are not
|
||
* the channel manager for. Ignore the request.
|
||
*/
|
||
WARNING_OUT (("PrivateChannel::ChannelDisbandRequest: "
|
||
"ignoring request from non-channel manager"));
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Void ChannelDisbandIndication ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This MCS command is initially sent by the Top Provider when it decides
|
||
* to delete a private channel from the domain. It travels downward to
|
||
* all attachments and connections that contain an admitted user or the
|
||
* channel manager in their sub-tree.
|
||
*/
|
||
Void PrivateChannel::ChannelDisbandIndication (
|
||
ChannelID)
|
||
{
|
||
CAttachmentList local_attachment_list;
|
||
CAttachmentList remote_attachment_list;
|
||
CAttachment *pAtt;
|
||
CUidList user_id_list;
|
||
|
||
TRACE_OUT (("PrivateChannel::ChannelDisbandIndication: "
|
||
"disbanding channel = %04X", Channel_ID));
|
||
|
||
/*
|
||
* Build the lists of unique local and remote attachments. These lists
|
||
* will be used to issue the appropriate indications.
|
||
*/
|
||
BuildAttachmentLists (&m_AuthorizedUserList, &local_attachment_list,
|
||
&remote_attachment_list);
|
||
|
||
/*
|
||
* It is also necessary to send the disband indication to the channel
|
||
* manager, if it is valid and in the sub-tree of this provider.
|
||
* Determine what attachment leads to the channel manager, and make sure
|
||
* that attachment is in the remote attachment list, if valid.
|
||
*/
|
||
if (ValidateUserID(m_uidChannelManager))
|
||
{
|
||
PChannel lpChannel;
|
||
if (NULL != (lpChannel = m_pChannelList2->Find(m_uidChannelManager)))
|
||
{
|
||
pAtt = lpChannel->GetAttachment();
|
||
if ((m_fDisbandRequestPending == FALSE) ||
|
||
(m_pAttachmentList->Find(pAtt) && pAtt->IsConnAttachment()))
|
||
{
|
||
if (remote_attachment_list.Find(pAtt) == FALSE)
|
||
{
|
||
remote_attachment_list.Append(pAtt);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("PrivateChannel::ChannelDisbandIndication: can't locate channel"));
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Loop through the local attachment list sending channel expel indications
|
||
* to each attachment contained therein.
|
||
*/
|
||
local_attachment_list.Reset();
|
||
while (NULL != (pAtt = local_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of
|
||
* the users that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&m_AuthorizedUserList, pAtt, &user_id_list);
|
||
|
||
/*
|
||
* Send the expel indication to the locally attached user.
|
||
*/
|
||
pAtt->ChannelExpelIndication(Channel_ID, &user_id_list);
|
||
}
|
||
|
||
/*
|
||
* Loop through the remote attachment list sending channel disband
|
||
* indications to each attachment contained therein.
|
||
*/
|
||
remote_attachment_list.Reset();
|
||
while (NULL != (pAtt = remote_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Send the disband indication to the remotely attached provider.
|
||
*/
|
||
pAtt->ChannelDisbandIndication(Channel_ID);
|
||
}
|
||
|
||
/*
|
||
* Set m_uidChannelManager to 0 and clear the authorized user list as an
|
||
* indicator that this private channel object is no longer valid, and
|
||
* cannot be used. The next time the domain object calls IsValid, it will
|
||
* return FALSE allowing the domain object to delete this object.
|
||
*/
|
||
m_uidChannelManager = 0;
|
||
m_AuthorizedUserList.Clear();
|
||
}
|
||
|
||
/*
|
||
* Void ChannelAdmitRequest ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This MCS command is initially sent by the manager of a private channel
|
||
* when it wishes to expand the authorized user list of that channel. If
|
||
* this is the Top Provider, then the request can be handled locally.
|
||
* Otherwise, it must be forwarded upward to the Top Provider.
|
||
*/
|
||
Void PrivateChannel::ChannelAdmitRequest (
|
||
CAttachment *,
|
||
UserID uidInitiator,
|
||
ChannelID,
|
||
CUidList *user_id_list)
|
||
{
|
||
UserID uid;
|
||
CUidList admitted_id_list;
|
||
CUidList user_id_subset;
|
||
|
||
/*
|
||
* Check to see if the requesting user is the channel manager. Only
|
||
* process the request if it is.
|
||
*/
|
||
if (uidInitiator == m_uidChannelManager)
|
||
{
|
||
/*
|
||
* See if this is the Top Provider. If it is, then the request can
|
||
* be processed locally. Otherwise, pass the request upward toward
|
||
* the Top Provider.
|
||
*/
|
||
if (IsTopProvider())
|
||
{
|
||
CAttachmentList local_attachment_list;
|
||
CAttachmentList remote_attachment_list;
|
||
CAttachment *pAtt;
|
||
|
||
TRACE_OUT (("PrivateChannel::ChannelAdmitRequest: "
|
||
"admitting users to channel = %04X", Channel_ID));
|
||
|
||
/*
|
||
* Iterate through the list of users to be admitted, adding all
|
||
* valid users to the local authorized user list.
|
||
*/
|
||
user_id_list->Reset();
|
||
while (NULL != (uid = user_id_list->Iterate()))
|
||
{
|
||
/*
|
||
* Make sure that the user ID corresponds to a valid user in
|
||
* the domain.
|
||
*/
|
||
if (ValidateUserID(uid))
|
||
{
|
||
/*
|
||
* If the user is not already in the authorized user list,
|
||
* then add it.
|
||
*/
|
||
if (m_AuthorizedUserList.Find(uid) == FALSE)
|
||
{
|
||
m_AuthorizedUserList.Append(uid);
|
||
admitted_id_list.Append(uid);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Build lists of unique attachments which can then be used to
|
||
* issue the appropriate admit indications. This prevents the
|
||
* transmission of an admit indication to the same attachment more
|
||
* than once.
|
||
*/
|
||
BuildAttachmentLists (&admitted_id_list, &local_attachment_list,
|
||
&remote_attachment_list);
|
||
|
||
/*
|
||
* Iterate through the local attachment list issuing an admit
|
||
* indication to each attachment contained therein.
|
||
*/
|
||
local_attachment_list.Reset();
|
||
while (NULL != (pAtt = local_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of
|
||
* the users that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&admitted_id_list, pAtt, &user_id_subset);
|
||
|
||
/*
|
||
* Send the admit indication to the named attachment.
|
||
*/
|
||
pAtt->ChannelAdmitIndication(uidInitiator, Channel_ID, &user_id_subset);
|
||
}
|
||
|
||
/*
|
||
* Iterate through the remote attachment list issuing an admit
|
||
* indication to each attachment contained therein.
|
||
*/
|
||
remote_attachment_list.Reset();
|
||
while (NULL != (pAtt = remote_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of
|
||
* the users that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&admitted_id_list, pAtt, &user_id_subset);
|
||
|
||
/*
|
||
* Send the admit indication to the named attachment.
|
||
*/
|
||
pAtt->ChannelAdmitIndication(uidInitiator, Channel_ID, &user_id_subset);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* This is not the Top Provider, so forward the request toward
|
||
* the Top Provider. This will result in a channel admit
|
||
* indication at a future time.
|
||
*/
|
||
TRACE_OUT (("PrivateChannel::ChannelAdmitRequest: "
|
||
"forwarding request to Top Provider"));
|
||
m_pConnToTopProvider->ChannelAdmitRequest(uidInitiator, Channel_ID, user_id_list);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* Someone is trying to admit users to a private channel that they are
|
||
* not the channel manager for. Ignore the request.
|
||
*/
|
||
WARNING_OUT (("PrivateChannel::ChannelAdmitRequest: "
|
||
"ignoring request from non-channel manager"));
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Void ChannelAdmitIndication ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This MCS command is initially sent by the Top Provider when it receives
|
||
* a channel admit indication from the manager of a private channel. This
|
||
* indication is broadcast downward to all providers that contain an
|
||
* admitted user somewhere in their sub-tree. A side-effect of this
|
||
* indication is that a private channel will be created in the information
|
||
* base if one does not already exist.
|
||
*/
|
||
Void PrivateChannel::ChannelAdmitIndication (
|
||
PConnection,
|
||
UserID uidInitiator,
|
||
ChannelID,
|
||
CUidList *user_id_list)
|
||
{
|
||
UserID uid;
|
||
CUidList admitted_id_list;
|
||
CAttachmentList local_attachment_list;
|
||
CAttachmentList remote_attachment_list;
|
||
CAttachment *pAtt;
|
||
CUidList user_id_subset;
|
||
|
||
TRACE_OUT (("PrivateChannel::ChannelAdmitIndication: "
|
||
"admitting users to channel = %04X", (UINT) Channel_ID));
|
||
|
||
/*
|
||
* Iterate through the list of users to be admitted, adding all
|
||
* valid users to the local authorized user list.
|
||
*/
|
||
user_id_list->Reset();
|
||
while (NULL != (uid = user_id_list->Iterate()))
|
||
{
|
||
/*
|
||
* Make sure that the user ID corresponds to a valid user in
|
||
* the domain.
|
||
*/
|
||
if (ValidateUserID(uid))
|
||
{
|
||
/*
|
||
* If the user is not already in the authorized user list,
|
||
* then add it.
|
||
*/
|
||
if (m_AuthorizedUserList.Find(uid) == FALSE)
|
||
{
|
||
m_AuthorizedUserList.Append(uid);
|
||
admitted_id_list.Append(uid);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Build lists of unique attachments which can then be used to
|
||
* issue the appropriate admit indications. This prevents the
|
||
* transmission of an admit indication to the same attachment more
|
||
* than once.
|
||
*/
|
||
BuildAttachmentLists (&admitted_id_list, &local_attachment_list,
|
||
&remote_attachment_list);
|
||
|
||
/*
|
||
* Iterate through the local attachment list issuing an admit
|
||
* indication to each attachment contained therein.
|
||
*/
|
||
local_attachment_list.Reset();
|
||
while (NULL != (pAtt = local_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of
|
||
* the users that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&admitted_id_list, pAtt, &user_id_subset);
|
||
|
||
/*
|
||
* Send the admit indication to the named attachment.
|
||
*/
|
||
pAtt->ChannelAdmitIndication(uidInitiator, Channel_ID, &user_id_subset);
|
||
}
|
||
|
||
/*
|
||
* Iterate through the remote attachment list issuing an admit
|
||
* indication to each attachment contained therein.
|
||
*/
|
||
remote_attachment_list.Reset();
|
||
while (NULL != (pAtt = remote_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of
|
||
* the users that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&admitted_id_list, pAtt, &user_id_subset);
|
||
|
||
/*
|
||
* Send the admit indication to the named attachment.
|
||
*/
|
||
pAtt->ChannelAdmitIndication(uidInitiator, Channel_ID, &user_id_subset);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Void ChannelExpelRequest ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This MCS command is initially sent by the manager of a private channel
|
||
* when it wishes to shrink the authorized user list of that channel. If
|
||
* the channel is in the local information base, the request is sent to it.
|
||
* Otherwise, the request is ignored.
|
||
*/
|
||
Void PrivateChannel::ChannelExpelRequest (
|
||
CAttachment *,
|
||
UserID uidInitiator,
|
||
ChannelID,
|
||
CUidList *user_id_list)
|
||
{
|
||
UserID uid;
|
||
CUidList expelled_id_list;
|
||
CUidList user_id_subset;
|
||
|
||
/*
|
||
* Check to see if the requesting user is the channel manager. Only
|
||
* process the request if it is.
|
||
*/
|
||
if (uidInitiator == m_uidChannelManager)
|
||
{
|
||
/*
|
||
* See if this is the Top Provider. If it is, then the request can
|
||
* be processed locally. Otherwise, pass the request upward toward
|
||
* the Top Provider.
|
||
*/
|
||
if (m_pConnToTopProvider == NULL)
|
||
{
|
||
CAttachmentList local_attachment_list;
|
||
CAttachmentList remote_attachment_list;
|
||
CAttachment *pAtt;
|
||
|
||
TRACE_OUT (("PrivateChannel::ChannelExpelRequest: "
|
||
"expelling users from channel = %04X", Channel_ID));
|
||
|
||
/*
|
||
* Iterate through the list of users to be expelled, removing all
|
||
* valid users from the local authorized user list.
|
||
*/
|
||
user_id_list->Reset();
|
||
while (NULL != (uid = user_id_list->Iterate()))
|
||
{
|
||
/*
|
||
* If the user is in the authorized user list, then remove it.
|
||
*/
|
||
if (m_AuthorizedUserList.Find(uid))
|
||
{
|
||
m_AuthorizedUserList.Remove(uid);
|
||
expelled_id_list.Append(uid);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Build lists of unique attachments which can then be used to
|
||
* issue the appropriate expel indications. This prevents the
|
||
* transmission of an expel indication to the same attachment more
|
||
* than once.
|
||
*/
|
||
BuildAttachmentLists (&expelled_id_list, &local_attachment_list,
|
||
&remote_attachment_list);
|
||
|
||
/*
|
||
* Iterate through the local attachment list issuing an expel
|
||
* indication to each attachment contained therein.
|
||
*/
|
||
local_attachment_list.Reset();
|
||
while (NULL != (pAtt = local_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of
|
||
* the users that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&expelled_id_list, pAtt, &user_id_subset);
|
||
|
||
/*
|
||
* Send the expel indication to the named attachment.
|
||
*/
|
||
pAtt->ChannelExpelIndication(Channel_ID, &user_id_subset);
|
||
|
||
/*
|
||
* Since this is a locally attached user, it is necessary to
|
||
* simulate a channel leave request from the user, indicating
|
||
* the fact that it can no longer use the channel.
|
||
*/
|
||
ChannelLeaveRequest(pAtt, (CChannelIDList *) &user_id_subset);
|
||
}
|
||
|
||
/*
|
||
* Iterate through the remote attachment list issuing an expel
|
||
* indication to each attachment contained therein.
|
||
*/
|
||
remote_attachment_list.Reset();
|
||
while (NULL != (pAtt = remote_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of
|
||
* the users that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&expelled_id_list, pAtt, &user_id_subset);
|
||
|
||
/*
|
||
* Send the expel indication to the named attachment.
|
||
*/
|
||
pAtt->ChannelExpelIndication(Channel_ID, &user_id_subset);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* This is not the Top Provider, so forward the request toward
|
||
* the Top Provider. This will result in a channel expel
|
||
* indication at a future time.
|
||
*/
|
||
TRACE_OUT (("PrivateChannel::ChannelExpelRequest: "
|
||
"forwarding request to Top Provider"));
|
||
m_pConnToTopProvider->ChannelExpelRequest(uidInitiator, Channel_ID, user_id_list);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* Someone is trying to admit users to a private channel that they are
|
||
* not the channel manager for. Ignore the request.
|
||
*/
|
||
WARNING_OUT (("PrivateChannel::ChannelExpelRequest: "
|
||
"ignoring request from non-channel manager"));
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Void ChannelExpelIndication ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This MCS command is initially sent by the Top Provider when it receives
|
||
* a request from the manager of a private channel to reduce the
|
||
* authorized user list. It travels downward to all attachments and
|
||
* connections that contain an admitted user or the channel manager in
|
||
* their sub-tree.
|
||
*/
|
||
Void PrivateChannel::ChannelExpelIndication (
|
||
PConnection,
|
||
ChannelID,
|
||
CUidList *user_id_list)
|
||
{
|
||
UserID uid;
|
||
CUidList expelled_id_list;
|
||
CAttachmentList local_attachment_list;
|
||
CAttachmentList remote_attachment_list;
|
||
CAttachment *pAtt;
|
||
CUidList user_id_subset;
|
||
|
||
TRACE_OUT (("PrivateChannel::ChannelExpelIndication: "
|
||
"expelling users from channel = %04X", Channel_ID));
|
||
|
||
/*
|
||
* Iterate through the list of users to be expelled, removing all
|
||
* valid users from the local authorized user list.
|
||
*/
|
||
user_id_list->Reset();
|
||
while (NULL != (uid = user_id_list->Iterate()))
|
||
{
|
||
/*
|
||
* If the user is in the authorized user list, then remove it.
|
||
*/
|
||
if (m_AuthorizedUserList.Find(uid))
|
||
{
|
||
m_AuthorizedUserList.Remove(uid);
|
||
expelled_id_list.Append(uid);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Build lists of unique attachments which can then be used to
|
||
* issue the appropriate expel indications. This prevents the
|
||
* transmission of an expel indication to the same attachment more
|
||
* than once.
|
||
*/
|
||
BuildAttachmentLists (&expelled_id_list, &local_attachment_list,
|
||
&remote_attachment_list);
|
||
|
||
/*
|
||
* Iterate through the local attachment list issuing an expel
|
||
* indication to each attachment contained therein.
|
||
*/
|
||
local_attachment_list.Reset();
|
||
while (NULL != (pAtt = local_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of
|
||
* the users that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&expelled_id_list, pAtt, &user_id_subset);
|
||
|
||
/*
|
||
* Send the expel indication to the named attachment.
|
||
*/
|
||
pAtt->ChannelExpelIndication(Channel_ID, &user_id_subset);
|
||
|
||
/*
|
||
* Since this is a locally attached user, it is necessary to
|
||
* simulate a channel leave request from the user, indicating
|
||
* the fact that it can no longer use the channel.
|
||
*/
|
||
ChannelLeaveRequest(pAtt, (CChannelIDList *) &user_id_subset);
|
||
}
|
||
|
||
/*
|
||
* Iterate through the remote attachment list issuing an expel
|
||
* indication to each attachment contained therein.
|
||
*/
|
||
remote_attachment_list.Reset();
|
||
while (NULL != (pAtt = remote_attachment_list.Iterate()))
|
||
{
|
||
/*
|
||
* Get the next attachment from the list and build a list of
|
||
* the users that lie in the direction of that attachment.
|
||
*/
|
||
BuildUserIDList(&expelled_id_list, pAtt, &user_id_subset);
|
||
|
||
/*
|
||
* Send the expel indication to the named attachment.
|
||
*/
|
||
pAtt->ChannelExpelIndication(Channel_ID, &user_id_subset);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Void SendDataRequest ()
|
||
*
|
||
* Public
|
||
*
|
||
* Functional Description:
|
||
* This MCS command is initially sent by a user that wishes to send data
|
||
* to other users who are joined to a specified channel. This routine
|
||
* is executed in the case that it is a private channel. It verifies
|
||
* that the user is authorized to use the channel before allowing the data
|
||
* to be sent.
|
||
*/
|
||
Void PrivateChannel::SendDataRequest (
|
||
CAttachment *pOrigAtt,
|
||
UINT type,
|
||
PDataPacket data_packet)
|
||
{
|
||
UserID uidInitiator;
|
||
|
||
uidInitiator = data_packet->GetInitiator();
|
||
if ((uidInitiator == m_uidChannelManager) || m_AuthorizedUserList.Find(uidInitiator))
|
||
{
|
||
/*
|
||
* The channel usage is authorized, so forward the request to the
|
||
* base class implementation for processing.
|
||
*/
|
||
Channel::SendDataRequest(pOrigAtt, type, data_packet);
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* Someone is trying to send data on a private channel that they are
|
||
* not authorized to use. Ignore the request.
|
||
*/
|
||
WARNING_OUT (("PrivateChannel::SendDataRequest: "
|
||
"ignoring request from non-authorized user"));
|
||
}
|
||
}
|
||
|
||
/*
|
||
* BOOL ValidateUserID ()
|
||
*
|
||
* Private
|
||
*
|
||
* Functional Description:
|
||
* This function is called whenever another member function of this class
|
||
* wants to check and see if a specified user is still valid in the
|
||
* domain channel list.
|
||
*
|
||
* Formal Parameters:
|
||
* user_id (i)
|
||
* This is the ID of the user being checked out.
|
||
*
|
||
* Return Value:
|
||
* TRUE if the user is valid. FALSE otherwise.
|
||
*
|
||
* Side Effects:
|
||
* None.
|
||
*/
|
||
BOOL PrivateChannel::ValidateUserID (
|
||
UserID user_id)
|
||
{
|
||
PChannel channel;
|
||
|
||
/*
|
||
* First check to see if the user ID is in the channel list at all. This
|
||
* prevents an attempt to read an invalid entry from the dictionary.
|
||
*/
|
||
if (NULL != (channel = m_pChannelList2->Find(user_id)))
|
||
{
|
||
/*
|
||
* We know that the ID is in the dictionary, but we don't know for sure
|
||
* whether or not it is a user ID channel. So check this. If it is a
|
||
* user channel, then set the valid flag to TRUE.
|
||
*/
|
||
if (channel->GetChannelType () == USER_CHANNEL)
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/*
|
||
* Void BuildAttachmentLists ()
|
||
*
|
||
* Private
|
||
*
|
||
* Functional Description:
|
||
* This function is called upon to build a list of unique attachments that
|
||
* lead to the users in the specified list. It builds two attachment
|
||
* lists. The first has an entry for each unique local attachment. The
|
||
* second for each remote attachment. The key to each list is the
|
||
* attachment.
|
||
*
|
||
* Formal Parameters:
|
||
* user_id_list (i)
|
||
* This is the list of users for which the list is to be built.
|
||
* local_attachment_list (i)
|
||
* This is the dictionary that is to contain the list of unique
|
||
* local attachments.
|
||
* remote_attachment_list (i)
|
||
* This is the dictionary that is to contain the list of unique
|
||
* remote attachments.
|
||
*
|
||
* Return Value:
|
||
* None.
|
||
*
|
||
* Side Effects:
|
||
* None.
|
||
*/
|
||
Void PrivateChannel::BuildAttachmentLists (
|
||
CUidList *user_id_list,
|
||
CAttachmentList *local_attachment_list,
|
||
CAttachmentList *remote_attachment_list)
|
||
{
|
||
UserID uid;
|
||
|
||
/*
|
||
* Loop through the passed in user ID list building a dictionary of local
|
||
* attachments (those leading to locally attached users) and a dictionary
|
||
* of remote attachments (those leading to remotely connected providers).
|
||
* These dictionaries will be used by this provider to issue various
|
||
* indications downward, without sending multiple indications to the same
|
||
* attachment.
|
||
*/
|
||
user_id_list->Reset();
|
||
while (NULL != (uid = user_id_list->Iterate()))
|
||
{
|
||
/*
|
||
* Check to see if the user ID refers to a valid user in the sub-tree
|
||
* of this provider.
|
||
*/
|
||
if (ValidateUserID(uid))
|
||
{
|
||
PChannel lpChannel;
|
||
/*
|
||
* Determine which attachment leads to the user in question.
|
||
*/
|
||
if (NULL != (lpChannel = m_pChannelList2->Find(uid)))
|
||
{
|
||
CAttachment *pAtt = lpChannel->GetAttachment();
|
||
/*
|
||
* This module builds separate lists for those users that are
|
||
* attached locally and those attached remotely.
|
||
*/
|
||
if (m_pAttachmentList->Find(pAtt))
|
||
{
|
||
if (pAtt->IsUserAttachment())
|
||
{
|
||
/*
|
||
* This attachment is a local one (meaning that it leads to a
|
||
* locally attached user, rather than another MCS provider).
|
||
* Check to see if this attachment has already been put into
|
||
* the dictionary while processing a previous user ID.
|
||
*/
|
||
if (local_attachment_list->Find(pAtt) == FALSE)
|
||
local_attachment_list->Append(pAtt);
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* This attachment is a remote one (meaning that it leads to
|
||
* another MCS provider, rather than a locally attached user).
|
||
* Check to see if this attachment has already been put into
|
||
* the dictionary while processing a previous user ID.
|
||
*/
|
||
if (remote_attachment_list->Find(pAtt) == FALSE)
|
||
remote_attachment_list->Append(pAtt);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("PrivateChannel::BuildAttachmentLists: can't find this attachment=0x%p", pAtt));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("PrivateChannel::BuildAttachmentLists: can't locate channel"));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* This user ID does not correspond to a valid user in the sub-tree
|
||
* of this provider. Therefore, discard the ID.
|
||
*/
|
||
ERROR_OUT (("PrivateChannel::BuildAttachmentLists: "
|
||
"ERROR - user ID not valid"));
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Void BuildUserIDList ()
|
||
*
|
||
* Private
|
||
*
|
||
* Functional Description:
|
||
* This function is called upon to build a list of all users in the
|
||
* specified list that are in the direction of the specified attachment.
|
||
*
|
||
* Formal Parameters:
|
||
* user_id_list (i)
|
||
* This is the list of users for which the list is to be built.
|
||
* attachment (i)
|
||
* This is the attachment that the caller wishes to have a list of
|
||
* user IDs for.
|
||
* user_id_subset (o)
|
||
* This is the subset of the passed in user IDs that are in the
|
||
* direction of the specified attachment.
|
||
*
|
||
* Return Value:
|
||
* None.
|
||
*
|
||
* Side Effects:
|
||
* None.
|
||
*/
|
||
Void PrivateChannel::BuildUserIDList (
|
||
CUidList *user_id_list,
|
||
CAttachment *pAtt,
|
||
CUidList *user_id_subset)
|
||
{
|
||
UserID uid;
|
||
|
||
/*
|
||
* Clear out the subset list, so that we start fresh.
|
||
*/
|
||
user_id_subset->Clear();
|
||
|
||
/*
|
||
* Loop through the specified user list, checking to see which users
|
||
* lie in the direction of the specified attachment.
|
||
*/
|
||
user_id_list->Reset();
|
||
while (NULL != (uid = user_id_list->Iterate()))
|
||
{
|
||
/*
|
||
* Check to see if the user ID refers to a valid user in the sub-tree
|
||
* of this provider.
|
||
*/
|
||
if (ValidateUserID(uid))
|
||
{
|
||
PChannel lpChannel;
|
||
/*
|
||
* Check to see if this user is the direction of the specified
|
||
* attachment. If it is, then put it into the user ID subset that
|
||
* we are building.
|
||
*/
|
||
if (NULL != (lpChannel = m_pChannelList2->Find(uid)))
|
||
{
|
||
if (lpChannel->GetAttachment () == pAtt)
|
||
user_id_subset->Append(uid);
|
||
}
|
||
else
|
||
{
|
||
ERROR_OUT(("PrivateChannel::BuildUserIDList: can't locate channel"));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
* This user ID does not correspond to a valid user in the sub-tree
|
||
* of this provider. Therefore, discard the ID.
|
||
*/
|
||
ERROR_OUT (("PrivateChannel::BuildUserIDList: "
|
||
"ERROR - user ID not valid"));
|
||
}
|
||
}
|
||
}
|
||
|
||
|