PageRenderTime 89ms CodeModel.GetById 3ms app.highlight 74ms RepoModel.GetById 1ms app.codeStats 1ms

/lib/cmyth/libcmyth/socket.c

https://github.com/smuehlmann/xbmc-pvr-addons
C | 3106 lines | 1888 code | 171 blank | 1047 comment | 349 complexity | d98aff2b8d2094b7470edaadec28fa1e MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 *  Copyright (C) 2004-2012, Eric Lund
   3 *  http://www.mvpmc.org/
   4 *
   5 *  This library is free software; you can redistribute it and/or
   6 *  modify it under the terms of the GNU Lesser General Public
   7 *  License as published by the Free Software Foundation; either
   8 *  version 2.1 of the License, or (at your option) any later version.
   9 *
  10 *  This library is distributed in the hope that it will be useful,
  11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 *  Lesser General Public License for more details.
  14 *
  15 *  You should have received a copy of the GNU Lesser General Public
  16 *  License along with this library; if not, write to the Free Software
  17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 */
  19
  20/*
  21 * socket.c - functions to handle low level socket interactions with a
  22 *            MythTV frontend.
  23 */
  24#include <stdlib.h>
  25#include <stdio.h>
  26#include <ctype.h>
  27#include <string.h>
  28#include <errno.h>
  29#include <sys/types.h>
  30#include <cmyth_local.h>
  31
  32#define __UNSIGNED	"0123456789"
  33#define __SIGNED	"+-0123456789"
  34#define __check_num(num)	(strspn((num), __SIGNED) == strlen((num)))
  35#define __check_unum(num)	(strspn((num), __UNSIGNED) == strlen((num)))
  36
  37/*
  38 * cmyth_send_message(cmyth_conn_t conn, char *request)
  39 *
  40 * Scope: PRIVATE (mapped to __cmyth_send_message)
  41 *
  42 * Description
  43 *
  44 * Send a myth protocol on the socket indicated by 'conn'.  The
  45 * message sent has the form:
  46 *
  47 *   <length><request>
  48 *
  49 * Where <length> is the 8 character, space padded, left justified
  50 * ASCII representation of the number of bytes in the message
  51 * (including <length>) and <request> is the string specified in the
  52 * 'request' argument.
  53 *
  54 * Return Value:
  55 *
  56 * Success: 0
  57 *
  58 * Failure: -(errno)
  59 */
  60int
  61cmyth_send_message(cmyth_conn_t conn, char *request)
  62{
  63	/*
  64	 * For now this is unimplemented.
  65	 */
  66	char *msg;
  67	int reqlen;
  68	int written = 0;
  69	int w;
  70	struct timeval tv;
  71	fd_set fds;
  72
  73	cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__);
  74	if (!conn) {
  75		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n",
  76			  __FUNCTION__);
  77		return -EBADF;
  78	}
  79	if (conn->conn_fd < 0) {
  80		cmyth_dbg(CMYTH_DBG_ERROR, "%s: not connected\n",
  81			  __FUNCTION__);
  82		conn->conn_hang = 1;
  83		return -EBADF;
  84	}
  85	if (!request) {
  86		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no request\n", __FUNCTION__);
  87		return -EINVAL;
  88	}
  89	reqlen = strlen(request);
  90	msg = malloc(9 + reqlen);
  91	if (!msg) {
  92		cmyth_dbg(CMYTH_DBG_ERROR,
  93			  "%s: cannot allocate message buffer\n",
  94			  __FUNCTION__);
  95		return -ENOMEM;
  96	}
  97	sprintf(msg, "%-8d%s", reqlen, request);
  98	cmyth_dbg(CMYTH_DBG_PROTO, "%s: sending message '%s'\n",
  99		  __FUNCTION__, msg);
 100	reqlen += 8;
 101	do {
 102		tv.tv_sec = 10;
 103		tv.tv_usec = 0;
 104		FD_ZERO(&fds);
 105		FD_SET(conn->conn_fd, &fds);
 106		if (select((int)conn->conn_fd+1, NULL, &fds, NULL, &tv) == 0) {
 107			conn->conn_hang = 1;
 108			return -ETIMEDOUT;
 109		} else {
 110			conn->conn_hang = 0;
 111		}
 112		w = send(conn->conn_fd, msg + written, reqlen - written, 0);
 113		if (w < 0) {
 114			cmyth_dbg(CMYTH_DBG_ERROR, "%s: write() failed (%d)\n",
 115				  __FUNCTION__, errno);
 116			free(msg);
 117			conn->conn_hang = 1;
 118			return -errno;
 119		}
 120		written += w;
 121	} while (written < reqlen);
 122
 123	free(msg);
 124	return 0;
 125}
 126
 127/*
 128 * cmyth_rcv_length(cmyth_conn_t conn)
 129 *
 130 * Scope: PRIVATE (mapped to __cmyth_rcv_length)
 131 *
 132 * Description
 133 *
 134 * Receive the <length> portion of a MythTV Protocol message
 135 * on the socket specified by 'conn'
 136 *
 137 * Return Value:
 138 *
 139 * Success: A length value > 0 and < 100000000
 140 *
 141 * Failure: -(errno)
 142 */
 143int
 144cmyth_rcv_length(cmyth_conn_t conn)
 145{
 146	char buf[16];
 147	int rtot = 0;
 148	int r;
 149	int hangcount = 0;
 150	int ret;
 151	struct timeval tv;
 152	fd_set fds;
 153
 154	cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__);
 155	if (!conn) {
 156		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n",
 157			  __FUNCTION__);
 158		return -EBADF;
 159	}
 160	if (conn->conn_fd < 0) {
 161		cmyth_dbg(CMYTH_DBG_ERROR, "%s: not connected\n",
 162			  __FUNCTION__);
 163		return -EBADF;
 164	}
 165	buf[8] ='\0';
 166	do {
 167		tv.tv_sec = 10;
 168		tv.tv_usec = 0;
 169		FD_ZERO(&fds);
 170		FD_SET(conn->conn_fd, &fds);
 171		r = select((int)conn->conn_fd+1, &fds, NULL, NULL, &tv);
 172		if (r > 0) {
 173			conn->conn_hang = 0;
 174			r = recv(conn->conn_fd, &buf[rtot], 8 - rtot, 0);
 175		}
 176		if (r == 0) {
 177			conn->conn_hang = 1;
 178			if (++hangcount > 2)
 179				return -ETIMEDOUT;
 180		}
 181		if (r < 0) {
 182			cmyth_dbg(CMYTH_DBG_ERROR, "%s: read() failed (%d)\n",
 183				  __FUNCTION__, errno);
 184			conn->conn_hang = 1;
 185			return -EBADF;
 186		}
 187		rtot += r;
 188	} while (rtot < 8);
 189	ret = atoi(buf);
 190	cmyth_dbg(CMYTH_DBG_PROTO, "%s: buffer is '%s' ret = %d\n",
 191		  __FUNCTION__, buf, ret);
 192	return ret;
 193}
 194
 195/*
 196 * cmyth_conn_refill(cmyth_conn_t conn, int len)
 197 *
 198 * Scope: PRIVATE (static)
 199 *
 200 * Description
 201 *
 202 * FIll up the buffer in the connection 'conn' with up to 'len' bytes
 203 * of data.
 204 *
 205 * Return Value:
 206 *
 207 * Success: 0
 208 *
 209 * Failure: -errno
 210 */
 211static int
 212cmyth_conn_refill(cmyth_conn_t conn, int len)
 213{
 214	int r;
 215	int total = 0;
 216	unsigned char *p;
 217	struct timeval tv;
 218	fd_set fds;
 219
 220	if (!conn) {
 221		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n",
 222			  __FUNCTION__);
 223		return -EINVAL;
 224	}
 225	if (!conn->conn_buf) {
 226		cmyth_dbg(CMYTH_DBG_ERROR, "%s: connection has no buffer\n",
 227			  __FUNCTION__);
 228		return -EINVAL;
 229	}
 230	if ((unsigned)len > conn->conn_buflen) {
 231		len = conn->conn_buflen;
 232	}
 233	p = conn->conn_buf;
 234	while (len > 0) {
 235		tv.tv_sec = 10;
 236		tv.tv_usec = 0;
 237		FD_ZERO(&fds);
 238		FD_SET(conn->conn_fd, &fds);
 239		if ((r = select((int)conn->conn_fd+1, &fds, NULL, NULL, &tv)) == 0) {
 240			conn->conn_hang = 1;
 241			return -ETIMEDOUT;
 242		} else if (r > 0) {
 243			conn->conn_hang = 0;
 244			r = recv(conn->conn_fd, p, len, 0);
 245		}
 246		if (r <= 0) {
 247			if (total == 0) {
 248				cmyth_dbg(CMYTH_DBG_ERROR,
 249					  "%s: read failed (%d)\n",
 250					  __FUNCTION__, errno);
 251				conn->conn_hang = 1;
 252				if ( r == 0 )
 253					return -1 * EBADF;
 254				else
 255					return -1 * errno;
 256			}
 257			/*
 258			 * There were bytes read before the error, use them and
 259			 * then report the error next time.
 260			 */
 261			break;
 262		}
 263		total += r;
 264		len -= r;
 265		p += r;
 266	}
 267	conn->conn_pos = 0;
 268	conn->conn_len = total;
 269	return 0;
 270}
 271
 272/*
 273 * cmyth_rcv_string(cmyth_conn_t conn, char *buf, int buflen, int count)
 274 *
 275 * Scope: PRIVATE (mapped to __cmyth_rcv_length)
 276 *
 277 * Description
 278 *
 279 * Receive a string token from a list of tokens in a MythTV Protocol
 280 * message.  Tokens in MythTV Protocol messages are separated by the
 281 * string: []:[] or terminated by running out of message.  Up to
 282 * 'count' Bytes will be consumed from the socket specified by 'conn'
 283 * (stopping when a separator is seen or 'count' is exhausted).  Of
 284 * these, the first 'buflen' bytes will be copied into 'buf'.  If
 285 * a full 'buflen' bytes is read, 'buf' will not be terminated with a
 286 * '\0', otherwise it will be.  If an error is encountered and
 287 * 'err' is not NULL, an indication of the nature of the error will be
 288 * recorded by placing an error code in the location pointed to by
 289 * 'err'.  If all goes well, 'err' wil be set to 0.
 290 *
 291 * Return Value:
 292 *
 293 * A value >=0 indicating the number of bytes consumed.
 294 */
 295int
 296cmyth_rcv_string(cmyth_conn_t conn, int *err, char *buf, int buflen, int count)
 297{
 298	static char separator[] = "[]:[]";
 299	int consumed = 0;
 300	int placed = 0;
 301	char *state = separator;
 302	char *sep_start = NULL;
 303	int tmp;
 304
 305	if (!err) {
 306		err = &tmp;
 307	}
 308
 309	if (count < 0) {
 310		/*
 311		 * Strings are terminated by either the next separator or the end of the payload. If
 312		 * the last string requested in the payload is empty the count will be zero. In this case
 313		 * we should return an empty string rather than an error.
 314		 *
 315		 * http://www.mythtv.org/wiki/Myth_Protocol#Packet_Data_Format
 316		 */
 317		*err = EINVAL;
 318		return 0;
 319	}
 320
 321	if (!conn) {
 322		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n",
 323			  __FUNCTION__);
 324		*err = EBADF;
 325		return 0;
 326	}
 327	if (conn->conn_fd < 0) {
 328		cmyth_dbg(CMYTH_DBG_ERROR, "%s: not connected\n",
 329			  __FUNCTION__);
 330		*err = EBADF;
 331		return 0;
 332	}
 333	if (!conn->conn_buf) {
 334		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection buffer\n",
 335			  __FUNCTION__);
 336		*err = EBADF;
 337		return 0;
 338	}
 339	if (!buf) {
 340		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no output buffer\n",
 341			  __FUNCTION__);
 342		*err = EBADF;
 343		return 0;
 344	}
 345
 346	while (1) {
 347		if (consumed >= count) {
 348			/*
 349			 * We have consumed all the characters we were
 350			 * asked to from the stream.  Force a refill
 351			 * on the next call, and return 'consumed'.
 352			 */
 353			conn->conn_pos = conn->conn_len = 0;
 354			if (buflen > placed) {
 355				buf[placed] = '\0';
 356			}
 357			break;
 358		}
 359
 360		if (conn->conn_pos >= conn->conn_len) {
 361			/*
 362			 * We have run out of (or never had any) bytes
 363			 * from the connection.  Refill the buffer.
 364			 */
 365			*err = cmyth_conn_refill(conn, count - consumed);
 366			if (*err < 0) {
 367				*err = -1 * (*err);
 368				break;
 369			}
 370		}
 371
 372		if (sep_start && conn->conn_buf[conn->conn_pos] != (unsigned char)*state) {
 373			/*
 374			 * Reset separator in case the current character does not match
 375			 * the expected part of the separator. This needs to take place
 376			 * before checking if the current character starts a new separator.
 377			 * (To resolve issues with strings that look like [[]:[])
 378			 */
 379			sep_start = NULL;
 380			state = separator;
 381		}
 382
 383		if (conn->conn_buf[conn->conn_pos] == (unsigned char)*state) {
 384			/*
 385			 * We matched the next (possibly first) step
 386			 * of a separator, advance to the next.
 387			 */
 388			if ((state == separator) && (placed < buflen)) {
 389				sep_start = &buf[placed];
 390			}
 391			++state;
 392		}
 393
 394		if (placed < buflen) {
 395			/*
 396			 * This character goes in the output buffer,
 397			 * put it there.
 398			 */
 399			buf[placed++] = conn->conn_buf[conn->conn_pos];
 400		}
 401		++conn->conn_pos;
 402		++consumed;
 403
 404		if (*state == '\0') {
 405			/*
 406			 * Reached the end of a separator, terminate
 407			 * the returned buffer at the beginning of the
 408			 * separator (if it fell within the buffer)
 409			 * and return.
 410			 */
 411			if (sep_start) {
 412				*sep_start = '\0';
 413			} else if (buflen > placed) {
 414				buf[placed] = '\0';
 415			}
 416			break;
 417		}
 418	}
 419	cmyth_dbg(CMYTH_DBG_PROTO, "%s: string received '%s'\n",
 420		  __FUNCTION__, buf);
 421	return consumed;
 422}
 423
 424/*
 425 * cmyth_rcv_uint32(cmyth_conn_t conn, int *err, uint32_t *buf,
 426 *                      int count)
 427 *
 428 * Scope: PRIVATE (mapped to __cmyth_rcv_uint32)
 429 *
 430 * Description
 431 *
 432 * Receive an unsigned (32 bit) integer token from a list of
 433 * tokens in a MythTV Protocol message.  Tokens in MythTV Protocol
 434 * messages are separated by the string: []:[] or terminated by
 435 * running out of message.  Up to 'count' Bytes will be consumed from
 436 * the socket specified by 'conn' (stopping when a separator is seen
 437 * or 'count' is exhausted).  The unsigned long long integer value of
 438 * the token is placed in the location pointed to by 'buf'.  If an
 439 * error is encountered and 'err' is not NULL, an indication of the
 440 * nature of the error will be recorded by placing an error code in
 441 * the location pointed to by 'err'.  If all goes well, 'err' wil be
 442 * set to 0.
 443 *
 444 * Return Value:
 445 *
 446 * A value >=0 indicating the number of bytes consumed.
 447 *
 448 * Error Codes:
 449 *
 450 * In addition to system call error codes, the following errors may be
 451 * placed in 'err':
 452 *
 453 * ERANGE       The token received is too large to fit in an unsinged
 454 *              long long integer
 455 *
 456 * EINVAL       The token received is not numeric or is signed
 457 */
 458int
 459cmyth_rcv_uint32(cmyth_conn_t conn, int *err, uint32_t *buf, int count)
 460{
 461	char num[32];
 462	char *num_p = num;
 463	uint64_t val = 0;
 464	uint64_t limit = UINT32_MAX;
 465	int consumed;
 466	int tmp;
 467
 468	*buf = 0;
 469
 470	if (!err) {
 471		err = &tmp;
 472	}
 473
 474	if (count <= 0) {
 475		*err = EINVAL;
 476		return 0;
 477	}
 478
 479	*err = 0;
 480	consumed = cmyth_rcv_string(conn, err, num, sizeof(num), count);
 481	if (*err) {
 482		cmyth_dbg(CMYTH_DBG_ERROR,
 483			  "%s: cmyth_rcv_string() failed (%d)\n",
 484			  __FUNCTION__, consumed);
 485		return consumed;
 486	}
 487	while (*num_p) {
 488		if (!isdigit(*num_p)) {
 489			cmyth_dbg(CMYTH_DBG_ERROR,
 490				  "%s: received illegal integer: '%s'\n",
 491				  __FUNCTION__, num);
 492			*err = EINVAL;
 493			return consumed;
 494		}
 495		/*
 496		 * If we are about to make 'val' bigger than 32bit,
 497		 * it is ERANGE.
 498		 */
 499		if (val > limit && *num_p > '5') {
 500			*err = ERANGE;
 501			return consumed;
 502		}
 503		val *= 10;
 504		val += ((*num_p) - '0');
 505		num_p++;
 506	}
 507
 508	/*
 509	 * Got a result, return it.
 510	 */
 511	*buf = (uint32_t)val;
 512	return consumed;
 513}
 514
 515/*
 516 * cmyth_rcv_int32(cmyth_conn_t conn, int *err, int32_t *buf, int count)
 517 *
 518 * Scope: PRIVATE (mapped to __cmyth_rcv_int32)
 519 *
 520 * Description
 521 *
 522 * Receive a signed (32 bit) integer token from a list of
 523 * tokens in a MythTV Protocol message.  Tokens in MythTV Protocol
 524 * messages are separated by the string: []:[] or terminated by
 525 * running out of message.  Up to 'count' Bytes will be consumed from
 526 * the socket specified by 'conn' (stopping when a separator is seen
 527 * or 'count' is exhausted).  The long long integer value of the token
 528 * is placed in the location pointed to by 'buf'.  If an error is
 529 * encountered and 'err' is not NULL, an indication of the nature of
 530 * the error will be recorded by placing an error code in the location
 531 * pointed to by 'err'.  If all goes well, 'err' wil be set to 0.
 532 *
 533 * Return Value:
 534 *
 535 * A value >=0 indicating the number of bytes consumed.
 536 *
 537 * Error Codes:
 538 *
 539 * In addition to system call error codes, the following errors may be
 540 * placed in 'err':
 541 *
 542 * ERANGE       The token received is too large to fit in a
 543 *              long long integer
 544 *
 545 * EINVAL       The token received is not numeric
 546 */
 547int
 548cmyth_rcv_int32(cmyth_conn_t conn, int *err, int32_t *buf, int count)
 549{
 550	char num[32];
 551	char *num_p = num;
 552	uint64_t val = 0;
 553	int sign = 1;
 554	uint64_t limit = INT32_MAX;
 555	int consumed;
 556	int tmp;
 557
 558	if (!err) {
 559		err = &tmp;
 560	}
 561	if (count <= 0) {
 562		*err = EINVAL;
 563		return 0;
 564	}
 565	*err = 0;
 566	consumed = cmyth_rcv_string(conn, err, num, sizeof(num), count);
 567	if (*err) {
 568		cmyth_dbg(CMYTH_DBG_ERROR,
 569			  "%s: cmyth_rcv_string() failed (%d)\n",
 570			  __FUNCTION__, consumed);
 571		return consumed;
 572	}
 573	if (*num_p && (*num_p == '-')) {
 574		++num_p;
 575		sign = -1;
 576	}
 577	while (*num_p) {
 578		if (!isdigit(*num_p)) {
 579			cmyth_dbg(CMYTH_DBG_ERROR,
 580				  "%s: received illegal integer: '%s'\n",
 581				  __FUNCTION__, num);
 582			*err = EINVAL;
 583			return consumed;
 584		}
 585		val *= 10;
 586		val += ((*num_p) - '0');
 587		/*
 588		 * Check and make sure we are still under the limit (this is
 589		 * an absolute value limit, sign will be applied later).
 590		 */
 591		if (val > limit) {
 592			cmyth_dbg(CMYTH_DBG_ERROR,
 593				  "%s: long out of range: '%s'\n",
 594				  __FUNCTION__, num);
 595			*err = ERANGE;
 596			return consumed;
 597		}
 598		num_p++;
 599	}
 600
 601	/*
 602	 * Got a result, return it.
 603	 */
 604	*buf = (int32_t)(sign * val);
 605
 606	return consumed;
 607}
 608
 609/*
 610 * cmyth_rcv_okay(cmyth_conn_t conn)
 611 *
 612 * Scope: PRIVATE (mapped to __cmyth_rcv_okay)
 613 *
 614 * Description
 615 *
 616 * Receive an OK response on a connection.
 617 * This is here to easily handle simple acknowledgement from
 618 * the server.
 619 *
 620 * Return Value:
 621 *
 622 * Success: 0
 623 *
 624 * Failure: -(errno)
 625 */
 626int
 627cmyth_rcv_okay(cmyth_conn_t conn)
 628{
 629	int count, consumed;
 630	char buf[3];
 631	char tmp[1024];
 632	int err, ret;
 633
 634	count = cmyth_rcv_length(conn);
 635	if (count < 0) {
 636		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed\n",
 637			  __FUNCTION__);
 638		return count;
 639	}
 640	consumed = cmyth_rcv_string(conn, &err, buf, sizeof(buf), count);
 641	if (err) {
 642		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed\n",
 643			  __FUNCTION__);
 644		return -err;
 645	}
 646	count -= consumed;
 647	cmyth_toupper_string(buf);
 648	ret = (strncmp(buf, "OK",2) == 0) ? 0 : -1;
 649	if (count > 0) {
 650		cmyth_dbg(CMYTH_DBG_INFO,
 651			  "%s: did not consume everything\n",
 652			  __FUNCTION__);
 653		while(count > 0 && err == 0) {
 654			consumed = cmyth_rcv_data(conn, &err, (unsigned char*)tmp, sizeof(tmp) - 1, count);
 655			cmyth_dbg(CMYTH_DBG_DEBUG, "%s: leftover data: count %i, read %i, errno %i\n", __FUNCTION__, count, consumed, err);
 656			count -= consumed;
 657		}
 658	}
 659	return ret;
 660}
 661
 662/*
 663 * cmyth_rcv_feedback(cmyth_conn_t conn, char *fb)
 664 *
 665 * Scope: PRIVATE (mapped to __cmyth_rcv_feedback)
 666 *
 667 * Description
 668 *
 669 * Receive user specified response on a connection.
 670 * This is here to easily handle simple acknowledgement from
 671 * the server.
 672 *
 673 * Return Value:
 674 *
 675 * Success: 0
 676 *
 677 * Failure: -(errno)
 678 */
 679int
 680cmyth_rcv_feedback(cmyth_conn_t conn, char *fb, int fblen)
 681{
 682	int count, consumed;
 683	char buf[8];
 684	char tmp[1024];
 685	int err, ret;
 686
 687	count = cmyth_rcv_length(conn);
 688	if (count < 0) {
 689		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed\n",
 690			  __FUNCTION__);
 691		return count;
 692	}
 693	consumed = cmyth_rcv_string(conn, &err, buf, sizeof(buf), count);
 694	if (err) {
 695		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed\n",
 696			  __FUNCTION__);
 697		return -err;
 698	}
 699	count -= consumed;
 700	ret = (strncmp(buf, fb, fblen) == 0) ? 0 : -1;
 701	if (count > 0) {
 702		cmyth_dbg(CMYTH_DBG_INFO,
 703			  "%s: did not consume everything\n",
 704			  __FUNCTION__);
 705		while(count > 0 && err == 0) {
 706			consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count);
 707			count -= consumed;
 708			cmyth_dbg(CMYTH_DBG_DEBUG, "%s: leftover data %s\n", __FUNCTION__, tmp);
 709		}
 710	}
 711	return ret;
 712}
 713
 714/*
 715 * cmyth_rcv_version(cmyth_conn_t conn, unsigned long *vers)
 716 *
 717 * Scope: PRIVATE (mapped to __cmyth_rcv_version)
 718 *
 719 * Description
 720 *
 721 * Receive an ACCEPT <version> or REJECT <version> response on a
 722 * connection.  If 'vers' is non-NULL it points to the location where
 723 * the received version number should be placed.  If it is NULL, this
 724 * routine will still read the version but it will throw it away.
 725 *
 726 * Return Value:
 727 *
 728 * Success: 0
 729 *
 730 * Failure: -(errno)
 731 */
 732int
 733cmyth_rcv_version(cmyth_conn_t conn, uint32_t *vers)
 734{
 735	int len;
 736	int consumed;
 737	char buf[8];
 738	uint32_t tmp_vers;
 739	int err;
 740
 741	if (!vers) {
 742		vers = &tmp_vers;
 743	}
 744	len = cmyth_rcv_length(conn);
 745	if (len < 0) {
 746		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed\n",
 747			  __FUNCTION__);
 748		return len;
 749	}
 750	consumed = cmyth_rcv_string(conn, &err, buf, sizeof(buf), len);
 751	if (err) {
 752		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed\n",
 753			  __FUNCTION__);
 754		return -err;
 755	}
 756	len -= consumed;
 757	/*
 758	 * The string we just consumed was either "ACCEPT" or "REJECT".  In
 759	 * either case, the number following it is the correct version, and
 760	 * we use it as an unsigned long.
 761	 */
 762	consumed = cmyth_rcv_uint32(conn, &err, vers, len);
 763	if (consumed < len) {
 764		cmyth_dbg(CMYTH_DBG_ERROR,
 765			  "%s: did not consume everything %d < %d\n",
 766			  __FUNCTION__, consumed, len);
 767	}
 768	return -err;
 769}
 770
 771/*
 772 * cmyth_rcv_int8(cmyth_conn_t conn, int *err, int8_t *buf, int count)
 773 *
 774 * Scope: PRIVATE (mapped to __cmyth_rcv_int8)
 775 *
 776 * Description
 777 *
 778 * Receive a byte (signed 8 bit) integer token from a list of tokens
 779 * in a MythTV Protocol message.  Tokens in MythTV Protocol messages
 780 * are separated by the string: []:[] or terminated by running out of
 781 * message.  Up to 'count' Bytes will be consumed from the socket
 782 * specified by 'conn' (stopping when a separator is seen or 'count'
 783 * is exhausted).  The byte integer value of the token is placed in
 784 * the location pointed to by 'buf'.  If an error is encountered and
 785 * 'err' is not NULL, an indication of the nature of the error will be
 786 * recorded by placing an error code in the location pointed to by
 787 * 'err'.  If all goes well, 'err' wil be set to 0.
 788 *
 789 * Return Value:
 790 *
 791 * Success / Failure: A value >=0 indicating the number of bytes
 792 *                    consumed.
 793 *
 794 * Error Codes:
 795 *
 796 * In addition to system call error codes, the following errors may be
 797 * placed in 'err' by this function:
 798 *
 799 * ERANGE       The token received is too large to fit in a byte integer
 800 *
 801 * EINVAL       The token received is not numeric
 802 */
 803int
 804cmyth_rcv_int8(cmyth_conn_t conn, int *err, int8_t *buf, int count)
 805{
 806	int32_t val;
 807	int consumed;
 808	int tmp;
 809
 810	if (!err) {
 811		err = &tmp;
 812	}
 813	if (count <= 0) {
 814		*err = EINVAL;
 815		return 0;
 816	}
 817	consumed = cmyth_rcv_int32(conn, err, &val, count);
 818	if (*err) {
 819		cmyth_dbg(CMYTH_DBG_ERROR,
 820			  "%s: cmyth_rcv_long() failed (%d)\n",
 821			  __FUNCTION__, consumed);
 822		return consumed;
 823	}
 824	if ((val > 127) || (val < -128)) {
 825		cmyth_dbg(CMYTH_DBG_ERROR, "%s: value doesn't fit: '%"PRId32"'\n",
 826			  __FUNCTION__, val);
 827		*err = ERANGE;
 828		return consumed;
 829	}
 830	*err = 0;
 831	*buf = (int8_t)val;
 832	return consumed;
 833}
 834
 835/*
 836 * cmyth_rcv_int16(cmyth_conn_t conn, int *err, int16_t *buf, int count)
 837 *
 838 * Scope: PRIVATE (mapped to __cmyth_rcv_int16)
 839 *
 840 * Description
 841 *
 842 * Receive a signed (16 bit) integer token from a list of tokens
 843 * in a MythTV Protocol message.  Tokens in MythTV Protocol messages
 844 * are separated by the string: []:[] or terminated by running out of
 845 * message.  Up to 'count' Bytes will be consumed from the socket
 846 * specified by 'conn' (stopping when a separator is seen or 'count'
 847 * is exhausted).  The short integer value of the token is placed in
 848 * the location pointed to by 'buf'.  If an error is encountered and
 849 * 'err' is not NULL, an indication of the nature of the error will be
 850 * recorded by placing an error code in the location pointed to by
 851 * 'err'.  If all goes well, 'err' wil be set to 0.
 852 *
 853 * Return Value:
 854 *
 855 * A value >=0 indicating the number of bytes consumed.
 856 *
 857 * Error Codes:
 858 *
 859 * In addition to system call error codes, the following errors may be
 860 * placed in 'err':
 861 *
 862 * ERANGE       The token received is too large to fit in a short integer
 863 *
 864 * EINVAL       The token received is not numeric
 865 */
 866int
 867cmyth_rcv_int16(cmyth_conn_t conn, int *err, int16_t *buf, int count)
 868{
 869	int32_t val;
 870	int consumed;
 871	int tmp;
 872
 873	if (!err) {
 874		err = &tmp;
 875	}
 876	if (count <= 0) {
 877		*err = EINVAL;
 878		return 0;
 879	}
 880	consumed = cmyth_rcv_int32(conn, err, &val, count);
 881	if (*err) {
 882		cmyth_dbg(CMYTH_DBG_ERROR,
 883			  "%s: cmyth_rcv_long() failed (%d)\n",
 884			  __FUNCTION__, consumed);
 885		return consumed;
 886	}
 887	if ((val > 32767) || (val < -32768)) {
 888		cmyth_dbg(CMYTH_DBG_ERROR, "%s: value doesn't fit: '%"PRId32"'\n",
 889			  __FUNCTION__, val);
 890		*err = ERANGE;
 891		return consumed;
 892	}
 893	*err = 0;
 894	*buf = (int16_t)val;
 895	return consumed;
 896}
 897
 898/*
 899 * cmyth_rcv_old_int64(cmyth_conn_t conn, int *err, long long *buf, int count)
 900 *
 901 * Scope: PRIVATE (mapped to __cmyth_rcv_long)
 902 *
 903 * Description
 904 *
 905 * Receive a long long (signed 64 bit) integer token from a list of tokens
 906 * in a MythTV Protocol message.  Tokens in MythTV Protocol messages
 907 * are separated by the string: []:[] or terminated by running out of
 908 * message.  Up to 'count' Bytes will be consumed from the socket
 909 * specified by 'conn' (stopping when a separator is seen or 'count'
 910 * is exhausted).  The long integer value of the token is placed in
 911 * the location pointed to by 'buf'.  If an error is encountered and
 912 * 'err' is not NULL, an indication of the nature of the error will be
 913 * recorded by placing an error code in the location pointed to by
 914 * 'err'.  If all goes well, 'err' wil be set to 0.
 915 *
 916 * Return Value:
 917 *
 918 * A value >=0 indicating the number of bytes consumed.
 919 *
 920 * Error Codes:
 921 *
 922 * In addition to system call error codes, the following errors may be
 923 * placed in 'err':
 924 *
 925 * ERANGE       The token received is too large to fit in a long integer
 926 *
 927 * EINVAL       The token received is not numeric
 928 */
 929int
 930cmyth_rcv_old_int64(cmyth_conn_t conn, int *err, int64_t *buf, int count)
 931{
 932	int64_t val;
 933	int consumed;
 934	int tmp;
 935	uint32_t hi, lo;
 936
 937	if (!err) {
 938		err = &tmp;
 939	}
 940
 941	if (count <= 0) {
 942		*err = EINVAL;
 943		return 0;
 944	}
 945
 946	consumed = cmyth_rcv_int32(conn, err, (int32_t*)&hi, count);
 947	if (*err) {
 948		cmyth_dbg(CMYTH_DBG_ERROR,
 949			  "%s: cmyth_rcv_u_long() failed (%d)\n",
 950			  __FUNCTION__, consumed);
 951		return consumed;
 952	}
 953	consumed += cmyth_rcv_int32(conn, err, (int32_t*)&lo, count-consumed);
 954	if (*err) {
 955		cmyth_dbg(CMYTH_DBG_ERROR,
 956			  "%s: cmyth_rcv_u_long() failed (%d)\n",
 957			  __FUNCTION__, consumed);
 958		return consumed;
 959	}
 960	val = (((int64_t)hi) << 32) | ((int64_t)(lo & 0xffffffff));
 961
 962	*err = 0;
 963	*buf = val;
 964
 965	return consumed;
 966}
 967
 968/*
 969 * cmyth_rcv_new_int64(cmyth_conn_t conn, int *err, long long *buf, int count)
 970 *
 971 * Scope: PRIVATE (mapped to __cmyth_rcv_long)
 972 *
 973 * Description
 974 *
 975 * Receive a long long (signed 64 bit) integer token from a list of tokens
 976 * in a MythTV Protocol message.  Tokens in MythTV Protocol messages
 977 * are separated by the string: []:[] or terminated by running out of
 978 * message.  Up to 'count' Bytes will be consumed from the socket
 979 * specified by 'conn' (stopping when a separator is seen or 'count'
 980 * is exhausted).  The long integer value of the token is placed in
 981 * the location pointed to by 'buf'.  If an error is encountered and
 982 * 'err' is not NULL, an indication of the nature of the error will be
 983 * recorded by placing an error code in the location pointed to by
 984 * 'err'.  If all goes well, 'err' wil be set to 0.
 985 *
 986 * As of protocol version 57, Myth now sends a single 64bit string instead
 987 * of 2 32bit strings when sending proginfo data.  This does not seem to
 988 * apply uniformly though. For instance 'ANN FILETRANSFER' still uses
 989 * the old method
 990 *
 991 * Return Value:
 992 *
 993 * A value >=0 indicating the number of bytes consumed.
 994 *
 995 * Error Codes:
 996 *
 997 * In addition to system call error codes, the following errors may be
 998 * placed in 'err':
 999 *
1000 * ERANGE       The token received is too large to fit in a long integer
1001 *
1002 * EINVAL       The token received is not numeric
1003 */
1004int
1005cmyth_rcv_new_int64(cmyth_conn_t conn, int *err, int64_t *buf, int count,
1006		    int forced)
1007{
1008	char num[32];
1009	char *num_p = num;
1010	uint64_t val = 0;
1011	int sign = 1;
1012	uint64_t limit = INT64_MAX;
1013	int consumed;
1014	int tmp;
1015
1016	/*
1017	 * Between protocols 57 and 66, not all messages used the new
1018	 * format for 64-bit values.
1019	 */
1020	if ((conn->conn_version < 57) ||
1021	    ((conn->conn_version < 66) && !forced)) {
1022		return cmyth_rcv_old_int64(conn, err, buf, count);
1023	}
1024
1025	if (!err) {
1026		err = &tmp;
1027	}
1028	if (count <= 0) {
1029		*err = EINVAL;
1030		return 0;
1031	}
1032	*err = 0;
1033	consumed = cmyth_rcv_string(conn, err, num, sizeof(num), count);
1034	if (*err) {
1035		cmyth_dbg(CMYTH_DBG_ERROR,
1036			"%s: cmyth_rcv_string() failed (%d)\n",
1037			__FUNCTION__, consumed);
1038		return consumed;
1039	}
1040	if (*num_p && (*num_p == '-')) {
1041		++num_p;
1042		sign = -1;
1043	}
1044	while (*num_p) {
1045		if (!isdigit(*num_p)) {
1046			cmyth_dbg(CMYTH_DBG_ERROR,
1047				  "%s: received illegal integer: '%s'\n",
1048				  __FUNCTION__, num);
1049			*err = EINVAL;
1050			return consumed;
1051		}
1052		val *= 10;
1053		val += ((*num_p) - '0');
1054		/*
1055		 * Check and make sure we are still under the limit (this is
1056		 * an absolute value limit, sign will be applied later).
1057		 */
1058		if (val > limit) {
1059			cmyth_dbg(CMYTH_DBG_ERROR,
1060				  "%s: long long out of range: '%s'\n",
1061				  __FUNCTION__, num);
1062			*err = ERANGE;
1063			return consumed;
1064		}
1065		num_p++;
1066	}
1067
1068	/*
1069	 * Got a result, return it.
1070	 */
1071	*buf = (int64_t)(sign * val);
1072
1073	return consumed;
1074}
1075
1076/*
1077 * cmyth_rcv_uint8(cmyth_conn_t conn, int *err, uint8_t *buf, int count)
1078 *
1079 * Scope: PRIVATE (mapped to __cmyth_rcv_uint8)
1080 *
1081 * Description
1082 *
1083 * Receive an unsigned byte (8 bit) integer token from a list of
1084 * tokens in a MythTV Protocol message.  Tokens in MythTV Protocol
1085 * messages are separated by the string: []:[] or terminated by
1086 * running out of message.  Up to 'count' Bytes will be consumed from
1087 * the socket specified by 'conn' (stopping when a separator is seen
1088 * or 'count' is exhausted).  The unsigned byte integer value of the
1089 * token is placed in the location pointed to by 'buf'.  If an error
1090 * is encountered and 'err' is not NULL, an indication of the nature
1091 * of the error will be recorded by placing an error code in the
1092 * location pointed to by 'err'.  If all goes well, 'err' wil be set
1093 * to 0.
1094 *
1095 * Return Value:
1096 *
1097 * A value >=0 indicating the number of bytes consumed.
1098 *
1099 * Error Codes:
1100 *
1101 * In addition to system call error codes, the following errors may be
1102 * placed in 'err':
1103 *
1104 * ERANGE       The token received is too large to fit in an
1105 #              unsigned byte integer
1106 *
1107 * EINVAL       The token received is not numeric or is signed
1108 */
1109int
1110cmyth_rcv_uint8(cmyth_conn_t conn, int *err, uint8_t *buf, int count)
1111{
1112	uint32_t val;
1113	int consumed;
1114	int tmp;
1115
1116	if (!err) {
1117		err = &tmp;
1118	}
1119	if (count <= 0) {
1120		*err = EINVAL;
1121		return 0;
1122	}
1123	consumed = cmyth_rcv_uint32(conn, err, &val, count);
1124	if (*err) {
1125		cmyth_dbg(CMYTH_DBG_ERROR,
1126			  "%s: cmyth_rcv_ulong() failed (%d)\n",
1127			  __FUNCTION__, consumed);
1128		return consumed;
1129	}
1130	if (val > 255) {
1131		cmyth_dbg(CMYTH_DBG_ERROR, "%s: value doesn't fit: '%llu'\n",
1132			  __FUNCTION__, val);
1133		*err = ERANGE;
1134		return consumed;
1135	}
1136	*err = 0;
1137	*buf = (uint8_t)val;
1138	return consumed;
1139}
1140
1141/*
1142 * cmyth_rcv_uint16(cmyth_conn_t conn, int *err, uint16_t *buf, int count)
1143 *
1144 * Scope: PRIVATE (mapped to __cmyth_rcv_uint16)
1145 *
1146 * Description
1147 *
1148 * Receive an unsigned (16 bit) integer token from a list of
1149 * tokens in a MythTV Protocol message.  Tokens in MythTV Protocol
1150 * messages are separated by the string: []:[] or terminated by
1151 * running out of message.  Up to 'count' Bytes will be consumed from
1152 * the socket specified by 'conn' (stopping when a separator is seen
1153 * or 'count' is exhausted).  The unsigned short integer value of the
1154 * token is placed in the location pointed to by 'buf'.  If an error
1155 * is encountered and 'err' is not NULL, an indication of the nature
1156 * of the error will be recorded by placing an error code in the
1157 * location pointed to by 'err'.  If all goes well, 'err' wil be set
1158 * to 0.
1159 *
1160 * Return Value:
1161 *
1162 * A value >=0 indicating the number of bytes consumed.
1163 *
1164 * Error Codes:
1165 *
1166 * In addition to system call error codes, the following errors may be
1167 * placed in 'err':
1168 *
1169 * ERANGE       The token received is too large to fit in an
1170 *              unsinged short integer
1171 *
1172 * EINVAL       The token received is not numeric or is signed
1173 */
1174int
1175cmyth_rcv_uint16(cmyth_conn_t conn, int *err, uint16_t *buf, int count)
1176{
1177	uint32_t val;
1178	int consumed;
1179	int tmp;
1180
1181	if (!err) {
1182		err = &tmp;
1183	}
1184	if (count <= 0) {
1185		*err = EINVAL;
1186		return 0;
1187	}
1188	consumed = cmyth_rcv_uint32(conn, err, &val, count);
1189	if (*err) {
1190		cmyth_dbg(CMYTH_DBG_ERROR,
1191			  "%s: cmyth_rcv_ulong() failed (%d)\n",
1192			  __FUNCTION__, consumed);
1193		return consumed;
1194	}
1195	if (val > 65535) {
1196		cmyth_dbg(CMYTH_DBG_ERROR, "%s: value doesn't fit: '%llu'\n",
1197			  __FUNCTION__, val);
1198		*err = ERANGE;
1199		return consumed;
1200	}
1201	*err = 0;
1202	*buf = (uint16_t)val;
1203	return consumed;
1204}
1205
1206/*
1207 * cmyth_rcv_timestamp(cmyth_conn_t conn, int *err, cmyth_timestamp_t buf,
1208 *                     int count)
1209 *
1210 * Scope: PRIVATE (mapped to __cmyth_rcv_timestamp)
1211 *
1212 * Description
1213 *
1214 * Receive a timestamp in international format from a list of
1215 * tokens in a MythTV Protocol message.  A time stamp is formatted
1216 * as follows:
1217 *
1218 *     <YYYY>-<MM>-<DD>T<HH>:<MM>:<SS>
1219 *
1220 * Tokens in MythTV Protocol messages are separated by the string:
1221 * []:[] or terminated by running out of message.  Up to 'count' Bytes
1222 * will be consumed from the socket specified by 'conn' (stopping when
1223 * a separator is seen or 'count' is exhausted).  The timestamp
1224 * structure specified in 'buf' will be filled out.  If an error is
1225 * encountered and 'err' is not NULL, an indication of the nature of
1226 * the error will be recorded by placing an error code in the location
1227 * pointed to by 'err'.  If all goes well, 'err' wil be set to 0.
1228 *
1229 * Return Value:
1230 *
1231 * A value >=0 indicating the number of bytes consumed.
1232 *
1233 * Error Codes:
1234 *
1235 * In addition to system call error codes, the following errors may be
1236 * placed in 'err':
1237 *
1238 * ERANGE       The token received did not parse into a timestamp
1239 *
1240 * EINVAL       The token received is not numeric or is signed
1241 */
1242int
1243cmyth_rcv_timestamp(cmyth_conn_t conn, int *err, cmyth_timestamp_t *ts,
1244		    int count)
1245{
1246	int consumed;
1247	char tbuf[CMYTH_TIMESTAMP_LEN + 1];
1248	int tmp;
1249
1250	if (!err) {
1251		err = &tmp;
1252	}
1253	if (count <= 0) {
1254		*err = EINVAL;
1255		return 0;
1256	}
1257	*err = 0;
1258	tbuf[CMYTH_TIMESTAMP_LEN] = '\0';
1259	consumed = cmyth_rcv_string(conn, err, tbuf,
1260				    CMYTH_TIMESTAMP_LEN, count);
1261	if (*err) {
1262		cmyth_dbg(CMYTH_DBG_ERROR,
1263			  "%s: cmyth_rcv_string() failed (%d)\n",
1264			  __FUNCTION__, *err);
1265		return consumed;
1266	}
1267
1268	/*
1269	 * Allow for the timestamp to be empty in the case of livetv
1270	 */
1271	if ((strlen(tbuf) == 1) && (tbuf[0] == ' '))
1272		return consumed;
1273
1274	if (strlen(tbuf) == 0)
1275		return consumed;
1276
1277	if (*ts)
1278		ref_release(*ts);
1279
1280	*ts = cmyth_timestamp_from_string(tbuf);
1281	if (*ts == NULL) {
1282		cmyth_dbg(CMYTH_DBG_ERROR,
1283			  "%s: cmyth_timestamp_from_string() failed\n",
1284			  __FUNCTION__);
1285		*err = -EINVAL;
1286	}
1287	return consumed;
1288}
1289
1290
1291/*
1292 * cmyth_rcv_datetime(cmyth_conn_t conn, int *err, cmyth_timestamp_t buf,
1293 *                     int count)
1294 *
1295 * Scope: PRIVATE (mapped to __cmyth_rcv_datetime)
1296 *
1297 * Description
1298 *
1299 * Receive a datetime as an unsigned integer -- number of seconds
1300 * since Jan 1, 1970.
1301 *
1302 * Tokens in MythTV Protocol messages are separated by the string:
1303 * []:[] or terminated by running out of message.  Up to 'count' Bytes
1304 * will be consumed from the socket specified by 'conn' (stopping when
1305 * a separator is seen or 'count' is exhausted).  The timestamp
1306 * structure specified in 'buf' will be filled out.  If an error is
1307 * encountered and 'err' is not NULL, an indication of the nature of
1308 * the error will be recorded by placing an error code in the location
1309 * pointed to by 'err'.  If all goes well, 'err' wil be set to 0.
1310 *
1311 * Return Value:
1312 *
1313 * A value >=0 indicating the number of bytes consumed.
1314 *
1315 * Error Codes:
1316 *
1317 * In addition to system call error codes, the following errors may be
1318 * placed in 'err':
1319 *
1320 * ERANGE       The token received did not parse into a datetime
1321 *
1322 * EINVAL       The token received is not numeric or is signed
1323 */
1324int
1325cmyth_rcv_datetime(cmyth_conn_t conn, int *err, cmyth_timestamp_t *ts,
1326		   int count)
1327{
1328	int consumed;
1329	char tbuf[CMYTH_INT32_LEN + 1];
1330	int tmp;
1331
1332	if (!err) {
1333		err = &tmp;
1334	}
1335	if (count <= 0) {
1336		*err = EINVAL;
1337		return 0;
1338	}
1339	*err = 0;
1340	tbuf[CMYTH_INT32_LEN] = '\0';
1341	consumed = cmyth_rcv_string(conn, err, tbuf, CMYTH_INT32_LEN, count);
1342	if (*err) {
1343		cmyth_dbg(CMYTH_DBG_ERROR,
1344			  "%s: cmyth_rcv_string() failed (%d)\n",
1345			  __FUNCTION__, *err);
1346		return consumed;
1347	}
1348	if (*ts)
1349		ref_release(*ts);
1350	*ts = cmyth_timestamp_from_unixtime((time_t)atoi(tbuf));
1351	if (*ts == NULL) {
1352		cmyth_dbg(CMYTH_DBG_ERROR,
1353			  "%s: cmyth_datetime_from_string() failed\n",
1354			  __FUNCTION__);
1355		*err = -EINVAL;
1356	}
1357	return consumed;
1358}
1359
1360static void
1361cmyth_proginfo_parse_url(cmyth_proginfo_t p)
1362{
1363	static const char service[]="myth://";
1364	char *host = NULL;
1365	char *port = NULL;
1366	char *path = NULL;
1367	char *placed = NULL;
1368	char *eaddr = NULL;
1369	int ip6 = 0;
1370
1371        if (!p || ! p->proginfo_url ||
1372	    (!strcmp(p->proginfo_url, "none")) ||
1373	    (!strcmp(p->proginfo_url, " "))) {
1374		cmyth_dbg(CMYTH_DBG_ERROR,
1375			  "%s: proginfo or url was NULL, p = %p, url = %p\n",
1376			  __FUNCTION__, p, p ? p->proginfo_url : NULL);
1377		return;
1378	}
1379	cmyth_dbg(CMYTH_DBG_DEBUG, "%s: url is: '%s'\n",
1380		  __FUNCTION__, p->proginfo_url);
1381	path = p->proginfo_url;
1382	if (strncmp(p->proginfo_url, service, sizeof(service) - 1) == 0) {
1383		/*
1384		 * The URL starts with myth://.  The rest looks like
1385		 * <host>:<port>/<filename>.
1386		 */
1387		host = p->proginfo_url + strlen(service);
1388
1389		/* JLB: ipv6 host looks like [...] */
1390		eaddr = strchr(host, '/');
1391		if (!eaddr) {
1392			eaddr = host + strlen(host) + 1;
1393		}
1394		if ((unsigned char)*host == '[') {
1395			placed = strchr(host,']');
1396			if (placed && placed < eaddr && (unsigned char)*(++placed) == ':') {
1397				ip6 = 1;
1398				port = placed;
1399			}
1400			else {
1401				goto out;
1402			}
1403		}
1404		else {
1405			port = strchr(host, ':');
1406		}
1407		if (!port || port > eaddr) {
1408			/*
1409			 * This does not seem to be a proper URL, so
1410			 * just assume it is a filename, and get out.
1411			 */
1412			host = NULL;
1413			port = NULL;
1414			goto out;
1415		}
1416		port = port + 1;
1417		path = strchr(port, '/');
1418		if (!path) {
1419			/*
1420			 * This does not seem to be a proper URL, so
1421			 * just assume it is a filename, and get out.
1422			 */
1423			goto out;
1424		}
1425	}
1426
1427    out:
1428	if (host && port) {
1429		char tmp;
1430	  if (ip6 == 1) {
1431			++host;
1432			tmp = *(port - 2);
1433			*(port - 2) = '\0';
1434			if (p->proginfo_host)
1435				ref_release(p->proginfo_host);
1436			p->proginfo_host = ref_strdup(host);
1437			*(port - 2) = tmp;
1438		}
1439		else {
1440			tmp = *(port - 1);
1441			*(port - 1) = '\0';
1442			if (p->proginfo_host)
1443				ref_release(p->proginfo_host);
1444			p->proginfo_host = ref_strdup(host);
1445			*(port - 1) = tmp;
1446		}
1447		if (path) {
1448			tmp = *(path);
1449			*(path) = '\0';
1450			p->proginfo_port = atoi(port);
1451			*(path) = tmp;
1452		}
1453		else {
1454			p->proginfo_port = atoi(port);
1455		}
1456	} else {
1457		if (p->proginfo_host)
1458			ref_release(p->proginfo_host);
1459		p->proginfo_host = ref_strdup(p->proginfo_hostname);
1460		p->proginfo_port = 6543;
1461	}
1462	if (p->proginfo_pathname)
1463		ref_release(p->proginfo_pathname);
1464	p->proginfo_pathname = ref_strdup(path);
1465}
1466
1467/*
1468 * cmyth_rcv_proginfo(cmyth_conn_t conn, cmyth_proginfo_t buf, int count)
1469 *
1470 * Scope: PRIVATE (mapped to __cmyth_rcv_proginfo)
1471 *
1472 * Description
1473 *
1474 * Receive a program information structure from a list of tokens in a
1475 * MythTV Protocol message.  Tokens in MythTV Protocol messages are
1476 * separated by the string: []:[] or terminated by running out of
1477 * message.  Up to 'count' Bytes will be consumed from the socket
1478 * specified by 'conn' (stopping when a separator is seen or 'count'
1479 * is exhausted).  The proginfo structure specified in 'buf' will be
1480 * filled out.  If an error is encountered and 'err' is not NULL, an
1481 * indication of the nature of the error will be recorded by placing
1482 * an error code in the location pointed to by 'err'.  If all goes
1483 * well, 'err' wil be set to 0.
1484 *
1485 * Return Value:
1486 *
1487 * A value >=0 indicating the number of bytes consumed.
1488 *
1489 * Error Codes:
1490 *
1491 * In addition to system call error codes, the following errors may be
1492 * placed in 'err':
1493 *
1494 * ERANGE       The token received did not parse into a program
1495 *              information structure
1496 *
1497 * EINVAL       The token received is not numeric or is signed
1498 */
1499int
1500cmyth_rcv_proginfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf,
1501		   int count)
1502{
1503	int consumed;
1504	int total = 0;
1505	char *failed = NULL;
1506	char tmp_str[32768];
1507
1508	if (count <= 0) {
1509		*err = EINVAL;
1510		return 0;
1511	}
1512
1513	tmp_str[sizeof(tmp_str) - 1] = '\0';
1514
1515	buf->proginfo_version = conn->conn_version;
1516	cmyth_dbg(CMYTH_DBG_DEBUG, "%s: VERSION IS %"PRIu32"\n",
1517		  __FUNCTION__, buf->proginfo_version);
1518
1519	/*
1520	 * Get proginfo_title (string)
1521	 */
1522	consumed = cmyth_rcv_string(conn, err,
1523				    tmp_str, sizeof(tmp_str) - 1, count);
1524	count -= consumed;
1525	total += consumed;
1526	if (*err) {
1527		failed = "cmyth_rcv_string";
1528		goto fail;
1529	}
1530	if (buf->proginfo_title)
1531		ref_release(buf->proginfo_title);
1532	buf->proginfo_title = ref_strdup(tmp_str);
1533
1534	/*
1535	 * Get proginfo_subtitle (string)
1536	 */
1537	consumed = cmyth_rcv_string(conn, err,
1538				    tmp_str, sizeof(tmp_str) - 1, count);
1539	count -= consumed;
1540	total += consumed;
1541	if (*err) {
1542		failed = "cmyth_rcv_string";
1543		goto fail;
1544	}
1545	if (buf->proginfo_subtitle)
1546		ref_release(buf->proginfo_subtitle);
1547	buf->proginfo_subtitle = ref_strdup(tmp_str);
1548
1549	/*
1550	 * Get proginfo_description (string)
1551	 */
1552	consumed = cmyth_rcv_string(conn, err,
1553				    tmp_str, sizeof(tmp_str) - 1, count);
1554	count -= consumed;
1555	total += consumed;
1556	if (*err) {
1557		failed = "cmyth_rcv_string";
1558		goto fail;
1559	}
1560	if (buf->proginfo_description)
1561		ref_release(buf->proginfo_description);
1562	buf->proginfo_description = ref_strdup(tmp_str);
1563
1564	if (buf->proginfo_version >= 67) {
1565		/*
1566		 * Get season and episode (unsigned int)
1567		 */
1568		consumed = cmyth_rcv_uint16(conn, err,
1569					   &buf->proginfo_season, count);
1570		count -= consumed;
1571		total += consumed;
1572		if (*err) {
1573			failed = "cmyth_rcv_ushort";
1574			goto fail;
1575		}
1576
1577		consumed = cmyth_rcv_uint16(conn, err,
1578					   &buf->proginfo_episode, count);
1579		count -= consumed;
1580		total += consumed;
1581		if (*err) {
1582			failed = "cmyth_rcv_ushort";
1583			goto fail;
1584		}
1585	}
1586
1587	if (buf->proginfo_version >= 76) {
1588		/*
1589		 * Get proginfo_syndicated_episode (string)
1590		 */
1591		consumed = cmyth_rcv_string(conn, err, tmp_str, sizeof(tmp_str) - 1, count);
1592		count -= consumed;
1593		total += consumed;
1594		if (*err) {
1595			failed = "cmyth_rcv_string";
1596			goto fail;
1597		}
1598		if (buf->proginfo_syndicated_episode)
1599			ref_release(buf->proginfo_syndicated_episode);
1600		buf->proginfo_syndicated_episode = ref_strdup(tmp_str);
1601	}
1602
1603	/*
1604	 * Get proginfo_category (string)
1605	 */
1606	consumed = cmyth_rcv_string(conn, err,
1607				    tmp_str, sizeof(tmp_str) - 1, count);
1608	count -= consumed;
1609	total += consumed;
1610	if (*err) {
1611		failed = "cmyth_rcv_string";
1612		goto fail;
1613	}
1614	if (buf->proginfo_category)
1615		ref_release(buf->proginfo_category);
1616	buf->proginfo_category = ref_strdup(tmp_str);
1617
1618	/*
1619	 * Get proginfo_chanId (ulong)
1620	 */
1621	consumed = cmyth_rcv_uint32(conn, err,
1622				    &buf->proginfo_chanId, count);
1623	count -= consumed;
1624	total += consumed;
1625	if (*err) {
1626		failed = "cmyth_rcv_ulong";
1627		goto fail;
1628	}
1629
1630	/*
1631	 * Get proginfo_chanstr (string)
1632	 */
1633	consumed = cmyth_rcv_string(conn, err,
1634				    tmp_str, sizeof(tmp_str) - 1, count);
1635	count -= consumed;
1636	total += consumed;
1637	if (*err) {
1638		failed = "cmyth_rcv_string";
1639		goto fail;
1640	}
1641	if (buf->proginfo_chanstr)
1642		ref_release(buf->proginfo_chanstr);
1643	buf->proginfo_chanstr = ref_strdup(tmp_str);
1644
1645	/*
1646	 * Get proginfo_chansign (string)
1647	 */
1648	consumed = cmyth_rcv_string(conn, err,
1649				    tmp_str, sizeof(tmp_str) - 1, count);
1650	count -= consumed;
1651	total += consumed;
1652	if (*err) {
1653		failed = "cmyth_rcv_string";
1654		goto fail;
1655	}
1656	if (buf->proginfo_chansign)
1657		ref_release(buf->proginfo_chansign);
1658	buf->proginfo_chansign = ref_strdup(tmp_str);
1659
1660	/*
1661	 * Get proginfo_channame (string) Version 1 or proginfo_chanicon
1662	 * (string) Version 8.
1663	 */
1664	consumed = cmyth_rcv_string(conn, err,
1665				    tmp_str, sizeof(tmp_str) - 1, count);
1666	count -= consumed;
1667	total += consumed;
1668	if (*err) {
1669		failed = "cmyth_rcv_string";
1670		goto fail;
1671	}
1672	/* FIXME: doesn't seem to match the dump? */
1673	cmyth_dbg(CMYTH_DBG_DEBUG, "%s: GOT TO ICON/NAME\n", __FUNCTION__);
1674	if (buf->proginfo_chanicon)
1675		ref_release(buf->proginfo_chanicon);
1676	if (buf->proginfo_channame)
1677		ref_release(buf->proginfo_channame);
1678	if (buf->proginfo_version >= 8) {
1679		buf->proginfo_chanicon = ref_strdup(tmp_str);
1680		/*
1681		 * Simulate a channel name (Number and Callsign) for
1682		 * compatibility.
1683		 */
1684		sprintf(tmp_str,
1685			"%s %s", buf->proginfo_chanstr,
1686			buf->proginfo_chansign);
1687		buf->proginfo_channame = ref_strdup(tmp_str);
1688	} else { /* Assume version 1 */
1689		buf->proginfo_channame = ref_strdup(tmp_str);
1690		buf->proginfo_chanicon = ref_strdup("");
1691	}
1692
1693	/*
1694	 * Get proginfo_url (string)
1695	 */
1696	consumed = cmyth_rcv_string(conn, err,
1697				    tmp_str, sizeof(tmp_str) - 1, count);
1698	count -= consumed;
1699	total += consumed;
1700	if (*err) {
1701		failed = "cmyth_rcv_string";
1702		goto fail;
1703	}
1704	if (buf->proginfo_url)
1705		ref_release(buf->proginfo_url);
1706	buf->proginfo_url = ref_strdup(tmp_str);
1707
1708	/*
1709	 * Get proginfo_Length (long_long)
1710	 */
1711	if (buf->proginfo_version < 57) {
1712		consumed = cmyth_rcv_old_int64(conn, err, &buf->proginfo_Length,
1713					       count);
1714	} else {
1715		/*
1716		 * Since protocol 57 mythbackend now sends a single 64 bit
1717		 * integer rather than two 32 bit hi and lo integers for the
1718		 * proginfo length.
1719		 */
1720		consumed = cmyth_rcv_new_int64(conn, err, &buf->proginfo_Length,
1721					       count, 1);
1722	}
1723	count -= consumed;
1724	total += consumed;
1725	if (*err) {
1726		failed = "rcv_64";
1727		goto fail;
1728	}
1729
1730	/*
1731	 * Get proginfo_start_ts (timestamp)
1732	 */
1733	cmyth_dbg(CMYTH_DBG_DEBUG, "%s: GOT TO START_TS\n", __FUNCTION__);
1734	if (buf->proginfo_version >= 14) {
1735		consumed = cmyth_rcv_datetime(conn, err,
1736					      &(buf->proginfo_start_ts),
1737					      count);
1738	}
1739	else {
1740		consumed = cmyth_rcv_timestamp(conn, err,
1741					       &(buf->proginfo_start_ts),
1742					       count);
1743	}
1744	count -= consumed;
1745	total += consumed;
1746	if (*err) {
1747		failed = "proginfo_start_ts cmyth_rcv";
1748		goto fail;
1749	}
1750
1751	/*
1752	 * Get proginfo_end_ts (timestamp)
1753	 */
1754	cmyth_dbg(CMYTH_DBG_DEBUG, "%s: GOT TO END_TS\n", __FUNCTION__);
1755	if (buf->proginfo_version >= 14) {
1756		consumed = cmyth_rcv_datetime(conn, err,
1757					      &(buf->proginfo_end_ts), count);
1758	}
1759	else {
1760		consumed = cmyth_rcv_timestamp(conn, err,
1761					       &(buf->proginfo_end_ts), count);
1762	}
1763	count -= consumed;
1764	total += consumed;
1765	if (*err) {
1766		failed = "cmyth_rcv_timestamp";
1767		goto fail;
1768	}
1769
1770	if (buf->proginfo_version < 57) {
1771		/*
1772		 * Get proginfo_conflicting (ulong in Version 1, string in Version 8)
1773		 */
1774		if (buf->proginfo_version >= 8) {
1775			consumed = cmyth_rcv_string(conn, err,
1776						    tmp_str, sizeof(tmp_str) - 1,
1777						    count);
1778			count -= consumed;
1779			total += consumed;
1780			if (*err) {
1781				failed = "cmyth_rcv_string";
1782				goto fail;
1783			}
1784			if (buf->proginfo_unknown_0)
1785				ref_release(buf->proginfo_unknown_0);
1786			buf->proginfo_unknown_0 = ref_strdup(tmp_str);
1787		} else { /* Assume version 1 */
1788			consumed = cmyth_rcv_uint32(conn, err,
1789						   &buf->proginfo_conflicting, count);
1790			count -= consumed;
1791			total += consumed;
1792			if (*err) {
1793				failed = "cmyth_rcv_ulong";
1794				goto fail;
1795			}
1796		}
1797
1798		/*
1799		 * Get proginfo_recording (ulong)
1800		 */
1801		consumed = cmyth_rcv_uint32(conn, err, &buf->proginfo_recording, count);
1802		count -= consumed;
1803		total += consumed;
1804		if (*err) {
1805			failed = "cmyth_rcv_ulong";
1806			goto fail;
1807		}
1808	}
1809
1810	/*
1811	 * Get proginfo_override (ulong)
1812	 */
1813	consumed = cmyth_rcv_uint32(conn, err, &buf->proginfo_override, count);
1814	count -= consumed;
1815	total += consumed;
1816	if (*err) {
1817		failed = "cmyth_rcv_ulong";
1818		goto fail;
1819	}
1820
1821	/*
1822	 * Get proginfo_hostname (string)
1823	 */
1824	consumed = cmyth_rcv_string(conn, err,
1825				    tmp_str, sizeof(tmp_str) - 1, count);
1826	count -= consumed;
1827	total += consumed;
1828	if (*err) {
1829		failed = "cmyth_rcv_string";
1830		goto fail;
1831	}
1832	if (buf->proginfo_hostname)
1833		ref_release(buf->proginfo_hostname);
1834	buf->proginfo_hostname = ref_strdup(tmp_str);
1835
1836	/*
1837	 * Get proginfo_source_id (ulong)
1838	 */
1839	consumed = cmyth_rcv_uint32(conn, err, &buf->proginfo_source_id, count);
1840	count -= consumed;
1841	total += consumed;
1842	if (*err) {
1843		failed = "cmyth_rcv_ulong";
1844		goto fail;
1845	}
1846
1847	/*
1848	 * Get proginfo_card_id (ulong)
1849	 */
1850	consumed = cmyth_rcv_uint32(conn, err, &buf->proginfo_card_id, count);
1851	count -= consumed;
1852	total += consumed;
1853	if (*err) {
1854		failed = "cmyth_rcv_ulong";
1855		goto fail;
1856	}
1857
1858	/*
1859	 * Get proginfo_input_id (ulong)
1860	 */
1861	consumed = cmyth_rcv_uint32(conn, err, &buf->proginfo_input_id, count);
1862	count -= consumed;
1863	total += consumed;
1864	if (*err) {
1865		failed = "cmyth_rcv_ulong";
1866		goto fail;
1867	}
1868
1869	/*
1870	 * Get proginfo_rec_priority (byte)
1871	 */
1872	consumed = cmyth_rcv_int32(conn, err,
1873				    &buf->proginfo_rec_priority, count);
1874	count -= consumed;
1875	total += consumed;
1876	if (*err) {
1877		failed = "cmyth_rcv_long";
1878		goto fail;
1879	}
1880
1881	/*
1882	 * Get proginfo_rec_status (byte)
1883	 */
1884	consumed = cmyth_rcv_int8(conn, err, &buf->proginfo_rec_status, count);
1885	count -= consumed;
1886	total += consumed;
1887	if (*err) {
1888		failed = "cmyth_rcv_byte";
1889		goto fail;
1890	}
1891
1892	/*
1893	 * Get proginfo_record_id (ulong)
1894	 */
1895	consumed = cmyth_rcv_uint32(conn, err, &buf->proginfo_record_id, count);
1896	count -= consumed;
1897	total += consumed;
1898	if (*err) {
1899		failed = "cmyth_rcv_ulong";
1900		goto fail;
1901	}
1902
1903	/*
1904	 * Get proginfo_rec_type (ubyte)
1905	 */
1906	consumed = cmyth_rcv_uint8(conn, err, &buf->proginfo_rec_type, count);
1907	count -= consumed;
1908	total += consumed;
1909	if (*err) {
1910		failed = "cmyth_rcv_ubyte";
1911		goto fail;
1912	}
1913
1914	/*
1915	 * Get proginfo_rec_dupin (ubyte)
1916	 */
1917	consumed = cmyth_rcv_uint8(conn, err, &buf->proginfo_rec_dupin, count);
1918	count -= consumed;
1919	total += consumed;
1920	if (*err) {
1921		failed = "cmyth_rcv_ubyte";
1922		goto fail;
1923	}
1924
1925	if (buf->proginfo_version >= 8) {
1926		/*
1927		 * Get proginfo_rec_dupmethod (ubyte)
1928		 */
1929		consumed = cmyth_rcv_uint8(conn, err,
1930					   &buf->proginfo_rec_dupmethod, count);
1931		count -= consumed;
1932		total += consumed;
1933		if (*err) {
1934			failed = "cmyth_rcv_ubyte";
1935			goto fail;
1936		}
1937	}
1938
1939	/*
1940	 * Get proginfo_rec_start_ts (timestamp)
1941	 */
1942	if (buf->proginfo_version >= 14) {
1943		consumed = cmyth_rcv_datetime(conn, err,
1944					      &(buf->proginfo_rec_start_ts),
1945					      count);
1946	}
1947	else {
1948		consumed = cmyth_rcv_timestamp(conn, err,
1949					       &(buf->proginfo_rec_start_ts),
1950					       count);
1951	}
1952
1953	count -= consumed;
1954	total += consumed;
1955	if (*err) {
1956		failed = "cmyth_rcv_timestamp";
1957		goto fail;
1958	}
1959
1960	/*
1961	 * Get proginfo_rec_end_ts (timestamp)
1962	 */
1963	if (buf->proginfo_version >= 14) {
1964		consumed = cmyth_rcv_datetime(conn, err,
1965					      &(buf->proginfo_rec_end_ts),
1966					      count);
1967	}
1968	else {
1969		consumed = cmyth_rcv_timestamp(conn, err,
1970					       &(buf->proginfo_rec_end_ts),
1971					       count);
1972	}
1973
1974	count -= consumed;
1975	total += consumed;
1976	if (*err) {
1977		failed = "cmyth_rcv_timestamp";
1978		goto fail;
1979	}
1980
1981	if (buf->proginfo_version < 57) {
1982		/*
1983		 * Get proginfo_repeat (ubyte)
1984		 */
1985		consumed = cmyth_rcv_uint8(conn, err, &buf->proginfo_repeat, count);
1986		count -= consumed;
1987		total += consumed;
1988		if (*err) {
1989			failed = "cmyth_rcv_ubyte";
1990			goto fail;
1991		}
1992	}
1993
1994	/*
1995	 * Get proginfo_program_flags (ulong)
1996	 */
1997	consumed = cmyth_rcv_uint32(conn, err, &buf->proginfo_program_flags,
1998				  count);
1999	count -= consumed;
2000	total += consumed;
2001	if (*err) {
2002		failed = "cmyth_rcv_ulong";
2003		goto fail;
2004	}
2005
2006	if (buf->proginfo_version >= 8) {
2007		/*
2008		 * Get proginfo_recgroup (string)
2009		 */
2010		consumed = cmyth_rcv_string(conn, err,
2011					    tmp_str, sizeof(tmp_str) - 1,
2012					    count);
2013		count -= consumed;
2014		total += consumed;
2015		if (*err) {
2016			failed = "cmyth_rcv_string";
2017			goto fail;
2018		}
2019		if (buf->proginfo_recgroup)
2020			ref_release(buf->proginfo_recgroup);
2021		buf->proginfo_recgroup = ref_strdup(tmp_str);
2022	}
2023
2024	if (buf->proginfo_version >= 8 && buf->proginfo_version < 57) {
2025		/*
2026		 * Get proginfo_chancommfree (string)
2027		 */
2028		consumed = cmyth_rcv_string(conn, err,
2029					    tmp_str, sizeof(tmp_str) - 1,
2030					    count);
2031		count -= consumed;
2032		total += consumed;
2033		if (*err) {
2034			failed = "cmyth_rcv_string";
2035			goto fail;
2036		}
2037		if (buf->proginfo_chancommfree)
2038			ref_release(buf->proginfo_chancommfree);
2039		buf->proginfo_chancommfree = ref_strdup(tmp_str

Large files files are truncated, but you can click here to view the full file