home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / md / windows / w95sock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  16.5 KB  |  615 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. /* Win95 Sockets module
  20.  *
  21.  */
  22.  
  23. #include "primpl.h"
  24.  
  25.  
  26. /* --- SOCKET IO --------------------------------------------------------- */
  27.  
  28.  
  29. PRInt32
  30. _PR_MD_SOCKET(int af, int type, int flags)
  31. {
  32.     SOCKET sock;
  33.     PRUint32  one = 1;
  34.     PRInt32   rv;
  35.     PRInt32   err;
  36.  
  37.     sock = socket(af, type, flags);
  38.  
  39.     if (sock == INVALID_SOCKET ) 
  40.     {
  41.         int rv = WSAGetLastError();
  42.         closesocket(sock);
  43.         _PR_MD_MAP_SOCKET_ERROR(rv);
  44.         return (PRInt32)INVALID_SOCKET;
  45.     }
  46.  
  47.     /*
  48.     ** Make the socket Non-Blocking
  49.     */
  50.     rv = ioctlsocket( sock, FIONBIO, &one);
  51.     if ( rv != 0 )
  52.     {
  53.         err = WSAGetLastError();
  54.         return -1;
  55.     }
  56.  
  57.     return (PRInt32)sock;
  58. }
  59.  
  60. /*
  61. ** _MD_CloseSocket() -- Close a socket
  62. **
  63. */
  64. PRInt32
  65. _MD_CloseSocket(PRInt32 osfd)
  66. {
  67.     PRInt32 rv = SOCKET_ERROR;
  68.  
  69.     rv = closesocket((SOCKET) osfd );
  70.     if (rv < 0)
  71.         _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError());
  72.  
  73.     return rv;
  74. }
  75.  
  76. PRInt32
  77. _MD_SocketAvailable(PRFileDesc *fd)
  78. {
  79.     PRInt32 result;
  80.  
  81.     if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) {
  82.         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError());
  83.         return -1;
  84.     }
  85.     return result;
  86. }
  87.  
  88. PRInt32
  89. _MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
  90.               PRIntervalTime timeout )
  91. {
  92.     PRInt32 osfd = fd->secret->md.osfd;
  93.     PRInt32 rv, err;
  94.     fd_set rd;
  95.     struct timeval tv, *tvp;
  96.  
  97.     FD_ZERO(&rd);
  98.     FD_SET((SOCKET)osfd, &rd);
  99.     if (timeout == PR_INTERVAL_NO_TIMEOUT) 
  100.     {
  101.         while ((rv = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1) 
  102.         {
  103.             if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) 
  104.                 && (!fd->secret->nonblocking))
  105.             {
  106.                 if ((rv = select(osfd + 1, &rd, NULL, NULL,NULL)) == -1) {
  107.                     _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
  108.                     break;
  109.             } 
  110.             } 
  111.             else {
  112.                 _PR_MD_MAP_ACCEPT_ERROR(err);
  113.                 break;
  114.         }
  115.         }
  116.         return(rv);
  117.     } 
  118.     else if (timeout == PR_INTERVAL_NO_WAIT) 
  119.     {
  120.         if ((rv = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1)
  121.         {
  122.             if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) 
  123.                 && (!fd->secret->nonblocking))
  124.             {
  125.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  126.             }
  127.             else
  128.             {
  129.                 _PR_MD_MAP_ACCEPT_ERROR(err);
  130.             }
  131.         }
  132.             return(rv);
  133.     } 
  134.     else 
  135.     {
  136. retry:
  137.         if ((rv = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1) 
  138.         {
  139.             if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) 
  140.                 && (!fd->secret->nonblocking))
  141.             {
  142.                 tv.tv_sec = PR_IntervalToSeconds(timeout);
  143.                 tv.tv_usec = PR_IntervalToMicroseconds(
  144.                     timeout - PR_SecondsToInterval(tv.tv_sec));
  145.                 tvp = &tv;
  146.  
  147.                 rv = select(osfd + 1, &rd, NULL, NULL, tvp);
  148.                 if (rv > 0) {
  149.                     goto retry;
  150.                 } 
  151.                 else if (rv == 0) 
  152.                 {
  153.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  154.                     rv = -1;
  155.                 } else {
  156.                     _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
  157.                 }
  158.             } else {
  159.                 _PR_MD_MAP_ACCEPT_ERROR(err);
  160.             }
  161.         }
  162.     }
  163.     return(rv);
  164. } /* end _MD_Accept() */
  165.  
  166.  
  167. PRInt32
  168. _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, 
  169.                PRIntervalTime timeout)
  170. {
  171.     PRInt32 osfd = fd->secret->md.osfd;
  172.     PRInt32 rv;
  173.     int err, len;
  174.     fd_set wd, ex;
  175.     struct timeval tv, *tvp;
  176.  
  177.     if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1) 
  178.     {
  179.         err = WSAGetLastError();
  180.         if ((!fd->secret->nonblocking) && (err == WSAEWOULDBLOCK))
  181.         {
  182.             if (timeout == PR_INTERVAL_NO_TIMEOUT)
  183.                 tvp = NULL;
  184.             else 
  185.             {
  186.                 tv.tv_sec = PR_IntervalToSeconds(timeout);
  187.                 tv.tv_usec = PR_IntervalToMicroseconds(
  188.                 timeout - PR_SecondsToInterval(tv.tv_sec));
  189.                 tvp = &tv;
  190.             }
  191.  
  192.             FD_ZERO(&wd);
  193.             FD_SET((SOCKET)osfd, &wd);
  194.             FD_ZERO(&ex);
  195.             FD_SET((SOCKET)osfd, &ex);
  196.             rv = select(osfd + 1, NULL, &wd, &ex, tvp);
  197.             if (rv > 0) 
  198.             {
  199.                 if (FD_ISSET((SOCKET)osfd, &ex))
  200.                 {
  201.                     Sleep(0);
  202.                     len = sizeof(err);
  203.                     if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
  204.                             (char *) &err, &len) == SOCKET_ERROR)
  205.                     {  
  206.                         _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
  207.                         return -1;
  208.                     }
  209.                     if (err != 0)
  210.                         _PR_MD_MAP_CONNECT_ERROR(err);
  211.                     else
  212.                         PR_SetError(PR_UNKNOWN_ERROR, 0);
  213.                     return -1;
  214.                 }
  215.                 if (FD_ISSET((SOCKET)osfd, &wd))
  216.                 {
  217.                     /* it's connected */
  218.                     return 0;
  219.                 }
  220.             } 
  221.             else if (rv == 0) 
  222.             {
  223.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  224.                 return(-1);
  225.             } else if (rv < 0) 
  226.             {
  227.                 _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
  228.                 return(-1);
  229.             }
  230.         } 
  231.         _PR_MD_MAP_CONNECT_ERROR(err);
  232.     }
  233.     return rv;
  234. }
  235.  
  236. PRInt32
  237. _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
  238. {
  239.     PRInt32 rv;
  240.     int one = 1;
  241.  
  242.     rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen);
  243.  
  244.     if (rv == SOCKET_ERROR)  {
  245.         _PR_MD_MAP_BIND_ERROR(WSAGetLastError());
  246.         return -1;
  247.     }
  248.  
  249.     return 0;
  250. }
  251.  
  252.  
  253. PRInt32
  254. _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, 
  255.             PRIntervalTime timeout)
  256. {
  257.     PRInt32 osfd = fd->secret->md.osfd;
  258.     PRInt32 rv, err;
  259.     struct timeval tv, *tvp;
  260.     fd_set rd;
  261.  
  262.     while ((rv = recv( osfd, buf, amount, 0)) == -1) 
  263.     {
  264.         if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) 
  265.             && (!fd->secret->nonblocking))
  266.         {
  267.             FD_ZERO(&rd);
  268.             FD_SET((SOCKET)osfd, &rd);
  269.             if (timeout == PR_INTERVAL_NO_TIMEOUT) 
  270.             {
  271.                 tvp = NULL;
  272.             } 
  273.             else 
  274.             {
  275.                 tv.tv_sec = PR_IntervalToSeconds(timeout);
  276.                 tv.tv_usec = PR_IntervalToMicroseconds(
  277.                 timeout - PR_SecondsToInterval(tv.tv_sec));
  278.                 tvp = &tv;
  279.             }
  280.             if ((rv = select(osfd + 1, &rd, NULL, NULL, tvp)) == -1) 
  281.             {
  282.                 _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
  283.                 return -1;
  284.             } 
  285.             else if (rv == 0) 
  286.             {
  287.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  288.                 rv = -1;
  289.                 break;
  290.             }
  291.         } 
  292.         else 
  293.         {
  294.             _PR_MD_MAP_RECV_ERROR(err);
  295.             break;
  296.         }
  297.     } /* end while() */
  298.     return(rv);
  299. }
  300.  
  301. PRInt32
  302. _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
  303.             PRIntervalTime timeout)
  304. {
  305.     PRInt32 osfd = fd->secret->md.osfd;
  306.     PRInt32 rv, err;
  307.     struct timeval tv, *tvp;
  308.     fd_set wd;
  309.     PRInt32 bytesSent = 0;
  310.  
  311.     while(bytesSent < amount ) 
  312.     {
  313.         while ((rv = send( osfd, buf, amount, 0 )) == -1) 
  314.         {
  315.             if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) 
  316.                 && (!fd->secret->nonblocking))
  317.             {
  318.                 if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  319.                 {
  320.                     tvp = NULL;
  321.                 } 
  322.                 else 
  323.                 {
  324.                     tv.tv_sec = PR_IntervalToSeconds(timeout);
  325.                     tv.tv_usec = PR_IntervalToMicroseconds(
  326.                         timeout - PR_SecondsToInterval(tv.tv_sec));
  327.                     tvp = &tv;
  328.                 }
  329.                 FD_ZERO(&wd);
  330.                 FD_SET((SOCKET)osfd, &wd);
  331.                 if ((rv = select( osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
  332.                     _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
  333.                     break;
  334.                 }
  335.                 if (rv == 0) 
  336.                 {
  337.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  338.                         return -1;
  339.                 }
  340.             } 
  341.             else {
  342.                 _PR_MD_MAP_SEND_ERROR(err);
  343.                 return -1;
  344.         }
  345.         }
  346.         bytesSent += rv;
  347.         if (fd->secret->nonblocking)
  348.         {
  349.             break;
  350.         }
  351.         if ((rv >= 0) && (bytesSent < amount )) 
  352.         {
  353.             if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  354.             {
  355.                 tvp = NULL;
  356.             } 
  357.             else 
  358.             {
  359.                 tv.tv_sec = PR_IntervalToSeconds(timeout);
  360.                 tv.tv_usec = PR_IntervalToMicroseconds(
  361.                     timeout - PR_SecondsToInterval(tv.tv_sec));
  362.                 tvp = &tv;
  363.             }
  364.             FD_ZERO(&wd);
  365.             FD_SET((SOCKET)osfd, &wd);
  366.             if ((rv = select(osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
  367.                 _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
  368.                 break;
  369.             }
  370.             if (rv == 0) 
  371.             {
  372.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  373.                     return -1;
  374.             }
  375.         }
  376.     }
  377.     return bytesSent;
  378. }
  379.  
  380. PRInt32
  381. _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
  382.               const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
  383. {
  384.     PRInt32 osfd = fd->secret->md.osfd;
  385.     PRInt32 rv, err;
  386.     struct timeval tv, *tvp;
  387.     fd_set wd;
  388.     PRInt32 bytesSent = 0;
  389.  
  390.     while(bytesSent < amount) 
  391.     {
  392.         while ((rv = sendto( osfd, buf, amount, 0, (struct sockaddr *) addr,
  393.                 addrlen)) == -1) 
  394.         {
  395.             if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) 
  396.                 && (!fd->secret->nonblocking))
  397.             {
  398.                 if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  399.                 {
  400.                     tvp = NULL;
  401.                 } 
  402.                 else 
  403.                 {
  404.                     tv.tv_sec = PR_IntervalToSeconds(timeout);
  405.                     tv.tv_usec = PR_IntervalToMicroseconds(
  406.                         timeout - PR_SecondsToInterval(tv.tv_sec));
  407.                     tvp = &tv;
  408.                 }
  409.                 FD_ZERO(&wd);
  410.                 FD_SET((SOCKET)osfd, &wd);
  411.                 if ((rv = select(osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
  412.                     _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
  413.                     break;
  414.                 }
  415.                 if (rv == 0) 
  416.                 {
  417.                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  418.                         return -1;
  419.                 }
  420.             } 
  421.             else {
  422.                 _PR_MD_MAP_SENDTO_ERROR(err);
  423.                 return -1;
  424.         }
  425.         }
  426.         bytesSent += rv;
  427.         if (fd->secret->nonblocking)
  428.         {
  429.             break;
  430.         }
  431.         if ((rv >= 0) && (bytesSent < amount )) 
  432.         {
  433.             if ( timeout == PR_INTERVAL_NO_TIMEOUT ) 
  434.             {
  435.                 tvp = NULL;
  436.             } 
  437.             else 
  438.             {
  439.                 tv.tv_sec = PR_IntervalToSeconds(timeout);
  440.                 tv.tv_usec = PR_IntervalToMicroseconds(
  441.                     timeout - PR_SecondsToInterval(tv.tv_sec));
  442.                 tvp = &tv;
  443.             }
  444.             FD_ZERO(&wd);
  445.             FD_SET((SOCKET)osfd, &wd);
  446.             if ((rv = select( osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
  447.                 _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
  448.                 break;
  449.             }
  450.             if (rv == 0) 
  451.             {
  452.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  453.                     return -1;
  454.             }
  455.         }
  456.     }
  457.     return bytesSent;
  458. }
  459.  
  460. PRInt32
  461. _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
  462.                 PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
  463. {
  464.     PRInt32 osfd = fd->secret->md.osfd;
  465.     PRInt32 rv, err;
  466.     struct timeval tv, *tvp;
  467.     fd_set rd;
  468.  
  469.     while ((rv = recvfrom( osfd, buf, amount, 0, (struct sockaddr *) addr,
  470.             addrlen)) == -1) 
  471.     {
  472.         if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) 
  473.             && (!fd->secret->nonblocking))
  474.         {
  475.             if (timeout == PR_INTERVAL_NO_TIMEOUT) 
  476.             {
  477.                 tvp = NULL;
  478.             } 
  479.             else 
  480.             {
  481.                 tv.tv_sec = PR_IntervalToSeconds(timeout);
  482.                 tv.tv_usec = PR_IntervalToMicroseconds(
  483.                 timeout - PR_SecondsToInterval(tv.tv_sec));
  484.                 tvp = &tv;
  485.             }
  486.             FD_ZERO(&rd);
  487.             FD_SET((SOCKET)osfd, &rd);
  488.             if ((rv = select(osfd + 1, &rd, NULL, NULL, tvp)) == -1) 
  489.             {
  490.                 _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
  491.                 return -1;
  492.             } else if (rv == 0) 
  493.             {
  494.                 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
  495.                 rv = -1;
  496.                 break;
  497.             }
  498.         } 
  499.         else 
  500.         {
  501.             _PR_MD_MAP_RECVFROM_ERROR(err);
  502.             break;
  503.         }
  504.     }
  505.     return(rv);
  506. }
  507.  
  508. PRInt32
  509. _PR_MD_WRITEV(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
  510. {
  511.     int index;
  512.     int sent = 0;
  513.     int rv;
  514.  
  515.     for (index=0; index < iov_size; index++) 
  516.     {
  517.         rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
  518.         if (rv > 0) 
  519.             sent += rv;
  520.         if ( rv != iov[index].iov_len ) 
  521.         {
  522.             if (rv < 0)
  523.             {
  524.                 if (fd->secret->nonblocking
  525.                     && (PR_GetError() == PR_WOULD_BLOCK_ERROR)
  526.                     && (sent > 0))
  527.                 {
  528.                     return sent;
  529.                 }
  530.                 else
  531.                 {
  532.                     return -1;
  533.                 }
  534.             }
  535.             /* Only a nonblocking socket can have partial sends */
  536.             PR_ASSERT(fd->secret->nonblocking);
  537.             return sent;
  538.         }
  539.     }
  540.     return sent;
  541. }
  542.  
  543. PRInt32
  544. _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
  545. {
  546. PRInt32 rv;
  547.  
  548.     rv = shutdown(fd->secret->md.osfd, how);
  549.     if (rv < 0)
  550.         _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError());
  551.     return rv;
  552. }
  553.  
  554. PRStatus
  555. _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
  556. {
  557.     PRInt32 rv;
  558.  
  559.     rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len);
  560.     if (rv==0)
  561.         return PR_SUCCESS;
  562.     else {
  563.         _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError());
  564.         return PR_FAILURE;
  565.     }
  566. }
  567.  
  568. PRStatus
  569. _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
  570. {
  571.     PRInt32 rv;
  572.  
  573.     rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len);
  574.     if (rv==0)
  575.         return PR_SUCCESS;
  576.     else {
  577.         _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError());
  578.         return PR_FAILURE;
  579.     }
  580. }
  581.  
  582. PRStatus
  583. _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
  584. {
  585.     PRInt32 rv;
  586.  
  587.     rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
  588.     if (rv==0)
  589.         return PR_SUCCESS;
  590.     else {
  591.         _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
  592.         return PR_FAILURE;
  593.     }
  594. }
  595.  
  596. PRStatus
  597. _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
  598. {
  599.     PRInt32 rv;
  600.  
  601.     rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
  602.     if (rv==0)
  603.         return PR_SUCCESS;
  604.     else {
  605.         _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError());
  606.         return PR_FAILURE;
  607.     }
  608. }
  609.  
  610. void
  611. _MD_MakeNonblock(PRFileDesc *f)
  612. {
  613.     return; // do nothing!
  614. }
  615.