// srvrdoc.cpp : implementation of the CServerDoc class // // This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #include "chatsrvr.h" #include "srvrdoc.h" #include "srvrvw.h" #include "msg.h" #include "dialogs.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CServerDoc IMPLEMENT_DYNCREATE(CServerDoc, CDocument) BEGIN_MESSAGE_MAP(CServerDoc, CDocument) //{{AFX_MSG_MAP(CServerDoc) //}}AFX_MSG_MAP ON_UPDATE_COMMAND_UI(ID_MESSAGES, OnUpdateMessages) ON_UPDATE_COMMAND_UI(ID_CONNECTIONS, OnUpdateConnections) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CServerDoc construction/destruction CServerDoc::CServerDoc() { m_pSocket = NULL; } CServerDoc::~CServerDoc() { delete m_pSocket; } BOOL CServerDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; CDiscussionDlg Dialog; if (Dialog.DoModal() == IDOK) { m_pSocket = new CListeningSocket(this); if (m_pSocket->Create(Dialog.m_nPort+700)) { if (m_pSocket->Listen()) return TRUE; } } return FALSE; } void CServerDoc::DeleteContents() { delete m_pSocket; m_pSocket = NULL; CString temp; if (temp.LoadString(IDS_SERVERSHUTDOWN)) m_msgList.AddTail(temp); while(!m_connectionList.IsEmpty()) { CClientSocket* pSocket = (CClientSocket*)m_connectionList.RemoveHead(); CMsg* pMsg = AssembleMsg(pSocket); pMsg->m_bClose = TRUE; SendMsg(pSocket, pMsg); if (!pSocket->IsAborted()) { pSocket->ShutDown(); BYTE Buffer[50]; while (pSocket->Receive(Buffer,50) > 0); delete pSocket; } } m_msgList.RemoveAll(); if (!m_viewList.IsEmpty()) ((CEditView*)m_viewList.GetHead())->SetWindowText(_T("")); CDocument::DeleteContents(); } ///////////////////////////////////////////////////////////////////////////// // CServerDoc serialization void CServerDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // CEditView contains an edit control which handles all serialization ((CEditView*)m_viewList.GetHead())->SerializeRaw(ar); } } ///////////////////////////////////////////////////////////////////////////// // CServerDoc diagnostics #ifdef _DEBUG void CServerDoc::AssertValid() const { CDocument::AssertValid(); } void CServerDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CServerDoc Operations void CServerDoc::UpdateClients() { for(POSITION pos = m_connectionList.GetHeadPosition(); pos != NULL;) { CClientSocket* pSocket = (CClientSocket*)m_connectionList.GetNext(pos); CMsg* pMsg = AssembleMsg(pSocket); if (pMsg != NULL) SendMsg(pSocket, pMsg); } } void CServerDoc::ProcessPendingAccept() { CClientSocket* pSocket = new CClientSocket(this); if (m_pSocket->Accept(*pSocket)) { pSocket->Init(); m_connectionList.AddTail(pSocket); } else delete pSocket; } void CServerDoc::ProcessPendingRead(CClientSocket* pSocket) { do { CMsg* pMsg = ReadMsg(pSocket); if (pMsg->m_bClose) { CloseSocket(pSocket); break; } } while (!pSocket->m_pArchiveIn->IsBufferEmpty()); UpdateClients(); } CMsg* CServerDoc::AssembleMsg(CClientSocket* pSocket) { static CMsg msg; msg.Init(); if (pSocket->m_nMsgCount >= m_msgList.GetCount()) return NULL; for (POSITION pos1 = m_msgList.FindIndex(pSocket->m_nMsgCount); pos1 != NULL;) { CString temp = m_msgList.GetNext(pos1); msg.m_msgList.AddTail(temp); } pSocket->m_nMsgCount = m_msgList.GetCount(); return &msg; } CMsg* CServerDoc::ReadMsg(CClientSocket* pSocket) { static CMsg msg; TRY { pSocket->ReceiveMsg(&msg); Message(msg.m_strText); m_msgList.AddTail(msg.m_strText); } CATCH(CFileException, e) { CString strTemp; if (strTemp.LoadString(IDS_READERROR)) Message(strTemp); msg.m_bClose = TRUE; pSocket->Abort(); } END_CATCH return &msg; } void CServerDoc::SendMsg(CClientSocket* pSocket, CMsg* pMsg) { TRY { pSocket->SendMsg(pMsg); } CATCH(CFileException, e) { pSocket->Abort(); CString strTemp; if (strTemp.LoadString(IDS_SENDERROR)) Message(strTemp); } END_CATCH } void CServerDoc::CloseSocket(CClientSocket* pSocket) { pSocket->Close(); POSITION pos,temp; for(pos = m_connectionList.GetHeadPosition(); pos != NULL;) { temp = pos; CClientSocket* pSock = (CClientSocket*)m_connectionList.GetNext(pos); if (pSock == pSocket) { m_connectionList.RemoveAt(temp); break; } } delete pSocket; } void CServerDoc::Message(LPCTSTR lpszMessage) { ((CServerView*)m_viewList.GetHead())->Message(lpszMessage); } ///////////////////////////////////////////////////////////////////////////// // CServerDoc Handlers void CServerDoc::OnUpdateMessages(CCmdUI* pCmdUI) { pCmdUI->Enable(TRUE); CString strFmt; if (strFmt.LoadString(IDS_MESSAGESFMT)) { CString strTemp; wsprintf(strTemp.GetBuffer(50),strFmt,m_msgList.GetCount()); strTemp.ReleaseBuffer(); pCmdUI->SetText(strTemp); } } void CServerDoc::OnUpdateConnections(CCmdUI* pCmdUI) { pCmdUI->Enable(TRUE); CString strFmt; if (strFmt.LoadString(IDS_CONNECTIONSFMT)) { CString strTemp; wsprintf(strTemp.GetBuffer(50),strFmt,m_connectionList.GetCount()); strTemp.ReleaseBuffer(); pCmdUI->SetText(strTemp); } }