From 955d4e00adc9f39ab93bf21f07506eb75b013c70 Mon Sep 17 00:00:00 2001 From: Michael Krelin Date: Mon, 05 Jul 2004 01:53:09 +0000 Subject: initial commit into svn repository git-svn-id: http://svn.klever.net/kin/T42/trunk@1 fe716a7a-6dde-0310-88d9-d003556173a8 --- (limited to 'T42Frame.cpp') diff --git a/T42Frame.cpp b/T42Frame.cpp new file mode 100644 index 0000000..96bc522 --- a/dev/null +++ b/T42Frame.cpp @@ -0,0 +1,1212 @@ +// T42Frame.cpp : implementation file +// + +#include "stdafx.h" +#include "T42.h" +#include "T42Frame.h" + +#include "T42View.h" +#include "CalleeDlg.h" +#include "shared-code/RegEx.h" +#include "T42Document.h" + +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// T42Frame + +IMPLEMENT_DYNCREATE(T42Frame, CFrameWnd) + +T42Frame::T42Frame() +{ + VERIFY(m_hNormal=AfxGetApp()->LoadIcon(IDR_T42FRAME)); + VERIFY(m_hFullCup=AfxGetApp()->LoadIcon(IDR_FULLT42)); + + m_bTrayMinimize = TRUE; + m_bSleepMinimize = TRUE; + m_bMinimizeSleep = TRUE; + m_onWake = wakeSound|wakePopup; + LoadLayout(); + + m_bHaveFocus = FALSE; + m_bTrayed = FALSE; + m_bSleep = FALSE; + + m_asyncHandle = NULL; + m_resolveHandle = NULL; + m_ctlSocket = INVALID_SOCKET; + m_Socket = INVALID_SOCKET; + m_localEC.m_cErase = 0177; + m_localEC.m_kill = 025; // ^U + m_localEC.m_wErase = 027; // ^W + m_bEstablished = FALSE; + + CleanUp(); +} + +T42Frame::~T42Frame() +{ +} + +BEGIN_MESSAGE_MAP(T42Frame, CFrameWnd) + //{{AFX_MSG_MAP(T42Frame) + ON_WM_CLOSE() + ON_COMMAND(ID_TALK_REMOTEUSER, OnTalkRemoteuser) + ON_MESSAGE(WM_INITIATETALK, OnInitiateTalk) + ON_MESSAGE(WM_TARGETRESOLVED, OnTargetResolved) + ON_MESSAGE(WM_SOURCERESOLVED, OnSourceResolved) + ON_WM_TIMER() + ON_MESSAGE(WM_CTLTRANSACT, OnCTLTransact) + ON_MESSAGE(WM_LOOKUP_SUCCESS, OnLookupSuccess) + ON_MESSAGE(WM_LOOKUP_FAILURE, OnLookupFailure) + ON_MESSAGE(WM_ANNOUNCE_SUCCESS, OnAnnounceSuccess) + ON_MESSAGE(WM_ANNOUNCE_FAILURE, OnAnnounceFailure) + ON_MESSAGE(WM_LEAVEINVITE_SUCCESS, OnLeaveInviteSuccess) + ON_MESSAGE(WM_LEAVEINVITE_FAILURE, OnLeaveInviteFailure) + ON_MESSAGE(WM_TALKACCEPT, OnTalkAccept) + ON_MESSAGE(WM_LOCAL_REMOVE_SUCCESS, OnLocalRemoveSuccess) + ON_MESSAGE(WM_LOCAL_REMOVE_FAILURE, OnLocalRemoveFailure) + ON_MESSAGE(WM_REMOTE_REMOVE_SUCCESS, OnRemoteRemoveSuccess) + ON_MESSAGE(WM_REMOTE_REMOVE_FAILURE, OnRemoteRemoveFailure) + ON_MESSAGE(WM_TALK, OnTalk) + ON_MESSAGE(WM_TALKCHAR, OnTalkChar) + ON_MESSAGE(WM_TALKCONNECT, OnTalkConnect) + ON_WM_CREATE() + ON_UPDATE_COMMAND_UI(ID_INDICATOR_DATE, OnUpdateDate) + ON_MESSAGE(WM_EXITMENULOOP, OnExitMenuLoop) + ON_WM_DESTROY() + ON_WM_SYSCOMMAND() + ON_MESSAGE(WM_NAMERESOLVED, OnNameResolved) + ON_MESSAGE(WM_IPRESOLVED, OnIPResolved) + ON_WM_ACTIVATE() + ON_MESSAGE(WM_TRAYICON, OnTrayIcon) + ON_UPDATE_COMMAND_UI(ID_WINDOW_HIDEINTRAYONMINIMIZE, OnUpdateWindowHideintrayonminimize) + ON_COMMAND(ID_WINDOW_HIDEINTRAYONMINIMIZE, OnWindowHideintrayonminimize) + ON_COMMAND(ID_TALK_ABORT, OnTalkAbort) + ON_UPDATE_COMMAND_UI(ID_TALK_ABORT, OnUpdateTalkAbort) + ON_COMMAND(ID_TALK_RECONNECT, OnTalkReconnect) + ON_UPDATE_COMMAND_UI(ID_TALK_RECONNECT, OnUpdateTalkReconnect) + ON_UPDATE_COMMAND_UI(ID_TALK_REMOTEUSER, OnUpdateTalkRemoteuser) + ON_UPDATE_COMMAND_UI(ID_SLEEP_SLEEP, OnUpdateSleepSleep) + ON_COMMAND(ID_SLEEP_SLEEP, OnSleepSleep) + ON_UPDATE_COMMAND_UI(ID_SLEEP_SLEEPONMINIMIZE, OnUpdateSleepSleeponminimize) + ON_COMMAND(ID_SLEEP_SLEEPONMINIMIZE, OnSleepSleeponminimize) + ON_UPDATE_COMMAND_UI(ID_SLEEP_WAKEUPACTION_MAKESOUND, OnUpdateSleepWakeupactionMakesound) + ON_COMMAND(ID_SLEEP_WAKEUPACTION_MAKESOUND, OnSleepWakeupactionMakesound) + ON_UPDATE_COMMAND_UI(ID_SLEEP_WAKEUPACTION_POPUP, OnUpdateSleepWakeupactionPopup) + ON_COMMAND(ID_SLEEP_WAKEUPACTION_POPUP, OnSleepWakeupactionPopup) + ON_UPDATE_COMMAND_UI(ID_SLEEP_MINIMIZEONSLEEP, OnUpdateSleepMinimizeonsleep) + ON_COMMAND(ID_SLEEP_MINIMIZEONSLEEP, OnSleepMinimizeonsleep) + ON_COMMAND(ID_TALK_CLOSE, OnTalkClose) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// T42Frame message handlers + +void T42Frame::OnClose() +{ + if(GetKeyState(VK_SHIFT)&0x8000){ + T42Document* pDoc = (T42Document*)GetActiveDocument(); + ASSERT_KINDOF(T42Document,pDoc); + pDoc->AutosaveLayout(); + } + CFrameWnd::OnClose(); +} + +BOOL T42Frame::PreCreateWindow(CREATESTRUCT& cs) +{ +CWinApp* app = AfxGetApp(); + ASSERT(app); + cs.x = app->GetProfileInt("T42Window","X",cs.x); + cs.y = app->GetProfileInt("T42Window","Y",cs.y); + cs.cx = app->GetProfileInt("T42Window","Width",cs.cx); + cs.cy = app->GetProfileInt("T42Window","Height",cs.cy); + +BOOL rv = CFrameWnd::PreCreateWindow(cs); + +// cs.style&=~FWS_PREFIXTITLE; +// cs.style|=FWS_ADDTOTITLE; + + return rv; +} + +void T42Frame::OnTalkRemoteuser() +{ +CCalleeDlg callee(this); + callee.m_Callee = m_Target; + callee.m_Caller = m_LocalUser; + callee.m_TTY = m_TargetTTY; + if(callee.DoModal() == IDOK){ + m_Target = callee.m_Callee; + m_LocalUser = callee.m_Caller; + m_TargetTTY = callee.m_TTY; + PostMessage(WM_INITIATETALK); + } +} + +LRESULT T42Frame::OnInitiateTalk(WPARAM,LPARAM) +{ + if( + (!((T42Document*)GetActiveDocument())->m_bHidden) + && !m_bTrayed + ) + SetForegroundWindow(); +CRegEx atRE, bangRE; + VERIFY(atRE.Compile("([-À-ßà-ÿ[:alnum:]_.]+)@([-[:alnum:].]+)",CRegEx::regExtended)); // u, h + VERIFY(bangRE.Compile("([-[:alnum:].]+)[!:]([-À-ßà-ÿ[:alnum:]._]+)",CRegEx::regExtended)); // h, u + if(atRE.Match(m_Target,CRegEx::regExtended)){ + m_TargetUser = atRE.GetMatch(1); + m_TargetHost = atRE.GetMatch(2); + }else if(bangRE.Match(m_Target,CRegEx::regExtended)){ + m_TargetUser = bangRE.GetMatch(2); + m_TargetHost = bangRE.GetMatch(1); + }else{ + ShowMessage(IDS_ERR_MALFORMEDREMOTE,MB_ICONSTOP|MB_OK); + return -1; + } + SetPeerName(); + memset(&m_TargetAddr,0,sizeof(m_TargetAddr)); + m_TargetAddr.sin_addr.s_addr = inet_addr(m_TargetHost); + if(m_TargetAddr.sin_addr.s_addr == INADDR_NONE){ + StatusLine(IDS_STATUS_RESOLVING); + m_asyncHandle = WSAAsyncGetHostByName( + m_hWnd,WM_TARGETRESOLVED, + (LPCTSTR)m_TargetHost, + (char*)m_gethostData,sizeof(m_gethostData) + ); + if(!m_asyncHandle){ + WSSystemMessage(IDS_ERR_REMOTERESOLVEFAILED,WSAGetLastError()); + return -1; + } + // Here we're trying to establish connection using hostname (as opposed + // to ip address) - no further investigation needed. + AddToHotList(); + }else{ + if(!Klever::FindIFace(m_TargetAddr.sin_addr,m_SourceAddr.sin_addr)) + m_SourceAddr.sin_addr.s_addr = INADDR_ANY; + PostMessage(WM_SOURCERESOLVED); + // Try to resolve hostname if it resolves back to the same IP - this + // is the canonical name we need. If not - leave it as IP. + m_resolveHandle = WSAAsyncGetHostByAddr( + m_hWnd,WM_NAMERESOLVED, + (char*)&m_TargetAddr.sin_addr,sizeof(m_TargetAddr.sin_addr),AF_INET, + (char*)m_ghResolve,sizeof(m_ghResolve) + ); + if(!m_resolveHandle){ + // We've failed to resolve hostname - leave IP - do nothing. + TRACE0("Failed to initiate IP resolve\n"); + AddToHotList(); + } + } + return 0; +} + +LRESULT T42Frame::OnNameResolved(WPARAM,LPARAM lP) +{ + m_resolveHandle=NULL; + if(WSAGETASYNCERROR(lP)){ + // We've failed to resolve hostname - leave IP - do nothing. + TRACE0("Failed to resolve name by ip\n"); + AddToHotList(); + }else{ + hostent* he = (hostent*)m_ghResolve; + m_nameFromIP = he->h_name; + m_resolveHandle = WSAAsyncGetHostByName( + m_hWnd,WM_IPRESOLVED, + (LPCTSTR)m_nameFromIP, + (char*)m_ghResolve,sizeof(m_ghResolve) + ); + if(!m_resolveHandle){ + // We've failed to resolve hostname - leave IP - do nothing. + TRACE0("Failed to initiate name resolve\n"); + AddToHotList(); + } + } + return 0; +} + +LRESULT T42Frame::OnIPResolved(WPARAM,LPARAM lP) +{ + m_resolveHandle=NULL; + if(WSAGETASYNCERROR(lP)){ + // We've failed to resolve hostname - leave IP - do nothing. + TRACE0("Failed to resolve name by ip\n"); + AddToHotList(); + }else{ + hostent* he = (hostent*)m_ghResolve; + if( + he->h_length!=sizeof(m_TargetAddr.sin_addr) + || he->h_addrtype!=m_TargetAddr.sin_family + || memcmp(*he->h_addr_list,&m_TargetAddr.sin_addr,he->h_length) + ){ + // The host resolved to different IP address.. + // maybe we should warn user about it? + TRACE0("IP/NAME investigations sucked in result\n"); + AddToHotList(); + }else{ + // We got new hostname!! Hurray! What do we do? + // Yes, we set new Target.. + m_TargetHost = m_nameFromIP; + m_Target = m_TargetUser + '@' + m_TargetHost; + SetPeerName(); + AddToHotList(); + T42Document* pDoc = (T42Document*)GetActiveDocument(); + ASSERT_KINDOF(T42Document,pDoc); + if(pDoc->m_pRobot) + pDoc->m_pRobot->OnIPResolved(); + TRACE0("IP/NAME investigations succeeded\n"); + } + } + return 0; +} + +LRESULT T42Frame::OnTargetResolved(WPARAM,LPARAM lP) +{ + m_asyncHandle=NULL; + if(WSAGETASYNCERROR(lP)){ + WSSystemMessage(IDS_ERR_REMOTERESOLVEFAILED,WSAGetLastError()); + return 0; + } + ASSERT(((hostent*)m_gethostData)->h_length==4); + memmove(&m_TargetAddr.sin_addr,*((hostent*)m_gethostData)->h_addr_list,sizeof(m_TargetAddr.sin_addr)); + if(!Klever::FindIFace(m_TargetAddr.sin_addr,m_SourceAddr.sin_addr)) + m_SourceAddr.sin_addr.s_addr = INADDR_ANY; + PostMessage(WM_SOURCERESOLVED); + return 0; +} + +LRESULT T42Frame::OnSourceResolved(WPARAM,LPARAM) +{ + // Open ctl socket + m_SourceAddr.sin_port = 0; + m_SourceAddr.sin_family = AF_INET; + m_ctlSocket = socket(AF_INET,SOCK_DGRAM,0); + if(m_ctlSocket==INVALID_SOCKET){ + WSSystemMessage(IDS_ERR_CTLCREATEFAILED,WSAGetLastError()); + return -1; + } + if(bind(m_ctlSocket,(sockaddr*)&m_SourceAddr,sizeof(m_SourceAddr))){ + WSSystemMessage(IDS_ERR_CTLBINDFAILED,WSAGetLastError()); + return -1; + } +int length = sizeof(m_ctlAddr); + if(getsockname(m_ctlSocket,(sockaddr*)&m_ctlAddr,&length)){ + WSSystemMessage(IDS_ERR_CTLGETFAILED,WSAGetLastError()); + return -1; + } + // Open socket for connection + m_SourceAddr.sin_port = 0; + m_SourceAddr.sin_family = AF_INET; + m_Socket = socket(AF_INET,SOCK_STREAM,0); + if(m_Socket==INVALID_SOCKET){ + WSSystemMessage(IDS_ERR_TCPCREATEFAILED,WSAGetLastError()); + return -1; + } + if(bind(m_Socket,(sockaddr*)&m_SourceAddr,sizeof(m_SourceAddr))){ + WSSystemMessage(IDS_ERR_TCPBINDFAILED,WSAGetLastError()); + return -1; + } + length = sizeof(m_SourceAddr); + if(getsockname(m_Socket,(sockaddr*)&m_SourceAddr,&length)){ + WSSystemMessage(IDS_ERR_TCPGETFAILED,WSAGetLastError()); + return -1; + } + StatusLine(IDS_STATUS_LOOKUPINVITE); +TalkCtlMessage rq; + FillInMessage(rq); + rq.m_Type = talkCtlReqLookUp; + m_TargetAddr.sin_family = AF_INET; +CT42App* app = (CT42App*)AfxGetApp(); + m_TargetAddr.sin_port = htons(app->m_T42TalkPort); + VERIFY(AsyncCtlTransact(rq,m_TargetAddr,WM_LOOKUP_SUCCESS,WM_LOOKUP_FAILURE)); + return 0; +} + +BOOL T42Frame::FillInMessage(TalkCtlMessage& msg) +{ + memset(&msg,0,sizeof(msg)); + msg.m_Version = talkCtlVersion; + msg.m_Addr = m_SourceAddr; + msg.m_ctlAddr = m_ctlAddr; + msg.m_ID = htonl(0); + msg.m_PID = htonl((LONG)m_hWnd); + ASSERT(m_LocalUser.GetLength()>0 && m_LocalUser.GetLength()0 && m_TargetUser.GetLength()=0 && m_TargetTTY.GetLength()sin_addr), + ntohs(((sockaddr_in*)&m_ctlRequest.m_Addr)->sin_port) + ); + TRACE("CTL ADDR: %s:%d\n", + inet_ntoa(((sockaddr_in*)&m_ctlRequest.m_ctlAddr)->sin_addr), + ntohs(((sockaddr_in*)&m_ctlRequest.m_ctlAddr)->sin_port) + ); + if(sendto(m_ctlSocket,(char*)&m_ctlRequest,sizeof(m_ctlRequest),0, + (sockaddr*)&m_ctlTarget,sizeof(m_ctlTarget))!=sizeof(m_ctlRequest) + ){ + AsyncCtlTransactFailed(ctlFailSendto,WSAGetLastError()); + return TRUE; + } + if(WSAAsyncSelect(m_ctlSocket,m_hWnd,WM_CTLTRANSACT,FD_READ)){ + AsyncCtlTransactFailed(ctlFailSelect,WSAGetLastError()); + return TRUE; + } + SetTimer(timerTransact,2000,NULL); + return TRUE; +} + +LRESULT T42Frame::OnCTLTransact(WPARAM,LPARAM lP) +{ + KillTimer(timerTransact); + if(!(m_ctlSuccess && m_ctlFailure)) + return -1; + if(WSAGETSELECTERROR(lP)){ + AsyncCtlTransactFailed(ctlFailError,WSAGETSELECTERROR(lP)); + return -1; + } + ASSERT(WSAGETSELECTEVENT(lP)&FD_READ); +long length; + do{ + if(ioctlsocket(m_ctlSocket,FIONREAD,(u_long*)&length) || length<=0) + break; + if(recv(m_ctlSocket,(char*)&m_ctlResponse,sizeof(m_ctlResponse),0)!=sizeof(m_ctlResponse)) + continue; + if( + m_ctlResponse.m_Version != talkCtlVersion + || m_ctlResponse.m_Type!=m_ctlRequest.m_Type + ) + continue; + // We got the datagram we need here + AsyncCtlTransactSucceeded(m_ctlResponse); + }while(1); + if(WSAAsyncSelect(m_ctlSocket,m_hWnd,WM_CTLTRANSACT,FD_READ)){ + AsyncCtlTransactFailed(ctlFailSelect,WSAGetLastError()); + return -1; + } + SetTimer(timerTransact,2000,NULL); + return 0; +} + +void T42Frame::OnTimer(UINT nIDEvent) +{ + switch(nIDEvent){ + case timerTransact: + KillTimer(timerTransact); + if(!(m_ctlSuccess && m_ctlFailure)){ + TRACE0("VERY STRANGE\n"); + break; + } + TRACE0("Transact timed out\n"); + if(sendto(m_ctlSocket,(char*)&m_ctlRequest,sizeof(m_ctlRequest),0, + (sockaddr*)&m_ctlTarget,sizeof(m_ctlTarget))!=sizeof(m_ctlRequest) + ){ + AsyncCtlTransactFailed(ctlFailSendto,WSAGetLastError()); + break; + } + if(WSAAsyncSelect(m_ctlSocket,m_hWnd,WM_CTLTRANSACT,FD_READ)){ + AsyncCtlTransactFailed(ctlFailSelect,WSAGetLastError()); + break; + } + SetTimer(timerTransact,2000,NULL); + break; + } + + CFrameWnd::OnTimer(nIDEvent); +} + + +void T42Frame::AsyncCtlTransactFailed(UINT code,LONG error) +{ + ASSERT(m_ctlSuccess && m_ctlFailure); +UINT m = m_ctlFailure; + m_ctlFailure = m_ctlSuccess = 0; + WSAAsyncSelect(m_ctlSocket,NULL,0,0); + TRACE2("CTL Transact failed %d (%ld)\n",(int)code,error); + PostMessage(m,code,error); +} + +void T42Frame::AsyncCtlTransactSucceeded(TalkCtlResponse& response) +{ + ASSERT(m_ctlSuccess && m_ctlFailure); +UINT m = m_ctlSuccess; + m_ctlFailure = m_ctlSuccess = 0; + WSAAsyncSelect(m_ctlSocket,NULL,0,0); + TRACE2("CTL Transaction succeeded - A: %d, ID: %ld\n", + (int)response.m_Answer, ntohl(response.m_ID) + ); + TRACE2("ADDR: %s:%d\n", + inet_ntoa(((sockaddr_in*)&response.m_Addr)->sin_addr), + ntohs(((sockaddr_in*)&response.m_Addr)->sin_port) + ); + PostMessage(m,0,(LPARAM)&response); +} + +LRESULT T42Frame::OnLookupSuccess(WPARAM,LPARAM lP) +{ +TalkCtlResponse& rp = *(TalkCtlResponse*)lP; + if(rp.m_Answer==talkCtlSuccess){ + TRACE0("Found an invitation\n"); + if(WSAAsyncSelect(m_Socket,m_hWnd,WM_TALKCONNECT,FD_CONNECT)){ + WSSystemMessage(IDS_ERR_TCPASELFAILED,WSAGetLastError()); + return -1; + } + SOCKADDR_IN sin; + memmove(&sin,&rp.m_Addr,sizeof(sin)); + sin.sin_family = ntohs(sin.sin_family); + StatusLine(IDS_STATUS_WAITINGTOCONNECT); + if(connect(m_Socket,(sockaddr*)&sin,sizeof(sin))){ + if(WSAGetLastError()!=WSAEWOULDBLOCK){ + WSSystemMessage(IDS_ERR_TCPCONNECTFAILED,WSAGetLastError()); + return -1; + } + }else + PostMessage(WM_TALKCONNECT,0,WSAMAKESELECTREPLY(FD_CONNECT,0)); + }else{ + if(listen(m_Socket,5)){ + WSSystemMessage(IDS_ERR_TCPLISTENFAILED,WSAGetLastError()); + return -1; + } + if(WSAAsyncSelect(m_Socket,m_hWnd,WM_TALKACCEPT,FD_ACCEPT)){ + WSSystemMessage(IDS_ERR_LTNASELFAILED,WSAGetLastError()); + return -1; + } + TalkCtlMessage rq; + FillInMessage(rq); + rq.m_Type = talkCtlReqLeaveInvite; + rq.m_ID = htonl(-1); + SOCKADDR_IN tgt; + memmove(&tgt,&m_SourceAddr,sizeof(tgt)); +CT42App* app = (CT42App*)AfxGetApp(); + tgt.sin_port = htons(app->m_T42TalkPort); + VERIFY(AsyncCtlTransact(rq,tgt,WM_LEAVEINVITE_SUCCESS,WM_LEAVEINVITE_FAILURE)); + } + return 0; +} +LRESULT T42Frame::OnLookupFailure(WPARAM wP,LPARAM lP) +{ + SystemMessage(IDS_ERR_CTLLOOKUPFAILED); + TRACE2("Lookup failed %d, %ld",(int)wP,lP); + return -1; +} + +LRESULT T42Frame::OnAnnounceSuccess(WPARAM,LPARAM lP) +{ +TalkCtlResponse& rp = *(TalkCtlResponse*)lP; + if(rp.m_Answer != talkCtlSuccess){ + static + UINT nReasons[] = {0,IDS_CTL_NOTHERE,IDS_CTL_FAILED,IDS_CTL_MACHUNKNOWN, + IDS_CTL_PERMISSIONDENIED, IDS_CTL_BADREQUEST, IDS_CTL_BADVERSION, + IDS_CTL_BADADDR, IDS_CTL_BADCTL}; + CString reason; + if(rp.m_Answer<(sizeof(nReasons)/sizeof(*nReasons))) + SystemMessage(IDS_ERR_ANNOUNCEFAILURE,nReasons[rp.m_Answer]); + else + SystemMessage(IDS_ERR_ANNOUNCEFAILURE,IDS_CTL_UNKNOWNERROR); + return -1; + } + m_remoteID = rp.m_ID; + return 0; +} +LRESULT T42Frame::OnAnnounceFailure(WPARAM wP,LPARAM lP) +{ + SystemMessage(IDS_ERR_ANNOUNCEFAILED); + return -1; +} + +LRESULT T42Frame::OnLeaveInviteSuccess(WPARAM,LPARAM lP) +{ +TalkCtlResponse& rp = *(TalkCtlResponse*)lP; + m_localID = rp.m_ID; +TalkCtlMessage rq; + FillInMessage(rq); + rq.m_ID = htonl(-1); + StatusLine(IDS_STATUS_ANNOUNCING); + rq.m_Type = talkCtlReqAnnounce; + m_TargetAddr.sin_family = AF_INET; +CT42App* app = (CT42App*)AfxGetApp(); + m_TargetAddr.sin_port = htons(app->m_T42TalkPort); + VERIFY(AsyncCtlTransact(rq,m_TargetAddr,WM_ANNOUNCE_SUCCESS,WM_ANNOUNCE_FAILURE)); + return 0; // Or? +} +LRESULT T42Frame::OnLeaveInviteFailure(WPARAM wP,LPARAM lP) +{ + SystemMessage(IDS_ERR_LEAVINVITEFAILED); + TRACE2("LeaveInvite failed %d, %ld",(int)wP,lP); + return -1; +} + +LRESULT T42Frame::OnTalkAccept(WPARAM,LPARAM lP) +{ + if(WSAGETSELECTERROR(lP)){ + WSSystemMessage(IDS_ERR_TCPACCEPTFAILED,WSAGETSELECTERROR(lP)); + return -1; + } + ASSERT(WSAGETSELECTEVENT(lP)&FD_ACCEPT); +SOCKET s = accept(m_Socket,NULL,NULL); + ASSERT(s!=INVALID_SOCKET); + VERIFY(!closesocket(m_Socket)); + m_Socket = s; + m_bConnected=TRUE; + SelectTalkSocket(); + StatusLine(IDS_STATUS_WAITINGTOCONNECT); +TalkCtlMessage rq; + FillInMessage(rq); + rq.m_Type = talkCtlReqDelete; + rq.m_ID = m_localID; +SOCKADDR_IN t; + memmove(&t,&m_SourceAddr,sizeof(t)); +CT42App* app = (CT42App*)AfxGetApp(); + t.sin_port = htons(app->m_T42TalkPort); + AsyncCtlTransact(rq,t,WM_LOCAL_REMOVE_SUCCESS,WM_LOCAL_REMOVE_FAILURE); + return 0; +} + +LRESULT T42Frame::OnTalkConnect(WPARAM,LPARAM lP) +{ + if(WSAGETSELECTERROR(lP)){ + WSSystemMessage(IDS_ERR_TCPCONNECTFAILED,WSAGETSELECTERROR(lP)); + return -1; + } + m_bConnected=TRUE; + ASSERT(WSAGETSELECTEVENT(lP)&FD_CONNECT); + SelectTalkSocket(); + StatusLine(IDS_STATUS_WAITINGTOCONNECT); + return 0; +} + +LRESULT T42Frame::OnLocalRemoveSuccess(WPARAM,LPARAM lP) +{ +TalkCtlResponse& rp = *(TalkCtlResponse*)lP; + ASSERT(rp.m_Answer==talkCtlSuccess); +TalkCtlMessage rq; + FillInMessage(rq); + rq.m_Type = talkCtlReqDelete; + rq.m_ID = m_remoteID; +SOCKADDR_IN t; + memmove(&t,&m_TargetAddr,sizeof(t)); +CT42App* app = (CT42App*)AfxGetApp(); + t.sin_port = htons(app->m_T42TalkPort); + AsyncCtlTransact(rq,t,WM_REMOTE_REMOVE_SUCCESS,WM_REMOTE_REMOVE_FAILURE); + return 0; +} +LRESULT T42Frame::OnLocalRemoveFailure(WPARAM wP,LPARAM lP) +{ +// SystemMessage(IDS_ERR_CTLLDELETEFAILED); + TRACE2("Local delete failed %d, %ld",(int)wP,lP); + return -1; +} + +LRESULT T42Frame::OnRemoteRemoveSuccess(WPARAM,LPARAM lP) +{ +TalkCtlResponse& rp = *(TalkCtlResponse*)lP; +// ASSERT(rp.m_Answer==talkCtlSuccess); // ??? + return 0; +} +LRESULT T42Frame::OnRemoteRemoveFailure(WPARAM wP,LPARAM lP) +{ +// SystemMessage(IDS_ERR_CTLRDELETEFAILED); + TRACE2("Local delete failed %d, %ld",(int)wP,lP); + return -1; +} + +LRESULT T42Frame::OnTalk(WPARAM wP,LPARAM lP) +{ + if(WSAGETSELECTEVENT(lP)&FD_CLOSE){ + StatusLine(IDS_STATUS_CONNECTIONCLOSED); + if(WSAGETSELECTERROR(lP)) + WSSystemMessage(IDS_ERR_CONNECTIONCLOSED,WSAGETSELECTERROR(lP)); + else + SystemMessage(IDS_CONNECTIONCLOSED); + Established(FALSE); + return 0; + } + if(WSAGETSELECTERROR(lP)){ + WSSystemMessage(IDS_ERR_TCPERROR,WSAGETSELECTERROR(lP)); + Established(FALSE); + TRACE1("Error on conversation socket: %ld\n",WSAGETSELECTERROR(lP)); + return -1; + } + if(WSAGETSELECTEVENT(lP)&FD_READ){ + CHAR rb[512+1]; + int rbytes = recv(m_Socket,rb,sizeof(rb)-1,0); + if(rbytes>0){ + if(m_receivedECm_pRobot) + pDoc->m_pRobot->OnReceive(rb,rbytes); + PutRemote(rb); + if(!m_bHaveFocus){ + SetTheIcon(m_hFullCup); + if(m_bSleep) + WakeUp(); + } + } + } + } + if(WSAGETSELECTEVENT(lP)&FD_WRITE){ + if(!m_bSentEC){ + if(send(m_Socket,(char*)&m_localEC,sizeof(m_localEC),0)!=sizeof(m_localEC)){ + WSSystemMessage(IDS_ERR_TCPERROR,WSAGetLastError()); + Established(FALSE); + }else + m_bSentEC = TRUE; + }else{ + int sb = send(m_Socket,(char*)(LPCTSTR)m_sendBuffer,m_sendBuffer.GetLength(),0); + if(sb<0){ + WSSystemMessage(IDS_ERR_TCPERROR,WSAGetLastError()); + Established(FALSE); + }else + m_sendBuffer = m_sendBuffer.Mid(sb); + } + } + SelectTalkSocket(); + return 0; +} + +void T42Frame::SelectTalkSocket() +{ + if(!m_bConnected) + return; +UINT mask = FD_READ|FD_CLOSE; + if(!(m_bSentEC && m_sendBuffer.IsEmpty())) + mask|=FD_WRITE; + if(WSAAsyncSelect(m_Socket,m_hWnd,WM_TALK,mask)){ + WSSystemMessage(IDS_ERR_TCPERROR,WSAGetLastError()); + Established(FALSE); + } +} + +BOOL T42Frame::PutRemote(LPCTSTR str) +{ +T42View* pView = (T42View*)GetActiveView(); + ASSERT_KINDOF(T42View,pView); + pView->m_remoteCtl.PutString(str); + return TRUE; +} + +LRESULT T42Frame::OnTalkChar(WPARAM wP,LPARAM lP) +{ + if(wP){ + CHAR c=(CHAR)(wP&0xFF); +// if(c=='\r') +//?? c='\n'; + m_sendBuffer+=c; + }else{ + CString str = (LPCTSTR)lP; + int cr; + while((cr=str.Find('\r'))>=0) + str = str.Left(cr)+str.Mid(cr+1); + m_sendBuffer+=str; + } + SelectTalkSocket(); + return 0; +} + +int T42Frame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if(CFrameWnd::OnCreate(lpCreateStruct)==-1) + return -1; + // CG: The following block was inserted by 'Status Bar' component. + { + // Create an array for status bar indicators + UINT pIndicators[3] = { ID_SEPARATOR }; + if (!m_wndStatusBar.Create(this) || + !InitStatusBar(pIndicators, 1, 60)) + { + TRACE0("Failed to create Status Bar\n"); + return -1; + } + } + + m_wndFake.CreateEx( + 0,AfxRegisterWndClass(0,0,0,0),"",WS_OVERLAPPED, + 0,0,0,0, + NULL,NULL,NULL + ); + + return 0; +} + +void T42Frame::OnUpdateDate(CCmdUI* pCmdUI) +{ + // CG: This function was inserted by 'Status Bar' component. + + // Get current date and format it + CTime time = CTime::GetCurrentTime(); + CString strDate = time.Format(_T("%A, %B %d, %y ")); + + // BLOCK: compute the width of the date string + CSize size; + { + HGDIOBJ hOldFont = NULL; + HFONT hFont = (HFONT)m_wndStatusBar.SendMessage(WM_GETFONT); + CClientDC dc(NULL); + if (hFont != NULL) + hOldFont = dc.SelectObject(hFont); + size = dc.GetTextExtent(strDate); + if (hOldFont != NULL) + dc.SelectObject(hOldFont); + } + + // Update the pane to reflect the current date + UINT nID, nStyle; + int nWidth; + m_wndStatusBar.GetPaneInfo(m_nDatePaneNo, nID, nStyle, nWidth); + m_wndStatusBar.SetPaneInfo(m_nDatePaneNo, nID, nStyle, size.cx); + pCmdUI->SetText(strDate); + pCmdUI->Enable(TRUE); + +} + +BOOL T42Frame::InitStatusBar(UINT *pIndicators, int nSize, int nSeconds) +{ + // CG: This function was inserted by 'Status Bar' component. + + // Create an index for the DATE pane + m_nDatePaneNo = nSize++; + pIndicators[m_nDatePaneNo] = ID_INDICATOR_DATE; + + m_wndStatusBar.SetTimer(0x1000, nSeconds * 1000, NULL); + + return m_wndStatusBar.SetIndicators(pIndicators, nSize); + +} + +void T42Frame::StatusLine(LPCTSTR str) +{ + m_wndStatusBar.SetPaneText(0,m_Status=str); +} + +void T42Frame::StatusLine(UINT nID) +{ + VERIFY(m_Status.LoadString(nID)); + m_wndStatusBar.SetPaneText(0,m_Status); +} + +LRESULT T42Frame::OnExitMenuLoop(WPARAM,LPARAM) +{ + m_wndStatusBar.SetPaneText(0,m_Status); + return 0; +} + +void T42Frame::OnDestroy() +{ + if(m_bTrayed){ + NOTIFYICONDATA nid; + memset(&nid,0,sizeof(nid)); + nid.cbSize=sizeof(nid); + nid.hWnd = m_hWnd; + nid.uID = IDC_TRAYICON; + nid.uFlags = 0; + VERIFY(Shell_NotifyIcon(NIM_DELETE,&nid)); + } + m_wndFake.DestroyWindow(); + CFrameWnd::OnDestroy(); + + CleanUp(); +} + +void T42Frame::ShowMessage(UINT nID,UINT flags) +{ +CString msg; + VERIFY(msg.LoadString(nID)); + ShowMessage(msg,flags); +} +void T42Frame::ShowMessage(LPCTSTR msg,UINT flags) +{ + MessageBox(msg,NULL,flags); +} + +void T42Frame::Established(BOOL bEstablished) +{ + if(!bEstablished) + CleanUp(); + else{ + if( + (!((T42Document*)GetActiveDocument())->m_bHidden) + && !m_bTrayed + ) + SetForegroundWindow(); + } +T42View* pView = (T42View*)GetActiveView(); + ASSERT_KINDOF(T42View,pView); + pView->SetEnable(bEstablished); + +BOOL bRobot = (m_bEstablished && !bEstablished) || (bEstablished && !m_bEstablished); + m_bEstablished = bEstablished; + + SetPeerName(); + if(bRobot){ + T42Document* pDoc = (T42Document*)pView->GetDocument(); + ASSERT_KINDOF(T42Document,pDoc); + if(pDoc->m_pRobot){ + if(bEstablished) + pDoc->m_pRobot->OnConnect(); + else + pDoc->m_pRobot->OnDisconnect(); + } + } +} + +void T42Frame::CleanUp() +{ + if(m_resolveHandle){ + WSACancelAsyncRequest(m_resolveHandle); + m_resolveHandle=NULL; + } + if(m_asyncHandle){ + WSACancelAsyncRequest(m_asyncHandle); + m_asyncHandle=NULL; + } + if(m_ctlSocket!=INVALID_SOCKET){ + closesocket(m_ctlSocket); + m_ctlSocket = INVALID_SOCKET; + } + if(m_Socket!=INVALID_SOCKET){ + closesocket(m_Socket); + m_Socket = INVALID_SOCKET; + } + + m_Status.LoadString(AFX_IDS_IDLEMESSAGE); + m_localID = m_remoteID = 0; + m_sendBuffer.Empty(); + m_ctlSuccess = 0; + m_ctlFailure = 0; + m_bSentEC = FALSE; + m_receivedEC = 0; + m_bConnected=FALSE; +} + +void T42Frame::OnSysCommand(UINT nID, LPARAM lParam) +{ + if(nID==SC_MINIMIZE){ + if(m_bTrayMinimize){ + NOTIFYICONDATA nid; + memset(&nid,0,sizeof(nid)); + nid.cbSize=sizeof(nid); + nid.hWnd = m_hWnd; + nid.uID = IDC_TRAYICON; + nid.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; + nid.uCallbackMessage = WM_TRAYICON; + nid.hIcon = m_hNormal; + CString tip; + GetWindowText(tip); + if(tip.GetLength()>=sizeof(nid.szTip)) + tip = tip.Left(sizeof(nid.szTip)-3)+".."; + strcpy(nid.szTip,(LPCTSTR)tip); + VERIFY(Shell_NotifyIcon(NIM_ADD,&nid)); + CWnd* pWnd = GetNextWindow(); + ShowWindow(SW_HIDE); + pWnd->SetForegroundWindow(); + m_bTrayed=TRUE; + }else + CFrameWnd::OnSysCommand(nID, lParam); + if(m_bSleepMinimize) + m_bSleep=TRUE; + }else + CFrameWnd::OnSysCommand(nID, lParam); +} + +void T42Frame::SaveLayout() +{ +CWinApp* app = AfxGetApp(); +CRect rc; + GetWindowRect(rc); + app->WriteProfileInt("T42Window","X",rc.left); + app->WriteProfileInt("T42Window","Y",rc.top); + app->WriteProfileInt("T42Window","Width",rc.Width()); + app->WriteProfileInt("T42Window","Height",rc.Height()); + app->WriteProfileInt("T42Window","TrayMinimize",m_bTrayMinimize); + app->WriteProfileInt("T42Window","SleepMinimize",m_bSleepMinimize); + app->WriteProfileInt("T42Window","OnWake",m_onWake); + app->WriteProfileInt("T42Window","MinimizeSleep",m_bMinimizeSleep); +} +void T42Frame::LoadLayout() +{ +CWinApp* app = AfxGetApp(); + m_bTrayMinimize = app->GetProfileInt("T42Window","TrayMinimize",m_bTrayMinimize); + m_bSleepMinimize = app->GetProfileInt("T42Window","SleepMinimize",m_bSleepMinimize); + m_onWake = app->GetProfileInt("T42Window","OnWake",m_onWake); + m_bMinimizeSleep = app->GetProfileInt("T42Window","MinimizeSleep",m_bMinimizeSleep); +} + +void T42Frame::SetPeerName(LPCTSTR str) +{ +T42Document* pDoc = (T42Document*)GetActiveDocument(); + ASSERT_KINDOF(T42Document,pDoc); +CString n = str?str:m_Target; + pDoc->SetTitle(n); + m_wndFake.SetWindowText("Talk with "+n); +} + +void T42Frame::OnUpdateFrameTitle(BOOL bAddToTitle) +{ +T42Document* pDoc = (T42Document*)GetActiveDocument(); + ASSERT_KINDOF(T42Document,pDoc); +CString title; + if(bAddToTitle && pDoc && m_bEstablished) + title.Format(IDS_TITLE_TEAWITH,pDoc->GetTitle()); + else + title.LoadString(IDS_TITLE_TEAFORTWO); + SetWindowText(title); +} + +void T42Frame::AddToHotList(LPCTSTR str) +{ +CT42App* app = (CT42App*)AfxGetApp(); + app->LastCallee(str?str:m_Target); +} + +void T42Frame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) +{ + CFrameWnd::OnActivate(nState, pWndOther, bMinimized); + if(nState==WA_INACTIVE){ + m_bHaveFocus=FALSE; + }else{ + DeTray(); + SetTheIcon(m_hNormal); + m_bHaveFocus=TRUE; + } +} + +LRESULT T42Frame::OnTrayIcon(WPARAM wP,LPARAM lP) +{ + ASSERT(wP==IDC_TRAYICON); + if(lP==WM_LBUTTONDOWN) + SetForegroundWindow(); + return 0; +} + +void T42Frame::SetTheIcon(HICON hicon) +{ + SetIcon(hicon,TRUE); SetIcon(hicon,FALSE); + if(m_bTrayed){ + NOTIFYICONDATA nid; + memset(&nid,0,sizeof(nid)); + nid.cbSize=sizeof(nid); + nid.hWnd = m_hWnd; + nid.uID = IDC_TRAYICON; + nid.uFlags = NIF_ICON; + nid.hIcon = hicon; + VERIFY(Shell_NotifyIcon(NIM_MODIFY,&nid)); + } +} + +void T42Frame::OnUpdateWindowHideintrayonminimize(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(m_bTrayMinimize?1:0); +} +void T42Frame::OnWindowHideintrayonminimize() +{ + m_bTrayMinimize=!m_bTrayMinimize; +} + +void T42Frame::OnTalkAbort() +{ + ASSERT(m_Socket); + closesocket(m_Socket); + StatusLine(IDS_STATUS_CONNECTIONCLOSED); + SystemMessage(IDS_CONNECTIONCLOSED); + Established(FALSE); +} +void T42Frame::OnUpdateTalkAbort(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(m_bEstablished); +} +void T42Frame::OnTalkReconnect() +{ + PostMessage(WM_INITIATETALK); +} +void T42Frame::OnUpdateTalkReconnect(CCmdUI* pCmdUI) +{ + pCmdUI->Enable((!m_bEstablished) && (!m_Target.IsEmpty())); +} +void T42Frame::OnUpdateTalkRemoteuser(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(!m_bEstablished); +} + +void T42Frame::WakeUp() +{ + if(m_onWake&wakeSound){ + CT42App* app = (CT42App*)AfxGetApp(); + ASSERT(app); + app->StartSound(app->m_sndT42Wake); + } + if(m_onWake&wakePopup) + SetForegroundWindow(); + m_bSleep=FALSE; +} + +void T42Frame::OnUpdateSleepSleep(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(m_bSleep?1:0); +} +void T42Frame::OnSleepSleep() +{ + m_bSleep=!m_bSleep; + if(m_bSleep && m_bMinimizeSleep) + PostMessage(WM_SYSCOMMAND,SC_MINIMIZE); +} + +void T42Frame::OnUpdateSleepSleeponminimize(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(m_bSleepMinimize?1:0); +} +void T42Frame::OnSleepSleeponminimize() +{ + m_bSleepMinimize=!m_bSleepMinimize; +} + +void T42Frame::OnUpdateSleepWakeupactionMakesound(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck((m_onWake&wakeSound)?1:0); +} +void T42Frame::OnSleepWakeupactionMakesound() +{ + m_onWake^=wakeSound; +} + +void T42Frame::OnUpdateSleepWakeupactionPopup(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck((m_onWake&wakePopup)?1:0); +} +void T42Frame::OnSleepWakeupactionPopup() +{ + m_onWake^=wakePopup; +} + +void T42Frame::DeTray() +{ + if(!m_bTrayed) + return; +NOTIFYICONDATA nid; + memset(&nid,0,sizeof(nid)); + nid.cbSize=sizeof(nid); + nid.hWnd = m_hWnd; + nid.uID = IDC_TRAYICON; + nid.uFlags = 0; + VERIFY(Shell_NotifyIcon(NIM_DELETE,&nid)); + m_bTrayed=FALSE; + ShowWindow(SW_SHOW); +} + +void T42Frame::OnUpdateSleepMinimizeonsleep(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(m_bMinimizeSleep?1:0); +} +void T42Frame::OnSleepMinimizeonsleep() +{ + m_bMinimizeSleep=!m_bMinimizeSleep; +} + +void T42Frame::OnTalkClose() +{ + PostMessage(WM_CLOSE); +} + +void T42Frame::SystemMessage(UINT nID) +{ +CString tmp; + VERIFY(tmp.LoadString(nID)); + SystemMessage(tmp); +} + +void T42Frame::SystemMessage(LPCTSTR str) +{ +T42View* pView = (T42View*)GetActiveView(); + ASSERT_KINDOF(T42View,pView); + pView->SystemMessage(str); +} + +void T42Frame::SystemMessage(UINT nID,UINT nIDi) +{ +CString idi; + VERIFY(idi.LoadString(nIDi)); +CString tmp; + tmp.Format(nID,idi); + SystemMessage(tmp); +} + +void T42Frame::WSSystemMessage(UINT nID,LONG wsaError) +{ +UINT wsid = 0; + switch(wsaError){ + case WSAENETDOWN: wsid = IDS_WSA_ENETDOWN; break; + case WSAECONNRESET: wsid = IDS_WSA_ECONNRESET; break; + case WSAECONNABORTED: wsid = IDS_WSA_ECONNABORTED; break; + case WSAECONNREFUSED: wsid = IDS_WSA_ECONNREFUSED; break; + case WSAENETUNREACH: wsid = IDS_WSA_ENETUNREACH; break; + case WSAETIMEDOUT: wsid = IDS_WSA_ETIMEDOUT; break; + case WSAHOST_NOT_FOUND: wsid = IDS_WSA_HOSTNOTFOUND; break; + case WSANO_DATA: wsid = IDS_WSA_NODATA; break; + } + if(wsid) + SystemMessage(nID,wsid); + else{ + CString tmp; + tmp.Format("#%ld",wsaError); + SystemMessage(nID,tmp); + } +} + +void T42Frame::SystemMessage(UINT nID,LPCTSTR str) +{ +CString tmp; + tmp.Format(nID,str); + SystemMessage(tmp); +} + +void T42Frame::ActivateFrame(int nCmdShow) +{ +T42Document* pDoc = (T42Document*)GetActiveDocument(); + ASSERT_KINDOF(T42Document,pDoc); + if(pDoc->m_bHidden) + nCmdShow=SW_HIDE; + CFrameWnd::ActivateFrame(nCmdShow); +} -- cgit v0.9.0.2