63b02a67074693616bed6f85980b1a380aef732f
[openafs.git] / src / rx / rx_xmit_nt.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 /* NT does not have uio structs, so we roll our own sendmsg and recvmsg.
11  *
12  * The dangerous part of this code is that it assumes that iovecs 0 and 1
13  * are contiguous and that all of 0 is used before any of 1.
14  * This is true if rx_packets are being sent, so we should be ok.
15  */
16
17 #include <afsconfig.h>
18 #include <afs/param.h>
19
20 RCSID
21     ("$Header$");
22
23 #if defined(AFS_NT40_ENV) 
24
25 #include <winsock2.h>
26
27 #include "rx.h"
28 #include "rx_packet.h"
29 #include "rx_globals.h"
30 #include "rx_xmit_nt.h"
31 #ifdef AFS_NT40_ENV
32 #include <malloc.h>
33 #endif
34 #include <errno.h>
35
36 int
37 recvmsg(osi_socket socket, struct msghdr *msgP, int flags)
38 {
39     char rbuf[RX_MAX_PACKET_SIZE];
40     int size;
41     int code;
42     int off, i, n;
43     int allocd = 0;
44
45
46     size = rx_maxJumboRecvSize;
47     code =
48         recvfrom((SOCKET) socket, rbuf, size, flags,
49                  (struct sockaddr *)(msgP->msg_name), &(msgP->msg_namelen));
50
51     if (code > 0) {
52         size = code;
53
54         for (off = i = 0; size > 0 && i < msgP->msg_iovlen; i++) {
55             if (msgP->msg_iov[i].iov_len) {
56                 if (msgP->msg_iov[i].iov_len < size) {
57                     n = msgP->msg_iov[i].iov_len;
58                 } else {
59                     n = size;
60                 }
61                 memcpy(msgP->msg_iov[i].iov_base, &rbuf[off], n);
62                 off += n;
63                 size -= n;
64             }
65         }
66
67         /* Accounts for any we didn't copy in to iovecs. */
68         code -= size;
69     } else {
70 #ifdef AFS_NT40_ENV
71         if (code == SOCKET_ERROR)
72             code = WSAGetLastError();
73         if (code == WSAEWOULDBLOCK || code == WSAECONNRESET)
74             errno = WSAEWOULDBLOCK;
75         else
76             errno = EIO;
77 #endif /* AFS_NT40_ENV */
78         code = -1;
79     }
80
81     return code;
82 }
83
84 int
85 sendmsg(osi_socket socket, struct msghdr *msgP, int flags)
86 {
87     char buf[RX_MAX_PACKET_SIZE];
88     char *sbuf = buf;
89     int size, tmp;
90     int code;
91     int off, i, n;
92     int allocd = 0;
93
94     for (size = i = 0; i < msgP->msg_iovlen; i++)
95         size += msgP->msg_iov[i].iov_len;
96
97     if (msgP->msg_iovlen <= 2) {
98         sbuf = msgP->msg_iov[0].iov_base;
99     } else {
100         /* Pack data into array from iovecs */
101         tmp = size;
102         for (off = i = 0; tmp > 0 && i < msgP->msg_iovlen; i++) {
103             if (msgP->msg_iov[i].iov_len > 0) {
104                 if (tmp > msgP->msg_iov[i].iov_len)
105                     n = msgP->msg_iov[i].iov_len;
106                 else
107                     n = tmp;
108                 memcpy(&sbuf[off], msgP->msg_iov[i].iov_base, n);
109                 off += n;
110                 tmp -= n;
111             }
112         }
113     }
114
115     code =
116         sendto((SOCKET) socket, sbuf, size, flags,
117                (struct sockaddr *)(msgP->msg_name), msgP->msg_namelen);
118
119 #ifdef AFS_NT40_ENV
120     if (code == SOCKET_ERROR) {
121         code = WSAGetLastError();
122         switch (code) {
123         case WSAEINPROGRESS:
124         case WSAENETRESET:
125         case WSAENOBUFS:
126             errno = 0;
127             break;
128         case WSAEWOULDBLOCK:
129         case WSAECONNRESET:
130             errno = WSAEWOULDBLOCK;
131             break;
132         case WSAEHOSTUNREACH:
133                 errno = WSAEHOSTUNREACH;
134                 break;
135         default:
136             errno = EIO;
137             break;
138         }
139         code = -1;
140     } else
141 #endif /* AFS_NT40_ENV */
142
143     if (code < size) {
144         errno = EIO;
145         code = -1;
146     }
147
148     return code;
149
150 }
151 #endif /* AFS_NT40_ENV */