tcpops.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /**
  2. * Copyright 2015 (C) Orange
  3. * <[email protected]>
  4. *
  5. * This file is part of Kamailio, a free SIP server.
  6. *
  7. * This file is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version
  11. *
  12. *
  13. * This file is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. */
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <netinet/tcp.h>
  26. #include <errno.h>
  27. #include "../../dprint.h"
  28. #include "../../tcp_options.h"
  29. #include "../../tcp_conn.h"
  30. #include "../../globals.h"
  31. #include "../../pass_fd.h"
  32. #include "../../timer.h"
  33. /**
  34. * gets the fd of the current message source connection
  35. *
  36. * @param conid - connection id
  37. * @param fd - placeholder to return the fd
  38. * @return 1 on success, 0 on failure
  39. *
  40. */
  41. int tcpops_get_current_fd(int conid, int *fd)
  42. {
  43. struct tcp_connection *s_con;
  44. if (unlikely((s_con = tcpconn_get(conid, 0, 0, 0, 0)) == NULL)) {
  45. LM_ERR("invalid connection id %d, (must be a TCP connid)\n", conid);
  46. return 0;
  47. }
  48. LM_DBG("got fd=%d from id=%d\n", s_con->fd, conid);
  49. *fd = s_con->fd;
  50. tcpconn_put(s_con);
  51. return 1;
  52. }
  53. /**
  54. * Request the fd corresponding to the given connection id to the TCP main process.
  55. * You may want to close() the fd after use.
  56. *
  57. * @param conid - connection id
  58. * @param fd - placeholder to return the fd
  59. * @return 1 on success, 0 on failure
  60. *
  61. */
  62. int tcpops_acquire_fd_from_tcpmain(int conid, int *fd)
  63. {
  64. struct tcp_connection *s_con, *tmp;
  65. long msg[2];
  66. int n;
  67. if (unlikely((s_con = tcpconn_get(conid, 0, 0, 0, 0)) == NULL)) {
  68. LM_ERR("invalid connection id %d, (must be a TCP connid)\n", conid);
  69. return 0;
  70. }
  71. msg[0] = (long)s_con;
  72. msg[1] = CONN_GET_FD;
  73. n = send_all(unix_tcp_sock, msg, sizeof(msg));
  74. if (unlikely(n <= 0)){
  75. LM_ERR("failed to send fd request: %s (%d)\n", strerror(errno), errno);
  76. goto error_release;
  77. }
  78. n = receive_fd(unix_tcp_sock, &tmp, sizeof(tmp), fd, MSG_WAITALL);
  79. if (unlikely(n <= 0)){
  80. LM_ERR("failed to get fd (receive_fd): %s (%d)\n", strerror(errno), errno);
  81. goto error_release;
  82. }
  83. tcpconn_put(s_con);
  84. return 1;
  85. error_release:
  86. tcpconn_put(s_con);
  87. return 0;
  88. }
  89. #if !defined(HAVE_SO_KEEPALIVE) || !defined(HAVE_TCP_KEEPIDLE) || !defined(HAVE_TCP_KEEPCNT) || !defined(HAVE_TCP_KEEPINTVL)
  90. #warning "TCP keepalive is not fully supported by your platform"
  91. int tcpops_keepalive_enable(int fd, int idle, int count, int interval, int closefd)
  92. {
  93. LM_ERR("tcp_keepalive_enable() failed: this module does not support your platform\n");
  94. return -1;
  95. }
  96. int tcpops_keepalive_disable(int fd, int closefd)
  97. {
  98. LM_ERR("tcp_keepalive_disable() failed: this module does not support your platform\n");
  99. return -1;
  100. }
  101. #else
  102. int tcpops_keepalive_enable(int fd, int idle, int count, int interval, int closefd)
  103. {
  104. static const int enable = 1;
  105. int ret = -1;
  106. if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enable,
  107. sizeof(enable))<0){
  108. LM_ERR("failed to enable SO_KEEPALIVE: %s\n", strerror(errno));
  109. return -1;
  110. } else {
  111. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle,
  112. sizeof(idle))<0){
  113. LM_ERR("failed to set keepalive idle interval: %s\n", strerror(errno));
  114. }
  115. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count,
  116. sizeof(count))<0){
  117. LM_ERR("failed to set maximum keepalive count: %s\n", strerror(errno));
  118. }
  119. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval,
  120. sizeof(interval))<0){
  121. LM_ERR("failed to set keepalive probes interval: %s\n", strerror(errno));
  122. }
  123. ret = 1;
  124. LM_DBG("keepalive enabled for fd=%d, idle=%d, cnt=%d, intvl=%d\n", fd, idle, count, interval);
  125. }
  126. if (closefd)
  127. {
  128. close(fd);
  129. }
  130. return ret;
  131. }
  132. int tcpops_keepalive_disable(int fd, int closefd)
  133. {
  134. static const int disable = 0;
  135. int ret = -1;
  136. if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &disable,
  137. sizeof(disable))<0){
  138. LM_WARN("failed to disable SO_KEEPALIVE: %s\n", strerror(errno));
  139. } else {
  140. ret = 1;
  141. LM_DBG("keepalive disabled for fd=%d\n", fd);
  142. }
  143. if (closefd)
  144. {
  145. close(fd);
  146. }
  147. return ret;
  148. }
  149. #endif
  150. int tcpops_set_connection_lifetime(struct tcp_connection* con, int time) {
  151. if (unlikely(con == NULL)) {
  152. LM_CRIT("BUG: con == NULL");
  153. return -1;
  154. }
  155. if (unlikely(time < 0)) {
  156. LM_ERR("Invalid timeout value, %d, must be >= 0\n", time);
  157. return -1;
  158. }
  159. con->lifetime = S_TO_TICKS(time);
  160. con->timeout = get_ticks_raw() + con->lifetime;
  161. LM_DBG("new connection lifetime for conid=%d: %d\n", con->id, con->timeout);
  162. return 1;
  163. }