PageRenderTime 72ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/cmyth/libcmyth/socket.c

https://github.com/xhaggi/xbmc-pvr-addons
C | 3000 lines | 1795 code | 161 blank | 1044 comment | 337 complexity | 7ca81e5509e1c731272b807433788412 MD5 | raw file
Possible License(s): GPL-3.0, AGPL-1.0, GPL-2.0, LGPL-2.1, MIT

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

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