move FrameworkName from corlib to System
[mcs.git] / class / System / System.Net.Sockets / GHStreamSocket.jvm.cs
blobc446a5ef0c6e8977bc610c8cabaa6b8a05ecbdab
1 using java.nio.channels;
2 using java.security;
3 using javax.net.ssl;
5 namespace System.Net.Sockets
7 /// <summary>
8 /// Summary description for GHStreamSocket.
9 /// </summary>
10 internal class GHStreamSocket : GHSocket
12 java.net.ServerSocket jServerSocket;
13 java.net.Socket jSocket;
14 java.nio.channels.ServerSocketChannel jServerSocketChannel;
15 java.nio.channels.SocketChannel jSocketChannel;
17 // This field I need because a bug in the java.nio.channels.SocketAdapter, which
18 // returns local port 0 if the socket is not connected (even if the socket is bound)
19 // so I need temporary use regular socket (not channel socket) to bind it to the
20 // local address and use this address in the LocalPoint property and to create the
21 // actual client/server channel sockets
22 // The bug #5076965 (SocketChannel does not report local address after binding to a wildcard )
23 // See: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5076965
24 java.net.InetSocketAddress jTempLocalSocketAddress;
26 public GHStreamSocket()
28 jSocketChannel = java.nio.channels.SocketChannel.open();
29 jSocket = jSocketChannel.socket();
32 public GHStreamSocket(java.nio.channels.SocketChannel socketChannel)
34 jSocketChannel = socketChannel;
35 jSocket = jSocketChannel.socket();
38 public override int GetHashCode ()
40 if (jSocket == null && jServerSocket == null)
41 return -1;
43 if (jServerSocket != null) {
44 return jServerSocket.ToString ().GetHashCode ();
47 return jSocket.ToString ().GetHashCode ();
50 public int Available_internal(out int error)
52 error = 0;
53 int r = 0;
55 if (jSocket == null || !jSocket.isConnected())
57 return r;
60 try
62 r = jSocket.getInputStream().available();
64 catch (Exception e)
66 error = 10054; //WSAECONNRESET (Connection reset by peer)
67 r = 0;
68 #if DEBUG
69 Console.WriteLine("Caught exception during Available_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
70 #endif
73 return r;
76 public void Blocking_internal(bool block, out int error)
78 error = 0;
80 if (jSocket == null && jServerSocket == null)
82 error = 10022; //WSAEINVAL (Invalid argument)
83 return;
86 try
88 if (jServerSocket != null)
90 jServerSocketChannel.configureBlocking(block);
92 else
94 jSocketChannel.configureBlocking(block);
97 catch (Exception e)
99 error = 10022; //WSAEINVAL (Invalid argument)
100 #if DEBUG
101 Console.WriteLine("Caught exception during Blocking_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
102 #endif
106 public EndPoint LocalEndPoint_internal(out int error)
108 error = 0;
109 java.net.InetSocketAddress localAddr = null;
113 if (jTempLocalSocketAddress != null)
115 localAddr = jTempLocalSocketAddress;
117 else if (jServerSocket != null)
119 localAddr = (java.net.InetSocketAddress)jServerSocket.getLocalSocketAddress();
121 else
123 localAddr = (java.net.InetSocketAddress)jSocket.getLocalSocketAddress();
126 catch (Exception e)
128 localAddr = null;
129 #if DEBUG
130 Console.WriteLine("Caught exception during LocalEndPoint_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
131 #endif
134 if (localAddr == null || localAddr.getAddress() == null || localAddr.getPort() < 0)
136 return null;
139 IPHostEntry lipa = Dns.Resolve(localAddr.getHostName());
140 IPEndPoint ret = new IPEndPoint(lipa.AddressList[0], localAddr.getPort());
141 return ret;
144 public EndPoint RemoteEndPoint_internal(out int error)
146 error = 0;
147 java.net.InetSocketAddress remoteAddr = null;
149 if (jSocket == null || !jSocket.isBound())
151 return null;
156 remoteAddr = (java.net.InetSocketAddress)jSocket.getRemoteSocketAddress();
158 catch (Exception e)
160 remoteAddr = null;
161 #if DEBUG
162 Console.WriteLine("Caught exception during RemoteEndPoint_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
163 #endif
166 if (remoteAddr == null || remoteAddr.getAddress() == null || remoteAddr.getPort() <= 0)
168 error = 10057; //WSAENOTCONN (Socket is not connected)
169 return null;
172 IPHostEntry lipa = Dns.Resolve(remoteAddr.getHostName());
173 IPEndPoint ret = new IPEndPoint(lipa.AddressList[0], remoteAddr.getPort());
174 return ret;
177 public GHSocket Accept_internal(out int error)
179 error = 0;
181 if (jServerSocket == null)
183 throw new InvalidOperationException("You must call Bind and Listen before calling Accept.");
189 If this channel is in non-blocking mode then this method will immediately
190 return null if there are no pending connections.
191 Otherwise it will block indefinitely until a new connection is
192 available or an I/O error occurs.
194 java.nio.channels.SocketChannel acceptedSocket = jServerSocketChannel.accept();
195 if (acceptedSocket == null)
197 error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable)
198 #if DEBUG
199 Console.WriteLine("The Accept_internal is in non-blocking mode and no pending connections are available");
200 #endif
201 return null;
204 return new GHStreamSocket(acceptedSocket);
206 catch (AsynchronousCloseException) {
207 error = 10004;
209 catch (Exception e)
211 error = 10061; //WSAECONNREFUSED (Connection refused)
212 #if DEBUG
213 Console.WriteLine("Caught exception during Accept_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
214 #endif
217 return null;
220 public void Bind_internal(EndPoint sa, out int error)
222 error = 0;
223 IPEndPoint addr = sa as IPEndPoint;
224 if (addr == null)
226 error = 10044; //WSAESOCKTNOSUPPORT (Socket type not supported)
227 return;
230 if (jSocket == null || jSocket.isBound() || jSocket.isConnected() || jSocketChannel.isConnectionPending())
232 error = 10022; //WSAEINVAL (Invalid argument)
233 return;
238 // This code I need because a bug in the java.nio.channels.SocketAdapter, which
239 // returns local port 0 if the socket is not connected (even if the socket is bound)
240 // so I need temporary use regular socket (not channel socket) to bind it to the
241 // local address and use this address in the LocalPoint property and to create the
242 // actual client/server channel sockets
243 // The bug #5076965 (SocketChannel does not report local address after binding to a wildcard )
244 // See: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5076965
245 java.net.Socket jTempSocket = new java.net.Socket();
246 jTempSocket.bind(new java.net.InetSocketAddress(java.net.InetAddress.getByName(addr.Address.ToString()),
247 addr.Port));
248 jTempLocalSocketAddress = (java.net.InetSocketAddress)jTempSocket.getLocalSocketAddress();
249 jTempSocket.close();
250 jSocket.bind(jTempLocalSocketAddress);
252 catch (Exception e)
254 error = 10048; //WSAEADDRINUSE (Address already in use)
255 #if DEBUG
256 Console.WriteLine("Caught exception during Bind_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
257 #endif
261 public void Close_internal(out int error)
263 error = 0;
265 if (jServerSocket != null)
269 jServerSocket.close();
271 catch (Exception e)
273 error = 10022; //WSAEINVAL (Invalid argument)
274 #if DEBUG
275 Console.WriteLine("Caught exception during Close_internal jServerSocket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
276 #endif
280 jServerSocketChannel.close();
282 catch (Exception e)
284 error = 10022; //WSAEINVAL (Invalid argument)
285 #if DEBUG
286 Console.WriteLine("Caught exception during Close_internal jServerSocketChannel - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
287 #endif
289 jServerSocket = null;
290 jServerSocketChannel = null;
292 else if (jSocket != null)
296 jSocket.close();
298 catch (Exception e)
300 error = 10022; //WSAEINVAL (Invalid argument)
301 #if DEBUG
302 Console.WriteLine("Caught exception during Close_internal jSocket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
303 #endif
307 jSocketChannel.close();
309 catch (Exception e)
311 error = 10022; //WSAEINVAL (Invalid argument)
312 #if DEBUG
313 Console.WriteLine("Caught exception during Close_internal jSocketChannel - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
314 #endif
316 jSocket = null;
317 jSocketChannel = null;
321 public void Connect_internal(EndPoint sa, out int error)
323 error = 0;
325 IPEndPoint addr = sa as IPEndPoint;
326 if (addr == null)
328 error = 10044; //WSAESOCKTNOSUPPORT (Socket type not supported)
329 return;
332 if (jSocket == null)
334 error = 10022; //WSAEINVAL (Invalid argument)
335 return;
338 if (jSocket.isConnected() || jSocketChannel.isConnectionPending())
340 error = 10056; //WSAEISCONN (Socket is already connected)
341 return;
347 If this channel is in non-blocking mode then an invocation of this method
348 initiates a non-blocking connection operation. If the connection is
349 established immediately, as can happen with a local connection, then this
350 method returns true. Otherwise this method returns false.
351 If this channel is in blocking mode then an invocation of this method
352 will block until the connection is established or an I/O error occurs.
354 bool status = jSocketChannel.connect(new java.net.InetSocketAddress(
355 java.net.InetAddress.getByName(addr.Address.ToString()),
356 addr.Port));
357 if (!status)
359 error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable)
362 catch (java.nio.channels.AlreadyConnectedException ae)
364 error = 10056; //WSAEISCONN (Socket is already connected)
366 catch (java.nio.channels.ConnectionPendingException cpe)
368 error = 10036; //WSAEINPROGRESS (Operation now in progress)
370 catch (java.nio.channels.UnresolvedAddressException uae)
372 error = 10039; //WSAEDESTADDRREQ (Destination address required)
374 catch (java.nio.channels.UnsupportedAddressTypeException uate)
376 error = 10041; //WSAEPROTOTYPE (Protocol wrong type for socket)
378 catch (AsynchronousCloseException) {
379 error = 10004;
381 catch (Exception e)
383 error = 10061; //WSAECONNREFUSED (Connection refused)
384 #if DEBUG
385 Console.WriteLine("Caught exception during Connect_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
386 #endif
390 public void Listen_internal(int backlog, out int error)
392 error = 0;
394 if (jSocket == null || !jSocket.isBound())
396 error = 10022; //WSAEINVAL (Invalid argument)
397 return;
400 if (jSocket.isConnected() || jSocketChannel.isConnectionPending())
402 error = 10056; //WSAEISCONN (Socket is already connected)
403 return;
406 bool blockMode = jSocketChannel.isBlocking();
407 bool reuseAddr = jSocket.getReuseAddress();
411 jSocket.close();
413 catch (Exception e)
415 #if DEBUG
416 Console.WriteLine("Caught exception during Listen_internal close old jSocket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
417 #endif
422 jSocketChannel.close();
424 catch (Exception e)
426 #if DEBUG
427 Console.WriteLine("Caught exception during Listen_internal close old jSocketChannel - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
428 #endif
431 jSocket = null;
432 jSocketChannel = null;
436 jServerSocketChannel = java.nio.channels.ServerSocketChannel.open();
437 jServerSocket = jServerSocketChannel.socket();
438 jServerSocket.bind(jTempLocalSocketAddress, backlog);
439 jServerSocketChannel.configureBlocking(blockMode);
440 jServerSocket.setReuseAddress(reuseAddr);
442 catch (Exception e)
444 error = 10048; //WSAEADDRINUSE (Address already in use)
445 #if DEBUG
446 Console.WriteLine("Caught exception during Listen_internal create server socket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
447 #endif
451 public bool Poll_internal (SelectMode mode, int timeout, Socket source, out int error)
453 error = 0;
455 if (mode == SelectMode.SelectError && !jSocketChannel.isConnectionPending())
457 return false;
460 java.nio.channels.Selector selector = java.nio.channels.Selector.open();
461 RegisterSelector(selector, ((mode == SelectMode.SelectRead)?0:1), source, out error);
463 if (error != 0)
465 error = 0;
466 GHSocketFactory.CloseSelector(selector);
467 return (mode == SelectMode.SelectError);
470 bool retVal = false;
472 long timeOutMillis = 1;
473 if (timeout < 0)
475 timeOutMillis = 0;
477 else if (timeout > 999)
479 timeOutMillis = (long)(timeout / 1000);
482 int readyCount = 0;
485 readyCount = selector.select(timeOutMillis);
487 catch (Exception e)
489 error = 10022; //WSAEINVAL (Invalid argument)
490 #if DEBUG
491 Console.WriteLine("Caught exception during Poll_internal selector.select - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
492 #endif
495 if (readyCount > 0)
497 if (jSocket != null && jSocketChannel.isConnectionPending())
499 bool status = false;
502 status = jSocketChannel.finishConnect();
504 catch (Exception e)
506 #if DEBUG
507 Console.WriteLine("Caught exception during Poll_internal, finishConnect - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
508 #endif
510 if (status)
512 retVal = (mode != SelectMode.SelectError);
514 else
516 retVal = (mode == SelectMode.SelectError);
519 else
521 retVal = true;
525 GHSocketFactory.CloseSelector(selector);
527 return retVal;
530 public void RegisterSelector(java.nio.channels.Selector selector, int mode, Socket source, out int error)
532 error = 0;
533 if (jServerSocket != null)
535 // only accept operation, which included to the read list, is allowed for server sockets
536 if (mode != 0)
538 // error = 10038; //WSAENOTSOCK (Socket operation on nonsocket)
539 #if DEBUG
540 Console.WriteLine("RegisterSelector, invalid mode {0} for the server socket", mode);
541 #endif
542 return;
547 if (jServerSocketChannel.isBlocking())
550 A channel must be placed into non-blocking mode before being registered
551 with a selector, and may not be returned to blocking mode until it has been
552 deregistered.
554 jServerSocketChannel.configureBlocking(false);
557 jServerSocketChannel.register(selector, java.nio.channels.SelectionKey.OP_ACCEPT, source);
559 catch (Exception e)
561 error = 10022; //WSAEINVAL (Invalid argument)
562 #if DEBUG
563 Console.WriteLine("Caught exception during RegisterSelector, register server socket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
564 #endif
567 else
571 int ops = java.nio.channels.SelectionKey.OP_READ;
572 if (mode > 0)
574 if (jSocketChannel.isConnectionPending())
576 ops = java.nio.channels.SelectionKey.OP_CONNECT;
578 else
580 ops = java.nio.channels.SelectionKey.OP_WRITE;
584 if (jSocketChannel.isBlocking())
587 A channel must be placed into non-blocking mode before being registered
588 with a selector, and may not be returned to blocking mode until it has been
589 deregistered.
591 jSocketChannel.configureBlocking(false);
594 jSocketChannel.register(selector, ops, source);
596 catch (Exception e)
598 error = 10022; //WSAEINVAL (Invalid argument)
599 #if DEBUG
600 Console.WriteLine("Caught exception during RegisterSelector, register client socket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
601 #endif
606 public bool CheckConnectionFinished()
608 bool status = true;
609 if (jSocket != null && jSocketChannel.isConnectionPending())
613 status = jSocketChannel.finishConnect();
615 catch (Exception e)
617 status = false;
618 #if DEBUG
619 Console.WriteLine("Caught exception during Poll_internal, finishConnect - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
620 #endif
624 return status;
627 public int Receive_internal(byte[] buffer, int offset, int count, SocketFlags flags,
628 out int error)
630 error = 0;
631 int ret = 0;
633 if (jSocket == null)
635 error = 10057; //WSAENOTCONN (Socket is not connected)
636 return ret;
641 if (jSocketChannel.isConnectionPending())
643 bool status = jSocketChannel.finishConnect();
644 if (!status)
646 error = 10022; //WSAEINVAL (Invalid argument)
647 #if DEBUG
648 Console.WriteLine("Receive_internal, jSocketChannel.finishConnect return false");
649 #endif
650 return 0;
653 else if (!jSocketChannel.isConnected())
655 error = 10057; //WSAENOTCONN (Socket is not connected)
656 return ret;
659 java.nio.ByteBuffer readBuff = java.nio.ByteBuffer.wrap(vmw.common.TypeUtils.ToSByteArray(buffer), offset, count);
660 ret = jSocketChannel.read(readBuff);
661 if (ret < 0) ret = 0;
663 catch (Exception e)
665 error = 10054; //WSAECONNRESET (Connection reset by peer)
666 ret = 0;
667 #if DEBUG
668 Console.WriteLine("Caught exception during Receive_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
669 #endif
672 if (ret == 0 && !jSocketChannel.isBlocking())
674 error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable)
676 return ret;
679 public int RecvFrom_internal(byte[] buffer, int offset, int count, SocketFlags flags,
680 ref SocketAddress sockaddr, out int error)
682 return Receive_internal(buffer, offset, count, flags, out error);
685 public int Send_internal(byte[] buf, int offset, int count, SocketFlags flags,
686 out int error)
688 error = 0;
689 int ret = 0;
691 if (jSocket == null)
693 error = 10057; //WSAENOTCONN (Socket is not connected)
694 return ret;
699 if (jSocketChannel.isConnectionPending())
701 bool status = jSocketChannel.finishConnect();
702 if (!status)
704 error = 10022; //WSAEINVAL (Invalid argument)
705 #if DEBUG
706 Console.WriteLine("Send_internal, jSocketChannel.finishConnect return false");
707 #endif
708 return 0;
711 else if (!jSocketChannel.isConnected())
713 error = 10057; //WSAENOTCONN (Socket is not connected)
714 return ret;
717 java.nio.ByteBuffer writeBuff = java.nio.ByteBuffer.wrap(vmw.common.TypeUtils.ToSByteArray(buf), offset, count);
718 ret = jSocketChannel.write(writeBuff);
719 if (ret < 0) ret = 0;
721 catch (Exception e)
723 error = 10054; //WSAECONNRESET (Connection reset by peer)
724 ret = 0;
725 #if DEBUG
726 Console.WriteLine("Caught exception during Send_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
727 #endif
730 if (ret == 0 && !jSocketChannel.isBlocking())
732 error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable)
734 return ret;
737 public int SendTo_internal(byte[] buffer, int offset, int count,
738 SocketFlags flags, SocketAddress sa, out int error)
740 return Send_internal(buffer, offset, count, flags, out error);
743 public void SetSocketOption_internal (SocketOptionLevel level,
744 SocketOptionName name, object obj_val,
745 byte [] byte_val, int int_val, out int error)
747 error = 0;
749 if (byte_val != null)
751 error = -1;
752 throw new NotImplementedException();
755 if (jSocket == null && jServerSocket == null)
757 error = 10022; //WSAEINVAL (Invalid argument)
758 return;
761 switch (level)
763 case SocketOptionLevel.IPv6:
764 error = 10042; //WSAENOPROTOOPT (Bad protocol option)
765 return;
766 case SocketOptionLevel.IP:
767 if (name != SocketOptionName.NoDelay)
769 error = 10042; //WSAENOPROTOOPT (Bad protocol option)
770 return;
772 break;
773 case SocketOptionLevel.Udp:
774 if (name == SocketOptionName.NoDelay)
776 error = 10042; //WSAENOPROTOOPT (Bad protocol option)
778 else
780 error = 10022; //WSAEINVAL (Invalid argument)
782 return;
783 case SocketOptionLevel.Tcp:
784 if (name != SocketOptionName.NoDelay)
786 error = 10022; //WSAEINVAL (Invalid argument)
787 return;
789 break;
794 bool bval = false;
795 int ival = 0;
796 switch (name)
798 case SocketOptionName.DontLinger:
799 jSocket.setSoLinger(false, 0);
800 break;
801 case SocketOptionName.Linger:
802 LingerOption lval = obj_val as LingerOption;
803 if (lval != null)
805 jSocket.setSoLinger(lval.Enabled, lval.LingerTime);
807 else
809 error = 10022; //WSAEINVAL (Invalid argument)
811 break;
812 case SocketOptionName.KeepAlive:
813 if (obj_val != null)
815 bval = ((int)obj_val == 0)?false:true;
817 else
819 bval = (int_val == 0)?false:true;
821 jSocket.setKeepAlive(bval);
822 break;
823 case SocketOptionName.NoDelay:
824 if (obj_val != null)
826 bval = ((int)obj_val == 0)?false:true;
828 else
830 bval = (int_val == 0)?false:true;
832 jSocket.setTcpNoDelay(bval);
833 break;
834 case SocketOptionName.ReceiveBuffer:
835 ival = int_val;
836 if (obj_val != null)
838 ival = (int) obj_val;
840 if (jServerSocket != null)
842 jServerSocket.setReceiveBufferSize(ival);
844 else
846 jSocket.setReceiveBufferSize(ival);
848 break;
849 case SocketOptionName.ReceiveTimeout:
850 ival = int_val;
851 if (obj_val != null)
853 ival = (int) obj_val;
855 if (jServerSocket != null)
857 jServerSocket.setSoTimeout(ival);
859 else
861 jSocket.setSoTimeout(ival);
863 break;
864 case SocketOptionName.ReuseAddress:
865 if (obj_val != null)
867 bval = ((int)obj_val == 0)?false:true;
869 else
871 bval = (int_val == 0)?false:true;
873 if (jServerSocket != null)
875 jServerSocket.setReuseAddress(bval);
877 else
879 jSocket.setReuseAddress(bval);
881 break;
882 case SocketOptionName.SendBuffer:
883 ival = int_val;
884 if (obj_val != null)
886 ival = (int) obj_val;
888 jSocket.setSendBufferSize(ival);
889 break;
890 case SocketOptionName.OutOfBandInline:
891 if (obj_val != null)
893 bval = ((int)obj_val == 0)?false:true;
895 else
897 bval = (int_val == 0)?false:true;
899 jSocket.setOOBInline(bval);
900 break;
901 default:
902 error = 10022; //WSAEINVAL (Invalid argument)
903 break;
906 catch (Exception e)
908 error = 10022; //WSAEINVAL (Invalid argument)
909 obj_val = null;
913 public void GetSocketOption_obj_internal(SocketOptionLevel level, SocketOptionName name,
914 out object obj_val, out int error)
916 obj_val = null;
917 error = 0;
919 if (jSocket == null && jServerSocket == null)
921 error = 10022; //WSAEINVAL (Invalid argument)
922 return;
925 switch (level)
927 case SocketOptionLevel.IPv6:
928 error = 10042; //WSAENOPROTOOPT (Bad protocol option)
929 return;
930 case SocketOptionLevel.IP:
931 if (name != SocketOptionName.NoDelay)
933 error = 10042; //WSAENOPROTOOPT (Bad protocol option)
934 return;
936 break;
937 case SocketOptionLevel.Udp:
938 if (name == SocketOptionName.NoDelay)
940 error = 10042; //WSAENOPROTOOPT (Bad protocol option)
942 else
944 error = 10022; //WSAEINVAL (Invalid argument)
946 return;
947 case SocketOptionLevel.Tcp:
948 if (name != SocketOptionName.NoDelay)
950 error = 10022; //WSAEINVAL (Invalid argument)
951 return;
953 break;
958 bool bval = false;
959 int ival = 0;
960 switch (name)
962 case SocketOptionName.DontLinger:
963 ival = jSocket.getSoLinger();
964 if (ival == -1)
966 obj_val = 1;
968 else
970 obj_val = 0;
972 break;
973 case SocketOptionName.Linger:
974 ival = jSocket.getSoLinger();
975 if (ival == -1)
977 ival = 0;
979 LingerOption ret = new LingerOption((ival != 0), ival);
980 obj_val = ret;
981 break;
982 case SocketOptionName.KeepAlive:
983 bval = jSocket.getKeepAlive();
984 obj_val = ((bval)?1:0);
985 break;
986 case SocketOptionName.NoDelay:
987 bval = jSocket.getTcpNoDelay();
988 obj_val = ((bval)?1:0);
989 break;
990 case SocketOptionName.ReceiveBuffer:
991 if (jServerSocket != null)
993 ival = jServerSocket.getReceiveBufferSize();
995 else
997 ival = jSocket.getReceiveBufferSize();
999 obj_val = ival;
1000 break;
1001 case SocketOptionName.ReceiveTimeout:
1002 if (jServerSocket != null)
1004 ival = jServerSocket.getSoTimeout();
1006 else
1008 ival = jSocket.getSoTimeout();
1010 obj_val = ival;
1011 break;
1012 case SocketOptionName.ReuseAddress:
1013 if (jServerSocket != null)
1015 bval = jServerSocket.getReuseAddress();
1017 else
1019 bval = jSocket.getReuseAddress();
1021 obj_val = ((bval)?1:0);
1022 break;
1023 case SocketOptionName.SendBuffer:
1024 ival = jSocket.getSendBufferSize();
1025 obj_val = ival;
1026 break;
1027 case SocketOptionName.OutOfBandInline:
1028 bval = jSocket.getOOBInline();
1029 obj_val = ((bval)?1:0);
1030 break;
1031 default:
1032 error = 10022; //WSAEINVAL (Invalid argument)
1033 break;
1036 catch (Exception e)
1038 error = 10022; //WSAEINVAL (Invalid argument)
1039 obj_val = null;
1043 public void GetSocketOption_arr_internal(SocketOptionLevel level, SocketOptionName name,
1044 ref byte[] byte_val, out int error)
1046 error = -1;
1047 throw new NotImplementedException();
1050 public int WSAIoctl (int ioctl_code, byte [] input, byte [] output, out int error)
1052 error = -1;
1053 throw new NotImplementedException();
1056 public void Shutdown_internal(SocketShutdown how, out int error)
1058 error = 0;
1060 if (jServerSocket != null || jSocket == null || !jSocket.isConnected())
1062 error = 10057; //WSAENOTCONN (Socket is not connected)
1063 return;
1068 switch (how)
1070 case SocketShutdown.Receive:
1071 jSocket.shutdownInput();
1072 break;
1073 case SocketShutdown.Send:
1074 jSocket.shutdownOutput();
1075 break;
1076 case SocketShutdown.Both:
1077 jSocket.shutdownInput();
1078 jSocket.shutdownOutput();
1079 break;
1082 catch (Exception e)
1084 error = 10022; //WSAEINVAL (Invalid argument)
1085 #if DEBUG
1086 Console.WriteLine("Caught exception during Shutdown_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace);
1087 #endif
1091 private java.io.FileInputStream searchDefaultCacerts()
1095 string javaHome = java.lang.System.getProperty("java.home");
1096 if(javaHome == null)
1097 return null;
1099 string keyStorePath = javaHome + "/lib/security/cacerts";
1100 //Console.WriteLine("keyStorePath = {0}", keyStorePath);
1102 java.io.File f = new java.io.File(keyStorePath);
1103 if(!f.exists())
1104 return null;
1105 return new java.io.FileInputStream(f);
1107 catch(Exception e)
1109 #if DEBUG
1110 //todo log it
1111 Console.WriteLine(e.GetType() + ":" + e.Message + "\n" + e.StackTrace);
1112 #endif
1113 return null;
1117 private SSLSocketFactory getSSLSocketFactory()
1119 SSLSocketFactory factory = null;
1123 //reading the keyStore path and password from the environment properties
1124 string keyStorePath = java.lang.System.getProperty("javax.net.ssl.keyStore");
1125 java.io.FileInputStream keyStoreStream = null;
1126 if (keyStorePath != null)
1128 java.io.File file = new java.io.File(keyStorePath);
1129 if(file.exists())
1130 keyStoreStream = new java.io.FileInputStream(file);
1131 else
1132 keyStoreStream = searchDefaultCacerts();
1134 else
1135 keyStoreStream = searchDefaultCacerts();
1137 string keyStorePassWord = java.lang.System.getProperty("javax.net.ssl.keyStorePassword");
1138 if (keyStorePassWord == null)
1139 keyStorePassWord = "changeit";
1140 char[] passphrase = keyStorePassWord.ToCharArray();
1142 //initiating SSLContext
1143 SSLContext ctx = SSLContext.getInstance("TLS");
1144 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
1145 TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
1146 KeyStore ks = KeyStore.getInstance("JKS");
1147 if (keyStoreStream != null)
1148 ks.load(keyStoreStream,passphrase);
1149 else
1150 ks.load(null,null);
1151 kmf.init(ks, passphrase);
1152 tmf.init(ks);
1153 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
1155 factory = ctx.getSocketFactory();
1157 catch (Exception e)
1159 factory = null;
1160 #if DEBUG
1161 Console.WriteLine("Can't get SSL Socket Factory, the exception is {0}, {1}", e.GetType(), e.Message);
1162 #endif
1165 return factory;
1168 public GHSocket ChangeToSSL(EndPoint remote_end)
1170 if (jSocket == null)
1172 throw new InvalidOperationException("The underlying socket is null");
1175 if (!jSocketChannel.isBlocking())
1177 throw new NotImplementedException("The SSL Socket for non-blocking mode is not supported");
1180 SSLSocketFactory factory = getSSLSocketFactory();
1181 if (factory == null)
1183 throw new ApplicationException("Can't get SSL Socket Factory");
1186 int err;
1188 // The problem with local address, when I closed the socket and try to create the new one
1189 // bounded to the given local address, I receive exception "Address already in use"
1190 IPEndPoint localEndPoint = null;
1191 // IPEndPoint localEndPoint = (IPEndPoint) LocalEndPoint_internal(out err);
1192 // if (err != 0)
1193 // localEndPoint = null;
1195 IPEndPoint remoteEndPoint = remote_end as IPEndPoint;
1196 if (remoteEndPoint == null)
1198 remoteEndPoint = (IPEndPoint) RemoteEndPoint_internal(out err);
1199 if (err != 0)
1200 remoteEndPoint = null;
1203 java.net.Socket sslSocket = null;
1206 if (remoteEndPoint != null)
1208 if (localEndPoint != null)
1210 sslSocket = factory.createSocket(
1211 java.net.InetAddress.getByName(remoteEndPoint.Address.ToString()),
1212 remoteEndPoint.Port,
1213 java.net.InetAddress.getByName(localEndPoint.Address.ToString()),
1214 localEndPoint.Port);
1216 else
1218 sslSocket = factory.createSocket(
1219 jSocket,
1220 remoteEndPoint.Address.ToString(),
1221 remoteEndPoint.Port,
1222 false);
1225 if (sslSocket != null)
1227 String[] protocols = { "TLSv1", "SSLv3" };
1228 ((SSLSocket)sslSocket).setUseClientMode(true);
1229 ((SSLSocket)sslSocket).startHandshake();
1233 else
1235 sslSocket = factory.createSocket();
1238 catch (Exception e)
1240 sslSocket = null;
1241 #if DEBUG
1242 Console.WriteLine("Can't create SSL Socket, the exception is {0}, {1}", e.GetType(), e.Message);
1243 #endif
1246 if (sslSocket == null)
1248 // throw new ApplicationException("Can't create SSL Socket");
1249 // it is important to the Socket class to distinguish if the underlying
1250 // handle (GHSocket) is still valid and can be used as non-SSL, or it is already
1251 // closed by this function and can't be used any more.
1252 return null;
1256 string[] arr = ((SSLSocket)sslSocket).getEnabledProtocols();
1257 if (arr != null)
1259 foreach (string s in arr)
1260 Console.WriteLine("s:"+s);
1262 string [] arr1 = ((SSLSocket)sslSocket).getEnabledCipherSuites();
1263 if (arr1 != null)
1265 foreach (string s in arr1)
1266 Console.WriteLine("s:"+s);
1270 return new GHStreamSocketSSL(sslSocket);