Пример #1
0
int Socket::send( unsigned char *inBuffer, int inNumBytes,
                  char inAllowedToBlock,
                  char inAllowDelay ) {

    unsigned int *socketIDptr = (unsigned int *)( mNativeObjectPointer );
    unsigned int socketID = socketIDptr[0];

    if( inAllowedToBlock ) {
        if( ! inAllowDelay ) {
            // turn nodelay on
            setNoDelay( 1 );
        }

        int returnVal = ::send( socketID, (char*)inBuffer, inNumBytes, 0 );

        if( ! inAllowDelay ) {
            // turn nodelay back off
            setNoDelay( 0 );
        }

        return returnVal;
    }
    else {
        // 1 for non-blocking, 0 for blocking
        u_long socketMode = 1;
        ioctlsocket( socketID, FIONBIO, &socketMode );

        if( ! inAllowDelay ) {
            // turn nodelay on
            setNoDelay( 1 );
        }

        int result = ::send( socketID, (char*)inBuffer, inNumBytes, 0 );

        if( ! inAllowDelay ) {
            // turn nodelay back off
            setNoDelay( 0 );
        }


        // set back to blocking
        socketMode = 0;
        ioctlsocket( socketID, FIONBIO, &socketMode );


        if( result == -1 &&
                WSAGetLastError() == WSAEWOULDBLOCK ) {

            return -2;
        }
        else {
            return result;
        }
    }
}
Пример #2
0
/*
 * Accept a connection.  This will block waiting for somebody to show up.
 */
bool jdwpAcceptConnection(NetState* netState)
{
    struct sockaddr_in addr;
    socklen_t addrlen;
    int sock;

    if (netState->listenSock < 0)
        return false;       /* you're not listening! */

    assert(netState->dbg.sock < 0);     /* must not already be talking */

    addrlen = sizeof(addr);
    do {
        sock = accept(netState->listenSock, (struct sockaddr*) &addr, &addrlen);
        if (sock < 0 && errno != EINTR) {
            fprintf(stderr, "accept failed: %s\n", strerror(errno));
            return false;
        }
    } while (sock < 0);

    fprintf(stderr, "+++ accepted connection from %s:%u\n",
        inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

    netState->dbg.sock = sock;
    netState->dbg.awaitingHandshake = true;
    netState->dbg.inputCount = 0;

    setNoDelay(sock);

    return true;
}
Пример #3
0
void TSocket::setSocketOptions(const Options& options) {
  // Connect timeout
  options_.connTimeout = options.connTimeout;

  // Send timeout
  if (options.sendTimeout >= 0) {
    setSendTimeout(options.sendTimeout);
  }

  // Recv timeout
  if (options.recvTimeout >= 0) {
    setRecvTimeout(options.recvTimeout);
  }

  // Send Buffer Size
  if (options.sendBufSize > 0) {
    setSendBufSize(options.sendBufSize);
  }

  // Recv Buffer Size
  if (options.recvBufSize > 0) {
    setRecvBufSize(options.recvBufSize);
  }

  // Linger
  setLinger(options.lingerOn, options.lingerVal);

  // No delay
  setNoDelay(options.noDelay);

  setReuseAddress(options.reuseAddr);
}
Пример #4
0
TCPSocket::TCPSocket(const Address& address, TCPSocketObserver *o)
    throw(NetworkException)
    : SocketBase(address,true), observer(o)
{
    doConnect();
    setNoDelay();
}
Пример #5
0
/*
 * Connect to the VM.
 */
bool jdwpConnectToVm(NetState* netState)
{
    struct sockaddr_in addr;
    int sock = -1;

    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock < 0) {
        fprintf(stderr, "Socket create failed: %s\n", strerror(errno));
        goto fail;
    }

    addr.sin_family = AF_INET;
    addr.sin_addr = netState->vmAddr;
    addr.sin_port = htons(netState->vmPort);
    if (connect(sock, (struct sockaddr*) &addr, sizeof(addr)) != 0) {
        fprintf(stderr, "Connection to %s:%u failed: %s\n",
            inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), strerror(errno));
        goto fail;
    }
    fprintf(stderr, "+++ connected to VM %s:%u\n",
        inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

    netState->vm.sock = sock;
    netState->vm.awaitingHandshake = true;
    netState->vm.inputCount = 0;

    setNoDelay(netState->vm.sock);
    return true;

fail:
    if (sock >= 0)
        close(sock);
    return false;
}
Пример #6
0
bool TransportTCP::initializeSocket()
{
  ROS_ASSERT(sock_ != ROS_INVALID_SOCKET);

  if (!setNonBlocking())
  {
    return false;
  }

  setKeepAlive(s_use_keepalive_, 60, 10, 9);

  // connect() will set cached_remote_host_ because it already has the host/port available
  if (cached_remote_host_.empty())
  {
    if (is_server_)
    {
      cached_remote_host_ = "TCPServer Socket";
    }
    else
    {
      std::stringstream ss;
      ss << getClientURI() << " on socket " << sock_;
      cached_remote_host_ = ss.str();
    }
  }

  if (local_port_ < 0)
  {
    la_len_ = s_use_ipv6_  ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);
    getsockname(sock_, (sockaddr *)&local_address_, &la_len_);
    switch (local_address_.ss_family)
    {
      case AF_INET:
        local_port_ = ntohs(((sockaddr_in *)&local_address_)->sin_port);
        break;
      case AF_INET6:
        local_port_ = ntohs(((sockaddr_in6 *)&local_address_)->sin6_port);
        break;
    }
  }

#ifdef ROSCPP_USE_TCP_NODELAY
  setNoDelay(true);
#endif

  ROS_ASSERT(poll_set_ || (flags_ & SYNCHRONOUS));
  if (poll_set_)
  {
    ROS_DEBUG("Adding tcp socket [%d] to pollset", sock_);
    poll_set_->addSocket(sock_, boost::bind(&TransportTCP::socketUpdate, this, _1), shared_from_this());
  }

  if (!(flags_ & SYNCHRONOUS))
  {
    //enableRead();
  }

  return true;
}
Пример #7
0
void TransportTCP::parseHeader(const Header& header)
{
  std::string nodelay;
  if (header.getValue("tcp_nodelay", nodelay) && nodelay == "1")
  {
    ROSCPP_LOG_DEBUG("Setting nodelay on socket [%d]", sock_);
    setNoDelay(true);
  }
}
Пример #8
0
/** Returns -1 if no data, else char from getchar **/
char getcharNoWait() {
	if(initialized == false) setNoDelay();
	if(lastChar >= 0) {
		char c = lastChar;
		lastChar = -1;
		return c;
	}
	return getchar();
}
Пример #9
0
void
TCPSocket::onResolved()
{
    SocketBase::onResolved();
    create();
    setNonBlocking();
    setConfigured();
    doConnect();
    setNoDelay();
}
Пример #10
0
/*
 * Accept a connection.  This will block waiting for somebody to show up.
 * If that's not desirable, use checkConnection() to make sure something
 * is pending.
 */
static bool acceptConnection(JdwpState* state)
{
    JdwpNetState* netState = state->netState;
    union {
        struct sockaddr_in  addrInet;
        struct sockaddr     addrPlain;
    } addr;
    socklen_t addrlen;
    int sock;

    if (netState->listenSock < 0)
        return false;       /* you're not listening! */

    assert(netState->clientSock < 0);      /* must not already be talking */

    addrlen = sizeof(addr);
    do {
        sock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
        if (sock < 0 && errno != EINTR) {
            // When we call shutdown() on the socket, accept() returns with
            // EINVAL.  Don't gripe about it.
            if (errno == EINVAL)
                LOGVV("accept failed: %s", strerror(errno));
            else
                ALOGE("accept failed: %s", strerror(errno));
            return false;
        }
    } while (sock < 0);

    netState->remoteAddr = addr.addrInet.sin_addr;
    netState->remotePort = ntohs(addr.addrInet.sin_port);
    ALOGV("+++ accepted connection from %s:%u",
        inet_ntoa(netState->remoteAddr), netState->remotePort);

    netState->clientSock = sock;
    netState->awaitingHandshake = true;
    netState->inputCount = 0;

    ALOGV("Setting TCP_NODELAY on accepted socket");
    setNoDelay(netState->clientSock);

    if (pipe(netState->wakePipe) < 0) {
        ALOGE("pipe failed");
        return false;
    }

    return true;
}
bool TransportTCP::initializeSocket()
{
    ROS_ASSERT(sock_ != ROS_INVALID_SOCKET);

    if (!setNonBlocking())
    {
        return false;
    }

    setKeepAlive(s_use_keepalive_, 60, 10, 9);

    // connect() will set cached_remote_host_ because it already has the host/port available
    if (cached_remote_host_.empty())
    {
        if (is_server_)
        {
            cached_remote_host_ = "TCPServer Socket";
        }
        else
        {
            std::stringstream ss;
            ss << getClientURI() << " on socket " << sock_;
            cached_remote_host_ = ss.str();
        }
    }

#ifdef ROSCPP_USE_TCP_NODELAY
    setNoDelay(true);
#endif

    ROS_ASSERT(poll_set_ || (flags_ & SYNCHRONOUS));
    if (poll_set_)
    {
        ROS_DEBUG("Adding tcp socket [%d] to pollset", sock_);
        poll_set_->addSocket(sock_, boost::bind(&TransportTCP::socketUpdate, this, _1), shared_from_this());
    }

    if (!(flags_ & SYNCHRONOUS))
    {
        //enableRead();
    }

    return true;
}
Пример #12
0
bool CMySocket::ConnectServer()
{
	Close();
	m_bfirstpack = true;
	m_bZlib = false;
	m_zlibIn.Init();
	m_zlibDe.Init();
	m_sRecvBuf.clear();

	struct sockaddr_in peer;
	if (!set_address(m_szdomian, m_port, &peer))
	{
		g_WriteLog.WriteLog(C_LOG_ERROR, "set_address error, domain:%s, port:%hd", m_szdomian, m_port);
		return FALSE;
	}
	SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
	if (s == INVALID_SOCKET)
	{
		int nerrid = WSAGetLastError();
		g_WriteLog.WriteLog(C_LOG_ERROR, "create sock error, errno=%d, %s", errno, FormatLastError(nerrid));
		return FALSE;
	}

	if (connect(s, (struct sockaddr *)&peer, sizeof(peer)))
	{
		int nerrid = WSAGetLastError();
		g_WriteLog.WriteLog(C_LOG_ERROR, "connect to %s:%hu,errno=%d, %s", m_szdomian, m_port, errno, FormatLastError(nerrid));
		closesocket(s);
		s = INVALID_SOCKET;
		return FALSE;
	}

	setNonblock(s);
	setNoDelay(s, true);


	m_hSocket = s; //赋值后导致recv线程开始执行

	return m_hSocket != INVALID_SOCKET;
}
Пример #13
0
void ClientSocket::connect(const Ip &ip, int port) {
	sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(ip.getString().c_str());
	addr.sin_port = htons(port);

	int res = ::connect(sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr));
	if (res == SOCKET_ERROR) {
		int errCode = get_error();
		if (errCode != WOULD_BLOCK) {
			handleError(__FUNCTION__);
		} else {

			// TODO
			// wait a bit, check writable, try again
			cout << "::connect() error, WOULD_BLOCK.\n";

		}
	} else {
		setNoDelay();
	}
}
Пример #14
0
bool isCharReady() {
	if(initialized == false) setNoDelay();
	if(lastChar >= 0) return true;
	lastChar = getchar();
	return (lastChar >= 0);
}
Пример #15
0
void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtSettings ) {
	char outarg[100];

	switch ( option ) {
		case '1': // Single Client
			setSingleClient( mExtSettings );
			break;
		case 'b': // UDP bandwidth
		#ifdef RINA
			if ( !isUDP( mExtSettings )  && !isRINA( mExtSettings ) ) {
		#else
			if ( !isUDP( mExtSettings ) ) {
		#endif
				fprintf( stderr, warn_implied_udp, option );
			}

			if ( mExtSettings->mThreadMode != kMode_Client ) {
				fprintf( stderr, warn_invalid_server_option, option );
				break;
			}

			Settings_GetLowerCaseArg(optarg,outarg);
			mExtSettings->mUDPRate = byte_atoi(outarg);
		#ifdef RINA
			if ( !isUDP( mExtSettings )  && !isRINA( mExtSettings ) ) 
		#endif
			setUDP( mExtSettings );

			// if -l has already been processed, mBufLenSet is true
			// so don't overwrite that value.
			if ( !isBuflenSet( mExtSettings ) ) {
				mExtSettings->mBufLen = kDefault_UDPBufLen;
			}
			break;

		case 'c': // client mode w/ server host to connect to
			mExtSettings->mHost = new char[ strlen( optarg ) + 1 ];
			strcpy( mExtSettings->mHost, optarg );

			if ( mExtSettings->mThreadMode == kMode_Unknown ) {
				// Test for Multicast
				iperf_sockaddr temp;
				SockAddr_setHostname( mExtSettings->mHost, &temp,
									  (isIPV6( mExtSettings ) ? 1 : 0 ));
				if ( SockAddr_isMulticast( &temp ) ) {
					setMulticast( mExtSettings );
				}
				mExtSettings->mThreadMode = kMode_Client;
				mExtSettings->mThreads = 1;
			}
			break;

		case 'd': // Dual-test Mode
		#ifdef RINA
			if ( isRINA( mExtSettings ) ) {
				fprintf( stderr, warn_invalid_rina_option, option );
				break;
			}
		#endif
			if ( mExtSettings->mThreadMode != kMode_Client ) {
				fprintf( stderr, warn_invalid_server_option, option );
				break;
			}
			if ( isCompat( mExtSettings ) ) {
				fprintf( stderr, warn_invalid_compatibility_option, option );
			}
		#ifdef HAVE_THREAD
			mExtSettings->mMode = kTest_DualTest;
		#else
			fprintf( stderr, warn_invalid_single_threaded, option );
			mExtSettings->mMode = kTest_TradeOff;
		#endif
			break;

		case 'f': // format to print in
			mExtSettings->mFormat = (*optarg);
			break;

		case 'h': // print help and exit
			fprintf(stderr, usage_long1);
			fprintf(stderr, usage_long2);
			exit(1);
			break;

		case 'i': // specify interval between periodic bw reports
			mExtSettings->mInterval = atof( optarg );
			if ( mExtSettings->mInterval < 0.5 ) {
				fprintf (stderr, report_interval_small, mExtSettings->mInterval);
				mExtSettings->mInterval = 0.5;
			}
			break;

		case 'l': // length of each buffer
			Settings_GetUpperCaseArg(optarg,outarg);
			mExtSettings->mBufLen = byte_atoi( outarg );
			setBuflenSet( mExtSettings );
		#ifdef RINA
			if ( !isUDP( mExtSettings )  && !isRINA( mExtSettings ) ) {
		#else
			if ( !isUDP( mExtSettings ) ) {
		#endif
				if ( mExtSettings->mBufLen < (int) sizeof( client_hdr ) &&
					!isCompat( mExtSettings ) ) {
					setCompat( mExtSettings );
					fprintf( stderr, warn_implied_compatibility, option );
				}
			} else {
				if ( mExtSettings->mBufLen < (int) sizeof( UDP_datagram ) ) {
					mExtSettings->mBufLen = sizeof( UDP_datagram );
					fprintf( stderr, warn_buffer_too_small, mExtSettings->mBufLen );
				}
				if ( !isCompat( mExtSettings ) &&
							mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram )
							+ sizeof( client_hdr ) ) ) {
					setCompat( mExtSettings );
					fprintf( stderr, warn_implied_compatibility, option );
				}
			}

			break;

		case 'm': // print TCP MSS
			setPrintMSS( mExtSettings );
			break;

		case 'n': // bytes of data
			// amount mode (instead of time mode)
			unsetModeTime( mExtSettings );
			Settings_GetUpperCaseArg(optarg,outarg);
			mExtSettings->mAmount = byte_atoi( outarg );
			break;

		case 'o' : // output the report and other messages into the file
			unsetSTDOUT( mExtSettings );
			mExtSettings->mOutputFileName = new char[strlen(optarg)+1];
			strcpy( mExtSettings->mOutputFileName, optarg);
			break;

		case 'p': // server port
			mExtSettings->mPort = atoi( optarg );
			break;

		case 'r': // test mode tradeoff
			if ( mExtSettings->mThreadMode != kMode_Client ) {
				fprintf( stderr, warn_invalid_server_option, option );
				break;
			}
			if ( isCompat( mExtSettings ) ) {
				fprintf( stderr, warn_invalid_compatibility_option, option );
			}

			mExtSettings->mMode = kTest_TradeOff;
			break;

		case 's': // server mode
		#ifdef RINA
			if ( mExtSettings->mThreadMode != kMode_Unknown && !isRINA( mExtSettings ) ) {
		#else
			if ( mExtSettings->mThreadMode != kMode_Unknown ) {
		#endif
				fprintf( stderr, warn_invalid_client_option, option );
				break;
			}

			mExtSettings->mThreadMode = kMode_Listener;
			break;

		case 't': // seconds to write for
			// time mode (instead of amount mode)
			setModeTime( mExtSettings );
			mExtSettings->mAmount = (int) (atof( optarg ) * 100.0);
			break;

		case 'u': // UDP instead of TCP
			// if -b has already been processed, UDP rate will
			// already be non-zero, so don't overwrite that value
			if ( !isUDP( mExtSettings ) ) {
				setUDP( mExtSettings );
		#ifdef RINA
				unsetRINA( mExtSettings );
		#endif
				mExtSettings->mUDPRate = kDefault_UDPRate;
			}

			// if -l has already been processed, mBufLenSet is true
			// so don't overwrite that value.
			if ( !isBuflenSet( mExtSettings ) ) {
				mExtSettings->mBufLen = kDefault_UDPBufLen;
			} else if ( mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram ) 
						+ sizeof( client_hdr ) ) &&
						!isCompat( mExtSettings ) ) {
				setCompat( mExtSettings );
				fprintf( stderr, warn_implied_compatibility, option );
			}
			break;

		case 'v': // print version and exit
			fprintf( stderr, version );
			exit(1);
			break;

		case 'w': // TCP window size (socket buffer size)
			Settings_GetUpperCaseArg(optarg,outarg);
			mExtSettings->mTCPWin = byte_atoi(outarg);

			if ( mExtSettings->mTCPWin < 2048 ) {
				fprintf( stderr, warn_window_small, mExtSettings->mTCPWin );
			}
			break;

		case 'x': // Limit Reports
			while ( *optarg != '\0' ) {
				switch ( *optarg ) {
					case 's':
					case 'S':
						setNoSettReport( mExtSettings );
						break;
					case 'c':
					case 'C':
						setNoConnReport( mExtSettings );
						break;
					case 'd':
					case 'D':
						setNoDataReport( mExtSettings );
						break;
					case 'v':
					case 'V':
						setNoServReport( mExtSettings );
						break;
					case 'm':
					case 'M':
						setNoMultReport( mExtSettings );
						break;
					default:
						fprintf(stderr, warn_invalid_report, *optarg);
				}
				optarg++;
			}
			break;

		case 'y': // Reporting Style
			switch ( *optarg ) {
				case 'c':
				case 'C':
					mExtSettings->mReportMode = kReport_CSV;
					break;
				default:
					fprintf( stderr, warn_invalid_report_style, optarg );
			}
			break;


			// more esoteric options

	#ifdef RINA
		case 'A': // RINA instead of UDP or TCP
			mExtSettings->mMode = kTest_Normal; // RINA don't work in dual mode
			setRINA( mExtSettings );
			// if -b has already been processed, UDP rate will
			// already be non-zero, so don't overwrite that value
			if ( isUDP( mExtSettings ) ) {
				unsetUDP( mExtSettings );
			} else {
				mExtSettings->mUDPRate = kDefault_UDPRate;
			}

			// if -l has already been processed, mBufLenSet is true
			// so don't overwrite that value.
			if ( !isBuflenSet( mExtSettings ) ) {
				mExtSettings->mBufLen = kDefault_UDPBufLen;
			} else if ( mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram ) 
						+ sizeof( client_hdr ) ) &&
						!isCompat( mExtSettings ) ) {
				setCompat( mExtSettings );
				fprintf( stderr, warn_implied_compatibility, option );
			}

			// if -s have not been used yet, consider the use of client mode
			if ( mExtSettings->mThreadMode == kMode_Unknown ) {
				mExtSettings->mThreadMode = kMode_Client;
			}
			rina::initialize("EMERG", "");
			break;
	#endif

		case 'B': // specify bind address
			mExtSettings->mLocalhost = new char[ strlen( optarg ) + 1 ];
			strcpy( mExtSettings->mLocalhost, optarg );
			// Test for Multicast
			iperf_sockaddr temp;
			SockAddr_setHostname( mExtSettings->mLocalhost, &temp,
								(isIPV6( mExtSettings ) ? 1 : 0 ));
			if ( SockAddr_isMulticast( &temp ) ) {
				setMulticast( mExtSettings );
			}
			break;

		case 'C': // Run in Compatibility Mode
			setCompat( mExtSettings );
			if ( mExtSettings->mMode != kTest_Normal ) {
				fprintf( stderr, warn_invalid_compatibility_option,
						( mExtSettings->mMode == kTest_DualTest ?
						'd' : 'r' ) );
				mExtSettings->mMode = kTest_Normal;
			}
			break;

		case 'D': // Run as a daemon
			setDaemon( mExtSettings );
			break;

		case 'F' : // Get the input for the data stream from a file
			if ( mExtSettings->mThreadMode != kMode_Client ) {
				fprintf( stderr, warn_invalid_server_option, option );
				break;
			}

			setFileInput( mExtSettings );
			mExtSettings->mFileName = new char[strlen(optarg)+1];
			strcpy( mExtSettings->mFileName, optarg);
			break;

		case 'I' : // Set the stdin as the input source
			if ( mExtSettings->mThreadMode != kMode_Client ) {
				fprintf( stderr, warn_invalid_server_option, option );
				break;
			}

			setFileInput( mExtSettings );
			setSTDIN( mExtSettings );
			mExtSettings->mFileName = new char[strlen("<stdin>")+1];
			strcpy( mExtSettings->mFileName,"<stdin>");
			break;

		case 'L': // Listen Port (bidirectional testing client-side)
			if ( mExtSettings->mThreadMode != kMode_Client ) {
				fprintf( stderr, warn_invalid_server_option, option );
				break;
			}

			mExtSettings->mListenPort = atoi( optarg );
			break;

		case 'M': // specify TCP MSS (maximum segment size)
			Settings_GetUpperCaseArg(optarg,outarg);

			mExtSettings->mMSS = byte_atoi( outarg );
			break;

		case 'N': // specify TCP nodelay option (disable Jacobson's Algorithm)
			setNoDelay( mExtSettings );
			break;

		case 'P': // number of client threads
	#ifdef HAVE_THREAD
			mExtSettings->mThreads = atoi( optarg );
	#else
			if ( mExtSettings->mThreadMode != kMode_Server ) {
				fprintf( stderr, warn_invalid_single_threaded, option );
			} else {
				mExtSettings->mThreads = atoi( optarg );
			}
	#endif
			break;

		case 'R':
			setRemoveService( mExtSettings );
			break;

		case 'S': // IP type-of-service
			// TODO use a function that understands base-2
			// the zero base here allows the user to specify
			// "0x#" hex, "0#" octal, and "#" decimal numbers
			mExtSettings->mTOS = strtol( optarg, NULL, 0 );
			break;

		case 'T': // time-to-live for multicast
			mExtSettings->mTTL = atoi( optarg );
			break;

		case 'U': // single threaded UDP server
			setSingleUDP( mExtSettings );
			break;

		case 'V': // IPv6 Domain
			setIPV6( mExtSettings );
			if ( mExtSettings->mThreadMode == kMode_Server 
				&& mExtSettings->mLocalhost != NULL ) {
				// Test for Multicast
				iperf_sockaddr temp;
				SockAddr_setHostname( mExtSettings->mLocalhost, &temp, 1);
				if ( SockAddr_isMulticast( &temp ) ) {
					setMulticast( mExtSettings );
				}
			} else if ( mExtSettings->mThreadMode == kMode_Client ) {
				// Test for Multicast
				iperf_sockaddr temp;
				SockAddr_setHostname( mExtSettings->mHost, &temp, 1 );
				if ( SockAddr_isMulticast( &temp ) ) {
					setMulticast( mExtSettings );
				}
			}
			break;

		case 'W' :
			setSuggestWin( mExtSettings );
			fprintf( stderr, "The -W option is not available in this release\n");
			break;

		case 'Z':
	#ifdef TCP_CONGESTION
			setCongestionControl( mExtSettings );
			mExtSettings->mCongestion = new char[strlen(optarg)+1];
			strcpy( mExtSettings->mCongestion, optarg);
	#else
			fprintf( stderr, "The -Z option is not available on this operating system\n");
	#endif
			break;

		default: // ignore unknown
			break;
	}
} // end Interpret

void Settings_GetUpperCaseArg(const char *inarg, char *outarg) {

	int len = strlen(inarg);
	strcpy(outarg,inarg);

	if ( (len > 0) && (inarg[len-1] >='a') 
		&& (inarg[len-1] <= 'z') )
        outarg[len-1]= outarg[len-1]+'A'-'a';
}

void Settings_GetLowerCaseArg(const char *inarg, char *outarg) {

    int len = strlen(inarg);
    strcpy(outarg,inarg);

    if ( (len > 0) && (inarg[len-1] >='A') 
         && (inarg[len-1] <= 'Z') )
        outarg[len-1]= outarg[len-1]-'A'+'a';
}

/*
 * Settings_GenerateListenerSettings
 * Called to generate the settings to be passed to the Listener
 * instance that will handle dual testings from the client side
 * this should only return an instance if it was called on 
 * the thread_Settings instance generated from the command line 
 * for client side execution 
 */
void Settings_GenerateListenerSettings( thread_Settings *client, thread_Settings **listener ) {
    if ( !isCompat( client ) && 
         (client->mMode == kTest_DualTest || client->mMode == kTest_TradeOff) ) {
        *listener = new thread_Settings;
        memcpy(*listener, client, sizeof( thread_Settings ));
        setCompat( (*listener) );
        unsetDaemon( (*listener) );
        if ( client->mListenPort != 0 ) {
            (*listener)->mPort   = client->mListenPort;
        } else {
            (*listener)->mPort   = client->mPort;
        }
        (*listener)->mFileName   = NULL;
        (*listener)->mHost       = NULL;
        (*listener)->mLocalhost  = NULL;
        (*listener)->mOutputFileName = NULL;
        (*listener)->mMode       = kTest_Normal;
        (*listener)->mThreadMode = kMode_Listener;
        if ( client->mHost != NULL ) {
            (*listener)->mHost = new char[strlen( client->mHost ) + 1];
            strcpy( (*listener)->mHost, client->mHost );
        }
        if ( client->mLocalhost != NULL ) {
            (*listener)->mLocalhost = new char[strlen( client->mLocalhost ) + 1];
            strcpy( (*listener)->mLocalhost, client->mLocalhost );
        }
    } else {
        *listener = NULL;
    }
}

/*
 * Settings_GenerateSpeakerSettings
 * Called to generate the settings to be passed to the Speaker
 * instance that will handle dual testings from the server side
 * this should only return an instance if it was called on 
 * the thread_Settings instance generated from the command line 
 * for server side execution. This should be an inverse operation
 * of GenerateClientHdr. 
 */
void Settings_GenerateClientSettings( thread_Settings *server, 
                                      thread_Settings **client,
                                      client_hdr *hdr ) {
    int flags = ntohl(hdr->flags);
    if ( (flags & HEADER_VERSION1) != 0 ) {
        *client = new thread_Settings;
        memcpy(*client, server, sizeof( thread_Settings ));
        setCompat( (*client) );
        (*client)->mTID = thread_zeroid();
        (*client)->mPort       = (unsigned short) ntohl(hdr->mPort);
        (*client)->mThreads    = ntohl(hdr->numThreads);
        if ( hdr->bufferlen != 0 ) {
            (*client)->mBufLen = ntohl(hdr->bufferlen);
        }
        if ( hdr->mWinBand != 0 ) {
#ifdef RINA
            if ( isUDP( server ) || isRINA( server ) ) {
#else
            if ( isUDP( server ) ) {
#endif
                (*client)->mUDPRate = ntohl(hdr->mWinBand);
            } else {
                (*client)->mTCPWin = ntohl(hdr->mWinBand);
            }
        }
        (*client)->mAmount     = ntohl(hdr->mAmount);
        if ( ((*client)->mAmount & 0x80000000) > 0 ) {
            setModeTime( (*client) );
#ifndef WIN32
            (*client)->mAmount |= 0xFFFFFFFF00000000LL;
#else
            (*client)->mAmount |= 0xFFFFFFFF00000000;
#endif
            (*client)->mAmount = -(*client)->mAmount;
        }
        (*client)->mFileName   = NULL;
        (*client)->mHost       = NULL;
        (*client)->mLocalhost  = NULL;
        (*client)->mOutputFileName = NULL;
        (*client)->mMode       = ((flags & RUN_NOW) == 0 ?
                                   kTest_TradeOff : kTest_DualTest);
        (*client)->mThreadMode = kMode_Client;
        if ( server->mLocalhost != NULL ) {
            (*client)->mLocalhost = new char[strlen( server->mLocalhost ) + 1];
            strcpy( (*client)->mLocalhost, server->mLocalhost );
        }
        (*client)->mHost = new char[REPORT_ADDRLEN];
        if ( ((sockaddr*)&server->peer)->sa_family == AF_INET ) {
            inet_ntop( AF_INET, &((sockaddr_in*)&server->peer)->sin_addr, 
                       (*client)->mHost, REPORT_ADDRLEN);
        }
#ifdef HAVE_IPV6
          else {
            inet_ntop( AF_INET6, &((sockaddr_in6*)&server->peer)->sin6_addr, 
                       (*client)->mHost, REPORT_ADDRLEN);
        }
#endif
    } else {
        *client = NULL;
    }
}

/*
 * Settings_GenerateClientHdr
 * Called to generate the client header to be passed to the
 * server that will handle dual testings from the server side
 * This should be an inverse operation of GenerateSpeakerSettings
 */
void Settings_GenerateClientHdr( thread_Settings *client, client_hdr *hdr ) {
    if ( client->mMode != kTest_Normal ) {
        hdr->flags  = htonl(HEADER_VERSION1);
    } else {
        hdr->flags  = 0;
    }
    if ( isBuflenSet( client ) ) {
        hdr->bufferlen = htonl(client->mBufLen);
    } else {
        hdr->bufferlen = 0;
    }
#ifdef RINA
    if ( isUDP( client ) || isRINA( client ) ) {
#else
    if ( isUDP( client ) ) {
#endif
        hdr->mWinBand  = htonl(client->mUDPRate);
    } else {
        hdr->mWinBand  = htonl(client->mTCPWin);
    }
    if ( client->mListenPort != 0 ) {
        hdr->mPort  = htonl(client->mListenPort);
    } else {
        hdr->mPort  = htonl(client->mPort);
    }
    hdr->numThreads = htonl(client->mThreads);
    if ( isModeTime( client ) ) {
        hdr->mAmount    = htonl(-(long)client->mAmount);
    } else {
        hdr->mAmount    = htonl((long)client->mAmount);
        hdr->mAmount &= htonl( 0x7FFFFFFF );
    }
    if ( client->mMode == kTest_DualTest ) {
        hdr->flags |= htonl(RUN_NOW);
    }
}
Пример #16
0
void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtSettings ) {
    char outarg[100];

    switch ( option ) {
        case '1': // Single Client
            setSingleClient( mExtSettings );
            break;
        case 'b': // UDP bandwidth
            if ( !isUDP( mExtSettings ) ) {
                fprintf( stderr, warn_implied_udp, option );
            }

            if ( mExtSettings->mThreadMode != kMode_Client ) {
                fprintf( stderr, warn_invalid_server_option, option );
                break;
            }

            Settings_GetLowerCaseArg(optarg,outarg);
            mExtSettings->mUDPRate = byte_atoi(outarg);
            setUDP( mExtSettings );

            // if -l has already been processed, mBufLenSet is true
            // so don't overwrite that value.
            if ( !isBuflenSet( mExtSettings ) ) {
                mExtSettings->mBufLen = kDefault_UDPBufLen;
            }
            break;

        case 'c': // client mode w/ server host to connect to
            mExtSettings->mHost = new char[ strlen( optarg ) + 1 ];
            strcpy( mExtSettings->mHost, optarg );

            if ( mExtSettings->mThreadMode == kMode_Unknown ) {
                // Test for Multicast
                iperf_sockaddr temp;
                SockAddr_setHostname( mExtSettings->mHost, &temp,
                                      (isIPV6( mExtSettings ) ? 1 : 0 ));
                if ( SockAddr_isMulticast( &temp ) ) {
                    setMulticast( mExtSettings );
                }
                mExtSettings->mThreadMode = kMode_Client;
                mExtSettings->mThreads = 1;
            }
            break;

        case 'd': // Dual-test Mode
            if ( mExtSettings->mThreadMode != kMode_Client ) {
                fprintf( stderr, warn_invalid_server_option, option );
                break;
            }
            if ( isCompat( mExtSettings ) ) {
                fprintf( stderr, warn_invalid_compatibility_option, option );
            }
#ifdef HAVE_THREAD
            mExtSettings->mMode = kTest_DualTest;
#else
            fprintf( stderr, warn_invalid_single_threaded, option );
            mExtSettings->mMode = kTest_TradeOff;
#endif
            break;

        case 'f': // format to print in
            mExtSettings->mFormat = (*optarg);
            break;

        case 'h': // print help and exit
            fprintf(stderr, usage_long1);
            fprintf(stderr, usage_long2);
            exit(1);
            break;

        case 'i': // specify interval between periodic bw reports
            mExtSettings->mInterval = atof( optarg );
            if ( mExtSettings->mInterval < 0.5 ) {
                fprintf (stderr, report_interval_small, mExtSettings->mInterval);
                mExtSettings->mInterval = 0.5;
            }
            break;

        case 'l': // length of each buffer
            Settings_GetUpperCaseArg(optarg,outarg);
            mExtSettings->mBufLen = byte_atoi( outarg );
            setBuflenSet( mExtSettings );
            if ( !isUDP( mExtSettings ) ) {
                 if ( mExtSettings->mBufLen < (int) sizeof( client_hdr ) &&
                      !isCompat( mExtSettings ) ) {
                    setCompat( mExtSettings );
                    fprintf( stderr, warn_implied_compatibility, option );
                 }
            } else {
                if ( mExtSettings->mBufLen < (int) sizeof( UDP_datagram ) ) {
                    mExtSettings->mBufLen = sizeof( UDP_datagram );
                    fprintf( stderr, warn_buffer_too_small, mExtSettings->mBufLen );
                }
                if ( !isCompat( mExtSettings ) &&
                            mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram )
                            + sizeof( client_hdr ) ) ) {
                    setCompat( mExtSettings );
                    fprintf( stderr, warn_implied_compatibility, option );
                }
            }

            break;

        case 'm': // print TCP MSS
            setPrintMSS( mExtSettings );
            break;

        case 'n': // bytes of data
            // amount mode (instead of time mode)
            unsetModeTime( mExtSettings );
            Settings_GetUpperCaseArg(optarg,outarg);
            mExtSettings->mAmount = byte_atoi( outarg );
            break;

        case 'o' : // output the report and other messages into the file
            unsetSTDOUT( mExtSettings );
            mExtSettings->mOutputFileName = new char[strlen(optarg)+1];
            strcpy( mExtSettings->mOutputFileName, optarg);
            break;

        case 'p': // server port
            mExtSettings->mPort = atoi( optarg );
            break;

        case 'r': // test mode tradeoff
            if ( mExtSettings->mThreadMode != kMode_Client ) {
                fprintf( stderr, warn_invalid_server_option, option );
                break;
            }
            if ( isCompat( mExtSettings ) ) {
                fprintf( stderr, warn_invalid_compatibility_option, option );
            }

            mExtSettings->mMode = kTest_TradeOff;
            break;

        case 's': // server mode
            if ( mExtSettings->mThreadMode != kMode_Unknown ) {
                fprintf( stderr, warn_invalid_client_option, option );
                break;
            }

            mExtSettings->mThreadMode = kMode_Listener;
            break;

        case 't': // seconds to write for
            // time mode (instead of amount mode)
            setModeTime( mExtSettings );
            mExtSettings->mAmount = (int) (atof( optarg ) * 100.0);
            break;

        case 'u': // UDP instead of TCP
            // if -b has already been processed, UDP rate will
            // already be non-zero, so don't overwrite that value
            if ( !isUDP( mExtSettings ) ) {
                setUDP( mExtSettings );
                mExtSettings->mUDPRate = kDefault_UDPRate;
            }

            // if -l has already been processed, mBufLenSet is true
            // so don't overwrite that value.
            if ( !isBuflenSet( mExtSettings ) ) {
                mExtSettings->mBufLen = kDefault_UDPBufLen;
            } else if ( mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram ) 
                        + sizeof( client_hdr ) ) &&
                        !isCompat( mExtSettings ) ) {
                setCompat( mExtSettings );
                fprintf( stderr, warn_implied_compatibility, option );
            }
            break;

        case 'v': // print version and exit
            fprintf( stderr, version );
            exit(1);
            break;

        case 'w': // TCP window size (socket buffer size)
            Settings_GetUpperCaseArg(optarg,outarg);
            mExtSettings->mTCPWin = byte_atoi(outarg);

            if ( mExtSettings->mTCPWin < 2048 ) {
                fprintf( stderr, warn_window_small, mExtSettings->mTCPWin );
            }
            break;

        case 'x': // Limit Reports
            while ( *optarg != '\0' ) {
                switch ( *optarg ) {
                    case 's':
                    case 'S':
                        setNoSettReport( mExtSettings );
                        break;
                    case 'c':
                    case 'C':
                        setNoConnReport( mExtSettings );
                        break;
                    case 'd':
                    case 'D':
                        setNoDataReport( mExtSettings );
                        break;
                    case 'v':
                    case 'V':
                        setNoServReport( mExtSettings );
                        break;
                    case 'm':
                    case 'M':
                        setNoMultReport( mExtSettings );
                        break;
                    default:
                        fprintf(stderr, warn_invalid_report, *optarg);
                }
                optarg++;
            }
            break;

        case 'y': // Reporting Style
            switch ( *optarg ) {
                case 'c':
                case 'C':
                    mExtSettings->mReportMode = kReport_CSV;
                    break;
                default:
                    fprintf( stderr, warn_invalid_report_style, optarg );
            }
            break;


            // more esoteric options
        case 'E': // specify the local port on this PC to connect with (only for client mode)
            mExtSettings->mLocalPort = atoi( optarg );
            break;
        
        case 'B': // specify bind address
            mExtSettings->mLocalhost = new char[ strlen( optarg ) + 1 ];
            strcpy( mExtSettings->mLocalhost, optarg );
            // Test for Multicast
            iperf_sockaddr temp;
            SockAddr_setHostname( mExtSettings->mLocalhost, &temp,
                             (isIPV6( mExtSettings ) ? 1 : 0 ));
            if ( SockAddr_isMulticast( &temp ) ) {
                setMulticast( mExtSettings );
            }
            break;

        case 'C': // Run in Compatibility Mode
            setCompat( mExtSettings );
            if ( mExtSettings->mMode != kTest_Normal ) {
                fprintf( stderr, warn_invalid_compatibility_option,
                        ( mExtSettings->mMode == kTest_DualTest ?
                          'd' : 'r' ) );
                mExtSettings->mMode = kTest_Normal;
            }
            break;

        case 'D': // Run as a daemon
            setDaemon( mExtSettings );
            break;

        case 'F' : // Get the input for the data stream from a file
            if ( mExtSettings->mThreadMode != kMode_Client ) {
                fprintf( stderr, warn_invalid_server_option, option );
                break;
            }

            setFileInput( mExtSettings );
            mExtSettings->mFileName = new char[strlen(optarg)+1];
            strcpy( mExtSettings->mFileName, optarg);
            break;

        case 'I' : // Set the stdin as the input source
            if ( mExtSettings->mThreadMode != kMode_Client ) {
                fprintf( stderr, warn_invalid_server_option, option );
                break;
            }

            setFileInput( mExtSettings );
            setSTDIN( mExtSettings );
            mExtSettings->mFileName = new char[strlen("<stdin>")+1];
            strcpy( mExtSettings->mFileName,"<stdin>");
            break;

        case 'L': // Listen Port (bidirectional testing client-side)
            if ( mExtSettings->mThreadMode != kMode_Client ) {
                fprintf( stderr, warn_invalid_server_option, option );
                break;
            }

            mExtSettings->mListenPort = atoi( optarg );
            break;

        case 'M': // specify TCP MSS (maximum segment size)
            Settings_GetUpperCaseArg(optarg,outarg);

            mExtSettings->mMSS = byte_atoi( outarg );
            break;

        case 'N': // specify TCP nodelay option (disable Jacobson's Algorithm)
            setNoDelay( mExtSettings );
            break;

        case 'P': // number of client threads
#ifdef HAVE_THREAD
            mExtSettings->mThreads = atoi( optarg );
#else
            if ( mExtSettings->mThreadMode != kMode_Server ) {
                fprintf( stderr, warn_invalid_single_threaded, option );
            } else {
                mExtSettings->mThreads = atoi( optarg );
            }
#endif
            break;

        case 'R':
            setRemoveService( mExtSettings );
            break;

        case 'S': // IP type-of-service
            // TODO use a function that understands base-2
            // the zero base here allows the user to specify
            // "0x#" hex, "0#" octal, and "#" decimal numbers
            mExtSettings->mTOS = strtol( optarg, NULL, 0 );
            break;

        case 'T': // time-to-live for multicast
            mExtSettings->mTTL = atoi( optarg );
            break;

        case 'U': // single threaded UDP server
            setSingleUDP( mExtSettings );
            break;

        case 'V': // IPv6 Domain
            setIPV6( mExtSettings );
            if ( mExtSettings->mThreadMode == kMode_Server 
                 && mExtSettings->mLocalhost != NULL ) {
                // Test for Multicast
                iperf_sockaddr temp;
                SockAddr_setHostname( mExtSettings->mLocalhost, &temp, 1);
                if ( SockAddr_isMulticast( &temp ) ) {
                    setMulticast( mExtSettings );
                }
            } else if ( mExtSettings->mThreadMode == kMode_Client ) {
                // Test for Multicast
                iperf_sockaddr temp;
                SockAddr_setHostname( mExtSettings->mHost, &temp, 1 );
                if ( SockAddr_isMulticast( &temp ) ) {
                    setMulticast( mExtSettings );
                }
            }
            break;

        case 'W' :
            setSuggestWin( mExtSettings );
            fprintf( stderr, "The -W option is not available in this release\n");
            break;

        case 'Z':
#ifdef TCP_CONGESTION
	    setCongestionControl( mExtSettings );
	    mExtSettings->mCongestion = new char[strlen(optarg)+1];
	    strcpy( mExtSettings->mCongestion, optarg);
#else
            fprintf( stderr, "The -Z option is not available on this operating system\n");
#endif
	    break;

        default: // ignore unknown
            break;
    }
} // end Interpret
Пример #17
0
int MprSocket::openServer(char *addr, int portNum, MprSocketAcceptProc acceptFn, 
						  void *data, int initialFlags)
{
#if BLD_FEATURE_IPV6
	struct addrinfo		hints, *res;
	struct sockaddr_storage	sockAddr6;
	char 				portNumString[MPR_MAX_IP_PORT];
	char 				addrBuf[MPR_MAX_IP_ADDR];
	char 				*bindName;
#endif
	struct sockaddr_in	sockAddr;
	struct sockaddr 	*sa;
	struct hostent		*hostent;
	MprSocklen 			addrlen;
	int					datagram, rc;

	mprAssert(addr);

	if (addr == 0 || *addr == '\0') {
		mprLog(6, log, "openServer: *:%d, flags %x\n", portNum, initialFlags);
	} else {
		mprLog(6, log, "openServer: %s:%d, flags %x\n", addr, portNum, initialFlags);
	}


#if BLD_FEATURE_IPV6

	if (addr[0] == '[') {
		ipv6 = 1;
		mprStrcpy(addrBuf, sizeof(addrBuf), &addr[1]);
		mprAssert(addrBuf[strlen(addrBuf) - 1] == ']');
		addrBuf[strlen(addrBuf) - 1] = '\0';
		addr = addrBuf;
	}

	if (ipv6) {
		memset((char *) &hints, '\0', sizeof(hints));
		memset((char *) &sockAddr6, '\0', sizeof(struct sockaddr_storage));

		mprSprintf(portNumString, sizeof(portNumString), "%d", portNum);

		hints.ai_socktype = SOCK_STREAM;
		hints.ai_family = AF_INET6;

		if (strcmp(addr, "") != 0) {
			bindName = addr;
		} else {
			bindName = NULL;
			hints.ai_flags |= AI_PASSIVE; 				/* Bind to 0.0.0.0 and :: */
														/* Sets to IN6ADDR_ANY_INIT */
		}
			
		rc = getaddrinfo(bindName, portNumString, &hints, &res);
		if (rc) {
			return MPR_ERR_CANT_OPEN;

		}
		sa = (struct sockaddr*) &sockAddr6;
		memcpy(sa, res->ai_addr, res->ai_addrlen);
		addrlen = res->ai_addrlen;
		freeaddrinfo(res);

	} else 
#endif
	{
		/*
		 *	TODO could we use getaddrinfo in all cases. ie. merge with IPV6 code
		 */
		memset((char *) &sockAddr, '\0', sizeof(struct sockaddr_in));
		addrlen = sizeof(struct sockaddr_in);
		sockAddr.sin_family = AF_INET;

		sockAddr.sin_port = htons((short) (portNum & 0xFFFF));
		if (strcmp(addr, "") != 0) {
			sockAddr.sin_addr.s_addr = inet_addr(addr);
			if (sockAddr.sin_addr.s_addr == INADDR_NONE) {
				hostent = mprGetHostByName(addr);
				if (hostent != 0) {
					memcpy((char*) &sockAddr.sin_addr, (char*) hostent->h_addr_list[0], 
						(size_t) hostent->h_length);
					mprFreeGetHostByName(hostent);
				} else {
					return MPR_ERR_NOT_FOUND;
				}
			}
		} else {
			sockAddr.sin_addr.s_addr = INADDR_ANY;
		}
		sa = (struct sockaddr*) &sockAddr;
	}

	lock();
	port = portNum;
	acceptCallback = acceptFn;
	acceptData = data;

	flags = (initialFlags & 
		(MPR_SOCKET_BROADCAST | MPR_SOCKET_DATAGRAM | MPR_SOCKET_BLOCK | 
		 MPR_SOCKET_LISTENER | MPR_SOCKET_NOREUSE | MPR_SOCKET_NODELAY));

	ipAddr = mprStrdup(addr);

	datagram = flags & MPR_SOCKET_DATAGRAM;

	//
	//	Create the O/S socket
	//
	sock = socket(sa->sa_family, datagram ? SOCK_DGRAM: SOCK_STREAM, 0);
	if (sock < 0) {
		unlock();
		return MPR_ERR_CANT_OPEN;
	}
#if !WIN && !WINCE && !VXWORKS
	fcntl(sock, F_SETFD, FD_CLOEXEC);		// Children won't inherit this fd
#endif

#if CYGWIN || LINUX || MACOSX || VXWORKS || FREEBSD
	if (!(flags & MPR_SOCKET_NOREUSE)) {
		rc = 1;
		setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &rc, sizeof(rc));
	}
#endif

	rc = bind(sock, sa, addrlen);
	// rc = bind(sock, res->ai_addr, res->ai_addrlen);
	if (rc < 0) {
		int err = errno;
		err = err;
		::closesocket(sock);
		sock = -1;
		unlock();
		return MPR_ERR_CANT_OPEN;
	}

	if (! datagram) {
		flags |= MPR_SOCKET_LISTENER;
		if (listen(sock, SOMAXCONN) < 0) {
			::closesocket(sock);
			sock = -1;
			unlock();
			return MPR_ERR_CANT_OPEN;
		}
		handler = new MprSelectHandler(sock, MPR_SOCKET_READABLE, 
			(MprSelectProc) acceptProcWrapper, (void*) this, handlerPriority);
	}
	handlerMask |= MPR_SOCKET_READABLE;

//TODO - what about WINCE?
#if WIN
	//
	//	Delay setting reuse until now so that we can be assured that we
	//	have exclusive use of the port.
	//
	if (!(flags & MPR_SOCKET_NOREUSE)) {
		rc = 1;
		setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &rc, sizeof(rc));
	}
#endif

	setBlockingMode((bool) (flags & MPR_SOCKET_BLOCK));

	//
	//	TCP/IP stacks have the No delay option (nagle algorithm) on by default.
	//
	if (flags & MPR_SOCKET_NODELAY) {
		setNoDelay(1);
	}
	unlock();
	return sock;
}
Пример #18
0
/*
 * Create a connection to a waiting debugger.
 */
static bool establishConnection(JdwpState* state)
{
    union {
        struct sockaddr_in  addrInet;
        struct sockaddr     addrPlain;
    } addr;
    struct hostent* pEntry;
    int h_errno;

    assert(state != NULL && state->netState != NULL);
    assert(!state->params.server);
    assert(state->params.host[0] != '\0');
    assert(state->params.port != 0);

    /*
     * Start by resolving the host name.
     */
//#undef HAVE_GETHOSTBYNAME_R
//#warning "forcing non-R"
#ifdef HAVE_GETHOSTBYNAME_R
    struct hostent he;
    char auxBuf[128];
    int cc = gethostbyname_r(state->params.host, &he, auxBuf, sizeof(auxBuf),
            &pEntry, &h_errno);
    if (cc != 0) {
        ALOGW("gethostbyname_r('%s') failed: %s",
            state->params.host, strerror(errno));
        return false;
    }

#else
    h_errno = 0;
    pEntry = gethostbyname(state->params.host);
    if (pEntry == NULL) {
        ALOGW("gethostbyname('%s') failed: %s",
            state->params.host, strerror(h_errno));
        return false;
    }
#endif

    /* copy it out ASAP to minimize risk of multithreaded annoyances */
    memcpy(&addr.addrInet.sin_addr, pEntry->h_addr, pEntry->h_length);
    addr.addrInet.sin_family = pEntry->h_addrtype;

    addr.addrInet.sin_port = htons(state->params.port);

    ALOGI("Connecting out to '%s' %d",
        inet_ntoa(addr.addrInet.sin_addr), ntohs(addr.addrInet.sin_port));

    /*
     * Create a socket.
     */
    JdwpNetState* netState;
    netState = state->netState;
    netState->clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (netState->clientSock < 0) {
        ALOGE("Unable to create socket: %s", strerror(errno));
        return false;
    }

    /*
     * Try to connect.
     */
    if (connect(netState->clientSock, &addr.addrPlain, sizeof(addr)) != 0) {
        ALOGE("Unable to connect to %s:%d: %s",
            inet_ntoa(addr.addrInet.sin_addr), ntohs(addr.addrInet.sin_port),
            strerror(errno));
        close(netState->clientSock);
        netState->clientSock = -1;
        return false;
    }

    ALOGI("Connection established to %s (%s:%d)",
        state->params.host, inet_ntoa(addr.addrInet.sin_addr),
        ntohs(addr.addrInet.sin_port));
    netState->awaitingHandshake = true;
    netState->inputCount = 0;

    setNoDelay(netState->clientSock);

    if (pipe(netState->wakePipe) < 0) {
        ALOGE("pipe failed");
        return false;
    }

    return true;
}
Пример #19
0
int MprSocket::openClient(char *addr, int portNum, int initialFlags)
{
#if BLD_FEATURE_IPV6
	struct addrinfo 	hints, *res;
	struct sockaddr_storage	remoteAddr6;
	char 				portNum_string[MPR_MAX_IP_PORT];
	char 				addrBuf[MPR_MAX_IP_ADDR];
#endif
	struct sockaddr_in	remoteAddr;
	struct hostent		*hostent;
	struct sockaddr 	*sa;
	MprSocklen			addrlen;
	int					broadcast, datagram, rc, err;

	mprLog(6, log, "openClient: %s:%d, flags %x\n", addr, portNum, 
		initialFlags);

#if BLD_FEATURE_IPV6
	if (addr[0] == '[') {
		ipv6 = 1;
		mprStrcpy(addrBuf, sizeof(addr), &addr[1]);
		mprAssert(addrBuf[strlen(addrBuf) - 2] == ']');
		addrBuf[strlen(addrBuf) - 2] = '\0';
		addr = addrBuf;
	} else {
        ipv6 = 0;
    }

	if (ipv6) {
		memset((char*) &hints, '\0', sizeof(hints));
		memset((char*) &remoteAddr6, '\0', sizeof(struct sockaddr_storage));

		mprSprintf(portNum_string, sizeof(portNum_string), "%d", portNum);

		hints.ai_socktype = SOCK_STREAM;

		rc = getaddrinfo(addr, portNum_string, &hints, &res);
		if (rc) {
			/* no need to unlock yet */
			return MPR_ERR_CANT_OPEN;

		}
		sa = (struct sockaddr*) &remoteAddr6;
		memcpy(sa, res->ai_addr, res->ai_addrlen);
		addrlen = res->ai_addrlen;
		freeaddrinfo(res);
		
	} else 
#endif
	{
		memset((char *) &remoteAddr, '\0', sizeof(struct sockaddr_in));
		remoteAddr.sin_family = AF_INET;
		remoteAddr.sin_port = htons((short) (portNum & 0xFFFF));
		sa = (struct sockaddr*) &remoteAddr;
		addrlen = sizeof(remoteAddr);
	}
		
	lock();
	port = portNum;
	flags = (initialFlags & 
		(MPR_SOCKET_BROADCAST | MPR_SOCKET_DATAGRAM | MPR_SOCKET_BLOCK | 
		 MPR_SOCKET_LISTENER | MPR_SOCKET_NOREUSE | MPR_SOCKET_NODELAY));

	//	Save copy of the address
	ipAddr = mprStrdup(addr);

#if BLD_FEATURE_IPV6
	if (!ipv6) {
		// Nothing here
	} else 
#endif
	{
		remoteAddr.sin_addr.s_addr = inet_addr(ipAddr);
		if (remoteAddr.sin_addr.s_addr == INADDR_NONE) {
			hostent = mprGetHostByName(ipAddr);
			if (hostent != 0) {
				memcpy((char*) &remoteAddr.sin_addr, (char*) hostent->h_addr_list[0], 
					(size_t) hostent->h_length);
				mprFreeGetHostByName(hostent);
			} else {
				unlock();
				return MPR_ERR_NOT_FOUND;
			}
		}
	}

	broadcast = flags & MPR_SOCKET_BROADCAST;
	if (broadcast) {
		flags |= MPR_SOCKET_DATAGRAM;
	}
	datagram = flags & MPR_SOCKET_DATAGRAM;

	//
	//	Create the O/S socket
	//
	sock = socket(sa->sa_family, datagram ? SOCK_DGRAM: SOCK_STREAM, 0);
	if (sock < 0) {
		err = getError();
		unlock();
		return -err;
	}
#if !WIN && !WINCE && !VXWORKS
	fcntl(sock, F_SETFD, FD_CLOEXEC);		// Children won't inherit this fd
#endif

	if (broadcast) {
		int	flag = 1;
		if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &flag, sizeof(flag)) < 0) {
			err = getError();
			::closesocket(sock);
			sock = -1;
			unlock();
			return -err;
		}
	}
 
	if (!datagram) {
		flags |= MPR_SOCKET_CONNECTING;
		rc = connect(sock, sa, addrlen);
		if (rc < 0) {
			err = getError();
			::closesocket(sock);
			sock = -1;
			unlock();
#if UNUSED
			//
			//	If the listen backlog is too high, ECONNREFUSED is returned
			//
			if (err == EADDRINUSE || err == ECONNREFUSED) {
				return MPR_ERR_BUSY;
			}
#endif
			return -err;
		}
	}

	setBlockingMode((bool) (flags & MPR_SOCKET_BLOCK));

	//
	//	TCP/IP stacks have the No delay option (nagle algorithm) on by default.
	//
	if (flags & MPR_SOCKET_NODELAY) {
		setNoDelay(1);
	}
	unlock();
	return sock;
}