|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 /* OS/2 Sockets module |
|
8 * |
|
9 */ |
|
10 |
|
11 /*Note from DSR111297 - it should be noted that there are two flavors of select() on OS/2 */ |
|
12 /*There is standard BSD (which is kind of slow) and a new flavor of select() that takes */ |
|
13 /*an integer list of sockets, the number of read sockets, write sockets, except sockets, and */ |
|
14 /*a millisecond count for timeout. In the interest of performance I have choosen the OS/2 */ |
|
15 /*specific version of select(). See OS/2 TCP/IP Programmer's Toolkit for more info. */ |
|
16 |
|
17 #include "primpl.h" |
|
18 |
|
19 #include <sys/time.h> /* For timeval. */ |
|
20 |
|
21 #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5 |
|
22 #define READ_FD 1 |
|
23 #define WRITE_FD 2 |
|
24 |
|
25 /* --- SOCKET IO --------------------------------------------------------- */ |
|
26 |
|
27 |
|
28 PRInt32 |
|
29 _PR_MD_SOCKET(int domain, int type, int flags) |
|
30 { |
|
31 PRInt32 osfd, err; |
|
32 |
|
33 osfd = socket(domain, type, flags); |
|
34 |
|
35 if (osfd == -1) |
|
36 { |
|
37 err = sock_errno(); |
|
38 _PR_MD_MAP_SOCKET_ERROR(err); |
|
39 } |
|
40 |
|
41 return(osfd); |
|
42 } |
|
43 |
|
44 /* |
|
45 ** _MD_CloseSocket() -- Close a socket |
|
46 ** |
|
47 */ |
|
48 PRInt32 |
|
49 _MD_CloseSocket(PRInt32 osfd) |
|
50 { |
|
51 PRInt32 rv, err; |
|
52 |
|
53 rv = soclose(osfd); |
|
54 if (rv == -1) { |
|
55 err = sock_errno(); |
|
56 _PR_MD_MAP_CLOSE_ERROR(err); |
|
57 } |
|
58 return rv; |
|
59 } |
|
60 |
|
61 PRInt32 |
|
62 _MD_SocketAvailable(PRFileDesc *fd) |
|
63 { |
|
64 PRInt32 result; |
|
65 |
|
66 if (so_ioctl(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) { |
|
67 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, sock_errno()); |
|
68 return -1; |
|
69 } |
|
70 return result; |
|
71 } |
|
72 |
|
73 static PRInt32 |
|
74 socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout ) |
|
75 { |
|
76 PRInt32 rv = -1; |
|
77 PRThread *me = _PR_MD_CURRENT_THREAD(); |
|
78 PRIntervalTime epoch, now, elapsed, remaining; |
|
79 PRBool wait_for_remaining; |
|
80 PRInt32 syserror; |
|
81 #ifdef BSD_SELECT |
|
82 struct timeval tv; |
|
83 fd_set rd_wr; |
|
84 #else |
|
85 int socks[1]; |
|
86 long lTimeout; |
|
87 #endif |
|
88 |
|
89 switch (timeout) { |
|
90 case PR_INTERVAL_NO_WAIT: |
|
91 PR_SetError(PR_IO_TIMEOUT_ERROR, 0); |
|
92 break; |
|
93 case PR_INTERVAL_NO_TIMEOUT: |
|
94 /* |
|
95 * This is a special case of the 'default' case below. |
|
96 * Please see the comments there. |
|
97 */ |
|
98 #ifdef BSD_SELECT |
|
99 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; |
|
100 tv.tv_usec = 0; |
|
101 FD_ZERO(&rd_wr); |
|
102 do { |
|
103 FD_SET(osfd, &rd_wr); |
|
104 if (fd_type == READ_FD) |
|
105 rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv); |
|
106 else |
|
107 rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv); |
|
108 #else |
|
109 lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; |
|
110 do { |
|
111 socks[0] = osfd; |
|
112 if (fd_type == READ_FD) |
|
113 rv = os2_select(socks, 1, 0, 0, lTimeout); |
|
114 else |
|
115 rv = os2_select(socks, 0, 1, 0, lTimeout); |
|
116 #endif |
|
117 if (rv == -1 && (syserror = sock_errno()) != EINTR) { |
|
118 _PR_MD_MAP_SELECT_ERROR(syserror); |
|
119 break; |
|
120 } |
|
121 if (_PR_PENDING_INTERRUPT(me)) { |
|
122 me->flags &= ~_PR_INTERRUPT; |
|
123 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); |
|
124 rv = -1; |
|
125 break; |
|
126 } |
|
127 } while (rv == 0 || (rv == -1 && syserror == EINTR)); |
|
128 break; |
|
129 default: |
|
130 now = epoch = PR_IntervalNow(); |
|
131 remaining = timeout; |
|
132 #ifdef BSD_SELECT |
|
133 FD_ZERO(&rd_wr); |
|
134 #endif |
|
135 do { |
|
136 /* |
|
137 * We block in select for at most |
|
138 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, |
|
139 * so that there is an upper limit on the delay |
|
140 * before the interrupt bit is checked. |
|
141 */ |
|
142 #ifdef BSD_SELECT |
|
143 wait_for_remaining = PR_TRUE; |
|
144 tv.tv_sec = PR_IntervalToSeconds(remaining); |
|
145 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { |
|
146 wait_for_remaining = PR_FALSE; |
|
147 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; |
|
148 tv.tv_usec = 0; |
|
149 } else { |
|
150 tv.tv_usec = PR_IntervalToMicroseconds( |
|
151 remaining - |
|
152 PR_SecondsToInterval(tv.tv_sec)); |
|
153 } |
|
154 FD_SET(osfd, &rd_wr); |
|
155 if (fd_type == READ_FD) |
|
156 rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv); |
|
157 else |
|
158 rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv); |
|
159 #else |
|
160 wait_for_remaining = PR_TRUE; |
|
161 lTimeout = PR_IntervalToMilliseconds(remaining); |
|
162 if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) { |
|
163 wait_for_remaining = PR_FALSE; |
|
164 lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; |
|
165 } |
|
166 socks[0] = osfd; |
|
167 if (fd_type == READ_FD) |
|
168 rv = os2_select(socks, 1, 0, 0, lTimeout); |
|
169 else |
|
170 rv = os2_select(socks, 0, 1, 0, lTimeout); |
|
171 #endif |
|
172 /* |
|
173 * we don't consider EINTR a real error |
|
174 */ |
|
175 if (rv == -1 && (syserror = sock_errno()) != EINTR) { |
|
176 _PR_MD_MAP_SELECT_ERROR(syserror); |
|
177 break; |
|
178 } |
|
179 if (_PR_PENDING_INTERRUPT(me)) { |
|
180 me->flags &= ~_PR_INTERRUPT; |
|
181 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); |
|
182 rv = -1; |
|
183 break; |
|
184 } |
|
185 /* |
|
186 * We loop again if select timed out or got interrupted |
|
187 * by a signal, and the timeout deadline has not passed yet. |
|
188 */ |
|
189 if (rv == 0 || (rv == -1 && syserror == EINTR)) { |
|
190 /* |
|
191 * If select timed out, we know how much time |
|
192 * we spent in blocking, so we can avoid a |
|
193 * PR_IntervalNow() call. |
|
194 */ |
|
195 if (rv == 0) { |
|
196 if (wait_for_remaining) { |
|
197 now += remaining; |
|
198 } else { |
|
199 #ifdef BSD_SELECT |
|
200 now += PR_SecondsToInterval(tv.tv_sec) |
|
201 + PR_MicrosecondsToInterval(tv.tv_usec); |
|
202 #else |
|
203 now += PR_MillisecondsToInterval(lTimeout); |
|
204 #endif |
|
205 } |
|
206 } else { |
|
207 now = PR_IntervalNow(); |
|
208 } |
|
209 elapsed = (PRIntervalTime) (now - epoch); |
|
210 if (elapsed >= timeout) { |
|
211 PR_SetError(PR_IO_TIMEOUT_ERROR, 0); |
|
212 rv = -1; |
|
213 break; |
|
214 } else { |
|
215 remaining = timeout - elapsed; |
|
216 } |
|
217 } |
|
218 } while (rv == 0 || (rv == -1 && syserror == EINTR)); |
|
219 break; |
|
220 } |
|
221 return(rv); |
|
222 } |
|
223 |
|
224 PRInt32 |
|
225 _MD_Accept(PRFileDesc *fd, PRNetAddr *addr, |
|
226 PRUint32 *addrlen, PRIntervalTime timeout) |
|
227 { |
|
228 PRInt32 osfd = fd->secret->md.osfd; |
|
229 PRInt32 rv, err; |
|
230 PRThread *me = _PR_MD_CURRENT_THREAD(); |
|
231 |
|
232 while ((rv = accept(osfd, (struct sockaddr*) addr, (int*)addrlen)) == -1) |
|
233 { |
|
234 err = sock_errno(); |
|
235 if ((err == EWOULDBLOCK) || (err == ECONNABORTED)) |
|
236 { |
|
237 if (fd->secret->nonblocking) { |
|
238 break; |
|
239 } |
|
240 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) |
|
241 goto done; |
|
242 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ |
|
243 continue; |
|
244 } else { |
|
245 break; |
|
246 } |
|
247 } |
|
248 if (rv < 0) { |
|
249 _PR_MD_MAP_ACCEPT_ERROR(err); |
|
250 } |
|
251 done: |
|
252 return(rv); |
|
253 } |
|
254 |
|
255 PRInt32 |
|
256 _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, |
|
257 PRIntervalTime timeout) |
|
258 { |
|
259 PRInt32 rv, err; |
|
260 PRThread *me = _PR_MD_CURRENT_THREAD(); |
|
261 PRInt32 osfd = fd->secret->md.osfd; |
|
262 PRNetAddr addrCopy = *addr; /* Work around a bug in OS/2 where connect |
|
263 * modifies the sockaddr structure. |
|
264 * See Bugzilla bug 100776. */ |
|
265 |
|
266 /* |
|
267 * We initiate the connection setup by making a nonblocking connect() |
|
268 * call. If the connect() call fails, there are two cases we handle |
|
269 * specially: |
|
270 * 1. The connect() call was interrupted by a signal. In this case |
|
271 * we simply retry connect(). |
|
272 * 2. The NSPR socket is nonblocking and connect() fails with |
|
273 * EINPROGRESS. We first wait until the socket becomes writable. |
|
274 * Then we try to find out whether the connection setup succeeded |
|
275 * or failed. |
|
276 */ |
|
277 |
|
278 retry: |
|
279 if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) |
|
280 { |
|
281 err = sock_errno(); |
|
282 |
|
283 if (err == EINTR) { |
|
284 if (_PR_PENDING_INTERRUPT(me)) { |
|
285 me->flags &= ~_PR_INTERRUPT; |
|
286 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); |
|
287 return -1; |
|
288 } |
|
289 goto retry; |
|
290 } |
|
291 |
|
292 if (!fd->secret->nonblocking && (err == EINPROGRESS)) |
|
293 { |
|
294 /* |
|
295 * socket_io_wait() may return -1 or 1. |
|
296 */ |
|
297 |
|
298 rv = socket_io_wait(osfd, WRITE_FD, timeout); |
|
299 if (rv == -1) { |
|
300 return -1; |
|
301 } |
|
302 |
|
303 PR_ASSERT(rv == 1); |
|
304 if (_PR_PENDING_INTERRUPT(me)) { |
|
305 me->flags &= ~_PR_INTERRUPT; |
|
306 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); |
|
307 return -1; |
|
308 } |
|
309 err = _MD_os2_get_nonblocking_connect_error(osfd); |
|
310 if (err != 0) { |
|
311 _PR_MD_MAP_CONNECT_ERROR(err); |
|
312 return -1; |
|
313 } |
|
314 return 0; |
|
315 } |
|
316 |
|
317 _PR_MD_MAP_CONNECT_ERROR(err); |
|
318 } |
|
319 |
|
320 return rv; |
|
321 } /* _MD_connect */ |
|
322 |
|
323 PRInt32 |
|
324 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) |
|
325 { |
|
326 PRInt32 rv, err; |
|
327 rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen); |
|
328 if (rv < 0) { |
|
329 err = sock_errno(); |
|
330 _PR_MD_MAP_BIND_ERROR(err); |
|
331 } |
|
332 return(rv); |
|
333 } |
|
334 |
|
335 |
|
336 PRInt32 |
|
337 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog) |
|
338 { |
|
339 PRInt32 rv, err; |
|
340 rv = listen(fd->secret->md.osfd, backlog); |
|
341 if (rv < 0) { |
|
342 err = sock_errno(); |
|
343 _PR_MD_MAP_DEFAULT_ERROR(err); |
|
344 } |
|
345 return(rv); |
|
346 } |
|
347 |
|
348 |
|
349 PRInt32 |
|
350 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, |
|
351 PRIntervalTime timeout) |
|
352 { |
|
353 PRInt32 osfd = fd->secret->md.osfd; |
|
354 PRInt32 rv, err; |
|
355 PRThread *me = _PR_MD_CURRENT_THREAD(); |
|
356 |
|
357 while ((rv = recv(osfd,buf,amount,flags)) == -1) |
|
358 { |
|
359 err = sock_errno(); |
|
360 if ((err == EWOULDBLOCK)) { |
|
361 if (fd->secret->nonblocking) { |
|
362 break; |
|
363 } |
|
364 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) |
|
365 goto done; |
|
366 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ |
|
367 continue; |
|
368 } else { |
|
369 break; |
|
370 } |
|
371 } |
|
372 if (rv < 0) { |
|
373 _PR_MD_MAP_RECV_ERROR(err); |
|
374 } |
|
375 done: |
|
376 return(rv); |
|
377 } |
|
378 |
|
379 PRInt32 |
|
380 _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, |
|
381 PRIntervalTime timeout) |
|
382 { |
|
383 PRInt32 osfd = fd->secret->md.osfd; |
|
384 PRInt32 rv, err; |
|
385 PRThread *me = _PR_MD_CURRENT_THREAD(); |
|
386 |
|
387 while ((rv = send(osfd,buf,amount,flags)) == -1) |
|
388 { |
|
389 err = sock_errno(); |
|
390 if ((err == EWOULDBLOCK)) { |
|
391 if (fd->secret->nonblocking) { |
|
392 break; |
|
393 } |
|
394 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0) |
|
395 goto done; |
|
396 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ |
|
397 continue; |
|
398 } else { |
|
399 break; |
|
400 } |
|
401 } |
|
402 |
|
403 /* |
|
404 * optimization; if bytes sent is less than "amount" call |
|
405 * select before returning. This is because it is likely that |
|
406 * the next send() call will return EWOULDBLOCK. |
|
407 */ |
|
408 if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) |
|
409 && (timeout != PR_INTERVAL_NO_WAIT)) |
|
410 { |
|
411 if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) { |
|
412 rv = -1; |
|
413 goto done; |
|
414 } |
|
415 } |
|
416 if (rv < 0) { |
|
417 _PR_MD_MAP_SEND_ERROR(err); |
|
418 } |
|
419 done: |
|
420 return(rv); |
|
421 } |
|
422 |
|
423 PRInt32 |
|
424 _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, |
|
425 const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) |
|
426 { |
|
427 PRInt32 osfd = fd->secret->md.osfd; |
|
428 PRInt32 rv, err; |
|
429 PRThread *me = _PR_MD_CURRENT_THREAD(); |
|
430 while ((rv = sendto(osfd, buf, amount, flags, |
|
431 (struct sockaddr *) addr, addrlen)) == -1) |
|
432 { |
|
433 err = sock_errno(); |
|
434 if ((err == EWOULDBLOCK)) |
|
435 { |
|
436 if (fd->secret->nonblocking) { |
|
437 break; |
|
438 } |
|
439 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0) |
|
440 goto done; |
|
441 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ |
|
442 continue; |
|
443 } else { |
|
444 break; |
|
445 } |
|
446 } |
|
447 if (rv < 0) { |
|
448 _PR_MD_MAP_SENDTO_ERROR(err); |
|
449 } |
|
450 done: |
|
451 return(rv); |
|
452 } |
|
453 |
|
454 PRInt32 |
|
455 _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, |
|
456 PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) |
|
457 { |
|
458 PRInt32 osfd = fd->secret->md.osfd; |
|
459 PRInt32 rv, err; |
|
460 PRThread *me = _PR_MD_CURRENT_THREAD(); |
|
461 |
|
462 while( (*addrlen = PR_NETADDR_SIZE(addr)), |
|
463 ((rv = recvfrom(osfd, buf, amount, flags, |
|
464 (struct sockaddr *) addr, (int *)addrlen)) == -1)) |
|
465 { |
|
466 err = sock_errno(); |
|
467 if ((err == EWOULDBLOCK)) { |
|
468 if (fd->secret->nonblocking) { |
|
469 break; |
|
470 } |
|
471 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) |
|
472 goto done; |
|
473 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ |
|
474 continue; |
|
475 } else { |
|
476 break; |
|
477 } |
|
478 } |
|
479 if (rv < 0) { |
|
480 _PR_MD_MAP_RECVFROM_ERROR(err); |
|
481 } |
|
482 done: |
|
483 return(rv); |
|
484 } |
|
485 |
|
486 PRInt32 |
|
487 _PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, |
|
488 PRIntervalTime timeout) |
|
489 { |
|
490 PRInt32 rv, err; |
|
491 PRThread *me = _PR_MD_CURRENT_THREAD(); |
|
492 PRInt32 index, amount = 0; |
|
493 PRInt32 osfd = fd->secret->md.osfd; |
|
494 struct iovec osiov[PR_MAX_IOVECTOR_SIZE]; |
|
495 |
|
496 /* Ensured by PR_Writev */ |
|
497 PR_ASSERT(iov_size <= PR_MAX_IOVECTOR_SIZE); |
|
498 |
|
499 /* |
|
500 * We can't pass iov to so_writev because PRIOVec and struct iovec |
|
501 * may not be binary compatible. Make osiov a copy of iov and |
|
502 * pass osiov to so_writev . |
|
503 */ |
|
504 for (index = 0; index < iov_size; index++) { |
|
505 osiov[index].iov_base = iov[index].iov_base; |
|
506 osiov[index].iov_len = iov[index].iov_len; |
|
507 } |
|
508 |
|
509 /* |
|
510 * Calculate the total number of bytes to be sent; needed for |
|
511 * optimization later. |
|
512 * We could avoid this if this number was passed in; but it is |
|
513 * probably not a big deal because iov_size is usually small (less than |
|
514 * 3) |
|
515 */ |
|
516 if (!fd->secret->nonblocking) { |
|
517 for (index=0; index<iov_size; index++) { |
|
518 amount += iov[index].iov_len; |
|
519 } |
|
520 } |
|
521 |
|
522 while ((rv = so_writev(osfd, osiov, iov_size)) == -1) { |
|
523 err = sock_errno(); |
|
524 if ((err == EWOULDBLOCK)) { |
|
525 if (fd->secret->nonblocking) { |
|
526 break; |
|
527 } |
|
528 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0) |
|
529 goto done; |
|
530 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ |
|
531 continue; |
|
532 } else { |
|
533 break; |
|
534 } |
|
535 } |
|
536 |
|
537 /* |
|
538 * optimization; if bytes sent is less than "amount" call |
|
539 * select before returning. This is because it is likely that |
|
540 * the next writev() call will return EWOULDBLOCK. |
|
541 */ |
|
542 if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) |
|
543 && (timeout != PR_INTERVAL_NO_WAIT)) { |
|
544 if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { |
|
545 rv = -1; |
|
546 goto done; |
|
547 } |
|
548 } |
|
549 if (rv < 0) { |
|
550 _PR_MD_MAP_WRITEV_ERROR(err); |
|
551 } |
|
552 done: |
|
553 return(rv); |
|
554 } |
|
555 |
|
556 PRInt32 |
|
557 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how) |
|
558 { |
|
559 PRInt32 rv; |
|
560 |
|
561 rv = shutdown(fd->secret->md.osfd, how); |
|
562 if (rv < 0) |
|
563 _PR_MD_MAP_SHUTDOWN_ERROR(sock_errno()); |
|
564 return rv; |
|
565 } |
|
566 |
|
567 PRInt32 |
|
568 _PR_MD_SOCKETPAIR(int af, int type, int flags, PRInt32 *osfd) |
|
569 { |
|
570 PRInt32 rv, err; |
|
571 |
|
572 rv = socketpair(af, type, flags, osfd); |
|
573 if (rv < 0) { |
|
574 err = _MD_ERRNO(); |
|
575 _PR_MD_MAP_SOCKETPAIR_ERROR(err); |
|
576 } |
|
577 return rv; |
|
578 } |
|
579 |
|
580 PRStatus |
|
581 _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) |
|
582 { |
|
583 PRInt32 rv, err; |
|
584 |
|
585 rv = getsockname(fd->secret->md.osfd, |
|
586 (struct sockaddr *) addr, (int *)addrlen); |
|
587 if (rv < 0) { |
|
588 err = sock_errno(); |
|
589 _PR_MD_MAP_GETSOCKNAME_ERROR(err); |
|
590 } |
|
591 return rv==0?PR_SUCCESS:PR_FAILURE; |
|
592 } |
|
593 |
|
594 PRStatus |
|
595 _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) |
|
596 { |
|
597 PRInt32 rv, err; |
|
598 |
|
599 rv = getpeername(fd->secret->md.osfd, |
|
600 (struct sockaddr *) addr, (int *)addrlen); |
|
601 if (rv < 0) { |
|
602 err = sock_errno(); |
|
603 _PR_MD_MAP_GETPEERNAME_ERROR(err); |
|
604 } |
|
605 return rv==0?PR_SUCCESS:PR_FAILURE; |
|
606 } |
|
607 |
|
608 PRStatus |
|
609 _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, |
|
610 char* optval, PRInt32* optlen) |
|
611 { |
|
612 PRInt32 rv, err; |
|
613 |
|
614 rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (int *)optlen); |
|
615 if (rv < 0) { |
|
616 err = sock_errno(); |
|
617 _PR_MD_MAP_GETSOCKOPT_ERROR(err); |
|
618 } |
|
619 return rv==0?PR_SUCCESS:PR_FAILURE; |
|
620 } |
|
621 |
|
622 PRStatus |
|
623 _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, |
|
624 const char* optval, PRInt32 optlen) |
|
625 { |
|
626 PRInt32 rv, err; |
|
627 |
|
628 rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen); |
|
629 if (rv < 0) { |
|
630 err = sock_errno(); |
|
631 _PR_MD_MAP_SETSOCKOPT_ERROR(err); |
|
632 } |
|
633 return rv==0?PR_SUCCESS:PR_FAILURE; |
|
634 } |
|
635 |
|
636 void |
|
637 _MD_MakeNonblock(PRFileDesc *fd) |
|
638 { |
|
639 PRInt32 osfd = fd->secret->md.osfd; |
|
640 PRInt32 err; |
|
641 PRUint32 one = 1; |
|
642 |
|
643 if (osfd <= 2) { |
|
644 /* Don't mess around with stdin, stdout or stderr */ |
|
645 return; |
|
646 } |
|
647 |
|
648 err = so_ioctl( osfd, FIONBIO, (char *) &one, sizeof(one)); |
|
649 if ( err != 0 ) |
|
650 { |
|
651 err = sock_errno(); |
|
652 _PR_MD_MAP_SOCKET_ERROR(err); |
|
653 } |
|
654 } |