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 }