comparison nspr/pr/src/md/windows/w95sock.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /* Win95 Sockets module
7 *
8 */
9
10 #include "primpl.h"
11
12 #define READ_FD 1
13 #define WRITE_FD 2
14 #define CONNECT_FD 3
15
16 static PRInt32 socket_io_wait(
17 PROsfd osfd,
18 PRInt32 fd_type,
19 PRIntervalTime timeout);
20
21
22 /* --- SOCKET IO --------------------------------------------------------- */
23
24 static PRBool socketFixInet6RcvBuf = PR_FALSE;
25
26 void _PR_MD_InitSockets(void)
27 {
28 OSVERSIONINFO osvi;
29
30 memset(&osvi, 0, sizeof(osvi));
31 osvi.dwOSVersionInfoSize = sizeof(osvi);
32 GetVersionEx(&osvi);
33
34 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
35 {
36 /* if Windows XP (32-bit) */
37 socketFixInet6RcvBuf = PR_TRUE;
38 }
39 }
40
41 void _PR_MD_CleanupSockets(void)
42 {
43 socketFixInet6RcvBuf = PR_FALSE;
44 }
45
46 PROsfd
47 _PR_MD_SOCKET(int af, int type, int flags)
48 {
49 SOCKET sock;
50 u_long one = 1;
51
52 sock = socket(af, type, flags);
53
54 if (sock == INVALID_SOCKET )
55 {
56 _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError());
57 return (PROsfd)sock;
58 }
59
60 /*
61 ** Make the socket Non-Blocking
62 */
63 if (ioctlsocket( sock, FIONBIO, &one) != 0)
64 {
65 PR_SetError(PR_UNKNOWN_ERROR, WSAGetLastError());
66 closesocket(sock);
67 return -1;
68 }
69
70 if (af == AF_INET6 && socketFixInet6RcvBuf)
71 {
72 int bufsize;
73 int len = sizeof(bufsize);
74 int rv;
75
76 /* Windows XP 32-bit returns an error on getpeername() for AF_INET6
77 * sockets if the receive buffer size is greater than 65535 before
78 * the connection is initiated. The default receive buffer size may
79 * be 128000 so fix it here to always be <= 65535. See bug 513659
80 * and IBM DB2 support technote "Receive/Send IPv6 Socket Size
81 * Problem in Windows XP SP2 & SP3".
82 */
83 rv = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, &len);
84 if (rv == 0 && bufsize > 65535)
85 {
86 bufsize = 65535;
87 setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, len);
88 }
89 }
90
91 return (PROsfd)sock;
92 }
93
94 /*
95 ** _MD_CloseSocket() -- Close a socket
96 **
97 */
98 PRInt32
99 _MD_CloseSocket(PROsfd osfd)
100 {
101 PRInt32 rv;
102
103 rv = closesocket((SOCKET) osfd );
104 if (rv < 0)
105 _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError());
106
107 return rv;
108 }
109
110 PRInt32
111 _MD_SocketAvailable(PRFileDesc *fd)
112 {
113 PRInt32 result;
114
115 if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) {
116 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError());
117 return -1;
118 }
119 return result;
120 }
121
122 PROsfd _MD_Accept(
123 PRFileDesc *fd,
124 PRNetAddr *raddr,
125 PRUint32 *rlen,
126 PRIntervalTime timeout )
127 {
128 PROsfd osfd = fd->secret->md.osfd;
129 SOCKET sock;
130 PRInt32 rv, err;
131
132 while ((sock = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1)
133 {
134 err = WSAGetLastError();
135 if ((err == WSAEWOULDBLOCK) && (!fd->secret->nonblocking))
136 {
137 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
138 {
139 break;
140 }
141 }
142 else
143 {
144 _PR_MD_MAP_ACCEPT_ERROR(err);
145 break;
146 }
147 }
148 return(sock);
149 } /* end _MD_accept() */
150
151 PRInt32
152 _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
153 PRIntervalTime timeout)
154 {
155 PROsfd osfd = fd->secret->md.osfd;
156 PRInt32 rv;
157 int err;
158
159 if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1)
160 {
161 err = WSAGetLastError();
162 if ((!fd->secret->nonblocking) && (err == WSAEWOULDBLOCK))
163 {
164 rv = socket_io_wait(osfd, CONNECT_FD, timeout);
165 if ( rv < 0 )
166 {
167 return(-1);
168 }
169 else
170 {
171 PR_ASSERT(rv > 0);
172 /* it's connected */
173 return(0);
174 }
175 }
176 _PR_MD_MAP_CONNECT_ERROR(err);
177 }
178 return rv;
179 }
180
181 PRInt32
182 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
183 {
184 PRInt32 rv;
185
186 rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen);
187
188 if (rv == SOCKET_ERROR) {
189 _PR_MD_MAP_BIND_ERROR(WSAGetLastError());
190 return -1;
191 }
192
193 return 0;
194 }
195
196 PRInt32
197 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
198 {
199 PRInt32 rv;
200
201 rv = listen(fd->secret->md.osfd, backlog);
202
203 if (rv == SOCKET_ERROR) {
204 _PR_MD_MAP_DEFAULT_ERROR(WSAGetLastError());
205 return -1;
206 }
207
208 return 0;
209 }
210
211 PRInt32
212 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
213 PRIntervalTime timeout)
214 {
215 PROsfd osfd = fd->secret->md.osfd;
216 PRInt32 rv, err;
217 int osflags;
218
219 if (0 == flags) {
220 osflags = 0;
221 } else {
222 PR_ASSERT(PR_MSG_PEEK == flags);
223 osflags = MSG_PEEK;
224 }
225 while ((rv = recv( osfd, buf, amount, osflags)) == -1)
226 {
227 if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
228 && (!fd->secret->nonblocking))
229 {
230 rv = socket_io_wait(osfd, READ_FD, timeout);
231 if ( rv < 0 )
232 {
233 return -1;
234 }
235 }
236 else
237 {
238 _PR_MD_MAP_RECV_ERROR(err);
239 break;
240 }
241 } /* end while() */
242 return(rv);
243 }
244
245 PRInt32
246 _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
247 PRIntervalTime timeout)
248 {
249 PROsfd osfd = fd->secret->md.osfd;
250 PRInt32 rv, err;
251 PRInt32 bytesSent = 0;
252
253 while(bytesSent < amount )
254 {
255 while ((rv = send( osfd, buf, amount, 0 )) == -1)
256 {
257 if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
258 && (!fd->secret->nonblocking))
259 {
260 rv = socket_io_wait(osfd, WRITE_FD, timeout);
261 if ( rv < 0 )
262 {
263 return -1;
264 }
265 }
266 else
267 {
268 _PR_MD_MAP_SEND_ERROR(err);
269 return -1;
270 }
271 }
272 bytesSent += rv;
273 if (fd->secret->nonblocking)
274 {
275 break;
276 }
277 if (bytesSent < amount)
278 {
279 rv = socket_io_wait(osfd, WRITE_FD, timeout);
280 if ( rv < 0 )
281 {
282 return -1;
283 }
284 }
285 }
286 return bytesSent;
287 }
288
289 PRInt32
290 _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
291 const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
292 {
293 PROsfd osfd = fd->secret->md.osfd;
294 PRInt32 rv, err;
295 PRInt32 bytesSent = 0;
296
297 while(bytesSent < amount)
298 {
299 while ((rv = sendto( osfd, buf, amount, 0, (struct sockaddr *) addr,
300 addrlen)) == -1)
301 {
302 if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
303 && (!fd->secret->nonblocking))
304 {
305 rv = socket_io_wait(osfd, WRITE_FD, timeout);
306 if ( rv < 0 )
307 {
308 return -1;
309 }
310 }
311 else
312 {
313 _PR_MD_MAP_SENDTO_ERROR(err);
314 return -1;
315 }
316 }
317 bytesSent += rv;
318 if (fd->secret->nonblocking)
319 {
320 break;
321 }
322 if (bytesSent < amount)
323 {
324 rv = socket_io_wait(osfd, WRITE_FD, timeout);
325 if (rv < 0)
326 {
327 return -1;
328 }
329 }
330 }
331 return bytesSent;
332 }
333
334 PRInt32
335 _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
336 PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
337 {
338 PROsfd osfd = fd->secret->md.osfd;
339 PRInt32 rv, err;
340
341 while ((rv = recvfrom( osfd, buf, amount, 0, (struct sockaddr *) addr,
342 addrlen)) == -1)
343 {
344 if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
345 && (!fd->secret->nonblocking))
346 {
347 rv = socket_io_wait(osfd, READ_FD, timeout);
348 if ( rv < 0)
349 {
350 return -1;
351 }
352 }
353 else
354 {
355 _PR_MD_MAP_RECVFROM_ERROR(err);
356 break;
357 }
358 }
359 return(rv);
360 }
361
362 PRInt32
363 _PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
364 {
365 int index;
366 int sent = 0;
367 int rv;
368
369 for (index=0; index < iov_size; index++)
370 {
371 rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
372 if (rv > 0)
373 sent += rv;
374 if ( rv != iov[index].iov_len )
375 {
376 if (rv < 0)
377 {
378 if (fd->secret->nonblocking
379 && (PR_GetError() == PR_WOULD_BLOCK_ERROR)
380 && (sent > 0))
381 {
382 return sent;
383 }
384 else
385 {
386 return -1;
387 }
388 }
389 /* Only a nonblocking socket can have partial sends */
390 PR_ASSERT(fd->secret->nonblocking);
391 return sent;
392 }
393 }
394 return sent;
395 }
396
397 PRInt32
398 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
399 {
400 PRInt32 rv;
401
402 rv = shutdown(fd->secret->md.osfd, how);
403 if (rv < 0)
404 _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError());
405 return rv;
406 }
407
408 PRStatus
409 _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
410 {
411 PRInt32 rv;
412
413 rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len);
414 if (rv==0) {
415 return PR_SUCCESS;
416 } else {
417 _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError());
418 return PR_FAILURE;
419 }
420 }
421
422 PRStatus
423 _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
424 {
425 PRInt32 rv;
426
427 rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len);
428 if (rv==0) {
429 return PR_SUCCESS;
430 } else {
431 _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError());
432 return PR_FAILURE;
433 }
434 }
435
436 PRStatus
437 _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
438 {
439 PRInt32 rv;
440
441 rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
442 if (rv==0) {
443 return PR_SUCCESS;
444 } else {
445 _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
446 return PR_FAILURE;
447 }
448 }
449
450 PRStatus
451 _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
452 {
453 PRInt32 rv;
454
455 rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
456 if (rv==0) {
457 return PR_SUCCESS;
458 } else {
459 _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError());
460 return PR_FAILURE;
461 }
462 }
463
464 void
465 _MD_MakeNonblock(PRFileDesc *f)
466 {
467 return; /* do nothing */
468 }
469
470
471
472 /*
473 * socket_io_wait --
474 *
475 * Wait for socket i/o, periodically checking for interrupt.
476 *
477 * This function returns 1 on success. On failure, it returns
478 * -1 and sets the error codes. It never returns 0.
479 */
480 #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
481
482 static PRInt32 socket_io_wait(
483 PROsfd osfd,
484 PRInt32 fd_type,
485 PRIntervalTime timeout)
486 {
487 PRInt32 rv = -1;
488 struct timeval tv;
489 PRThread *me = _PR_MD_CURRENT_THREAD();
490 PRIntervalTime elapsed, remaining;
491 PRBool wait_for_remaining;
492 fd_set rd_wr, ex;
493 int err, len;
494
495 switch (timeout) {
496 case PR_INTERVAL_NO_WAIT:
497 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
498 break;
499 case PR_INTERVAL_NO_TIMEOUT:
500 /*
501 * This is a special case of the 'default' case below.
502 * Please see the comments there.
503 */
504 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
505 tv.tv_usec = 0;
506 FD_ZERO(&rd_wr);
507 FD_ZERO(&ex);
508 do {
509 FD_SET(osfd, &rd_wr);
510 FD_SET(osfd, &ex);
511 switch( fd_type )
512 {
513 case READ_FD:
514 rv = _MD_SELECT(0, &rd_wr, NULL, NULL, &tv);
515 break;
516 case WRITE_FD:
517 rv = _MD_SELECT(0, NULL, &rd_wr, NULL, &tv);
518 break;
519 case CONNECT_FD:
520 rv = _MD_SELECT(0, NULL, &rd_wr, &ex, &tv);
521 break;
522 default:
523 PR_ASSERT(0);
524 break;
525 } /* end switch() */
526 if (rv == -1 )
527 {
528 _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
529 break;
530 }
531 if ( rv > 0 && fd_type == CONNECT_FD )
532 {
533 /*
534 * Call Sleep(0) to work around a Winsock timing bug.
535 */
536 Sleep(0);
537 if (FD_ISSET((SOCKET)osfd, &ex))
538 {
539 len = sizeof(err);
540 if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
541 (char *) &err, &len) == SOCKET_ERROR)
542 {
543 _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
544 return -1;
545 }
546 if (err != 0)
547 _PR_MD_MAP_CONNECT_ERROR(err);
548 else
549 PR_SetError(PR_UNKNOWN_ERROR, 0);
550 return -1;
551 }
552 if (FD_ISSET((SOCKET)osfd, &rd_wr))
553 {
554 /* it's connected */
555 return 1;
556 }
557 PR_ASSERT(0);
558 }
559 if (_PR_PENDING_INTERRUPT(me)) {
560 me->flags &= ~_PR_INTERRUPT;
561 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
562 rv = -1;
563 break;
564 }
565 } while (rv == 0);
566 break;
567 default:
568 remaining = timeout;
569 FD_ZERO(&rd_wr);
570 FD_ZERO(&ex);
571 do {
572 /*
573 * We block in _MD_SELECT for at most
574 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
575 * so that there is an upper limit on the delay
576 * before the interrupt bit is checked.
577 */
578 wait_for_remaining = PR_TRUE;
579 tv.tv_sec = PR_IntervalToSeconds(remaining);
580 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
581 wait_for_remaining = PR_FALSE;
582 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
583 tv.tv_usec = 0;
584 } else {
585 tv.tv_usec = PR_IntervalToMicroseconds(
586 remaining -
587 PR_SecondsToInterval(tv.tv_sec));
588 }
589 FD_SET(osfd, &rd_wr);
590 FD_SET(osfd, &ex);
591 switch( fd_type )
592 {
593 case READ_FD:
594 rv = _MD_SELECT(0, &rd_wr, NULL, NULL, &tv);
595 break;
596 case WRITE_FD:
597 rv = _MD_SELECT(0, NULL, &rd_wr, NULL, &tv);
598 break;
599 case CONNECT_FD:
600 rv = _MD_SELECT(0, NULL, &rd_wr, &ex, &tv);
601 break;
602 default:
603 PR_ASSERT(0);
604 break;
605 } /* end switch() */
606 if (rv == -1)
607 {
608 _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
609 break;
610 }
611 if ( rv > 0 && fd_type == CONNECT_FD )
612 {
613 /*
614 * Call Sleep(0) to work around a Winsock timing bug.
615 */
616 Sleep(0);
617 if (FD_ISSET((SOCKET)osfd, &ex))
618 {
619 len = sizeof(err);
620 if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
621 (char *) &err, &len) == SOCKET_ERROR)
622 {
623 _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
624 return -1;
625 }
626 if (err != 0)
627 _PR_MD_MAP_CONNECT_ERROR(err);
628 else
629 PR_SetError(PR_UNKNOWN_ERROR, 0);
630 return -1;
631 }
632 if (FD_ISSET((SOCKET)osfd, &rd_wr))
633 {
634 /* it's connected */
635 return 1;
636 }
637 PR_ASSERT(0);
638 }
639 if (_PR_PENDING_INTERRUPT(me)) {
640 me->flags &= ~_PR_INTERRUPT;
641 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
642 rv = -1;
643 break;
644 }
645 /*
646 * We loop again if _MD_SELECT timed out and the
647 * timeout deadline has not passed yet.
648 */
649 if (rv == 0 )
650 {
651 if (wait_for_remaining) {
652 elapsed = remaining;
653 } else {
654 elapsed = PR_SecondsToInterval(tv.tv_sec)
655 + PR_MicrosecondsToInterval(tv.tv_usec);
656 }
657 if (elapsed >= remaining) {
658 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
659 rv = -1;
660 break;
661 } else {
662 remaining = remaining - elapsed;
663 }
664 }
665 } while (rv == 0 );
666 break;
667 }
668 return(rv);
669 } /* end socket_io_wait() */
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)