Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Side by Side Diff: nspr/pr/src/io/prsocket.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nspr/pr/src/io/prscanf.c ('k') | nspr/pr/src/io/prstdio.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 #include "primpl.h"
7
8 #include <string.h>
9
10 /************************************************************************/
11
12 /* These two functions are only used in assertions. */
13 #if defined(DEBUG)
14
15 PRBool IsValidNetAddr(const PRNetAddr *addr)
16 {
17 if ((addr != NULL)
18 #if defined(XP_UNIX) || defined(XP_OS2)
19 && (addr->raw.family != PR_AF_LOCAL)
20 #endif
21 && (addr->raw.family != PR_AF_INET6)
22 && (addr->raw.family != PR_AF_INET)) {
23 return PR_FALSE;
24 }
25 return PR_TRUE;
26 }
27
28 static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
29 {
30 /*
31 * The definition of the length of a Unix domain socket address
32 * is not uniform, so we don't check it.
33 */
34 if ((addr != NULL)
35 #if defined(XP_UNIX) || defined(XP_OS2)
36 && (addr->raw.family != AF_UNIX)
37 #endif
38 && (PR_NETADDR_SIZE(addr) != addr_len)) {
39 #if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1
40 /*
41 * In glibc 2.1, struct sockaddr_in6 is 24 bytes. In glibc 2.2
42 * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id
43 * field and is 28 bytes. It is possible for socket functions
44 * to return an addr_len greater than sizeof(struct sockaddr_in6).
45 * We need to allow that. (Bugzilla bug #77264)
46 */
47 if ((PR_AF_INET6 == addr->raw.family)
48 && (sizeof(addr->ipv6) == addr_len)) {
49 return PR_TRUE;
50 }
51 #endif
52 /*
53 * The accept(), getsockname(), etc. calls on some platforms
54 * do not set the actual socket address length on return.
55 * In this case, we verifiy addr_len is still the value we
56 * passed in (i.e., sizeof(PRNetAddr)).
57 */
58 #if defined(QNX)
59 if (sizeof(PRNetAddr) == addr_len) {
60 return PR_TRUE;
61 }
62 #endif
63 return PR_FALSE;
64 }
65 return PR_TRUE;
66 }
67
68 #endif /* DEBUG */
69
70 static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, const PRIOVec *iov,
71 PRInt32 iov_size, PRIntervalTime timeout)
72 {
73 PRThread *me = _PR_MD_CURRENT_THREAD();
74 int w = 0;
75 const PRIOVec *tmp_iov;
76 #define LOCAL_MAXIOV 8
77 PRIOVec local_iov[LOCAL_MAXIOV];
78 PRIOVec *iov_copy = NULL;
79 int tmp_out;
80 int index, iov_cnt;
81 int count=0, sz = 0; /* 'count' is the return value. */
82
83 if (_PR_PENDING_INTERRUPT(me)) {
84 me->flags &= ~_PR_INTERRUPT;
85 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
86 return -1;
87 }
88 if (_PR_IO_PENDING(me)) {
89 PR_SetError(PR_IO_PENDING_ERROR, 0);
90 return -1;
91 }
92
93 /*
94 * Assume the first writev will succeed. Copy iov's only on
95 * failure.
96 */
97 tmp_iov = iov;
98 for (index = 0; index < iov_size; index++)
99 sz += iov[index].iov_len;
100
101 iov_cnt = iov_size;
102
103 while (sz > 0) {
104
105 w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout);
106 if (w < 0) {
107 count = -1;
108 break;
109 }
110 count += w;
111 if (fd->secret->nonblocking) {
112 break;
113 }
114 sz -= w;
115
116 if (sz > 0) {
117 /* find the next unwritten vector */
118 for ( index = 0, tmp_out = count;
119 tmp_out >= iov[index].iov_len;
120 tmp_out -= iov[index].iov_len, index++){;} /* no thing to execute */
121
122 if (tmp_iov == iov) {
123 /*
124 * The first writev failed so we
125 * must copy iov's around.
126 * Avoid calloc/free if there
127 * are few enough iov's.
128 */
129 if (iov_size - index <= LOCAL_MAXIOV)
130 iov_copy = local_iov;
131 else if ((iov_copy = (PRIOVec *) PR_CALLOC((iov_ size - index) *
132 sizeof *iov_copy)) == NULL) {
133 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
134 return -1;
135 }
136 tmp_iov = iov_copy;
137 }
138
139 PR_ASSERT(tmp_iov == iov_copy);
140
141 /* fill in the first partial read */
142 iov_copy[0].iov_base = &(((char *)iov[index].iov_base)[t mp_out]);
143 iov_copy[0].iov_len = iov[index].iov_len - tmp_out;
144 index++;
145
146 /* copy the remaining vectors */
147 for (iov_cnt=1; index<iov_size; iov_cnt++, index++) {
148 iov_copy[iov_cnt].iov_base = iov[index].iov_base ;
149 iov_copy[iov_cnt].iov_len = iov[index].iov_len;
150 }
151 }
152 }
153
154 if (iov_copy != local_iov)
155 PR_DELETE(iov_copy);
156 return count;
157 }
158
159 /************************************************************************/
160
161 PR_IMPLEMENT(PRFileDesc *) PR_ImportTCPSocket(PROsfd osfd)
162 {
163 PRFileDesc *fd;
164
165 if (!_pr_initialized) _PR_ImplicitInitialization();
166 fd = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
167 if (fd != NULL) {
168 _PR_MD_MAKE_NONBLOCK(fd);
169 _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
170 #ifdef _PR_NEED_SECRET_AF
171 /* this means we can only import IPv4 sockets here.
172 * but this is what the function in ptio.c does.
173 * We need a way to import IPv6 sockets, too.
174 */
175 fd->secret->af = AF_INET;
176 #endif
177 } else
178 _PR_MD_CLOSE_SOCKET(osfd);
179 return(fd);
180 }
181
182 PR_IMPLEMENT(PRFileDesc *) PR_ImportUDPSocket(PROsfd osfd)
183 {
184 PRFileDesc *fd;
185
186 if (!_pr_initialized) _PR_ImplicitInitialization();
187 fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods());
188 if (fd != NULL) {
189 _PR_MD_MAKE_NONBLOCK(fd);
190 _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
191 } else
192 _PR_MD_CLOSE_SOCKET(osfd);
193 return(fd);
194 }
195
196
197 static const PRIOMethods* PR_GetSocketPollFdMethods(void);
198
199 PR_IMPLEMENT(PRFileDesc*) PR_CreateSocketPollFd(PROsfd osfd)
200 {
201 PRFileDesc *fd;
202
203 if (!_pr_initialized) _PR_ImplicitInitialization();
204
205 fd = _PR_Getfd();
206
207 if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
208 else
209 {
210 fd->secret->md.osfd = osfd;
211 fd->secret->inheritable = _PR_TRI_FALSE;
212 fd->secret->state = _PR_FILEDESC_OPEN;
213 fd->methods = PR_GetSocketPollFdMethods();
214 }
215
216 return fd;
217 } /* PR_CreateSocketPollFD */
218
219 PR_IMPLEMENT(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd)
220 {
221 if (NULL == fd)
222 {
223 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
224 return PR_FAILURE;
225 }
226 fd->secret->state = _PR_FILEDESC_CLOSED;
227 _PR_Putfd(fd);
228 return PR_SUCCESS;
229 } /* PR_DestroySocketPollFd */
230
231 static PRStatus PR_CALLBACK SocketConnect(
232 PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
233 {
234 PRInt32 rv; /* Return value of _PR_MD_CONNECT */
235 const PRNetAddr *addrp = addr;
236 #if defined(_PR_INET6)
237 PRNetAddr addrCopy;
238 #endif
239 PRThread *me = _PR_MD_CURRENT_THREAD();
240
241 if (_PR_PENDING_INTERRUPT(me)) {
242 me->flags &= ~_PR_INTERRUPT;
243 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
244 return PR_FAILURE;
245 }
246 #if defined(_PR_INET6)
247 if (addr->raw.family == PR_AF_INET6) {
248 addrCopy = *addr;
249 addrCopy.raw.family = AF_INET6;
250 addrp = &addrCopy;
251 }
252 #endif
253
254 rv = _PR_MD_CONNECT(fd, addrp, PR_NETADDR_SIZE(addr), timeout);
255 PR_LOG(_pr_io_lm, PR_LOG_MAX, ("connect -> %d", rv));
256 if (rv == 0)
257 return PR_SUCCESS;
258 else
259 return PR_FAILURE;
260 }
261
262 static PRStatus PR_CALLBACK SocketConnectContinue(
263 PRFileDesc *fd, PRInt16 out_flags)
264 {
265 PROsfd osfd;
266 int err;
267
268 if (out_flags & PR_POLL_NVAL) {
269 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
270 return PR_FAILURE;
271 }
272 if ((out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR)) == 0) {
273 PR_ASSERT(out_flags == 0);
274 PR_SetError(PR_IN_PROGRESS_ERROR, 0);
275 return PR_FAILURE;
276 }
277
278 osfd = fd->secret->md.osfd;
279
280 #if defined(XP_UNIX)
281
282 err = _MD_unix_get_nonblocking_connect_error(osfd);
283 if (err != 0) {
284 _PR_MD_MAP_CONNECT_ERROR(err);
285 return PR_FAILURE;
286 }
287 return PR_SUCCESS;
288
289 #elif defined(WIN32) || defined(WIN16)
290
291 if (out_flags & PR_POLL_EXCEPT) {
292 int len = sizeof(err);
293 if (getsockopt(osfd, (int)SOL_SOCKET, SO_ERROR, (char *) &err, &len)
294 == SOCKET_ERROR) {
295 _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
296 return PR_FAILURE;
297 }
298 if (err != 0) {
299 _PR_MD_MAP_CONNECT_ERROR(err);
300 } else {
301 PR_SetError(PR_UNKNOWN_ERROR, 0);
302 }
303 return PR_FAILURE;
304 }
305
306 PR_ASSERT(out_flags & PR_POLL_WRITE);
307 return PR_SUCCESS;
308
309 #elif defined(XP_OS2)
310
311 err = _MD_os2_get_nonblocking_connect_error(osfd);
312 if (err != 0) {
313 _PR_MD_MAP_CONNECT_ERROR(err);
314 return PR_FAILURE;
315 }
316 return PR_SUCCESS;
317
318 #elif defined(XP_BEOS)
319
320 #ifdef BONE_VERSION /* bug 122364 */
321 /* temporary workaround until getsockopt(SO_ERROR) works in BONE */
322 if (out_flags & PR_POLL_EXCEPT) {
323 PR_SetError(PR_CONNECT_REFUSED_ERROR, 0);
324 return PR_FAILURE;
325 }
326 PR_ASSERT(out_flags & PR_POLL_WRITE);
327 return PR_SUCCESS;
328 #else
329 err = _MD_beos_get_nonblocking_connect_error(fd);
330 if( err != 0 ) {
331 _PR_MD_MAP_CONNECT_ERROR(err);
332 return PR_FAILURE;
333 }
334 else
335 return PR_SUCCESS;
336 #endif /* BONE_VERSION */
337
338 #else
339 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
340 return PR_FAILURE;
341 #endif
342 }
343
344 PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd)
345 {
346 /* Find the NSPR layer and invoke its connectcontinue method */
347 PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
348
349 if (NULL == bottom) {
350 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
351 return PR_FAILURE;
352 }
353 return SocketConnectContinue(bottom, pd->out_flags);
354 }
355
356 static PRFileDesc* PR_CALLBACK SocketAccept(PRFileDesc *fd, PRNetAddr *addr,
357 PRIntervalTime timeout)
358 {
359 PROsfd osfd;
360 PRFileDesc *fd2;
361 PRUint32 al;
362 PRThread *me = _PR_MD_CURRENT_THREAD();
363 #ifdef WINNT
364 PRNetAddr addrCopy;
365 #endif
366
367 if (_PR_PENDING_INTERRUPT(me)) {
368 me->flags &= ~_PR_INTERRUPT;
369 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
370 return 0;
371 }
372 if (_PR_IO_PENDING(me)) {
373 PR_SetError(PR_IO_PENDING_ERROR, 0);
374 return 0;
375 }
376
377 #ifdef WINNT
378 if (addr == NULL) {
379 addr = &addrCopy;
380 }
381 #endif
382 al = sizeof(PRNetAddr);
383 osfd = _PR_MD_ACCEPT(fd, addr, &al, timeout);
384 if (osfd == -1)
385 return 0;
386
387 fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
388 if (!fd2) {
389 _PR_MD_CLOSE_SOCKET(osfd);
390 return NULL;
391 }
392
393 fd2->secret->nonblocking = fd->secret->nonblocking;
394 fd2->secret->inheritable = fd->secret->inheritable;
395 #ifdef WINNT
396 if (!fd2->secret->nonblocking && fd2->secret->inheritable != _PR_TRI_TRU E) {
397 /*
398 * The new socket has been associated with an I/O
399 * completion port. There is no going back.
400 */
401 fd2->secret->md.io_model_committed = PR_TRUE;
402 }
403 PR_ASSERT(al == PR_NETADDR_SIZE(addr));
404 fd2->secret->md.accepted_socket = PR_TRUE;
405 memcpy(&fd2->secret->md.peer_addr, addr, al);
406 #endif
407
408 /*
409 * On some platforms, the new socket created by accept()
410 * inherits the nonblocking (or overlapped io) attribute
411 * of the listening socket. As an optimization, these
412 * platforms can skip the following _PR_MD_MAKE_NONBLOCK
413 * call.
414 */
415 #if !defined(SOLARIS) && !defined(IRIX) && !defined(WINNT)
416 _PR_MD_MAKE_NONBLOCK(fd2);
417 #endif
418
419 #ifdef _PR_INET6
420 if (addr && (AF_INET6 == addr->raw.family))
421 addr->raw.family = PR_AF_INET6;
422 #endif
423 PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
424 PR_ASSERT(IsValidNetAddrLen(addr, al) == PR_TRUE);
425
426 return fd2;
427 }
428
429 #ifdef WINNT
430 PR_IMPLEMENT(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr,
431 PRIntervalTime timeout)
432 {
433 PROsfd osfd;
434 PRFileDesc *fd2;
435 PRIntn al;
436 PRThread *me = _PR_MD_CURRENT_THREAD();
437 PRNetAddr addrCopy;
438
439 if (_PR_PENDING_INTERRUPT(me)) {
440 me->flags &= ~_PR_INTERRUPT;
441 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
442 return 0;
443 }
444 if (_PR_IO_PENDING(me)) {
445 PR_SetError(PR_IO_PENDING_ERROR, 0);
446 return 0;
447 }
448
449 if (addr == NULL) {
450 addr = &addrCopy;
451 }
452 al = PR_NETADDR_SIZE(addr);
453 osfd = _PR_MD_FAST_ACCEPT(fd, addr, &al, timeout, PR_TRUE, NULL, NULL);
454 if (osfd == -1) {
455 return 0;
456 }
457
458 fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
459 if (!fd2) {
460 _PR_MD_CLOSE_SOCKET(osfd);
461 } else {
462 fd2->secret->nonblocking = fd->secret->nonblocking;
463 fd2->secret->md.io_model_committed = PR_TRUE;
464 PR_ASSERT(al == PR_NETADDR_SIZE(addr));
465 fd2->secret->md.accepted_socket = PR_TRUE;
466 memcpy(&fd2->secret->md.peer_addr, addr, al);
467 #ifdef _PR_INET6
468 if (AF_INET6 == addr->raw.family)
469 addr->raw.family = PR_AF_INET6;
470 #endif
471 #ifdef _PR_NEED_SECRET_AF
472 fd2->secret->af = fd->secret->af;
473 #endif
474 }
475 return fd2;
476 }
477 #endif /* WINNT */
478
479
480 static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr)
481 {
482 PRInt32 result;
483 const PRNetAddr *addrp = addr;
484 #if defined(_PR_INET6)
485 PRNetAddr addrCopy;
486 #endif
487
488 PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
489
490 #ifdef XP_UNIX
491 if (addr->raw.family == AF_UNIX) {
492 /* Disallow relative pathnames */
493 if (addr->local.path[0] != '/') {
494 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
495 return PR_FAILURE;
496 }
497 }
498 #endif /* XP_UNIX */
499
500 #if defined(_PR_INET6)
501 if (addr->raw.family == PR_AF_INET6) {
502 addrCopy = *addr;
503 addrCopy.raw.family = AF_INET6;
504 addrp = &addrCopy;
505 }
506 #endif
507 result = _PR_MD_BIND(fd, addrp, PR_NETADDR_SIZE(addr));
508 if (result < 0) {
509 return PR_FAILURE;
510 }
511 return PR_SUCCESS;
512 }
513
514 static PRStatus PR_CALLBACK SocketListen(PRFileDesc *fd, PRIntn backlog)
515 {
516 PRInt32 result;
517
518 result = _PR_MD_LISTEN(fd, backlog);
519 if (result < 0) {
520 return PR_FAILURE;
521 }
522 return PR_SUCCESS;
523 }
524
525 static PRStatus PR_CALLBACK SocketShutdown(PRFileDesc *fd, PRIntn how)
526 {
527 PRInt32 result;
528
529 result = _PR_MD_SHUTDOWN(fd, how);
530 if (result < 0) {
531 return PR_FAILURE;
532 }
533 return PR_SUCCESS;
534 }
535
536 static PRInt32 PR_CALLBACK SocketRecv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
537 PRIntervalTime timeout)
538 {
539 PRInt32 rv;
540 PRThread *me = _PR_MD_CURRENT_THREAD();
541
542 if ((flags != 0) && (flags != PR_MSG_PEEK)) {
543 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
544 return -1;
545 }
546 if (_PR_PENDING_INTERRUPT(me)) {
547 me->flags &= ~_PR_INTERRUPT;
548 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
549 return -1;
550 }
551 if (_PR_IO_PENDING(me)) {
552 PR_SetError(PR_IO_PENDING_ERROR, 0);
553 return -1;
554 }
555
556 PR_LOG(_pr_io_lm, PR_LOG_MAX,
557 ("recv: fd=%p osfd=%" PR_PRIdOSFD " buf=%p amount=%d flags=%d",
558 fd, fd->secret->md.osfd, buf, amount, flags));
559
560 #ifdef _PR_HAVE_PEEK_BUFFER
561 if (fd->secret->peekBytes != 0) {
562 rv = (amount < fd->secret->peekBytes) ?
563 amount : fd->secret->peekBytes;
564 memcpy(buf, fd->secret->peekBuffer, rv);
565 if (flags == 0) {
566 /* consume the bytes in the peek buffer */
567 fd->secret->peekBytes -= rv;
568 if (fd->secret->peekBytes != 0) {
569 memmove(fd->secret->peekBuffer,
570 fd->secret->peekBuffer + rv,
571 fd->secret->peekBytes);
572 }
573 }
574 return rv;
575 }
576
577 /* allocate peek buffer, if necessary */
578 if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) {
579 PR_ASSERT(0 == fd->secret->peekBytes);
580 /* impose a max size on the peek buffer */
581 if (amount > _PR_PEEK_BUFFER_MAX) {
582 amount = _PR_PEEK_BUFFER_MAX;
583 }
584 if (fd->secret->peekBufSize < amount) {
585 if (fd->secret->peekBuffer) {
586 PR_Free(fd->secret->peekBuffer);
587 }
588 fd->secret->peekBufSize = amount;
589 fd->secret->peekBuffer = PR_Malloc(amount);
590 if (NULL == fd->secret->peekBuffer) {
591 fd->secret->peekBufSize = 0;
592 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
593 return -1;
594 }
595 }
596 }
597 #endif
598
599 rv = _PR_MD_RECV(fd, buf, amount, flags, timeout);
600 PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv -> %d, error = %d, os error = %d",
601 rv, PR_GetError(), PR_GetOSError()));
602
603 #ifdef _PR_HAVE_PEEK_BUFFER
604 if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) {
605 if (rv > 0) {
606 memcpy(fd->secret->peekBuffer, buf, rv);
607 fd->secret->peekBytes = rv;
608 }
609 }
610 #endif
611
612 return rv;
613 }
614
615 static PRInt32 PR_CALLBACK SocketRead(PRFileDesc *fd, void *buf, PRInt32 amount)
616 {
617 return SocketRecv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
618 }
619
620 static PRInt32 PR_CALLBACK SocketSend(PRFileDesc *fd, const void *buf, PRInt32 a mount,
621 PRIntn flags, PRIntervalTime timeout)
622 {
623 PRInt32 temp, count;
624 PRThread *me = _PR_MD_CURRENT_THREAD();
625
626 if (_PR_PENDING_INTERRUPT(me)) {
627 me->flags &= ~_PR_INTERRUPT;
628 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
629 return -1;
630 }
631 if (_PR_IO_PENDING(me)) {
632 PR_SetError(PR_IO_PENDING_ERROR, 0);
633 return -1;
634 }
635
636 count = 0;
637 while (amount > 0) {
638 PR_LOG(_pr_io_lm, PR_LOG_MAX,
639 ("send: fd=%p osfd=%" PR_PRIdOSFD " buf=%p amount=%d",
640 fd, fd->secret->md.osfd, buf, amount));
641 temp = _PR_MD_SEND(fd, buf, amount, flags, timeout);
642 if (temp < 0) {
643 count = -1;
644 break;
645 }
646
647 count += temp;
648 if (fd->secret->nonblocking) {
649 break;
650 }
651 buf = (const void*) ((const char*)buf + temp);
652
653 amount -= temp;
654 }
655 PR_LOG(_pr_io_lm, PR_LOG_MAX, ("send -> %d", count));
656 return count;
657 }
658
659 static PRInt32 PR_CALLBACK SocketWrite(PRFileDesc *fd, const void *buf, PRInt32 amount)
660 {
661 return SocketSend(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
662 }
663
664 static PRStatus PR_CALLBACK SocketClose(PRFileDesc *fd)
665 {
666 if (!fd || !fd->secret
667 || (fd->secret->state != _PR_FILEDESC_OPEN
668 && fd->secret->state != _PR_FILEDESC_CLOSED)) {
669 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
670 return PR_FAILURE;
671 }
672
673 if (fd->secret->state == _PR_FILEDESC_OPEN) {
674 if (_PR_MD_CLOSE_SOCKET(fd->secret->md.osfd) < 0) {
675 return PR_FAILURE;
676 }
677 fd->secret->state = _PR_FILEDESC_CLOSED;
678 }
679
680 #ifdef _PR_HAVE_PEEK_BUFFER
681 if (fd->secret->peekBuffer) {
682 PR_ASSERT(fd->secret->peekBufSize > 0);
683 PR_DELETE(fd->secret->peekBuffer);
684 fd->secret->peekBufSize = 0;
685 fd->secret->peekBytes = 0;
686 }
687 #endif
688
689 PR_FreeFileDesc(fd);
690 return PR_SUCCESS;
691 }
692
693 static PRInt32 PR_CALLBACK SocketAvailable(PRFileDesc *fd)
694 {
695 PRInt32 rv;
696 #ifdef _PR_HAVE_PEEK_BUFFER
697 if (fd->secret->peekBytes != 0) {
698 return fd->secret->peekBytes;
699 }
700 #endif
701 rv = _PR_MD_SOCKETAVAILABLE(fd);
702 return rv;
703 }
704
705 static PRInt64 PR_CALLBACK SocketAvailable64(PRFileDesc *fd)
706 {
707 PRInt64 rv;
708 #ifdef _PR_HAVE_PEEK_BUFFER
709 if (fd->secret->peekBytes != 0) {
710 LL_I2L(rv, fd->secret->peekBytes);
711 return rv;
712 }
713 #endif
714 LL_I2L(rv, _PR_MD_SOCKETAVAILABLE(fd));
715 return rv;
716 }
717
718 static PRStatus PR_CALLBACK SocketSync(PRFileDesc *fd)
719 {
720 return PR_SUCCESS;
721 }
722
723 static PRInt32 PR_CALLBACK SocketSendTo(
724 PRFileDesc *fd, const void *buf, PRInt32 amount,
725 PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
726 {
727 PRInt32 temp, count;
728 const PRNetAddr *addrp = addr;
729 #if defined(_PR_INET6)
730 PRNetAddr addrCopy;
731 #endif
732 PRThread *me = _PR_MD_CURRENT_THREAD();
733
734 if (_PR_PENDING_INTERRUPT(me)) {
735 me->flags &= ~_PR_INTERRUPT;
736 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
737 return -1;
738 }
739 if (_PR_IO_PENDING(me)) {
740 PR_SetError(PR_IO_PENDING_ERROR, 0);
741 return -1;
742 }
743
744 PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
745 #if defined(_PR_INET6)
746 if (addr->raw.family == PR_AF_INET6) {
747 addrCopy = *addr;
748 addrCopy.raw.family = AF_INET6;
749 addrp = &addrCopy;
750 }
751 #endif
752
753 count = 0;
754 while (amount > 0) {
755 temp = _PR_MD_SENDTO(fd, buf, amount, flags,
756 addrp, PR_NETADDR_SIZE(addr), timeout);
757 if (temp < 0) {
758 count = -1;
759 break;
760 }
761 count += temp;
762 if (fd->secret->nonblocking) {
763 break;
764 }
765 buf = (const void*) ((const char*)buf + temp);
766 amount -= temp;
767 }
768 return count;
769 }
770
771 static PRInt32 PR_CALLBACK SocketRecvFrom(PRFileDesc *fd, void *buf, PRInt32 amo unt,
772 PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
773 {
774 PRInt32 rv;
775 PRUint32 al;
776 PRThread *me = _PR_MD_CURRENT_THREAD();
777
778 if (_PR_PENDING_INTERRUPT(me)) {
779 me->flags &= ~_PR_INTERRUPT;
780 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
781 return -1;
782 }
783 if (_PR_IO_PENDING(me)) {
784 PR_SetError(PR_IO_PENDING_ERROR, 0);
785 return -1;
786 }
787
788 al = sizeof(PRNetAddr);
789 rv = _PR_MD_RECVFROM(fd, buf, amount, flags, addr, &al, timeout);
790 #ifdef _PR_INET6
791 if (addr && (AF_INET6 == addr->raw.family))
792 addr->raw.family = PR_AF_INET6;
793 #endif
794 return rv;
795 }
796
797 static PRInt32 PR_CALLBACK SocketAcceptRead(PRFileDesc *sd, PRFileDesc **nd,
798 PRNetAddr **raddr, void *buf, PRInt32 amount,
799 PRIntervalTime timeout)
800 {
801 PRInt32 rv;
802 PRThread *me = _PR_MD_CURRENT_THREAD();
803
804 if (_PR_PENDING_INTERRUPT(me)) {
805 me->flags &= ~_PR_INTERRUPT;
806 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
807 return -1;
808 }
809 if (_PR_IO_PENDING(me)) {
810 PR_SetError(PR_IO_PENDING_ERROR, 0);
811 return -1;
812 }
813 /* The socket must be in blocking mode. */
814 if (sd->secret->nonblocking) {
815 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
816 return -1;
817 }
818 *nd = NULL;
819
820 #if defined(WINNT)
821 {
822 PROsfd newSock;
823 PRNetAddr *raddrCopy;
824
825 if (raddr == NULL) {
826 raddr = &raddrCopy;
827 }
828 rv = _PR_MD_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout);
829 if (rv < 0) {
830 rv = -1;
831 } else {
832 /* Successfully accepted and read; create the new PRFileDesc */
833 *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods());
834 if (*nd == 0) {
835 _PR_MD_CLOSE_SOCKET(newSock);
836 /* PR_AllocFileDesc() has invoked PR_SetError(). */
837 rv = -1;
838 } else {
839 (*nd)->secret->md.io_model_committed = PR_TRUE;
840 (*nd)->secret->md.accepted_socket = PR_TRUE;
841 memcpy(&(*nd)->secret->md.peer_addr, *raddr,
842 PR_NETADDR_SIZE(*raddr));
843 #ifdef _PR_INET6
844 if (AF_INET6 == *raddr->raw.family)
845 *raddr->raw.family = PR_AF_INET6;
846 #endif
847 }
848 }
849 }
850 #else
851 rv = PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout);
852 #endif
853 return rv;
854 }
855
856 #ifdef WINNT
857 PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead(PRFileDesc *sd, PRFileDesc **nd,
858 PRNetAddr **raddr, void *buf, PRInt32 amount,
859 PRIntervalTime timeout)
860 {
861 PRInt32 rv;
862 PROsfd newSock;
863 PRThread *me = _PR_MD_CURRENT_THREAD();
864 PRNetAddr *raddrCopy;
865
866 if (_PR_PENDING_INTERRUPT(me)) {
867 me->flags &= ~_PR_INTERRUPT;
868 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
869 return -1;
870 }
871 if (_PR_IO_PENDING(me)) {
872 PR_SetError(PR_IO_PENDING_ERROR, 0);
873 return -1;
874 }
875 *nd = NULL;
876
877 if (raddr == NULL) {
878 raddr = &raddrCopy;
879 }
880 rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount,
881 timeout, PR_TRUE, NULL, NULL);
882 if (rv < 0) {
883 rv = -1;
884 } else {
885 /* Successfully accepted and read; create the new PRFileDesc */
886 *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods());
887 if (*nd == 0) {
888 _PR_MD_CLOSE_SOCKET(newSock);
889 /* PR_AllocFileDesc() has invoked PR_SetError(). */
890 rv = -1;
891 } else {
892 (*nd)->secret->md.io_model_committed = PR_TRUE;
893 (*nd)->secret->md.accepted_socket = PR_TRUE;
894 memcpy(&(*nd)->secret->md.peer_addr, *raddr,
895 PR_NETADDR_SIZE(*raddr));
896 #ifdef _PR_INET6
897 if (AF_INET6 == *raddr->raw.family)
898 *raddr->raw.family = PR_AF_INET6;
899 #endif
900 #ifdef _PR_NEED_SECRET_AF
901 (*nd)->secret->af = sd->secret->af;
902 #endif
903 }
904 }
905 return rv;
906 }
907
908 PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead_WithTimeoutCallback(
909 PRFileDesc *sd, PRFileDesc **nd,
910 PRNetAddr **raddr, void *buf, PRInt32 amount,
911 PRIntervalTime timeout,
912 _PR_AcceptTimeoutCallback callback,
913 void *callbackArg)
914 {
915 PRInt32 rv;
916 PROsfd newSock;
917 PRThread *me = _PR_MD_CURRENT_THREAD();
918 PRNetAddr *raddrCopy;
919
920 if (_PR_PENDING_INTERRUPT(me)) {
921 me->flags &= ~_PR_INTERRUPT;
922 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
923 return -1;
924 }
925 if (_PR_IO_PENDING(me)) {
926 PR_SetError(PR_IO_PENDING_ERROR, 0);
927 return -1;
928 }
929 *nd = NULL;
930
931 if (raddr == NULL) {
932 raddr = &raddrCopy;
933 }
934 rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount,
935 timeout, PR_TRUE, callback, callbackArg);
936 if (rv < 0) {
937 rv = -1;
938 } else {
939 /* Successfully accepted and read; create the new PRFileDesc */
940 *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods());
941 if (*nd == 0) {
942 _PR_MD_CLOSE_SOCKET(newSock);
943 /* PR_AllocFileDesc() has invoked PR_SetError(). */
944 rv = -1;
945 } else {
946 (*nd)->secret->md.io_model_committed = PR_TRUE;
947 (*nd)->secret->md.accepted_socket = PR_TRUE;
948 memcpy(&(*nd)->secret->md.peer_addr, *raddr,
949 PR_NETADDR_SIZE(*raddr));
950 #ifdef _PR_INET6
951 if (AF_INET6 == *raddr->raw.family)
952 *raddr->raw.family = PR_AF_INET6;
953 #endif
954 #ifdef _PR_NEED_SECRET_AF
955 (*nd)->secret->af = sd->secret->af;
956 #endif
957 }
958 }
959 return rv;
960 }
961 #endif /* WINNT */
962
963 #ifdef WINNT
964 PR_IMPLEMENT(void)
965 PR_NTFast_UpdateAcceptContext(PRFileDesc *socket, PRFileDesc *acceptSocket)
966 {
967 _PR_MD_UPDATE_ACCEPT_CONTEXT(
968 socket->secret->md.osfd, acceptSocket->secret->md.osfd);
969 }
970 #endif /* WINNT */
971
972 static PRInt32 PR_CALLBACK SocketSendFile(
973 PRFileDesc *sd, PRSendFileData *sfd,
974 PRTransmitFileFlags flags, PRIntervalTime timeout)
975 {
976 PRInt32 rv;
977 PRThread *me = _PR_MD_CURRENT_THREAD();
978
979 if (_PR_PENDING_INTERRUPT(me)) {
980 me->flags &= ~_PR_INTERRUPT;
981 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
982 return -1;
983 }
984 if (_PR_IO_PENDING(me)) {
985 PR_SetError(PR_IO_PENDING_ERROR, 0);
986 return -1;
987 }
988 /* The socket must be in blocking mode. */
989 if (sd->secret->nonblocking) {
990 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
991 return -1;
992 }
993 #if defined(WINNT)
994 rv = _PR_MD_SENDFILE(sd, sfd, flags, timeout);
995 if ((rv >= 0) && (flags == PR_TRANSMITFILE_CLOSE_SOCKET)) {
996 /*
997 * This should be kept the same as SocketClose, except
998 * that _PR_MD_CLOSE_SOCKET(sd->secret->md.osfd) should
999 * not be called because the socket will be recycled.
1000 */
1001 PR_FreeFileDesc(sd);
1002 }
1003 #else
1004 rv = PR_EmulateSendFile(sd, sfd, flags, timeout);
1005 #endif /* WINNT */
1006
1007 return rv;
1008 }
1009
1010 static PRInt32 PR_CALLBACK SocketTransmitFile(PRFileDesc *sd, PRFileDesc *fd,
1011 const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
1012 PRIntervalTime timeout)
1013 {
1014 PRSendFileData sfd;
1015
1016 sfd.fd = fd;
1017 sfd.file_offset = 0;
1018 sfd.file_nbytes = 0;
1019 sfd.header = headers;
1020 sfd.hlen = hlen;
1021 sfd.trailer = NULL;
1022 sfd.tlen = 0;
1023
1024 return(SocketSendFile(sd, &sfd, flags, timeout));
1025 }
1026
1027 static PRStatus PR_CALLBACK SocketGetName(PRFileDesc *fd, PRNetAddr *addr)
1028 {
1029 PRInt32 result;
1030 PRUint32 addrlen;
1031
1032 addrlen = sizeof(PRNetAddr);
1033 result = _PR_MD_GETSOCKNAME(fd, addr, &addrlen);
1034 if (result < 0) {
1035 return PR_FAILURE;
1036 }
1037 #ifdef _PR_INET6
1038 if (AF_INET6 == addr->raw.family)
1039 addr->raw.family = PR_AF_INET6;
1040 #endif
1041 PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
1042 PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE);
1043 return PR_SUCCESS;
1044 }
1045
1046 static PRStatus PR_CALLBACK SocketGetPeerName(PRFileDesc *fd, PRNetAddr *addr)
1047 {
1048 PRInt32 result;
1049 PRUint32 addrlen;
1050
1051 addrlen = sizeof(PRNetAddr);
1052 result = _PR_MD_GETPEERNAME(fd, addr, &addrlen);
1053 if (result < 0) {
1054 return PR_FAILURE;
1055 }
1056 #ifdef _PR_INET6
1057 if (AF_INET6 == addr->raw.family)
1058 addr->raw.family = PR_AF_INET6;
1059 #endif
1060 PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
1061 PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE);
1062 return PR_SUCCESS;
1063 }
1064
1065 static PRInt16 PR_CALLBACK SocketPoll(
1066 PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
1067 {
1068 *out_flags = 0;
1069 return in_flags;
1070 } /* SocketPoll */
1071
1072 static PRIOMethods tcpMethods = {
1073 PR_DESC_SOCKET_TCP,
1074 SocketClose,
1075 SocketRead,
1076 SocketWrite,
1077 SocketAvailable,
1078 SocketAvailable64,
1079 SocketSync,
1080 (PRSeekFN)_PR_InvalidInt,
1081 (PRSeek64FN)_PR_InvalidInt64,
1082 (PRFileInfoFN)_PR_InvalidStatus,
1083 (PRFileInfo64FN)_PR_InvalidStatus,
1084 SocketWritev,
1085 SocketConnect,
1086 SocketAccept,
1087 SocketBind,
1088 SocketListen,
1089 SocketShutdown,
1090 SocketRecv,
1091 SocketSend,
1092 (PRRecvfromFN)_PR_InvalidInt,
1093 (PRSendtoFN)_PR_InvalidInt,
1094 SocketPoll,
1095 SocketAcceptRead,
1096 SocketTransmitFile,
1097 SocketGetName,
1098 SocketGetPeerName,
1099 (PRReservedFN)_PR_InvalidInt,
1100 (PRReservedFN)_PR_InvalidInt,
1101 _PR_SocketGetSocketOption,
1102 _PR_SocketSetSocketOption,
1103 SocketSendFile,
1104 SocketConnectContinue,
1105 (PRReservedFN)_PR_InvalidInt,
1106 (PRReservedFN)_PR_InvalidInt,
1107 (PRReservedFN)_PR_InvalidInt,
1108 (PRReservedFN)_PR_InvalidInt
1109 };
1110
1111 static PRIOMethods udpMethods = {
1112 PR_DESC_SOCKET_UDP,
1113 SocketClose,
1114 SocketRead,
1115 SocketWrite,
1116 SocketAvailable,
1117 SocketAvailable64,
1118 SocketSync,
1119 (PRSeekFN)_PR_InvalidInt,
1120 (PRSeek64FN)_PR_InvalidInt64,
1121 (PRFileInfoFN)_PR_InvalidStatus,
1122 (PRFileInfo64FN)_PR_InvalidStatus,
1123 SocketWritev,
1124 SocketConnect,
1125 (PRAcceptFN)_PR_InvalidDesc,
1126 SocketBind,
1127 SocketListen,
1128 SocketShutdown,
1129 SocketRecv,
1130 SocketSend,
1131 SocketRecvFrom,
1132 SocketSendTo,
1133 SocketPoll,
1134 (PRAcceptreadFN)_PR_InvalidInt,
1135 (PRTransmitfileFN)_PR_InvalidInt,
1136 SocketGetName,
1137 SocketGetPeerName,
1138 (PRReservedFN)_PR_InvalidInt,
1139 (PRReservedFN)_PR_InvalidInt,
1140 _PR_SocketGetSocketOption,
1141 _PR_SocketSetSocketOption,
1142 (PRSendfileFN)_PR_InvalidInt,
1143 (PRConnectcontinueFN)_PR_InvalidStatus,
1144 (PRReservedFN)_PR_InvalidInt,
1145 (PRReservedFN)_PR_InvalidInt,
1146 (PRReservedFN)_PR_InvalidInt,
1147 (PRReservedFN)_PR_InvalidInt
1148 };
1149
1150
1151 static PRIOMethods socketpollfdMethods = {
1152 (PRDescType) 0,
1153 (PRCloseFN)_PR_InvalidStatus,
1154 (PRReadFN)_PR_InvalidInt,
1155 (PRWriteFN)_PR_InvalidInt,
1156 (PRAvailableFN)_PR_InvalidInt,
1157 (PRAvailable64FN)_PR_InvalidInt64,
1158 (PRFsyncFN)_PR_InvalidStatus,
1159 (PRSeekFN)_PR_InvalidInt,
1160 (PRSeek64FN)_PR_InvalidInt64,
1161 (PRFileInfoFN)_PR_InvalidStatus,
1162 (PRFileInfo64FN)_PR_InvalidStatus,
1163 (PRWritevFN)_PR_InvalidInt,
1164 (PRConnectFN)_PR_InvalidStatus,
1165 (PRAcceptFN)_PR_InvalidDesc,
1166 (PRBindFN)_PR_InvalidStatus,
1167 (PRListenFN)_PR_InvalidStatus,
1168 (PRShutdownFN)_PR_InvalidStatus,
1169 (PRRecvFN)_PR_InvalidInt,
1170 (PRSendFN)_PR_InvalidInt,
1171 (PRRecvfromFN)_PR_InvalidInt,
1172 (PRSendtoFN)_PR_InvalidInt,
1173 SocketPoll,
1174 (PRAcceptreadFN)_PR_InvalidInt,
1175 (PRTransmitfileFN)_PR_InvalidInt,
1176 (PRGetsocknameFN)_PR_InvalidStatus,
1177 (PRGetpeernameFN)_PR_InvalidStatus,
1178 (PRReservedFN)_PR_InvalidInt,
1179 (PRReservedFN)_PR_InvalidInt,
1180 (PRGetsocketoptionFN)_PR_InvalidStatus,
1181 (PRSetsocketoptionFN)_PR_InvalidStatus,
1182 (PRSendfileFN)_PR_InvalidInt,
1183 (PRConnectcontinueFN)_PR_InvalidStatus,
1184 (PRReservedFN)_PR_InvalidInt,
1185 (PRReservedFN)_PR_InvalidInt,
1186 (PRReservedFN)_PR_InvalidInt,
1187 (PRReservedFN)_PR_InvalidInt
1188 };
1189
1190 PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods()
1191 {
1192 return &tcpMethods;
1193 }
1194
1195 PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods()
1196 {
1197 return &udpMethods;
1198 }
1199
1200 static const PRIOMethods* PR_GetSocketPollFdMethods()
1201 {
1202 return &socketpollfdMethods;
1203 } /* PR_GetSocketPollFdMethods */
1204
1205 #if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
1206 PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd);
1207
1208 #if defined(_PR_INET6_PROBE)
1209
1210 extern PRBool _pr_ipv6_is_present(void);
1211
1212 PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket()
1213 {
1214 PROsfd osfd;
1215
1216 osfd = _PR_MD_SOCKET(AF_INET6, SOCK_STREAM, 0);
1217 if (osfd != -1) {
1218 _PR_MD_CLOSE_SOCKET(osfd);
1219 return PR_TRUE;
1220 }
1221 return PR_FALSE;
1222 }
1223 #endif /* _PR_INET6_PROBE */
1224
1225 #endif
1226
1227 PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
1228 {
1229 PROsfd osfd;
1230 PRFileDesc *fd;
1231 PRInt32 tmp_domain = domain;
1232
1233 if (!_pr_initialized) _PR_ImplicitInitialization();
1234 if (PR_AF_INET != domain
1235 && PR_AF_INET6 != domain
1236 #if defined(XP_UNIX) || defined(XP_OS2)
1237 && PR_AF_LOCAL != domain
1238 #endif
1239 ) {
1240 PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
1241 return NULL;
1242 }
1243
1244 #if defined(_PR_INET6_PROBE)
1245 if (PR_AF_INET6 == domain)
1246 domain = _pr_ipv6_is_present() ? AF_INET6 : AF_INET;
1247 #elif defined(_PR_INET6)
1248 if (PR_AF_INET6 == domain)
1249 domain = AF_INET6;
1250 #else
1251 if (PR_AF_INET6 == domain)
1252 domain = AF_INET;
1253 #endif /* _PR_INET6 */
1254 osfd = _PR_MD_SOCKET(domain, type, proto);
1255 if (osfd == -1) {
1256 return 0;
1257 }
1258 if (type == SOCK_STREAM)
1259 fd = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
1260 else
1261 fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods());
1262 /*
1263 * Make the sockets non-blocking
1264 */
1265 if (fd != NULL) {
1266 _PR_MD_MAKE_NONBLOCK(fd);
1267 _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
1268 #ifdef _PR_NEED_SECRET_AF
1269 fd->secret->af = domain;
1270 #endif
1271 #if defined(_PR_INET6_PROBE) || !defined(_PR_INET6)
1272 /*
1273 * For platforms with no support for IPv6
1274 * create layered socket for IPv4-mapped IPv6 addresses
1275 */
1276 if (PR_AF_INET6 == tmp_domain && PR_AF_INET == domain) {
1277 if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) {
1278 PR_Close(fd);
1279 fd = NULL;
1280 }
1281 }
1282 #endif
1283 } else
1284 _PR_MD_CLOSE_SOCKET(osfd);
1285
1286 return fd;
1287 }
1288
1289 PR_IMPLEMENT(PRFileDesc *) PR_NewTCPSocket(void)
1290 {
1291 PRInt32 domain = AF_INET;
1292
1293 return PR_Socket(domain, SOCK_STREAM, 0);
1294 }
1295
1296 PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void)
1297 {
1298 PRInt32 domain = AF_INET;
1299
1300 return PR_Socket(domain, SOCK_DGRAM, 0);
1301 }
1302
1303 PR_IMPLEMENT(PRFileDesc *) PR_OpenTCPSocket(PRIntn af)
1304 {
1305 return PR_Socket(af, SOCK_STREAM, 0);
1306 }
1307
1308 PR_IMPLEMENT(PRFileDesc*) PR_OpenUDPSocket(PRIntn af)
1309 {
1310 return PR_Socket(af, SOCK_DGRAM, 0);
1311 }
1312
1313 PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[])
1314 {
1315 #ifdef XP_UNIX
1316 PRInt32 rv, osfd[2];
1317
1318 if (!_pr_initialized) _PR_ImplicitInitialization();
1319
1320 rv = _PR_MD_SOCKETPAIR(AF_UNIX, SOCK_STREAM, 0, osfd);
1321 if (rv == -1) {
1322 return PR_FAILURE;
1323 }
1324
1325 f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods());
1326 if (!f[0]) {
1327 _PR_MD_CLOSE_SOCKET(osfd[0]);
1328 _PR_MD_CLOSE_SOCKET(osfd[1]);
1329 /* PR_AllocFileDesc() has invoked PR_SetError(). */
1330 return PR_FAILURE;
1331 }
1332 f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods());
1333 if (!f[1]) {
1334 PR_Close(f[0]);
1335 _PR_MD_CLOSE_SOCKET(osfd[1]);
1336 /* PR_AllocFileDesc() has invoked PR_SetError(). */
1337 return PR_FAILURE;
1338 }
1339 _PR_MD_MAKE_NONBLOCK(f[0]);
1340 _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE);
1341 _PR_MD_MAKE_NONBLOCK(f[1]);
1342 _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE);
1343 return PR_SUCCESS;
1344 #elif defined(WINNT)
1345 /*
1346 * A socket pair is often used for interprocess communication,
1347 * so we need to make sure neither socket is associated with
1348 * the I/O completion port; otherwise it can't be used by a
1349 * child process.
1350 *
1351 * The default implementation below cannot be used for NT
1352 * because PR_Accept would have associated the I/O completion
1353 * port with the listening and accepted sockets.
1354 */
1355 SOCKET listenSock;
1356 SOCKET osfd[2];
1357 struct sockaddr_in selfAddr, peerAddr;
1358 int addrLen;
1359
1360 if (!_pr_initialized) _PR_ImplicitInitialization();
1361
1362 osfd[0] = osfd[1] = INVALID_SOCKET;
1363 listenSock = socket(AF_INET, SOCK_STREAM, 0);
1364 if (listenSock == INVALID_SOCKET) {
1365 goto failed;
1366 }
1367 selfAddr.sin_family = AF_INET;
1368 selfAddr.sin_port = 0;
1369 selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* BugZilla: 35408 */
1370 addrLen = sizeof(selfAddr);
1371 if (bind(listenSock, (struct sockaddr *) &selfAddr,
1372 addrLen) == SOCKET_ERROR) {
1373 goto failed;
1374 }
1375 if (getsockname(listenSock, (struct sockaddr *) &selfAddr,
1376 &addrLen) == SOCKET_ERROR) {
1377 goto failed;
1378 }
1379 if (listen(listenSock, 5) == SOCKET_ERROR) {
1380 goto failed;
1381 }
1382 osfd[0] = socket(AF_INET, SOCK_STREAM, 0);
1383 if (osfd[0] == INVALID_SOCKET) {
1384 goto failed;
1385 }
1386 selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1387
1388 /*
1389 * Only a thread is used to do the connect and accept.
1390 * I am relying on the fact that connect returns
1391 * successfully as soon as the connect request is put
1392 * into the listen queue (but before accept is called).
1393 * This is the behavior of the BSD socket code. If
1394 * connect does not return until accept is called, we
1395 * will need to create another thread to call connect.
1396 */
1397 if (connect(osfd[0], (struct sockaddr *) &selfAddr,
1398 addrLen) == SOCKET_ERROR) {
1399 goto failed;
1400 }
1401 /*
1402 * A malicious local process may connect to the listening
1403 * socket, so we need to verify that the accepted connection
1404 * is made from our own socket osfd[0].
1405 */
1406 if (getsockname(osfd[0], (struct sockaddr *) &selfAddr,
1407 &addrLen) == SOCKET_ERROR) {
1408 goto failed;
1409 }
1410 osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen);
1411 if (osfd[1] == INVALID_SOCKET) {
1412 goto failed;
1413 }
1414 if (peerAddr.sin_port != selfAddr.sin_port) {
1415 /* the connection we accepted is not from osfd[0] */
1416 PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
1417 goto failed;
1418 }
1419 closesocket(listenSock);
1420
1421 f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods());
1422 if (!f[0]) {
1423 closesocket(osfd[0]);
1424 closesocket(osfd[1]);
1425 /* PR_AllocFileDesc() has invoked PR_SetError(). */
1426 return PR_FAILURE;
1427 }
1428 f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods());
1429 if (!f[1]) {
1430 PR_Close(f[0]);
1431 closesocket(osfd[1]);
1432 /* PR_AllocFileDesc() has invoked PR_SetError(). */
1433 return PR_FAILURE;
1434 }
1435 _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE);
1436 _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE);
1437 return PR_SUCCESS;
1438
1439 failed:
1440 if (listenSock != INVALID_SOCKET) {
1441 closesocket(listenSock);
1442 }
1443 if (osfd[0] != INVALID_SOCKET) {
1444 closesocket(osfd[0]);
1445 }
1446 if (osfd[1] != INVALID_SOCKET) {
1447 closesocket(osfd[1]);
1448 }
1449 return PR_FAILURE;
1450 #else /* not Unix or NT */
1451 /*
1452 * default implementation
1453 */
1454 PRFileDesc *listenSock;
1455 PRNetAddr selfAddr, peerAddr;
1456 PRUint16 port;
1457
1458 f[0] = f[1] = NULL;
1459 listenSock = PR_NewTCPSocket();
1460 if (listenSock == NULL) {
1461 goto failed;
1462 }
1463 PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); /* BugZilla: 35408 */
1464 if (PR_Bind(listenSock, &selfAddr) == PR_FAILURE) {
1465 goto failed;
1466 }
1467 if (PR_GetSockName(listenSock, &selfAddr) == PR_FAILURE) {
1468 goto failed;
1469 }
1470 port = ntohs(selfAddr.inet.port);
1471 if (PR_Listen(listenSock, 5) == PR_FAILURE) {
1472 goto failed;
1473 }
1474 f[0] = PR_NewTCPSocket();
1475 if (f[0] == NULL) {
1476 goto failed;
1477 }
1478 #ifdef _PR_CONNECT_DOES_NOT_BIND
1479 /*
1480 * If connect does not implicitly bind the socket (e.g., on
1481 * BeOS), we have to bind the socket so that we can get its
1482 * port with getsockname later.
1483 */
1484 PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr);
1485 if (PR_Bind(f[0], &selfAddr) == PR_FAILURE) {
1486 goto failed;
1487 }
1488 #endif
1489 PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr);
1490
1491 /*
1492 * Only a thread is used to do the connect and accept.
1493 * I am relying on the fact that PR_Connect returns
1494 * successfully as soon as the connect request is put
1495 * into the listen queue (but before PR_Accept is called).
1496 * This is the behavior of the BSD socket code. If
1497 * connect does not return until accept is called, we
1498 * will need to create another thread to call connect.
1499 */
1500 if (PR_Connect(f[0], &selfAddr, PR_INTERVAL_NO_TIMEOUT)
1501 == PR_FAILURE) {
1502 goto failed;
1503 }
1504 /*
1505 * A malicious local process may connect to the listening
1506 * socket, so we need to verify that the accepted connection
1507 * is made from our own socket f[0].
1508 */
1509 if (PR_GetSockName(f[0], &selfAddr) == PR_FAILURE) {
1510 goto failed;
1511 }
1512 f[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT);
1513 if (f[1] == NULL) {
1514 goto failed;
1515 }
1516 if (peerAddr.inet.port != selfAddr.inet.port) {
1517 /* the connection we accepted is not from f[0] */
1518 PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
1519 goto failed;
1520 }
1521 PR_Close(listenSock);
1522 return PR_SUCCESS;
1523
1524 failed:
1525 if (listenSock) {
1526 PR_Close(listenSock);
1527 }
1528 if (f[0]) {
1529 PR_Close(f[0]);
1530 }
1531 if (f[1]) {
1532 PR_Close(f[1]);
1533 }
1534 return PR_FAILURE;
1535 #endif
1536 }
1537
1538 PR_IMPLEMENT(PROsfd)
1539 PR_FileDesc2NativeHandle(PRFileDesc *fd)
1540 {
1541 if (fd) {
1542 fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER);
1543 }
1544 if (!fd) {
1545 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
1546 return -1;
1547 }
1548 return fd->secret->md.osfd;
1549 }
1550
1551 PR_IMPLEMENT(void)
1552 PR_ChangeFileDescNativeHandle(PRFileDesc *fd, PROsfd handle)
1553 {
1554 if (fd)
1555 fd->secret->md.osfd = handle;
1556 }
1557
1558 /*
1559 ** Select compatibility
1560 **
1561 */
1562
1563 PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set)
1564 {
1565 memset(set, 0, sizeof(PR_fd_set));
1566 }
1567
1568 PR_IMPLEMENT(void) PR_FD_SET(PRFileDesc *fh, PR_fd_set *set)
1569 {
1570 PR_ASSERT( set->hsize < PR_MAX_SELECT_DESC );
1571
1572 set->harray[set->hsize++] = fh;
1573 }
1574
1575 PR_IMPLEMENT(void) PR_FD_CLR(PRFileDesc *fh, PR_fd_set *set)
1576 {
1577 PRUint32 index, index2;
1578
1579 for (index = 0; index<set->hsize; index++)
1580 if (set->harray[index] == fh) {
1581 for (index2=index; index2 < (set->hsize-1); index2++) {
1582 set->harray[index2] = set->harray[index2+1];
1583 }
1584 set->hsize--;
1585 break;
1586 }
1587 }
1588
1589 PR_IMPLEMENT(PRInt32) PR_FD_ISSET(PRFileDesc *fh, PR_fd_set *set)
1590 {
1591 PRUint32 index;
1592 for (index = 0; index<set->hsize; index++)
1593 if (set->harray[index] == fh) {
1594 return 1;
1595 }
1596 return 0;
1597 }
1598
1599 PR_IMPLEMENT(void) PR_FD_NSET(PROsfd fd, PR_fd_set *set)
1600 {
1601 PR_ASSERT( set->nsize < PR_MAX_SELECT_DESC );
1602
1603 set->narray[set->nsize++] = fd;
1604 }
1605
1606 PR_IMPLEMENT(void) PR_FD_NCLR(PROsfd fd, PR_fd_set *set)
1607 {
1608 PRUint32 index, index2;
1609
1610 for (index = 0; index<set->nsize; index++)
1611 if (set->narray[index] == fd) {
1612 for (index2=index; index2 < (set->nsize-1); index2++) {
1613 set->narray[index2] = set->narray[index2+1];
1614 }
1615 set->nsize--;
1616 break;
1617 }
1618 }
1619
1620 PR_IMPLEMENT(PRInt32) PR_FD_NISSET(PROsfd fd, PR_fd_set *set)
1621 {
1622 PRUint32 index;
1623 for (index = 0; index<set->nsize; index++)
1624 if (set->narray[index] == fd) {
1625 return 1;
1626 }
1627 return 0;
1628 }
1629
1630
1631 #if !defined(NEED_SELECT)
1632 #include "obsolete/probslet.h"
1633
1634 #define PD_INCR 20
1635
1636 static PRPollDesc *_pr_setfd(
1637 PR_fd_set *set, PRInt16 flags, PRPollDesc *polldesc)
1638 {
1639 PRUintn fsidx, pdidx;
1640 PRPollDesc *poll = polldesc;
1641
1642 if (NULL == set) return poll;
1643
1644 /* First set the pr file handle osfds */
1645 for (fsidx = 0; fsidx < set->hsize; fsidx++)
1646 {
1647 for (pdidx = 0; 1; pdidx++)
1648 {
1649 if ((PRFileDesc*)-1 == poll[pdidx].fd)
1650 {
1651 /* our vector is full - extend and condition it */
1652 poll = (PRPollDesc*)PR_Realloc(
1653 poll, (pdidx + 1 + PD_INCR) * sizeof(PRPollDesc));
1654 if (NULL == poll) goto out_of_memory;
1655 memset(
1656 poll + pdidx * sizeof(PRPollDesc),
1657 0, PD_INCR * sizeof(PRPollDesc));
1658 poll[pdidx + PD_INCR].fd = (PRFileDesc*)-1;
1659 }
1660 if ((NULL == poll[pdidx].fd)
1661 || (poll[pdidx].fd == set->harray[fsidx]))
1662 {
1663 /* PR_ASSERT(0 == (poll[pdidx].in_flags & flags)); */
1664 /* either empty or prevously defined */
1665 poll[pdidx].fd = set->harray[fsidx]; /* possibly redundant */
1666 poll[pdidx].in_flags |= flags; /* possibly redundant */
1667 break;
1668 }
1669 }
1670 }
1671
1672 #if 0
1673 /* Second set the native osfds */
1674 for (fsidx = 0; fsidx < set->nsize; fsidx++)
1675 {
1676 for (pdidx = 0; ((PRFileDesc*)-1 != poll[pdidx].fd); pdidx++)
1677 {
1678 if ((PRFileDesc*)-1 == poll[pdidx].fd)
1679 {
1680 /* our vector is full - extend and condition it */
1681 poll = PR_Realloc(
1682 poll, (pdidx + PD_INCR) * sizeof(PRPollDesc));
1683 if (NULL == poll) goto out_of_memory;
1684 memset(
1685 poll + pdidx * sizeof(PRPollDesc),
1686 0, PD_INCR * sizeof(PRPollDesc));
1687 poll[(pdidx + PD_INCR)].fd = (PRFileDesc*)-1;
1688 }
1689 if ((NULL == poll[pdidx].fd)
1690 || (poll[pdidx].fd == set->narray[fsidx]))
1691 {
1692 /* either empty or prevously defined */
1693 poll[pdidx].fd = set->narray[fsidx];
1694 PR_ASSERT(0 == (poll[pdidx].in_flags & flags));
1695 poll[pdidx].in_flags |= flags;
1696 break;
1697 }
1698 }
1699 }
1700 #endif /* 0 */
1701
1702 return poll;
1703
1704 out_of_memory:
1705 if (NULL != polldesc) PR_DELETE(polldesc);
1706 return NULL;
1707 } /* _pr_setfd */
1708
1709 #endif /* !defined(NEED_SELECT) */
1710
1711 PR_IMPLEMENT(PRInt32) PR_Select(
1712 PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr,
1713 PR_fd_set *pr_ex, PRIntervalTime timeout)
1714 {
1715
1716 #if !defined(NEED_SELECT)
1717 PRInt32 npds = 0;
1718 /*
1719 ** Find out how many fds are represented in the three lists.
1720 ** Then allocate a polling descriptor for the logical union
1721 ** (there can't be any overlapping) and call PR_Poll().
1722 */
1723
1724 PRPollDesc *copy, *poll;
1725
1726 static PRBool warning = PR_TRUE;
1727 if (warning) warning = _PR_Obsolete( "PR_Select()", "PR_Poll()");
1728
1729 /* try to get an initial guesss at how much space we need */
1730 npds = 0;
1731 if ((NULL != pr_rd) && ((pr_rd->hsize + pr_rd->nsize - npds) > 0))
1732 npds = pr_rd->hsize + pr_rd->nsize;
1733 if ((NULL != pr_wr) && ((pr_wr->hsize + pr_wr->nsize - npds) > 0))
1734 npds = pr_wr->hsize + pr_wr->nsize;
1735 if ((NULL != pr_ex) && ((pr_ex->hsize + pr_ex->nsize - npds) > 0))
1736 npds = pr_ex->hsize + pr_ex->nsize;
1737
1738 if (0 == npds)
1739 {
1740 PR_Sleep(timeout);
1741 return 0;
1742 }
1743
1744 copy = poll = (PRPollDesc*)PR_Calloc(npds + PD_INCR, sizeof(PRPollDesc));
1745 if (NULL == poll) goto out_of_memory;
1746 poll[npds + PD_INCR - 1].fd = (PRFileDesc*)-1;
1747
1748 poll = _pr_setfd(pr_rd, PR_POLL_READ, poll);
1749 if (NULL == poll) goto out_of_memory;
1750 poll = _pr_setfd(pr_wr, PR_POLL_WRITE, poll);
1751 if (NULL == poll) goto out_of_memory;
1752 poll = _pr_setfd(pr_ex, PR_POLL_EXCEPT, poll);
1753 if (NULL == poll) goto out_of_memory;
1754 unused = 0;
1755 while (NULL != poll[unused].fd && (PRFileDesc*)-1 != poll[unused].fd)
1756 {
1757 ++unused;
1758 }
1759
1760 PR_ASSERT(unused > 0);
1761 npds = PR_Poll(poll, unused, timeout);
1762
1763 if (npds > 0)
1764 {
1765 /* Copy the results back into the fd sets */
1766 if (NULL != pr_rd) pr_rd->nsize = pr_rd->hsize = 0;
1767 if (NULL != pr_wr) pr_wr->nsize = pr_wr->hsize = 0;
1768 if (NULL != pr_ex) pr_ex->nsize = pr_ex->hsize = 0;
1769 for (copy = &poll[unused - 1]; copy >= poll; --copy)
1770 {
1771 if (copy->out_flags & PR_POLL_NVAL)
1772 {
1773 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
1774 npds = -1;
1775 break;
1776 }
1777 if (copy->out_flags & PR_POLL_READ)
1778 if (NULL != pr_rd) pr_rd->harray[pr_rd->hsize++] = copy->fd;
1779 if (copy->out_flags & PR_POLL_WRITE)
1780 if (NULL != pr_wr) pr_wr->harray[pr_wr->hsize++] = copy->fd;
1781 if (copy->out_flags & PR_POLL_EXCEPT)
1782 if (NULL != pr_ex) pr_ex->harray[pr_ex->hsize++] = copy->fd;
1783 }
1784 }
1785 PR_DELETE(poll);
1786
1787 return npds;
1788 out_of_memory:
1789 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
1790 return -1;
1791
1792 #endif /* !defined(NEED_SELECT) */
1793
1794 }
OLDNEW
« no previous file with comments | « nspr/pr/src/io/prscanf.c ('k') | nspr/pr/src/io/prstdio.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698