1 /****************************************************************
2 **
3 ** PORTTCP.C - Support for portable TCP/IP
4 **
5 ****************************************************************/
6
7 #define TCPIP_IBM_NOHIDE
8 #include <stdio.h>
9 #include "tcpip.h"
10
11 /*
12 * Common unknown error buffer
13 */
14 static char ErrUnknownBuf[36];
15
16 #ifndef SockStrError
17
18 /****************************************************************
19 * Routine: SockStrError
20 * Returns: Pointer to static buffer
21 * Action : Convert SOCK_ERRNO into error text
22 ****************************************************************/
23
24 const char *
SockStrError(int SockErrno)25 SockStrError(int SockErrno)
26 {
27 #if defined (TCPIP_IBM) && defined (IBM_CPP)
28 switch (SockErrno)
29 {
30 case SOCEPERM: return "Not owner";
31 case SOCESRCH: return "No such process";
32 case SOCEINTR: return "Interrupted system call";
33 case SOCENXIO: return "No such device or address";
34 case SOCEBADF: return "Bad file number";
35 case SOCEACCES: return "Permission denied";
36 case SOCEFAULT: return "Bad address";
37 case SOCEINVAL: return "Invalid argument";
38 case SOCEMFILE: return "Too many open files";
39 case SOCEPIPE: return "Broken pipe";
40 case SOCEOS2ERR: return "OS/2 Error";
41 case SOCEWOULDBLOCK: return "Operation would block";
42 case SOCEINPROGRESS: return "Operation now in progress";
43 case SOCEALREADY: return "Operation already in progress";
44 case SOCENOTSOCK: return "Socket operation on non-socket";
45 case SOCEDESTADDRREQ: return "Destination address required";
46 case SOCEMSGSIZE: return "Message too long";
47 case SOCEPROTOTYPE: return "Protocol wrong type for socket";
48 case SOCENOPROTOOPT: return "Protocol not available";
49 case SOCEPROTONOSUPPORT: return "Protocol not supported";
50 case SOCESOCKTNOSUPPORT: return "Socket type not supported";
51 case SOCEOPNOTSUPP: return "Operation not supported on socket";
52 case SOCEPFNOSUPPORT: return "Protocol family not supported";
53 case SOCEAFNOSUPPORT:
54 return "Address family not supported by protocol family";
55 case SOCEADDRINUSE: return "Address already in use";
56 case SOCEADDRNOTAVAIL: return "Can't assign requested address";
57 case SOCENETDOWN: return "Network is down";
58 case SOCENETUNREACH: return "Network is unreachable";
59 case SOCENETRESET: return "Network dropped connection on reset";
60 case SOCECONNABORTED: return "Software caused connection abort";
61 case SOCECONNRESET: return "Connection reset by peer";
62 case SOCENOBUFS: return "No buffer space available";
63 case SOCEISCONN: return "Socket is already connected";
64 case SOCENOTCONN: return "Socket is not connected";
65 case SOCESHUTDOWN: return "Can't send after socket shutdown";
66 case SOCETOOMANYREFS: return "Too many references: can't splice";
67 case SOCETIMEDOUT: return "Connection timed out";
68 case SOCECONNREFUSED: return "Connection refused";
69 case SOCELOOP: return "Too many levels of symbolic links";
70 case SOCENAMETOOLONG: return "File name too long";
71 case SOCEHOSTDOWN: return "Host is down";
72 case SOCEHOSTUNREACH: return "No route to host";
73 case SOCENOTEMPTY: return "Directory not empty";
74
75 default:
76 sprintf( ErrUnknownBuf, "SockStrErrno( %d ) unknown", SockErrno );
77 return ErrUnknownBuf;
78 }
79 #else
80 #error SockStrError not supported for this OS
81 #endif
82 }
83
84 #endif /* SockStrError */
85
86
87 /****************************************************************
88 * Routine: HostStrError
89 * Returns: Pointer to static buffer
90 * Action : Convert HOST_ERRNO into error text
91 ****************************************************************/
92
93 const char *
HostStrError(int HostErrno)94 HostStrError(int HostErrno)
95 {
96 switch (HostErrno)
97 {
98 case HOST_NOT_FOUND:
99 return "Host not found";
100 case TRY_AGAIN:
101 return "Host not found (suggest try again)";
102 case NO_RECOVERY:
103 return "Non-recoverable error: FORMERR, REFUSED, NOTIMP";
104 case NO_DATA:
105 return "No Data (valid name, but no record of requested type)";
106
107 default:
108 sprintf( ErrUnknownBuf, "HostStrErrno( %d ) unknown", HostErrno );
109 return ErrUnknownBuf;
110 }
111 }
112
113
114 #if defined( TCPIP_IBM )
115 /****************************************************************
116 * Routine: IbmSockSend
117 * Returns: same as send
118 * Action : Do the right thing for IBM TCP/IP which includes
119 * the following two stupidities:
120 * 1) Never try to send more than 32K
121 * 2) Never pass a buffer that crosses a 64K boundary
122 * If Flags is non-zero, this function only attempts
123 * to deal with condition (1) above.
124 ****************************************************************/
125
126 int
IbmSockSend(int Socket,const void * Buffer,int Len,int Flags)127 IbmSockSend (int Socket, const void *Buffer, int Len, int Flags)
128 {
129 int Sent, ToSend, TotalSent = 0;
130
131 const char *Tmp = Buffer;
132
133 /*
134 * If Flags have been passed in, the 64K boundary optimization
135 * can not be performed. For example, MSG_PEEK would not work
136 * correctly.
137 */
138 if (Flags)
139 return send (Socket, (char *) Buffer, min (0x7FFF, Len), Flags);
140
141 do
142 {
143 /* Never send across a 64K boundary */
144 ToSend = min (Len, (int) (0x10000 - (0xFFFF & (long) Tmp)));
145
146 /* Never send more than 32K */
147 if (ToSend > 0x7FFF)
148 ToSend = 0x7FFF;
149
150 Sent = send (Socket, (char *) Tmp, ToSend, 0);
151 if (Sent < 0)
152 {
153 if ((TotalSent > 0) && (SOCK_ERRNO == EWOULDBLOCK))
154 return TotalSent;
155 if (SOCK_ERRNO == EINTR)
156 continue;
157 return Sent;
158 }
159 if (Sent < ToSend)
160 return TotalSent + Sent;
161
162 Tmp += Sent;
163 TotalSent += Sent;
164 Len -= Sent;
165 } while (Len > 0);
166
167 return TotalSent;
168 }
169
170
171
172 /****************************************************************
173 * Routine: IbmSockRecv
174 * Returns: same as recv
175 * Action : Do the right thing for IBM TCP/IP which includes
176 * the following two stupidities:
177 * 1) Never try to recv more than 32K
178 * 2) Never pass a buffer that crosses a 64K boundary
179 * If Flags is non-zero, this function only attempts
180 * to deal with condition (1) above.
181 ****************************************************************/
182
183 int
IbmSockRecv(int Socket,const void * Buffer,int Len,int Flags)184 IbmSockRecv (int Socket, const void *Buffer, int Len, int Flags)
185 {
186 int Recvd, ToRecv, TotalRecvd = 0;
187
188 char *Tmp = Buffer;
189
190 /* If Flags have been passed in, the 64K boundary optimization
191 probably can not be performed. */
192
193 if (Flags)
194 return recv (Socket, Buffer, min (0x7FFF, Len), Flags);
195
196 do
197 {
198 /* Never send across a 64K boundary */
199 ToRecv = min( Len, (int)( 0x10000 - ( 0xFFFF & (long)Tmp )));
200
201 /* Never send more than 32K */
202 if( ToRecv > 0x7FFF )
203 ToRecv = 0x7FFF;
204
205 Recvd = recv (Socket, Tmp, ToRecv, 0);
206 if (Recvd <= 0)
207 {
208 if ((TotalRecvd > 0)
209 && (Recvd == 0 || (SOCK_ERRNO == EWOULDBLOCK )))
210 return TotalRecvd;
211 if (SOCK_ERRNO == EINTR)
212 continue;
213
214 return Recvd;
215 }
216 if (Recvd < ToRecv)
217 return TotalRecvd + Recvd;
218
219 Tmp += Recvd;
220 TotalRecvd += Recvd;
221 Len -= Recvd;
222 } while (Len > 0);
223
224 return TotalRecvd;
225 }
226 #endif /* defined( TCPIP_IBM ) */
227
228