4c56679e5043fe9ffe10af58ea280381a3053dbf
[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) || defined(AFS_DJGPP_ENV)
24
25 #ifdef AFS_NT40_ENV
26 #include <winsock2.h>
27 #else
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 typedef int SOCKET;
36 #endif
37
38 #include "rx.h"
39 #include "rx_packet.h"
40 #include "rx_globals.h"
41 #include "rx_xmit_nt.h"
42 #ifdef AFS_NT40_ENV
43 #include <malloc.h>
44 #endif
45 #include <errno.h>
46
47 int
48 recvmsg(int socket, struct msghdr *msgP, int flags)
49 {
50     char rbuf[RX_MAX_PACKET_SIZE];
51     int size;
52     int code;
53     int off, i, n;
54     int allocd = 0;
55
56
57     size = rx_maxJumboRecvSize;
58     code =
59         recvfrom((SOCKET) socket, rbuf, size, flags,
60                  (struct sockaddr *)(msgP->msg_name), &(msgP->msg_namelen));
61
62     if (code > 0) {
63         size = code;
64
65         for (off = i = 0; size > 0 && i < msgP->msg_iovlen; i++) {
66             if (msgP->msg_iov[i].iov_len) {
67                 if (msgP->msg_iov[i].iov_len < size) {
68                     n = msgP->msg_iov[i].iov_len;
69                 } else {
70                     n = size;
71                 }
72                 memcpy(msgP->msg_iov[i].iov_base, &rbuf[off], n);
73                 off += n;
74                 size -= n;
75             }
76         }
77
78         /* Accounts for any we didn't copy in to iovecs. */
79         code -= size;
80     } else {
81 #ifdef AFS_NT40_ENV
82     if (code == SOCKET_ERROR)
83         code = WSAGetLastError();
84     if (code == WSAEWOULDBLOCK)
85         errno = WSAEWOULDBLOCK;
86     else
87         errno = EIO;
88 #endif /* AFS_NT40_ENV */
89         code = -1;
90     }
91
92     return code;
93 }
94
95 int
96 sendmsg(int socket, struct msghdr *msgP, int flags)
97 {
98     char buf[RX_MAX_PACKET_SIZE];
99     char *sbuf = buf;
100     int size, tmp;
101     int code;
102     int off, i, n;
103     int allocd = 0;
104
105     for (size = i = 0; i < msgP->msg_iovlen; i++)
106         size += msgP->msg_iov[i].iov_len;
107
108     if (msgP->msg_iovlen <= 2) {
109         sbuf = msgP->msg_iov[0].iov_base;
110     } else {
111         /* Pack data into array from iovecs */
112         tmp = size;
113         for (off = i = 0; tmp > 0 && i < msgP->msg_iovlen; i++) {
114             if (msgP->msg_iov[i].iov_len > 0) {
115                 if (tmp > msgP->msg_iov[i].iov_len)
116                     n = msgP->msg_iov[i].iov_len;
117                 else
118                     n = tmp;
119                 memcpy(&sbuf[off], msgP->msg_iov[i].iov_base, n);
120                 off += n;
121                 tmp -= n;
122             }
123         }
124     }
125
126     code =
127         sendto((SOCKET) socket, sbuf, size, flags,
128                (struct sockaddr *)(msgP->msg_name), msgP->msg_namelen);
129
130 #ifdef AFS_NT40_ENV
131     if (code == SOCKET_ERROR) {
132         code = WSAGetLastError();
133         switch (code) {
134         case WSAEINPROGRESS:
135         case WSAENETRESET:
136         case WSAENOBUFS:
137             errno = 0;
138             break;
139     case WSAEWOULDBLOCK:
140         errno = WSAEWOULDBLOCK;
141         break;
142         default:
143             errno = EIO;
144             break;
145         }
146         code = -1;
147     }
148 #endif /* AFS_NT40_ENV */
149
150     if (code < size) {
151         errno = EIO;
152         code = -1;
153     }
154
155     return code;
156
157 }
158 #endif /* AFS_NT40_ENV || AFS_DJGPP_ENV */