2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / gnu / java / net / natPlainSocketImplWin32.cc
blobc4a54a90c3a1673c7872b475516260b2cd7b568f
1 /* Copyright (C) 2003 Free Software Foundation
3 This file is part of libgcj.
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
7 details. */
9 #include <config.h>
10 #include <platform.h>
12 #undef STRICT
13 #undef MAX_PRIORITY
14 #undef MIN_PRIORITY
16 #include <gnu/java/net/PlainSocketImpl.h>
17 #include <gnu/java/net/PlainSocketImpl$SocketInputStream.h>
18 #include <gnu/java/net/PlainSocketImpl$SocketOutputStream.h>
19 #include <java/io/IOException.h>
20 #include <java/net/BindException.h>
21 #include <java/net/ConnectException.h>
22 #include <java/net/InetAddress.h>
23 #include <java/net/InetSocketAddress.h>
24 #include <java/net/SocketException.h>
25 #include <java/net/SocketTimeoutException.h>
26 #include <java/lang/InternalError.h>
27 #include <java/lang/Object.h>
28 #include <java/lang/Boolean.h>
29 #include <java/lang/Class.h>
30 #include <java/lang/Integer.h>
31 #include <java/lang/Thread.h>
32 #include <java/lang/NullPointerException.h>
33 #include <java/lang/ArrayIndexOutOfBoundsException.h>
34 #include <java/lang/IllegalArgumentException.h>
36 union SockAddr
38 struct sockaddr_in address;
39 #ifdef HAVE_INET6
40 struct sockaddr_in6 address6;
41 #endif
44 void
45 gnu::java::net::PlainSocketImpl::create (jboolean stream)
47 SOCKET sock = ::socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
49 if (sock == INVALID_SOCKET)
51 _Jv_ThrowIOException ();
54 // Cast this to a HANDLE so we can make
55 // it non-inheritable via _Jv_platform_close_on_exec.
56 HANDLE hSocket = (HANDLE) sock;
57 _Jv_platform_close_on_exec (hSocket);
59 // We use native_fd in place of fd here. From leaving fd null we avoid
60 // the double close problem in FileDescriptor.finalize.
61 native_fd = (jint) hSocket;
64 void
65 gnu::java::net::PlainSocketImpl::bind (::java::net::InetAddress *host, jint lport)
67 union SockAddr u;
68 struct sockaddr *ptr = (struct sockaddr *) &u.address;
69 jbyteArray haddress = host->addr;
70 jbyte *bytes = elements (haddress);
71 int len = haddress->length;
73 if (len == 4)
75 u.address.sin_family = AF_INET;
77 if (host != NULL)
78 memcpy (&u.address.sin_addr, bytes, len);
79 else
80 u.address.sin_addr.s_addr = htonl (INADDR_ANY);
82 len = sizeof (struct sockaddr_in);
83 u.address.sin_port = htons (lport);
85 #ifdef HAVE_INET6
86 else if (len == 16)
88 u.address6.sin6_family = AF_INET6;
89 memcpy (&u.address6.sin6_addr, bytes, len);
90 len = sizeof (struct sockaddr_in6);
91 u.address6.sin6_port = htons (lport);
93 #endif
94 else
95 throw new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
97 if (::bind (native_fd, ptr, len) != SOCKET_ERROR)
99 socklen_t addrlen = sizeof(u);
101 if (lport != 0)
102 localport = lport;
103 else if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) != SOCKET_ERROR)
104 localport = ntohs (u.address.sin_port);
105 else
106 goto error;
108 return;
111 error:
112 DWORD dwErrorCode = WSAGetLastError ();
113 throw new ::java::net::BindException (_Jv_WinStrError (dwErrorCode));
116 static void
117 throwConnectException (DWORD dwErrorCode)
119 throw new ::java::net::ConnectException (_Jv_WinStrError (dwErrorCode));
122 static void
123 throwConnectException ()
125 throwConnectException (WSAGetLastError ());
128 void
129 gnu::java::net::PlainSocketImpl::connect (::java::net::SocketAddress *addr,
130 jint timeout)
132 ::java::net::InetSocketAddress *tmp = (::java::net::InetSocketAddress*) addr;
133 ::java::net::InetAddress *host = tmp->getAddress();
134 jint rport = tmp->getPort();
136 union SockAddr u;
137 socklen_t addrlen = sizeof(u);
138 jbyteArray haddress = host->addr;
139 jbyte *bytes = elements (haddress);
140 int len = haddress->length;
141 struct sockaddr *ptr = (struct sockaddr *) &u.address;
143 if (len == 4)
145 u.address.sin_family = AF_INET;
146 memcpy (&u.address.sin_addr, bytes, len);
147 len = sizeof (struct sockaddr_in);
148 u.address.sin_port = htons (rport);
150 #ifdef HAVE_INET6
151 else if (len == 16)
153 u.address6.sin6_family = AF_INET6;
154 memcpy (&u.address6.sin6_addr, bytes, len);
155 len = sizeof (struct sockaddr_in6);
156 u.address6.sin6_port = htons (rport);
158 #endif
159 else
160 throw new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
162 if (timeout > 0)
164 // FIXME: we're creating a fresh WSAEVENT for each connect().
165 WSAEventWrapper aWSAEventWrapper(native_fd, FD_CONNECT);
166 WSAEVENT hEvent = aWSAEventWrapper.getEventHandle ();
168 if (::connect (native_fd, ptr, len) == SOCKET_ERROR)
170 if (WSAGetLastError () != WSAEWOULDBLOCK)
171 throwConnectException ();
173 DWORD dwRet =
174 WSAWaitForMultipleEvents (1, &hEvent, true, timeout, false);
175 // use true, false instead of TRUE, FALSE because the
176 // MS constants got undefined
178 // Reset and ignore our thread's interrupted flag.
179 // It's not possible to interrupt these sort of
180 // operations on Win32 anyway.
181 ::java::lang::Thread::interrupted();
183 if (dwRet == WSA_WAIT_FAILED)
184 throwConnectException ();
185 else if (dwRet == WSA_WAIT_TIMEOUT)
186 throw new ::java::net::SocketTimeoutException
187 (JvNewStringUTF ("connect timed out"));
189 // If we get here, we still need to check whether the actual
190 // connect() succeeded. Use any socket-specific error code
191 // instead of the thread-based one.
192 int nErrCode; int nErrLen=sizeof(nErrCode);
193 if (::getsockopt(native_fd, SOL_SOCKET, SO_ERROR, (char*) &nErrCode,
194 &nErrLen) == SOCKET_ERROR)
196 throwConnectException ();
199 if (nErrCode != NO_ERROR)
201 throwConnectException (nErrCode);
205 else
207 if (::connect (native_fd, ptr, len) == SOCKET_ERROR)
208 throwConnectException();
211 address = host;
212 port = rport;
214 // A bind may not have been done on this socket; if so, set localport now.
215 if (localport == 0)
217 if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) != SOCKET_ERROR)
218 localport = ntohs (u.address.sin_port);
219 else
220 throwConnectException();
224 void
225 gnu::java::net::PlainSocketImpl::listen (jint backlog)
227 if (::listen (native_fd, backlog) == SOCKET_ERROR)
229 _Jv_ThrowIOException ();
233 void
234 gnu::java::net::PlainSocketImpl::accept (gnu::java::net::PlainSocketImpl *s)
236 union SockAddr u;
237 socklen_t addrlen = sizeof(u);
238 HANDLE hSocket = 0;
239 SOCKET new_socket = 0;
241 if (timeout > 0)
243 // FIXME: we're creating a fresh WSAEVENT for each accept().
244 // One possible alternative would be that native_fd really points
245 // to an extended structure consisting of the SOCKET, its
246 // associated WSAEVENT, etc.
247 WSAEventWrapper aWSAEventWrapper(native_fd, FD_ACCEPT);
248 WSAEVENT hEvent = aWSAEventWrapper.getEventHandle ();
250 for (;;)
252 new_socket = ::accept (native_fd, (sockaddr*) &u, &addrlen);
254 if (new_socket != INVALID_SOCKET)
256 // This new child socket is nonblocking because the parent
257 // socket became nonblocking via the WSAEventSelect() call,
258 // so we set its mode back to blocking.
259 WSAEventSelect (new_socket, hEvent, 0);
260 // undo the hEvent <-> FD_ACCEPT association inherited
261 // inherited from our parent socket
263 unsigned long lSockOpt = 0L;
264 // blocking mode
265 if (ioctlsocket(new_socket, FIONBIO, &lSockOpt) == SOCKET_ERROR)
267 goto error;
269 break;
271 else if (WSAGetLastError () != WSAEWOULDBLOCK)
273 goto error;
276 DWORD dwRet =
277 WSAWaitForMultipleEvents (1, &hEvent, true, timeout, false);
278 // use true, false instead of TRUE, FALSE because the
279 // MS constants got undefined
281 // Reset and ignore our thread's interrupted flag.
282 ::java::lang::Thread::interrupted();
284 if (dwRet == WSA_WAIT_FAILED)
285 goto error;
286 else if (dwRet == WSA_WAIT_TIMEOUT)
287 throw new ::java::net::SocketTimeoutException
288 (JvNewStringUTF ("Accept timed out"));
291 else
293 new_socket = ::accept (native_fd, (sockaddr*) &u, &addrlen);
296 if (new_socket == INVALID_SOCKET)
297 goto error;
299 // Cast this to a HANDLE so we can make
300 // it non-inheritable via _Jv_platform_close_on_exec.
301 hSocket = (HANDLE) new_socket;
302 _Jv_platform_close_on_exec (hSocket);
304 jbyteArray raddr;
305 jint rport;
306 if (u.address.sin_family == AF_INET)
308 raddr = JvNewByteArray (4);
309 memcpy (elements (raddr), &u.address.sin_addr, 4);
310 rport = ntohs (u.address.sin_port);
312 #ifdef HAVE_INET6
313 else if (u.address.sin_family == AF_INET6)
315 raddr = JvNewByteArray (16);
316 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
317 rport = ntohs (u.address6.sin6_port);
319 #endif
320 else
321 throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
323 s->native_fd = (jint) hSocket;
324 s->localport = localport;
325 s->address = new ::java::net::InetAddress (raddr, NULL);
326 s->port = rport;
327 return;
329 error:
330 _Jv_ThrowIOException ();
333 // Close(shutdown) the socket.
334 void
335 gnu::java::net::PlainSocketImpl::close()
337 // Avoid races from asynchronous finalization.
338 JvSynchronize sync (this);
340 // should we use shutdown here? how would that effect so_linger?
341 int res = ::closesocket (native_fd);
343 if (res == -1)
345 // These three errors are not errors according to tests performed
346 // on the reference implementation.
347 DWORD dwErr = WSAGetLastError();
348 if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET
349 && dwErr != WSAENOTSOCK)
350 _Jv_ThrowIOException ();
352 // Safe place to reset the file pointer.
353 native_fd = -1;
354 timeout = 0;
357 // Write a byte to the socket.
358 void
359 gnu::java::net::PlainSocketImpl$SocketOutputStream::write(jint b)
361 jbyte d =(jbyte) b;
362 int r = 0;
364 while (r != 1)
366 r = ::send (this$0->native_fd, (char*) &d, 1, 0);
367 if (r == -1)
369 DWORD dwErr = WSAGetLastError();
371 // Reset and ignore our thread's interrupted flag.
372 // It's not possible to interrupt these sort of
373 // operations on Win32 anyway.
374 ::java::lang::Thread::interrupted();
376 // Some errors should not cause exceptions.
377 if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET
378 && dwErr != WSAENOTSOCK)
379 _Jv_ThrowIOException ();
380 break;
385 // Write some bytes to the socket.
386 void
387 gnu::java::net::PlainSocketImpl$SocketOutputStream::write(jbyteArray b,
388 jint offset, jint len)
390 if (! b)
391 throw new ::java::lang::NullPointerException;
392 if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
393 throw new ::java::lang::ArrayIndexOutOfBoundsException;
395 jbyte *bytes = elements (b) + offset;
396 int written = 0;
397 while (len > 0)
399 int r = ::send (this$0->native_fd, (char*) bytes, len, 0);
401 if (r == -1)
403 DWORD dwErr = WSAGetLastError();
405 // Reset and ignore our thread's interrupted flag.
406 ::java::lang::Thread::interrupted();
408 // Some errors should not cause exceptions.
409 if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET
410 && dwErr != WSAENOTSOCK)
411 _Jv_ThrowIOException ();
412 break;
415 written += r;
416 len -= r;
417 bytes += r;
421 void
422 gnu::java::net::PlainSocketImpl::sendUrgentData (jint)
424 throw new ::java::net::SocketException (JvNewStringLatin1 (
425 "PlainSocketImpl: sending of urgent data not supported by this socket"));
428 // read() helper
429 static jint
430 doRead(int native_fd, void* buf, int count, int timeout)
432 int r = 0;
433 DWORD dwErrorCode = 0;
434 // we are forced to declare this here because
435 // a call to Thread::interrupted() blanks out
436 // WSAGetLastError().
438 // FIXME: we unconditionally set SO_RCVTIMEO here
439 // because we can't detect whether someone has
440 // gone from a non-zero to zero timeout. What we'd
441 // really need is a member state variable in addition
442 // to timeout
443 int nRet= ::setsockopt(native_fd, SOL_SOCKET, SO_RCVTIMEO,
444 (char*)&timeout, sizeof(timeout));
445 if (nRet != NO_ERROR)
447 dwErrorCode = WSAGetLastError ();
448 goto error;
451 r = ::recv (native_fd, (char*) buf, count, 0);
453 if (r == 0)
454 return -1;
456 dwErrorCode = WSAGetLastError ();
457 // save WSAGetLastError() before calling Thread.interrupted()
459 // Reset and ignore our thread's interrupted flag.
460 ::java::lang::Thread::interrupted();
462 if (r == -1)
464 error:
465 // Some errors cause us to return end of stream...
466 if (dwErrorCode == WSAENOTCONN)
467 return -1;
469 // Other errors need to be signalled.
470 if (dwErrorCode == WSAETIMEDOUT)
471 throw new ::java::net::SocketTimeoutException
472 (JvNewStringUTF ("Read timed out") );
473 else
474 _Jv_ThrowIOException (dwErrorCode);
477 return r;
480 // Read a single byte from the socket.
481 jint
482 gnu::java::net::PlainSocketImpl$SocketInputStream::read(void)
484 jbyte b;
485 doRead(this$0->native_fd, &b, 1, this$0->timeout);
486 return b & 0xFF;
489 // Read count bytes into the buffer, starting at offset.
490 jint
491 gnu::java::net::PlainSocketImpl$SocketInputStream::read(jbyteArray buffer,
492 jint offset, jint count)
494 if (! buffer)
495 throw new ::java::lang::NullPointerException;
497 jsize bsize = JvGetArrayLength (buffer);
499 if (offset < 0 || count < 0 || offset + count > bsize)
500 throw new ::java::lang::ArrayIndexOutOfBoundsException;
502 jbyte *bytes = elements (buffer) + offset;
504 // Read the socket.
505 return doRead(this$0->native_fd, bytes, count, this$0->timeout);
508 // How many bytes are available?
509 jint
510 gnu::java::net::PlainSocketImpl::available(void)
512 unsigned long num = 0;
514 if (::ioctlsocket (native_fd, FIONREAD, &num) == SOCKET_ERROR)
515 _Jv_ThrowIOException ();
517 return (jint) num;
520 void
521 gnu::java::net::PlainSocketImpl::setOption (jint optID, ::java::lang::Object *value)
523 int val;
524 socklen_t val_len = sizeof (val);
526 if (native_fd < 0)
527 throw new ::java::net::SocketException (JvNewStringUTF ("Socket closed"));
529 if (_Jv_IsInstanceOf (value, &::java::lang::Boolean::class$))
531 ::java::lang::Boolean *boolobj =
532 static_cast< ::java::lang::Boolean *> (value);
533 if (boolobj->booleanValue())
534 val = 1;
535 else
537 if (optID == _Jv_SO_LINGER_)
538 val = -1;
539 else
540 val = 0;
543 else if (_Jv_IsInstanceOf (value, &::java::lang::Integer::class$))
545 ::java::lang::Integer *intobj =
546 static_cast< ::java::lang::Integer *> (value);
547 val = (int) intobj->intValue();
549 else
551 throw new ::java::lang::IllegalArgumentException (
552 JvNewStringLatin1 ("`value' must be Boolean or Integer"));
555 switch (optID)
557 case _Jv_TCP_NODELAY_ :
558 if (::setsockopt (native_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
559 val_len) == SOCKET_ERROR)
560 goto error;
561 return;
563 case _Jv_SO_KEEPALIVE_ :
564 if (::setsockopt (native_fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
565 val_len) == SOCKET_ERROR)
566 goto error;
567 break;
569 case _Jv_SO_BROADCAST_ :
570 throw new ::java::net::SocketException
571 (JvNewStringUTF ("SO_BROADCAST not valid for TCP"));
572 break;
574 case _Jv_SO_OOBINLINE_ :
575 if (::setsockopt (native_fd, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
576 val_len) == SOCKET_ERROR)
577 goto error;
578 break;
580 case _Jv_SO_LINGER_ :
581 struct linger l_val;
582 l_val.l_onoff = (val != -1);
583 l_val.l_linger = val;
585 if (::setsockopt (native_fd, SOL_SOCKET, SO_LINGER, (char *) &l_val,
586 sizeof(l_val)) == SOCKET_ERROR)
587 goto error;
588 return;
590 case _Jv_SO_SNDBUF_ :
591 case _Jv_SO_RCVBUF_ :
592 int opt;
593 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
594 if (::setsockopt (native_fd, SOL_SOCKET, opt, (char *) &val,
595 val_len) == SOCKET_ERROR)
596 goto error;
597 return;
599 case _Jv_SO_BINDADDR_ :
600 throw new ::java::net::SocketException (
601 JvNewStringUTF ("SO_BINDADDR: read only option"));
602 return;
604 case _Jv_IP_MULTICAST_IF_ :
605 throw new ::java::net::SocketException (
606 JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
607 return;
609 case _Jv_IP_MULTICAST_IF2_ :
610 throw new ::java::net::SocketException (
611 JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
612 break;
614 case _Jv_IP_MULTICAST_LOOP_ :
615 throw new ::java::net::SocketException (
616 JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
617 break;
619 case _Jv_IP_TOS_ :
620 if (::setsockopt (native_fd, SOL_SOCKET, IP_TOS, (char *) &val,
621 val_len) == SOCKET_ERROR)
622 goto error;
623 break;
625 case _Jv_SO_REUSEADDR_ :
626 throw new ::java::net::SocketException (
627 JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
628 return;
630 case _Jv_SO_TIMEOUT_ :
631 timeout = val;
632 return;
634 default :
635 WSASetLastError (WSAENOPROTOOPT);
638 error:
639 _Jv_ThrowSocketException ();
642 ::java::lang::Object *
643 gnu::java::net::PlainSocketImpl::getOption (jint optID)
645 int val;
646 socklen_t val_len = sizeof(val);
647 union SockAddr u;
648 socklen_t addrlen = sizeof(u);
649 struct linger l_val;
650 socklen_t l_val_len = sizeof(l_val);
652 switch (optID)
654 case _Jv_TCP_NODELAY_ :
655 if (::getsockopt (native_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
656 &val_len) == SOCKET_ERROR)
657 goto error;
658 else
659 return new ::java::lang::Boolean (val != 0);
660 break;
662 case _Jv_SO_LINGER_ :
663 if (::getsockopt (native_fd, SOL_SOCKET, SO_LINGER, (char *) &l_val,
664 &l_val_len) == SOCKET_ERROR)
665 goto error;
667 if (l_val.l_onoff)
668 return new ::java::lang::Integer (l_val.l_linger);
669 else
670 return new ::java::lang::Boolean ((jboolean)false);
671 break;
673 case _Jv_SO_KEEPALIVE_ :
674 if (::getsockopt (native_fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
675 &val_len) == SOCKET_ERROR)
676 goto error;
677 else
678 return new ::java::lang::Boolean (val != 0);
680 case _Jv_SO_BROADCAST_ :
681 if (::getsockopt (native_fd, SOL_SOCKET, SO_BROADCAST, (char *) &val,
682 &val_len) == SOCKET_ERROR)
683 goto error;
684 return new ::java::lang::Boolean ((jboolean)val);
686 case _Jv_SO_OOBINLINE_ :
687 if (::getsockopt (native_fd, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
688 &val_len) == SOCKET_ERROR)
689 goto error;
690 return new ::java::lang::Boolean ((jboolean)val);
692 case _Jv_SO_RCVBUF_ :
693 case _Jv_SO_SNDBUF_ :
694 int opt;
695 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
696 if (::getsockopt (native_fd, SOL_SOCKET, opt, (char *) &val,
697 &val_len) == SOCKET_ERROR)
698 goto error;
699 else
700 return new ::java::lang::Integer (val);
701 break;
702 case _Jv_SO_BINDADDR_:
703 // cache the local address
704 if (localAddress == NULL)
706 jbyteArray laddr;
708 if (::getsockname (native_fd, (sockaddr*) &u,
709 &addrlen) == SOCKET_ERROR)
710 goto error;
712 if (u.address.sin_family == AF_INET)
714 laddr = JvNewByteArray (4);
715 memcpy (elements (laddr), &u.address.sin_addr, 4);
717 #ifdef HAVE_INET6
718 else if (u.address.sin_family == AF_INET6)
720 laddr = JvNewByteArray (16);
721 memcpy (elements (laddr), &u.address6.sin6_addr, 16);
723 #endif
724 else
725 throw new ::java::net::SocketException
726 (JvNewStringUTF ("invalid family"));
727 localAddress = new ::java::net::InetAddress (laddr, NULL);
730 return localAddress;
731 break;
732 case _Jv_IP_MULTICAST_IF_ :
733 throw new ::java::net::SocketException
734 (JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
735 break;
737 case _Jv_IP_MULTICAST_IF2_ :
738 throw new ::java::net::SocketException
739 (JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
740 break;
742 case _Jv_IP_MULTICAST_LOOP_ :
743 throw new ::java::net::SocketException
744 (JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
745 break;
747 case _Jv_IP_TOS_ :
748 if (::getsockopt (native_fd, SOL_SOCKET, IP_TOS, (char *) &val,
749 &val_len) == SOCKET_ERROR)
750 goto error;
751 return new ::java::lang::Integer (val);
752 break;
754 case _Jv_SO_REUSEADDR_ :
755 throw new ::java::net::SocketException
756 (JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
757 break;
759 case _Jv_SO_TIMEOUT_ :
760 return new ::java::lang::Integer (timeout);
761 break;
763 default :
764 WSASetLastError (WSAENOPROTOOPT);
767 error:
768 _Jv_ThrowSocketException ();
769 return 0;
770 // we should never get here
773 void
774 gnu::java::net::PlainSocketImpl::shutdownInput (void)
776 if (::shutdown (native_fd, 0))
777 _Jv_ThrowSocketException ();
780 void
781 gnu::java::net::PlainSocketImpl::shutdownOutput (void)
783 if (::shutdown (native_fd, 1))
784 _Jv_ThrowSocketException ();