sockopt.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nspr.h"
  6. #include "prio.h"
  7. #include "prinit.h"
  8. #include "prprf.h"
  9. #include "obsolete/probslet.h"
  10. #include "plerror.h"
  11. #ifdef XP_UNIX
  12. #include <sys/socket.h> /* SO_REUSEPORT */
  13. #endif
  14. static PRFileDesc *err = NULL;
  15. static PRBool failed = PR_FALSE;
  16. static void Failed(const char *msg1, const char *msg2)
  17. {
  18. if (NULL != msg1) {
  19. PR_fprintf(err, "%s ", msg1);
  20. }
  21. PL_FPrintError(err, msg2);
  22. failed = PR_TRUE;
  23. } /* Failed */
  24. static PRSockOption Incr(PRSockOption *option)
  25. {
  26. PRIntn val = ((PRIntn)*option) + 1;
  27. *option = (PRSockOption)val;
  28. return (PRSockOption)val;
  29. } /* Incr */
  30. int main(int argc, char **argv)
  31. {
  32. PRStatus rv;
  33. PRFileDesc *udp = PR_NewUDPSocket();
  34. PRFileDesc *tcp = PR_NewTCPSocket();
  35. const char *tag[] =
  36. {
  37. "PR_SockOpt_Nonblocking", /* nonblocking io */
  38. "PR_SockOpt_Linger", /* linger on close if data present */
  39. "PR_SockOpt_Reuseaddr", /* allow local address reuse */
  40. "PR_SockOpt_Keepalive", /* keep connections alive */
  41. "PR_SockOpt_RecvBufferSize", /* receive buffer size */
  42. "PR_SockOpt_SendBufferSize", /* send buffer size */
  43. "PR_SockOpt_IpTimeToLive", /* time to live */
  44. "PR_SockOpt_IpTypeOfService", /* type of service and precedence */
  45. "PR_SockOpt_AddMember", /* add an IP group membership */
  46. "PR_SockOpt_DropMember", /* drop an IP group membership */
  47. "PR_SockOpt_McastInterface", /* multicast interface address */
  48. "PR_SockOpt_McastTimeToLive", /* multicast timetolive */
  49. "PR_SockOpt_McastLoopback", /* multicast loopback */
  50. "PR_SockOpt_NoDelay", /* don't delay send to coalesce packets */
  51. "PR_SockOpt_MaxSegment", /* maximum segment size */
  52. "PR_SockOpt_Broadcast", /* Enable broadcast */
  53. "PR_SockOpt_Reuseport", /* allow local address & port reuse */
  54. "PR_SockOpt_Last"
  55. };
  56. err = PR_GetSpecialFD(PR_StandardError);
  57. PR_STDIO_INIT();
  58. if (NULL == udp) {
  59. Failed("PR_NewUDPSocket()", NULL);
  60. }
  61. else if (NULL == tcp) {
  62. Failed("PR_NewTCPSocket()", NULL);
  63. }
  64. else
  65. {
  66. PRSockOption option;
  67. PRUint32 segment = 1024;
  68. PRNetAddr addr;
  69. rv = PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr);
  70. if (PR_FAILURE == rv) {
  71. Failed("PR_InitializeNetAddr()", NULL);
  72. }
  73. rv = PR_Bind(udp, &addr);
  74. if (PR_FAILURE == rv) {
  75. Failed("PR_Bind()", NULL);
  76. }
  77. for(option = PR_SockOpt_Linger; option < PR_SockOpt_Last; Incr(&option))
  78. {
  79. PRSocketOptionData data;
  80. PRFileDesc *fd = tcp;
  81. data.option = option;
  82. switch (option)
  83. {
  84. case PR_SockOpt_Nonblocking:
  85. data.value.non_blocking = PR_TRUE;
  86. break;
  87. case PR_SockOpt_Linger:
  88. data.value.linger.polarity = PR_TRUE;
  89. data.value.linger.linger = PR_SecondsToInterval(2);
  90. break;
  91. case PR_SockOpt_Reuseaddr:
  92. data.value.reuse_addr = PR_TRUE;
  93. break;
  94. case PR_SockOpt_Keepalive:
  95. data.value.keep_alive = PR_TRUE;
  96. break;
  97. case PR_SockOpt_RecvBufferSize:
  98. data.value.recv_buffer_size = segment;
  99. break;
  100. case PR_SockOpt_SendBufferSize:
  101. data.value.send_buffer_size = segment;
  102. break;
  103. case PR_SockOpt_IpTimeToLive:
  104. data.value.ip_ttl = 64;
  105. break;
  106. case PR_SockOpt_IpTypeOfService:
  107. data.value.tos = 0;
  108. break;
  109. case PR_SockOpt_McastTimeToLive:
  110. fd = udp;
  111. data.value.mcast_ttl = 4;
  112. break;
  113. case PR_SockOpt_McastLoopback:
  114. fd = udp;
  115. data.value.mcast_loopback = PR_TRUE;
  116. break;
  117. case PR_SockOpt_NoDelay:
  118. data.value.no_delay = PR_TRUE;
  119. break;
  120. #ifndef WIN32
  121. case PR_SockOpt_MaxSegment:
  122. data.value.max_segment = segment;
  123. break;
  124. #endif
  125. case PR_SockOpt_Broadcast:
  126. fd = udp;
  127. data.value.broadcast = PR_TRUE;
  128. break;
  129. #ifdef SO_REUSEPORT
  130. case PR_SockOpt_Reuseport:
  131. data.value.reuse_port = PR_TRUE;
  132. break;
  133. #endif
  134. default: continue;
  135. }
  136. /*
  137. * TCP_MAXSEG can only be read, not set
  138. */
  139. if (option != PR_SockOpt_MaxSegment) {
  140. #ifdef WIN32
  141. if (option != PR_SockOpt_McastLoopback)
  142. #endif
  143. {
  144. rv = PR_SetSocketOption(fd, &data);
  145. if (PR_FAILURE == rv) {
  146. Failed("PR_SetSocketOption()", tag[option]);
  147. }
  148. }
  149. }
  150. rv = PR_GetSocketOption(fd, &data);
  151. if (PR_FAILURE == rv) {
  152. Failed("PR_GetSocketOption()", tag[option]);
  153. }
  154. }
  155. PR_Close(udp);
  156. PR_Close(tcp);
  157. }
  158. PR_fprintf(err, "%s\n", (failed) ? "FAILED" : "PASSED");
  159. return (failed) ? 1 : 0;
  160. } /* main */
  161. /* sockopt.c */