rnb_err_t RNBSocket::Connect (const char *host, uint16_t port) { Disconnect (false); // Create the socket m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_fd == -1) return rnb_err; // Enable local address reuse SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); struct sockaddr_in sa; ::memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; sa.sin_port = htons (port); if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr)) { DNBLogThreaded("error: failed to resolve host '%s'", host); Disconnect (false); return rnb_err; } if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) { Disconnect (false); return rnb_err; } // Keep our TCP packets coming without any delays. SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); return rnb_success; }
rnb_err_t RNBSocket::Connect (const char *host, uint16_t port) { Disconnect (false); // Create the socket m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_fd == -1) return rnb_err; // Enable local address reuse SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); struct sockaddr_in sa; ::memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; sa.sin_port = htons (port); if (host == NULL) host = "localhost"; int inet_pton_result = ::inet_pton (AF_INET, host, &sa.sin_addr); if (inet_pton_result <= 0) { struct hostent *host_entry = gethostbyname (host); if (host_entry) { std::string host_str (::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list)); inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); if (inet_pton_result <= 0) { Disconnect (false); return rnb_err; } } } if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) { Disconnect (false); return rnb_err; } // Keep our TCP packets coming without any delays. SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); return rnb_success; }
MPIPTVSOURCE_API int SetAndCheckSocketOption(CLogger *logger, const TCHAR *protocolName, const TCHAR *functionName, const TCHAR *optionName, SOCKET s, int level, int optname, const char *optval, int optlen) { int result = SetSocketOption(logger, protocolName, functionName, optionName, s, level, optname, optval, optlen); if (result == 0) { // option correctly set, now check it int valLen = optlen; ALLOC_MEM_DEFINE_SET(val, char, optlen, 0); result = (val == NULL) ? E_OUTOFMEMORY : 0; if (result == 0) { result = GetSocketOption(logger, protocolName, functionName, optionName, s, level, optname, val, &valLen); if (result == 0) { // successfully retrieved value if (optlen == valLen) { result = (memcmp(optval, val, optlen) == 0) ? 0 : (-1); } } } FREE_MEM(val); }
MPIPTVSOURCE_API int JoinMulticastGroupIPv6(CLogger *logger, const TCHAR *protocolName, SOCKET m_socket, const struct sockaddr_in6 *local, CParameterCollection *parameters) { int result = 0; struct ipv6_mreq gr6; memset(&gr6, 0, sizeof(gr6)); gr6.ipv6mr_interface = local->sin6_scope_id; memcpy(&gr6.ipv6mr_multiaddr, &local->sin6_addr, 16); if (parameters != NULL) { // we have set some parameters // get interface parameter PCParameter networkInterfaceParameter = parameters->GetParameter(INTERFACE_PARAMETER_NAME, true); if (networkInterfaceParameter != NULL) { ULONG interfaceId = GetInterfaceId(logger, protocolName, networkInterfaceParameter->GetValue(), local->sin6_family); result = (interfaceId != 0) ? 0 : (-1); if (result == 0) { gr6.ipv6mr_interface = interfaceId; logger->Log(LOGGER_INFO, _T("%s: %s: try to bind on interface '%s', id: %u"), protocolName, METHOD_JOIN_MULTICAST_GROUP_IPV6_NAME, networkInterfaceParameter->GetValue(), gr6.ipv6mr_interface); } else { logger->Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, protocolName, METHOD_JOIN_MULTICAST_GROUP_IPV6_NAME, _T("cannot get interface ID")); } } } logger->Log(LOGGER_INFO, METHOD_MESSAGE_FORMAT, protocolName, METHOD_JOIN_MULTICAST_GROUP_IPV6_NAME, _T("IPV6_JOIN_GROUP multicast request")); result = (SetSocketOption(logger, protocolName, METHOD_JOIN_MULTICAST_GROUP_IPV6_NAME, _T("IPV6_JOIN_GROUP"), m_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&gr6, sizeof(gr6)) == 0) ? 0 : (-1); logger->Log(LOGGER_INFO, (result == 0) ? METHOD_END_FORMAT : METHOD_END_FAIL_FORMAT, protocolName, METHOD_JOIN_MULTICAST_GROUP_IPV6_NAME); return result; }
void NetIO::Init() { listen_fd = socket(AF_INET, SOCK_STREAM, 0); if(listen_fd == -1) error("Error %d occured in socket()", errno); if(is_server) { if(!SetSocketOption(listen_fd, SOL_SOCKET, SO_REUSEADDR, 1)) error("Error %d occured in SetSocketOption(listen_fd, SO_REUSEADDR)", errno); } sockaddr_in servaddr; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port); if(ip_address != NULL) { if(inet_pton(AF_INET, ip_address, &servaddr.sin_addr) == -1) error("Error %d occured in inet_pton(%s)", errno, ip_address); } else servaddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(listen_fd, (sockaddr*) &servaddr, sizeof(servaddr)) == -1) error("Error %d occured in bind()", errno); }
void CSocketItems::ApplyBonusOptions(LPOBJ lpObj) { BYTE btBonusOption = 0; _SOCKET_BONUS_DATA* lpBonusOption = NULL; for(int i = 0; i < INVETORY_WEAR_SIZE; i++) { if( IsSocketItem(&lpObj->pInventory[i]) == FALSE ) continue; btBonusOption = lpObj->pInventory[i].m_SocketBonus; if( btBonusOption == 0xFF || btBonusOption == 0xFE ) continue; lpBonusOption = GetBonusOption(btBonusOption); if( lpBonusOption == NULL ) continue; LogAddTD("[SocketItem] [%s][%s] Set Bonus Socket Option - OptionIndex : %d, EffectType : %d, OptionType : %d, OptionValue : %d", lpObj->AccountID,lpObj->Name,lpBonusOption->btIndex,lpBonusOption->btEffectType,lpBonusOption->btOptionType,lpBonusOption->btOptionValue); SetSocketOption(lpObj,2,lpBonusOption->btEffectType,lpBonusOption->btOptionType,lpBonusOption->btOptionValue); } }
int CSocketItems::ApplySocketOptions(LPOBJ lpObj) { int OptionCount = 0; BYTE btSocketOption = 0; BYTE btOption = 0; BYTE btLevel = 0; _SOCKET_SPHERE_OPTION tmpSphere; for(int i = 0; i < INVETORY_WEAR_SIZE; i++) { if( IsSocketItem(&lpObj->pInventory[i]) == FALSE ) continue; for(int n = 0; n < MAX_SOCKET_COUNT; n++) { btSocketOption = lpObj->pInventory[i].m_SocketOption[n]; if( btSocketOption == 0xFF || btSocketOption == 0xFE ) continue; btOption = btSocketOption%50; btLevel = (btSocketOption-btOption)/50+1; if( IsOptionSet(&tmpSphere,btOption,btLevel) == FALSE ) continue; SetSocketOption(lpObj,TRUE,btOption,tmpSphere.btIncType,tmpSphere.wSphereValue); OptionCount++; } } return OptionCount; }
//////////////////////////////////////////////////////////////////////////////// // 函数名:SOCKET Accept( // struct sockaddr * pSocketAddr, // LPINT nAddrLen, // DWORD dwTimeout /*= DEFAULT_ACCEPT_TIMEOUT*/ ) // 用 途:接受套接字连接 // 对全局变量的影响:无 // 参 数: // pSocketAddr : SOCKET地址 // nAddrLen : 地址参数的长度 // dwTimeout : 超时 // 返回值:SOCKET //////////////////////////////////////////////////////////////////////////////// SOCKET CBufSocket::Accept(struct sockaddr * pSocketAddr, LPINT nAddrLen,DWORD dwTimeout /*= DEFAULT_ACCEPT_TIMEOUT*/) { HANDLE hAcceptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hAcceptEvent == NULL) { SetLastError( (INT)GetLastError() ); return (INVALID_SOCKET); } // 注册FD_ACCEPT事件 if( WSAEventSelect(m_hSocket, (WSAEVENT) hAcceptEvent, FD_ACCEPT) == SOCKET_ERROR) { CloseHandle(hAcceptEvent); SetLastError( WSAGetLastError() ); return (INVALID_SOCKET); } SOCKET hSocketAccept = WSAAccept(m_hSocket, pSocketAddr, nAddrLen, NULL, 0); INT nConnectError = WSAGetLastError(); if ((hSocketAccept == INVALID_SOCKET) && (nConnectError == WSAEWOULDBLOCK)) { // 阻塞 DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hAcceptEvent, TRUE,dwTimeout, TRUE); if (dwWaitResult == WSA_WAIT_EVENT_0) { ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(m_hSocket,hAcceptEvent,&NetEvent) == SOCKET_ERROR) SetLastError( WSAGetLastError() ); else if(NetEvent.iErrorCode[FD_ACCEPT_BIT] !=0 ) // 发生错误 SetLastError( NetEvent.iErrorCode[FD_ACCEPT_BIT] ); else hSocketAccept = WSAAccept(m_hSocket, pSocketAddr, nAddrLen, NULL, 0); } else SetLastError( WSAGetLastError() ); } // 注销网络事件 WSAEventSelect( m_hSocket, (WSAEVENT) hAcceptEvent, 0); CloseHandle(hAcceptEvent); if (hSocketAccept != INVALID_SOCKET) { // 设置套接字的属性为地址可重用并且为非阻塞的 if ( !Block(hSocketAccept, 0) || !SetSocketOption(hSocketAccept) ) { closesocket(hSocketAccept); return (INVALID_SOCKET); } } return (hSocketAccept); }
void NetIO::Accept(WorkersPool *workers) { if(listen_fd == 0) Init(); if(!SetSocketOption(listen_fd, SOL_SOCKET, SO_RCVBUF, MAX_BUFF_SIZE)) error("Error %d occured in SetSocketOption(listen_fd, SO_RCVBUF, %d)", errno, MAX_BUFF_SIZE); if(!SetSocketOption(listen_fd, SOL_SOCKET, SO_SNDBUF, MAX_BUFF_SIZE)) error("Error %d occured in SetSocketOption(listen_fd, SO_SNDBUF, %d)", errno, MAX_BUFF_SIZE); if(listen(listen_fd, -1) == -1) error("Error %d occured in listen(listen_fd)", errno); while(true) { int conn_fd = accept(listen_fd, (sockaddr*) NULL, NULL); if(terminated) return; if(conn_fd == -1) { if(errno == EINTR || errno == ECONNABORTED) continue; error("Error %d occured in accept()", errno); } if(!AddFcntl(conn_fd, O_NONBLOCK)) error("Error %d occured in AddFcntl(conn_fd, O_NONBLOCK)", errno); if(!SetSocketOption(conn_fd, SOL_SOCKET, SO_KEEPALIVE, 1)) error("Error %d occured in SetSocketOption(conn_fd, SO_KEEPALIVE, 1)", errno); if(!SetSocketOption(conn_fd, IPPROTO_TCP, TCP_NODELAY, 1)) error("Error %d occured in SetSocketOption(conn_fd, TCP_NODELAY, 1)", errno); workers->Accept(conn_fd); } }
bool CSocket::SetNoDelay(void) { m_enError = SOCK_OK; m_strErrorMsg.clear(); if (m_enType == IP_TCP && m_enType == UN_TCP) { m_enError = SOCK_TYPE; m_strErrorMsg = "socket type invalied, only TCP"; return false; } int optval = 1; return SetSocketOption(IPPROTO_TCP, TCP_NODELAY, (void *)&optval, sizeof(optval)); }
void CSocketItems::ApplySetOptions(LPOBJ lpObj) { BYTE OpCount[8]; BYTE btGroup = 0; BYTE btCount = 0; memset(&OpCount,0,sizeof(OpCount)); for(int i = 0; i < 35; i++) { btGroup = GetOptionGroup(lpObj->m_SocketOptions[i].btOption); if( btGroup == NULL ) break; OpCount[-1+btGroup] += lpObj->m_SocketOptions[i].Count; } for(int n = 0; n < MAX_SET_OPTION; n++) { for(int i = 0; i < MAX_SEED_TYPE; i++) { if( this->m_SetOption[n].SeedCount[i] <= OpCount[i] ) { btCount++; } } if( btCount == 6 ) { SetSocketOption(lpObj,3,this->m_SetOption[n].btEffect,this->m_SetOption[n].btIncType,this->m_SetOption[n].btIncValue); } btCount = 0; } }
MPIPTVSOURCE_API int UnsubscribeFromMulticastGroup(CLogger *logger, const TCHAR *protocolName, SOCKET m_socket, const struct sockaddr *source, socklen_t sourceLen, const struct sockaddr *local, socklen_t localLen, CParameterCollection *parameters) { int result = 0; int level; ULONG iid = 0; if (parameters != NULL) { // we have set some parameters // get interface parameter PCParameter networkInterfaceParameter = parameters->GetParameter(INTERFACE_PARAMETER_NAME, true); if (networkInterfaceParameter != NULL) { ULONG interfaceId = GetInterfaceId(logger, protocolName, networkInterfaceParameter->GetValue(), local->sa_family); result = (interfaceId != 0) ? 0 : (-1); if (result == 0) { iid = interfaceId; logger->Log(LOGGER_INFO, _T("%s: %s: try to bind on interface '%s', id: %u"), protocolName, METHOD_UNSUBSCRIBE_FROM_MULTICAST_GROUP_NAME, networkInterfaceParameter->GetValue(), iid); } else { logger->Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, protocolName, METHOD_UNSUBSCRIBE_FROM_MULTICAST_GROUP_NAME, _T("cannot get interface ID")); } } } if (result == 0) { switch (local->sa_family) { case AF_INET6: level = IPPROTO_IPV6; break; case AF_INET: level = IPPROTO_IP; break; default: logger->Log(LOGGER_ERROR, _T("%s: %s: not supported internet family: %d"), protocolName, METHOD_UNSUBSCRIBE_FROM_MULTICAST_GROUP_NAME, local->sa_family); result = -1; } } if (result == 0) { if (source != NULL) { switch (source->sa_family) { case AF_INET6: if (memcmp(&((const struct sockaddr_in6 *)source)->sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) { source = NULL; } break; case AF_INET: if (((const struct sockaddr_in *)source)->sin_addr.s_addr == INADDR_ANY) { source = NULL; } break; } } union { struct group_req gr; struct group_source_req gsr; } opt; socklen_t optlen; memset(&opt, 0, sizeof (opt)); if (source != NULL) { if ((localLen > sizeof (opt.gsr.gsr_group)) || (sourceLen > sizeof (opt.gsr.gsr_source))) { result = -1; } if (result == 0) { opt.gsr.gsr_interface = iid; memcpy(&opt.gsr.gsr_source, source, sourceLen); memcpy(&opt.gsr.gsr_group, local, localLen); optlen = sizeof(opt.gsr); } } else { if (localLen > sizeof (opt.gr.gr_group)) { result = -1; } if (result == 0) { opt.gr.gr_interface = iid; memcpy(&opt.gr.gr_group, local, localLen); optlen = sizeof(opt.gr); } } if (result == 0) { logger->Log(LOGGER_INFO, METHOD_MESSAGE_FORMAT, protocolName, METHOD_UNSUBSCRIBE_FROM_MULTICAST_GROUP_NAME, (source != NULL) ? _T("multicast source group leave request") : _T("multicast group leave request")); result = (SetSocketOption(logger, protocolName, METHOD_UNSUBSCRIBE_FROM_MULTICAST_GROUP_NAME, (source != NULL) ? _T("MCAST_LEAVE_SOURCE_GROUP") : _T("MCAST_LEAVE_GROUP"), m_socket, level, (source != NULL) ? MCAST_LEAVE_SOURCE_GROUP : MCAST_LEAVE_GROUP, (char *)&opt, optlen) == 0) ? 0 : (-1); if (result != 0) { result = 0; logger->Log(LOGGER_INFO, METHOD_MESSAGE_FORMAT, protocolName, METHOD_UNSUBSCRIBE_FROM_MULTICAST_GROUP_NAME, (source != NULL) ? _T("multicast source group leave request not successful") : _T("multicast group leave request not successful")); // fallback to IPv-specific APIs if ((source != NULL) && (source->sa_family != local->sa_family)) { logger->Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, protocolName, METHOD_UNSUBSCRIBE_FROM_MULTICAST_GROUP_NAME, _T("source and local internet address family not same")); result = -1; } if (result == 0) { switch (local->sa_family) { case AF_INET: if ((localLen < sizeof (struct sockaddr_in)) || ((source != NULL) && (sourceLen < sizeof (struct sockaddr_in)))) { result = -1; } if (result == 0) { result = LeaveMulticastGroupIPv4(logger, protocolName, m_socket, (const struct sockaddr_in *)source, (const struct sockaddr_in *)local, parameters); } break; case AF_INET6: if ((localLen < sizeof (struct sockaddr_in6)) || ((source != NULL) && (sourceLen < sizeof (struct sockaddr_in6)))) { result = -1; } if (result == 0) { result = LeaveMulticastGroupIPv6(logger, protocolName, m_socket, (const struct sockaddr_in6 *)local, parameters); } break; } if (result != 0) { logger->Log(LOGGER_ERROR, METHOD_MESSAGE_FORMAT, protocolName, METHOD_UNSUBSCRIBE_FROM_MULTICAST_GROUP_NAME, _T("multicast group leave error")); if (source != NULL) { logger->Log(LOGGER_WARNING, METHOD_MESSAGE_FORMAT, protocolName, METHOD_UNSUBSCRIBE_FROM_MULTICAST_GROUP_NAME, _T("trying another leave method")); result = UnsubscribeFromMulticastGroup(logger, protocolName, m_socket, NULL, 0, local, localLen, parameters); } } } } } } logger->Log(LOGGER_INFO, (result == 0) ? METHOD_END_FORMAT : METHOD_END_FAIL_FORMAT, protocolName, METHOD_UNSUBSCRIBE_FROM_MULTICAST_GROUP_NAME); return result; }
MPIPTVSOURCE_API int LeaveMulticastGroupIPv4(CLogger *logger, const TCHAR *protocolName, SOCKET m_socket, const struct sockaddr_in *source, const struct sockaddr_in *local, CParameterCollection *parameters) { ADDRINFOT *networkInterface = NULL; ADDRINFOT hints; hints.ai_family = local->sin_family; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; hints.ai_flags = AI_PASSIVE; int result = 0; if (parameters != NULL) { // we have set some parameters // get interface parameter PCParameter networkInterfaceParameter = parameters->GetParameter(INTERFACE_PARAMETER_NAME, true); if (networkInterfaceParameter != NULL) { TCHAR *networkInterfaceAddress = GetInterfaceAddress(logger, protocolName, networkInterfaceParameter->GetValue(), local->sin_family); int errorCode = GetIpAddress(networkInterfaceAddress, 0, &networkInterface, &hints); if (errorCode != 0) { logger->Log(LOGGER_ERROR, _T("%s: %s: getaddrinfo() for network interface error: %d"), protocolName, METHOD_LEAVE_MULTICAST_GROUP_IPV4_NAME, errorCode); result = -1; } if (result == 0) { logger->Log(LOGGER_INFO, _T("%s: %s: try to bind on interface '%s', address: %s"), protocolName, METHOD_LEAVE_MULTICAST_GROUP_IPV4_NAME, networkInterfaceParameter->GetValue(), networkInterfaceAddress); } FREE_MEM(networkInterfaceAddress); } } if (result == 0) { union { struct ip_mreq gr4; struct ip_mreq_source gsr4; } opt; int cmd; struct in_addr id; if (networkInterface != NULL) { id = ((sockaddr_in *)networkInterface->ai_addr)->sin_addr; } else { id.s_addr = INADDR_ANY; } socklen_t optlen; memset(&opt, 0, sizeof(opt)); if (source != NULL) { cmd = IP_DROP_SOURCE_MEMBERSHIP; opt.gsr4.imr_multiaddr = local->sin_addr; opt.gsr4.imr_sourceaddr = source->sin_addr; opt.gsr4.imr_interface = id; optlen = sizeof (opt.gsr4); } else { cmd = IP_DROP_MEMBERSHIP; opt.gr4.imr_multiaddr = local->sin_addr; opt.gr4.imr_interface = id; optlen = sizeof(opt.gr4); } logger->Log(LOGGER_INFO, METHOD_MESSAGE_FORMAT, protocolName, METHOD_LEAVE_MULTICAST_GROUP_IPV4_NAME, (source != NULL) ? _T("IP_DROP_SOURCE_MEMBERSHIP multicast request") : _T("IP_DROP_MEMBERSHIP multicast request")); result = (SetSocketOption(logger, protocolName, METHOD_LEAVE_MULTICAST_GROUP_IPV4_NAME, (source != NULL) ? _T("IP_DROP_SOURCE_MEMBERSHIP") : _T("IP_DROP_MEMBERSHIP"), m_socket, IPPROTO_IP, cmd, (char *)&opt, optlen) == 0) ? 0 : (-1); } if (networkInterface != NULL) { FreeAddrInfo(networkInterface); networkInterface = NULL; } logger->Log(LOGGER_INFO, (result == 0) ? METHOD_END_FORMAT : METHOD_END_FAIL_FORMAT, protocolName, METHOD_LEAVE_MULTICAST_GROUP_IPV4_NAME); return result; }
//////////////////////////////////////////////////////////////////////////////// // 函数名:BOOL Create( // INT nAddressFamily /*= AF_INET*/, // INT nType /*= SOCK_STREAM*/, // INT nProtocol /*= 0*/, // INT nBufferSize /*= DEFAULT_BUFFER_SIZE*/, // SOCKET hSocket /*= INVALID_SOCKET*/, // DWORD dwFlags /*= WSA_FLAG_OVERLAPPED*/ ) // 用 途:创建SOCKET和BSD结构 // 对全局变量的影响:无 // 参 数: // nAddressFamily : SOCKET地址家族 // nType : SOCKET类型 // nProtocol : SOCKET采用的协议 // nBufferSize : 缓冲区的大小 // hSocket : 类实例绑定的套接字 // dwFlags : 套接字的属性 // 返回值:BOOL //////////////////////////////////////////////////////////////////////////////// BOOL CBufSocket::Create( INT nAddressFamily /*= AF_INET*/, INT nType /*= SOCK_STREAM*/, INT nProtocol /*= 0*/, INT nBufferSize /*= DEFAULT_BUFFER_SIZE*/, SOCKET hSocket /*= INVALID_SOCKET*/, DWORD dwFlags /*= WSA_FLAG_OVERLAPPED*/) { if (INVALID_SOCKET == hSocket) { m_hSocket = WSASocket(nAddressFamily, nType, nProtocol, NULL,0,dwFlags); if (INVALID_SOCKET == m_hSocket) { SetLastError( WSAGetLastError() ); //为何获得了还需要设置 return FALSE; } } else { m_hSocket = hSocket; } if (SOCK_STREAM == nType) //TCP { //设置套接字选项 if (!SetSocketOption(m_hSocket)) //设置属性失败 { Close(TRUE); m_hSocket = INVALID_SOCKET; return FALSE; } //创建BSD //分配内存 m_pBSD = new BSD; if (NULL == m_pBSD) { Close(TRUE); return FALSE; } CHAR *pszBuffer = new CHAR[nBufferSize]; if (NULL == pszBuffer) { Close(TRUE); delete m_pBSD; m_pBSD = NULL; return FALSE; } CHAR *pszBufferRecv = new CHAR[nBufferSize]; if (NULL == pszBufferRecv) { Close(TRUE); delete m_pBSD; m_pBSD = NULL; delete pszBuffer; return FALSE; } // 设置结构成员 ZeroMemory(m_pBSD, sizeof(BSD)); ZeroMemory(pszBuffer, nBufferSize); ZeroMemory(pszBufferRecv, nBufferSize); m_pBSD->hSocket = m_hSocket; m_pBSD->nBufferSize = nBufferSize; m_pBSD->pszBuffer = pszBuffer; m_pBSD->pszBufferRecv = pszBufferRecv; m_pBSD->nBytesInBuffer = 0; m_pBSD->nReadIndex = 0; m_pBSD->nBufferIndex = 0; } else // UDP { m_pBSD = NULL; } return TRUE; }
rnb_err_t RNBSocket::Listen (in_port_t port, PortBoundCallback callback, const void *callback_baton) { //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); // Disconnect without saving errno Disconnect (false); DNBError err; int listen_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_fd == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_fd); if (err.Fail()) return rnb_err; // enable local address reuse SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); struct sockaddr_in sa; ::memset (&sa, 0, sizeof sa); sa.sin_len = sizeof sa; sa.sin_family = AF_INET; sa.sin_port = htons (port); sa.sin_addr.s_addr = htonl (INADDR_ANY); int error = ::bind (listen_fd, (struct sockaddr *) &sa, sizeof(sa)); if (error == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_fd); if (err.Fail()) { ClosePort (listen_fd, false); return rnb_err; } if (callback && port == 0) { // We were asked to listen on port zero which means we // must now read the actual port that was given to us // as port zero is a special code for "find an open port // for me". socklen_t sa_len = sizeof (sa); if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) { port = ntohs (sa.sin_port); callback (callback_baton, port); } } error = ::listen (listen_fd, 1); if (error == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd); if (err.Fail()) { ClosePort (listen_fd, false); return rnb_err; } m_fd = ::accept (listen_fd, NULL, 0); if (m_fd == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::accept ( socket = %i, address = NULL, address_len = 0 )", listen_fd); ClosePort (listen_fd, false); if (err.Fail()) { return rnb_err; } else { // Keep our TCP packets coming without any delays. SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); } return rnb_success; }
rnb_err_t RNBSocket::Listen (const char *listen_host, uint16_t port, PortBoundCallback callback, const void *callback_baton) { //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); // Disconnect without saving errno Disconnect (false); // Now figure out the hostname that will be attaching and palce it into struct sockaddr_in listen_addr; ::memset (&listen_addr, 0, sizeof listen_addr); listen_addr.sin_len = sizeof listen_addr; listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons (port); listen_addr.sin_addr.s_addr = INADDR_ANY; if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr)) { DNBLogThreaded("error: failed to resolve connecting host '%s'", listen_host); return rnb_err; } DNBError err; int listen_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_fd == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_fd); if (err.Fail()) return rnb_err; // enable local address reuse SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); struct sockaddr_in sa; ::memset (&sa, 0, sizeof sa); sa.sin_len = sizeof sa; sa.sin_family = AF_INET; sa.sin_port = htons (port); sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host network interface (this is NOT who can connect to us) int error = ::bind (listen_fd, (struct sockaddr *) &sa, sizeof(sa)); if (error == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_fd); if (err.Fail()) { ClosePort (listen_fd, false); return rnb_err; } error = ::listen (listen_fd, 5); if (error == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd); if (err.Fail()) { ClosePort (listen_fd, false); return rnb_err; } if (callback) { // We were asked to listen on port zero which means we // must now read the actual port that was given to us // as port zero is a special code for "find an open port // for me". if (port == 0) { socklen_t sa_len = sizeof (sa); if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) { port = ntohs (sa.sin_port); callback (callback_baton, port); } } else { callback (callback_baton, port); } } struct sockaddr_in accept_addr; ::memset (&accept_addr, 0, sizeof accept_addr); accept_addr.sin_len = sizeof accept_addr; bool accept_connection = false; // Loop until we are happy with our connection while (!accept_connection) { socklen_t accept_addr_len = sizeof accept_addr; m_fd = ::accept (listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len); if (m_fd == -1) err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) err.LogThreaded("::accept ( socket = %i, address = %p, address_len = %u )", listen_fd, &accept_addr, accept_addr_len); if (err.Fail()) break; if (listen_addr.sin_addr.s_addr == INADDR_ANY) accept_connection = true; else { if (accept_addr_len == listen_addr.sin_len && accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr) { accept_connection = true; } else { ::close (m_fd); m_fd = -1; const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sin_addr.s_addr; ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n", accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); DNBLogThreaded ("error: rejecting connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)", accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); } } } ClosePort (listen_fd, false); if (err.Fail()) { return rnb_err; } else { // Keep our TCP packets coming without any delays. SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); } return rnb_success; }