Beispiel #1
0
// --------------------------------------------------------------------------
// NetTCP6Connect:
//
// Return values:
//    0: success
//   -1: Failed to resolve srvname.
//   -2: Socket error / Failed to connect (TCP only).
//
sint32_t NetTCP6Connect( pal_socket_t *p_sock, char *Host, uint16_t Port ) 
{
  pal_socket_t         sockfd;
  struct sockaddr_in6  serv_addr;
  struct in6_addr      addr;

  if( NULL == NetText2Addr6(Host, &addr) )
  {
    return -1;
  }

  memset(&serv_addr, 0, sizeof(serv_addr)); 
  serv_addr.sin6_family      = AF_INET6;
  serv_addr.sin6_port        = htons(Port);
  serv_addr.sin6_addr = addr;

  /*
   * Open a TCP socket (an Internet 6 stream socket).
   */
  if( (sockfd = pal_socket(AF_INET6, SOCK_STREAM, 0)) < 0 )
  {
    return -2;
  }

  /*
   * Connect to the server.
   */
  if( pal_connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
  {
    pal_closesocket( sockfd );
    return -2;
  }
  
  *p_sock = sockfd;
  return 0;
}
Beispiel #2
0
// --------------------------------------------------------------------------
// NetUDPConnect:
//
// Return values:
//    0: success
//   -1: Failed to resolve srvname.
//   -2: Socket error / Failed to connect (TCP only).
//
sint32_t NetUDPConnect(pal_socket_t *p_sock, char *Host, uint16_t Port)
{
  pal_socket_t        sockfd;
  struct sockaddr_in  serv_addr;
  struct in_addr      addr;

  if( NetText2Addr(Host, &addr) == NULL )
  {
    return -1;
  }

  memset(&serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family      = AF_INET;
  serv_addr.sin_port        = htons(Port);
  serv_addr.sin_addr.s_addr = addr.s_addr;

  /*
   * Open a UDP socket.
   */
  if( (sockfd = pal_socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
  {
    return -2;
  }

  /*
   * Connect to the server.
   */
  if( pal_connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
  {
    pal_closesocket( sockfd );
    return -2;
  }

  *p_sock = sockfd;
  return 0;
}
void M2MConnectionHandlerPimpl::dns_handler()
{
    palStatus_t status;
    palSocketLength_t _socket_address_len;

    tr_debug("M2MConnectionHandlerPimpl::dns_handler - _socket_state = %d", _socket_state);

    switch (_socket_state) {
        case ESocketStateConnectBeingCalled:
        case ESocketStateCloseBeingCalled:
            // Ignore these events
            break;

        case ESocketStateDisconnected:

            // Initialize the socket to stable state
            close_socket();

            status = pal_getAddressInfo(_server_address.c_str(), &_socket_address, &_socket_address_len);
            if (PAL_SUCCESS != status) {
                tr_error("addrInfo, err: %d", (int)status);
                _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
                return;
            }
            status = pal_setSockAddrPort(&_socket_address, _server_port);

            if (PAL_SUCCESS != status) {
                tr_error("setSockAddrPort err: %d", (int)status);
            } else {
                tr_debug("address family: %d", (int)_socket_address.addressType);
            }

            if (_socket_address.addressType == PAL_AF_INET) {
                status = pal_getSockAddrIPV4Addr(&_socket_address,_ipV4Addr);
                if (PAL_SUCCESS != status) {
                    tr_error("sockAddr4, err: %d", (int)status);
                    _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
                    return;
                }

                tr_debug("IPv4 Address %s", tr_array(_ipV4Addr, 4));

                _address._address = (void*)_ipV4Addr;
                _address._length = PAL_IPV4_ADDRESS_SIZE;
                _address._port = _server_port;
            }
            else if (_socket_address.addressType == PAL_AF_INET6) {
                status = pal_getSockAddrIPV6Addr(&_socket_address,_ipV6Addr);
                if (PAL_SUCCESS != status) {
                    tr_error("sockAddr6, err: %d", (int)status);
                    _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
                    return;
                }

                tr_debug("IPv6 Address %s", tr_array(_ipV6Addr,sizeof(_ipV6Addr)));

                _address._address = (void*)_ipV6Addr;
                _address._length = PAL_IPV6_ADDRESS_SIZE;
                _address._port = _server_port;
            }
            else {
                tr_error("socket config error, stack: %d", (int)_socket_address.addressType);
                _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
                return;
            }

            if(!init_socket()) {
                tr_error("socket init error");
                // The init_socket() calls the socket_error() -callback directly, so it must not be
                // done here too.
                return;
            }

            if(is_tcp_connection()) {
#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
                tr_debug("resolve_server_address - Using TCP");

                // At least on mbed-os the pal_connect() will perform callbacks even during it
                // is called, which we will ignore when this state is set.
                _socket_state = ESocketStateConnectBeingCalled;

                status = pal_connect(_socket, &_socket_address, sizeof(_socket_address));

                if (status == PAL_ERR_SOCKET_IN_PROGRES) {
                    // In this case the connect is done asynchronously, and the pal_socketMiniSelect()
                    // will be used to detect the end of connect.
                    // XXX: the mbed-os version of PAL has a bug (IOTPAL-228) open that the select
                    // does not necessarily work correctly. So, should we actually handle
                    // the PAL_ERR_SOCKET_IN_PROGRESS as a error here if code is compiled for mbed-os?
                    tr_debug("pal_connect(): %d, async connect started", (int)status);
                    // we need to wait for the event
                    _socket_state = ESocketStateConnecting;
                    break;

                } else if (status == PAL_SUCCESS) {

                    tr_info("pal_connect(): success");
                    _running = true;
                    _socket_state = ESocketStateConnected;

                } else {
                    tr_error("pal_connect(): failed: %d", (int)status);
                    close_socket();
                    _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
                    return;
                }
#else
                tr_error("dns_handler() - TCP not configured"
#endif //PAL_NET_TCP_AND_TLS_SUPPORT
            } else {
                tr_debug("resolve_server_address - Using UDP");
                _socket_state = ESocketStateConnected;
                _running = true;
            }

        // fall through is a normal flow in case the UDP was used or pal_connect() happened to return immediately with PAL_SUCCESS
        case ESocketStateConnected:
            if (_security) {
                if (_security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Certificate ||
                    _security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Psk) {
                    if( _security_impl != NULL ){
                        _security_impl->reset();
                        if (_security_impl->init(_security) == 0) {
                            _is_handshaking = true;
                            tr_debug("resolve_server_address - connect DTLS");
                            if(_security_impl->start_connecting_non_blocking(_base) < 0 ){
                                tr_debug("dns_handler - handshake failed");
                                _is_handshaking = false;
                                close_socket();
                                _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR);
                                return;
                            }
                        } else {
                            tr_error("resolve_server_address - init failed");
                            close_socket();
                            _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, false);
                            return;
                        }
                    } else {
                        tr_error("dns_handler - sec is null");
                        close_socket();
                        _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, false);
                        return;
                    }
                }
            }
            if(!_is_handshaking) {
                enable_keepalive();
                _observer.address_ready(_address,
                                        _server_type,
                                        _address._port);
            }
            break;

        // This case is a continuation of a nonblocking connect() and is skipped
        // completely on UDP.
        case ESocketStateConnecting:

            // there is only one socket which we are interested
            uint8_t socketStatus[1];
            pal_timeVal_t zeroTime = {0, 0};
            uint32_t socketsSet = 0;

            status = pal_socketMiniSelect(&_socket, 1, &zeroTime, socketStatus, &socketsSet);
            if (status != PAL_SUCCESS) {
                // XXX: how could this fail? What to do?
                tr_error("dns_handler() - read select fail, err: %d", (int)status);
                close_socket(); // this will also set the socket state to disconnect
                // XXX: should we inform the observer here too?
                return;
            }

            if (socketsSet > 0) {
                if (PAL_NET_SELECT_IS_TX(socketStatus, 0)) {
                    // Socket is connected, signal the dns_handler() again to run rest of the steps
                    tr_debug("dns_handler() - connect+select succeeded");
                    _socket_state = ESocketStateConnected;
                    send_dns_event();
                } else if (PAL_NET_SELECT_IS_ERR(socketStatus, 0)) {
                    tr_error("dns_handler() - connect+select failed");
                    close_socket(); // this will also set the socket state to disconnect
                    // XXX: should we inform the observer here too?
                } else {
                    tr_debug("dns_handler() - connect+select not ready yet, continue waiting");
                }
            }
            break;
    }