]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/threadTest/ioSockThr.c
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / threadTest / ioSockThr.c
1 /*
2 * io_sock.c - SecureTransport sample I/O module, X sockets version
3 */
4
5 #include "ioSockThr.h"
6 #include <errno.h>
7 #include <stdio.h>
8
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <netinet/in.h>
12 #include <sys/socket.h>
13 #include <netdb.h>
14 #include <arpa/inet.h>
15 #include <fcntl.h>
16
17 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
18 #include <time.h>
19 #include <strings.h>
20
21 /* debugging for this module */
22 #define SSL_OT_DEBUG 1
23
24 /* log errors to stdout */
25 #define SSL_OT_ERRLOG 1
26
27 /* trace all low-level network I/O */
28 #define SSL_OT_IO_TRACE 0
29
30 /* if SSL_OT_IO_TRACE, only log non-zero length transfers */
31 #define SSL_OT_IO_TRACE_NZ 1
32
33 /* pause after each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */
34 #define SSL_OT_IO_PAUSE 0
35
36 /* print a stream of dots while I/O pending */
37 #define SSL_OT_DOT 1
38
39 /* dump some bytes of each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */
40 #define SSL_OT_IO_DUMP 0
41 #define SSL_OT_IO_DUMP_SIZE 64
42
43 /* general, not-too-verbose debugging */
44 #if SSL_OT_DEBUG
45 #define dprintf(s) printf s
46 #else
47 #define dprintf(s)
48 #endif
49
50 /* errors --> stdout */
51 #if SSL_OT_ERRLOG
52 #define eprintf(s) printf s
53 #else
54 #define eprintf(s)
55 #endif
56
57 /* enable nonblocking I/O - maybe should be an arg to MakeServerConnection() */
58 #define NON_BLOCKING 0
59
60 /* trace completion of every r/w */
61 #if SSL_OT_IO_TRACE
62 static void tprintf(
63 const char *str,
64 UInt32 req,
65 UInt32 act,
66 const UInt8 *buf)
67 {
68 #if SSL_OT_IO_TRACE_NZ
69 if(act == 0) {
70 return;
71 }
72 #endif
73 printf("%s(%d): moved %d bytes\n", str, req, act);
74 #if SSL_OT_IO_DUMP
75 {
76 int i;
77
78 for(i=0; i<act; i++) {
79 printf("%02X ", buf[i]);
80 if(i >= (SSL_OT_IO_DUMP_SIZE - 1)) {
81 break;
82 }
83 }
84 printf("\n");
85 }
86 #endif
87 #if SSL_OT_IO_PAUSE
88 {
89 char instr[20];
90 printf("CR to continue: ");
91 gets(instr);
92 }
93 #endif
94 }
95
96 #else
97 #define tprintf(str, req, act, buf)
98 #endif /* SSL_OT_IO_TRACE */
99
100 /*
101 * If SSL_OT_DOT, output a '.' every so often while waiting for
102 * connection. This gives user a chance to do something else with the
103 * UI.
104 */
105
106 #if SSL_OT_DOT
107
108 static time_t lastTime = (time_t)0;
109 #define TIME_INTERVAL 3
110
111 static void outputDot()
112 {
113 time_t thisTime = time(0);
114
115 if((thisTime - lastTime) >= TIME_INTERVAL) {
116 printf("."); fflush(stdout);
117 lastTime = thisTime;
118 }
119 }
120 #else
121 #define outputDot()
122 #endif
123
124
125 /*
126 * One-time only init.
127 */
128 void initSslOt()
129 {
130
131 }
132
133 /*
134 * Connect to server.
135 *
136 * Seeing a lot of soft errors...for threadTest (only) let's retry.
137 */
138 #define CONNECT_RETRIES 10
139
140 OSStatus MakeServerConnection(
141 const char *hostName,
142 int port,
143 otSocket *socketNo, // RETURNED
144 PeerSpec *peer) // RETURNED
145 {
146 struct sockaddr_in addr;
147 struct hostent *ent;
148 struct in_addr host;
149 int sock = 0;
150 int i;
151
152 *socketNo = NULL;
153 if (hostName[0] >= '0' && hostName[0] <= '9') {
154 host.s_addr = inet_addr(hostName);
155 }
156 else {
157 for(i=0; i<CONNECT_RETRIES; i++) {
158 /* seeing a lot of spurious "No address associated with name"
159 * failures on known good names (www.amazon.com) */
160 ent = gethostbyname(hostName);
161 if (ent == NULL) {
162 printf("gethostbyname failed\n");
163 herror("hostName");
164
165 }
166 else {
167 memcpy(&host, ent->h_addr, sizeof(struct in_addr));
168 break;
169 }
170 }
171 if(ent == NULL) {
172 return ioErr;
173 }
174 }
175 addr.sin_family = AF_INET;
176 for(i=0; i<CONNECT_RETRIES; i++) {
177 sock = socket(AF_INET, SOCK_STREAM, 0);
178 addr.sin_addr = host;
179 addr.sin_port = htons((u_short)port);
180
181 if (connect(sock, (struct sockaddr *) &addr,
182 sizeof(struct sockaddr_in)) == 0) {
183 break;
184 }
185 /* retry */
186 close(sock);
187 fprintf(stderr, "%s ", hostName);
188 perror("connect");
189 }
190 if(i == CONNECT_RETRIES) {
191 return ioErr;
192 }
193
194 #if NON_BLOCKING
195 /* OK to do this after connect? */
196 {
197 int rtn = fcntl(sock, F_SETFL, O_NONBLOCK);
198 if(rtn == -1) {
199 perror("fctnl(O_NONBLOCK)");
200 return ioErr;
201 }
202 }
203 #endif /* NON_BLOCKING*/
204
205 peer->ipAddr = addr.sin_addr.s_addr;
206 peer->port = htons((u_short)port);
207 *socketNo = (otSocket)sock;
208 return noErr;
209 }
210
211 /*
212 * Accept a client connection.
213 */
214 OSStatus AcceptClientConnection(
215 int port,
216 otSocket *socketNo, // RETURNED
217 PeerSpec *peer) // RETURNED
218 {
219 /* maybe some day */
220 return unimpErr;
221 }
222
223 /*
224 * Shut down a connection.
225 */
226 void endpointShutdown(
227 otSocket socket)
228 {
229 close((int)socket);
230 }
231
232 /*
233 * R/W. Called out from SSL.
234 */
235 OSStatus SocketRead(
236 SSLConnectionRef connection,
237 void *data, /* owned by
238 * caller, data
239 * RETURNED */
240 size_t *dataLength) /* IN/OUT */
241 {
242 size_t bytesToGo = *dataLength;
243 size_t initLen = bytesToGo;
244 UInt8 *currData = (UInt8 *)data;
245 int sock = (int)((long)connection);
246 OSStatus rtn = noErr;
247 size_t bytesRead;
248 int rrtn;
249
250 *dataLength = 0;
251
252 for(;;) {
253 bytesRead = 0;
254 rrtn = read(sock, currData, bytesToGo);
255 if (rrtn <= 0) {
256 /* this is guesswork... */
257 switch(errno) {
258 case ENOENT:
259 /* connection closed */
260 rtn = errSSLClosedGraceful;
261 break;
262 #if NON_BLOCKING
263 case EAGAIN:
264 #else
265 case 0: /* ??? */
266 #endif
267 rtn = errSSLWouldBlock;
268 break;
269 default:
270 dprintf(("SocketRead: read(%lu) error %d\n",
271 bytesToGo, errno));
272 rtn = ioErr;
273 break;
274 }
275 break;
276 }
277 else {
278 bytesRead = rrtn;
279 }
280 bytesToGo -= bytesRead;
281 currData += bytesRead;
282
283 if(bytesToGo == 0) {
284 /* filled buffer with incoming data, done */
285 break;
286 }
287 }
288 *dataLength = initLen - bytesToGo;
289 tprintf("SocketRead", initLen, *dataLength, (UInt8 *)data);
290
291 #if SSL_OT_DOT || (SSL_OT_DEBUG && !SSL_OT_IO_TRACE)
292 if((rtn == 0) && (*dataLength == 0)) {
293 /* keep UI alive */
294 outputDot();
295 }
296 #endif
297 return rtn;
298 }
299
300 OSStatus SocketWrite(
301 SSLConnectionRef connection,
302 const void *data,
303 size_t *dataLength) /* IN/OUT */
304 {
305 size_t bytesSent = 0;
306 int sock = (int)((long)connection);
307 int length;
308 UInt32 dataLen = *dataLength;
309 const UInt8 *dataPtr = (UInt8 *)data;
310 OSStatus ortn;
311
312 *dataLength = 0;
313
314 do {
315 length = write(sock,
316 (char*)dataPtr + bytesSent,
317 dataLen - bytesSent);
318 } while ((length > 0) &&
319 ( (bytesSent += length) < dataLen) );
320
321 if(length == 0) {
322 if(errno == EAGAIN) {
323 ortn = errSSLWouldBlock;
324 }
325 else {
326 ortn = ioErr;
327 }
328 }
329 else {
330 ortn = noErr;
331 }
332 tprintf("SocketWrite", dataLen, bytesSent, dataPtr);
333 *dataLength = bytesSent;
334 return ortn;
335 }