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 <afsconfig.h>
11 #include "afs/param.h"
16 #include "rx/rx_kcommon.h"
19 #define SECONDS_TO_SLEEP 0
20 #define NANO_SECONDS_TO_SLEEP 100000000 /* 100 milliseconds */
21 #define LOOPS_PER_WAITCHECK 10 /* once per second */
23 unsigned short usr_rx_port = 0;
25 struct usr_ifnet *usr_ifnet = NULL;
26 struct usr_in_ifaddr *usr_in_ifaddr = NULL;
28 void rxk_InitializeSocket();
31 afs_rxevent_daemon(void)
39 tv.tv_sec = SECONDS_TO_SLEEP;
40 tv.tv_nsec = NANO_SECONDS_TO_SLEEP;
41 usr_thread_sleep(&tv);
43 * Check for shutdown, don't try to stop the listener
45 if (afs_termState == AFSOP_STOP_RXEVENT
46 || afs_termState == AFSOP_STOP_RXK_LISTENER) {
48 afs_termState = AFSOP_STOP_COMPLETE;
49 afs_osi_Wakeup(&afs_termState);
52 rxevent_RaiseEvents(&temp);
53 if (++i >= LOOPS_PER_WAITCHECK) {
55 afs_osi_CheckTimedWaits();
61 /* Loop to listen on a socket. Return setting *newcallp if this
62 * thread should become a server thread. */
64 rxi_ListenerProc(osi_socket usockp, int *tnop, struct rx_call **newcallp)
72 * Use the rxk_GetPacketProc and rxk_PacketArrivalProc routines
73 * to allocate rx_packet buffers and pass them to the RX layer
77 tp = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
78 usr_assert(tp != NULL);
79 rc = rxi_ReadPacket(usockp->sock, tp, &host, &port);
81 tp = rxi_ReceivePacket(tp, usockp, host, port, tnop, newcallp);
82 if (newcallp && *newcallp) {
92 if (afs_termState == AFSOP_STOP_RXEVENT) {
93 afs_termState = AFSOP_STOP_RXK_LISTENER;
94 afs_osi_Wakeup(&afs_termState);
99 /* This is the listener process request loop. The listener process loop
100 * becomes a server thread when rxi_ListenerProc returns, and stays
101 * server thread until rxi_ServerProc returns. */
106 osi_socket sock = (osi_socket) rx_socket;
107 struct rx_call *newcall;
108 struct usr_socket *usockp;
111 * Initialize the rx_socket and start the receiver threads
113 rxk_InitializeSocket();
115 usockp = (struct usr_socket *)rx_socket;
116 assert(usockp != NULL);
122 rxi_ListenerProc(sock, &threadID, &newcall);
123 /* assert(threadID != -1); */
124 /* assert(newcall != NULL); */
125 sock = OSI_NULLSOCKET;
126 rxi_ServerProc(threadID, newcall, &sock);
127 if (sock == OSI_NULLSOCKET) {
134 /* This is the server process request loop. The server process loop
135 * becomes a listener thread when rxi_ServerProc returns, and stays
136 * listener thread until rxi_ListenerProc returns. */
142 struct rx_call *newcall = NULL;
144 rxi_MorePackets(rx_maxReceiveWindow + 2); /* alloc more packets */
145 rxi_dataQuota += rx_initSendWindow; /* Reserve some pkts for hard times */
146 /* threadID is used for making decisions in GetCall. Get it by bumping
147 * number of threads handling incoming calls */
148 threadID = rxi_availProcs++;
152 sock = OSI_NULLSOCKET;
153 rxi_ServerProc(threadID, newcall, &sock);
154 if (sock == OSI_NULLSOCKET) {
159 rxi_ListenerProc(sock, &threadID, &newcall);
160 /* assert(threadID != -1); */
161 /* assert(newcall != NULL); */
167 * At this point, RX wants a socket, but still has not initialized the
168 * rx_port variable or the pointers to the packet allocater and arrival
169 * routines. Allocate the socket buffer here, but don't open it until
170 * we start the receiver threads.
173 rxk_NewSocketHost(afs_uint32 ahost, short aport)
175 struct usr_socket *usockp;
177 usockp = (struct usr_socket *)afs_osi_Alloc(sizeof(struct usr_socket));
178 usr_assert(usockp != NULL);
182 return (osi_socket *)usockp;
186 rxk_NewSocket(short aport)
188 return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
192 * This routine is called from rxk_Listener. By this time rx_port
193 * is set to 7001 and rx_socket points to the socket buffer
194 * we allocated in rxk_NewSocket. Now is the time to bind our
195 * socket and start the receiver threads.
198 rxk_InitializeSocket(void)
201 #ifdef AFS_USR_AIX_ENV
202 unsigned long len, optval, optval0, optlen;
203 #else /* AFS_USR_AIX_ENV */
204 int len, optval, optval0, optlen;
205 #endif /* AFS_USR_AIX_ENV */
206 struct usr_socket *usockp;
207 struct sockaddr_in lcladdr;
209 usr_assert(rx_socket != NULL);
210 usockp = (struct usr_socket *)rx_socket;
213 sock = socket(PF_INET, SOCK_DGRAM, 0);
214 usr_assert(sock >= 0);
216 memset((void *)&lcladdr, 0, sizeof(struct sockaddr_in));
217 lcladdr.sin_family = AF_INET;
218 lcladdr.sin_port = htons(usr_rx_port);
219 lcladdr.sin_addr.s_addr = INADDR_ANY;
220 rc = bind(sock, (struct sockaddr *)&lcladdr, sizeof(struct sockaddr_in));
222 len = sizeof(struct sockaddr_in);
223 rc = getsockname(sock, (struct sockaddr *)&lcladdr, &len);
225 #ifdef AFS_USR_LINUX22_ENV
231 rc = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&optval,
234 optlen = sizeof(optval);
235 rc = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&optval, &optlen);
237 /* usr_assert(optval == optval0); */
238 #ifdef AFS_USR_LINUX22_ENV
244 rc = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&optval,
247 optlen = sizeof(optval);
248 rc = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&optval, &optlen);
250 /* usr_assert(optval == optval0); */
252 #ifdef AFS_USR_AIX_ENV
254 rc = setsockopt(sock, SOL_SOCKET, SO_CKSUMRECV, (void *)&optval,
257 #endif /* AFS_USR_AIX_ENV */
260 usockp->port = lcladdr.sin_port;
263 * Set the value of rx_port to reflect the address we actually
264 * are listening on, since the kernel is probably already using 7001.
266 rx_port = usockp->port;
270 rxk_FreeSocket(struct usr_socket *sockp)
276 osi_StopListener(void)
278 rxk_FreeSocket((struct usr_socket *)rx_socket);
282 osi_NetSend(osi_socket sockp, struct sockaddr_in *addr, struct iovec *iov,
283 int nio, afs_int32 size, int stack)
288 struct usr_socket *usockp = (struct usr_socket *)sockp;
290 struct iovec tmpiov[64];
293 * The header is in the first iovec
295 usr_assert(nio > 0 && nio <= 64);
296 for (i = 0; i < nio; i++) {
297 tmpiov[i].iov_base = iov[i].iov_base;
298 tmpiov[i].iov_len = iov[i].iov_len;
301 memset(&msg, 0, sizeof(msg));
302 msg.msg_name = (void *)addr;
303 msg.msg_namelen = sizeof(struct sockaddr_in);
304 msg.msg_iov = &tmpiov[0];
305 msg.msg_iovlen = nio;
307 rc = sendmsg(usockp->sock, &msg, 0);
311 usr_assert(rc == size);
317 shutdown_rxkernel(void)
334 rxi_Recvmsg(osi_socket socket, struct msghdr *msg_p, int flags)
338 ret = recvmsg(socket, msg_p, flags);
339 } while (ret == -1 && errno == EAGAIN);