gmyth/src/gmyth_socket.c
branchtrunk
changeset 463 771f91aa9d5d
parent 444 d6603c86582f
child 464 5ef4452c42cc
     1.1 --- a/gmyth/src/gmyth_socket.c	Fri Mar 23 15:26:38 2007 +0000
     1.2 +++ b/gmyth/src/gmyth_socket.c	Tue Mar 27 21:31:34 2007 +0100
     1.3 @@ -46,6 +46,7 @@
     1.4  #include <netdb.h>
     1.5  #include <net/if.h>
     1.6  #include <errno.h>
     1.7 +#include <assert.h>
     1.8  #include <stdlib.h>
     1.9  
    1.10  #include <unistd.h>
    1.11 @@ -116,7 +117,6 @@
    1.12   
    1.13      g_return_val_if_fail ( addr != NULL, -1 );
    1.14  
    1.15 -    /* hints = g_malloc0 ( sizeof(struct addrinfo) ); */
    1.16      memset ( &hints, 0, sizeof(struct addrinfo) );
    1.17      hints.ai_family = AF_INET;
    1.18      hints.ai_socktype = SOCK_STREAM;
    1.19 @@ -125,21 +125,22 @@
    1.20      if ( port != -1 )	
    1.21          portStr = g_strdup_printf ( "%d", port );
    1.22      else
    1.23 -	portStr = NULL;
    1.24 +        portStr = NULL;
    1.25  
    1.26      gmyth_debug ("Getting name resolution for: %s, %d\n", addr, port);
    1.27  
    1.28      if ( ( errorn = getaddrinfo(addr, portStr, &hints, addrInfo) ) != 0 ) {
    1.29  		g_debug( "[%s] Socket ERROR: %s\n", __FUNCTION__, gai_strerror(errorn) );
    1.30      }
    1.31 +
    1.32      g_free (portStr);
    1.33 -    /* g_free (hints); */
    1.34 +
    1.35      return errorn;
    1.36  }
    1.37  
    1.38  static gint
    1.39 -gmyth_socket_find_match_address_uri( GMythURI* uri, gchar *address ) {
    1.40 -
    1.41 +gmyth_socket_find_match_address_uri( GMythURI* uri, gchar *address )
    1.42 +{
    1.43      if ( g_ascii_strcasecmp( gmyth_uri_get_host( uri ), address ) == 0 ) {
    1.44          //g_debug( "Found URI: %s !!!\n", rui_uri_getvalue(uri) );
    1.45          return 0;
    1.46 @@ -212,7 +213,6 @@
    1.47  static gchar *
    1.48  gmyth_socket_get_primary_addr()
    1.49  {
    1.50 -	
    1.51  	gchar *if_eth0 = g_new0( gchar, sizeof(struct ifaddr)-1 );
    1.52  	GList *if_tmp = NULL;
    1.53  	
    1.54 @@ -240,9 +240,8 @@
    1.55   * @return GString* get local hostname.
    1.56   */
    1.57  GString *
    1.58 -gmyth_socket_get_local_hostname  ()
    1.59 +gmyth_socket_get_local_hostname ()
    1.60  {
    1.61 -
    1.62      char hname[50];
    1.63      gint res = gethostname (hname, 50);
    1.64  
    1.65 @@ -338,14 +337,12 @@
    1.66      gmyth_socket_close_connection (gmyth_socket);
    1.67      
    1.68      g_free (gmyth_socket->hostname);
    1.69 -    gmyth_socket->hostname = NULL;
    1.70      
    1.71      g_free (local_hostname);
    1.72      
    1.73      local_hostname = NULL;
    1.74      
    1.75 -    if ( gmyth_socket->mutex != NULL )
    1.76 -    {
    1.77 +    if ( gmyth_socket->mutex != NULL ) {
    1.78      	g_mutex_free( gmyth_socket->mutex );
    1.79      	gmyth_socket->mutex = NULL; 
    1.80      }
    1.81 @@ -379,11 +376,11 @@
    1.82  
    1.83  /** Try to open an asynchronous connection to the MythTV backend.
    1.84   * 
    1.85 - * @param fd 			Socket descriptor.
    1.86 + * @param fd 		Socket descriptor.
    1.87   * @param remote 	Remote address.
    1.88   * @param len 		Newly created socket length field.
    1.89   * @param timeout	Timeval argument with the time interval to timeout before closing.
    1.90 - * @param err			Error message number.
    1.91 + * @param err		Error message number.
    1.92   * @return Any numerical value below 0, if an error had been found.
    1.93   */
    1.94  static gint 
    1.95 @@ -490,7 +487,11 @@
    1.96  	const gchar *hostname, gint port, guint timeout)
    1.97  {
    1.98      struct addrinfo *addr_info_data = NULL, *addr_info0 = NULL;
    1.99 +    struct linger* ling = NULL;
   1.100 +    gchar *tmp_str;
   1.101      gint ret_code = 0; /* -1 */
   1.102 +    /* FIXME: add as function parameter */
   1.103 +    gint err;
   1.104      gint errno;
   1.105      gboolean ret = TRUE;
   1.106  
   1.107 @@ -500,18 +501,21 @@
   1.108          gmyth_debug ( "Invalid hostname parameter!\n");
   1.109  
   1.110      /* store hostname and port number */
   1.111 -    if (gmyth_socket->hostname != NULL) {
   1.112 -        //g_free (gmyth_socket->hostname);
   1.113 -        gmyth_socket->hostname = NULL;
   1.114 -    }
   1.115 +    gmyth_debug ("CONNECTING %s:%d", hostname, port);
   1.116  
   1.117      errno = gmyth_socket_toaddrinfo ( hostname, port, &addr_info_data );
   1.118  
   1.119      g_return_val_if_fail( addr_info_data != NULL && hostname != NULL, FALSE );
   1.120  
   1.121 +    /* hack to avoid deleting the hostname when
   1.122 +     * gmyth_socket->hostname == hostname */
   1.123 +    tmp_str = gmyth_socket->hostname;
   1.124 +
   1.125      gmyth_socket->hostname = g_strdup( hostname );
   1.126      gmyth_socket->port = port;
   1.127  
   1.128 +    g_free (tmp_str);
   1.129 +
   1.130      for ( addr_info0 = addr_info_data; addr_info0; addr_info0 = addr_info_data->ai_next ) {
   1.131          /* init socket descriptor */
   1.132          gmyth_socket->sd = socket( addr_info0->ai_family, addr_info0->ai_socktype,
   1.133 @@ -521,19 +525,16 @@
   1.134              continue;
   1.135  
   1.136          struct timeval *timeout_val = g_new0 (struct timeval, 1);
   1.137 -	if (timeout != 0) {
   1.138 -	    /*timeout_val = g_new0 (struct timeval, 1);*/
   1.139 -	    
   1.140 +        if (timeout != 0) {
   1.141              timeout_val->tv_sec = timeout;
   1.142              timeout_val->tv_usec = 0;
   1.143 -	} else {
   1.144 +        } else {
   1.145              timeout_val->tv_sec = 5;
   1.146              timeout_val->tv_usec = 100;
   1.147 -	}
   1.148 +        }
   1.149          
   1.150          if (gmyth_socket_try_connect (gmyth_socket->sd, (struct sockaddr *)addr_info0->ai_addr,
   1.151 -                addr_info0->ai_addrlen, timeout_val, &ret_code ) < 0 )
   1.152 -        {
   1.153 +                addr_info0->ai_addrlen, timeout_val, &ret_code ) < 0 ) {
   1.154              g_debug( "[%s] Error connecting to backend!\n", __FUNCTION__ );
   1.155              if (ret_code == ETIMEDOUT)
   1.156                  g_debug( "[%s]\tBackend host unreachable!\n", __FUNCTION__ );
   1.157 @@ -541,11 +542,11 @@
   1.158              close (gmyth_socket->sd);
   1.159              gmyth_socket->sd = -1;
   1.160              g_debug ("ERROR: %s\n", gai_strerror(ret_code));
   1.161 -	    g_free (timeout_val);
   1.162 +    	    g_free (timeout_val);
   1.163              continue;
   1.164          }
   1.165  
   1.166 -	g_free (timeout_val);
   1.167 +	    g_free (timeout_val);
   1.168  
   1.169          /* only will be reached if none of the error above occurred */
   1.170          break;
   1.171 @@ -559,12 +560,19 @@
   1.172          gmyth_socket->sd_io_ch = NULL;
   1.173      }
   1.174      
   1.175 -    struct linger* ling = g_malloc0( sizeof(struct linger) );
   1.176 +    ling = g_malloc0( sizeof(struct linger) );
   1.177      ling->l_onoff = TRUE;
   1.178      ling->l_linger = 1;
   1.179      
   1.180 -    setsockopt(gmyth_socket->sd, SOL_SOCKET, SO_LINGER, ling, sizeof(struct linger));
   1.181 -    
   1.182 +    err = setsockopt(gmyth_socket->sd, SOL_SOCKET, SO_LINGER, ling, sizeof(struct linger));
   1.183 +	  
   1.184 +    if( err < 0 ) {
   1.185 +        g_debug( "[%s] Setting connection unsucessfull.\n", __FUNCTION__ );
   1.186 +	    err=errno;
   1.187 +        ret = FALSE;
   1.188 +        goto cleanup;
   1.189 +    } 
   1.190 +
   1.191      gmyth_socket->sd_io_ch = g_io_channel_unix_new (gmyth_socket->sd);
   1.192      
   1.193      g_io_channel_set_close_on_unref (gmyth_socket->sd_io_ch, TRUE);
   1.194 @@ -578,6 +586,11 @@
   1.195  		g_io_channel_set_flags (gmyth_socket->sd_io_ch, flags, NULL);
   1.196  
   1.197      ret = ( ret_code == 0 ) ? TRUE : FALSE ;
   1.198 +
   1.199 +cleanup:
   1.200 +    if ( !ling )
   1.201 +        g_free (ling);
   1.202 +    
   1.203      if ( !ret )
   1.204      	gmyth_debug("GMythSocket error - return code error!");
   1.205      	
   1.206 @@ -732,36 +745,35 @@
   1.207      }
   1.208  
   1.209      if ( gmyth_socket_check_protocol_version (gmyth_socket) ) {
   1.210 +        GString *result;
   1.211 +        GString *base_str = g_string_new("");	
   1.212 +        GString *hostname = NULL;
   1.213  
   1.214 -	GString *result;
   1.215 -	GString *base_str = g_string_new("");
   1.216 -	GString *hostname = NULL;
   1.217 +        hostname = gmyth_socket_get_local_hostname();
   1.218 +        if (hostname == NULL) {
   1.219 +            g_debug ("Hostname not available, setting to n800frontend\n");
   1.220 +            hostname = g_string_new ("n800frontend");
   1.221 +        }
   1.222 +        
   1.223 +        g_string_printf(base_str, "ANN %s %s %u", 
   1.224 +		    (blocking_client ? "Playback" : "Monitor"),
   1.225 +    		hostname->str, with_events);
   1.226  
   1.227 -	hostname = gmyth_socket_get_local_hostname();
   1.228 -	if (hostname == NULL) {
   1.229 -	    g_debug ("Hostname not available, setting to n800frontend\n");
   1.230 -	    hostname = g_string_new ("n800frontend");
   1.231 -	}
   1.232 -
   1.233 -	g_string_printf(base_str, "ANN %s %s %u", 
   1.234 -		(blocking_client ? "Playback" : "Monitor"),
   1.235 -		hostname->str, with_events);
   1.236 -
   1.237 -	gmyth_socket_send_command (gmyth_socket, base_str);
   1.238 -	result = gmyth_socket_receive_response (gmyth_socket);
   1.239 -
   1.240 -	if (result != NULL) {
   1.241 -	    gmyth_debug ("Response received from backend: %s", result->str);
   1.242 -	    g_string_free (result, TRUE);
   1.243 -	}
   1.244 -
   1.245 -	g_string_free (hostname, TRUE);
   1.246 -	g_string_free (base_str, TRUE);
   1.247 -
   1.248 -	return TRUE;
   1.249 +        gmyth_socket_send_command (gmyth_socket, base_str);
   1.250 +        result = gmyth_socket_receive_response (gmyth_socket);
   1.251 +        
   1.252 +        if (result != NULL) {
   1.253 +            gmyth_debug ("Response received from backend: %s", result->str);
   1.254 +            g_string_free (result, TRUE);
   1.255 +        }
   1.256 +        
   1.257 +        g_string_free (hostname, TRUE);
   1.258 +        g_string_free (base_str, TRUE);
   1.259 +        
   1.260 +        return TRUE;
   1.261      } else {
   1.262 -	g_debug ("[%s] GMythSocket could not connect to the backend", __FUNCTION__);	
   1.263 -	return FALSE;
   1.264 +        g_debug ("[%s] GMythSocket could not connect to the backend", __FUNCTION__);
   1.265 +        return FALSE;
   1.266      }
   1.267  }
   1.268  
   1.269 @@ -852,6 +864,8 @@
   1.270      gint mythtv_new_version = MYTHTV_CANNOT_NEGOTIATE_VERSION;
   1.271      guint max_iterations = MYTHTV_MAX_VERSION_CHECKS;
   1.272  
   1.273 +    assert (gmyth_socket);
   1.274 +
   1.275  try_new_version:
   1.276      payload = g_string_new ("MYTH_PROTO_VERSION");
   1.277      g_string_append_printf( payload, " %d", mythtv_version );
   1.278 @@ -867,26 +881,30 @@
   1.279  
   1.280      res = g_str_has_prefix (response->str, "ACCEPT");
   1.281      if (!res) {
   1.282 -		g_debug ("[%s] Protocol version request error: %s", __FUNCTION__, response->str);
   1.283 -	/* get the version number returned by the REJECT message */
   1.284 -	if ( ( res = g_str_has_prefix (response->str, "REJECT") ) == TRUE ) {
   1.285 -        gchar *new_version = NULL;
   1.286 -	    new_version = g_strrstr( response->str, "]" );
   1.287 -	    if (new_version!=NULL) {
   1.288 -		++new_version; /* skip ']' character */
   1.289 -		if ( new_version != NULL ) {
   1.290 -		    gmyth_debug ( "[%s] got MythTV version = %s.\n", __FUNCTION__, new_version );
   1.291 -		    mythtv_version = (gint)g_ascii_strtoull (new_version, NULL, 10 );
   1.292 -		    /* do reconnection to the socket (socket is closed if the MythTV version was wrong) */
   1.293 -		    gmyth_socket_connect( gmyth_socket, gmyth_socket->hostname, gmyth_socket->port );
   1.294 -            new_version =NULL;
   1.295 -		    if ( --max_iterations > 0 ) 
   1.296 -		    	goto try_new_version;
   1.297 -		    else
   1.298 -		    	goto done;
   1.299 -		}
   1.300 -	    }
   1.301 -	}
   1.302 +        g_debug ("[%s] Protocol version request error: %s", __FUNCTION__, response->str);
   1.303 +        /* get the version number returned by the REJECT message */
   1.304 +        if ( ( res = g_str_has_prefix (response->str, "REJECT") ) == TRUE ) {
   1.305 +            gchar *new_version = NULL;
   1.306 +            new_version = g_strrstr( response->str, "]" );
   1.307 +            if (new_version!=NULL) {
   1.308 +                ++new_version; /* skip ']' character */
   1.309 +                if ( new_version != NULL ) {
   1.310 +                    gmyth_debug ( "[%s] got MythTV version = %s.\n", 
   1.311 +                            __FUNCTION__, new_version );
   1.312 +                    mythtv_version = (gint)g_ascii_strtoull (new_version, NULL, 10 );
   1.313 +                    /* do reconnection to the socket (socket is closed if the MythTV version was wrong) */
   1.314 +                    gmyth_socket_connect( gmyth_socket, gmyth_socket->hostname, 
   1.315 +                            gmyth_socket->port );
   1.316 +                    new_version = NULL;
   1.317 +                    if ( --max_iterations > 0 ) {
   1.318 +                        g_string_free (payload, TRUE);
   1.319 +                        g_string_free (response, TRUE);
   1.320 +                        goto try_new_version;
   1.321 +                    } else
   1.322 +                        goto done;
   1.323 +                }
   1.324 +            }
   1.325 +        }
   1.326      }
   1.327      
   1.328      /* change the return value to a valid one */
   1.329 @@ -896,10 +914,8 @@
   1.330      }
   1.331  
   1.332  done:
   1.333 -    if ( payload != NULL )
   1.334 -		g_string_free (payload, TRUE);
   1.335 -    if ( response != NULL )
   1.336 -		g_string_free (response, TRUE);
   1.337 +    g_string_free (payload, TRUE);
   1.338 +    g_string_free (response, TRUE);
   1.339  
   1.340      return mythtv_new_version;
   1.341  }
   1.342 @@ -945,8 +961,8 @@
   1.343      gsize bytes_read = 0;
   1.344      gint  len = 0;
   1.345      
   1.346 -		if ( !( gmyth_socket != NULL) )
   1.347 -			return NULL;
   1.348 +    if ( gmyth_socket == NULL )
   1.349 +        return NULL;
   1.350  
   1.351      GIOCondition io_cond;
   1.352  
   1.353 @@ -965,7 +981,11 @@
   1.354       */	
   1.355   
   1.356      if ( gmyth_socket->sd_io_ch->is_readable /*&& !( ( io_cond & G_IO_IN ) == 0 )*/ )
   1.357 -    	io_status = g_io_channel_read_chars (gmyth_socket->sd_io_ch, buffer, MYTH_PROTOCOL_FIELD_SIZE, &bytes_read, &error);
   1.358 +    	io_status = g_io_channel_read_chars (gmyth_socket->sd_io_ch, 
   1.359 +                                             buffer,
   1.360 +                                             MYTH_PROTOCOL_FIELD_SIZE,
   1.361 +                                             &bytes_read, 
   1.362 +                                             &error);
   1.363      else
   1.364      	return g_string_new("");
   1.365  
   1.366 @@ -979,25 +999,22 @@
   1.367  
   1.368      if( (io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0) ) {
   1.369          g_debug ("[%s] Error in mythprotocol response from backend\n", __FUNCTION__);
   1.370 -	str = NULL;
   1.371 -	//return NULL;
   1.372 +    	str = NULL;
   1.373 +	    //return NULL;
   1.374      } else if ( buffer != NULL && strlen(buffer) > 0 ) {
   1.375  
   1.376 -	//io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error );
   1.377 -	/* verify if the input (read) buffer is ready to receive data */
   1.378 -	//io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
   1.379 +    	//io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error );
   1.380 +    	/* verify if the input (read) buffer is ready to receive data */
   1.381 +    	//io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch );
   1.382  	
   1.383 - 	//if ( ( io_cond & G_IO_IN ) != 0 ) {
   1.384 +        //if ( ( io_cond & G_IO_IN ) != 0 ) {
   1.385              //gchar *buffer_aux = NULL;
   1.386  
   1.387          /* removes trailing whitespace */
   1.388          //buffer_aux = g_strstrip (buffer);
   1.389          len = (gint)g_ascii_strtoull ( g_strstrip (buffer), NULL, 10 );
   1.390  
   1.391 -        if (buffer != NULL) {
   1.392 -            g_free (buffer);
   1.393 -            buffer = NULL;
   1.394 -        }
   1.395 +        g_free (buffer);
   1.396              
   1.397          /*            
   1.398          if (buffer_aux != NULL) {
   1.399 @@ -1010,10 +1027,11 @@
   1.400  	
   1.401          bytes_read = 0;
   1.402          if ( !( gmyth_socket != NULL && gmyth_socket->sd_io_ch != NULL) )
   1.403 -	    return NULL;
   1.404 +	        return NULL;
   1.405  
   1.406 -	if ( gmyth_socket->sd_io_ch->is_readable )
   1.407 -            io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer, len, &bytes_read, &error);
   1.408 +        if ( gmyth_socket->sd_io_ch->is_readable )
   1.409 +            io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer,
   1.410 +                                                 len, &bytes_read, &error);
   1.411          else
   1.412              return g_string_new("");
   1.413  		    	
   1.414 @@ -1026,14 +1044,15 @@
   1.415  
   1.416      gmyth_debug ("Response received from backend: ----- {%s}\n", buffer);
   1.417      if ( ( bytes_read != len ) || ( io_status == G_IO_STATUS_ERROR ) )
   1.418 -	str = NULL;
   1.419 +        str = NULL;
   1.420      else
   1.421 -	str = g_string_new (buffer);
   1.422 +        str = g_string_new (buffer);
   1.423  
   1.424      if ( error != NULL ) {
   1.425 -	g_debug( "[%s] Error found receiving response from the IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message );
   1.426 -	str = NULL;
   1.427 -	g_error_free (error);
   1.428 +        g_debug( "[%s] Error found receiving response from the IO channel: (%d, %s)\n",
   1.429 +                __FUNCTION__, error->code, error->message );
   1.430 +        str = NULL;
   1.431 +        g_error_free (error);
   1.432      }
   1.433  
   1.434      g_free (buffer);
   1.435 @@ -1062,11 +1081,11 @@
   1.436      // FIXME: change this implementation!
   1.437      tmp_list = str_list->glist;
   1.438      for(; tmp_list; tmp_list = tmp_list->next) {
   1.439 -	if ( tmp_list->data != NULL ) {
   1.440 -	    g_ptr_array_add(ptr_array, ((GString*)tmp_list->data)->str);
   1.441 -	} else {
   1.442 -	    g_ptr_array_add (ptr_array, "");
   1.443 -	}
   1.444 +        if ( tmp_list->data != NULL ) {
   1.445 +	        g_ptr_array_add(ptr_array, ((GString*)tmp_list->data)->str);
   1.446 +        } else {
   1.447 +            g_ptr_array_add (ptr_array, "");
   1.448 +        }
   1.449      }
   1.450      g_ptr_array_add(ptr_array, NULL); // g_str_joinv() needs a NULL terminated string
   1.451  
   1.452 @@ -1081,10 +1100,13 @@
   1.453      // TODO: implement looping to send remaining data, and add timeout testing!    
   1.454      GString *command = g_string_new(str_array);
   1.455      gmyth_socket_send_command(gmyth_socket, command);
   1.456 +
   1.457      g_string_free (command, TRUE);
   1.458  
   1.459      g_free (str_array);
   1.460 -    g_ptr_array_free (ptr_array, TRUE);
   1.461 +
   1.462 +    /* ptr_array is pointing to data inside str_list->glist */
   1.463 +    g_ptr_array_free (ptr_array, FALSE);
   1.464  
   1.465      return TRUE;
   1.466  }
   1.467 @@ -1098,17 +1120,16 @@
   1.468  gint
   1.469  gmyth_socket_read_stringlist (GMythSocket *gmyth_socket, GMythStringList* str_list)
   1.470  {
   1.471 -    GString *response;
   1.472 -    gchar **str_array = NULL;
   1.473 +    GString *response; 
   1.474      gint i;
   1.475  
   1.476 +	gmyth_string_list_clear_all (str_list);
   1.477 +
   1.478      response = gmyth_socket_receive_response(gmyth_socket);
   1.479 -    if ( response != NULL && response->str != NULL && response->len > 0 )
   1.480 -    {
   1.481 -    	  
   1.482 -	    g_mutex_lock( gmyth_socket->mutex );    
   1.483 +    if ( response != NULL && response->str != NULL && response->len > 0 ) {
   1.484 +        gchar **str_array;
   1.485 +	    g_mutex_lock( gmyth_socket->mutex );
   1.486  	
   1.487 -	    gmyth_string_list_clear_all (str_list);	
   1.488  	    str_array = g_strsplit (response->str, MYTH_SEPARATOR, -1);
   1.489  	
   1.490  	    for ( i=0; i< g_strv_length (str_array); i++ ) {
   1.491 @@ -1117,11 +1138,10 @@
   1.492  	    }
   1.493  	    
   1.494  	    g_mutex_unlock( gmyth_socket->mutex );
   1.495 -	    
   1.496 +        g_strfreev (str_array);
   1.497      }
   1.498  
   1.499      g_string_free (response, TRUE);
   1.500 -    g_strfreev (str_array);
   1.501  
   1.502      return gmyth_string_list_length (str_list);
   1.503  }