public function connect($addr, $port = 6667, $reconnecting = false)
    {
        ob_implicit_flush();
        $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: connecting',
            __FILE__, __LINE__
        );

        if ($hasPort = preg_match(self::IP_PATTERN, $addr)) {
            $colon = strrpos($addr, ':');
            $this->_address = substr($addr, 0, $colon);
            $this->_port = (int) substr($addr, $colon + 1);
        } elseif ($hasPort === 0) {
            $this->_address = $addr;
            $this->_port = $port;
            $addr .= ':' . $port;
        }

        $timeout = ini_get("default_socket_timeout");
        $context = stream_context_create(array('socket' => array('bindto' => $this->_bindto)));
        $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: binding to '.$this->_bindto,
            __FILE__, __LINE__);


        if ($this->_socket = stream_socket_client($addr, $errno, $errstr,
                $timeout, STREAM_CLIENT_CONNECT, $context)
        ) {
            if (!stream_set_blocking($this->_socket, 0)) {
                $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_SOCKET: unable to unblock stream',
                    __FILE__, __LINE__
                );
                $this->throwError('unable to unblock stream');
            }

            $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: connected',
                __FILE__, __LINE__
            );

            $this->_autoretrycount = 0;
            $this->_connectionerror = false;

            $this->registerTimeHandler($this->_rxtimeout * 125, $this, '_pingcheck');

            $this->_lasttx = $this->_lastrx = time();
            $this->_updatestate();
            return $this;
        }

        $error_msg = "couldn't connect to \"$addr\" reason: \"$errstr ($errno)\"";
        $this->log(SMARTIRC_DEBUG_SOCKET, 'DEBUG_NOTICE: '.$error_msg,
            __FILE__, __LINE__
        );
        $this->throwError($error_msg);

        return ($reconnecting) ? false : $this->reconnect();
    }