f8ce9a350bd6e9f3997896c734b8646be82cfe86
[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         code = -1;
82     }
83
84     return code;
85 }
86
87 int
88 sendmsg(int socket, struct msghdr *msgP, int flags)
89 {
90     char buf[RX_MAX_PACKET_SIZE];
91     char *sbuf = buf;
92     int size, tmp;
93     int code;
94     int off, i, n;
95     int allocd = 0;
96
97     for (size = i = 0; i < msgP->msg_iovlen; i++)
98         size += msgP->msg_iov[i].iov_len;
99
100     if (msgP->msg_iovlen <= 2) {
101         sbuf = msgP->msg_iov[0].iov_base;
102     } else {
103         /* Pack data into array from iovecs */
104         tmp = size;
105         for (off = i = 0; tmp > 0 && i < msgP->msg_iovlen; i++) {
106             if (msgP->msg_iov[i].iov_len > 0) {
107                 if (tmp > msgP->msg_iov[i].iov_len)
108                     n = msgP->msg_iov[i].iov_len;
109                 else
110                     n = tmp;
111                 memcpy(&sbuf[off], msgP->msg_iov[i].iov_base, n);
112                 off += n;
113                 tmp -= n;
114             }
115         }
116     }
117
118     code =
119         sendto((SOCKET) socket, sbuf, size, flags,
120                (struct sockaddr *)(msgP->msg_name), msgP->msg_namelen);
121
122 #ifdef AFS_NT40_ENV
123     if (code == SOCKET_ERROR) {
124         code = WSAGetLastError();
125         switch (code) {
126         case WSAEINPROGRESS:
127         case WSAENETRESET:
128         case WSAEWOULDBLOCK:
129         case WSAENOBUFS:
130             errno = 0;
131             break;
132         default:
133             errno = EIO;
134             break;
135         }
136         code = -1;
137     }
138 #endif /* AFS_NT40_ENV */
139
140     if (code < size) {
141         errno = EIO;
142         code = -1;
143     }
144
145     return code;
146
147 }
148
149
150
151
152 #endif /* AFS_NT40_ENV || AFS_DJGPP_ENV */