📄 staftcpconnprovider.cpp
字号:
STAFRC_t rc;#ifdef STAF_USE_IPV6 rc = STAFConnectionProviderStartIPv6(provider, errorBuffer);#else rc = STAFConnectionProviderStartIPv4(provider, errorBuffer);#endif if (rc != kSTAFOk) return rc; // Ok, the provider is now ready provider->syncSem->reset(); provider->state = kSTAFConnectionProviderActive;#ifdef STAF_USE_IPV6 provider->threadManager->dispatch(STAFTCPRunThreadIPv6, provider);#else provider->threadManager->dispatch(STAFTCPRunThreadIPv4, provider);#endif // XXX: Might want to time out on this one. provider->syncSem->wait(); return kSTAFOk; } CATCH_STANDARD("STAFConnectionProviderStart"); return kSTAFUnknownError;}STAFRC_t STAFConnectionProviderStop(STAFConnectionProvider_t baseProvider, void *stopInfo, unsigned int stopInfoLevel, STAFString_t *errorBuffer){ if (baseProvider == 0) return kSTAFInvalidObject; if (stopInfoLevel != 0) return kSTAFInvalidAPILevel; try { STAFTCPConnectionProviderImpl *provider = static_cast<STAFTCPConnectionProviderImpl *>(baseProvider); provider->state = kSTAFConnectionProviderStopped; // Connect to the server socket to wake up the run thread provider->syncSem->reset(); STAFString host = STAFString(provider->logicalNetworkID); unsigned short port = provider->port; STAFSocket_t shutdownSocket; int rc = 0;#ifdef STAF_USE_IPV6 struct addrinfo hints = { 0 }; hints.ai_flags = 0; // default hints.ai_family = PF_UNSPEC; // Any family is accepted hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; // Any protocol is accepted STAFNetworkAddress na; rc = getaddrinfo((host + STAFString(kUTF8_NULL)).buffer(), (STAFString(port) + STAFString(kUTF8_NULL)).buffer(), &hints, na.getBuffer()); if (rc == 0) { while (na.next()) { if (na.getCurrent()->ai_family == PF_INET6 && (provider->family == PF_INET6 || provider->family == PF_UNSPEC)) break; if (na.getCurrent()->ai_family == PF_INET && (provider->family == PF_INET || provider->family == PF_UNSPEC)) break; } if (na.getCurrent() != NULL) { shutdownSocket = socket( na.getCurrent()->ai_family, na.getCurrent()->ai_socktype, na.getCurrent()->ai_protocol); } else { rc = 1; } }#else //IPv4 struct sockaddr_in serverAddress = { 0 }; serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(port); if (host.findFirstNotOf("1234567890.") != STAFString::kNPos) { // This is a hostname unsigned int osRC = 0; rc = STAFSocketGetInAddrByName( host.getImpl(), &serverAddress.sin_addr, errorBuffer); } else { // This is an IP address serverAddress.sin_addr.s_addr = inet_addr(host.toCurrentCodePage()->buffer()); } shutdownSocket = socket(PF_INET, SOCK_STREAM, 0);#endif if ((rc == 0) && STAFUtilIsValidSocket(shutdownSocket)) { int connectRC = 0;#ifdef STAF_USE_IPV6 connectRC = connect( shutdownSocket, na.getCurrent()->ai_addr, na.getCurrent()->ai_addrlen);#else connectRC = connect( shutdownSocket, reinterpret_cast<struct sockaddr *>(&serverAddress), sizeof(serverAddress));#endif STAFSocketClose(shutdownSocket); } if (provider->syncSem->wait(10000) != 0) { STAFTrace::trace( kSTAFTraceError, STAFString("STAFTCPConnectionProviderStop - Timed out " "waiting for run thread to wake up")); } // Release resources acquired when starting provider STAFSocketClose(provider->serverSocket);#ifdef STAF_USE_IPV6 STAFSocketClose(provider->serverSocketIPv6);#endif return kSTAFOk; } CATCH_STANDARD("STAFConnectionProviderStop"); return kSTAFUnknownError;}STAFRC_t STAFConnectionProviderDestruct(STAFConnectionProvider_t *baseProvider, void *destructInfo, unsigned int destructInfoLevel, STAFString_t *errorBuffer){ if (baseProvider == 0) return kSTAFInvalidObject; if (*baseProvider == 0) return kSTAFInvalidObject; if (destructInfoLevel != 0) return kSTAFInvalidAPILevel; try { STAFTCPConnectionProviderImpl *provider = static_cast<STAFTCPConnectionProviderImpl *>(*baseProvider); STAFMutexSemLock lock(sActiveProvidersSem); sActiveProviders.erase(provider); if (provider->state != kSTAFConnectionProviderStopped) { provider->state = kSTAFConnectionProviderStopped; // XXX: Should we check the RC? STAFSocketClose(provider->serverSocket);#ifdef STAF_USE_IPV6 STAFSocketClose(provider->serverSocketIPv6);#endif }#ifdef STAF_USE_SSL if (provider->secure.isEqualTo(sYes, kSTAFStringCaseInsensitive)) { // Free SSL context SSL_CTX_free(provider->server_ctx); SSL_CTX_free(provider->client_ctx); }#endif delete provider; provider = 0; return kSTAFOk; } CATCH_STANDARD("STAFConnectionProviderDestruct"); return kSTAFUnknownError;}STAFRC_t STAFConnectionProviderConnect(STAFConnectionProvider_t baseProvider, STAFConnection_t *connection, void *connectInfo, unsigned int connectInfoLevel, STAFString_t *errorBuffer){ if (baseProvider == 0) return kSTAFInvalidObject; if (connectInfoLevel != 1) return kSTAFInvalidAPILevel; if (connection == 0) return kSTAFInvalidParm; STAFConnectionProviderConnectInfoLevel1 *cpInfo = reinterpret_cast<STAFConnectionProviderConnectInfoLevel1 *>(connectInfo); try { STAFTCPConnectionProviderImpl *provider = static_cast<STAFTCPConnectionProviderImpl *>(baseProvider); STAFTCPConnectionImpl connImpl; STAFString host = cpInfo->endpoint; unsigned short port = provider->port; // Extract out the port if specified. Note, because IPv6 uses colons // in IP addresses, we use '@' to separate the host/IP address from // the port, instead of the more conventional ':'. unsigned int atPos = host.find(kUTF8_AT); if (atPos != STAFString::kNPos) { STAFString portString = host.subString(atPos + 1); if (portString.isDigits()) { port = portString.asUInt(); host = host.subString(0, atPos); } }#ifdef STAF_USE_IPV6 struct addrinfo hints = { 0 }; hints.ai_flags = 0; // default hints.ai_family = PF_UNSPEC; // Any family is accepted hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; // Any protocol is accepted STAFNetworkAddress na; int rc = getaddrinfo((host + STAFString(kUTF8_NULL)).buffer(), (STAFString(port) + STAFString(kUTF8_NULL)).buffer(), &hints, na.getBuffer()); if (rc != 0) { STAFString error = STAFString( "Error getting address info: ") + host; if (errorBuffer) *errorBuffer = error.adoptImpl(); return kSTAFCommunicationError; } while (na.next()) { if (na.getCurrent()->ai_family == PF_INET6 && (provider->family == PF_INET6 || provider->family == PF_UNSPEC)) break; if (na.getCurrent()->ai_family == PF_INET && (provider->family == PF_INET || provider->family == PF_UNSPEC)) break; } if (na.getCurrent() == NULL) { STAFString error = STAFString( "Error getting IPv4 or IPv6 address info: ") + host; if (errorBuffer) *errorBuffer = error.adoptImpl(); return kSTAFCommunicationError; } connImpl.clientSocket = socket(na.getCurrent()->ai_family, na.getCurrent()->ai_socktype, na.getCurrent()->ai_protocol);#else //IPv4 struct sockaddr_in serverAddress = { 0 }; serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(port); if (host.findFirstNotOf("1234567890.") != STAFString::kNPos) { // This is a hostname unsigned int osRC = 0; STAFRC_t rc = STAFSocketGetInAddrByName(host.getImpl(), &serverAddress.sin_addr, errorBuffer); if (rc != kSTAFOk) { STAFString error = STAFString("Error resolving host name: "); if (errorBuffer) { error += STAFString(*errorBuffer, STAFString::kShallow); *errorBuffer = error.adoptImpl(); } return kSTAFCommunicationError; } } else { // This is an IP address if (host.count(kUTF8_PERIOD) != 3) { STAFString error = STAFString("Invalid IP Address: ") + host; if (errorBuffer) *errorBuffer = error.adoptImpl(); return kSTAFCommunicationError; } serverAddress.sin_addr.s_addr = inet_addr(host.toCurrentCodePage()->buffer()); } connImpl.clientSocket = socket(PF_INET, SOCK_STREAM, 0);#endif if (!STAFUtilIsValidSocket(connImpl.clientSocket)) { STAFString error = STAFString( "Error creating socket: socket() RC=") + STAFSocketGetLastError(); if (errorBuffer) *errorBuffer = error.adoptImpl(); return kSTAFCommunicationError; } // Set the socket to be non-inheritable unsigned int osRC = 0; STAFSocket_t newSocket; if (STAFUtilGetNonInheritableSocket(connImpl.clientSocket, &newSocket, &osRC)) { STAFString error = STAFString( "Error getting non-inheritable socket, " "STAFUtilGetNonInheritableSocket(), OS RC: ") + STAFString(osRC); if (errorBuffer) { error += STAFString(*errorBuffer, STAFString::kShallow); *errorBuffer = error.adoptImpl(); } STAFSocketClose(connImpl.clientSocket); return kSTAFCommunicationError; } connImpl.clientSocket = newSocket; // Turn on the SO_KEEPALIVE socket option (which is turned // off by default on Windows) to make the socket send // keepalive messages on the session so that if one side // of the connection is terminated, the other side will be // notified after the keepalive time which is 2 hours by // default for most operating systems. See Bug #1559514. bool bOptVal = true; setsockopt(connImpl.clientSocket, SOL_SOCKET, SO_KEEPALIVE, (char*)&bOptVal, sizeof(bool)); int modeRC = STAFSocketSetBlockingMode(connImpl.clientSocket, kSTAFSocketNonBlocking, errorBuffer); if (modeRC != kSTAFOk) { STAFString error = STAFString( "Error setting socket to non-blocking mode:"); if (errorBuffer) { error += STAFString(*errorBuffer, STAFString:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -