[svn r269] Changed structure from gmyth_http to use *libcurl*. trunk
authormorphbr
Fri Jan 12 21:26:30 2007 +0000 (2007-01-12)
branchtrunk
changeset 26891eb7e03b1b1
parent 267 55e1c59ed983
child 269 6c34a8d85a9b
[svn r269] Changed structure from gmyth_http to use *libcurl*.
gmyth/configure.ac
gmyth/src/gmyth_http.c
gmyth/src/gmyth_http.h
gmyth/tests/http.c
maemo-ui/src/mmyth_epg_grid_widget.c
maemo-ui/src/mmyth_ui.c
maemo-ui/src/mmyth_uisettings.c
     1.1 --- a/gmyth/configure.ac	Fri Jan 12 11:58:01 2007 +0000
     1.2 +++ b/gmyth/configure.ac	Fri Jan 12 21:26:30 2007 +0000
     1.3 @@ -142,6 +142,18 @@
     1.4  AC_SUBST(LIBXML_CFLAGS)
     1.5  AC_SUBST(LIBXML_LIBS)
     1.6  
     1.7 +# Check for libcurl
     1.8 +PKG_CHECK_MODULES(LIBCURL, libcurl, HAVE_LIBCRUL=yes, HAVE_LIBCURL=no)
     1.9 +
    1.10 +# Give error and exit if we don't have libcurl
    1.11 +if test "x$HAVE_LIBCURL" = "xno"; then
    1.12 +  AC_MSG_ERROR(you need libcurl installed)
    1.13 +fi
    1.14 +
    1.15 +# make LIBCURL_CFLAGS and LIBCURL_LIBS available
    1.16 +AC_SUBST(LIBCURL_CFLAGS)
    1.17 +AC_SUBST(LIBCURL_LIBS)
    1.18 +
    1.19  
    1.20  # check for gstreamer development files
    1.21  GST_REQUIRED=0.10
     2.1 --- a/gmyth/src/gmyth_http.c	Fri Jan 12 11:58:01 2007 +0000
     2.2 +++ b/gmyth/src/gmyth_http.c	Fri Jan 12 21:26:30 2007 +0000
     2.3 @@ -39,232 +39,122 @@
     2.4  #include "gmyth_debug.h"
     2.5  #include "gmyth_socket.h"
     2.6  
     2.7 -static void gmyth_http_class_init (GMythHttpClass *klass);
     2.8 -static void gmyth_http_init (GMythHttp *object);
     2.9 +struct MemoryStruct 
    2.10 +{
    2.11 +  char *memory;
    2.12 +  size_t size;
    2.13 +};
    2.14  
    2.15 -static void gmyth_http_dispose (GObject *object);
    2.16 -static void gmyth_http_finalize (GObject *object);
    2.17 -
    2.18 -G_DEFINE_TYPE(GMythHttp, gmyth_http, G_TYPE_OBJECT)
    2.19 -
    2.20 -
    2.21 -static void gmyth_http_class_init (GMythHttpClass *klass)
    2.22 +/* Aux functions got from libcurl */
    2.23 +void *myrealloc(void *ptr, size_t size)
    2.24  {
    2.25 -    GObjectClass *gobject_class;
    2.26 -
    2.27 -    gobject_class = (GObjectClass *) klass;
    2.28 -    gobject_class->dispose  = gmyth_http_dispose;
    2.29 -    gobject_class->finalize = gmyth_http_finalize; 
    2.30 +    /* There might be a realloc() out there that doesn't like reallocing
    2.31 +        NULL pointers, so we take care of it here */
    2.32 +    if(ptr)
    2.33 +        return realloc(ptr, size);
    2.34 +    else
    2.35 +        return malloc(size);
    2.36  }
    2.37  
    2.38 -static void gmyth_http_init (GMythHttp *gmyth_http)
    2.39 +size_t
    2.40 +WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
    2.41  {
    2.42 -    gmyth_http->backend_info = NULL;
    2.43 -    gmyth_http->socket = gmyth_socket_new (MYTH_PORT_STATUS);
    2.44 -    
    2.45 +  size_t realsize = size * nmemb;
    2.46 +  struct MemoryStruct *mem = (struct MemoryStruct *)data;
    2.47 +
    2.48 +  mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1);
    2.49 +  if (mem->memory) {
    2.50 +    memcpy(&(mem->memory[mem->size]), ptr, realsize);
    2.51 +    mem->size += realsize;
    2.52 +    mem->memory[mem->size] = 0;
    2.53 +  }
    2.54 +  return realsize;
    2.55  }
    2.56  
    2.57 -static void gmyth_http_dispose (GObject *object)
    2.58 +/** Create a String containing the URL with the command
    2.59 + *
    2.60 + * @param command A string with the command
    2.61 + * @param variables Vars to use with their values \
    2.62 + *                    MUST FINISH WITH NULL!!!
    2.63 + * @return The response
    2.64 + */
    2.65 +GString* gmyth_http_create_command(GString *command, ...)
    2.66  {
    2.67 -    GMythHttp *gmyth_http = GMYTH_HTTP (object);
    2.68 -    
    2.69 -    if (gmyth_http->backend_info)
    2.70 -        g_object_unref (gmyth_http->backend_info);
    2.71 +    va_list args;
    2.72 +    va_start(args, command);
    2.73 +    char* s = NULL;
    2.74  
    2.75 -    if (gmyth_http->socket) 
    2.76 -        g_object_unref (gmyth_http->socket);
    2.77 -    
    2.78 -    G_OBJECT_CLASS (gmyth_http_parent_class)->dispose (object);
    2.79 +    g_string_append(command, "?");
    2.80 +
    2.81 +    while ( (s = va_arg(args, char *)) != NULL ) 
    2.82 +    {
    2.83 +        g_string_append(command, s);
    2.84 +        g_string_append(command, "=");
    2.85 +        s = va_arg(args, char *);
    2.86 +        g_string_append(command, s);
    2.87 +        g_string_append(command, "&");
    2.88 +    }
    2.89 +
    2.90 +
    2.91 +    /* TODO: erase this */
    2.92 +    printf("Comando: %s\n", command);
    2.93 +    free(s);
    2.94 +
    2.95 +    va_end(args);
    2.96 +
    2.97 +    return command;
    2.98  }
    2.99  
   2.100 -static void gmyth_http_finalize (GObject *object)
   2.101 -{
   2.102 -    g_signal_handlers_destroy (object);
   2.103 -    G_OBJECT_CLASS (gmyth_http_parent_class)->finalize (object);
   2.104 -}
   2.105 -
   2.106 -/** Creates a new instance of GMythHttp.
   2.107 - * 
   2.108 - * @return a new instance of GMythHttp.
   2.109 +/** Send HTTP Command and receives the result of it
   2.110 + *
   2.111 + * @return A string with the response from the server
   2.112   */
   2.113 -GMythHttp* gmyth_http_new ()
   2.114 -{
   2.115 -    GMythHttp *http = GMYTH_HTTP (g_object_new(GMYTH_HTTP_TYPE, NULL));
   2.116 -    return http;
   2.117 -}
   2.118 -
   2.119 -/** Creates the Header of the packet.
   2.120 - * 
   2.121 - * @param command The string of the command to be sent
   2.122 - * @return String with the header appended to the command
   2.123 - */
   2.124 -GString * gmyth_http_create_header (GString *command)
   2.125 +GString 
   2.126 +*gmyth_http_request (GMythBackendInfo *backend_info, GString *command)
   2.127  {
   2.128  
   2.129 -    /* secure len to avoid buffer overflows */
   2.130 -    /* len must be big enough to support the command */
   2.131 -    gsize len = command->len + 2048;
   2.132 -    gchar *new_command = g_new0 (gchar, command->len + 2048);
   2.133 - 
   2.134 -    g_snprintf(new_command, len, 
   2.135 -                "GET /%s HTTP/1.1\r\n"
   2.136 -                "Host: 127.0.0.1:6544\r\n"
   2.137 -                "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.8) "
   2.138 -                    "Gecko/20061025 Firefox/1.5.0.8\r\n"
   2.139 -                "Accept: text/xml,application/xml,application/xhtml+xml,text/html;"
   2.140 -                    "q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"
   2.141 -                "Accept-Language: en-us,en;q=0.5\r\n"
   2.142 -                "Accept-Encoding: gzip,deflate\r\n"
   2.143 -                "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
   2.144 -                "Keep-Alive: 300\r\n"
   2.145 -                "Connection: keep-alive\r\n"
   2.146 -                "\r\n"
   2.147 -                , command->str);
   2.148 +    size_t size = strlen(backend_info->hostname) + strlen(command->str) + 13;
   2.149 +    char *URL = malloc(sizeof(char)*size);
   2.150 +    snprintf(URL, size+1, "http://%s:6544/%s", backend_info->hostname, command->str);     
   2.151  
   2.152 -    GString *new = g_string_new(new_command);
   2.153 -    return new;
   2.154 +    CURL *curl_handle;
   2.155 +    
   2.156 +    struct MemoryStruct chunk;
   2.157 +    
   2.158 +    chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
   2.159 +    chunk.size = 0;    /* no data at this point */
   2.160 +    
   2.161 +    curl_global_init(CURL_GLOBAL_ALL);
   2.162 +    
   2.163 +    /* init the curl session */
   2.164 +    curl_handle = curl_easy_init();
   2.165 +    
   2.166 +    /* specify URL to get */
   2.167 +    curl_easy_setopt(curl_handle, CURLOPT_URL, URL);
   2.168 +    
   2.169 +    /* send all data to this function  */
   2.170 +    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
   2.171 +    
   2.172 +    /* we pass our 'chunk' struct to the callback function */
   2.173 +    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
   2.174 +    
   2.175 +    /* some servers don't like requests that are made without a user-agent
   2.176 +        field, so we provide one */
   2.177 +    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
   2.178 +    
   2.179 +    /* get it! */
   2.180 +    curl_easy_perform(curl_handle);
   2.181 +    
   2.182 +    /* cleanup curl stuff */
   2.183 +    curl_easy_cleanup(curl_handle);
   2.184 +    
   2.185 +    GString *response = NULL;
   2.186  
   2.187 -}
   2.188 -
   2.189 -/** Removes the Header of the packet.
   2.190 - * 
   2.191 - * @param packet The string of the packet
   2.192 - * @return String without the header
   2.193 - */
   2.194 -GString * gmyth_http_remove_header (GString *packet)
   2.195 -{
   2.196 -}
   2.197 -
   2.198 -/** Sends a command to the backend.
   2.199 - * 
   2.200 - * @param gmyth_socket the GMythSocket instance.
   2.201 - * @param command The string command to be sent.
   2.202 - * @return gboolean If everything went ok
   2.203 - */
   2.204 -gboolean gmyth_http_send_command(GMythSocket *gmyth_socket, GString *command) 
   2.205 -{
   2.206 -    gboolean ret = TRUE;
   2.207 -
   2.208 -    GIOStatus io_status = G_IO_STATUS_NORMAL;
   2.209 -    GError* error = NULL;  
   2.210 -    
   2.211 -    gsize bytes_written = 0;
   2.212 -
   2.213 -    if( command == NULL || ( command->len <= 0 ) || command->str == NULL ) 
   2.214 +    if(chunk.memory)
   2.215      {
   2.216 -        g_warning ("[%s] Invalid NULL command parameter!\n", __FUNCTION__);
   2.217 -        return FALSE;
   2.218 +        response = g_string_new(chunk.memory);
   2.219 +        free(chunk.memory);
   2.220      }
   2.221  
   2.222 -    gmyth_debug ("[%s] Sending command to Myth_HTTP_Server: %s\n", \
   2.223 -                __FUNCTION__, command->str);
   2.224 -
   2.225 -    /* write bytes to socket */    
   2.226 -    io_status = g_io_channel_write_chars( gmyth_socket->sd_io_ch, \
   2.227 -                command->str, command->len, &bytes_written, &error );
   2.228 -
   2.229 -    /* try to catch errors */
   2.230 -    if( (io_status == G_IO_STATUS_ERROR) || ( bytes_written <= 0 ) ) 
   2.231 -    {
   2.232 -        g_warning ("[%s] Error while writing to socket", __FUNCTION__);
   2.233 -        ret = FALSE;
   2.234 -    } else if ( bytes_written < command->len ) 
   2.235 -    {
   2.236 -        g_warning ("[%s] Not all data was written socket", __FUNCTION__);
   2.237 -        ret = FALSE;
   2.238 -    }
   2.239 -
   2.240 -    io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error );
   2.241 -
   2.242 -    /* not all bytes were sent */
   2.243 -    if ( ( bytes_written != command->len ) || ( io_status == G_IO_STATUS_ERROR ) )
   2.244 -    {
   2.245 -        g_warning ("[%s] Problems when sending data to the socket\n", __FUNCTION__);
   2.246 -        ret = TRUE;
   2.247 -    }
   2.248 -
   2.249 -    if ( error != NULL ) 
   2.250 -    {
   2.251 -        g_printerr( "Error found reading data from IO channel");
   2.252 -        ret = FALSE;
   2.253 -        g_error_free( error );
   2.254 -    }
   2.255 -
   2.256 -    return ret;
   2.257 +    return response;
   2.258  }
   2.259 -
   2.260 -
   2.261 -/** Receives an http answer after a gmyth_socket_send_command ().
   2.262 - * 
   2.263 - * @param gmyth_socket The GMythSocket instance.
   2.264 - * @return The response received, or NULL if error or nothing was received.
   2.265 - */
   2.266 -GString* gmyth_http_receive_response(GMythSocket *gmyth_socket)
   2.267 -{
   2.268 -    GIOStatus io_status = G_IO_STATUS_NORMAL;
   2.269 -    GError* error = NULL;
   2.270 -    GString *str = NULL;
   2.271 -    gchar *buff = NULL;
   2.272 -    GIOCondition io_cond; 
   2.273 -
   2.274 -    gsize bytes_read = -1;
   2.275 -
   2.276 -    /* if gmyth_socket == NULL, return NULL */
   2.277 -    if ( gmyth_socket != NULL )
   2.278 -    {
   2.279 -    
   2.280 -        /* verify if there is data to read */
   2.281 -        io_cond = g_io_channel_get_buffer_condition (gmyth_socket->sd_io_ch);
   2.282 -    
   2.283 -        if ( io_cond == G_IO_OUT ) 
   2.284 -        {
   2.285 -            /* read all data in the buffer */
   2.286 -            g_io_channel_read_to_end( gmyth_socket->sd_io_ch, &buff, &bytes_read, &error);
   2.287 -            str = g_string_new(buff);
   2.288 -            gmyth_debug ( "[%s] Bytes read = %d\n", __FUNCTION__, bytes_read );
   2.289 -        }
   2.290 -    
   2.291 -        if ( ( bytes_read < 0 ) || ( io_status == G_IO_STATUS_ERROR ) || ( error != NULL ))
   2.292 -        {
   2.293 -            g_free (buff);
   2.294 -            g_free (str);
   2.295 -            g_error_free (error);
   2.296 -            g_printerr( "[%s] Error found receiving response from the IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message );
   2.297 -            return NULL;
   2.298 -        }
   2.299 -
   2.300 -    }
   2.301 -
   2.302 -    /* everything went allright */
   2.303 -    return str;
   2.304 -}
   2.305 -
   2.306 -/** Send HTTP Command
   2.307 - *
   2.308 - * @return true or false
   2.309 - */
   2.310 -GString* gmyth_http_request (GMythHttp *gmyth_http, GString *command)
   2.311 -{
   2.312 -    gmyth_socket_connect (gmyth_http->socket, gmyth_http->backend_info->hostname, 6544);
   2.313 -
   2.314 -    GString *result = NULL;
   2.315 -    gchar *buffer = NULL;
   2.316 -
   2.317 -    buffer = g_strnfill( BUFLEN, ' ');
   2.318 -
   2.319 -    /* creates header */
   2.320 -    GString *new_command = gmyth_http_create_header(command);
   2.321 -
   2.322 -    /* sends the command throught the socket */
   2.323 -    gmyth_http_send_command (gmyth_http->socket, new_command);
   2.324 -
   2.325 -    result = gmyth_http_receive_response (gmyth_http->socket);
   2.326 -
   2.327 -    //if (result != NULL) 
   2.328 -    //    gmyth_debug ("[%s] Response received from Myth_HTTP_Server: %s", __FUNCTION__, result->str);
   2.329 -
   2.330 -    gmyth_socket_close_connection (gmyth_http->socket);
   2.331 -    g_string_free (command, TRUE);
   2.332 -
   2.333 -    return result;
   2.334 -}
     3.1 --- a/gmyth/src/gmyth_http.h	Fri Jan 12 11:58:01 2007 +0000
     3.2 +++ b/gmyth/src/gmyth_http.h	Fri Jan 12 21:26:30 2007 +0000
     3.3 @@ -31,49 +31,34 @@
     3.4  
     3.5  #include <glib-object.h>
     3.6  
     3.7 -#include "gmyth_socket.h"
     3.8 +#include <stdio.h>
     3.9 +#include <stdlib.h>
    3.10 +#include <string.h>
    3.11 +#include <stdarg.h>
    3.12 +
    3.13  #include "gmyth_backendinfo.h"
    3.14  
    3.15 -#define BUFLEN 1024
    3.16 +#include <curl/curl.h>
    3.17 +#include <curl/types.h>
    3.18 +#include <curl/easy.h>
    3.19  
    3.20  G_BEGIN_DECLS
    3.21  
    3.22 -#define GMYTH_HTTP_TYPE               (gmyth_http_get_type ())
    3.23 -#define GMYTH_HTTP(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_HTTP_TYPE, GMythHttp))
    3.24 -#define GMYTH_HTTP_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_HTTP_TYPE, GMythHttpClass))
    3.25 -#define IS_GMYTH_HTTP(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_HTTP_TYPE))
    3.26 -#define IS_GMYTH_HTTP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_HTTP_TYPE))
    3.27 -#define GMYTH_HTTP_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_HTTP_TYPE, GMythHttpClass))
    3.28 +#define MYTH_PORT_STATUS 6544
    3.29 +#define BUFLEN 2048
    3.30 +#define TYPE_TEXT_XML 0
    3.31 +#define TYPE_FORM_URLENCODED 1
    3.32  
    3.33 -#define MYTH_PORT_STATUS 6544
    3.34 +typedef struct _GMythPacket     GMythPacket;       
    3.35  
    3.36 -typedef struct _GMythHttp         GMythHttp;
    3.37 -typedef struct _GMythHttpClass    GMythHttpClass;
    3.38 -
    3.39 -struct _GMythHttpClass
    3.40 +struct _GMythPacket
    3.41  {
    3.42 -  GObjectClass parent_class;
    3.43 -
    3.44 -  /* callbacks */
    3.45 -  /* no one for now */
    3.46 +    GString *response;
    3.47 +    int    type;
    3.48  };
    3.49  
    3.50 -struct _GMythHttp
    3.51 -{
    3.52 -    GObject parent;
    3.53 -  
    3.54 -    GMythBackendInfo *backend_info;
    3.55 -    GMythSocket *socket;
    3.56 -
    3.57 -    GString *opt_socket_name; /* socket name (use built-in value) */
    3.58 -    unsigned int opt_flags; /* connection flags (none) */
    3.59 -};
    3.60 -
    3.61 -
    3.62 -GType gmyth_http_get_type (void);
    3.63 -
    3.64 -GMythHttp* gmyth_http_new ();
    3.65 -GString* gmyth_http_request (GMythHttp *gmyth_http, GString *command);
    3.66 +GString* gmyth_http_create_command(GString *command, ...);
    3.67 +GString *gmyth_http_request (GMythBackendInfo *backend_info, GString *command);
    3.68  
    3.69  G_END_DECLS
    3.70  
     4.1 --- a/gmyth/tests/http.c	Fri Jan 12 11:58:01 2007 +0000
     4.2 +++ b/gmyth/tests/http.c	Fri Jan 12 21:26:30 2007 +0000
     4.3 @@ -13,12 +13,10 @@
     4.4      gmyth_backend_info_set_hostname (backend_info, "localhost");
     4.5      gmyth_backend_info_set_port (backend_info, 6543);
     4.6      
     4.7 -    GMythHttp *gmyth_http = gmyth_http_new();
     4.8 -    gmyth_http->backend_info = backend_info;
     4.9 -
    4.10      GString *command = g_string_new(argv[1]);
    4.11  
    4.12 -    GString *result = gmyth_http_request(gmyth_http, command);
    4.13 +    GString *new_command = gmyth_http_create_command(command, "ChanId", "1001", "StartTime", "2006-12-20T00:05:00", NULL);
    4.14 +    GString *result = gmyth_http_request(backend_info, new_command);
    4.15  
    4.16      printf("%s", result->str);
    4.17  
     5.1 --- a/maemo-ui/src/mmyth_epg_grid_widget.c	Fri Jan 12 11:58:01 2007 +0000
     5.2 +++ b/maemo-ui/src/mmyth_epg_grid_widget.c	Fri Jan 12 21:26:30 2007 +0000
     5.3 @@ -109,7 +109,7 @@
     5.4      
     5.5      private->DISPLAY_CHANS = MAX_DISPLAY_CHANS;
     5.6  
     5.7 -    private->backend_info = gmyth_backend_info_new_full ( "192.168.1.109", "mythtv",
     5.8 +    private->backend_info = gmyth_backend_info_new_full ( "localhost", "mythtv",
     5.9      	"mythtv", "mythconverg", 6543 );
    5.10  
    5.11      // TODO: Close the epg and unref it in dispose call
     6.1 --- a/maemo-ui/src/mmyth_ui.c	Fri Jan 12 11:58:01 2007 +0000
     6.2 +++ b/maemo-ui/src/mmyth_ui.c	Fri Jan 12 21:26:30 2007 +0000
     6.3 @@ -56,7 +56,7 @@
     6.4  
     6.5      mmyth_ui = g_new0 (MMythUi, 1);
     6.6  
     6.7 -    mmyth_ui->backend_info = gmyth_backend_info_new_full( "192.168.1.109", "mythtv", "mythtv", "mythconverg", 6543 );
     6.8 +    mmyth_ui->backend_info = gmyth_backend_info_new_full( "localhost", "mythtv", "mythtv", "mythconverg", 6543 );
     6.9  
    6.10      mmyth_ui->main_window = main_window;    
    6.11      mmyth_ui->videow = NULL;
     7.1 --- a/maemo-ui/src/mmyth_uisettings.c	Fri Jan 12 11:58:01 2007 +0000
     7.2 +++ b/maemo-ui/src/mmyth_uisettings.c	Fri Jan 12 21:26:30 2007 +0000
     7.3 @@ -34,7 +34,7 @@
     7.4  	GtkWidget *label_hostname, *label_dbname;
     7.5  	GtkWidget *label_username, *label_passwd, *label_port;
     7.6  
     7.7 -	backend_info = gmyth_backend_info_new_full( "192.168.1.109", "mythtv", 
     7.8 +	backend_info = gmyth_backend_info_new_full( "localhost", "mythtv", 
     7.9  			"mythtv", "mythconverg", 6543 );
    7.10  	
    7.11  	settings_dialog = gtk_dialog_new_with_buttons ("Settings",