void SSLSocket::Connect(std::string host, uint32_t port, std::function<void(bool)> connectedCallback) { std::thread([&, host, port, connectedCallback] { //Setup TCP socket //Create socket struct sockaddr_in serverAddress; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == INVALID_SOCKET) { LOGI("Create socket fail"); if (connectedCallback) { connectedCallback(FAIL); } return; } int opt = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) < 0) { LOGI("Set socket options error"); if (connectedCallback) { connectedCallback(FAIL); } return; } memset(&serverAddress, 0, sizeof(serverAddress)); serverAddress.sin_family = AF_INET; #if defined(WIN32) || defined(WIN64) if (inet_pton(AF_INET, host.c_str(), &serverAddress.sin_addr.S_un.S_addr) <= 0) #else if (inet_pton(AF_INET, host.c_str(), &serverAddress.sin_addr.s_addr) <= 0) #endif { LOGI("Invalid address"); if (connectedCallback) { connectedCallback(FAIL); } return; } serverAddress.sin_port = htons(port); //Connect to server if (connect(sockfd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) { LOGI("Failed to connect to server"); if (connectedCallback) { connectedCallback(FAIL); } return; } //Setup socket ssl if (SSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { LOGI("SSL_set_fd error"); LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL));; if (connectedCallback) { connectedCallback(FAIL); } return; } if (SSL_connect(ssl) != SSL_SUCCESS) { LOGI("SSL_connect error"); LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL)); if (connectedCallback) { connectedCallback(FAIL); } return; } LOGI("SSL connection using %s\n", SSL_get_cipher(ssl)); LOGI("Connected to server"); //Set socket nonblocking if (!SetSocketBlockingEnabled(false)) { LOGI("Set socket blocking error"); if (connectedCallback) { connectedCallback(FAIL); } return; } if (connectedCallback) { connectedCallback(SUCCESS); } return; }).detach(); }
/** 对 url 发出 cmd,接收保存到 res 中. FIXME: 这种接收是有问题的,因为不知道何时接受完成 ... */ static int tcp_req(const char *url, const char *cmd, int cmdlen, char *res, size_t res_buf_len, int timeout) { char host[128], who[64]; int port; if (sscanf(url, "tcp://%[^:]:%d/%s", host, &port, who) != 3) { fprintf(stderr, "[libptz] ERR: invalid tcp url format %s\n", url); fprintf(stderr, "\tusing: tcp://<host>:<port>/<who>\n\n"); return -1; } struct addrinfo ai, *info, *p; memset(&ai, 0, sizeof(ai)); ai.ai_family = AF_INET; ai.ai_socktype = SOCK_STREAM; ai.ai_protocol = IPPROTO_TCP; char service[16]; snprintf(service, sizeof(service), "%d", port); if (getaddrinfo(host, service, &ai, &info) != 0) { fprintf(stderr, "[libptz] ERR: getaddrinfo err for %s\n", url); return -2; } bool completed = false; char *recvbuf = res; int data_len = 0; for (p = info; p && !completed; p = p->ai_next) { int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sock < 0) { fprintf(stderr, "[libptz] ERR: can't create socket ???\n"); continue; } SetSocketBlockingEnabled(sock, false); if (connect_t(sock, p->ai_addr, p->ai_addrlen, timeout) < 0) { fprintf(stderr, "[libptz] ERR: can't connect to %s\n", url); closesocket(sock); continue; } send(sock, cmd, cmdlen, 0); // FIXME: 这一句基本不会出错了 :) fd_set r; FD_ZERO(&r); FD_SET(sock, &r); timeval tv = { timeout/1000, timeout % 1000 * 1000 }; int rc = select(sock+1, &r, 0, 0, &tv); if (rc == -1) { fprintf(stderr, "[libptz] ERR: select falut??\n"); closesocket(sock); continue; } else if (rc == 0) { fprintf(stderr, "[libptz] ERR: recv timeout\n"); closesocket(sock); continue; } rc = recv(sock, recvbuf, res_buf_len, 0); if (rc > 0) { completed = true; data_len = rc; closesocket(sock); } else if (rc == 0) { fprintf(stderr, "[libptz] ERR: peer closed???\n"); closesocket(sock); continue; } else { // FIXME: 应该检查 lasterr ... fprintf(stderr, "[libptz] ERR: recv fault!\n"); closesocket(sock); continue; } } freeaddrinfo(info); return data_len; }
StdinDataIO :: StdinDataIO(bool blocking) : _stdinBlocking(blocking) #ifdef USE_WIN32_STDINDATAIO_IMPLEMENTATION , _slaveSocketTag(0) #else , _fdIO(ConstSocketRef(&_stdinSocket, false), true) #endif { #ifdef USE_WIN32_STDINDATAIO_IMPLEMENTATION if (_stdinBlocking == false) { // For non-blocking I/O, we need to handle stdin in a separate thread. // note that I freopen stdin to "nul" so that other code (read: Python) // won't try to muck about with stdin and interfere with StdinDataIO's // operation. I don't know of any good way to restore it again after, // though... so a side effect of StdinDataIO under Windows is that // stdin gets redirected to nul... once you've created one non-blocking // StdinDataIO, you'll need to continue accessing stdin only via // non-blocking StdinDataIOs. bool okay = false; ConstSocketRef slaveSocket; if ((CreateConnectedSocketPair(_masterSocket, slaveSocket, false) == B_NO_ERROR)&&(SetSocketBlockingEnabled(slaveSocket, true) == B_NO_ERROR)&&(_slaveSocketsMutex.Lock() == B_NO_ERROR)) { bool threadCreated = false; if (_stdinThreadStatus == STDIN_THREAD_STATUS_UNINITIALIZED) { DWORD junkThreadID; #if __STDC_WANT_SECURE_LIB__ FILE * junkFD; #endif _stdinThreadStatus = ((DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE), GetCurrentProcess(), &_stdinHandle, 0, false, DUPLICATE_SAME_ACCESS))&& #if __STDC_WANT_SECURE_LIB__ (freopen_s(&junkFD, "nul", "r", stdin) == 0) #else (freopen("nul", "r", stdin) != NULL) #endif &&((_slaveThread = (::HANDLE) _beginthreadex(NULL, 0, StdinThreadEntryFunc, NULL, CREATE_SUSPENDED, (unsigned *) &junkThreadID)) != 0)) ? STDIN_THREAD_STATUS_RUNNING : STDIN_THREAD_STATUS_EXITED; threadCreated = (_stdinThreadStatus == STDIN_THREAD_STATUS_RUNNING); } if ((_stdinThreadStatus == STDIN_THREAD_STATUS_RUNNING)&&(_slaveSockets.Put(_slaveSocketTag = (++_slaveSocketTagCounter), slaveSocket) == B_NO_ERROR)) okay = true; else LogTime(MUSCLE_LOG_ERROR, "StdinDataIO: Could not start stdin thread!\n"); _slaveSocketsMutex.Unlock(); // We don't start the thread running until here, that way there's no chance of race conditions if the thread exits immediately if (threadCreated) ResumeThread(_slaveThread); } else LogTime(MUSCLE_LOG_ERROR, "StdinDataIO: Error setting up I/O sockets!\n"); if (okay == false) Close(); } #endif }
/** receive data from tcp connection, using session ID */ long Network::TCPServer::TCPReceive(int iSession_ID, char ** ucBufferReceive, int iLenBufferReceive, int * iOutLenDataReceive, bool bAllowAllocate) { if(!m_bConnected) { return TCP_ERR_SERV_NOT_CONNECT; } if(!m_bAccepted) { return TCP_ERR_SERV_NOT_ACCEPTED; } int iSizeBuffer = 0; char * pBuffer = NULL; char * pReallocBuffer = NULL; char cTempBuffer[TCP_MAX_DATA]; memset(cTempBuffer, 0x00, TCP_MAX_DATA); // Put the socket in non-blocking mode: SetSocketBlockingEnabled(iSession_ID, false); int i_total_received = 0; int nb_recept = 1; int i_try_to_receive_counter = 0; do { nb_recept = recv(iSession_ID, cTempBuffer, TCP_MAX_DATA, 0); if(nb_recept > 0) { // need to increase buffer size if(iSizeBuffer <= (i_total_received + nb_recept)) { iSizeBuffer += TCP_MAX_DATA; pReallocBuffer = (char*) realloc(pBuffer, iSizeBuffer * sizeof(char)); if(NULL == pReallocBuffer) { #ifdef _WINDOWS WSACleanup(); #endif // _WINDOWS free(pBuffer); return TCP_ERR_SERV_INVALID_PT; } pBuffer = pReallocBuffer; } memcpy(pBuffer+i_total_received, cTempBuffer, nb_recept); i_total_received += nb_recept; } else { i_try_to_receive_counter++; Timing::Timing::sleepInMilliSecond(100); } } while( (nb_recept > 0) || (i_try_to_receive_counter < MAX_TRY_RECEIVED) ); // copy output data if data buffer size is efficient if( false == bAllowAllocate && (i_total_received > iLenBufferReceive) ) { #ifdef _WINDOWS WSACleanup(); #endif // _WINDOWS free(pBuffer); return TCP_ERR_SERV_RECV; } if(i_total_received > 0) { *iOutLenDataReceive = i_total_received; if(!bAllowAllocate) { int maxCopy = TCP_MAX_DATA; if(i_total_received < maxCopy) { maxCopy = i_total_received; } memcpy(*ucBufferReceive, pBuffer, maxCopy); } else { *ucBufferReceive = (char*)malloc(i_total_received * sizeof(char)); memcpy(*ucBufferReceive, pBuffer, i_total_received); } free(pBuffer); } else { free(pBuffer); return TCP_ERR_SERV_RECV; } return TCP_SERVER_SUCCESS; }