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"
14 #include "rx/rx_kcommon.h"
15 #include "rx_atomic.h"
16 #include "rx_internal.h"
18 #define SECONDS_TO_SLEEP 0
19 #define NANO_SECONDS_TO_SLEEP 100000000 /* 100 milliseconds */
20 #define LOOPS_PER_WAITCHECK 10 /* once per second */
27 unsigned short usr_rx_port = 0;
29 struct usr_ifnet *usr_ifnet = NULL;
30 struct usr_in_ifaddr *usr_in_ifaddr = NULL;
32 void rxk_InitializeSocket(void);
33 extern int afs_osi_CheckTimedWaits(void);
36 afs_rxevent_daemon(void)
44 tv.tv_sec = SECONDS_TO_SLEEP;
45 tv.tv_nsec = NANO_SECONDS_TO_SLEEP;
46 usr_thread_sleep(&tv);
48 * Check for shutdown, don't try to stop the listener
50 if (afs_termState == AFSOP_STOP_RXEVENT
51 || afs_termState == AFSOP_STOP_RXK_LISTENER) {
53 afs_termState = AFSOP_STOP_COMPLETE;
54 afs_osi_Wakeup(&afs_termState);
57 rxevent_RaiseEvents(&temp);
58 if (++i >= LOOPS_PER_WAITCHECK) {
60 afs_osi_CheckTimedWaits();
66 /* Loop to listen on a socket. Return setting *newcallp if this
67 * thread should become a server thread. */
69 rxi_ListenerProc(osi_socket usockp, int *tnop, struct rx_call **newcallp)
77 * Use the rxk_GetPacketProc and rxk_PacketArrivalProc routines
78 * to allocate rx_packet buffers and pass them to the RX layer
82 /* See if a check for additional packets was issued */
85 tp = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
86 usr_assert(tp != NULL);
87 rc = rxi_ReadPacket(usockp, tp, &host, &port);
89 tp = rxi_ReceivePacket(tp, usockp, host, port, tnop, newcallp);
90 if (newcallp && *newcallp) {
100 if (afs_termState == AFSOP_STOP_RXEVENT) {
101 afs_termState = AFSOP_STOP_RXK_LISTENER;
102 afs_osi_Wakeup(&afs_termState);
107 /* This is the listener process request loop. The listener process loop
108 * becomes a server thread when rxi_ListenerProc returns, and stays
109 * server thread until rxi_ServerProc returns. */
114 osi_socket sock = (osi_socket) rx_socket;
115 struct rx_call *newcall;
116 struct usr_socket *usockp;
119 * Initialize the rx_socket and start the receiver threads
121 rxk_InitializeSocket();
123 usockp = (struct usr_socket *)rx_socket;
124 assert(usockp != NULL);
130 rxi_ListenerProc(sock, &threadID, &newcall);
131 /* assert(threadID != -1); */
132 /* assert(newcall != NULL); */
133 sock = OSI_NULLSOCKET;
134 rxi_ServerProc(threadID, newcall, &sock);
135 if (sock == OSI_NULLSOCKET) {
142 /* This is the server process request loop. The server process loop
143 * becomes a listener thread when rxi_ServerProc returns, and stays
144 * listener thread until rxi_ListenerProc returns. */
146 rx_ServerProc(void *unused)
150 struct rx_call *newcall = NULL;
152 rxi_MorePackets(rx_maxReceiveWindow + 2); /* alloc more packets */
153 rxi_dataQuota += rx_initSendWindow; /* Reserve some pkts for hard times */
154 /* threadID is used for making decisions in GetCall. Get it by bumping
155 * number of threads handling incoming calls */
156 threadID = rxi_availProcs++;
160 sock = OSI_NULLSOCKET;
161 rxi_ServerProc(threadID, newcall, &sock);
162 if (sock == OSI_NULLSOCKET) {
167 rxi_ListenerProc(sock, &threadID, &newcall);
168 /* assert(threadID != -1); */
169 /* assert(newcall != NULL); */
176 * At this point, RX wants a socket, but still has not initialized the
177 * rx_port variable or the pointers to the packet allocater and arrival
178 * routines. Allocate the socket buffer here, but don't open it until
179 * we start the receiver threads.
182 rxk_NewSocketHost(afs_uint32 ahost, short aport)
184 struct usr_socket *usockp;
186 usockp = afs_osi_Alloc(sizeof(struct usr_socket));
187 usr_assert(usockp != NULL);
191 return (osi_socket *)usockp;
195 rxk_NewSocket(short aport)
197 return rxk_NewSocketHost(htonl(INADDR_ANY), aport);
201 * This routine is called from rxk_Listener. By this time rx_port
202 * is set to 7001 and rx_socket points to the socket buffer
203 * we allocated in rxk_NewSocket. Now is the time to bind our
204 * socket and start the receiver threads.
207 rxk_InitializeSocket(void)
210 #ifdef AFS_USR_AIX_ENV
211 unsigned long len, optval, optval0, optlen;
212 #else /* AFS_USR_AIX_ENV */
213 socklen_t len, optlen;
215 #endif /* AFS_USR_AIX_ENV */
216 struct usr_socket *usockp;
217 struct sockaddr_in lcladdr;
219 usr_assert(rx_socket != NULL);
220 usockp = (struct usr_socket *)rx_socket;
222 sock = socket(PF_INET, SOCK_DGRAM, 0);
223 usr_assert(sock >= 0);
225 memset((void *)&lcladdr, 0, sizeof(struct sockaddr_in));
226 lcladdr.sin_family = AF_INET;
227 lcladdr.sin_port = htons(usr_rx_port);
228 lcladdr.sin_addr.s_addr = INADDR_ANY;
229 rc = bind(sock, (struct sockaddr *)&lcladdr, sizeof(struct sockaddr_in));
231 len = sizeof(struct sockaddr_in);
232 rc = getsockname(sock, (struct sockaddr *)&lcladdr, &len);
234 #ifdef AFS_USR_LINUX_ENV
240 rc = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&optval,
243 optlen = sizeof(optval);
244 rc = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&optval, &optlen);
246 /* usr_assert(optval == optval0); */
247 #ifdef AFS_USR_LINUX_ENV
253 rc = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&optval,
256 optlen = sizeof(optval);
257 rc = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&optval, &optlen);
259 /* usr_assert(optval == optval0); */
261 #ifdef AFS_USR_AIX_ENV
263 rc = setsockopt(sock, SOL_SOCKET, SO_CKSUMRECV, (void *)&optval,
266 #endif /* AFS_USR_AIX_ENV */
269 fcntl(sock, F_SETFD, FD_CLOEXEC);
273 usockp->port = lcladdr.sin_port;
276 * Set the value of rx_port to reflect the address we actually
277 * are listening on, since the kernel is probably already using 7001.
279 rx_port = usockp->port;
283 rxk_FreeSocket(struct usr_socket *sockp)
289 osi_StopListener(void)
291 rxk_FreeSocket((struct usr_socket *)rx_socket);
295 osi_NetSend(osi_socket sockp, struct sockaddr_in *addr, struct iovec *iov,
296 int nio, afs_int32 size, int stack)
300 struct usr_socket *usockp = (struct usr_socket *)sockp;
302 struct iovec tmpiov[64];
305 * The header is in the first iovec
307 usr_assert(nio > 0 && nio <= 64);
308 for (i = 0; i < nio; i++) {
309 tmpiov[i].iov_base = iov[i].iov_base;
310 tmpiov[i].iov_len = iov[i].iov_len;
313 memset(&msg, 0, sizeof(msg));
314 msg.msg_name = (void *)addr;
315 msg.msg_namelen = sizeof(struct sockaddr_in);
316 msg.msg_iov = &tmpiov[0];
317 msg.msg_iovlen = nio;
319 rc = sendmsg(usockp->sock, &msg, 0);
323 usr_assert(rc == size);
329 shutdown_rxkernel(void)
346 rxi_Recvmsg(osi_socket socket, struct msghdr *msg_p, int flags)
348 struct usr_socket *usock = (struct usr_socket *)socket;
351 ret = recvmsg(usock->sock, msg_p, flags);
352 } while (ret == -1 && errno == EAGAIN);