int SocketClient::bind(const char* bindaddress, unsigned short localport) { if (!my_socket_valid(m_sockfd)) return -1; struct sockaddr_in local; memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_port = htons(localport); // Convert ip address presentation format to numeric format if (Ndb_getInAddr(&local.sin_addr, bindaddress)) { return errno ? errno : EINVAL; } if (my_socket_reuseaddr(m_sockfd, true) == -1) { int ret = my_socket_errno(); my_socket_close(m_sockfd); my_socket_invalidate(&m_sockfd); return ret; } if (my_bind_inet(m_sockfd, &local) == -1) { int ret = my_socket_errno(); my_socket_close(m_sockfd); my_socket_invalidate(&m_sockfd); return ret; } return 0; }
int TCP_Transporter::doReceive(TransporterReceiveHandle& recvdata) { // Select-function must return the socket for read // before this method is called // It reads the external TCP/IP interface once Uint32 size = receiveBuffer.sizeOfBuffer - receiveBuffer.sizeOfData; if(size > 0){ const int nBytesRead = (int)my_recv(theSocket, receiveBuffer.insertPtr, size < maxReceiveSize ? size : maxReceiveSize, 0); if (nBytesRead > 0) { receiveBuffer.sizeOfData += nBytesRead; receiveBuffer.insertPtr += nBytesRead; if(receiveBuffer.sizeOfData > receiveBuffer.sizeOfBuffer){ #ifdef DEBUG_TRANSPORTER g_eventLogger->error("receiveBuffer.sizeOfData(%d) > receiveBuffer.sizeOfBuffer(%d)", receiveBuffer.sizeOfData, receiveBuffer.sizeOfBuffer); g_eventLogger->error("nBytesRead = %d", nBytesRead); #endif g_eventLogger->error("receiveBuffer.sizeOfData(%d) > receiveBuffer.sizeOfBuffer(%d)", receiveBuffer.sizeOfData, receiveBuffer.sizeOfBuffer); report_error(TE_INVALID_MESSAGE_LENGTH); return 0; } receiveCount ++; receiveSize += nBytesRead; m_bytes_received += nBytesRead; if(receiveCount == reportFreq){ recvdata.reportReceiveLen(remoteNodeId, receiveCount, receiveSize); receiveCount = 0; receiveSize = 0; } return nBytesRead; } else { #if defined DEBUG_TRANSPORTER g_eventLogger->error("Receive Failure(disconnect==%d) to node = %d nBytesSent = %d " "errno = %d strerror = %s", DISCONNECT_ERRNO(my_socket_errno(), nBytesRead), remoteNodeId, nBytesRead, my_socket_errno(), (char*)ndbstrerror(my_socket_errno())); #endif if(DISCONNECT_ERRNO(my_socket_errno(), nBytesRead)){ do_disconnect(my_socket_errno()); } } return nBytesRead; } else { return 0; } }
NDB_SOCKET_TYPE SocketClient::connect(const char *toaddress, unsigned short toport) { if (!my_socket_valid(m_sockfd)) { if (!init()) { return m_sockfd; } } if (toaddress) { if (m_server_name) free(m_server_name); m_server_name = strdup(toaddress); m_port = toport; memset(&m_servaddr, 0, sizeof(m_servaddr)); m_servaddr.sin_family = AF_INET; m_servaddr.sin_port = htons(toport); // Convert ip address presentation format to numeric format if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name)) { my_socket_close(m_sockfd); my_socket_invalidate(&m_sockfd); return m_sockfd; } } // Set socket non blocking if (my_socket_nonblock(m_sockfd, true) < 0) { my_socket_close(m_sockfd); my_socket_invalidate(&m_sockfd); return m_sockfd; } // Start non blocking connect int r = my_connect_inet(m_sockfd, &m_servaddr); if (r == 0) goto done; // connected immediately. if (r < 0 && NONBLOCKERR(my_socket_errno())) { // Start of non blocking connect failed my_socket_close(m_sockfd); my_socket_invalidate(&m_sockfd); return m_sockfd; } if (ndb_poll(m_sockfd, true, true, true, m_connect_timeout_millisec > 0 ? m_connect_timeout_millisec : -1) <= 0) { // Nothing has happened on the socket after timeout // or an error occured my_socket_close(m_sockfd); my_socket_invalidate(&m_sockfd); return m_sockfd; } // Activity detected on the socket { // Check socket level error code int so_error = 0; SOCKET_SIZE_TYPE len= sizeof(so_error); if (my_getsockopt(m_sockfd, SOL_SOCKET, SO_ERROR, &so_error, &len) < 0) { my_socket_close(m_sockfd); my_socket_invalidate(&m_sockfd); return m_sockfd; } if (so_error) { my_socket_close(m_sockfd); my_socket_invalidate(&m_sockfd); return m_sockfd; } } done: if (my_socket_nonblock(m_sockfd, true) < 0) { my_socket_close(m_sockfd); my_socket_invalidate(&m_sockfd); return m_sockfd; } if (m_auth) { if (!m_auth->client_authenticate(m_sockfd)) { my_socket_close(m_sockfd); my_socket_invalidate(&m_sockfd); return m_sockfd; } } NDB_SOCKET_TYPE sockfd = m_sockfd; my_socket_invalidate(&m_sockfd); return sockfd; }
int TCP_Transporter::doSend() { struct iovec iov[64]; Uint32 cnt = fetch_send_iovec_data(iov, NDB_ARRAY_SIZE(iov)); if (cnt == 0) { return 0; } Uint32 sum = 0; for(Uint32 i = 0; i<cnt; i++) { assert(iov[i].iov_len); sum += iov[i].iov_len; } Uint32 pos = 0; Uint32 sum_sent = 0; Uint32 send_cnt = 0; Uint32 remain = sum; if (cnt == NDB_ARRAY_SIZE(iov)) { // If pulling all iov's make sure that we never return everyting // flushed sum++; } while (send_cnt < 5) { send_cnt++; Uint32 iovcnt = cnt > m_os_max_iovec ? m_os_max_iovec : cnt; int nBytesSent = (int)my_socket_writev(theSocket, iov+pos, iovcnt); assert(nBytesSent <= (int)remain); if (Uint32(nBytesSent) == remain) { sum_sent += nBytesSent; goto ok; } else if (nBytesSent > 0) { sum_sent += nBytesSent; remain -= nBytesSent; /** * Forward in iovec */ while (Uint32(nBytesSent) >= iov[pos].iov_len) { assert(iov[pos].iov_len > 0); nBytesSent -= iov[pos].iov_len; pos++; cnt--; } if (nBytesSent) { assert(iov[pos].iov_len > Uint32(nBytesSent)); iov[pos].iov_len -= nBytesSent; iov[pos].iov_base = ((char*)(iov[pos].iov_base))+nBytesSent; } continue; } else { int err = my_socket_errno(); if (!(DISCONNECT_ERRNO(err, nBytesSent))) { if (sum_sent) { goto ok; } else { return remain; } } #if defined DEBUG_TRANSPORTER g_eventLogger->error("Send Failure(disconnect==%d) to node = %d " "nBytesSent = %d " "errno = %d strerror = %s", DISCONNECT_ERRNO(err, nBytesSent), remoteNodeId, nBytesSent, my_socket_errno(), (char*)ndbstrerror(err)); #endif do_disconnect(err); return 0; } } ok: assert(sum >= sum_sent); iovec_data_sent(sum_sent); sendCount += send_cnt; sendSize += sum_sent; if(sendCount >= reportFreq) { get_callback_obj()->reportSendLen(remoteNodeId, sendCount, sendSize); sendCount = 0; sendSize = 0; } return sum - sum_sent; // 0 if every thing flushed else >0 }