4 * @file gmyth/gmyth_socket.c
6 * @brief <p> MythTV socket implementation, according to the MythTV Project
9 * This component provides basic socket functionalities to interact with
13 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
14 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU Lesser General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU Lesser General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include "gmyth_socket.h"
39 #include <glib/gprintf.h>
41 #include <arpa/inet.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <sys/param.h>
52 #include <netinet/in.h>
56 #include <sys/ioctl.h>
58 #include "gmyth_stringlist.h"
59 #include "gmyth_uri.h"
60 #include "gmyth_debug.h"
63 #define MYTH_SEPARATOR "[]:[]"
64 #define MYTH_PROTOCOL_FIELD_SIZE 8
67 * max number of iterations
69 #define MYTHTV_MAX_VERSION_CHECKS 40
71 // FIXME: put this in the right place
72 #define MYTHTV_VERSION_DEFAULT 31
75 * static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
79 * static GStaticRWLock rwlock = G_STATIC_RW_LOCK_INIT;
82 static gchar *local_hostname = NULL;
84 static void gmyth_socket_class_init(GMythSocketClass * klass);
85 static void gmyth_socket_init(GMythSocket * object);
87 static void gmyth_socket_dispose(GObject * object);
88 static void gmyth_socket_finalize(GObject * object);
90 G_DEFINE_TYPE(GMythSocket, gmyth_socket, G_TYPE_OBJECT)
91 static void gmyth_socket_class_init(GMythSocketClass * klass)
93 GObjectClass *gobject_class;
95 gobject_class = (GObjectClass *) klass;
97 gobject_class->dispose = gmyth_socket_dispose;
98 gobject_class->finalize = gmyth_socket_finalize;
102 gmyth_socket_init(GMythSocket * gmyth_socket)
106 * gmyth_socket->local_hostname = NULL;
111 /** Gets the some important address translation info, from the client socket
112 * that will open a connection.
114 * @return gint that represents the error number from getaddrinfo().
117 gmyth_socket_toaddrinfo(const gchar * addr, gint port,
118 struct addrinfo **addrInfo)
120 struct addrinfo hints;
121 gchar *portStr = NULL;
122 gint errorn = EADDRNOTAVAIL;
124 g_return_val_if_fail(addr != NULL, -1);
126 memset(&hints, 0, sizeof(struct addrinfo));
127 hints.ai_family = AF_INET;
128 hints.ai_socktype = SOCK_STREAM;
130 * hints.ai_flags = AI_NUMERICHOST;
134 portStr = g_strdup_printf("%d", port);
138 gmyth_debug("Getting name resolution for: %s, %d\n", addr, port);
140 if ((errorn = getaddrinfo(addr, portStr, &hints, addrInfo)) != 0) {
141 gmyth_debug("[%s] Socket ERROR: %s\n", __FUNCTION__,
142 gai_strerror(errorn));
151 * static gint gmyth_socket_find_match_address_uri( GMythURI* uri, gchar
152 * *address ) { if ( g_ascii_strcasecmp( gmyth_uri_get_host( uri ),
153 * address ) == 0 ) { //gmyth_debug( "Found URI: %s !!!\n",
154 * rui_uri_getvalue(uri) ); return 0; } else { return -1; } }
157 const gchar *PATH_PROC_NET_DEV = "/proc/net/dev";
159 /** Gets the list of all local network interfaces (using the /proc/net/dev directory).
161 * @param current_connections A list with all the network interfaces are valid,
162 * to be applied just like a filter.
163 * @return List with all the local net interfaces.
166 gmyth_socket_get_local_addrs(GList * current_connections)
169 GList *local_addrs = NULL;
172 gchar buffer[256 + 1];
173 gchar ifaddr[20 + 1];
177 s = socket(AF_INET, SOCK_DGRAM, 0);
180 fd = fopen(PATH_PROC_NET_DEV, "r");
181 fgets(buffer, sizeof(buffer) - 1, fd);
182 fgets(buffer, sizeof(buffer) - 1, fd);
186 if (fgets(buffer, sizeof(buffer) - 1, fd) == NULL)
188 sep = strrchr(buffer, ':');
191 while (*ifname == ' ')
195 strcpy(req.ifr_name, ifname);
196 if (ioctl(s, SIOCGIFFLAGS, &req) < 0)
198 if (!(req.ifr_flags & IFF_UP))
200 if (req.ifr_flags & IFF_LOOPBACK)
202 if (ioctl(s, SIOCGIFADDR, &req) < 0)
205 inet_ntoa(((struct sockaddr_in *) &req.ifr_addr)->
206 sin_addr), sizeof(struct ifaddr) - 1);
207 local_addrs = g_list_append(local_addrs, g_strdup(ifaddr));
210 ("( from the /proc/net/dev) Interface name: %s, address: %s\n",
219 * Get only the local addresses from the primary interface
222 gmyth_socket_get_primary_addr(void)
224 gchar *if_eth0 = g_new0(gchar, sizeof(struct ifaddr) - 1);
225 GList *if_tmp = NULL;
227 GList *interfs = gmyth_socket_get_local_addrs(NULL);
229 if (interfs != NULL && (g_list_length(interfs) > 0)) {
230 // get the first occurrence (primary interface)
231 if_tmp = g_list_first(interfs);
234 g_strlcpy(if_eth0, (gchar *) if_tmp->data,
235 sizeof(struct ifaddr) - 1);
240 g_list_free(interfs);
245 /** This function retrieves the local hostname of the
248 * @return GString* get local hostname.
251 gmyth_socket_get_local_hostname(void)
254 gint res = gethostname(hname, 50);
257 gmyth_debug("Error while getting hostname");
258 return g_string_new("default");
261 return g_string_new(hname);
266 if (local_hostname != NULL && strlen(local_hostname) > 0)
267 return g_string_new(local_hostname);
269 gchar *localaddr = NULL;
270 gboolean found_addr = FALSE;
271 struct addrinfo *addr_info_data = NULL,
273 struct sockaddr_in *sa = NULL;
274 gchar localhostname[MAXHOSTNAMELEN];
277 if (gethostname(localhostname, MAXHOSTNAMELEN) != 0) {
278 gmyth_debug("Error on gethostname");
280 localhostname[MAXHOSTNAMELEN - 1] = 0;
283 gmyth_socket_toaddrinfo(localhostname, -1, &addr_info_data);
285 if (err == EADDRNOTAVAIL) {
286 gmyth_debug("[%s] Address (%s) not available. (reason = %d)\n",
287 __FUNCTION__, localhostname, err);
291 g_mutex_lock(gmyth_socket->mutex);
293 addr_info0 = addr_info_data;
295 while (addr_info0 != NULL && addr_info0->ai_addr != NULL &&
296 (sa = (struct sockaddr_in *) addr_info0->ai_addr) != NULL
298 localaddr = inet_ntoa(sa->sin_addr);
300 if (localaddr != NULL && (g_strrstr(localaddr, "127") == NULL)) {
301 str = g_string_new(localaddr);
307 * if (localaddr != NULL) { g_free (localaddr); localaddr = NULL;
311 addr_info0 = addr_info0->ai_next;
314 freeaddrinfo(addr_info_data);
315 addr_info_data = NULL;
317 if (found_addr == FALSE) {
318 gchar *prim_addr = gmyth_socket_get_primary_addr();
320 if (prim_addr != NULL) {
322 ("[%s] Could not determine the local alphanumerical hostname. Setting to %s\n",
323 __FUNCTION__, prim_addr);
325 str = g_string_new(prim_addr);
328 str = g_string_new(localhostname);
332 g_mutex_unlock(gmyth_socket->mutex);
334 if (str != NULL && str->str != NULL)
335 local_hostname = g_strdup(str->str);
342 gmyth_socket_dispose(GObject * object)
344 GMythSocket *gmyth_socket = GMYTH_SOCKET(object);
349 gmyth_socket_close_connection(gmyth_socket);
351 g_free(gmyth_socket->hostname);
353 g_free(local_hostname);
355 local_hostname = NULL;
357 if (gmyth_socket->mutex != NULL) {
358 g_mutex_free(gmyth_socket->mutex);
359 gmyth_socket->mutex = NULL;
362 G_OBJECT_CLASS(gmyth_socket_parent_class)->dispose(object);
366 gmyth_socket_finalize(GObject * object)
368 g_signal_handlers_destroy(object);
370 G_OBJECT_CLASS(gmyth_socket_parent_class)->finalize(object);
373 /** Creates a new instance of GMythSocket.
375 * @return a new instance of GMythSocket.
380 GMythSocket *gmyth_socket =
381 GMYTH_SOCKET(g_object_new(GMYTH_SOCKET_TYPE, NULL));
383 gmyth_socket->mythtv_version = MYTHTV_VERSION_DEFAULT;
385 gmyth_socket->mutex = g_mutex_new();
390 /** Try to open an asynchronous connection to the MythTV backend.
392 * @param fd Socket descriptor.
393 * @param remote Remote address.
394 * @param len Newly created socket length field.
395 * @param timeout Timeval argument with the time interval to timeout before closing.
396 * @param err Error message number.
397 * @return Any numerical value below 0, if an error had been found.
400 gmyth_socket_try_connect(gint fd, struct sockaddr *remote, gint len,
401 struct timeval *timeout, gint * err)
404 * g_return_val_if_fail( timeout != NULL, 0 );
412 saveflags = fcntl(fd, F_GETFL, 0);
414 gmyth_debug("[%s] Problems when getting socket flags on fcntl.\n",
423 if (fcntl(fd, F_SETFL, saveflags | O_NONBLOCK) < 0) {
425 ("[%s] Problems when setting non-blocking using fcntl.\n",
432 * This will return immediately
434 *err = connect(fd, remote, len);
440 if (fcntl(fd, F_SETFL, saveflags) < 0) {
442 ("[%s] Problems when trying to restore flags with fcntl.\n",
449 * return unless the connection was successful or the connect is still
452 if (*err < 0 && back_err != EINPROGRESS) {
454 ("[%s] Connection unsucessfully (it is not in progress).\n",
463 *err = select(FD_SETSIZE, NULL, &fd_w, NULL, timeout);
465 gmyth_debug("[%s] Connection unsucessfull (timed out).\n",
472 * 0 means it timeout out & no fds changed
476 ("[%s] Connection unsucessfull [%d] - 0 means it timeout out & no fds changed\n",
484 * Get the return code from the connect
487 *err = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, (socklen_t *) & len);
490 gmyth_debug("[%s] Connection unsucessfull.\n", __FUNCTION__);
496 * ret=0 means success, otherwise it contains the errno
500 ("[%s] Connection unsucessfull - Couldn't connect to remote host!!!\n",
510 /** Connects to the backend.
512 * @param gmyth_socket The GMythSocket instance.
513 * @param hostname The backend hostname or IP address.
514 * @param port The backend port.
515 * @return TRUE if success, FALSE if error.
520 gmyth_socket_connect(GMythSocket * gmyth_socket,
521 const gchar * hostname, gint port)
523 return gmyth_socket_connect_with_timeout(gmyth_socket, hostname, port,
528 gmyth_socket_connect_with_timeout(GMythSocket * gmyth_socket,
529 const gchar * hostname, gint port,
532 struct addrinfo *addr_info_data = NULL,
536 gint ret_code = 0; /* -1 */
539 * FIXME: add as function parameter
545 gmyth_debug("CONNECTING %s:%d", hostname, port);
547 if (hostname == NULL)
548 gmyth_debug("Invalid hostname parameter!\n");
551 * store hostname and port number
553 gmyth_debug("CONNECTING %s:%d", hostname, port);
555 errno = gmyth_socket_toaddrinfo(hostname, port, &addr_info_data);
557 g_return_val_if_fail(addr_info_data != NULL
558 && hostname != NULL, FALSE);
561 * hack to avoid deleting the hostname when gmyth_socket->hostname ==
564 tmp_str = gmyth_socket->hostname;
566 gmyth_socket->hostname = g_strdup(hostname);
567 gmyth_socket->port = port;
571 for (addr_info0 = addr_info_data; addr_info0;
572 addr_info0 = addr_info_data->ai_next) {
574 * init socket descriptor
577 g_debug ("FAMILY: %d, TYPE: %d, PROTOCOL: %d",
578 addr_info0->ai_family,
579 addr_info0->ai_socktype,
580 addr_info0->ai_protocol);
582 socket(addr_info0->ai_family, addr_info0->ai_socktype,
583 addr_info0->ai_protocol);
585 if (gmyth_socket->sd < 0)
588 struct timeval *timeout_val = g_new0(struct timeval, 1);
591 timeout_val->tv_sec = timeout;
592 timeout_val->tv_usec = 0;
594 timeout_val->tv_sec = 5;
595 timeout_val->tv_usec = 100;
598 if (gmyth_socket_try_connect
599 (gmyth_socket->sd, (struct sockaddr *) addr_info0->ai_addr,
600 addr_info0->ai_addrlen, timeout_val, &ret_code) < 0) {
601 gmyth_debug("[%s] Error connecting to backend!\n",
603 if (ret_code == ETIMEDOUT)
604 gmyth_debug("[%s]\tBackend host unreachable!\n",
607 close(gmyth_socket->sd);
608 gmyth_socket->sd = -1;
609 gmyth_debug("ERROR: %s\n", gai_strerror(ret_code));
617 * only will be reached if none of the error above occurred
622 freeaddrinfo(addr_info_data);
623 addr_info_data = NULL;
625 if (gmyth_socket->sd_io_ch != NULL) {
626 g_io_channel_unref(gmyth_socket->sd_io_ch);
627 gmyth_socket->sd_io_ch = NULL;
631 memset(&ling, 0, sizeof(struct linger));
636 setsockopt(gmyth_socket->sd, SOL_SOCKET, SO_LINGER, &ling,
637 sizeof(struct linger));
640 gmyth_debug("[%s] Setting connection unsucessfull.\n",
647 gmyth_socket->sd_io_ch = g_io_channel_unix_new(gmyth_socket->sd);
649 g_io_channel_set_close_on_unref(gmyth_socket->sd_io_ch, TRUE);
650 // g_io_channel_set_encoding (gmyth_socket->sd_io_ch, NULL, NULL );
652 GIOFlags flags = g_io_channel_get_flags(gmyth_socket->sd_io_ch);
655 * unset the nonblock flag
657 flags &= ~G_IO_FLAG_NONBLOCK;
659 * unset the nonblocking stuff for some time, because GNUTLS doesn't
662 g_io_channel_set_flags(gmyth_socket->sd_io_ch, flags, NULL);
664 ret = (ret_code == 0) ? TRUE : FALSE;
668 gmyth_debug("GMythSocket error - return code error!");
673 /** Gets the GIOChannel associated to the given GMythSocket.
675 * @param gmyth_socket The GMythSocket instance.
678 gmyth_socket_get_io_channel(GMythSocket * gmyth_socket)
680 g_return_val_if_fail(gmyth_socket != NULL, NULL);
682 return gmyth_socket->sd_io_ch;
685 /** Verifies if the socket is able to read.
687 * @param gmyth_socket The GMythSocket instance.
688 * @return TRUE if the socket is able to read, FALSE if not.
691 gmyth_socket_is_able_to_read(GMythSocket * gmyth_socket)
696 * verify if the input (read) buffer is ready to receive data
698 GIOCondition io_cond =
699 g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
701 if ((io_cond & G_IO_IN) == 0) {
702 gmyth_debug("[%s] IO channel is not able to send data!\n",
711 /** Verifies if the socket is able to write.
713 * @param gmyth_socket The GMythSocket instance.
714 * @return TRUE if the socket is able to write, FALSE if not.
717 gmyth_socket_is_able_to_write(GMythSocket * gmyth_socket)
722 * verify if the input (read) buffer is ready to receive data
724 GIOCondition io_cond =
725 g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
727 if (((io_cond & G_IO_OUT) == 0) || ((io_cond & G_IO_HUP) == 0)) {
728 gmyth_debug("[%s] IO channel is not able to send data!\n",
737 /** Sends a command to the backend.
739 * @param gmyth_socket the GMythSocket instance.
740 * @param command The string command to be sent.
743 gmyth_socket_send_command(GMythSocket * gmyth_socket, GString * command)
747 GIOStatus io_status = G_IO_STATUS_NORMAL;
749 // GIOCondition io_cond;
750 GError *error = NULL;
752 gchar *buffer = NULL;
754 gsize bytes_written = 0;
756 g_return_val_if_fail(gmyth_socket->sd_io_ch != NULL, FALSE);
758 if (command == NULL || (command->len <= 0) || command->str == NULL) {
759 gmyth_debug("[%s] Invalid NULL command parameter!\n",
765 g_mutex_lock(gmyth_socket->mutex);
766 gmyth_debug("Sending command to backend: %s\n", command->str);
768 buffer = g_strnfill(BUFLEN, ' ');
769 g_snprintf(buffer, MYTH_PROTOCOL_FIELD_SIZE + 1, "%-8d", command->len);
771 command = g_string_prepend(command, buffer);
774 * write bytes to socket
777 g_io_channel_write_chars(gmyth_socket->sd_io_ch, command->str,
778 command->len, &bytes_written, &error);
781 if ((io_status == G_IO_STATUS_ERROR) || (bytes_written <= 0)) {
782 gmyth_debug("[%s] Error while writing to socket", __FUNCTION__);
784 } else if (bytes_written < command->len) {
785 gmyth_debug("[%s] Not all data was written socket", __FUNCTION__);
789 io_status = g_io_channel_flush(gmyth_socket->sd_io_ch, &error);
791 if ((bytes_written != command->len)
792 || (io_status == G_IO_STATUS_ERROR)) {
794 ("[%s] Some problem occurred when sending data to the socket\n",
800 g_mutex_unlock(gmyth_socket->mutex);
804 ("[%s] Error found reading data from IO channel: (%d, %s)\n",
805 __FUNCTION__, error->code, error->message);
816 /** Starts Mythtv protocol level connection. Checks Mythtv protocol version
817 * supported by the backend and send the "ANN" command.
819 * @param gmyth_socket the GMythSocket instance.
820 * @param hostname_backend The backend hostname or IP address.
821 * @param port The backend port to connect.
822 * @param blocking_client A flag to choose between blocking and non-blocking
823 * @param with_events Sets the connection flag to receive events.
824 * backend connection.
827 gmyth_socket_connect_to_backend_and_events(GMythSocket * gmyth_socket,
828 const gchar * hostname_backend,
830 gboolean blocking_client,
831 gboolean with_events)
833 if (!gmyth_socket_connect(gmyth_socket, hostname_backend, port)) {
834 gmyth_debug("[%s] Could not open socket to backend machine [%s]\n",
835 __FUNCTION__, hostname_backend);
839 if (gmyth_socket_check_protocol_version(gmyth_socket)) {
841 GString *base_str = g_string_new("");
842 GString *hostname = NULL;
844 hostname = gmyth_socket_get_local_hostname();
845 if (hostname == NULL) {
847 ("Hostname not available, setting to n800frontend\n");
848 hostname = g_string_new("n800frontend");
851 g_string_printf(base_str, "ANN %s %s %u",
852 (blocking_client ? "Playback" : "Monitor"),
853 hostname->str, with_events);
855 gmyth_socket_send_command(gmyth_socket, base_str);
856 result = gmyth_socket_receive_response(gmyth_socket);
858 if (result != NULL) {
859 gmyth_debug("Response received from backend: %s", result->str);
860 g_string_free(result, TRUE);
863 g_string_free(hostname, TRUE);
864 g_string_free(base_str, TRUE);
868 gmyth_debug("[%s] GMythSocket could not connect to the backend",
874 /** Starts Mythtv protocol level connection. Checks Mythtv protocol version
875 * supported by the backend and send the "ANN" command.
877 * @param gmyth_socket the GMythSocket instance.
878 * @param hostname_backend The backend hostname or IP address.
879 * @param port The backend port to connect.
880 * @param blocking_client A flag to choose between blocking and non-blocking
883 gmyth_socket_connect_to_backend(GMythSocket * gmyth_socket,
884 const gchar * hostname_backend, gint port,
885 gboolean blocking_client)
887 if (!gmyth_socket_connect_to_backend_and_events
888 (gmyth_socket, hostname_backend, port, blocking_client, FALSE)) {
889 gmyth_debug("Could not open socket to backend machine [%s]\n",
898 /** Starts Mythtv protocol level connection. Checks Mythtv protocol version
899 * supported by the backend and send the "ANN" command.
901 * @param gmyth_socket the GMythSocket instance.
902 * @param hostname_backend The backend hostname or IP address.
903 * @param port The backend port to connect.
904 * @param blocking_client A flag to choose between blocking and non-blocking
907 gmyth_socket_connect_to_backend_events(GMythSocket * gmyth_socket,
908 const gchar * hostname_backend,
909 gint port, gboolean blocking_client)
911 if (!gmyth_socket_connect_to_backend_and_events
912 (gmyth_socket, hostname_backend, port, blocking_client, TRUE)) {
914 ("Could not open socket to backend machine in order to receive events [%s]\n",
922 /** Closes the socket connection to the backend.
924 * @param gmyth_socket The GMythSocket instance.
927 gmyth_socket_close_connection(GMythSocket * gmyth_socket)
930 * if ( gmyth_socket->sd != -1 ) { close (gmyth_socket->sd);
931 * gmyth_socket->sd = -1; }
934 if (gmyth_socket->sd_io_ch != NULL) {
935 g_io_channel_shutdown(gmyth_socket->sd_io_ch, TRUE, NULL);
936 g_io_channel_unref(gmyth_socket->sd_io_ch);
937 gmyth_socket->sd_io_ch = NULL;
938 gmyth_socket->sd = -1;
944 /** Try the MythTV version numbers, and get the version returned by
945 * the possible REJECT message, in order to contruct a new
946 * MythTV version request.
948 * @param gmyth_socket The GMythSocket instance.
949 * @param mythtv_version The Mythtv protocol version to be tested
951 * @return The actual MythTV the client is connected to.
954 gmyth_socket_check_protocol_version_number(GMythSocket * gmyth_socket,
957 GString *response = NULL;
958 GString *payload = NULL;
960 gint mythtv_new_version = MYTHTV_CANNOT_NEGOTIATE_VERSION;
961 guint max_iterations = MYTHTV_MAX_VERSION_CHECKS;
963 assert(gmyth_socket);
966 payload = g_string_new("MYTH_PROTO_VERSION");
967 g_string_append_printf(payload, " %d", mythtv_version);
969 gmyth_socket_send_command(gmyth_socket, payload);
970 response = gmyth_socket_receive_response(gmyth_socket);
972 if (response == NULL) {
973 gmyth_debug("[%s] Check protocol version error! Not answered!",
979 res = g_str_has_prefix(response->str, "ACCEPT");
981 gmyth_debug("[%s] Protocol version request error: %s",
982 __FUNCTION__, response->str);
984 * get the version number returned by the REJECT message
986 if ((res = g_str_has_prefix(response->str, "REJECT")) == TRUE) {
987 gchar *new_version = NULL;
989 new_version = g_strrstr(response->str, "]");
990 if (new_version != NULL) {
991 ++new_version; /* skip ']' character */
992 if (new_version != NULL) {
993 gmyth_debug("[%s] got MythTV version = %s.\n",
994 __FUNCTION__, new_version);
996 (gint) g_ascii_strtoull(new_version, NULL, 10);
998 * do reconnection to the socket (socket is closed if
999 * the MythTV version was wrong)
1001 gmyth_socket_connect(gmyth_socket,
1002 gmyth_socket->hostname,
1003 gmyth_socket->port);
1005 if (--max_iterations > 0) {
1006 g_string_free(payload, TRUE);
1007 g_string_free(response, TRUE);
1008 goto try_new_version;
1017 * change the return value to a valid one
1020 mythtv_new_version = mythtv_version;
1021 gmyth_socket->mythtv_version = mythtv_new_version;
1025 g_string_free(payload, TRUE);
1026 g_string_free(response, TRUE);
1028 return mythtv_new_version;
1031 /** Verifies if the Mythtv backend supported the GMyth supported version.
1033 * @param gmyth_socket The GMythSocket instance.
1034 * @return TRUE if supports, FALSE if not.
1037 gmyth_socket_check_protocol_version(GMythSocket * gmyth_socket)
1039 return ((gmyth_socket->mythtv_version =
1040 gmyth_socket_check_protocol_version_number(gmyth_socket,
1041 MYTHTV_VERSION_DEFAULT))
1042 != MYTHTV_CANNOT_NEGOTIATE_VERSION);
1045 /** Returns the Mythtv backend supported version.
1047 * @param gmyth_socket The GMythSocket instance.
1048 * @return The actual MythTV version number.
1051 gmyth_socket_get_protocol_version(GMythSocket * gmyth_socket)
1053 return gmyth_socket->mythtv_version;
1056 /** Receives a backend answer after a gmyth_socket_send_command_call ().
1058 * @param gmyth_socket The GMythSocket instance.
1059 * @return The response received, or NULL if error or nothing was received.
1062 gmyth_socket_receive_response(GMythSocket * gmyth_socket)
1064 GIOStatus io_status = G_IO_STATUS_NORMAL;
1065 GError *error = NULL;
1066 gchar *buffer = NULL;
1068 GString *str = NULL;
1070 gsize bytes_read = 0;
1073 if (gmyth_socket == NULL)
1076 GIOCondition io_cond;
1079 * verify if the input (read) buffer is ready to receive data
1081 g_mutex_lock(gmyth_socket->mutex);
1083 buffer = g_strnfill(MYTH_PROTOCOL_FIELD_SIZE, ' ');
1084 if (NULL == gmyth_socket->sd_io_ch) {
1085 gmyth_socket_connect(gmyth_socket, gmyth_socket->hostname,
1086 gmyth_socket->port);
1089 io_cond = g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
1091 * if ( NULL == gmyth_socket->sd_io_ch->read_buf || ( NULL ==
1092 * gmyth_socket->sd_io_ch->read_buf->str ) ) gmyth_socket->sd_io_ch =
1093 * g_io_channel_unix_new( gmyth_socket->sd );
1096 if (gmyth_socket->sd_io_ch->is_readable /* && !( ( io_cond & G_IO_IN )
1099 g_io_channel_read_chars(gmyth_socket->sd_io_ch, buffer,
1100 MYTH_PROTOCOL_FIELD_SIZE, &bytes_read,
1103 return g_string_new("");
1106 * verify if the input (read) buffer is ready to receive data
1108 io_cond = g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
1110 // if ( ( io_cond & G_IO_IN ) == 0 )
1113 gmyth_debug("[%s] Bytes read = %d\n", __FUNCTION__, bytes_read);
1115 if ((io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0)) {
1116 gmyth_debug("[%s] Error in mythprotocol response from backend\n",
1120 } else if (buffer != NULL && strlen(buffer) > 0) {
1122 // io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error
1125 * verify if the input (read) buffer is ready to receive data
1127 // io_cond = g_io_channel_get_buffer_condition(
1128 // gmyth_socket->sd_io_ch );
1130 // if ( ( io_cond & G_IO_IN ) != 0 ) {
1131 // gchar *buffer_aux = NULL;
1134 * removes trailing whitespace
1136 // buffer_aux = g_strstrip (buffer);
1137 len = (gint) g_ascii_strtoull(g_strstrip(buffer), NULL, 10);
1142 * if (buffer_aux != NULL) { g_free (buffer_aux); buffer_aux =
1146 buffer = g_new0(gchar, len + 1);
1149 if (!(gmyth_socket != NULL && gmyth_socket->sd_io_ch != NULL))
1152 if (gmyth_socket->sd_io_ch->is_readable)
1154 g_io_channel_read_chars(gmyth_socket->sd_io_ch, buffer,
1155 len, &bytes_read, &error);
1157 return g_string_new("");
1159 buffer[bytes_read] = '\0';
1163 g_mutex_unlock(gmyth_socket->mutex);
1164 // g_static_rw_lock_reader_unlock (&rwlock);
1166 gmyth_debug("Response received from backend: ----- {%s}\n", buffer);
1167 if ((bytes_read != len) || (io_status == G_IO_STATUS_ERROR))
1170 str = g_string_new(buffer);
1172 if (error != NULL) {
1174 ("[%s] Error found receiving response from the IO channel: (%d, %s)\n",
1175 __FUNCTION__, error->code, error->message);
1177 g_error_free(error);
1184 /** Format a Mythtv command from the str_list entries and send it to backend.
1186 * @param gmyth_socket The GMythSocket instance.
1187 * @param str_list The string list to form the command
1188 * @return TRUE if command was sent, FALSE if any error happens.
1191 gmyth_socket_write_stringlist(GMythSocket * gmyth_socket,
1192 GMythStringList * str_list)
1195 GList *tmp_list = NULL;
1196 GPtrArray *ptr_array = NULL;
1197 gchar *str_array = NULL;
1199 g_mutex_lock(gmyth_socket->mutex);
1200 // g_static_rw_lock_writer_lock (&rwlock);
1202 ptr_array = g_ptr_array_sized_new(g_list_length(str_list->glist));
1204 // FIXME: change this implementation!
1205 tmp_list = str_list->glist;
1206 for (; tmp_list; tmp_list = tmp_list->next) {
1207 if (tmp_list->data != NULL) {
1208 g_ptr_array_add(ptr_array, ((GString *) tmp_list->data)->str);
1210 g_ptr_array_add(ptr_array, "");
1213 g_ptr_array_add(ptr_array, NULL); // g_str_joinv() needs a NULL
1214 // terminated string
1216 str_array = g_strjoinv(MYTH_SEPARATOR, (gchar **) (ptr_array->pdata));
1218 g_mutex_unlock(gmyth_socket->mutex);
1219 // g_static_rw_lock_writer_unlock (&rwlock);
1221 gmyth_debug("[%s] Sending socket request: %s\n", __FUNCTION__,
1224 // Sends message to backend
1225 // TODO: implement looping to send remaining data, and add timeout
1227 GString *command = g_string_new(str_array);
1229 gmyth_socket_send_command(gmyth_socket, command);
1231 g_string_free(command, TRUE);
1236 * ptr_array is pointing to data inside str_list->glist
1238 g_ptr_array_free(ptr_array, TRUE);
1244 * Receives a backend command response and split it into the given string
1245 * list. @param gmyth_socket The GMythSocket instance. @param str_list
1246 * the string list to be filled. @return The number of received strings.
1249 gmyth_socket_read_stringlist(GMythSocket * gmyth_socket,
1250 GMythStringList * str_list)
1255 gmyth_string_list_clear_all(str_list);
1257 response = gmyth_socket_receive_response(gmyth_socket);
1258 if (response != NULL && response->str != NULL && response->len > 0) {
1261 g_mutex_lock(gmyth_socket->mutex);
1263 str_array = g_strsplit(response->str, MYTH_SEPARATOR, -1);
1265 for (i = 0; i < g_strv_length(str_array); i++) {
1266 // if ( str_array[i] != NULL && strlen( str_array[i] ) > 0 )
1267 gmyth_string_list_append_char_array(str_list, str_array[i]);
1270 g_mutex_unlock(gmyth_socket->mutex);
1271 g_strfreev(str_array);
1274 g_string_free(response, TRUE);
1276 return gmyth_string_list_length(str_list);
1279 /** Formats a Mythtv protocol command based on str_list and sends it to
1280 * the connected backend. The backend response is overwritten into str_list.
1282 * @param gmyth_socket The GMythSocket instance.
1283 * @param str_list The string list to be sent, and on which the answer
1285 * @return TRUE if command was sent and an answer was received, FALSE if any
1289 gmyth_socket_sendreceive_stringlist(GMythSocket * gmyth_socket,
1290 GMythStringList * str_list)
1292 gmyth_socket_write_stringlist(gmyth_socket, str_list);
1294 return gmyth_socket_read_stringlist(gmyth_socket, str_list);