2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include "../afs/param.h"
11 #include "../rx/rx_kcommon.h"
14 #define SECONDS_TO_SLEEP 0
15 #define NANO_SECONDS_TO_SLEEP 100000000 /* 100 milliseconds */
16 #define LOOPS_PER_WAITCHECK 10 /* once per second */
18 unsigned short usr_rx_port = 0;
20 struct usr_ifnet *usr_ifnet = NULL;
21 struct usr_in_ifaddr *usr_in_ifaddr = NULL;
23 void rxk_InitializeSocket();
25 void afs_rxevent_daemon(argp)
34 tv.tv_sec = SECONDS_TO_SLEEP;
35 tv.tv_nsec = NANO_SECONDS_TO_SLEEP;
36 usr_thread_sleep(&tv);
38 * Check for shutdown, don't try to stop the listener
40 if (afs_termState == AFSOP_STOP_RXEVENT ||
41 afs_termState == AFSOP_STOP_RXK_LISTENER) {
43 afs_termState = AFSOP_STOP_COMPLETE;
44 afs_osi_Wakeup(&afs_termState);
47 rxevent_RaiseEvents(&temp);
48 if (++i >= LOOPS_PER_WAITCHECK) {
50 afs_osi_CheckTimedWaits();
56 /* Loop to listen on a socket. Return setting *newcallp if this
57 * thread should become a server thread. */
58 void rxi_ListenerProc(usockp, tnop, newcallp)
61 struct rx_call **newcallp;
69 * Use the rxk_GetPacketProc and rxk_PacketArrivalProc routines
70 * to allocate rx_packet buffers and pass them to the RX layer
74 tp = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
75 usr_assert(tp != NULL);
76 rc = rxi_ReadPacket(usockp->sock, tp, &host, &port);
78 tp = rxi_ReceivePacket(tp, usockp, host, port, tnop, newcallp);
79 if (newcallp && *newcallp) {
89 if (afs_termState == AFSOP_STOP_RXEVENT ) {
90 afs_termState = AFSOP_STOP_RXK_LISTENER;
91 afs_osi_Wakeup(&afs_termState);
96 /* This is the listener process request loop. The listener process loop
97 * becomes a server thread when rxi_ListenerProc returns, and stays
98 * server thread until rxi_ServerProc returns. */
99 void rxk_Listener(void)
102 osi_socket sock = (osi_socket) rx_socket;
103 struct rx_call *newcall;
104 struct usr_socket *usockp;
107 * Initialize the rx_socket and start the receiver threads
109 rxk_InitializeSocket();
111 usockp = (struct usr_socket *)rx_socket;
112 assert(usockp != NULL);
118 rxi_ListenerProc(sock, &threadID, &newcall);
119 /* assert(threadID != -1); */
120 /* assert(newcall != NULL); */
121 sock = OSI_NULLSOCKET;
122 rxi_ServerProc(threadID, newcall, &sock);
123 if (sock == OSI_NULLSOCKET) {
130 /* This is the server process request loop. The server process loop
131 * becomes a listener thread when rxi_ServerProc returns, and stays
132 * listener thread until rxi_ListenerProc returns. */
137 struct rx_call *newcall = NULL;
139 rxi_MorePackets(rx_maxReceiveWindow+2); /* alloc more packets */
140 rxi_dataQuota += rx_initSendWindow; /* Reserve some pkts for hard times */
141 /* threadID is used for making decisions in GetCall. Get it by bumping
142 * number of threads handling incoming calls */
143 threadID = rxi_availProcs++;
147 sock = OSI_NULLSOCKET;
148 rxi_ServerProc(threadID, newcall, &sock);
149 if (sock == OSI_NULLSOCKET) {
154 rxi_ListenerProc(sock, &threadID, &newcall);
155 /* assert(threadID != -1); */
156 /* assert(newcall != NULL); */
162 * At this point, RX wants a socket, but still has not initialized the
163 * rx_port variable or the pointers to the packet allocater and arrival
164 * routines. Allocate the socket buffer here, but don't open it until
165 * we start the receiver threads.
167 struct osi_socket *rxk_NewSocket(short aport)
169 struct usr_socket *usockp;
171 usockp = (struct usr_socket *)afs_osi_Alloc(sizeof(struct usr_socket));
172 usr_assert(usockp != NULL);
176 return (struct osi_socket *)usockp;
180 * This routine is called from rxk_Listener. By this time rx_port
181 * is set to 7001 and rx_socket points to the socket buffer
182 * we allocated in rxk_NewSocket. Now is the time to bind our
183 * socket and start the receiver threads.
185 void rxk_InitializeSocket()
188 #ifdef AFS_USR_AIX_ENV
189 unsigned long len, optval, optval0, optlen;
190 #else /* AFS_USR_AIX_ENV */
191 int len, optval, optval0, optlen;
192 #endif /* AFS_USR_AIX_ENV */
193 struct usr_socket *usockp;
194 struct sockaddr_in lcladdr;
196 usr_assert(rx_socket != NULL);
197 usockp = (struct usr_socket *)rx_socket;
200 sock = socket(PF_INET, SOCK_DGRAM, 0);
201 usr_assert(sock >= 0);
203 memset((void *)&lcladdr, 0, sizeof(struct sockaddr_in));
204 lcladdr.sin_family = AF_INET;
205 lcladdr.sin_port = htons(usr_rx_port);
206 lcladdr.sin_addr.s_addr = INADDR_ANY;
207 rc = bind(sock, (struct sockaddr *)&lcladdr, sizeof(struct sockaddr_in));
209 len = sizeof(struct sockaddr_in);
210 rc = getsockname(sock, (struct sockaddr *)&lcladdr, &len);
212 #ifdef AFS_USR_LINUX22_ENV
218 rc = setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
219 (void *)&optval, sizeof(optval));
221 optlen = sizeof(optval);
222 rc = getsockopt(sock, SOL_SOCKET, SO_SNDBUF,
223 (void *)&optval, &optlen);
225 usr_assert(optval == optval0);
226 #ifdef AFS_USR_LINUX22_ENV
232 rc = setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
233 (void *)&optval, sizeof(optval));
235 optlen = sizeof(optval);
236 rc = getsockopt(sock, SOL_SOCKET, SO_RCVBUF,
237 (void *)&optval, &optlen);
239 usr_assert(optval == optval0);
241 #ifdef AFS_USR_AIX_ENV
243 rc = setsockopt(sock, SOL_SOCKET, SO_CKSUMRECV,
244 (void *)&optval, sizeof(optval));
246 #endif /* AFS_USR_AIX_ENV */
249 usockp->port = lcladdr.sin_port;
252 * Set the value of rx_port to reflect the address we actually
253 * are listening on, since the kernel is probably already using 7001.
255 rx_port = usockp->port;
258 int rxk_FreeSocket(sockp)
259 struct usr_socket *sockp;
264 void osi_StopListener(void)
266 rxk_FreeSocket((struct usr_socket *)rx_socket);
269 int osi_NetSend(sockp, addr, iov, nio, size, stack)
270 struct osi_socket *sockp;
271 struct sockaddr_in *addr;
280 struct usr_socket *usockp = (struct usr_socket *)sockp;
282 struct iovec tmpiov[64];
285 * The header is in the first iovec
287 usr_assert(nio > 0 && nio <= 64);
288 for (i = 0 ; i < nio ; i++) {
289 tmpiov[i].iov_base = iov[i].iov_base;
290 tmpiov[i].iov_len = iov[i].iov_len;
293 memset(&msg, 0, sizeof(msg));
294 msg.msg_name = (void *)addr;
295 msg.msg_namelen = sizeof(struct sockaddr_in);
296 msg.msg_iov = &tmpiov[0];
297 msg.msg_iovlen = nio;
299 rc = sendmsg(usockp->sock, &msg, 0);
303 usr_assert(rc == size);
308 void shutdown_rxkernel(void)
325 struct msghdr *msg_p,
330 ret = recvmsg(socket, msg_p, flags);
331 } while (ret == -1 && errno == EAGAIN);