private function connect() {
        $connection = fsockopen('tcp://'.$this->options['host'],
                                         $this->options['port'],
                                         $errorCode,
                                         $errorMsg,
                                         $this->options['timeout']);
        // TODO: connect() might hang without producing an error if the connection fails
        if (!$connection) throw new RuntimeException('Could not open socket: '.$errorMsg.' (error '.$errorCode.')');

        $data = stream_get_meta_data($connection);
        if ($data['timed_out']) throw new InfrastructureException('Timeout on socket connection');

        socket_set_timeout($connection, $this->options['timeout']);
        $this->connection = $connection;

        // init connection
        $this->readResponse();                          // read greeting
        $this->writeData('EHLO '.$this->hostName);      // extended "Hello" first
        $response = $this->readResponse();

        $this->parseResponse($response);
        if ($this->responseStatus != 250) {
            $this->writeData('HELO '.$this->hostName);  // regular "Hello" if the extended one fails
            $response = $this->readResponse();

            $this->parseResponse($response);
            if ($this->responseStatus != 250)
                throw new RuntimeException('HELO command not accepted: '.$this->responseStatus.' '.$this->response);
        }
    }