gmyth-stream/libgnomevfs2/modules/gmythstream-method.c
author renatofilho
Mon Aug 13 23:03:08 2007 +0100 (2007-08-13)
branchtrunk
changeset 802 d0e8c542c38e
parent 556 7dfd742a02eb
permissions -rw-r--r--
[svn r808] fixed some security bugs
     1 /*
     2  * @author Artur Duque de Souza <souza.artur@indt.org.br>
     3  *
     4  * This program is free software; you can redistribute it and/or modify
     5  * it under the terms of the GNU Lesser General Public License as published by
     6  * the Free Software Foundation; either version 2 of the License, or
     7  * (at your option) any later version.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  m * You should have received a copy of the GNU Lesser General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  */
    18 
    19 #ifdef HAVE_CONFIG_H
    20 #include <config.h>
    21 #endif
    22 
    23 #include <sys/socket.h>         /* for socket(), connect(), send(), and
    24                                  * recv() */
    25 #include <arpa/inet.h>          /* for sockaddr_in and inet_addr() */
    26 #include <stdlib.h>             /* for atoi() and exit() */
    27 #include <string.h>             /* for memset() */
    28 #include <unistd.h>             /* for close() */
    29 #include <errno.h>
    30 
    31 #include <glib.h>
    32 #include <glib/gprintf.h>
    33 #include <glib/gstdio.h>
    34 #include <gmyth-stream-client.h>
    35 
    36 #include <libgnomevfs/gnome-vfs-module.h>
    37 #include <libgnomevfs/gnome-vfs-utils.h>
    38 
    39 #define BUFFER_SIZE 4096
    40 
    41 typedef struct {
    42     gint            port;
    43     gchar          *hostname;
    44 
    45     GMythStreamClient *stream;
    46     gint            fd;
    47 } gmsHandle;
    48 
    49 typedef struct {
    50     gchar          *file_name;
    51     gchar          *mux;
    52     gchar          *vcodec;
    53     guint           vbitrate;
    54     gdouble         fps;
    55     gchar          *acodec;
    56     guint           abitrate;
    57     guint           width;
    58     guint           height;
    59     guint           port;
    60     gchar          *opt;
    61 } UriArgs;
    62 
    63 
    64 static gmsHandle *gmsHandle_new(GnomeVFSURI * uri);
    65 
    66 static          GnomeVFSResult
    67 do_open(GnomeVFSMethod * method,
    68         GnomeVFSMethodHandle ** method_handle,
    69         GnomeVFSURI * uri,
    70         GnomeVFSOpenMode mode, GnomeVFSContext * context);
    71 
    72 static          GnomeVFSResult
    73 do_read(GnomeVFSMethod * method,
    74         GnomeVFSMethodHandle * method_handle,
    75         gpointer buffer,
    76         GnomeVFSFileSize bytes,
    77         GnomeVFSFileSize * bytes_read, GnomeVFSContext * context);
    78 
    79 static          GnomeVFSResult
    80 do_close(GnomeVFSMethod * method,
    81          GnomeVFSMethodHandle * method_handle, GnomeVFSContext * context);
    82 
    83 static          GnomeVFSResult
    84 do_get_file_info(GnomeVFSMethod * method,
    85                  GnomeVFSURI * uri,
    86                  GnomeVFSFileInfo * file_info,
    87                  GnomeVFSFileInfoOptions options,
    88                  GnomeVFSContext * context);
    89 
    90 
    91 static          GnomeVFSResult
    92 do_get_file_info_from_handle(GnomeVFSMethod * method,
    93                              GnomeVFSMethodHandle * method_handle,
    94                              GnomeVFSFileInfo * file_info,
    95                              GnomeVFSFileInfoOptions options,
    96                              GnomeVFSContext * context);
    97 
    98 
    99 static          gboolean
   100 do_is_local(GnomeVFSMethod * method, const GnomeVFSURI * uri);
   101 
   102 
   103 static gmsHandle *
   104 gmsHandle_new(GnomeVFSURI * uri)
   105 {
   106     gmsHandle      *handler = (gmsHandle *) g_malloc0(sizeof(gmsHandle));
   107 
   108     handler->hostname = (gchar *) gnome_vfs_uri_get_host_name(uri);
   109     handler->port = gnome_vfs_uri_get_host_port(uri);
   110     handler->stream = gmyth_stream_client_new();
   111 
   112     return handler;
   113 }
   114 
   115 static GnomeVFSMethod method = {
   116     sizeof(GnomeVFSMethod),
   117     do_open,                    /* open */
   118     NULL,                       /* create */
   119     do_close,                   /* close */
   120     do_read,                    /* read */
   121     NULL,                       /* write */
   122     NULL,                       /* seek */
   123     NULL,                       /* tell */
   124     NULL,                       /* truncate_handle */
   125     NULL,                       /* open_directory */
   126     NULL,                       /* close_directory */
   127     NULL,                       /* read_directory */
   128     do_get_file_info,           /* get_file_info */
   129     do_get_file_info_from_handle,   /* get_file_info_from_handle */
   130     do_is_local,                /* is_local */
   131     NULL,                       /* make_directory */
   132     NULL,                       /* remove_directory */
   133     NULL,                       /* move */
   134     NULL,                       /* unlink */
   135     NULL,                       /* check_same_fs */
   136     NULL,                       /* set_file_info */
   137     NULL,                       /* truncate */
   138     NULL,                       /* find_directory */
   139     NULL,                       /* create_symbolic_link */
   140     NULL,                       /* monitor_add */
   141     NULL,                       /* monitor_cancel */
   142     NULL                        /* file_control */
   143 };
   144 
   145 GnomeVFSMethod *
   146 vfs_module_init(const char *method_name, const char *args)
   147 {
   148     return &method;
   149 }
   150 
   151 void
   152 vfs_module_shutdown(GnomeVFSMethod * method)
   153 {
   154     return;
   155 }
   156 
   157 char           *
   158 _parse_opt(char *opt)
   159 {
   160     char          **list = g_strsplit(opt, "opt=", 2);
   161     char          **opts = g_strsplit(list[1], "+", 32);
   162     char           *value = "";
   163     char           *aux;
   164     gint            i = 0;
   165 
   166     for (aux = opts[0]; aux != NULL; aux = opts[++i])
   167         value = g_strdup_printf("%s %s", value, aux);
   168 
   169     g_free(aux);
   170     g_strfreev(list);
   171     g_strfreev(opts);
   172     return value;
   173 }
   174 
   175 static UriArgs *
   176 _uri_parse_args(const GnomeVFSURI * uri)
   177 {
   178     gchar          *file = gnome_vfs_unescape_string(uri->text, NULL);
   179 
   180     gchar         **list = g_strsplit(file, "\'", 3);
   181     gchar         **prefix = g_strsplit_set(list[0], "/=", 3);
   182     gchar         **lst = g_strsplit(list[2], "?", 0);
   183 
   184     UriArgs        *info = g_new0(UriArgs, 1);
   185     gint            i = 1;
   186 
   187     gchar         **prop = NULL;
   188     prop = g_strsplit_set(lst[0], "/=", 3);
   189 
   190     info->file_name = g_strdup_printf("%s://%s", prefix[1], list[1]);
   191 
   192     // g_debug("FILENAME: [%s]", info->file_name);
   193 
   194     g_strfreev(prop);
   195 
   196     gchar          *walk;
   197     for (walk = lst[1]; walk != NULL; walk = lst[++i]) {
   198         prop = g_strsplit(walk, "=", 2);
   199 
   200         if (g_strv_length(prop) == 2) {
   201             if (strcmp(prop[0], "mux") == 0) {
   202                 info->mux = g_strdup(prop[1]);
   203             } else if (strcmp(prop[0], "vcodec") == 0) {
   204                 info->vcodec = g_strdup(prop[1]);
   205             } else if (strcmp(prop[0], "vbitrate") == 0) {
   206                 info->vbitrate = atoi(prop[1]);
   207             } else if (strcmp(prop[0], "fps") == 0) {
   208                 info->fps = g_strtod(prop[1], NULL);
   209             } else if (strcmp(prop[0], "acodec") == 0) {
   210                 info->acodec = g_strdup(prop[1]);
   211             } else if (strcmp(prop[0], "abitrate") == 0) {
   212                 info->abitrate = atoi(prop[1]);
   213             } else if (strcmp(prop[0], "width") == 0) {
   214                 info->width = atoi(prop[1]);
   215             } else if (strcmp(prop[0], "height") == 0) {
   216                 info->height = atoi(prop[1]);
   217             } else if (strcmp(prop[0], "opt") == 0) {
   218                 info->opt = g_strdup(_parse_opt(walk));
   219             }
   220         }
   221         g_strfreev(prop);
   222     }
   223 
   224     g_free(file);
   225     g_strfreev(list);
   226     g_strfreev(prefix);
   227     g_strfreev(lst);
   228     return info;
   229 }
   230 
   231 static          GnomeVFSResult
   232 do_open(GnomeVFSMethod * method,
   233         GnomeVFSMethodHandle ** method_handle,
   234         GnomeVFSURI * uri,
   235         GnomeVFSOpenMode mode, GnomeVFSContext * context)
   236 {
   237     gmsHandle      *handle = gmsHandle_new(uri);
   238     UriArgs        *args;
   239 
   240     if (!gmyth_stream_client_connect(handle->stream,
   241                                      gnome_vfs_uri_get_host_name(uri),
   242                                      gnome_vfs_uri_get_host_port(uri))) {
   243 
   244         return GNOME_VFS_ERROR_HOST_NOT_FOUND;
   245     }
   246 
   247     args = _uri_parse_args(uri);
   248 
   249     gint            ret = gmyth_stream_client_open_stream(handle->stream,
   250                                                           args->file_name,
   251                                                           args->mux,
   252                                                           args->vcodec,
   253                                                           args->vbitrate,
   254                                                           args->fps,
   255                                                           args->acodec,
   256                                                           args->abitrate,
   257                                                           args->width,
   258                                                           args->height,
   259                                                           args->opt);
   260 
   261     g_free(args);
   262 
   263     if (ret == -1) {
   264         gmyth_stream_client_disconnect(handle->stream);
   265         return GNOME_VFS_ERROR_HOST_NOT_FOUND;
   266     }
   267 
   268     handle->fd = gmyth_stream_client_play_stream(handle->stream);
   269 
   270     if (handle->fd == -1) {
   271         gmyth_stream_client_disconnect(handle->stream);
   272         return GNOME_VFS_ERROR_HOST_NOT_FOUND;
   273     }
   274 
   275     *method_handle = (GnomeVFSMethodHandle *) handle;
   276     return GNOME_VFS_OK;
   277 }
   278 
   279 static          GnomeVFSResult
   280 do_read(GnomeVFSMethod * method,
   281         GnomeVFSMethodHandle * method_handle,
   282         gpointer buffer,
   283         GnomeVFSFileSize bytes,
   284         GnomeVFSFileSize * bytes_read, GnomeVFSContext * context)
   285 {
   286 
   287     gint64          total_read = 0;
   288     gmsHandle      *handle = (gmsHandle *) method_handle;
   289 
   290     // g_debug("waiting something");
   291 
   292     total_read = recv(handle->fd, buffer, BUFFER_SIZE, 0);
   293     // g_debug("COULD READ: %d bytes", total_read);
   294     *bytes_read = (GnomeVFSFileSize) total_read;
   295 
   296     // if (total_read < 0) g_debug("ERROR!!!!!!!!!!!!!!!!");
   297 
   298     if (total_read < 0)
   299         return GNOME_VFS_ERROR_INTERNAL;
   300     else
   301         return GNOME_VFS_OK;
   302 
   303 }
   304 
   305 static          GnomeVFSResult
   306 do_close(GnomeVFSMethod * method,
   307          GnomeVFSMethodHandle * method_handle, GnomeVFSContext * context)
   308 {
   309     gmsHandle      *handle = (gmsHandle *) method_handle;
   310 
   311     g_debug("close close close");
   312 
   313     gmyth_stream_client_close_stream(handle->stream);
   314     gmyth_stream_client_disconnect(handle->stream);
   315 
   316     g_free(handle);
   317     return GNOME_VFS_OK;
   318 }
   319 
   320 
   321 static          GnomeVFSResult
   322 do_get_file_info(GnomeVFSMethod * method,
   323                  GnomeVFSURI * uri,
   324                  GnomeVFSFileInfo * file_info,
   325                  GnomeVFSFileInfoOptions options,
   326                  GnomeVFSContext * context)
   327 {
   328     file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
   329         GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
   330 
   331     file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
   332 
   333     file_info->permissions = GNOME_VFS_PERM_USER_READ |
   334         GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_GROUP_READ;
   335 
   336     return GNOME_VFS_OK;
   337 }
   338 
   339 
   340 static          GnomeVFSResult
   341 do_get_file_info_from_handle(GnomeVFSMethod * method,
   342                              GnomeVFSMethodHandle * method_handle,
   343                              GnomeVFSFileInfo * file_info,
   344                              GnomeVFSFileInfoOptions options,
   345                              GnomeVFSContext * context)
   346 {
   347     file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
   348         GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
   349 
   350     file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
   351 
   352     file_info->permissions = GNOME_VFS_PERM_USER_READ |
   353         GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_GROUP_READ;
   354 
   355     return GNOME_VFS_OK;
   356 }
   357 
   358 
   359 static          gboolean
   360 do_is_local(GnomeVFSMethod * method, const GnomeVFSURI * uri)
   361 {
   362     return FALSE;
   363 }