localserver.cpp

来自「mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体」· C++ 代码 · 共 401 行

CPP
401
字号

#include "stdafx.h"
#include "LocalServer.h"
#include "ChannelMenu.h"

#if USE_NAT
#include "../../natproxy/Client/nsvrctrl.h"
#endif
#pragma comment(lib, "Ws2_32.lib")

CLocalServer* CLocalServer::m_pLocalServer = NULL;
extern volatile HWND g_hMainWnd;;

// { Implementation of CLocalServer
DWORD WINAPI CLocalServer::_ConnectProc(LPVOID lpParam)
{
	CLocalServer *pLocalServer = (CLocalServer *)lpParam;
	assert(pLocalServer);
	sockaddr saddr;
	int iSize = sizeof(saddr);

	SOCKET Sock;
	while( (Sock = accept(pLocalServer->m_ListenSocket, &saddr, &iSize)) != INVALID_SOCKET )
	{
		if(!pLocalServer->AddChannel(Sock))
		{
			assert(0);
		}
	}

	CloseHandle(pLocalServer->m_hConncetThread);
	pLocalServer->m_hConncetThread = NULL;

	return 0;
}

CLocalServer::CLocalServer()
: m_ThreadRef(0), m_uChlCounter(0), m_ListenSocket(INVALID_SOCKET),
  m_ErrMsgID(0), m_bConnStop(false), m_hConncetThread(NULL)
{
}

CLocalServer::~CLocalServer()
{
//	Stop();
}

CLocalServer *CLocalServer::CreateInstance()
{
	if(m_pLocalServer == NULL)
	{
		m_pLocalServer = new CLocalServer();
	}

	return m_pLocalServer;
}

void CLocalServer::DeleteInstance()
{
	if(m_pLocalServer)
	{
		delete m_pLocalServer;
		m_pLocalServer = NULL;
	}
}

void    CLocalServer::HandleLocalSrvNotify(WPARAM wparam, LPARAM lparam)
{
    switch(wparam)
    {
    case CASE_THREAD_EXIT:
        assert(m_ThreadRef != 0);
        if(m_ThreadRef == 0)
            FireExit();
        m_ThreadRef --;
        if(m_ThreadRef == 0)
            FireExit();
        break;
    }

}

void    CLocalServer::FireExit()
{
    if(m_ThreadRef == 0)
        PostMessage(g_hMainWnd, WM_EXIT_EX, 0, 0);
}

#if USE_NAT

#define SERVICE_FILENAME "service.exe"

BOOL CLocalServer::InitNatProxy()
{
	STARTUPINFO si;
	PROCESS_INFORMATION pi ;

	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	ZeroMemory(&pi, sizeof(pi));

	char apppath[0xff];
	::GetModuleFileName(NULL, apppath, 0xff);
	char* p = apppath;
	while(strchr(p, '\\')) 
	{ 
		p = strchr(p, '\\'); 
		p++; 
	}
	*p = '\0';
	strcat(apppath, SERVICE_FILENAME);

	if (CreateProcess(apppath, NULL, NULL, NULL, FALSE, 
		NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW, 
		NULL, NULL, &si, &pi))
	{
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		return TRUE;
	}
	return FALSE;
}

BOOL CLocalServer::ExitNatProxy()
{
	NSvrCtrl nsc;
	nsc.Exit();
	Sleep(10);	// wait udp send
	return TRUE;
}

#endif
#define	MSGLIFETIME	5

BOOL CLocalServer::Run()
{
#if USE_NAT
	InitNatProxy();
#endif

	m_ErrMsgID = m_MsgMgr.CreateMsgID(MSGLIFETIME);

	if(!InitNetWork())
	{
		assert(0);
		m_MsgMgr.DeleteMsgID(m_ErrMsgID);
		return FALSE;
	}
	else
	{
		sockaddr_in LocalAddr;
		memset(&LocalAddr, 0, sizeof(LocalAddr));

		LocalAddr.sin_family = AF_INET;
		LocalAddr.sin_port = htons(short(LOCALSERVERPORT));

		char sLocalName[MAX_PATH] = "";
		gethostname(sLocalName, sizeof(sLocalName));
		hostent *ht = gethostbyname(sLocalName);
		char *sIP = inet_ntoa((*(struct in_addr *)*ht->h_addr_list));
		LocalAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

		if(bind(m_ListenSocket, (sockaddr*)&LocalAddr, sizeof(sockaddr)) != 0)
		{
			WSACleanup();
			return FALSE;
		}

		if(listen(m_ListenSocket, MAX_PENDING_SOCKET) != 0)
		{
			WSACleanup();
			return FALSE;
		}

		if(NULL == (m_hConncetThread = CreateThread(NULL, 0, _ConnectProc,
			(LPVOID)this, 0, &m_dwConnectThreadID)))
		{
			WSACleanup();
			return FALSE;
		}

		return TRUE;
	}
}

void CLocalServer::Stop()
{
	if( INVALID_SOCKET != m_ListenSocket )
	{
		closesocket(m_ListenSocket);
		m_ListenSocket = INVALID_SOCKET;
	}
	if( m_hConncetThread )
	{
		if( WaitForSingleObject(m_hConncetThread, 3000) != WAIT_OBJECT_0 )
		{
			TerminateThread(m_hConncetThread, 0);
			m_hConncetThread = NULL;
		}
	}

	ChannelMap::iterator itr = NULL;
	for(itr=m_ChannelMap.begin(); itr!=m_ChannelMap.end(); itr++)
	{
		CChannelMgr::Dellocator(itr->second, TRUE);
	}
	m_ChannelMap.clear();
#if USE_NAT
	ExitNatProxy();	
#endif

	m_MsgMgr.DeleteMsgID(m_ErrMsgID);
	m_ErrMsgID = 0;
	WSACleanup();
}

BOOL CLocalServer::AddChannel(SOCKET Sock)
{
	assert(INVALID_SOCKET != Sock);

	m_uChlCounter += 1;
	CHANNELID ChannelID = m_uChlCounter;
	CChannelMgr *pChannelMgr = CChannelMgr::Allocator(ChannelID);
	
	if(!pChannelMgr->Init(Sock))
	{
		CChannelMgr::Dellocator(pChannelMgr);
		assert(0);
		return FALSE;
	}

	CAutoLock lock(&m_MapCritSec);
	m_ChannelMap.insert(ChannelMap::value_type(ChannelID, pChannelMgr));
    CChannelMenu::GetInstance()->SetChannelRunning(TRUE);

	return TRUE;
}

void CLocalServer::DeleteChannel(CHANNELID ChannelID)
{
	ChannelMap::iterator itr = NULL;

	CAutoLock lock(&m_MapCritSec);
	for(itr=m_ChannelMap.begin(); itr!=m_ChannelMap.end(); itr++)
	{
		if(ChannelID == itr->first)
		{
			CChannelMgr *pChannelMgr = itr->second;
			if(pChannelMgr->DeadforFatalError())	//将最终的一条错误信息加进localserver
			{
				CString strRet, strRetErr;
				pChannelMgr->GetChannelName(strRet);
				CChannelMgr::HandleLayerErrCode(pChannelMgr->GetErrorCode(), strRetErr);
				strRet += strRetErr;
				m_MsgMgr.UpdateMessage(m_ErrMsgID, strRet, CMsgMgr::FORCESHOW | MSGLIFETIME);
			}

			m_ChannelMap.erase(itr);
			CChannelMgr::Dellocator(pChannelMgr);
			break;
		}
	}

    if(m_ChannelMap.empty())
        CChannelMenu::GetInstance()->SetChannelRunning(FALSE);

}

UINT CLocalServer::GetChannelNum()
{
	CAutoLock lock(&m_MapCritSec);
	UINT uChannelNum = (UINT)m_ChannelMap.size();
	return uChannelNum;
}

void CLocalServer::GetChannelIDArray(CHANNELID *pChannelIDArray)
{
	int i = 0;
	ChannelMap::iterator itr = NULL;

	CAutoLock lock(&m_MapCritSec);
	for(itr=m_ChannelMap.begin(); itr!=m_ChannelMap.end(); itr++)
	{
		*(pChannelIDArray+i) = itr->first;
		i++;
	}
}

void CLocalServer::GetChannelMgrArray(CChannelMgr* pChannelMgrArray[])
{
	int i = 0;
	ChannelMap::iterator itr = NULL;

	CAutoLock lock(&m_MapCritSec);
	for(itr=m_ChannelMap.begin(); itr!=m_ChannelMap.end(); itr++)
	{
		pChannelMgrArray[i] = itr->second;
		i++;
	}
}

void GetChannelName(CHANNELID ChannelID);

CChannelMgr *CLocalServer::GetChannelMgr(CHANNELID ChannelID)
{
	ChannelMap::iterator itr = NULL;

	CAutoLock lock(&m_MapCritSec);
	for(itr=m_ChannelMap.begin(); itr!=m_ChannelMap.end(); itr++)
	{
		if(ChannelID == itr->first)
		{
			return itr->second;
		}
	}

	return NULL;
}

void CLocalServer::UpdateNoChannelMsg()
{
	MultiLanguage	LangDll;
	CString strChl;
	strChl = LangDll.GetStringByStr(_T("当前没有频道"));
	m_MsgMgr.UpdateMessage(m_ErrMsgID, strChl, CMsgMgr::FORCESHOW | MSGLIFETIME);
}

void CLocalServer::UpdateLayer1Notify(WPARAM wparam, LPARAM lparam)
{
	CHANNELID chlID = HIWORD(wparam);
	UINT16	RetType = LOWORD(wparam);

	CChannelMgr* pMgr = GetChannelMgr(chlID);
	CString strRet;
	if(pMgr)
	{
		pMgr->GetChannelName(strRet);
	}	

	MultiLanguage	LangDll;
	int	RetTypeOrigin = (SHORT) RetType ;

	switch(RetTypeOrigin)
	{
	case PNT_CANNOT_LOGON_TS:
		strRet += LangDll.GetStringByStr(_TEXT("无法登陆服务器,可能是服务暂时停止,或者是本台机器的防火墙在捣乱。"));	
		break;
	case PNT_NO_CP:
		strRet += LangDll.GetStringByStr(_TEXT("没有数据服务器,请联系服务商。"));
		break;
	case PNT_CHNL_CLOSED:
		strRet += LangDll.GetStringByStr(_TEXT("此频道已经关闭,清尝试其他打开的频道。"));
		break;
	case PNT_NO_SUCH_RES:
		strRet += LangDll.GetStringByStr(_TEXT("服务器上没有这个频道,请确认你打开的URL或者GTV文件是最新的。"));
		break;
	case PNT_CHNL_ENDED:
		strRet += LangDll.GetStringByStr(_TEXT("此频道到此结束,谢谢观看。"));
		break;
	case PNT_LOW_VERSION:
		strRet += LangDll.GetStringByStr(_TEXT("您使用的是旧版客户端,请到www.Openmysee.com下载最新版的客户端。"));
		break;
	case PNT_DISK_ERR:
		strRet += LangDll.GetStringByStr(_TEXT("将数据写入磁盘时出错,请检查是否磁盘已满。"));
		break;
	default:
		strRet += LangDll.GetStringByStr(_TEXT("未知类型的错误,请重新播放此频道!"));
		break;
	}
	m_MsgMgr.UpdateMessage(m_ErrMsgID, strRet, CMsgMgr::FORCESHOW | MSGLIFETIME, CMsgMgr::MSGLV_WARNING);
}

CMsgMgr* CLocalServer::GetMsgMgr()
{
	return &m_MsgMgr;
}

BOOL CLocalServer::InitNetWork()
{
	WSADATA WsaData;

	if(WSAStartup(MAKEWORD(2, 2), &WsaData) != 0)
		return FALSE;

	if(LOBYTE(WsaData.wVersion) != 2 || HIBYTE(WsaData.wVersion) != 2)
	{
		WSACleanup();
		return FALSE;
	}

	m_ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
	if(INVALID_SOCKET == m_ListenSocket)
	{
		WSACleanup();
		return FALSE;
	}

	return TRUE;
}
// Implementation of CLocalServer }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?