gmyth/src/gmyth_socket.c
author melunko
Fri Nov 24 21:43:04 2006 +0000 (2006-11-24)
branchtrunk
changeset 112 a99f881ed02f
parent 105 ba9bf90e7c4b
child 115 9f3c698e34a7
permissions -rw-r--r--
[svn r113] A lot of changes at gmyth_socket.c and gmyth_filetransfer. From now on, file transfer dont handle the monitor socket, and the QUERY_RECORDER messages - dont call spawn livetv, dont call get_file_position, is_recording, etc. These are gmyth_livetv responsibility. File transfer now has the _new, _open, _seek, and _close methods, just like gnomevfs does.
     1 /**
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_socket.c
     5  * 
     6  * @brief <p> MythTV socket implementation, according to the MythTV Project
     7  * (www.mythtv.org). 
     8  * 
     9  * This component provides basic socket functionalities to interact with
    10  * the Mythtv backend.
    11  * <p>
    12  *
    13  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
    14  * @author Rosfran Lins Borges <rosfran.borges@indt.org.br> 
    15  *
    16  *//*
    17  * 
    18  * This program is free software; you can redistribute it and/or modify
    19  * it under the terms of the GNU Lesser General Public License as published by
    20  * the Free Software Foundation; either version 2 of the License, or
    21  * (at your option) any later version.
    22  *
    23  * This program is distributed in the hope that it will be useful,
    24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    26  * GNU General Public License for more details.
    27  *
    28  * You should have received a copy of the GNU Lesser General Public License
    29  * along with this program; if not, write to the Free Software
    30  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    31  */
    32 
    33 #ifdef HAVE_CONFIG_H
    34 #  include "config.h"
    35 #endif
    36 
    37 #include <glib.h> 
    38 #include <glib/gprintf.h>
    39 
    40 #include <arpa/inet.h>
    41 #include <sys/types.h>
    42 #include <sys/socket.h>
    43 #include <netdb.h>
    44 #include <net/if.h>
    45 #include <errno.h>
    46 #include <stdlib.h>
    47 
    48 #include <unistd.h>
    49 #include <netinet/in.h>
    50 #include <fcntl.h>
    51 #include <signal.h>
    52 
    53 #if defined(HAVE_IFADDRS_H)
    54 	#include <ifaddrs.h>
    55 #else
    56 	#include <sys/ioctl.h>
    57 #endif
    58 
    59 #include "gmyth_socket.h"
    60 #include "gmyth_stringlist.h"
    61 #include "gmyth_context.h"
    62 #include "gmyth_uri.h"
    63 
    64 #define BUFLEN 				        			512
    65 #define MYTH_SEPARATOR 			    		"[]:[]"
    66 #define MYTH_PROTOCOL_FIELD_SIZE		8
    67 
    68 /* max number of iterations */
    69 #define MYTHTV_MAX_VERSION_CHECKS		40
    70 
    71 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
    72 
    73 static void gmyth_socket_class_init          (GMythSocketClass *klass);
    74 static void gmyth_socket_init                (GMythSocket *object);
    75 
    76 static void gmyth_socket_dispose  (GObject *object);
    77 static void gmyth_socket_finalize (GObject *object);
    78 
    79 G_DEFINE_TYPE(GMythSocket, gmyth_socket, G_TYPE_OBJECT)
    80 
    81 static void
    82 gmyth_socket_class_init (GMythSocketClass *klass)
    83 {
    84     GObjectClass *gobject_class;
    85 
    86     gobject_class = (GObjectClass *) klass;
    87 
    88     gobject_class->dispose  = gmyth_socket_dispose;
    89     gobject_class->finalize = gmyth_socket_finalize;	
    90 }
    91 
    92 static void
    93 gmyth_socket_init (GMythSocket *gmyth_socket)
    94 {
    95 }
    96 
    97 /** Gets the some important address translation info, from the client socket
    98  * that will open a connection.
    99  * 
   100  * @return gint that represents the error number from getaddrinfo(). 
   101  */
   102 static gint
   103 gmyth_socket_toaddrinfo( gchar *addr, gint port, struct addrinfo **addrInfo )
   104 {
   105     struct addrinfo hints;
   106     gchar *portStr = g_strnfill( 32, ' ' );
   107     gint errorn = EADDRNOTAVAIL;
   108 
   109     memset( &hints, 0, sizeof(hints) );
   110     hints.ai_family = AF_INET;
   111     hints.ai_socktype = SOCK_STREAM;
   112     /* hints.ai_flags = AI_NUMERICHOST; */
   113     if ( port != -1 )	
   114 		sprintf(portStr, "%d", port);
   115     else
   116 		portStr = NULL;
   117 
   118     g_debug( "[%s] Address: %s, port: %s\n", __FUNCTION__, addr, portStr );
   119     if ( ( errorn = getaddrinfo(addr, portStr, &hints, addrInfo) ) != 0 ) {
   120 		g_printerr( "[%s] Socket ERROR: %s\n", __FUNCTION__, gai_strerror(errorn) );
   121     }
   122 
   123     return errorn;
   124 }
   125 
   126 static gint
   127 gmyth_socket_find_match_address_uri( GMythURI* uri, gchar *address ) {
   128 
   129         if ( g_ascii_strcasecmp( gmyth_uri_gethost( uri ), address ) == 0 ) {
   130                 //g_printerr( "Found URI: %s !!!\n", rui_uri_getvalue(uri) );
   131                 return 0;
   132         } else {
   133                 return -1;
   134         }
   135 
   136 }
   137 
   138 #if defined(HAVE_IFADDRS_H)
   139 
   140 /** Gets the list of all local network interfaces.
   141  * 
   142  * @param current_connections	A list with all the network interfaces are valid, 
   143  * 		to be applied just like a filter.
   144  * @return List with all the local net interfaces. 
   145  */
   146 static GList *
   147 gmyth_socket_get_local_addrs( GList *current_connections ) {
   148 	
   149 	GList *local_addrs = NULL;
   150 	
   151 	struct ifaddrs *ifaddr;	
   152 	struct ifaddrs *i;
   153 
   154 	gchar addr[NI_MAXHOST+1];
   155 	gchar *ifname;
   156 	gint ifIdx;
   157 	
   158 	if (getifaddrs(&ifaddr) != 0)
   159 	{
   160 		g_printerr("No addresses for interfaces!\n");
   161 		return NULL;
   162 	}
   163 	
   164 	for ( i = ifaddr; i != NULL; i = i->ifa_next ) {
   165 		if (!(i->ifa_flags & IFF_UP))
   166 			continue;
   167 		if (i->ifa_flags & IFF_LOOPBACK)
   168 			continue;
   169 		if ( getnameinfo(i->ifa_addr, sizeof(struct sockaddr), addr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0 ) {
   170 
   171 			ifname = i->ifa_name;
   172 			ifIdx = if_nametoindex(ifname);
   173 			/* g_debug( "[%s] Interface name: %s, index: %d, address: %s\n", __FUNCTION__, ifname, ifIdx, addr ); */
   174 			if ( current_connections == NULL || ( current_connections != NULL && 
   175 					g_list_find_custom( current_connections, (gchar *)addr, 
   176 						(GCompareFunc)gmyth_socket_find_match_address_uri ) == NULL ) )
   177 				local_addrs = g_list_append( local_addrs, g_strdup( addr ) );
   178 
   179 		}
   180 	} /* iterates over network interfaces */
   181 	
   182 	freeifaddrs(ifaddr);
   183 	
   184 	return local_addrs;
   185 
   186 }
   187 
   188 #else
   189 
   190 static const char *PATH_PROC_NET_DEV = "/proc/net/dev";
   191 
   192 /** Gets the list of all local network interfaces (using the /proc/net/dev directory).
   193  * 
   194  * @param current_connections	A list with all the network interfaces are valid, 
   195  * 		to be applied just like a filter.
   196  * @return List with all the local net interfaces. 
   197  */
   198 static GList *
   199 gmyth_socket_get_local_addrs( GList *current_connections )
   200 {
   201 
   202 	GList *local_addrs = NULL;
   203 	FILE *fd;
   204 	gint s;
   205 	gchar buffer[256+1];
   206 	gchar ifaddr[20+1];
   207 	gchar *ifname;
   208 	gchar *sep;
   209 	
   210 	s = socket(AF_INET, SOCK_DGRAM, 0);
   211 	if (s < 0)
   212 		return 0;
   213 	fd = fopen(PATH_PROC_NET_DEV, "r");
   214 	fgets(buffer, sizeof(buffer)-1, fd);
   215 	fgets(buffer, sizeof(buffer)-1, fd);
   216 	while (!feof(fd)) {
   217 		ifname = buffer;
   218 		sep;
   219 		if (fgets(buffer, sizeof(buffer)-1, fd) == NULL)
   220 			break;
   221 		sep = strrchr(buffer, ':');
   222 		if (sep)
   223 			*sep = 0;
   224 		while (*ifname == ' ')
   225 			ifname++;
   226 		struct ifreq req;
   227 		strcpy(req.ifr_name, ifname);
   228 		if (ioctl(s, SIOCGIFFLAGS, &req) < 0)
   229 			continue;
   230 		if (!(req.ifr_flags & IFF_UP))
   231 			continue;
   232 		if (req.ifr_flags & IFF_LOOPBACK)
   233 			continue;
   234 		if (ioctl(s, SIOCGIFADDR, &req) < 0)
   235 			continue;
   236 		g_strlcpy( ifaddr, inet_ntoa(((struct sockaddr_in*)&req.ifr_addr)->sin_addr), sizeof(struct ifaddr)-1 );
   237 		local_addrs = g_list_append( local_addrs, g_strdup( ifaddr ) );
   238 
   239 		g_debug( "[%s] ( from the /proc/net/dev) Interface name: %s, address: %s\n", __FUNCTION__, 
   240 								ifname, ifaddr );
   241 	}
   242 	fclose(fd);
   243 	close(s);
   244 	return local_addrs;
   245 
   246 }
   247 
   248 #endif
   249 
   250 /**
   251  * Get only the local addresses from the primary interface
   252  */
   253 static gchar *
   254 gmyth_socket_get_primary_addr()
   255 {
   256 	
   257 	gchar *if_eth0 = g_new0( gchar, sizeof(struct ifaddr)-1 );
   258 	GList *if_tmp = NULL;
   259 	
   260 	GList *interfs = gmyth_socket_get_local_addrs( NULL );
   261 	
   262 	if ( interfs != NULL && ( g_list_length( interfs ) > 0 ) ) 
   263 	{
   264 		/* get the first occurrence (primary interface) */
   265 		if_tmp = g_list_first( interfs );
   266 		
   267 		if ( if_tmp != NULL )
   268 			g_strlcpy( if_eth0, g_strdup( (gchar *)if_tmp->data ), sizeof(struct ifaddr)-1 );
   269 
   270 	}
   271 	
   272 	if ( interfs != NULL )
   273 		g_list_free( interfs );
   274 	
   275 	return if_eth0;
   276 }
   277 
   278 /** This function retrieves the local hostname of the 
   279  * client machine.
   280  *
   281  * @return GString* get local hostname.
   282  */
   283 GString *
   284 gmyth_socket_get_local_hostname( )
   285 {
   286     GString *str = g_string_sized_new( 1024 );
   287 
   288     gchar *localhostname = g_strnfill( 1024, ' ' );
   289     gchar *localaddr = g_strdup( "127.0.0.1" );
   290 
   291     gboolean found_addr = FALSE;
   292 
   293     struct addrinfo* addr_info_data = NULL, *addr_info0 = NULL;
   294 
   295     struct sockaddr_in* sa = NULL;
   296 
   297     gethostname(localhostname, 1024);
   298     gint err = gmyth_socket_toaddrinfo( localhostname, -1,  &addr_info_data );
   299     
   300     if ( err == EADDRNOTAVAIL )
   301     {
   302     	g_warning( "[%s] Address (%s) not available. (reason = %d)\n", __FUNCTION__, localhostname, err );
   303     	return str;
   304     }
   305     
   306     g_static_mutex_lock( &mutex );    	
   307 
   308     addr_info0 = addr_info_data;
   309 
   310     while( addr_info0 != NULL && addr_info0->ai_addr != NULL && 
   311 	    ( sa = (struct sockaddr_in*)addr_info0->ai_addr ) != NULL && !found_addr ) {
   312     	localaddr = inet_ntoa( sa->sin_addr );
   313 
   314 	    if ( localaddr != NULL && ( g_strrstr( localaddr, "127" ) == NULL ) ) {
   315 	        str = g_string_assign( str, g_strdup( localaddr ) );
   316 	        found_addr = TRUE;
   317 	        break;
   318 	    }
   319 	    addr_info0 = addr_info0->ai_next;
   320     };
   321 
   322     if ( found_addr == FALSE ) {
   323       gchar *prim_addr = gmyth_socket_get_primary_addr();
   324 
   325     	if ( prim_addr != NULL ) {
   326 			    g_warning("[%s] Could not determine the local alphanumerical hostname. Setting to %s\n",
   327     				__FUNCTION__, prim_addr );
   328       
   329 	        str = g_string_assign( str, g_strdup( prim_addr ) );
   330 	        g_free( prim_addr );
   331     	} else {
   332 					str = g_string_assign( str, g_strdup( localhostname ) );
   333     	}
   334     }
   335 
   336     g_static_mutex_unlock( &mutex );
   337 
   338     if (localhostname!=NULL)
   339 	g_free( localhostname );
   340 
   341     return str;
   342 }
   343 
   344 static void
   345 gmyth_socket_dispose  (GObject *object)
   346 {
   347     GMythSocket *gmyth_socket = GMYTH_SOCKET(object);
   348 
   349     gmyth_socket_close_connection (gmyth_socket);
   350     /* disconnect socket */
   351     G_OBJECT_CLASS (gmyth_socket_parent_class)->dispose (object);
   352 }
   353 
   354 static void
   355 gmyth_socket_finalize (GObject *object)
   356 {
   357     g_signal_handlers_destroy (object);
   358 
   359     G_OBJECT_CLASS (gmyth_socket_parent_class)->finalize (object);
   360 }
   361 
   362 /** Creates a new instance of GMythSocket.
   363  * 
   364  * @return a new instance of GMythSocket.
   365  */
   366 GMythSocket*
   367 gmyth_socket_new ()
   368 {
   369     GMythSocket *gmyth_socket = GMYTH_SOCKET (g_object_new(GMYTH_SOCKET_TYPE, NULL));
   370 
   371     gmyth_socket->sd_io_ch = NULL;
   372 
   373     gmyth_socket->hostname = g_strdup("");
   374 
   375     gmyth_socket->port = 6543;
   376     
   377     gmyth_socket->mythtv_version = MYTHTV_VERSION_DEFAULT;
   378 
   379     return gmyth_socket;
   380 }
   381 
   382 /** Try to open an asynchronous connection to the MythTV backend.
   383  * 
   384  * @param fd 			Socket descriptor.
   385  * @param remote 	Remote address.
   386  * @param len 		Newly created socket length field.
   387  * @param timeout	Timeval argument with the time interval to timeout before closing.
   388  * @param err			Error message number.
   389  * @return Any numerical value below 0, if an error had been found.
   390  */
   391 static gint 
   392 gmyth_socket_try_connect ( gint fd, struct sockaddr *remote, gint len,
   393                struct timeval *timeout, gint *err)
   394 {
   395 	  gint saveflags, ret, back_err;
   396 	  
   397 	  fd_set fd_w;
   398 	
   399 	  saveflags = fcntl( fd, F_GETFL, 0 );
   400 	  if( saveflags < 0 ) {
   401 	    g_warning( "[%s] Problems when getting socket flags on fcntl.\n", __FUNCTION__ );
   402 	    *err=errno;
   403 	    return -1;
   404 	  }
   405 	
   406 	  /* Set non blocking */
   407 	  if( fcntl( fd, F_SETFL, saveflags | O_NONBLOCK ) < 0) {
   408 	  	g_warning( "[%s] Problems when setting non-blocking using fcntl.\n", __FUNCTION__ );
   409 	    *err=errno;
   410 	    return -1;
   411 	  }
   412 	
   413 	  /* This will return immediately */
   414 	  *err= connect ( fd, remote, len );
   415 		back_err=errno;
   416 	
   417 		/* restore flags */
   418 	  if( fcntl( fd, F_SETFL, saveflags ) < 0) {
   419 	    g_warning( "[%s] Problems when trying to restore flags with fcntl.\n", __FUNCTION__ );
   420 	    *err=errno;
   421 	    return -1;
   422 	  }
   423 	
   424 	  /* return unless the connection was successful or the connect is
   425 	     still in progress. */
   426 	  if( *err < 0 && back_err != EINPROGRESS) {
   427 	    g_warning( "[%s] Connection unsucessfully (it is not in progress).\n", __FUNCTION__ );
   428 	    *err = errno;
   429 	    return -1;
   430 	  }
   431 	
   432 	  FD_ZERO( &fd_w );
   433 	  FD_SET( fd, &fd_w );
   434 	
   435 	  *err = select( FD_SETSIZE, NULL, &fd_w, NULL, timeout);
   436 	  if ( *err < 0 ) {
   437 	    g_warning( "[%s] Connection unsucessfull (timed out).\n", __FUNCTION__ );
   438 	    *err=errno;
   439 	    return -1;
   440 	  }
   441 	
   442 	  /* 0 means it timeout out & no fds changed */
   443 	  if(*err==0) {
   444 	    close(fd);
   445 	    *err=ETIMEDOUT;
   446 	    return -1;
   447 	  }
   448 	
   449 	  /* Get the return code from the connect */
   450 	  len = sizeof( ret );
   451 	  *err=getsockopt( fd, SOL_SOCKET, SO_ERROR, &ret, &len );
   452 	  
   453 	  if( *err < 0 ) {
   454 	    g_warning( "[%s] Connection usnsucessfull.\n", __FUNCTION__ );
   455 	    *err=errno;
   456 	    return -1;
   457 	  }
   458 	
   459 	  /* ret=0 means success, otherwise it contains the errno */
   460 	  if (ret) {
   461 	    *err=ret;
   462 	    return -1;
   463 	  }
   464 	
   465 	  *err=0;
   466 	  return 0;
   467 }
   468 
   469 /** Connects to the backend.
   470  * 
   471  * @param gmyth_socket The GMythSocket instance.
   472  * @param hostname The backend hostname or IP address.
   473  * @param port The backend port.
   474  * @return TRUE if success, FALSE if error.
   475  */
   476 gboolean
   477 gmyth_socket_connect (GMythSocket *gmyth_socket,
   478 	gchar *hostname, gint port)
   479 {
   480     struct addrinfo *addr_info_data = NULL, *addr_info0 = NULL;
   481     gint ret_code = -1;
   482     gint errno;
   483     gboolean ret = TRUE;
   484 
   485     if ( hostname == NULL )
   486 		g_printerr ( "[%s] Invalid hostname parameter!\n", __FUNCTION__ );
   487 
   488     errno = gmyth_socket_toaddrinfo( hostname, port, &addr_info_data );
   489 
   490     g_return_val_if_fail( addr_info_data != NULL, FALSE );
   491 
   492     /* store hostname and port number */
   493     gmyth_socket->hostname = g_strdup( hostname );
   494     gmyth_socket->port = port;
   495 
   496     for ( addr_info0 = addr_info_data; addr_info0; addr_info0 = addr_info_data->ai_next ) {
   497 
   498 	struct sockaddr_in *sa = (struct sockaddr_in*)addr_info0->ai_addr;
   499 	/* init socket descriptor */
   500 	gmyth_socket->sd = socket( addr_info0->ai_family, addr_info0->ai_socktype,
   501 				     addr_info0->ai_protocol );
   502 
   503 	if ( gmyth_socket->sd < 0 )
   504 	    continue;
   505 
   506 	g_debug( "[%s] hostname = %s, sock_fd = %d, addr = %s, addr_len = %d, \
   507 		ai_family = %d, ai_protocol = %d\n",
   508 		__FUNCTION__, hostname, gmyth_socket->sd, inet_ntoa( sa->sin_addr ),
   509 		addr_info0->ai_addrlen, addr_info0->ai_family, addr_info0->ai_protocol );
   510 		
   511 	struct timeval *timeout = g_new0( struct timeval, 1 );
   512 	
   513 	/* using 40 seconds timeout */
   514 	timeout->tv_sec = 40;
   515 	timeout->tv_usec = 0;
   516 		
   517 	if ( gmyth_socket_try_connect( gmyth_socket->sd, (struct sockaddr *)addr_info0->ai_addr,
   518 			addr_info0->ai_addrlen, timeout, &ret_code ) < 0 )
   519 	{
   520 	    g_printerr( "[%s] Error connecting to backend!\n", __FUNCTION__ );
   521 	    if ( ret_code == ETIMEDOUT )
   522 		g_printerr( "[%s]\tBackend host unreachable!\n", __FUNCTION__ );
   523 
   524 	    g_printerr( "ERROR: %s\n", gai_strerror(ret_code) );
   525 	    continue;
   526 	}
   527 
   528 	/* only will be reached if none of the error above occurred */
   529 	break;
   530 
   531     }
   532 
   533     gmyth_socket->sd_io_ch = g_io_channel_unix_new( gmyth_socket->sd );
   534 
   535     ret = ( ret_code == 0 ) ? TRUE : FALSE ;
   536 
   537     return ret;
   538 
   539 }
   540 
   541 /** Gets the GIOChannel associated to the given GMythSocket.
   542  * 
   543  * @param gmyth_socket The GMythSocket instance.
   544  */
   545 GIOChannel *
   546 gmyth_socket_get_io_channel( GMythSocket *gmyth_socket )
   547 {
   548     g_return_val_if_fail( gmyth_socket != NULL, NULL );
   549 
   550     return gmyth_socket->sd_io_ch;
   551 }
   552 
   553 /** Verifies if the socket is able to read.
   554  * 
   555  * @param gmyth_socket The GMythSocket instance.
   556  * @return TRUE if the socket is able to read, FALSE if not.
   557  */
   558 gboolean
   559 gmyth_socket_is_able_to_read( GMythSocket *gmyth_socket )
   560 {
   561     gboolean ret = TRUE;
   562 
   563     /* verify if the input (read) buffer is ready to receive data */
   564     GIOCondition io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
   565 
   566     if ( ( io_cond & G_IO_IN ) == 0 ) {
   567 	g_warning ("[%s] IO channel is not able to send data!\n", __FUNCTION__);
   568 	ret = FALSE;
   569     }
   570 
   571     return ret;
   572 
   573 }
   574 
   575 /** Verifies if the socket is able to write.
   576  * 
   577  * @param gmyth_socket The GMythSocket instance.
   578  * @return TRUE if the socket is able to write, FALSE if not.
   579  */
   580 gboolean
   581 gmyth_socket_is_able_to_write( GMythSocket *gmyth_socket )
   582 {
   583     gboolean ret = TRUE;
   584 
   585     /* verify if the input (read) buffer is ready to receive data */
   586     GIOCondition io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
   587 
   588     if ( ( ( io_cond & G_IO_OUT ) == 0 ) || ( ( io_cond & G_IO_HUP ) == 0 ) ) {
   589 	g_warning ("[%s] IO channel is not able to send data!\n", __FUNCTION__);
   590 	ret = FALSE;
   591     }
   592 
   593     return ret;
   594 
   595 }
   596 
   597 /** Sends a command to the backend.
   598  * 
   599  * @param gmyth_socket the GMythSocket instance.
   600  * @param command The string command to be sent.
   601  */
   602 gboolean
   603 gmyth_socket_send_command(GMythSocket *gmyth_socket, GString *command) 
   604 {
   605     gboolean ret = TRUE;
   606 
   607     GIOStatus io_status = G_IO_STATUS_NORMAL;
   608     //GIOCondition io_cond;
   609     GError* error = NULL;
   610     gchar *buffer = NULL;
   611 
   612     gsize bytes_written = 0;
   613 
   614     if( command == NULL || ( command->len <= 0 ) || command->str == NULL ) {
   615 		g_warning ("[%s] Invalid NULL command parameter!\n", __FUNCTION__);
   616 		ret = FALSE;
   617 		goto done;
   618     }
   619 
   620     g_static_mutex_lock( &mutex );
   621     g_print ("[%s] Sending command to backend: %s\n", __FUNCTION__, command->str);
   622 
   623     /*
   624        io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
   625 
   626        if ( ( io_cond & G_IO_IN ) == 0 ) {
   627        g_warning ("[%s] IO channel is not able to send data!\n", __FUNCTION__);
   628        ret = FALSE;
   629        goto done;
   630        }
   631        */
   632 
   633     buffer = g_strnfill( BUFLEN, ' ' );
   634     snprintf( buffer, MYTH_PROTOCOL_FIELD_SIZE+1, "%-8d", command->len);
   635     g_print( "[%s] buffer = [%s]\n", __FUNCTION__, buffer  );
   636 
   637     command = g_string_prepend(command, buffer);
   638 
   639     g_print( "[%s] command = [%s]\n", __FUNCTION__, command->str  );
   640 
   641     /* write bytes to socket */    
   642     io_status = g_io_channel_write_chars( gmyth_socket->sd_io_ch, command->str, 
   643 	    command->len, &bytes_written, &error );
   644 
   645 
   646     if( (io_status == G_IO_STATUS_ERROR) || ( bytes_written <= 0 ) ) {
   647 		g_warning ("[%s] Error while writing to socket", __FUNCTION__);
   648 		ret = FALSE;
   649     } else if ( bytes_written < command->len ) {
   650 		g_warning ("[%s] Not all data was written socket", __FUNCTION__);
   651 		ret = FALSE;
   652     }
   653 
   654     io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error );
   655 
   656     if ( ( bytes_written != command->len ) || ( io_status == G_IO_STATUS_ERROR ) )
   657     {
   658 		g_warning ("[%s] Some problem occurred when sending data to the socket\n", __FUNCTION__);
   659 	
   660 		ret = TRUE;
   661     }
   662 
   663     g_static_mutex_unlock( &mutex );
   664 done:
   665     if ( error != NULL ) {
   666 		g_printerr( "[%s] Error found reading data from IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message );
   667 		ret = FALSE;
   668 		g_error_free( error );
   669     }
   670 
   671     if ( buffer!= NULL )
   672 		g_free( buffer );
   673 
   674     return ret;
   675 }
   676 
   677 /** Starts Mythtv protocol level connection. Checks Mythtv protocol version
   678  * supported by the backend and send the "ANN" command.
   679  * 
   680  * @param gmyth_socket the GMythSocket instance.
   681  * @param hostname_backend The backend hostname or IP address.
   682  * @param port The backend port to connect.
   683  * @param blocking_client A flag to choose between blocking and non-blocking 
   684  * backend connection.
   685  */
   686 gboolean
   687 gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket, 
   688 	gchar *hostname_backend, int port, gboolean blocking_client)
   689 {
   690     if (!gmyth_socket_connect (gmyth_socket, hostname_backend, port)) {
   691 		g_warning ("[%s] Could not open socket to backend machine", __FUNCTION__);
   692 		return FALSE;
   693     }
   694 
   695     if ( gmyth_socket_check_protocol_version (gmyth_socket) ) {
   696 
   697 	GString *result;
   698 	GString *base_str = g_string_new("");
   699 	GString *hostname = NULL;
   700 
   701 	hostname = gmyth_socket_get_local_hostname();
   702 
   703 	g_string_printf(base_str, "ANN %s %s 0", 
   704 		(blocking_client ? "Playback" : "Monitor"),
   705 		hostname->str);
   706 
   707 	g_debug ("[%s] Connection command sent to backend: %s", __FUNCTION__, base_str->str);
   708 
   709 	gmyth_socket_send_command (gmyth_socket, base_str);
   710 	result = gmyth_socket_receive_response(gmyth_socket);
   711 
   712 	if (result != NULL) {
   713 	    g_debug ("[%s] Response received from backend: %s", __FUNCTION__, result->str);
   714 	    g_string_free (result, TRUE);
   715 	}
   716 
   717 	g_string_free (hostname, TRUE);
   718 	g_string_free (base_str, TRUE);
   719 
   720 	return TRUE;
   721     } else {
   722 	g_warning ("[%s] GMythSocket could not connect to the backend", __FUNCTION__);	
   723 	return FALSE;
   724     }
   725 }
   726 
   727 /** Closes the socket connection to the backend.
   728  * 
   729  * @param gmyth_socket The GMythSocket instance.
   730  */
   731 void
   732 gmyth_socket_close_connection (GMythSocket *gmyth_socket)
   733 {
   734     close (gmyth_socket->sd);	
   735 }
   736 
   737 
   738 /** Try the MythTV version numbers, and get the version returned by
   739  * the possible REJECT message, in order to contruct a new
   740  * MythTV version request.
   741  * 
   742  * @param gmyth_socket The GMythSocket instance.
   743  * @param mythtv_version The Mythtv protocol version to be tested
   744  * 
   745  * @return The actual MythTV the client is connected to.
   746  */
   747 gint
   748 gmyth_socket_check_protocol_version_number (GMythSocket *gmyth_socket, gint mythtv_version)
   749 {
   750     GString *response;
   751     GString *payload;
   752     gchar *new_version = g_strdup("");
   753     gboolean res = TRUE;
   754     gint mythtv_new_version = MYTHTV_CANNOT_NEGOTIATE_VERSION;
   755     guint max_iterations = MYTHTV_MAX_VERSION_CHECKS;
   756 
   757 try_new_version:
   758     payload = g_string_new ("MYTH_PROTO_VERSION");
   759     g_string_append_printf( payload, " %d", mythtv_version );
   760 
   761     gmyth_socket_send_command(gmyth_socket, payload);
   762     response = gmyth_socket_receive_response(gmyth_socket);
   763 
   764     if (response == NULL) {
   765 		g_warning ("[%s] Check protocol version error! Not answered!", __FUNCTION__);
   766 		res = FALSE;	
   767 		goto done;
   768     }
   769 
   770     res = g_str_has_prefix (response->str, "ACCEPT");
   771     if (!res) {
   772 		g_warning ("[%s] Protocol version request error: %s", __FUNCTION__, response->str);
   773 	/* get the version number returned by the REJECT message */
   774 	if ( ( res = g_str_has_prefix (response->str, "REJECT") ) == TRUE ) {
   775 	    new_version = g_strrstr( response->str, "]" );
   776 	    if (new_version!=NULL) {
   777 		++new_version; /* skip ']' character */
   778 		if ( new_version != NULL ) {
   779 		    g_print( "[%s] got MythTV version = %s.\n", __FUNCTION__, new_version );
   780 		    mythtv_version = (gint)g_ascii_strtoull( g_strdup( new_version ), NULL, 10 );
   781 		    /* do reconnection to the socket (socket is closed if the MythTV version was wrong) */
   782 		    gmyth_socket_connect( gmyth_socket, gmyth_socket->hostname, gmyth_socket->port );
   783 		    /* g_free( new_version ); */
   784 		    if ( --max_iterations > 0 ) 
   785 		    	goto try_new_version;
   786 		    else
   787 		    	goto done;
   788 		}
   789 	    }
   790 	}
   791     }
   792     
   793     /* change the return value to a valid one */
   794     if ( res ) {
   795     	mythtv_new_version = mythtv_version;
   796     	gmyth_socket->mythtv_version = mythtv_new_version;
   797     }
   798 
   799 done:
   800     if ( payload != NULL )
   801 		g_string_free (payload, TRUE);
   802     if ( response != NULL )
   803 		g_string_free (response, TRUE);
   804 
   805     return mythtv_new_version;
   806 }
   807 
   808 /** Verifies if the Mythtv backend supported the GMyth supported version.
   809  * 
   810  * @param gmyth_socket The GMythSocket instance.
   811  * @return TRUE if supports, FALSE if not.
   812  */
   813 gboolean
   814 gmyth_socket_check_protocol_version (GMythSocket *gmyth_socket)
   815 {
   816     return ( ( gmyth_socket->mythtv_version = 
   817     		gmyth_socket_check_protocol_version_number ( gmyth_socket, 
   818     							MYTHTV_VERSION_DEFAULT ) ) != MYTHTV_CANNOT_NEGOTIATE_VERSION );
   819 }
   820 
   821 /** Returns the Mythtv backend supported version.
   822  * 
   823  * @param gmyth_socket The GMythSocket instance.
   824  * @return The actual MythTV version number.
   825  */
   826 gint
   827 gmyth_socket_get_protocol_version (GMythSocket *gmyth_socket) 
   828 {
   829 	return gmyth_socket->mythtv_version;
   830 }
   831 
   832 /** Receives a backend answer after a gmyth_socket_send_command_call ().
   833  * 
   834  * @param gmyth_socket The GMythSocket instance.
   835  * @return The response received, or NULL if error or nothing was received.
   836  */
   837 GString*
   838 gmyth_socket_receive_response(GMythSocket *gmyth_socket)
   839 {
   840     GIOStatus io_status = G_IO_STATUS_NORMAL;
   841     GError* error = NULL;
   842     gchar *buffer = NULL;
   843 
   844     GString *str = NULL;
   845 
   846     gsize bytes_read = 0;
   847     gint  len = 0;
   848     GIOCondition io_cond;
   849 
   850     g_return_val_if_fail( gmyth_socket != NULL, NULL );
   851 
   852     /* verify if the input (read) buffer is ready to receive data */
   853 
   854     buffer = g_strnfill( BUFLEN, ' ' );
   855 
   856     g_static_mutex_lock( &mutex );
   857 
   858     io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer, MYTH_PROTOCOL_FIELD_SIZE, &bytes_read, &error );
   859 
   860     /* verify if the input (read) buffer is ready to receive data */
   861     io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
   862 
   863     g_print ( "[%s] Bytes read = %d\n", __FUNCTION__, bytes_read );
   864 
   865     if( (io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0) ) {
   866 		g_warning ("[%s] Error in mythprotocol response from backend\n", __FUNCTION__);
   867 		str = NULL;
   868 		//return NULL;
   869     } else {
   870 
   871 		io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error );
   872 		/* verify if the input (read) buffer is ready to receive data */
   873 		io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
   874 	
   875 		if ( ( io_cond & G_IO_IN ) != 0 ) {
   876 	
   877 		    snprintf( buffer, MYTH_PROTOCOL_FIELD_SIZE+1, "%-8s", g_strdup(buffer));
   878 		    g_print( "[%s] buffer = [%s]\n", __FUNCTION__, buffer  );
   879 	
   880 		    /* removes trailing whitespace */
   881 		    buffer = g_strstrip( buffer );
   882 	
   883 		    len = (gint)g_ascii_strtoull ( buffer, NULL, 10 );  
   884 	
   885 		    bytes_read = 0;
   886 		    io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer, len, &bytes_read, &error );
   887 		    buffer[bytes_read] = '\0';
   888 		}
   889     }  
   890 
   891     g_static_mutex_unlock( &mutex );
   892 
   893     g_debug ("[%s] Response received from backend: {%s}\n", __FUNCTION__, buffer);
   894 
   895     if ( ( bytes_read != len ) || ( io_status == G_IO_STATUS_ERROR ) )
   896 		str = NULL;
   897     else
   898 		str = g_string_new( buffer );
   899 
   900     if ( buffer != NULL )
   901 		g_free( buffer );
   902 
   903     if ( error != NULL ) {
   904 		g_printerr( "[%s] Error found receiving response from the IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message );
   905 		str = NULL;
   906 		g_error_free( error );
   907     }
   908 
   909     return str;
   910 }
   911 
   912 /** Format a Mythtv command from the str_list entries and send it to backend.
   913  * 
   914  * @param gmyth_socket The GMythSocket instance.
   915  * @param str_list The string list to form the command
   916  * @return TRUE if command was sent, FALSE if any error happens.
   917  */
   918 gboolean
   919 gmyth_socket_write_stringlist(GMythSocket *gmyth_socket, GMythStringList* str_list)
   920 {
   921 
   922     GList *tmp_list;
   923     GPtrArray *ptr_array;
   924     gchar *str_array;
   925 
   926     g_static_mutex_lock( &mutex );
   927 
   928     ptr_array = g_ptr_array_sized_new(g_list_length(str_list->glist));
   929 
   930     g_print( "[%s] Number of parameters = %d\n", __FUNCTION__, g_list_length(str_list->glist) );    
   931 
   932     // FIXME: change this implementation!
   933     tmp_list = str_list->glist;
   934     for(; tmp_list; tmp_list = tmp_list->next) {
   935 	if ( tmp_list->data != NULL )
   936 	    g_ptr_array_add(ptr_array, ((GString*)tmp_list->data)->str);
   937     }
   938     g_ptr_array_add(ptr_array, NULL); // g_str_joinv() needs a NULL terminated string
   939 
   940     str_array = g_strjoinv (MYTH_SEPARATOR, (gchar **) (ptr_array->pdata));
   941 
   942     g_static_mutex_unlock( &mutex );
   943 
   944     g_print( "[%s]\t\tSending the String list = %s\n", __FUNCTION__, str_array );
   945 
   946     // Sends message to backend	
   947     // TODO: implement looping to send remaining data, and add timeout testing!
   948     gmyth_socket_send_command(gmyth_socket, g_string_new(str_array));
   949 
   950     g_free (str_array);
   951     g_ptr_array_free (ptr_array, TRUE);
   952 
   953     return TRUE;
   954 }
   955 
   956 /* Receives a backend command response and split it into the given string list.
   957  * 
   958  * @param gmyth_socket The GMythSocket instance.
   959  * @param str_list the string list to be filled.
   960  * @return The number of received strings.
   961  */
   962 gint
   963 gmyth_socket_read_stringlist (GMythSocket *gmyth_socket, GMythStringList* str_list)
   964 {
   965     GString *response;
   966     gchar **str_array;
   967     gint i;
   968 
   969     response = gmyth_socket_receive_response(gmyth_socket);
   970     g_static_mutex_lock( &mutex );
   971 
   972     gmyth_string_list_clear_all (str_list);	
   973     str_array = g_strsplit (response->str, MYTH_SEPARATOR, -1);
   974 
   975     for (i=0; i< g_strv_length (str_array); i++) {
   976 	gmyth_string_list_append_string (str_list, g_string_new (str_array[i]));
   977     }
   978     g_static_mutex_unlock( &mutex );
   979 
   980     g_string_free (response, TRUE);
   981     g_strfreev (str_array);
   982 
   983     return gmyth_string_list_length (str_list);
   984 }
   985 
   986 /** Formats a Mythtv protocol command based on str_list and sends it to
   987  * the connected backend. The backend response is overwritten into str_list.
   988  *
   989  * @param gmyth_socket The GMythSocket instance.
   990  * @param str_list The string list to be sent, and on which the answer 
   991  * will be written.
   992  * @return TRUE if command was sent and an answer was received, FALSE if any
   993  * error happens.
   994  */
   995 gint
   996 gmyth_socket_sendreceive_stringlist (GMythSocket *gmyth_socket, GMythStringList *str_list)
   997 {
   998     gmyth_socket_write_stringlist (gmyth_socket, str_list);
   999 
  1000     return gmyth_socket_read_stringlist (gmyth_socket, str_list);
  1001 }