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.

144 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 "avformat.h"
  20. #include <unistd.h>
  21. #include <sys/types.h>
  22. #include <sys/socket.h>
  23. #include <netinet/in.h>
  24. #include <arpa/inet.h>
  25. #include <netdb.h>
  26. typedef struct {
  27. int udp_socket;
  28. int max_payload_size; /* in bytes */
  29. } UDPContext;
  30. #define UDP_TX_BUF_SIZE 32768
  31. /* put it in UDP context */
  32. static struct sockaddr_in dest_addr;
  33. /* return non zero if error */
  34. static int udp_open(URLContext *h, const char *uri, int flags)
  35. {
  36. int local_port = 0;
  37. struct sockaddr_in my_addr;
  38. const char *p, *q;
  39. char hostname[1024];
  40. int port, udp_socket, tmp;
  41. struct hostent *hp;
  42. UDPContext *s;
  43. h->is_streamed = 1;
  44. if (!(flags & URL_WRONLY))
  45. return -EIO;
  46. /* fill the dest addr */
  47. p = uri;
  48. if (!strstart(p, "udp:", &p))
  49. return -1;
  50. q = strchr(p, ':');
  51. if (!q)
  52. return -1;
  53. memcpy(hostname, p, q - p);
  54. hostname[q - p] = '\0';
  55. port = strtol(q+1, NULL, 10);
  56. if (port <= 0)
  57. return -1;
  58. dest_addr.sin_family = AF_INET;
  59. dest_addr.sin_port = htons(port);
  60. if ((inet_aton(hostname, &dest_addr.sin_addr)) == 0) {
  61. hp = gethostbyname(hostname);
  62. if (!hp)
  63. return -1;
  64. memcpy ((char *) &dest_addr.sin_addr, hp->h_addr, hp->h_length);
  65. }
  66. udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
  67. if (udp_socket < 0)
  68. return -1;
  69. my_addr.sin_family = AF_INET;
  70. my_addr.sin_port = htons(local_port);
  71. my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
  72. /* the bind is needed to give a port to the socket now */
  73. if (bind(udp_socket,(struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
  74. goto fail;
  75. /* limit the tx buf size to limit latency */
  76. tmp = UDP_TX_BUF_SIZE;
  77. if (setsockopt(udp_socket, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
  78. perror("setsockopt sndbuf");
  79. goto fail;
  80. }
  81. s = av_malloc(sizeof(UDPContext));
  82. if (!s)
  83. return -ENOMEM;
  84. h->priv_data = s;
  85. s->udp_socket = udp_socket;
  86. h->packet_size = 1500;
  87. return 0;
  88. fail:
  89. return -EIO;
  90. }
  91. int udp_close(URLContext *h)
  92. {
  93. UDPContext *s = h->priv_data;
  94. close(s->udp_socket);
  95. return 0;
  96. }
  97. int udp_write(URLContext *h, UINT8 *buf, int size)
  98. {
  99. UDPContext *s = h->priv_data;
  100. int ret, len, size1;
  101. /* primitive way to avoid big packets */
  102. size1 = size;
  103. while (size > 0) {
  104. len = size;
  105. if (len > h->packet_size)
  106. len = h->packet_size;
  107. ret = sendto (s->udp_socket, buf, len, 0,
  108. (struct sockaddr *) &dest_addr,
  109. sizeof (dest_addr));
  110. if (ret < 0)
  111. perror("sendto");
  112. buf += len;
  113. size -= len;
  114. }
  115. return size1 - size;
  116. }
  117. URLProtocol udp_protocol = {
  118. "udp",
  119. udp_open,
  120. NULL, /* read */
  121. udp_write,
  122. NULL, /* seek */
  123. udp_close,
  124. };