netsock.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2005, Digium, Inc.
  5. *
  6. * Kevin P. Fleming <kpfleming@digium.com>
  7. * Mark Spencer <markster@digium.com>
  8. *
  9. * See http://www.asterisk.org for more information about
  10. * the Asterisk project. Please do not directly contact
  11. * any of the maintainers of this project for assistance;
  12. * the project provides a web site, mailing lists and IRC
  13. * channels for your use.
  14. *
  15. * This program is free software, distributed under the terms of
  16. * the GNU General Public License Version 2. See the LICENSE file
  17. * at the top of the source tree.
  18. */
  19. /*! \file
  20. *
  21. * \brief Network socket handling
  22. *
  23. * \author Kevin P. Fleming <kpfleming@digium.com>
  24. * \author Mark Spencer <markster@digium.com>
  25. */
  26. #include "asterisk.h"
  27. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  28. #if defined (SOLARIS)
  29. #include <sys/sockio.h>
  30. #endif
  31. #include "asterisk/netsock.h"
  32. #include "asterisk/utils.h"
  33. struct ast_netsock {
  34. ASTOBJ_COMPONENTS(struct ast_netsock);
  35. struct sockaddr_in bindaddr;
  36. int sockfd;
  37. int *ioref;
  38. struct io_context *ioc;
  39. void *data;
  40. };
  41. struct ast_netsock_list {
  42. ASTOBJ_CONTAINER_COMPONENTS(struct ast_netsock);
  43. struct io_context *ioc;
  44. };
  45. static void ast_netsock_destroy(struct ast_netsock *netsock)
  46. {
  47. ast_io_remove(netsock->ioc, netsock->ioref);
  48. close(netsock->sockfd);
  49. ast_free(netsock);
  50. }
  51. struct ast_netsock_list *ast_netsock_list_alloc(void)
  52. {
  53. return ast_calloc(1, sizeof(struct ast_netsock_list));
  54. }
  55. int ast_netsock_init(struct ast_netsock_list *list)
  56. {
  57. memset(list, 0, sizeof(*list));
  58. ASTOBJ_CONTAINER_INIT(list);
  59. return 0;
  60. }
  61. int ast_netsock_release(struct ast_netsock_list *list)
  62. {
  63. ASTOBJ_CONTAINER_DESTROYALL(list, ast_netsock_destroy);
  64. ASTOBJ_CONTAINER_DESTROY(list);
  65. ast_free(list);
  66. return 0;
  67. }
  68. struct ast_netsock *ast_netsock_find(struct ast_netsock_list *list,
  69. struct sockaddr_in *sa)
  70. {
  71. struct ast_netsock *sock = NULL;
  72. ASTOBJ_CONTAINER_TRAVERSE(list, !sock, {
  73. ASTOBJ_RDLOCK(iterator);
  74. if (!inaddrcmp(&iterator->bindaddr, sa))
  75. sock = iterator;
  76. ASTOBJ_UNLOCK(iterator);
  77. });
  78. return sock;
  79. }
  80. struct ast_netsock *ast_netsock_bindaddr(struct ast_netsock_list *list, struct io_context *ioc, struct sockaddr_in *bindaddr, int tos, int cos, ast_io_cb callback, void *data)
  81. {
  82. int netsocket = -1;
  83. int *ioref;
  84. struct ast_netsock *ns;
  85. const int reuseFlag = 1;
  86. /* Make a UDP socket */
  87. netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
  88. if (netsocket < 0) {
  89. ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
  90. return NULL;
  91. }
  92. if (setsockopt(netsocket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseFlag, sizeof reuseFlag) < 0) {
  93. ast_log(LOG_WARNING, "Error setting SO_REUSEADDR on sockfd '%d'\n", netsocket);
  94. }
  95. if (bind(netsocket,(struct sockaddr *)bindaddr, sizeof(struct sockaddr_in))) {
  96. ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(bindaddr->sin_addr), ntohs(bindaddr->sin_port), strerror(errno));
  97. close(netsocket);
  98. return NULL;
  99. }
  100. ast_netsock_set_qos(netsocket, tos, cos, "IAX2");
  101. ast_enable_packet_fragmentation(netsocket);
  102. if (!(ns = ast_calloc(1, sizeof(*ns)))) {
  103. close(netsocket);
  104. return NULL;
  105. }
  106. /* Establish I/O callback for socket read */
  107. if (!(ioref = ast_io_add(ioc, netsocket, callback, AST_IO_IN, ns))) {
  108. close(netsocket);
  109. ast_free(ns);
  110. return NULL;
  111. }
  112. ASTOBJ_INIT(ns);
  113. ns->ioref = ioref;
  114. ns->ioc = ioc;
  115. ns->sockfd = netsocket;
  116. ns->data = data;
  117. memcpy(&ns->bindaddr, bindaddr, sizeof(ns->bindaddr));
  118. ASTOBJ_CONTAINER_LINK(list, ns);
  119. return ns;
  120. }
  121. int ast_netsock_set_qos(int netsocket, int tos, int cos, const char *desc)
  122. {
  123. int res;
  124. if ((res = setsockopt(netsocket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))))
  125. ast_log(LOG_WARNING, "Unable to set %s TOS to %d, may be you have no root privileges\n", desc, tos);
  126. else if (tos)
  127. ast_verb(2, "Using %s TOS bits %d\n", desc, tos);
  128. #if defined(linux)
  129. if (setsockopt(netsocket, SOL_SOCKET, SO_PRIORITY, &cos, sizeof(cos)))
  130. ast_log(LOG_WARNING, "Unable to set %s CoS to %d\n", desc, cos);
  131. else if (cos)
  132. ast_verb(2, "Using %s CoS mark %d\n", desc, cos);
  133. #endif
  134. return res;
  135. }
  136. struct ast_netsock *ast_netsock_bind(struct ast_netsock_list *list, struct io_context *ioc, const char *bindinfo, int defaultport, int tos, int cos, ast_io_cb callback, void *data)
  137. {
  138. struct sockaddr_in sin;
  139. char *tmp;
  140. char *host;
  141. char *port;
  142. int portno;
  143. memset(&sin, 0, sizeof(sin));
  144. sin.sin_family = AF_INET;
  145. sin.sin_port = htons(defaultport);
  146. tmp = ast_strdupa(bindinfo);
  147. host = strsep(&tmp, ":");
  148. port = tmp;
  149. if (port && ((portno = atoi(port)) > 0))
  150. sin.sin_port = htons(portno);
  151. inet_aton(host, &sin.sin_addr);
  152. return ast_netsock_bindaddr(list, ioc, &sin, tos, cos, callback, data);
  153. }
  154. int ast_netsock_sockfd(const struct ast_netsock *ns)
  155. {
  156. return ns ? ns-> sockfd : -1;
  157. }
  158. const struct sockaddr_in *ast_netsock_boundaddr(const struct ast_netsock *ns)
  159. {
  160. return &(ns->bindaddr);
  161. }
  162. void *ast_netsock_data(const struct ast_netsock *ns)
  163. {
  164. return ns->data;
  165. }
  166. void ast_netsock_unref(struct ast_netsock *ns)
  167. {
  168. ASTOBJ_UNREF(ns, ast_netsock_destroy);
  169. }