////////////////////////////////////////////////////////////////////////// // Lan protocol #include "stdafx.h" CLan::CLan() { m_income = INVALID_SOCKET; m_filesoc = INVALID_SOCKET; m_status = LS_OK; m_mode = LM_OFF; m_hListenThread = NULL; m_hAcceptTCPThread = NULL; InitializeCriticalSection(&m_csAcceptTCPThread); Startup(); } CLan::~CLan() { Shutdown(); DeleteCriticalSection(&m_csAcceptTCPThread); } void CLan::Startup() { WSADATA wsa; if (WSAStartup(MAKEWORD(2,2), &wsa)==0) { m_status = LS_OK; m_mode = LM_ON; char hostname[256]; if (gethostname(hostname, 256)==0) { hostent* host = gethostbyname(hostname); char** pAddr = host->h_addr_list; m_hostAddrCount = 0; while (*pAddr && m_hostAddrCount<MAX_INTERNAL_IP) { in_addr addr; addr.S_un.S_addr = *((u_long*)(*pAddr)); m_hostAddr[m_hostAddrCount++] = addr; pAddr++; } m_curAddr = m_hostAddr[0]; } else { m_status = LS_CANT_GET_HOSTADDR; } } else { m_status = LS_OK; m_mode = LM_OFF; } } void CLan::Shutdown() { if (m_mode == LM_OFF) return; m_hostAddrCount = 0; StopListen(); WSACleanup(); m_status = LS_OK; m_mode = LM_OFF; } void CLan::StopListen() { if (m_mode==LM_OFF) return; if (m_hListenThread) { TerminateThread(m_hListenThread, 0); m_hListenThread = NULL; } if (m_hAcceptTCPThread) { EnterCriticalSection(&m_csAcceptTCPThread); TerminateThread(m_hAcceptTCPThread, 0); m_hAcceptTCPThread = NULL; LeaveCriticalSection(&m_csAcceptTCPThread); } if (m_income != INVALID_SOCKET) { closesocket(m_income); m_income = INVALID_SOCKET; } if (m_filesoc != INVALID_SOCKET) { closesocket(m_filesoc); m_filesoc = INVALID_SOCKET; } m_mode = LM_ON; } void CLan::StartListen() { if (m_mode!=LM_ON) return; m_income = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); m_filesoc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_income == INVALID_SOCKET || m_filesoc == INVALID_SOCKET) { m_status = LS_CANT_CREATE_SOCKET; StopListen(); } else { int enable = 1; if (setsockopt(m_income, SOL_SOCKET, SO_BROADCAST, (const char*)&enable, sizeof(enable))!=0) { m_mode = LM_ON; m_status = LS_CANT_TURN_ON_BROADCAST; StopListen(); return; } m_mode = LM_LISTEN; sockaddr_in addr; addr.sin_addr = m_curAddr; addr.sin_family = AF_INET; addr.sin_port = PORT_NUMBER; if (bind(m_income, (sockaddr*)&addr, sizeof(addr))!=0) { m_mode = LM_ON; m_status = LS_CANT_BIND_SOCKET; StopListen(); return; } if (bind(m_filesoc, (sockaddr*)&addr, sizeof(addr))!=0) { m_mode = LM_ON; m_status = LS_CANT_BIND_SOCKET; StopListen(); return; } if (listen(m_filesoc, SOMAXCONN)!=0) { m_mode = LM_ON; m_status = LS_CANT_START_LISTEN; StopListen(); return; } DWORD threadId; m_hListenThread = CreateThread(NULL, 0, ListenProc, (LPVOID)this, 0, &threadId); m_hAcceptTCPThread = CreateThread(NULL, 0, AcceptTCPProc, (LPVOID)this, 0, &threadId); if (m_hListenThread==NULL || m_hAcceptTCPThread==NULL) { m_mode = LM_ON; m_status = LS_CANT_CREATE_THREADS; StopListen(); return; } } } void CLan::SetCurHostAddress(in_addr addr) { if (m_mode!=LM_OFF) { int oldMode = m_mode; StopListen(); m_curAddr = addr; if (oldMode==LM_LISTEN) StartListen(); } } DWORD WINAPI CLan::ListenProc(LPVOID lpParameter) { CLan* lan = (CLan*)lpParameter; lan->Listen(); return 0; } void CLan::Listen() { if (m_mode==LM_LISTEN) { char buf[65536]; while(1) { sockaddr_in addr; int addrLen = sizeof(addr); Sleep(20); int recLen = recvfrom(m_income, buf, 65536, 0, (sockaddr*)&addr, &addrLen); if (recLen!=SOCKET_ERROR) OnRecvPacket((u_char*)buf, recLen, addr.sin_addr); } } } void CLan::SendPacketBroadcast(const u_char* mes, int len) { in_addr addr; addr.S_un.S_addr = INADDR_BROADCAST; SendPacket(addr, mes, len); } void CLan::SendPacket(in_addr addr, const u_char* mes, int len) { if (m_mode==LM_LISTEN) { sockaddr_in addrTo; addrTo.sin_addr = addr; addrTo.sin_family = AF_INET; addrTo.sin_port = PORT_NUMBER; int res = sendto(m_income, (const char*)mes, len, 0, (sockaddr*)&addrTo, sizeof(addrTo)); } } ////////////////////////////////////////////////////////////////////////// DWORD WINAPI CLan::AcceptTCPProc(LPVOID lpParameter) { CLan* lan = (CLan*)lpParameter; lan->AcceptTCP(); return 0; } void CLan::AcceptTCP() { while (1) { SOCKET in_socket; sockaddr_in addrFrom; int addrLen = sizeof(addrFrom); in_socket = accept(m_filesoc, (sockaddr*)&addrFrom, &addrLen); EnterCriticalSection(&m_csAcceptTCPThread); if (in_socket != INVALID_SOCKET) { TTCPConnect* tcp_conn = new TTCPConnect; tcp_conn->m_addr = addrFrom.sin_addr.S_un.S_addr; tcp_conn->m_lan = this; tcp_conn->m_socket = in_socket; DWORD threadId; CreateThread(NULL, 0, OnInTCPConnectionProc, (LPVOID)tcp_conn, 0, &threadId); } LeaveCriticalSection(&m_csAcceptTCPThread); Sleep(100); } } DWORD WINAPI CLan::OnInTCPConnectionProc(LPVOID lpParameter) { TTCPConnect* tcp_conn = (TTCPConnect*)lpParameter; tcp_conn->m_lan->OnInTCPConnection(tcp_conn->m_addr, tcp_conn->m_socket); shutdown(tcp_conn->m_socket, SD_BOTH); closesocket(tcp_conn->m_socket); delete tcp_conn; return 0; } SOCKET CLan::CreateTCPConnection(u_long addr, LPVOID lpParameter) { SOCKET out_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (out_socket==INVALID_SOCKET) return INVALID_SOCKET; sockaddr_in addrTo; addrTo.sin_addr.S_un.S_addr = addr; addrTo.sin_family = AF_INET; addrTo.sin_port = PORT_NUMBER; if (connect(out_socket, (sockaddr*)&addrTo, sizeof(addrTo))!=0) { closesocket(out_socket); out_socket = INVALID_SOCKET; } //OnOutTCPConnectionProc is called anyway TTCPConnect* tcp_conn = new TTCPConnect; tcp_conn->m_socket = out_socket; tcp_conn->m_lan = this; tcp_conn->m_addr = addr; tcp_conn->m_lpParameter = lpParameter; DWORD threadId; CreateThread(NULL, 0, OnOutTCPConnectionProc, (LPVOID)tcp_conn, 0, &threadId); return out_socket; } DWORD WINAPI CLan::OnOutTCPConnectionProc(LPVOID lpParameter) { TTCPConnect* tcp_conn = (TTCPConnect*)lpParameter; tcp_conn->m_lan->OnOutTCPConnection(tcp_conn->m_addr, tcp_conn->m_socket, tcp_conn->m_lpParameter); shutdown(tcp_conn->m_socket, SD_BOTH); closesocket(tcp_conn->m_socket); delete tcp_conn; return 0; }