mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1477 lines
44 KiB
1477 lines
44 KiB
#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"));
|
|
}
|
|
}
|
|
}
|
|
|
|
|