2 * io_sock.c - SecureTransport sample I/O module, X sockets version
10 #include <sys/types.h>
11 #include <netinet/in.h>
12 #include <sys/socket.h>
14 #include <arpa/inet.h>
17 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
21 /* debugging for this module */
22 #define SSL_OT_DEBUG 1
24 /* log errors to stdout */
25 #define SSL_OT_ERRLOG 1
27 /* trace all low-level network I/O */
28 #define SSL_OT_IO_TRACE 0
30 /* if SSL_OT_IO_TRACE, only log non-zero length transfers */
31 #define SSL_OT_IO_TRACE_NZ 1
33 /* pause after each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */
34 #define SSL_OT_IO_PAUSE 0
36 /* print a stream of dots while I/O pending */
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
43 /* general, not-too-verbose debugging */
45 #define dprintf(s) printf s
50 /* errors --> stdout */
52 #define eprintf(s) printf s
57 /* enable nonblocking I/O - maybe should be an arg to MakeServerConnection() */
58 #define NON_BLOCKING 0
60 /* trace completion of every r/w */
68 #if SSL_OT_IO_TRACE_NZ
73 printf("%s(%d): moved %d bytes\n", str
, req
, act
);
78 for(i
=0; i
<act
; i
++) {
79 printf("%02X ", buf
[i
]);
80 if(i
>= (SSL_OT_IO_DUMP_SIZE
- 1)) {
90 printf("CR to continue: ");
97 #define tprintf(str, req, act, buf)
98 #endif /* SSL_OT_IO_TRACE */
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
108 static time_t lastTime
= (time_t)0;
109 #define TIME_INTERVAL 3
111 static void outputDot()
113 time_t thisTime
= time(0);
115 if((thisTime
- lastTime
) >= TIME_INTERVAL
) {
116 printf("."); fflush(stdout
);
126 * One-time only init.
136 * Seeing a lot of soft errors...for threadTest (only) let's retry.
138 #define CONNECT_RETRIES 10
140 OSStatus
MakeServerConnection(
141 const char *hostName
,
143 otSocket
*socketNo
, // RETURNED
144 PeerSpec
*peer
) // RETURNED
146 struct sockaddr_in addr
;
153 if (hostName
[0] >= '0' && hostName
[0] <= '9') {
154 host
.s_addr
= inet_addr(hostName
);
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
);
162 printf("gethostbyname failed\n");
167 memcpy(&host
, ent
->h_addr
, sizeof(struct in_addr
));
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
);
181 if (connect(sock
, (struct sockaddr
*) &addr
,
182 sizeof(struct sockaddr_in
)) == 0) {
187 fprintf(stderr
, "%s ", hostName
);
190 if(i
== CONNECT_RETRIES
) {
195 /* OK to do this after connect? */
197 int rtn
= fcntl(sock
, F_SETFL
, O_NONBLOCK
);
199 perror("fctnl(O_NONBLOCK)");
203 #endif /* NON_BLOCKING*/
205 peer
->ipAddr
= addr
.sin_addr
.s_addr
;
206 peer
->port
= htons((u_short
)port
);
207 *socketNo
= (otSocket
)sock
;
212 * Accept a client connection.
214 OSStatus
AcceptClientConnection(
216 otSocket
*socketNo
, // RETURNED
217 PeerSpec
*peer
) // RETURNED
224 * Shut down a connection.
226 void endpointShutdown(
233 * R/W. Called out from SSL.
236 SSLConnectionRef connection
,
237 void *data
, /* owned by
240 size_t *dataLength
) /* IN/OUT */
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
;
254 rrtn
= read(sock
, currData
, bytesToGo
);
256 /* this is guesswork... */
259 /* connection closed */
260 rtn
= errSSLClosedGraceful
;
267 rtn
= errSSLWouldBlock
;
270 dprintf(("SocketRead: read(%lu) error %d\n",
280 bytesToGo
-= bytesRead
;
281 currData
+= bytesRead
;
284 /* filled buffer with incoming data, done */
288 *dataLength
= initLen
- bytesToGo
;
289 tprintf("SocketRead", initLen
, *dataLength
, (UInt8
*)data
);
291 #if SSL_OT_DOT || (SSL_OT_DEBUG && !SSL_OT_IO_TRACE)
292 if((rtn
== 0) && (*dataLength
== 0)) {
300 OSStatus
SocketWrite(
301 SSLConnectionRef connection
,
303 size_t *dataLength
) /* IN/OUT */
305 size_t bytesSent
= 0;
306 int sock
= (int)((long)connection
);
308 UInt32 dataLen
= *dataLength
;
309 const UInt8
*dataPtr
= (UInt8
*)data
;
316 (char*)dataPtr
+ bytesSent
,
317 dataLen
- bytesSent
);
318 } while ((length
> 0) &&
319 ( (bytesSent
+= length
) < dataLen
) );
322 if(errno
== EAGAIN
) {
323 ortn
= errSSLWouldBlock
;
332 tprintf("SocketWrite", dataLen
, bytesSent
, dataPtr
);
333 *dataLength
= bytesSent
;