Changeset e45c692c9be3706dbaee7f84a294a943b05c6962

Show
Ignore:
Timestamp:
09/09/06 11:53:34 (2 years ago)
Author:
Rémi Denis-Courmont <rem@videolan.org>
git-committer:
Rémi Denis-Courmont <rem@videolan.org> 1157795614 +0000
git-parent:

[4a0c164d8c02d3ed72dd78631ba1ea050f9bcd03]

git-author:
Rémi Denis-Courmont <rem@videolan.org> 1157795614 +0000
Message:

Untested FTP access output (closes #605)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/access/ftp.c

    r230ff45 re45c692  
    2828 *****************************************************************************/ 
    2929#include <stdlib.h> 
     30#include <assert.h> 
    3031 
    3132#include <vlc/vlc.h> 
     
    3536#include "network.h" 
    3637#include "vlc_url.h" 
     38#include "stream_output.h" 
    3739 
    3840/***************************************************************************** 
    3941 * Module descriptor 
    4042 *****************************************************************************/ 
    41 static int     Open ( vlc_object_t * ); 
    42 static void    Close( vlc_object_t * ); 
     43static int   InOpen ( vlc_object_t * ); 
     44static void  InClose( vlc_object_t * ); 
     45static int  OutOpen ( vlc_object_t * ); 
     46static void OutClose( vlc_object_t * ); 
    4347 
    4448#define CACHING_TEXT N_("Caching value in ms") 
     
    7175                ACCOUNT_LONGTEXT, VLC_FALSE ); 
    7276    add_shortcut( "ftp" ); 
    73     set_callbacks( Open, Close ); 
     77    set_callbacks( InOpen, InClose ); 
     78 
     79    add_submodule(); 
     80    set_shortname( "FTP" ); 
     81    set_description( _("FTP upload output") ); 
     82    set_capability( "sout access", 0 ); 
     83    set_category( CAT_SOUT ); 
     84    set_subcategory( SUBCAT_SOUT_ACO ); 
     85    add_shortcut( "ftp" ); 
     86    set_callbacks( OutOpen, OutClose ); 
    7487vlc_module_end(); 
    7588 
     
    7891 *****************************************************************************/ 
    7992static int Read( access_t *, uint8_t *, int ); 
     93static int Write( sout_access_out_t *, block_t * ); 
    8094static int Seek( access_t *, int64_t ); 
     95static int OutSeek( sout_access_out_t *, int64_t ); 
    8196static int Control( access_t *, int, va_list ); 
    8297 
     
    90105    char       sz_epsv_ip[NI_MAXNUMERICHOST]; 
    91106}; 
    92  
    93 static int  ftp_SendCommand( access_t *, char *, ... ); 
    94 static int  ftp_ReadCommand( access_t *, int *, char ** ); 
    95 static int  ftp_StartStream( access_t *, int64_t ); 
    96 static int  ftp_StopStream ( access_t *); 
    97  
    98 static int Connect( access_t *p_access, access_sys_t *p_sys ) 
    99 
    100     int fd, i_answer; 
     107#define GET_OUT_SYS( p_this ) \ 
     108    ((access_sys_t *)(((sout_access_out_t *)(p_this))->p_sys)) 
     109 
     110static int ftp_SendCommand( vlc_object_t *, access_sys_t *, const char *, ... ); 
     111static int ftp_ReadCommand( vlc_object_t *, access_sys_t *, int *, char ** ); 
     112static int ftp_StartStream( vlc_object_t *, access_sys_t *, int64_t ); 
     113static int ftp_StopStream ( vlc_object_t *, access_sys_t * ); 
     114 
     115static int Login( vlc_object_t *p_access, access_sys_t *p_sys ) 
     116
     117    int i_answer; 
    101118    char *psz; 
    102119 
    103120    /* *** Open a TCP connection with server *** */ 
    104     p_sys->fd_cmd = fd = net_ConnectTCP( p_access, p_sys->url.psz_host, 
    105                                       p_sys->url.i_port ); 
     121    int fd = p_sys->fd_cmd = net_ConnectTCP( p_access, p_sys->url.psz_host, 
     122                                             p_sys->url.i_port ); 
    106123    if( fd == -1 ) 
    107124    { 
     
    112129    } 
    113130 
    114     while( ftp_ReadCommand( p_access, &i_answer, NULL ) == 1 ); 
     131    while( ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) == 1 ); 
    115132 
    116133    if( i_answer / 100 != 2 ) 
     
    129146        psz = var_CreateGetString( p_access, "ftp-user" ); 
    130147 
    131     if( ftp_SendCommand( p_access, "USER %s", psz ) < 0 || 
    132         ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 ) 
     148    if( ftp_SendCommand( p_access, p_sys, "USER %s", psz ) < 0 || 
     149        ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) < 0 ) 
    133150    { 
    134151        free( psz ); 
     
    149166                psz = var_CreateGetString( p_access, "ftp-pwd" ); 
    150167 
    151             if( ftp_SendCommand( p_access, "PASS %s", psz ) < 0 || 
    152                 ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 ) 
     168            if( ftp_SendCommand( p_access, p_sys, "PASS %s", psz ) < 0 || 
     169                ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) < 0 ) 
    153170            { 
    154171                free( psz ); 
     
    165182                    msg_Dbg( p_access, "account needed" ); 
    166183                    psz = var_CreateGetString( p_access, "ftp-account" ); 
    167                     if( ftp_SendCommand( p_access, "ACCT %s", 
     184                    if( ftp_SendCommand( p_access, p_sys, "ACCT %s", 
    168185                                         psz ) < 0 || 
    169                         ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 ) 
     186                        ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) < 0 ) 
    170187                    { 
    171188                        free( psz ); 
     
    204221} 
    205222 
    206 /**************************************************************************** 
    207  * Open: connect to ftp server and ask for file 
    208  ****************************************************************************/ 
    209 static int Open( vlc_object_t *p_this ) 
    210 
    211     access_t     *p_access = (access_t*)p_this; 
    212     access_sys_t *p_sys; 
    213     char         *psz; 
    214  
    215     int          i_answer; 
    216     char         *psz_arg; 
    217  
    218     /* Init p_access */ 
    219     STANDARD_READ_ACCESS_INIT 
    220     p_sys->fd_cmd = -1; 
    221     p_sys->fd_data = -1; 
    222  
    223     /* *** Parse URL and get server addr/port and path *** */ 
    224     psz = p_access->psz_path; 
    225     while( *psz == '/' ) 
    226     { 
    227         psz++; 
    228     } 
    229     vlc_UrlParse( &p_sys->url, psz, 0 ); 
    230  
    231     if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' ) 
    232     { 
    233         msg_Err( p_access, "invalid server name" ); 
    234         goto exit_error; 
    235     } 
    236     if( p_sys->url.i_port <= 0 ) 
    237     { 
    238         p_sys->url.i_port = 21; /* default port */ 
    239     } 
    240  
    241     /* FTP URLs are relative to user's default directory (RFC1738) 
    242        For absolute path use ftp://foo.bar//usr/local/etc/filename */ 
    243  
    244     if( *p_sys->url.psz_path == '/' ) 
    245         p_sys->url.psz_path++; 
    246  
    247     if( Connect( p_access, p_sys ) < 0 ) 
    248         goto exit_error; 
     223static int Connect( vlc_object_t *p_access, access_sys_t *p_sys ) 
     224
     225    if( Login( p_access, p_sys ) < 0 ) 
     226        return -1; 
    249227 
    250228    /* Extended passive mode */ 
    251     if( ftp_SendCommand( p_access, "EPSV ALL" ) < 0 ) 
     229    if( ftp_SendCommand( p_access, p_sys, "EPSV ALL" ) < 0 ) 
    252230    { 
    253231        msg_Err( p_access, "cannot request extended passive mode" ); 
    254         return -1; 
    255     } 
    256  
    257     if( ftp_ReadCommand( p_access, &i_answer, NULL ) == 2 ) 
     232        net_Close( p_sys->fd_cmd ); 
     233        return -1; 
     234    } 
     235 
     236    if( ftp_ReadCommand( p_access, p_sys, NULL, NULL ) == 2 ) 
    258237    { 
    259238        if( net_GetPeerAddress( p_sys->fd_cmd, p_sys->sz_epsv_ip, NULL ) ) 
    260             goto exit_error; 
     239        { 
     240            net_Close( p_sys->fd_cmd ); 
     241            return -1; 
     242        } 
    261243    } 
    262244    else 
     
    267249         * the initial connection. 
    268250         */ 
     251        msg_Info( p_access, "FTP Extended passive mode disabled" ); 
    269252        net_Close( p_sys->fd_cmd ); 
    270         p_sys->fd_cmd = -1; 
    271         *p_sys->sz_epsv_ip = '\0'; 
    272  
    273         msg_Info( p_access, "FTP Extended passive mode disabled" ); 
    274  
    275         if( ( p_sys->fd_cmd = Connect( p_access, p_sys ) ) < 0 ) 
    276            goto exit_error; 
    277     } 
    278  
    279     /* binary mode */ 
    280     if( ftp_SendCommand( p_access, "TYPE I" ) < 0 || 
    281         ftp_ReadCommand( p_access, &i_answer, NULL ) != 2 ) 
     253 
     254        if( ( p_sys->fd_cmd = Login( p_access, p_sys ) ) < 0 ) 
     255        { 
     256            net_Close( p_sys->fd_cmd ); 
     257            return -1; 
     258        } 
     259    } 
     260 
     261    /* check binary mode support */ 
     262    if( ftp_SendCommand( p_access, p_sys, "TYPE I" ) < 0 || 
     263        ftp_ReadCommand( p_access, p_sys, NULL, NULL ) != 2 ) 
    282264    { 
    283265        msg_Err( p_access, "cannot set binary transfer mode" ); 
     266        net_Close( p_sys->fd_cmd ); 
     267        return -1; 
     268    } 
     269 
     270    return 0; 
     271} 
     272 
     273 
     274static int parseURL( vlc_url_t *url, const char *path ) 
     275{ 
     276    if( path == NULL ) 
     277        return -1; 
     278 
     279    /* *** Parse URL and get server addr/port and path *** */ 
     280    while( *path == '/' ) 
     281        path++; 
     282 
     283    vlc_UrlParse( url, path, 0 ); 
     284 
     285    if( url->psz_host == NULL || *url->psz_host == '\0' ) 
     286        return -1; 
     287 
     288    if( url->i_port <= 0 ) 
     289        url->i_port = IPPORT_FTP; /* default port */ 
     290 
     291    /* FTP URLs are relative to user's default directory (RFC1738) 
     292    For absolute path use ftp://foo.bar//usr/local/etc/filename */ 
     293 
     294    if( *url->psz_path == '/' ) 
     295        url->psz_path++; 
     296 
     297    return 0; 
     298} 
     299 
     300 
     301/**************************************************************************** 
     302 * Open: connect to ftp server and ask for file 
     303 ****************************************************************************/ 
     304static int InOpen( vlc_object_t *p_this ) 
     305{ 
     306    access_t     *p_access = (access_t*)p_this; 
     307    access_sys_t *p_sys; 
     308    char         *psz_arg; 
     309 
     310    /* Init p_access */ 
     311    STANDARD_READ_ACCESS_INIT 
     312    p_sys->fd_data = -1; 
     313 
     314    if( parseURL( &p_sys->url, p_access->psz_path ) ) 
    284315        goto exit_error; 
    285     } 
     316 
     317    if( Connect( p_this, p_sys ) ) 
     318        goto exit_error; 
    286319 
    287320    /* get size */ 
    288     if( ftp_SendCommand( p_access, "SIZE %s", p_sys->url.psz_path ) < 0 || 
    289         ftp_ReadCommand( p_access, &i_answer, &psz_arg ) != 2 ) 
     321    if( ftp_SendCommand( p_this, p_sys, "SIZE %s", p_sys->url.psz_path ) < 0 || 
     322        ftp_ReadCommand( p_this, p_sys, NULL, &psz_arg ) != 2 ) 
    290323    { 
    291324        msg_Err( p_access, "cannot get file size" ); 
     325        net_Close( p_sys->fd_cmd ); 
    292326        goto exit_error; 
    293327    } 
     
    297331 
    298332    /* Start the 'stream' */ 
    299     if( ftp_StartStream( p_access, 0 ) < 0 ) 
     333    if( ftp_StartStream( p_this, p_sys, 0 ) < 0 ) 
    300334    { 
    301335        msg_Err( p_access, "cannot retrieve file" ); 
     336        net_Close( p_sys->fd_cmd ); 
    302337        goto exit_error; 
    303338    } 
     
    309344 
    310345exit_error: 
    311     if( p_sys->fd_cmd != -1 ) 
    312         net_Close( p_sys->fd_cmd ); 
    313346    vlc_UrlClean( &p_sys->url ); 
    314347    free( p_sys ); 
     
    316349} 
    317350 
     351static int OutOpen( vlc_object_t *p_this ) 
     352{ 
     353    sout_access_out_t *p_access = (sout_access_out_t *)p_this; 
     354    access_sys_t      *p_sys; 
     355 
     356    p_sys = malloc( sizeof( *p_sys ) ); 
     357    if( p_sys == NULL ) 
     358        return VLC_ENOMEM; 
     359    memset( p_sys, 0, sizeof( *p_sys ) ); 
     360 
     361    /* Init p_access */ 
     362    p_sys->fd_data = -1; 
     363 
     364    if( parseURL( &p_sys->url, p_access->psz_name ) ) 
     365        goto exit_error; 
     366 
     367    if( Connect( p_this, p_sys ) ) 
     368        goto exit_error; 
     369 
     370    /* Start the 'stream' */ 
     371    if( ftp_StartStream( p_this, p_sys, 0 ) < 0 ) 
     372    { 
     373        msg_Err( p_access, "cannot store file" ); 
     374        net_Close( p_sys->fd_cmd ); 
     375        goto exit_error; 
     376    } 
     377 
     378    p_access->pf_seek = OutSeek; 
     379    p_access->pf_write = Write; 
     380 
     381    return VLC_SUCCESS; 
     382 
     383exit_error: 
     384        vlc_UrlClean( &p_sys->url ); 
     385    free( p_sys ); 
     386    return VLC_EGENERIC; 
     387} 
     388 
    318389/***************************************************************************** 
    319390 * Close: free unused data structures 
    320391 *****************************************************************************/ 
    321 static void Close( vlc_object_t *p_this ) 
    322 
    323     access_t      *p_access = (access_t*)p_this; 
    324     access_sys_t  *p_sys = p_access->p_sys; 
    325  
     392static void Close( vlc_object_t *p_access, access_sys_t *p_sys ) 
     393
    326394    msg_Dbg( p_access, "stopping stream" ); 
    327     ftp_StopStream( p_access ); 
    328  
    329     if( ftp_SendCommand( p_access, "QUIT" ) < 0 ) 
     395    ftp_StopStream( p_access, p_sys ); 
     396 
     397    if( ftp_SendCommand( p_access, p_sys, "QUIT" ) < 0 ) 
    330398    { 
    331399        msg_Warn( p_access, "cannot quit" ); 
     
    333401    else 
    334402    { 
    335         ftp_ReadCommand( p_access, NULL, NULL ); 
     403        ftp_ReadCommand( p_access, p_sys, NULL, NULL ); 
    336404    } 
    337405    net_Close( p_sys->fd_cmd ); 
     
    342410} 
    343411 
     412static void InClose( vlc_object_t *p_this ) 
     413{ 
     414    Close( p_this, ((access_t *)p_this)->p_sys); 
     415} 
     416 
     417static void OutClose( vlc_object_t *p_this ) 
     418{ 
     419    Close( p_this, GET_OUT_SYS(p_this)); 
     420} 
     421 
     422 
    344423/***************************************************************************** 
    345424 * Seek: try to go at the right place 
    346425 *****************************************************************************/ 
     426static int _Seek( vlc_object_t *p_access, access_sys_t *p_sys, int64_t i_pos ) 
     427{ 
     428    if( i_pos < 0 ) 
     429        return VLC_EGENERIC; 
     430 
     431    msg_Dbg( p_access, "seeking to "I64Fd, i_pos ); 
     432 
     433    ftp_StopStream( (vlc_object_t *)p_access, p_sys ); 
     434    if( ftp_StartStream( (vlc_object_t *)p_access, p_sys, i_pos ) < 0 ) 
     435        return VLC_EGENERIC; 
     436 
     437    return VLC_SUCCESS; 
     438} 
     439 
    347440static int Seek( access_t *p_access, int64_t i_pos ) 
    348441{ 
    349     if( i_pos < 0 ) 
    350     { 
    351         return VLC_EGENERIC; 
    352     } 
    353     msg_Dbg( p_access, "seeking to "I64Fd, i_pos ); 
    354  
    355     ftp_StopStream( p_access ); 
    356     if( ftp_StartStream( p_access, i_pos ) < 0 ) 
    357     { 
    358         p_access->info.b_eof = VLC_TRUE; 
    359         return VLC_EGENERIC; 
    360     } 
     442    int val = _Seek( (vlc_object_t *)p_access, p_access->p_sys, i_pos ); 
     443    if( val ) 
     444        return val; 
    361445 
    362446    p_access->info.b_eof = VLC_FALSE; 
     
    366450} 
    367451 
     452static int OutSeek( sout_access_out_t *p_access, off_t i_pos ) 
     453{ 
     454    return _Seek( (vlc_object_t *)p_access, GET_OUT_SYS( p_access ), i_pos); 
     455} 
     456 
    368457/***************************************************************************** 
    369458 * Read: 
     
    373462    access_sys_t *p_sys = p_access->p_sys; 
    374463    int i_read; 
     464 
     465    assert( p_sys->fd_data != -1 ); 
     466    assert( p_access->i_object_type == VLC_OBJECT_ACCESS ); 
    375467 
    376468    if( p_access->info.b_eof ) 
     
    388480 
    389481/***************************************************************************** 
     482 * Write: 
     483 *****************************************************************************/ 
     484static int Write( sout_access_out_t *p_access, block_t *p_buffer ) 
     485{ 
     486    access_sys_t *p_sys = GET_OUT_SYS(p_access); 
     487    size_t i_write = 0; 
     488 
     489    assert( p_sys->fd_data != -1 ); 
     490 
     491    while( p_buffer != NULL ) 
     492    { 
     493        block_t *p_next = p_buffer->p_next;; 
     494 
     495        i_write += net_Write( p_access, p_sys->fd_data, NULL, 
     496                              p_buffer->p_buffer, p_buffer->i_buffer ); 
     497        block_Release( p_buffer ); 
     498 
     499        p_buffer = p_next; 
     500    } 
     501 
     502    return i_write; 
     503} 
     504 
     505/***************************************************************************** 
    390506 * Control: 
    391507 *****************************************************************************/ 
     
    451567 * ftp_*: 
    452568 *****************************************************************************/ 
    453 static int ftp_SendCommand( access_t *p_access, char *psz_fmt, ... ) 
    454 
    455     access_sys_t *p_sys = p_access->p_sys; 
     569static int ftp_SendCommand( vlc_object_t *p_access, access_sys_t *p_sys, 
     570                            const char *psz_fmt, ... ) 
     571
    456572    va_list      args; 
    457573    char         *psz_cmd; 
     
    486602 These strings are not part of the requests, except in the case \377\377, 
    487603 where the request contains one \377. */ 
    488 static int ftp_ReadCommand( access_t *p_access, 
     604static int ftp_ReadCommand( vlc_object_t *p_access, access_sys_t *p_sys, 
    489605                            int *pi_answer, char **ppsz_answer ) 
    490606{ 
    491     access_sys_t *p_sys = p_access->p_sys; 
    492607    char         *psz_line; 
    493608    int          i_answer; 
     
    541656} 
    542657 
    543 static int ftp_StartStream( access_t *p_access, off_t i_start ) 
    544 
    545     access_sys_t *p_sys = p_access->p_sys; 
    546  
    547     char psz_ipv4[16], *psz_ip; 
     658static int ftp_StartStream( vlc_object_t *p_access, access_sys_t *p_sys, 
     659                            off_t i_start ) 
     660
     661    char psz_ipv4[16], *psz_ip = p_sys->sz_epsv_ip; 
    548662    int  i_answer; 
    549663    char *psz_arg, *psz_parser; 
    550664    int  i_port; 
    551665 
    552     psz_ip = p_sys->sz_epsv_ip
    553  
    554     if( ( ftp_SendCommand( p_access, *psz_ip ? "EPSV" : "PASV" ) < 0 ) 
    555      || ( ftp_ReadCommand( p_access, &i_answer, &psz_arg ) != 2 ) ) 
     666    assert( p_sys->fd_data == -1 )
     667 
     668    if( ( ftp_SendCommand( p_access, p_sys, *psz_ip ? "EPSV" : "PASV" ) < 0 ) 
     669     || ( ftp_ReadCommand( p_access, p_sys, &i_answer, &psz_arg ) != 2 ) ) 
    556670    { 
    557671        msg_Err( p_access, "cannot set passive mode" ); 
     
    600714    msg_Dbg( p_access, "ip:%s port:%d", psz_ip, i_port ); 
    601715 
    602     if( ftp_SendCommand( p_access, "TYPE I" ) < 0 || 
    603         ftp_ReadCommand( p_access, &i_answer, NULL ) != 2 ) 
     716    if( ftp_SendCommand( p_access, p_sys, "TYPE I" ) < 0 || 
     717        ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) != 2 ) 
    604718    { 
    605719        msg_Err( p_access, "cannot set binary transfer mode" ); 
     
    609723    if( i_start > 0 ) 
    610724    { 
    611         if( ftp_SendCommand( p_access, "REST "I64Fu, i_start ) < 0 || 
    612             ftp_ReadCommand( p_access, &i_answer, NULL ) > 3 ) 
     725        if( ftp_SendCommand( p_access, p_sys, "REST "I64Fu, i_start ) < 0 || 
     726            ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) > 3 ) 
    613727        { 
    614             msg_Err( p_access, "cannot set restart point" ); 
     728            msg_Err( p_access, "cannot set restart offset" ); 
    615729            return VLC_EGENERIC; 
    616730        } 
     
    628742 
    629743    /* "1xx" message */ 
    630     if( ftp_SendCommand( p_access, "RETR %s", p_sys->url.psz_path ) < 0 || 
    631         ftp_ReadCommand( p_access, &i_answer, NULL ) > 2 ) 
     744    if( ftp_SendCommand( p_access, p_sys, "%s %s", 
     745                         (p_access->i_object_type == VLC_OBJECT_ACCESS) 
     746                                 ? "RETR" : "STOR", 
     747                         p_sys->url.psz_path ) < 0 || 
     748        ftp_ReadCommand( p_access, p_sys, &i_answer, NULL ) > 2 ) 
    632749    { 
    633750        msg_Err( p_access, "cannot retreive file" ); 
     
    637754} 
    638755 
    639 static int ftp_StopStream ( access_t *p_access ) 
    640 
    641     access_sys_t *p_sys = p_access->p_sys; 
    642  
    643     int i_answer; 
    644  
    645     if( ftp_SendCommand( p_access, "ABOR" ) < 0 ) 
     756static int ftp_StopStream ( vlc_object_t *p_access, access_sys_t *p_sys ) 
     757
     758    if( ftp_SendCommand( p_access, p_sys, "ABOR" ) < 0 ) 
    646759    { 
    647760        msg_Warn( p_access, "cannot abort file" ); 
     
    651764        return VLC_EGENERIC; 
    652765    } 
    653     if(  p_sys->fd_data > 0 ) 
     766 
     767    if( p_sys->fd_data != -1 ) 
    654768    { 
    655769        net_Close( p_sys->fd_data ); 
    656770        p_sys->fd_data = -1; 
    657         ftp_ReadCommand( p_access, &i_answer, NULL ); 
    658     } 
    659     ftp_ReadCommand( p_access, &i_answer, NULL ); 
     771        ftp_ReadCommand( p_access, p_sys, NULL, NULL ); 
     772    } 
     773    ftp_ReadCommand( p_access, p_sys, NULL, NULL ); 
    660774 
    661775    return VLC_SUCCESS; 
    662776} 
    663