static int ftp_open(URLContext *h, const char *url, int flags)
{
    char proto[10], path[MAX_URL_SIZE], buf[CONTROL_BUFFER_SIZE], opts_format[20];
    AVDictionary *opts = NULL;
    int port, err;
    FTPContext *s = h->priv_data;

    av_dlog(h, "ftp protocol open\n");

    s->state = DISCONNECTED;
    s->filesize = -1;
    s->conn_control_interrupt_cb.opaque = s;
    s->conn_control_interrupt_cb.callback = ftp_conn_control_block_control;

    av_url_split(proto, sizeof(proto),
                 s->credencials, sizeof(s->credencials),
                 s->hostname, sizeof(s->hostname),
                 &port,
                 path, sizeof(path),
                 url);

    if (port < 0)
        port = 21;

    if (!s->conn_control) {
        ff_url_join(buf, sizeof(buf), "tcp", NULL, s->hostname, port, NULL);
        if (s->rw_timeout != -1) {
            snprintf(opts_format, sizeof(opts_format), "%d", s->rw_timeout);
            av_dict_set(&opts, "timeout", opts_format, 0);
        } /* if option is not given, don't pass it and let tcp use its own default */
        err = ffurl_open(&s->conn_control, buf, AVIO_FLAG_READ_WRITE,
                         &s->conn_control_interrupt_cb, &opts);
        av_dict_free(&opts);
        if (err < 0)
            goto fail;

        /* consume all messages from server */
        if (ftp_status(s, NULL, NULL, NULL, NULL, 220) != 220) {
            av_log(h, AV_LOG_ERROR, "Server not ready for new users\n");
            err = AVERROR(EACCES);
            goto fail;
        }

        if ((err = ftp_auth(s)) < 0)
            goto fail;

        if ((err = ftp_type(s)) < 0)
            goto fail;

        if ((err = ftp_current_dir(s)) < 0)
            goto fail;
        av_strlcat(s->path, path, sizeof(s->path));

        if ((err = ftp_passive_mode(s)) < 0)
            goto fail;

        if (ftp_file_size(s) < 0 && flags & AVIO_FLAG_READ)
            h->is_streamed = 1;
        if (s->write_seekable != 1 && flags & AVIO_FLAG_WRITE)
            h->is_streamed = 1;
    }

    if ((err = ftp_reconnect_data_connection(h)) < 0)
        goto fail;

    return 0;
  fail:
    av_log(h, AV_LOG_ERROR, "FTP open failed\n");
    ffurl_closep(&s->conn_control);
    ffurl_closep(&s->conn_data);
    return err;
}