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 */
22 unsigned short usr_rx_port
= 0;
24 struct usr_ifnet
*usr_ifnet
= NULL
;
25 struct usr_in_ifaddr
*usr_in_ifaddr
= NULL
;
27 void rxk_InitializeSocket(void);
28 extern int afs_osi_CheckTimedWaits(void);
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 /* See if a check for additional packets was issued */
80 tp
= rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE
);
81 usr_assert(tp
!= NULL
);
82 rc
= rxi_ReadPacket(usockp
, tp
, &host
, &port
);
84 tp
= rxi_ReceivePacket(tp
, usockp
, host
, port
, tnop
, newcallp
);
85 if (newcallp
&& *newcallp
) {
95 if (afs_termState
== AFSOP_STOP_RXEVENT
) {
96 afs_termState
= AFSOP_STOP_RXK_LISTENER
;
97 afs_osi_Wakeup(&afs_termState
);
102 /* This is the listener process request loop. The listener process loop
103 * becomes a server thread when rxi_ListenerProc returns, and stays
104 * server thread until rxi_ServerProc returns. */
109 osi_socket sock
= (osi_socket
) rx_socket
;
110 struct rx_call
*newcall
;
111 struct usr_socket
*usockp
;
114 * Initialize the rx_socket and start the receiver threads
116 rxk_InitializeSocket();
118 usockp
= (struct usr_socket
*)rx_socket
;
119 assert(usockp
!= NULL
);
125 rxi_ListenerProc(sock
, &threadID
, &newcall
);
126 /* assert(threadID != -1); */
127 /* assert(newcall != NULL); */
128 sock
= OSI_NULLSOCKET
;
129 rxi_ServerProc(threadID
, newcall
, &sock
);
130 if (sock
== OSI_NULLSOCKET
) {
137 /* This is the server process request loop. The server process loop
138 * becomes a listener thread when rxi_ServerProc returns, and stays
139 * listener thread until rxi_ListenerProc returns. */
141 rx_ServerProc(void *unused
)
145 struct rx_call
*newcall
= NULL
;
147 rxi_MorePackets(rx_maxReceiveWindow
+ 2); /* alloc more packets */
148 rxi_dataQuota
+= rx_initSendWindow
; /* Reserve some pkts for hard times */
149 /* threadID is used for making decisions in GetCall. Get it by bumping
150 * number of threads handling incoming calls */
151 threadID
= rxi_availProcs
++;
155 sock
= OSI_NULLSOCKET
;
156 rxi_ServerProc(threadID
, newcall
, &sock
);
157 if (sock
== OSI_NULLSOCKET
) {
162 rxi_ListenerProc(sock
, &threadID
, &newcall
);
163 /* assert(threadID != -1); */
164 /* assert(newcall != NULL); */
171 * At this point, RX wants a socket, but still has not initialized the
172 * rx_port variable or the pointers to the packet allocater and arrival
173 * routines. Allocate the socket buffer here, but don't open it until
174 * we start the receiver threads.
177 rxk_NewSocketHost(afs_uint32 ahost
, short aport
)
179 struct usr_socket
*usockp
;
181 usockp
= afs_osi_Alloc(sizeof(struct usr_socket
));
182 usr_assert(usockp
!= NULL
);
186 return (osi_socket
*)usockp
;
190 rxk_NewSocket(short aport
)
192 return rxk_NewSocketHost(htonl(INADDR_ANY
), aport
);
196 * This routine is called from rxk_Listener. By this time rx_port
197 * is set to 7001 and rx_socket points to the socket buffer
198 * we allocated in rxk_NewSocket. Now is the time to bind our
199 * socket and start the receiver threads.
202 rxk_InitializeSocket(void)
205 #ifdef AFS_USR_AIX_ENV
206 unsigned long len
, optval
, optval0
, optlen
;
207 #else /* AFS_USR_AIX_ENV */
208 socklen_t len
, optlen
;
210 #endif /* AFS_USR_AIX_ENV */
211 struct usr_socket
*usockp
;
212 struct sockaddr_in lcladdr
;
214 usr_assert(rx_socket
!= NULL
);
215 usockp
= (struct usr_socket
*)rx_socket
;
218 sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
219 usr_assert(sock
>= 0);
221 memset((void *)&lcladdr
, 0, sizeof(struct sockaddr_in
));
222 lcladdr
.sin_family
= AF_INET
;
223 lcladdr
.sin_port
= htons(usr_rx_port
);
224 lcladdr
.sin_addr
.s_addr
= INADDR_ANY
;
225 rc
= bind(sock
, (struct sockaddr
*)&lcladdr
, sizeof(struct sockaddr_in
));
227 len
= sizeof(struct sockaddr_in
);
228 rc
= getsockname(sock
, (struct sockaddr
*)&lcladdr
, &len
);
230 #ifdef AFS_USR_LINUX22_ENV
236 rc
= setsockopt(sock
, SOL_SOCKET
, SO_SNDBUF
, (void *)&optval
,
239 optlen
= sizeof(optval
);
240 rc
= getsockopt(sock
, SOL_SOCKET
, SO_SNDBUF
, (void *)&optval
, &optlen
);
242 /* usr_assert(optval == optval0); */
243 #ifdef AFS_USR_LINUX22_ENV
249 rc
= setsockopt(sock
, SOL_SOCKET
, SO_RCVBUF
, (void *)&optval
,
252 optlen
= sizeof(optval
);
253 rc
= getsockopt(sock
, SOL_SOCKET
, SO_RCVBUF
, (void *)&optval
, &optlen
);
255 /* usr_assert(optval == optval0); */
257 #ifdef AFS_USR_AIX_ENV
259 rc
= setsockopt(sock
, SOL_SOCKET
, SO_CKSUMRECV
, (void *)&optval
,
262 #endif /* AFS_USR_AIX_ENV */
265 fcntl(sock
, F_SETFD
, FD_CLOEXEC
);
269 usockp
->port
= lcladdr
.sin_port
;
272 * Set the value of rx_port to reflect the address we actually
273 * are listening on, since the kernel is probably already using 7001.
275 rx_port
= usockp
->port
;
279 rxk_FreeSocket(struct usr_socket
*sockp
)
285 osi_StopListener(void)
287 rxk_FreeSocket((struct usr_socket
*)rx_socket
);
291 osi_NetSend(osi_socket sockp
, struct sockaddr_in
*addr
, struct iovec
*iov
,
292 int nio
, afs_int32 size
, int stack
)
296 struct usr_socket
*usockp
= (struct usr_socket
*)sockp
;
298 struct iovec tmpiov
[64];
301 * The header is in the first iovec
303 usr_assert(nio
> 0 && nio
<= 64);
304 for (i
= 0; i
< nio
; i
++) {
305 tmpiov
[i
].iov_base
= iov
[i
].iov_base
;
306 tmpiov
[i
].iov_len
= iov
[i
].iov_len
;
309 memset(&msg
, 0, sizeof(msg
));
310 msg
.msg_name
= (void *)addr
;
311 msg
.msg_namelen
= sizeof(struct sockaddr_in
);
312 msg
.msg_iov
= &tmpiov
[0];
313 msg
.msg_iovlen
= nio
;
315 rc
= sendmsg(usockp
->sock
, &msg
, 0);
319 usr_assert(rc
== size
);
325 shutdown_rxkernel(void)
342 rxi_Recvmsg(osi_socket socket
, struct msghdr
*msg_p
, int flags
)
346 ret
= recvmsg(socket
->sock
, msg_p
, flags
);
347 } while (ret
== -1 && errno
== EAGAIN
);