home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / md / os2 / os2sock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  20.4 KB  |  771 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /* OS/2 Sockets module
  20.  *
  21.  */
  22.  
  23. /*Note from DSR111297 - it should be noted that there are two flavors of select() on OS/2    */
  24. /*There is standard BSD (which is kind of slow) and a new flavor of select() that takes      */
  25. /*an integer list of sockets, the number of read sockets, write sockets, except sockets, and */
  26. /*a millisecond count for timeout. In the interest of performance I have choosen the OS/2    */
  27. /*specific version of select(). See OS/2 TCP/IP Programmer's Toolkit for more info.          */ 
  28.  
  29. #include "primpl.h"
  30.  
  31. void
  32. _PR_MD_INIT_IO()
  33. {
  34.     sock_init();
  35. }
  36.  
  37. /* --- SOCKET IO --------------------------------------------------------- */
  38.  
  39.  
  40. PRInt32
  41. _PR_MD_SOCKET(int af, int type, int flags)
  42. {
  43.     int sock;
  44.     PRUint32  one = 1;
  45.     PRInt32   rv;
  46.     PRInt32   err;
  47.  
  48.     sock = socket(af, type, flags);
  49.  
  50.     if (sock == -1 ) 
  51.     {
  52.         int rv = sock_errno();
  53.         soclose(sock);
  54.         _PR_MD_MAP_SOCKET_ERROR(rv);
  55.         return (PRInt32) -1;
  56.     }
  57.  
  58.     /*
  59.     ** Make the socket Non-Blocking
  60.     */
  61.     rv = ioctl( sock, FIONBIO, (char *) &one, sizeof(one));
  62.     if ( rv != 0 )
  63.     {
  64.         err = sock_errno();
  65.         return -1;
  66.     }
  67.  
  68.     return (PRInt32)sock;
  69. }
  70.  
  71. /*
  72. ** _MD_CloseSocket() -- Close a socket
  73. **
  74. */
  75. PRInt32
  76. _MD_CloseSocket(PRInt32 osfd)
  77. {
  78.     PRInt32 rv = -1;
  79.  
  80.     rv = soclose((int) osfd );
  81.     if (rv < 0)
  82.         _PR_MD_MAP_SOCKET_ERROR(sock_errno());
  83.  
  84.     return rv;
  85. }
  86.  
  87. PRInt32
  88. _MD_SocketAvailable(PRFileDesc *fd)
  89. {
  90.     PRInt32 result;
  91.  
  92.     if (ioctl(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) {
  93.         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, sock_errno());
  94.         return -1;
  95.     }
  96.     return result;
  97. }
  98.  
  99. PRInt32
  100. _MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
  101.               PRIntervalTime timeout )
  102. {
  103.     PRInt32 osfd = fd->secret->md.osfd;
  104.     PRInt32 rv, err;
  105. #ifdef BSD_SELECT
  106.     fd_set rd;
  107.     struct timeval tv, *tvp;
  108.  
  109.     FD_ZERO(&rd);
  110.     FD_SET(osfd, &rd);
  111. #else
  112.     int socks[1];
  113.     socks[0] = osfd; 
  114. #endif
  115.     if (timeout == PR_INTERVAL_NO_TIMEOUT) 
  116.     {
  117.         while ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1) 
  118.         {
  119.             if (((err = sock_errno()) == EWOULDBLOCK) 
  120.                 && (!fd->secret->nonblocking))
  121.             {
  122. #ifdef BSD_SELECT
  123.                 if ((rv = select(osfd + 1, &rd, NULL, NULL,NULL)) == -1) {
  124. #else
  125.                 if ((rv = select(socks, 1, 0, 0, -1)) == -1) {
  126. #endif
  127.                     _PR_MD_MAP_SELECT_ERROR(sock_errno());
  128.                     break;
  129.             } 
  130.             } 
  131.             else {
  132.                 _PR_MD_MAP_ACCEPT_ERROR(err);
  133.                 break;
  134.         }
  135.         }
  136.         return(rv);
  137.     } 
  138.     else if (timeout == PR_INTERVAL_NO_WAIT) 
  139.     {
  140.         if ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1)
  141.         {
  142.             if (((err = sock_errno()) == EWOULDBLOCK) 
  143.                 && (!fd->secret->nonblocking))
  144.             {
  145.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  146.             }
  147.             else
  148.             {
  149.                 _PR_MD_MAP_ACCEPT_ERROR(err);
  150.             }
  151.         }
  152.             return(rv);
  153.     } 
  154.     else 
  155.     {
  156. retry:
  157.         if ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1) 
  158.         {
  159.             if (((err = sock_errno()) == EWOULDBLOCK) 
  160.                 && (!fd->secret->nonblocking))
  161.             {
  162. #ifdef BSD_SELECT
  163.                 tv.tv_sec = PR_IntervalToSeconds(timeout);
  164.                 tv.tv_usec = PR_IntervalToMicroseconds(
  165.                     timeout - PR_SecondsToInterval(tv.tv_sec));
  166.                 tvp = &tv;
  167.                 rv = select(osfd + 1, &rd, NULL, NULL, tvp);
  168. #else
  169.                 long lTimeout = PR_IntervalToMilliseconds(timeout); 
  170.                 rv = select(socks, 1, 0, 0, lTimeout);
  171. #endif
  172.                 if (rv > 0) {
  173.                     goto retry;
  174.                 } 
  175.                 else if (rv == 0) 
  176.                 {
  177.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  178.                     rv = -1;
  179.                 } else {
  180.                     _PR_MD_MAP_SELECT_ERROR(sock_errno());
  181.                 }
  182.             } else {
  183.                 _PR_MD_MAP_ACCEPT_ERROR(err);
  184.             }
  185.         }
  186.     }
  187.     return(rv);
  188. } /* end _MD_Accept() */
  189.  
  190.  
  191.  
  192. PRInt32
  193. _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, 
  194.                PRIntervalTime timeout)
  195. {
  196.     PRInt32 osfd = fd->secret->md.osfd;
  197.     PRInt32 rv;
  198.     int err, len;
  199. #ifdef BSD_SELECT
  200.     fd_set wd, ex;
  201.     struct timeval tv, *tvp;
  202. #else
  203.     int socks[1]; 
  204.     long lTimeout = -1;
  205. #endif
  206.  
  207.     if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1) 
  208.     {
  209.         err = sock_errno();
  210.         if ((!fd->secret->nonblocking) && (err == EINPROGRESS) || (err == EWOULDBLOCK))
  211.         {
  212. #ifdef BSD_SELECT
  213.            if (timeout == PR_INTERVAL_NO_TIMEOUT)
  214.                tvp = NULL;
  215.             else 
  216.             {
  217.                 tv.tv_sec = PR_IntervalToSeconds(timeout);
  218.                 tv.tv_usec = PR_IntervalToMicroseconds(
  219.                 timeout - PR_SecondsToInterval(tv.tv_sec));
  220.                 tvp = &tv;
  221.             }
  222.  
  223.             FD_ZERO(&wd);
  224.             FD_SET(osfd, &wd);
  225.             FD_ZERO(&ex);
  226.             FD_SET(osfd, &ex);
  227.             rv = select(osfd + 1, NULL, &wd, &ex, tvp);
  228. #else
  229.             if (timeout == PR_INTERVAL_NO_TIMEOUT)
  230.                 lTimeout = -1;
  231.             else 
  232.             {
  233.                 lTimeout = PR_IntervalToMilliseconds(timeout);  
  234.             }
  235.         
  236.             socks[0] = osfd; 
  237.             rv = select(socks, 0, 1, 1, lTimeout);
  238. #endif
  239.             if (rv > 0) 
  240.             {
  241. #ifdef BSD_SELECT
  242.                if (FD_ISSET(osfd, &ex))
  243.                {
  244.                    DosSleep(0);
  245.                    len = sizeof(err);
  246.                    if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
  247.                            (char *) &err, &len) < 0)
  248.                    {  
  249.                        _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
  250.                        return -1;
  251.                    }
  252.                    if (err != 0)
  253.                        _PR_MD_MAP_CONNECT_ERROR(err);
  254.                    else
  255.                        PR_SetError(PR_UNKNOWN_ERROR, 0);
  256.                    return -1;
  257.                }
  258.                if (FD_ISSET(osfd, &wd))
  259.                {
  260.                    /* it's connected */
  261.                    return 0;
  262.                }
  263. #else
  264.                if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
  265.                        (char *) &err, &len) < 0)
  266.                {  
  267.                    _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
  268.                    return -1;
  269.                }
  270.                else
  271.                   return 0; /* It's connected ! */
  272. #endif
  273.             } 
  274.             else if (rv == 0) 
  275.             {
  276.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  277.                 return(-1);
  278.             } else if (rv < 0) 
  279.             {
  280.                 _PR_MD_MAP_SELECT_ERROR(sock_errno());
  281.                 return(-1);
  282.             }
  283.         } 
  284.         _PR_MD_MAP_CONNECT_ERROR(err);
  285.     }
  286.     return rv;
  287. }
  288.  
  289.  
  290. PRInt32
  291. _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
  292. {
  293.     PRInt32 rv;
  294.     int one = 1;
  295.  
  296.     rv = bind(fd->secret->md.osfd, (struct sockaddr*) &(addr->inet), addrlen);
  297.  
  298.     if (rv == -1)  {
  299.         _PR_MD_MAP_BIND_ERROR(sock_errno());
  300.         return -1;
  301.     }
  302.  
  303.     return 0;
  304. }
  305.  
  306.  
  307. PRInt32
  308. _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, 
  309.             PRIntervalTime timeout)
  310. {
  311.     PRInt32 osfd = fd->secret->md.osfd;
  312.     PRInt32 rv, err;
  313. #ifdef BSD_SELECT
  314.     struct timeval tv, *tvp;
  315.     fd_set rd;
  316. #else
  317.     int socks[1]; 
  318.     long lTimeout = -1; 
  319. #endif
  320.  
  321.     while ((rv = recv( osfd, buf, amount, 0)) == -1) 
  322.     {
  323.         if (((err = sock_errno()) == EWOULDBLOCK) 
  324.             && (!fd->secret->nonblocking))
  325.         {
  326. #ifdef BSD_SELECT
  327.            FD_ZERO(&rd);
  328.            FD_SET(osfd, &rd);
  329.            if (timeout == PR_INTERVAL_NO_TIMEOUT) 
  330.            {
  331.                tvp = NULL;
  332.            } 
  333.            else 
  334.            {
  335.                tv.tv_sec = PR_IntervalToSeconds(timeout);
  336.                tv.tv_usec = PR_IntervalToMicroseconds(
  337.                timeout - PR_SecondsToInterval(tv.tv_sec));
  338.                tvp = &tv;
  339.            }
  340.            if ((rv = select(osfd + 1, &rd, NULL, NULL, tvp)) == -1) 
  341. #else
  342.             socks[0] = osfd; 
  343.             if (timeout == PR_INTERVAL_NO_TIMEOUT) 
  344.             {
  345.                 lTimeout = -1; 
  346.             } 
  347.             else 
  348.             {
  349.                 lTimeout = PR_IntervalToMilliseconds(timeout); 
  350.             }
  351.             if ((rv = select(socks, 1, 0, 0, lTimeout)) == -1) 
  352. #endif
  353.             {
  354.                 _PR_MD_MAP_SELECT_ERROR(sock_errno());
  355.                 return -1;
  356.             } 
  357.             else if (rv == 0) 
  358.             {
  359.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  360.                 rv = -1;
  361.                 break;
  362.             }
  363.         } 
  364.         else 
  365.         {
  366.             _PR_MD_MAP_RECV_ERROR(err);
  367.             break;
  368.         }
  369.     } /* end while() */
  370.     return(rv);
  371. }
  372.  
  373. PRInt32
  374. _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
  375.             PRIntervalTime timeout)
  376. {
  377.     PRInt32 osfd = fd->secret->md.osfd;
  378.     PRInt32 rv, err;
  379. #ifdef BSD_SELECT
  380.     struct timeval tv, *tvp;
  381.     fd_set wd;
  382. #else
  383.     int socks[1]; 
  384.     long lTimeout = -1; 
  385. #endif
  386.     PRInt32 bytesSent = 0;
  387.  
  388.     while(bytesSent < amount ) 
  389.     {
  390.         while ((rv = send( osfd, (char *) buf, amount, 0 )) == -1) 
  391.         {
  392.             if (((err = sock_errno()) == EWOULDBLOCK) 
  393.                 && (!fd->secret->nonblocking))
  394.             {
  395. #ifdef BSD_SELECT
  396.                 if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  397.                 {
  398.                     tvp = NULL;
  399.                 } 
  400.                 else 
  401.                 {
  402.                     tv.tv_sec = PR_IntervalToSeconds(timeout);
  403.                     tv.tv_usec = PR_IntervalToMicroseconds(
  404.                         timeout - PR_SecondsToInterval(tv.tv_sec));
  405.                     tvp = &tv;
  406.                 }
  407.                 FD_ZERO(&wd);
  408.                 FD_SET(osfd, &wd);
  409.                 if ((rv = select( osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
  410. #else
  411.                 if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  412.                 {
  413.                     lTimeout = -1; 
  414.                 } 
  415.                 else 
  416.                 {
  417.                     lTimeout = PR_IntervalToMilliseconds(timeout); 
  418.                 }
  419.                 socks[0] = osfd; 
  420.                 if ((rv = select( socks, 0, 1, 0, lTimeout)) == -1) {
  421. #endif
  422.                     _PR_MD_MAP_SELECT_ERROR(sock_errno());
  423.                     break;
  424.                 }
  425.                 if (rv == 0) 
  426.                 {
  427.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  428.                         return -1;
  429.                 }
  430.             } 
  431.             else {
  432.                 _PR_MD_MAP_SEND_ERROR(err);
  433.                 return -1;
  434.         }
  435.         }
  436.         bytesSent += rv;
  437.         if (fd->secret->nonblocking)
  438.         {
  439.             break;
  440.         }
  441.         if ((rv >= 0) && (bytesSent < amount )) 
  442.         {
  443. #ifdef BSD_SELECT
  444.            if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  445.            {
  446.                tvp = NULL;
  447.            } 
  448.            else 
  449.            {
  450.                tv.tv_sec = PR_IntervalToSeconds(timeout);
  451.                tv.tv_usec = PR_IntervalToMicroseconds(
  452.                    timeout - PR_SecondsToInterval(tv.tv_sec));
  453.                tvp = &tv;
  454.            }
  455.            FD_ZERO(&wd);
  456.            FD_SET(osfd, &wd);
  457.            if ((rv = select(osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
  458. #else
  459.             if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  460.             {
  461.                 lTimeout = -1; 
  462.             } 
  463.             else 
  464.             {
  465.                 lTimeout = PR_IntervalToMilliseconds(timeout); 
  466.             }
  467.             socks[0] = osfd; 
  468.             if ((rv = select(socks, 0, 1, 0,lTimeout)) == -1) {
  469. #endif
  470.                 _PR_MD_MAP_SELECT_ERROR(sock_errno());
  471.                 break;
  472.             }
  473.             if (rv == 0) 
  474.             {
  475.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  476.                     return -1;
  477.             }
  478.         }
  479.     }
  480.     return bytesSent;
  481. }
  482.  
  483. PRInt32
  484. _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
  485.               const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
  486. {
  487.     PRInt32 osfd = fd->secret->md.osfd;
  488.     PRInt32 rv, err;
  489.     PRInt32 bytesSent = 0;
  490. #ifdef BSD_SELECT
  491.     struct timeval tv, *tvp;
  492.     fd_set wd;
  493. #else
  494.     int socks[1];
  495.     long lTimeout = -1; 
  496. #endif
  497.  
  498.     while(bytesSent < amount) 
  499.     {
  500.         while ((rv = sendto( osfd, (char *) buf, amount, 0, (struct sockaddr *) addr,
  501.                 addrlen)) == -1) 
  502.         {
  503.             if (((err = sock_errno()) == EWOULDBLOCK) 
  504.                 && (!fd->secret->nonblocking))
  505.             {
  506. #ifdef BSD_SELECT
  507.                if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  508.                {
  509.                    tvp = NULL;
  510.                } 
  511.                else 
  512.                {
  513.                    tv.tv_sec = PR_IntervalToSeconds(timeout);
  514.                    tv.tv_usec = PR_IntervalToMicroseconds(
  515.                        timeout - PR_SecondsToInterval(tv.tv_sec));
  516.                    tvp = &tv;
  517.                }
  518.                FD_ZERO(&wd);
  519.                FD_SET(osfd, &wd);
  520.                if ((rv = select(osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
  521. #else
  522.                 if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  523.                 {
  524.                     lTimeout = -1; 
  525.                 } 
  526.                 else 
  527.                 {
  528.                     lTimeout = PR_IntervalToMilliseconds(timeout);
  529.                 }
  530.                 socks[0] = osfd; 
  531.                 if ((rv = select(socks, 0, 1, 0, lTimeout)) == -1) {
  532. #endif
  533.                     _PR_MD_MAP_SELECT_ERROR(sock_errno());
  534.                     break;
  535.                 }
  536.                 if (rv == 0) 
  537.                 {
  538.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  539.                         return -1;
  540.                 }
  541.             } 
  542.             else {
  543.                 _PR_MD_MAP_SENDTO_ERROR(err);
  544.                 return -1;
  545.         }
  546.         }
  547.         bytesSent += rv;
  548.         if (fd->secret->nonblocking)
  549.         {
  550.             break;
  551.         }
  552.         if ((rv >= 0) && (bytesSent < amount )) 
  553.         {
  554. #ifdef BSD_SELECT
  555.            if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  556.            {
  557.                tvp = NULL;
  558.            } 
  559.            else 
  560.            {
  561.                tv.tv_sec = PR_IntervalToSeconds(timeout);
  562.                tv.tv_usec = PR_IntervalToMicroseconds(
  563.                    timeout - PR_SecondsToInterval(tv.tv_sec));
  564.                tvp = &tv;
  565.            }
  566.            FD_ZERO(&wd);
  567.            FD_SET(osfd, &wd);
  568.            if ((rv = select( osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
  569. #else
  570.             if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  571.             {
  572.                 lTimeout = -1; 
  573.             } 
  574.             else 
  575.             {
  576.                 lTimeout = PR_IntervalToMilliseconds(timeout);  
  577.             }
  578.             socks[0] = osfd; 
  579.             if ((rv = select( socks, 0, 1, 0, lTimeout)) == -1) {
  580. #endif
  581.                 _PR_MD_MAP_SELECT_ERROR(sock_errno());
  582.                 break;
  583.             }
  584.             if (rv == 0) 
  585.             {
  586.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  587.                     return -1;
  588.             }
  589.         }
  590.     }
  591.     return bytesSent;
  592. }
  593.  
  594. PRInt32
  595. _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
  596.                 PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
  597. {
  598.     PRInt32 osfd = fd->secret->md.osfd;
  599.     PRInt32 rv, err;
  600.     PRUint32 addrlen_temp = *addrlen;
  601. #ifdef BSD_SELECT
  602.     struct timeval tv, *tvp;
  603.     fd_set rd;
  604. #else
  605.     int socks[1]; 
  606.     long lTimeout = -1; 
  607. #endif
  608.  
  609.     while ((rv = recvfrom( osfd, (char *) buf, amount, 0, (struct sockaddr *) addr,
  610.             (int *) addrlen)) == -1) 
  611.     {
  612.         if (((err = sock_errno()) == EWOULDBLOCK) 
  613.             && (!fd->secret->nonblocking))
  614.         {
  615. #ifdef BSD_SELECT
  616.            if (timeout == PR_INTERVAL_NO_TIMEOUT) 
  617.            {
  618.                tvp = NULL;
  619.            } 
  620.            else 
  621.            {
  622.                tv.tv_sec = PR_IntervalToSeconds(timeout);
  623.                tv.tv_usec = PR_IntervalToMicroseconds(
  624.                timeout - PR_SecondsToInterval(tv.tv_sec));
  625.                tvp = &tv;
  626.            }
  627.            FD_ZERO(&rd);
  628.            FD_SET(osfd, &rd);
  629.            if ((rv = select(osfd + 1, &rd, NULL, NULL, tvp)) == -1) 
  630. #else
  631.             if (timeout == PR_INTERVAL_NO_TIMEOUT) 
  632.             {
  633.                 lTimeout = -1;
  634.             } 
  635.             else 
  636.             {
  637.                 lTimeout = PR_IntervalToMilliseconds(timeout);  
  638.             }
  639.             socks[0] = osfd; 
  640.             if ((rv = select(socks, 1, 0, 0, lTimeout)) == -1) 
  641. #endif
  642.             {
  643.                 _PR_MD_MAP_SELECT_ERROR(sock_errno());
  644.                 return -1;
  645.             } else if (rv == 0) 
  646.             {
  647.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  648.                 rv = -1;
  649.                 break;
  650.             }
  651.  
  652.             /* recvfrom blows this value away if it fails first time */
  653.             *addrlen = addrlen_temp;
  654.         } 
  655.         else 
  656.         {
  657.             _PR_MD_MAP_RECVFROM_ERROR(err);
  658.             break;
  659.         }
  660.     }
  661.     return(rv);
  662. }
  663.  
  664. PRInt32
  665. _PR_MD_WRITEV(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
  666. {
  667.     int index;
  668.     int sent = 0;
  669.     int rv;
  670.  
  671.     for (index=0; index < iov_size; index++) 
  672.     {
  673.         rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
  674.         if (rv > 0) 
  675.             sent += rv;
  676.         if ( rv != iov[index].iov_len ) 
  677.         {
  678.             if (rv < 0)
  679.             {
  680.                 if (fd->secret->nonblocking
  681.                     && (PR_GetError() == PR_WOULD_BLOCK_ERROR)
  682.                     && (sent > 0))
  683.                 {
  684.                     return sent;
  685.                 }
  686.                 else
  687.                 {
  688.                     return -1;
  689.                 }
  690.             }
  691.             /* Only a nonblocking socket can have partial sends */
  692.             PR_ASSERT(fd->secret->nonblocking);
  693.             return sent;
  694.         }
  695.     }
  696.     return sent;
  697. }
  698.  
  699. PRInt32
  700. _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
  701. {
  702. PRInt32 rv;
  703.  
  704.     rv = shutdown(fd->secret->md.osfd, how);
  705.     if (rv < 0)
  706.         _PR_MD_MAP_SHUTDOWN_ERROR(sock_errno());
  707.     return rv;
  708. }
  709.  
  710. PRStatus
  711. _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
  712. {
  713.     PRInt32 rv;
  714.  
  715.     rv = getsockname((int)fd->secret->md.osfd, (struct sockaddr *)addr, (int *) len);
  716.     if (rv==0)
  717.         return PR_SUCCESS;
  718.     else {
  719.         _PR_MD_MAP_GETSOCKNAME_ERROR(sock_errno());
  720.         return PR_FAILURE;
  721.     }
  722. }
  723.  
  724. PRStatus
  725. _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
  726. {
  727.     PRInt32 rv;
  728.  
  729.     rv = getpeername((int)fd->secret->md.osfd, (struct sockaddr *)addr, (int *) len);
  730.     if (rv==0)
  731.         return PR_SUCCESS;
  732.     else {
  733.         _PR_MD_MAP_GETPEERNAME_ERROR(sock_errno());
  734.         return PR_FAILURE;
  735.     }
  736. }
  737.  
  738. PRStatus
  739. _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
  740. {
  741.     PRInt32 rv;
  742.  
  743.     rv = getsockopt((int)fd->secret->md.osfd, level, optname, optval, optlen);
  744.     if (rv==0)
  745.         return PR_SUCCESS;
  746.     else {
  747.         _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
  748.         return PR_FAILURE;
  749.     }
  750. }
  751.  
  752. PRStatus
  753. _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
  754. {
  755.     PRInt32 rv;
  756.  
  757.     rv = setsockopt((int)fd->secret->md.osfd, level, optname, (char *) optval, optlen);
  758.     if (rv==0)
  759.         return PR_SUCCESS;
  760.     else {
  761.         _PR_MD_MAP_SETSOCKOPT_ERROR(sock_errno());
  762.         return PR_FAILURE;
  763.     }
  764. }
  765.  
  766. void
  767. _MD_MakeNonblock(PRFileDesc *f)
  768. {
  769.     return; /* do nothing! */ 
  770. }
  771.