#include "precomp.h" DEBUG_FILEZONE(ZONE_T120_MCSNC); /* * channel.cpp * * Copyright (c) 1993 - 1995 by DataBeam Corporation, Lexington, KY * * Abstract: * This is the implementation file for class Channel. It contains the * code necessary to implement static and assigned channels in the * MCS system. * * This is also to be the base class for other classes that represent * channels in the system. Therefore, there will be times when some * of these member functions are overridden to provide different * behavior. These derived classes may or may not invoke the operations * in this class. * * Protected Instance Variables: * Channel_ID * This instance variable contains the channel ID that is associated * with a given instance of this class. * m_pDomain * This is a pointer to the local provider. Note that no messages * ever sent to this provider. This pointer is used as a parameter * whenever other MCS commands are issued, since this class acts on * behalf of the local provider. * m_pConnToTopProvider * This is a pointer to the Top Provider. This is used when it is * necessary to send requests to the Top Provider. * m_pChannelList2 * This is a reference to the channel list that is owned and maintained * by the parent domain. It is NEVER modified by this class. * m_JoinedAttachmentList * This is a container that contains the list of attachments currently * joined to the channel. * * Private Member Functions: * None. * * Caveats: * None. * * Author: * James P. Galvin, Jr. */ /* * Channel () * * Public * * Functional Description: * This is the primary constructor for the Channel class. It simply * initializes the instance variable to valid values. It leaves the * attachment list empty. */ Channel::Channel ( ChannelID channel_id, PDomain local_provider, PConnection top_provider, CChannelList2 *channel_list, CAttachmentList *attachment_list) : Channel_ID (channel_id), m_pDomain(local_provider), m_pConnToTopProvider(top_provider), m_pChannelList2(channel_list), m_pAttachmentList(attachment_list) { } /* * Channel () * * Public * * Functional Description: * This version of the constructor is used to create a Channel object * with an existing attachment. It is otherwise the same as the primary * constructor above. */ Channel::Channel ( ChannelID channel_id, PDomain local_provider, PConnection top_provider, CChannelList2 *channel_list, CAttachmentList *attachment_list, PConnection pConn) : Channel_ID (channel_id), m_pDomain(local_provider), m_pConnToTopProvider(top_provider), m_pChannelList2(channel_list), m_pAttachmentList(attachment_list) { /* * Add the initial attachment to the attachment list. */ if (pConn != NULL) m_JoinedAttachmentList.Append(pConn); } /* * ~Channel () * * Public * * Functional Description: * If the object is destroyed before the attachment list is empty, it is * the responsibility of this destructor to issue channel leave indications * to all locally joined users. */ Channel::~Channel () { CAttachment *pAtt; //DWORD type; /* * Iterate through the joined attachment list sending channel leave * indications to all users who are locally attached to this provider. */ m_JoinedAttachmentList.Reset(); while (NULL != (pAtt = m_JoinedAttachmentList.Iterate())) { if (m_pAttachmentList->Find(pAtt) && pAtt->IsUserAttachment()) { PUser pUser = (PUser) pAtt; pUser->ChannelLeaveIndication(REASON_CHANNEL_PURGED, Channel_ID); } } } /* * Channel_Type GetChannelType () * * Public * * Functional Description: * This function returns the type of the channel. For a Channel object, * this will always be either STATIC_CHANNEL or ASSIGNED_CHANNEL, depending * on the value of the channel ID. */ Channel_Type Channel::GetChannelType () { /* * T.125 specifies that channels from 1 to 1000 are static. The rest * are dynamic (for this type of Channel object, that equates to * assigned). */ return (Channel_ID <= 1000) ? STATIC_CHANNEL : ASSIGNED_CHANNEL; } /* * BOOL IsValid () * * Public * * Functional Description: * This function returns TRUE if the Channel object is still valid, or * FALSE if it is ready to be deleted. */ BOOL Channel::IsValid () { CAttachment *pAtt; CAttachmentList deletion_list; /* * Iterate through the joined attachment list, building a list of those * attachments in the list that are no longer valid. */ m_JoinedAttachmentList.Reset(); while (NULL != (pAtt = m_JoinedAttachmentList.Iterate())) { if (m_pAttachmentList->Find(pAtt) == FALSE) deletion_list.Append(pAtt); } /* * Iterate through the deletion list, removing all those attachments that * were found to be invalid above. */ while (NULL != (pAtt = deletion_list.Get())) { m_JoinedAttachmentList.Remove(pAtt); } return (! m_JoinedAttachmentList.IsEmpty()); } /* * Void IssueMergeRequest () * * Public * * Functional Description: * This member function is used to cause the Channel object to issue a * merge request to the pending top provier. */ Void Channel::IssueMergeRequest () { Channel_Type channel_type; 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_type = GetChannelType (); channel_attributes.channel_type = channel_type; switch (channel_type) { case STATIC_CHANNEL: channel_attributes.u.static_channel_attributes.channel_id = Channel_ID; break; case ASSIGNED_CHANNEL: channel_attributes.u.assigned_channel_attributes.channel_id = Channel_ID; break; } 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 is used to add a new attachment to the attachment list. * If the user ID is valid, this routine will also issue an automatic * join confirm to the user. */ Void Channel::ChannelJoinRequest ( CAttachment *pOrigAtt, UserID uidInitiator, ChannelID channel_id) { /* * Make sure the attachment isn't already in the list before adding it. */ if (m_JoinedAttachmentList.Find(pOrigAtt) == FALSE) { TRACE_OUT (("Channel::ChannelJoinRequest: " "user %04X joining channel %04X", (UINT) uidInitiator, (UINT) Channel_ID)); m_JoinedAttachmentList.Append(pOrigAtt); } /* * If the user ID is valid, then send a join confirm to the initiating * attachment. Note that setting the user ID to 0 is a way of disabling * this behavior. This is sometimes useful when adding attachments during * a domain merge. */ if (uidInitiator != 0) { pOrigAtt->ChannelJoinConfirm(RESULT_SUCCESSFUL, uidInitiator, channel_id, Channel_ID); } } /* * Void ChannelJoinConfirm () * * Public * * Functional Description: * This function performs the same operation as JoinRequest above. */ Void Channel::ChannelJoinConfirm ( CAttachment *pOrigAtt, Result, UserID uidInitiator, ChannelID requested_id, ChannelID) { /* * Make sure the attachment isn't already in the list before adding it. */ if (m_JoinedAttachmentList.Find(pOrigAtt) == FALSE) { TRACE_OUT (("Channel::ChannelJoinConfirm: " "user %04X joining channel %04X", (UINT) uidInitiator, (UINT) Channel_ID)); m_JoinedAttachmentList.Append(pOrigAtt); } /* * Send a join confirm to the initiating attachment. */ pOrigAtt->ChannelJoinConfirm(RESULT_SUCCESSFUL, uidInitiator, requested_id, Channel_ID); } /* * Void ChannelLeaveRequest () * * Public * * Functional Description: * This function is used to remove an attachment from the attachment list. * A leave request will also be issued upward (unless this is the Top * Provider). */ Void Channel::ChannelLeaveRequest ( CAttachment *pOrigAtt, CChannelIDList *) { CChannelIDList channel_leave_list; /* * Make sure the attachment is in the list before trying to remove it. */ if (m_JoinedAttachmentList.Remove(pOrigAtt)) { TRACE_OUT (("Channel::ChannelLeaveRequest: leaving channel %04X", Channel_ID)); /* * Remove the attachment from the list. */ /* * If this results in an empty list, then we have more work to do. */ if (m_JoinedAttachmentList.IsEmpty()) { /* * If this is not the Top Provider, send a leave request upward * to the Top Provider. */ if (! IsTopProvider()) { TRACE_OUT (("Channel::ChannelLeaveRequest: " "sending ChannelLeaveRequest to Top Provider")); channel_leave_list.Append(Channel_ID); m_pConnToTopProvider->ChannelLeaveRequest(&channel_leave_list); } } } } /* * Void SendDataRequest () * * Public * * Functional Description: * This function is used to send data through the channel. */ Void Channel::SendDataRequest ( CAttachment *pOrigAtt, UINT type, PDataPacket data_packet) { CAttachment *pAtt; ASSERT (Channel_ID == data_packet->GetChannelID()); /* * If this is not the Top Provider, forward the data upward. */ if (m_pConnToTopProvider != NULL) m_pConnToTopProvider->SendDataRequest(data_packet); /* * Iterate through the attachment list, sending the data to all * the attachments (except for one from whence the data came). */ m_JoinedAttachmentList.Reset(); while (NULL != (pAtt = m_JoinedAttachmentList.Iterate())) { if ((pAtt != pOrigAtt) || (type != MCS_SEND_DATA_INDICATION)) { pAtt->SendDataIndication(type, data_packet); } } } /* * Void SendDataIndication () * * Public * * Functional Description: * This function is used to send data through the channel. */ Void Channel::SendDataIndication ( PConnection, UINT type, PDataPacket data_packet) { CAttachment *pAtt; ASSERT (Channel_ID == data_packet->GetChannelID()); /* * Iterate through the attachment list, sending the data to all * the attachments. */ m_JoinedAttachmentList.Reset(); while (NULL != (pAtt = m_JoinedAttachmentList.Iterate())) { pAtt->SendDataIndication(type, data_packet); } }