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