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

Side by Side Diff: mozilla/nsprpub/pr/src/io/prsocket.c

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

Powered by Google App Engine
This is Rietveld 408576698