// MultiPortDlg.cpp : implementation file // #include "stdafx.h" #include "MultiPort.h" #include "MultiPortDlg.h" //#include "IPSerial.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif HANDLE g_ahSendnExitEvent[2]; //g_ahSendnExitEvent[0] SendEvent //g_ahSendnExitEvent[1] ExitEvent HANDLE g_hMainThread; HANDLE g_hMonitorEventThread; HANDLE g_hRecvThread[MAX_CONNECTIONS]; HANDLE g_hSendThread[MAX_CONNECTIONS]; DWORD dwThreadId = 0; int port_index; CMultiPortDlg *pointer; int GetFreeRecvHandleIndex() { int nIndex = -1; for(int i=0 ; im_OpenCtrl.EnableWindow(TRUE); pointer->m_CloseCtrl.EnableWindow(FALSE); CIPAddressCtrl *pIpAddrCtrl = NULL; pIpAddrCtrl = (CIPAddressCtrl *)(pointer->GetDlgItem(IDC_SERVER_IPADDRESS )); pIpAddrCtrl->EnableWindow( TRUE ); pointer->m_ServerPort1Ctrl.EnableWindow(TRUE); pointer->m_Transmitter1.EnableWindow(FALSE); AfxMessageBox("Server Stopped!!"); } return (DWORD) -1; } DWORD WINAPI AcceptThread(LPVOID param) { CLIENT_INFO sClientInfo; char szTemp[128]; int port_id; THREAD_INPUT szThreadInput; int iFreeIndex ; CString szServerIp = _T(""); CIPAddressCtrl *pIpAddrCtrl = NULL; pIpAddrCtrl = (CIPAddressCtrl *)(pointer->GetDlgItem(IDC_SERVER_IPADDRESS)); pIpAddrCtrl->GetWindowText( szServerIp ); sprintf(szTemp, szServerIp); while(TRUE) { port_id = slan_acceptconnection(port_index, (PCLIENT_INFO)&sClientInfo); if( port_id >= 0 ) { pointer->UpdateConnectionCount( TRUE ); //store the accepted socket in the context->m_csSocket... //HANDLE hThread = NULL; //DWORD dwThreadId = 0; szThreadInput.nPort_id = port_id; szThreadInput.sClientThreadInfo = sClientInfo; iFreeIndex = GetFreeRecvHandleIndex(); g_hRecvThread[iFreeIndex] = CreateThread(NULL, 0, RecvThread, (LPVOID)&szThreadInput, 0, &dwThreadId); if( NULL == g_hRecvThread ) { DWORD dwError = GetLastError(); AfxMessageBox("CreateThread - Error"); return (DWORD) -1 ; } Sleep(10); iFreeIndex = GetFreeSendHandleIndex(); g_hSendThread[iFreeIndex] = CreateThread(NULL, 0, SendThread, (LPVOID)&port_id, 0, &dwThreadId); if( NULL == g_hSendThread ) { DWORD dwError = GetLastError(); AfxMessageBox("CreateThread - Error "); return (DWORD) -1 ; } Sleep(100); } else { //AfxMessageBox("Fail to Start!!"); SetEvent(g_ahSendnExitEvent[1]); return (DWORD) -1 ; } if( WaitForSingleObject(g_ahSendnExitEvent[1], 0) != WAIT_TIMEOUT) { return (DWORD) -1; } } return (DWORD) -1; } DWORD WINAPI RecvThread(LPVOID param) { CString szLogMsg = _T(""); THREAD_INPUT szThreadInput; szThreadInput = *(PTHREAD_INPUT)param; szLogMsg.Format( "RecvThread Arg Value = %d \n", szThreadInput.nPort_id ); AfxTrace(szLogMsg); szLogMsg.Format( "RecvThread Client IP = %s \n", szThreadInput.sClientThreadInfo.szClientIp); AfxTrace(szLogMsg); szLogMsg.Format( "RecvThread Client IP = %s \n", szThreadInput.sClientThreadInfo.szClientPort); AfxTrace(szLogMsg); //PCLIENT_INFO psClientInfo; int len = 2048; slan_SetReadTimeouts (szThreadInput.nPort_id, 0); while( TRUE ) { pointer->WriteDataToApp(&szThreadInput); if( WaitForSingleObject(g_ahSendnExitEvent[1], 0) != WAIT_TIMEOUT) { return (DWORD) -1; } Sleep(10); } return (DWORD) -1; } DWORD WINAPI SendThread(LPVOID param) { CString szLogMsg = _T(""); int port_id; int iStatus; port_id = *(PINT) param; DWORD dwReturnWaitValue; szLogMsg.Format( "SendThread Arg Value = %d \n", port_id ); AfxTrace(szLogMsg); while( TRUE ) { dwReturnWaitValue = WaitForMultipleObjects( 2, g_ahSendnExitEvent, FALSE, INFINITE); if( (dwReturnWaitValue - WAIT_OBJECT_0) == 1)//Exit Event has been set { pointer->UpdateConnectionCount( FALSE ); slan_close( port_id ); return (DWORD) -1; } ResetEvent(g_ahSendnExitEvent[0]); iStatus = pointer->SendDataToClient(port_id); if(iStatus == SLAN_SND_ERR) { pointer->UpdateConnectionCount( FALSE ); slan_close( port_id ); szLogMsg.Format( "Send Error %d \n", iStatus ); AfxMessageBox(szLogMsg); return (DWORD) -1; } } return (DWORD) -1; } ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMultiPortDlg dialog CMultiPortDlg::CMultiPortDlg(CWnd* pParent /*=NULL*/) : CDialog(CMultiPortDlg::IDD, pParent) { //{{AFX_DATA_INIT(CMultiPortDlg) m_ServerPort1 = 0; //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); //Initialisation m_bCancel = FALSE; m_uiConCount = 0; InitializeCriticalSection( &m_csLock ); } void CMultiPortDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMultiPortDlg) DDX_Control(pDX, IDC_TRANSMITTER, m_Transmitter1); DDX_Control(pDX, IDC_RECEIVER1, m_Receiver1); DDX_Control(pDX, IDC_SERVER_PORT1, m_ServerPort1Ctrl); DDX_Control(pDX, IDC_OPEN, m_OpenCtrl); DDX_Control(pDX, IDC_CLOSE, m_CloseCtrl); DDX_Text(pDX, IDC_SERVER_PORT1, m_ServerPort1); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CMultiPortDlg, CDialog) //{{AFX_MSG_MAP(CMultiPortDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_OPEN, OnOpen) ON_BN_CLICKED(IDC_CLOSE, OnClose) ON_EN_CHANGE(IDC_TRANSMITTER1, OnChangeTransmitter1) ON_BN_CLICKED(IDC_BTN_EXIT, OnBtnExit) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMultiPortDlg message handlers BOOL CMultiPortDlg::OnInitDialog() { for(int i = 0;i < MAX_CONNECTIONS;i++) { g_hRecvThread[i] = INVALID_HANDLE_VALUE; g_hSendThread[i] = INVALID_HANDLE_VALUE; } CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here UpdateData(FALSE); pointer = this; m_OpenCtrl.EnableWindow(TRUE); m_CloseCtrl.EnableWindow(FALSE); //m_ServerIP1Ctrl.EnableWindow(TRUE); CIPAddressCtrl *pIpAddrCtrl = NULL; pIpAddrCtrl = (CIPAddressCtrl *)GetDlgItem(IDC_SERVER_IPADDRESS); pIpAddrCtrl->EnableWindow( TRUE ); m_ServerPort1Ctrl.EnableWindow(TRUE); m_Transmitter1.EnableWindow(FALSE); return TRUE; // return TRUE unless you set the focus to a control } void CMultiPortDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMultiPortDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMultiPortDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CMultiPortDlg::GetInputData() { UpdateData(TRUE); } int CMultiPortDlg::SendDataToClient(int port_id) { char cSendChar; findCharToSend(&cSendChar); int ret = slan_write(port_id, &cSendChar, 1 ); return ret; }; void CMultiPortDlg::WriteDataToApp(PTHREAD_INPUT pszThreadInput) { char szStr[3072]; CString strTemp; CString strResult; char strClientInfo[100]; int len = 2048; int ret = slan_read(pszThreadInput->nPort_id, szStr, &len); if(ret>=0) { if(!len) Sleep(1000); if( len > 0) { sprintf( strClientInfo,"\r\n[ %s : %s ] - ", pszThreadInput->sClientThreadInfo.szClientIp, pszThreadInput->sClientThreadInfo.szClientPort); szStr[len] = '\0'; m_Receiver1.GetWindowText(strTemp); strResult.Format("%s%s%s", strTemp, strClientInfo, szStr); m_Receiver1.SetWindowText(strResult); } } else { SetEvent(g_ahSendnExitEvent[1]); } }; void CMultiPortDlg::UpdateConnectionCount( BOOL bIncrement ) { CString szConnCount = _T(""); EnterCriticalSection( &m_csLock ); if( bIncrement ) { m_uiConCount++; } else { m_uiConCount--; } szConnCount.Format( "%d", m_uiConCount ); GetDlgItem(IDC_STATIC_CLIENTCOUNT)->SetWindowText(szConnCount); LeaveCriticalSection( &m_csLock ); } void CMultiPortDlg::OnOpen() { // TODO: Add your control notification handler code here GetInputData(); OPMODE eMode; INPUTS sParam; CString szServerIp = _T(""); CIPAddressCtrl *pIpAddrCtrl = NULL; pIpAddrCtrl = (CIPAddressCtrl *)GetDlgItem(IDC_SERVER_IPADDRESS); pIpAddrCtrl->GetWindowText( szServerIp ); //Validate the inputs... if( szServerIp.IsEmpty() || 0==pointer->m_ServerPort1) { AfxMessageBox( "Enter the proper Inputs !!" ); return; } slan_init(); eMode = TCP_CLNT; sprintf(sParam.tcp.ip,szServerIp); sParam.tcp.portno = m_ServerPort1; port_index = slan_open(eMode, sParam); if( port_index >= 0 ) { AfxMessageBox("OK"); int port_id; g_ahSendnExitEvent[0] = CreateEvent(NULL, TRUE, FALSE, NULL ); g_ahSendnExitEvent[1] = CreateEvent(NULL, TRUE, FALSE, NULL ); g_hMainThread = CreateThread(NULL, 0, AcceptThread, (LPVOID)&port_id, 0, &dwThreadId); g_hMonitorEventThread = CreateThread(NULL, 0, MonitorEventThread, (LPVOID)&port_id, 0, &dwThreadId); m_OpenCtrl.EnableWindow(FALSE); m_CloseCtrl.EnableWindow(TRUE); CIPAddressCtrl *pIpAddrCtrl = NULL; pIpAddrCtrl = (CIPAddressCtrl *)GetDlgItem(IDC_SERVER_IPADDRESS); pIpAddrCtrl->EnableWindow(FALSE); //m_ServerIP1Ctrl.EnableWindow(FALSE); m_ServerPort1Ctrl.EnableWindow(FALSE); m_Transmitter1.EnableWindow(TRUE); m_Transmitter1.SetFocus(); } else AfxMessageBox("Fail"); } void CMultiPortDlg::OnClose() { // TODO: Add your control notification handler code here //Momentarily to allow send thread to exit SetEvent(g_ahSendnExitEvent[1]); } void CMultiPortDlg::OnChangeTransmitter1() { // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask() // with the ENM_CHANGE flag ORed into the mask. // TODO: Add your control notification handler code here //calculate the current Cursor position index SetEvent(g_ahSendnExitEvent[0]); } void CMultiPortDlg::OnCancel() { // TODO: Add extra cleanup here //To close the Slan Library inline with slan_open in OnInitDialog } void CMultiPortDlg::OnBtnExit() { // TODO: Add your control notification handler code here slan_end(); CDialog::OnCancel(); } void CMultiPortDlg::findCharToSend(char* pcSendChar) { WORD wLineIndex = 0; WORD dwGetSel = 0; WORD wStart = 0; DWORD wColNumber = 0; DWORD wLineNumber = 0; DWORD cbText = 0; char szBuf[2048] = {0}; CEdit* pEdit = (CEdit*)GetDlgItem(IDC_TRANSMITTER); wLineNumber = pEdit->SendMessage(EM_LINEFROMCHAR, -1, 0L); dwGetSel = (WORD)pEdit->SendMessage(EM_GETSEL,0, 0L); wStart = LOWORD(dwGetSel); wLineIndex = (WORD)pEdit->SendMessage(EM_LINEINDEX, -1, 0L); wColNumber = wStart - wLineIndex; *(WORD *)szBuf = sizeof(szBuf); cbText = pEdit->SendMessage(EM_GETLINE, wLineNumber,(DWORD)(LPSTR) szBuf); szBuf[cbText] = '\0'; *pcSendChar = szBuf[wColNumber-1]; } BOOL CMultiPortDlg::PreTranslateMessage(MSG* pMsg) { if ((pMsg->message == WM_KEYDOWN) && (pMsg->hwnd == GetDlgItem( IDC_TRANSMITTER )->m_hWnd)) { int nVirtKey = (int) pMsg->wParam; if (nVirtKey == VK_DELETE || nVirtKey == VK_BACK) return TRUE; } return CDialog::PreTranslateMessage(pMsg); }