netsend-proto-and-obsd-includes-20021010
[openafs.git] / src / rx / DARWIN / rx_knet.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 #include <afsconfig.h>
11 #include "../afs/param.h"
12
13 RCSID("$Header$");
14
15 #include "../rx/rx_kcommon.h"
16
17 int osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,         
18         int nvecs, int *alength)
19 {
20     struct socket *asocket = (struct socket *)so;
21     struct uio u;
22     int i;
23     struct iovec iov[RX_MAXIOVECS];
24     struct sockaddr *sa;
25     int code;
26
27     int haveGlock = ISAFS_GLOCK();
28     /*AFS_STATCNT(osi_NetReceive);*/
29
30     if (nvecs > RX_MAXIOVECS) {
31         osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
32     }
33
34     for (i = 0 ; i < nvecs ; i++) {
35         iov[i].iov_base = dvec[i].iov_base;
36         iov[i].iov_len = dvec[i].iov_len;
37     }
38
39     u.uio_iov=&iov[0];
40     u.uio_iovcnt=nvecs;
41     u.uio_offset=0;
42     u.uio_resid=*alength;
43     u.uio_segflg=UIO_SYSSPACE; 
44     u.uio_rw=UIO_READ;
45     u.uio_procp=NULL;  
46
47     if (haveGlock) { 
48         AFS_GUNLOCK();
49     }
50 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
51     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
52 #endif
53     code = soreceive(asocket, &sa, &u, NULL, NULL, NULL);
54 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
55     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
56 #endif
57     if (haveGlock) {
58         AFS_GLOCK();
59     }
60     *alength=*alength-u.uio_resid;
61     if (sa) {
62        if (sa->sa_family == AF_INET) {
63           if (addr) *addr=*(struct sockaddr_in *)sa;
64        } else {
65           printf("Unknown socket family %d in NetReceive\n");
66        }
67     }
68     return code;
69 }
70
71 extern int rxk_ListenerPid;
72 void osi_StopListener(void)
73 {
74    struct proc *p;
75
76 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
77     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
78 #endif
79    soclose(rx_socket);
80 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
81     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
82 #endif
83    p=pfind(rxk_ListenerPid); 
84    if (p)
85        psignal(p, SIGUSR1);
86 }
87
88 /* rx_NetSend - send asize bytes at adata from asocket to host at addr.
89  *
90  * Now, why do we allocate a new buffer when we could theoretically use the one
91  * pointed to by adata?  Because PRU_SEND returns after queueing the message,
92  * not after sending it.  If the sender changes the data after queueing it,
93  * we'd see the already-queued data change.  One attempt to fix this without
94  * adding a copy would be to have this function wait until the datagram is
95  * sent; however this doesn't work well.  In particular, if a host is down, and
96  * an ARP fails to that host, this packet will be queued until the ARP request
97  * comes back, which could be hours later.  We can't block in this routine that
98  * long, since it prevents RPC timeouts from happening.
99  */
100 /* XXX In the brave new world, steal the data bufs out of the rx_packet iovec,
101  * and just queue those.  XXX
102  */
103
104
105 int 
106 osi_NetSend(osi_socket asocket, struct sockaddr_in *addr,
107             struct iovec *dvec, int nvecs, afs_int32 alength, int istack)
108 {
109     register afs_int32 code;
110     int s;
111     int len;
112     int i;
113     struct iovec iov[RX_MAXIOVECS];
114     char *tdata;
115     struct uio u;
116     struct mbuf *nam;
117     int haveGlock = ISAFS_GLOCK();
118
119     AFS_STATCNT(osi_NetSend);
120     if (nvecs > RX_MAXIOVECS) {
121         osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
122     } 
123
124     for (i = 0 ; i < nvecs ; i++) {
125         iov[i].iov_base = dvec[i].iov_base; 
126         iov[i].iov_len = dvec[i].iov_len; 
127     } 
128
129     u.uio_iov=&iov[0];
130     u.uio_iovcnt=nvecs;
131     u.uio_offset=0;
132     u.uio_resid=alength;
133     u.uio_segflg=UIO_SYSSPACE;
134     u.uio_rw=UIO_WRITE;
135     u.uio_procp=NULL;
136     if (haveGlock) {
137         AFS_GUNLOCK();
138     }
139 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
140     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
141 #endif
142     nam=m_get(M_DONTWAIT, MT_SONAME);
143     if (nam == NULL) {
144         code=ENOBUFS;
145         goto bad;
146     }
147     nam->m_len=addr->sin_len=sizeof(struct sockaddr_in);
148     memcpy(mtod(nam, caddr_t), (caddr_t)addr, addr->sin_len);
149     code = sosend(asocket, mtod(nam, struct sockaddr *), &u, NULL, NULL, 0);
150     m_freem(nam);
151 bad:
152 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
153     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
154 #endif
155     if (haveGlock) {
156         AFS_GLOCK();
157     }
158     return code;
159 }