# HG changeset patch # User morphbr # Date 1168542455 0 # Node ID 1098f58ae8e142a72680dbf852352928b99a44fa # Parent c7050cb68338ae6b98a0cf386543d2c09c46bef7 [svn r267] Added gmyth_http to handle HTTP queries to port 6544 on the backend diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/Makefile.am --- a/gmyth/src/Makefile.am Thu Jan 11 19:05:37 2007 +0000 +++ b/gmyth/src/Makefile.am Thu Jan 11 19:07:35 2007 +0000 @@ -6,7 +6,7 @@ gmyth_marshal.c \ gmyth_marshal.h -libgmyth_la_SOURCES = \ +libgmyth_la_SOURCES = \ gmyth_common.c \ gmyth_debug.c \ gmyth_epg.c \ @@ -18,12 +18,13 @@ gmyth_query.c \ gmyth_socket.c \ gmyth_stringlist.c \ - gmyth_monitor_handler.c \ - gmyth_file_transfer.c \ + gmyth_monitor_handler.c \ + gmyth_file_transfer.c \ gmyth_livetv.c \ gmyth_backendinfo.c \ gmyth_programinfo.c \ - gmyth_uri.c \ + gmyth_uri.c \ + gmyth_http.c \ $(BUILT_SOURCES) @@ -69,7 +70,7 @@ $(pkgincludedir) libgmyth_include_HEADERS = \ - gmyth.h \ + gmyth.h \ gmyth_common.h \ gmyth_debug.h \ gmyth_epg.h \ @@ -81,11 +82,12 @@ gmyth_socket.h \ gmyth_remote_util.h \ gmyth_stringlist.h \ - gmyth_monitor_handler.h \ - gmyth_file_transfer.h \ + gmyth_monitor_handler.h \ + gmyth_file_transfer.h \ gmyth_livetv.h \ gmyth_backendinfo.h \ gmyth_programinfo.h \ - gmyth_uri.h + gmyth_uri.h \ + gmyth_http.h CLEANFILES = $(BUILT_SOURCES) diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth.h --- a/gmyth/src/gmyth.h Thu Jan 11 19:05:37 2007 +0000 +++ b/gmyth/src/gmyth.h Thu Jan 11 19:07:35 2007 +0000 @@ -46,5 +46,6 @@ #include #include #include +#include #endif /* _GMYTH_H_ */ diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth_file_transfer.c --- a/gmyth/src/gmyth_file_transfer.c Thu Jan 11 19:05:37 2007 +0000 +++ b/gmyth/src/gmyth_file_transfer.c Thu Jan 11 19:07:35 2007 +0000 @@ -282,7 +282,7 @@ transfer->control_sock = NULL; } - transfer->control_sock = gmyth_socket_new(); + transfer->control_sock = gmyth_socket_new(6543); // Connects the socket, send Mythtv ANN command and verify Mythtv protocol version if (!gmyth_socket_connect_to_backend (transfer->control_sock, @@ -299,7 +299,7 @@ transfer->sock = NULL; } - transfer->sock = gmyth_socket_new (); + transfer->sock = gmyth_socket_new (6543); gmyth_socket_connect (transfer->sock, transfer->backend_info->hostname, transfer->backend_info->port); strlist = gmyth_string_list_new(); diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth_http.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_http.c Thu Jan 11 19:07:35 2007 +0000 @@ -0,0 +1,270 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_http.c + * + * @brief

GMythHttp class provides a wrapper to access + * data from the database using http+xml + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza <@indt.org.br> + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "gmyth_http.h" +#include "gmyth_debug.h" +#include "gmyth_socket.h" + +static void gmyth_http_class_init (GMythHttpClass *klass); +static void gmyth_http_init (GMythHttp *object); + +static void gmyth_http_dispose (GObject *object); +static void gmyth_http_finalize (GObject *object); + +G_DEFINE_TYPE(GMythHttp, gmyth_http, G_TYPE_OBJECT) + + +static void gmyth_http_class_init (GMythHttpClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + gobject_class->dispose = gmyth_http_dispose; + gobject_class->finalize = gmyth_http_finalize; +} + +static void gmyth_http_init (GMythHttp *gmyth_http) +{ + gmyth_http->backend_info = NULL; + gmyth_http->socket = gmyth_socket_new (MYTH_PORT_STATUS); + +} + +static void gmyth_http_dispose (GObject *object) +{ + GMythHttp *gmyth_http = GMYTH_HTTP (object); + + if (gmyth_http->backend_info) + g_object_unref (gmyth_http->backend_info); + + if (gmyth_http->socket) + g_object_unref (gmyth_http->socket); + + G_OBJECT_CLASS (gmyth_http_parent_class)->dispose (object); +} + +static void gmyth_http_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + G_OBJECT_CLASS (gmyth_http_parent_class)->finalize (object); +} + +/** Creates a new instance of GMythHttp. + * + * @return a new instance of GMythHttp. + */ +GMythHttp* gmyth_http_new () +{ + GMythHttp *http = GMYTH_HTTP (g_object_new(GMYTH_HTTP_TYPE, NULL)); + return http; +} + +/** Creates the Header of the packet. + * + * @param command The string of the command to be sent + * @return String with the header appended to the command + */ +GString * gmyth_http_create_header (GString *command) +{ + + /* secure len to avoid buffer overflows */ + /* len must be big enough to support the command */ + gsize len = command->len + 2048; + gchar *new_command = g_new0 (gchar, command->len + 2048); + + g_snprintf(new_command, len, + "GET /%s HTTP/1.1\r\n" + "Host: 127.0.0.1:6544\r\n" + "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.8) " + "Gecko/20061025 Firefox/1.5.0.8\r\n" + "Accept: text/xml,application/xml,application/xhtml+xml,text/html;" + "q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n" + "Accept-Language: en-us,en;q=0.5\r\n" + "Accept-Encoding: gzip,deflate\r\n" + "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" + "Keep-Alive: 300\r\n" + "Connection: keep-alive\r\n" + "\r\n" + , command->str); + + GString *new = g_string_new(new_command); + return new; + +} + +/** Removes the Header of the packet. + * + * @param packet The string of the packet + * @return String without the header + */ +GString * gmyth_http_remove_header (GString *packet) +{ +} + +/** Sends a command to the backend. + * + * @param gmyth_socket the GMythSocket instance. + * @param command The string command to be sent. + * @return gboolean If everything went ok + */ +gboolean gmyth_http_send_command(GMythSocket *gmyth_socket, GString *command) +{ + gboolean ret = TRUE; + + GIOStatus io_status = G_IO_STATUS_NORMAL; + GError* error = NULL; + + gsize bytes_written = 0; + + if( command == NULL || ( command->len <= 0 ) || command->str == NULL ) + { + g_warning ("[%s] Invalid NULL command parameter!\n", __FUNCTION__); + return FALSE; + } + + gmyth_debug ("[%s] Sending command to Myth_HTTP_Server: %s\n", \ + __FUNCTION__, command->str); + + /* write bytes to socket */ + io_status = g_io_channel_write_chars( gmyth_socket->sd_io_ch, \ + command->str, command->len, &bytes_written, &error ); + + /* try to catch errors */ + if( (io_status == G_IO_STATUS_ERROR) || ( bytes_written <= 0 ) ) + { + g_warning ("[%s] Error while writing to socket", __FUNCTION__); + ret = FALSE; + } else if ( bytes_written < command->len ) + { + g_warning ("[%s] Not all data was written socket", __FUNCTION__); + ret = FALSE; + } + + io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error ); + + /* not all bytes were sent */ + if ( ( bytes_written != command->len ) || ( io_status == G_IO_STATUS_ERROR ) ) + { + g_warning ("[%s] Problems when sending data to the socket\n", __FUNCTION__); + ret = TRUE; + } + + if ( error != NULL ) + { + g_printerr( "Error found reading data from IO channel"); + ret = FALSE; + g_error_free( error ); + } + + return ret; +} + + +/** Receives an http answer after a gmyth_socket_send_command (). + * + * @param gmyth_socket The GMythSocket instance. + * @return The response received, or NULL if error or nothing was received. + */ +GString* gmyth_http_receive_response(GMythSocket *gmyth_socket) +{ + GIOStatus io_status = G_IO_STATUS_NORMAL; + GError* error = NULL; + GString *str = NULL; + gchar *buff = NULL; + GIOCondition io_cond; + + gsize bytes_read = -1; + + /* if gmyth_socket == NULL, return NULL */ + if ( gmyth_socket != NULL ) + { + + /* verify if there is data to read */ + io_cond = g_io_channel_get_buffer_condition (gmyth_socket->sd_io_ch); + + if ( io_cond == G_IO_OUT ) + { + /* read all data in the buffer */ + g_io_channel_read_to_end( gmyth_socket->sd_io_ch, &buff, &bytes_read, &error); + str = g_string_new(buff); + gmyth_debug ( "[%s] Bytes read = %d\n", __FUNCTION__, bytes_read ); + } + + if ( ( bytes_read < 0 ) || ( io_status == G_IO_STATUS_ERROR ) || ( error != NULL )) + { + g_free (buff); + g_free (str); + g_error_free (error); + g_printerr( "[%s] Error found receiving response from the IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message ); + return NULL; + } + + } + + /* everything went allright */ + return str; +} + +/** Send HTTP Command + * + * @return true or false + */ +GString* gmyth_http_request (GMythHttp *gmyth_http, GString *command) +{ + gmyth_socket_connect (gmyth_http->socket, gmyth_http->backend_info->hostname, 6544); + + GString *result = NULL; + gchar *buffer = NULL; + + buffer = g_strnfill( BUFLEN, ' '); + + /* creates header */ + GString *new_command = gmyth_http_create_header(command); + + /* sends the command throught the socket */ + gmyth_http_send_command (gmyth_http->socket, new_command); + + result = gmyth_http_receive_response (gmyth_http->socket); + + //if (result != NULL) + // gmyth_debug ("[%s] Response received from Myth_HTTP_Server: %s", __FUNCTION__, result->str); + + gmyth_socket_close_connection (gmyth_http->socket); + g_string_free (command, TRUE); + + return result; +} diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth_http.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_http.h Thu Jan 11 19:07:35 2007 +0000 @@ -0,0 +1,80 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_http.c + * + * @brief

GMythHttp class provides a wrapper to access + * data from the database using http+xml + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza <@indt.org.br> + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_HTTP_H__ +#define __GMYTH_HTTP_H__ + +#include + +#include "gmyth_socket.h" +#include "gmyth_backendinfo.h" + +#define BUFLEN 1024 + +G_BEGIN_DECLS + +#define GMYTH_HTTP_TYPE (gmyth_http_get_type ()) +#define GMYTH_HTTP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_HTTP_TYPE, GMythHttp)) +#define GMYTH_HTTP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_HTTP_TYPE, GMythHttpClass)) +#define IS_GMYTH_HTTP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_HTTP_TYPE)) +#define IS_GMYTH_HTTP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_HTTP_TYPE)) +#define GMYTH_HTTP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_HTTP_TYPE, GMythHttpClass)) + +#define MYTH_PORT_STATUS 6544 + +typedef struct _GMythHttp GMythHttp; +typedef struct _GMythHttpClass GMythHttpClass; + +struct _GMythHttpClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythHttp +{ + GObject parent; + + GMythBackendInfo *backend_info; + GMythSocket *socket; + + GString *opt_socket_name; /* socket name (use built-in value) */ + unsigned int opt_flags; /* connection flags (none) */ +}; + + +GType gmyth_http_get_type (void); + +GMythHttp* gmyth_http_new (); +GString* gmyth_http_request (GMythHttp *gmyth_http, GString *command); + +G_END_DECLS + +#endif /* __GMYTH_HTTP_H__ */ diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth_livetv.c --- a/gmyth/src/gmyth_livetv.c Thu Jan 11 19:05:37 2007 +0000 +++ b/gmyth/src/gmyth_livetv.c Thu Jan 11 19:07:35 2007 +0000 @@ -235,7 +235,7 @@ { gboolean res = TRUE; - GMythSocket *socket = gmyth_socket_new (); + GMythSocket *socket = gmyth_socket_new (6543); livetv->backend_info = backend_info; diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth_monitor_handler.c --- a/gmyth/src/gmyth_monitor_handler.c Thu Jan 11 19:05:37 2007 +0000 +++ b/gmyth/src/gmyth_monitor_handler.c Thu Jan 11 19:07:35 2007 +0000 @@ -475,7 +475,7 @@ { gboolean ret = TRUE; - monitor->event_sock = gmyth_socket_new(); + monitor->event_sock = gmyth_socket_new(6543); /* Connects the socket, send Mythtv ANN Monitor and verify Mythtv protocol version */ if (!gmyth_socket_connect_to_backend_events ( monitor->event_sock, diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth_recorder.c --- a/gmyth/src/gmyth_recorder.c Thu Jan 11 19:05:37 2007 +0000 +++ b/gmyth/src/gmyth_recorder.c Thu Jan 11 19:07:35 2007 +0000 @@ -118,7 +118,7 @@ if (recorder->myth_socket == NULL) { - recorder->myth_socket = gmyth_socket_new (); + recorder->myth_socket = gmyth_socket_new (6543); if (!gmyth_socket_connect_to_backend ( recorder->myth_socket, recorder->hostname->str, recorder->port, TRUE ) ) { diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth_scheduler.c --- a/gmyth/src/gmyth_scheduler.c Thu Jan 11 19:05:37 2007 +0000 +++ b/gmyth/src/gmyth_scheduler.c Thu Jan 11 19:07:35 2007 +0000 @@ -624,7 +624,7 @@ g_string_append_printf (datastr, "%d", record_id); gmyth_string_list_append_string (strlist, datastr); - socket = gmyth_socket_new (); + socket = gmyth_socket_new (6543); if (gmyth_socket_connect (socket, scheduler->backend_info->hostname, scheduler->backend_info->port)) { gmyth_socket_sendreceive_stringlist (socket, strlist); diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth_socket.c --- a/gmyth/src/gmyth_socket.c Thu Jan 11 19:05:37 2007 +0000 +++ b/gmyth/src/gmyth_socket.c Thu Jan 11 19:07:35 2007 +0000 @@ -408,11 +408,11 @@ * @return a new instance of GMythSocket. */ GMythSocket* -gmyth_socket_new () +gmyth_socket_new (int port) { GMythSocket *gmyth_socket = GMYTH_SOCKET (g_object_new(GMYTH_SOCKET_TYPE, NULL)); - gmyth_socket->port = 6543; + gmyth_socket->port = port; gmyth_socket->mythtv_version = MYTHTV_VERSION_DEFAULT; @@ -967,7 +967,7 @@ gsize bytes_read = 0; gint len = 0; - GIOCondition io_cond; + GIOCondition io_cond = g_io_channel_get_buffer_condition (gmyth_socket->sd_io_ch); g_return_val_if_fail( gmyth_socket != NULL, NULL ); diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth_socket.h --- a/gmyth/src/gmyth_socket.h Thu Jan 11 19:05:37 2007 +0000 +++ b/gmyth/src/gmyth_socket.h Thu Jan 11 19:07:35 2007 +0000 @@ -69,7 +69,7 @@ GObject parent; /* socket descriptor */ - gint sd; + gint sd; GIOChannel *sd_io_ch; gchar *hostname; @@ -82,7 +82,10 @@ GType gmyth_socket_get_type (void); -GMythSocket * gmyth_socket_new ( ); +GMythSocket * gmyth_socket_new (gint port); + +gboolean gmyth_socket_connect (GMythSocket *gmyth_socket, const gchar *hostname, gint port); + GIOChannel * gmyth_socket_get_io_channel (GMythSocket *gmyth_socket ); @@ -92,7 +95,7 @@ gboolean gmyth_socket_send_command (GMythSocket *gmyth_socket, GString *command); GString * gmyth_socket_receive_response (GMythSocket *gmyth_socket); -gint gmyth_socket_sendreceive_stringlist (GMythSocket *gmyth_socket, +gint gmyth_socket_sendreceive_stringlist (GMythSocket *gmyth_socket, GMythStringList *str_list); gboolean gmyth_socket_connect (GMythSocket *gmyth_socket, diff -r c7050cb68338 -r 1098f58ae8e1 gmyth/src/gmyth_util.c --- a/gmyth/src/gmyth_util.c Thu Jan 11 19:05:37 2007 +0000 +++ b/gmyth/src/gmyth_util.c Thu Jan 11 19:07:35 2007 +0000 @@ -420,7 +420,7 @@ GMythSocket *socket; gboolean res; - socket = gmyth_socket_new (); + socket = gmyth_socket_new (6543); res = gmyth_socket_connect_to_backend (socket, backend_info->hostname, backend_info->port, TRUE);