You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
3.6KB

  1. /*
  2. * UDP prototype streaming system
  3. * Copyright (c) 2000 Gerard Lantau.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program 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
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <errno.h>
  24. #include <sys/types.h>
  25. #include <sys/socket.h>
  26. #include <netinet/in.h>
  27. #include <arpa/inet.h>
  28. #include <netdb.h>
  29. #include "avformat.h"
  30. typedef struct {
  31. int udp_socket;
  32. int max_payload_size; /* in bytes */
  33. } UDPContext;
  34. #define UDP_TX_BUF_SIZE 32768
  35. /* put it in UDP context */
  36. static struct sockaddr_in dest_addr;
  37. /* return non zero if error */
  38. static int udp_open(URLContext *h, const char *uri, int flags)
  39. {
  40. int local_port = 0;
  41. struct sockaddr_in my_addr;
  42. const char *p, *q;
  43. char hostname[1024];
  44. int port, udp_socket, tmp;
  45. struct hostent *hp;
  46. UDPContext *s;
  47. h->is_streamed = 1;
  48. if (!(flags & URL_WRONLY))
  49. return -EIO;
  50. /* fill the dest addr */
  51. p = uri;
  52. if (!strstart(p, "udp:", &p))
  53. return -1;
  54. q = strchr(p, ':');
  55. if (!q)
  56. return -1;
  57. memcpy(hostname, p, q - p);
  58. hostname[q - p] = '\0';
  59. port = strtol(q+1, NULL, 10);
  60. if (port <= 0)
  61. return -1;
  62. dest_addr.sin_family = AF_INET;
  63. dest_addr.sin_port = htons(port);
  64. if ((inet_aton(hostname, &dest_addr.sin_addr)) == 0) {
  65. hp = gethostbyname(hostname);
  66. if (!hp)
  67. return -1;
  68. memcpy ((char *) &dest_addr.sin_addr, hp->h_addr, hp->h_length);
  69. }
  70. udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
  71. if (udp_socket < 0)
  72. return -1;
  73. my_addr.sin_family = AF_INET;
  74. my_addr.sin_port = htons(local_port);
  75. my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
  76. /* the bind is needed to give a port to the socket now */
  77. if (bind(udp_socket,(struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
  78. goto fail;
  79. /* limit the tx buf size to limit latency */
  80. tmp = UDP_TX_BUF_SIZE;
  81. if (setsockopt(udp_socket, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
  82. perror("setsockopt sndbuf");
  83. goto fail;
  84. }
  85. s = malloc(sizeof(UDPContext));
  86. if (!s)
  87. return -ENOMEM;
  88. h->priv_data = s;
  89. s->udp_socket = udp_socket;
  90. h->packet_size = 1500;
  91. return 0;
  92. fail:
  93. return -EIO;
  94. }
  95. int udp_close(URLContext *h)
  96. {
  97. UDPContext *s = h->priv_data;
  98. close(s->udp_socket);
  99. return 0;
  100. }
  101. int udp_write(URLContext *h, UINT8 *buf, int size)
  102. {
  103. UDPContext *s = h->priv_data;
  104. int ret, len, size1;
  105. /* primitive way to avoid big packets */
  106. size1 = size;
  107. while (size > 0) {
  108. len = size;
  109. if (len > h->packet_size)
  110. len = h->packet_size;
  111. ret = sendto (s->udp_socket, buf, len, 0,
  112. (struct sockaddr *) &dest_addr,
  113. sizeof (dest_addr));
  114. if (ret < 0)
  115. perror("sendto");
  116. buf += len;
  117. size -= len;
  118. }
  119. return size1 - size;
  120. }
  121. URLProtocol udp_protocol = {
  122. "udp",
  123. udp_open,
  124. NULL, /* read */
  125. udp_write,
  126. NULL, /* seek */
  127. udp_close,
  128. };