using java.nio.channels; using java.security; using javax.net.ssl; namespace System.Net.Sockets { /// /// Summary description for GHStreamSocket. /// internal class GHStreamSocket : GHSocket { java.net.ServerSocket jServerSocket; java.net.Socket jSocket; java.nio.channels.ServerSocketChannel jServerSocketChannel; java.nio.channels.SocketChannel jSocketChannel; // This field I need because a bug in the java.nio.channels.SocketAdapter, which // returns local port 0 if the socket is not connected (even if the socket is bound) // so I need temporary use regular socket (not channel socket) to bind it to the // local address and use this address in the LocalPoint property and to create the // actual client/server channel sockets // The bug #5076965 (SocketChannel does not report local address after binding to a wildcard ) // See: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5076965 java.net.InetSocketAddress jTempLocalSocketAddress; public GHStreamSocket() { jSocketChannel = java.nio.channels.SocketChannel.open(); jSocket = jSocketChannel.socket(); } public GHStreamSocket(java.nio.channels.SocketChannel socketChannel) { jSocketChannel = socketChannel; jSocket = jSocketChannel.socket(); } public override int GetHashCode () { if (jSocket == null && jServerSocket == null) return -1; if (jServerSocket != null) { return jServerSocket.ToString ().GetHashCode (); } return jSocket.ToString ().GetHashCode (); } public int Available_internal(out int error) { error = 0; int r = 0; if (jSocket == null || !jSocket.isConnected()) { return r; } try { r = jSocket.getInputStream().available(); } catch (Exception e) { error = 10054; //WSAECONNRESET (Connection reset by peer) r = 0; #if DEBUG Console.WriteLine("Caught exception during Available_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } return r; } public void Blocking_internal(bool block, out int error) { error = 0; if (jSocket == null && jServerSocket == null) { error = 10022; //WSAEINVAL (Invalid argument) return; } try { if (jServerSocket != null) { jServerSocketChannel.configureBlocking(block); } else { jSocketChannel.configureBlocking(block); } } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Caught exception during Blocking_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } } public EndPoint LocalEndPoint_internal(out int error) { error = 0; java.net.InetSocketAddress localAddr = null; try { if (jTempLocalSocketAddress != null) { localAddr = jTempLocalSocketAddress; } else if (jServerSocket != null) { localAddr = (java.net.InetSocketAddress)jServerSocket.getLocalSocketAddress(); } else { localAddr = (java.net.InetSocketAddress)jSocket.getLocalSocketAddress(); } } catch (Exception e) { localAddr = null; #if DEBUG Console.WriteLine("Caught exception during LocalEndPoint_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } if (localAddr == null || localAddr.getAddress() == null || localAddr.getPort() < 0) { return null; } IPHostEntry lipa = Dns.Resolve(localAddr.getHostName()); IPEndPoint ret = new IPEndPoint(lipa.AddressList[0], localAddr.getPort()); return ret; } public EndPoint RemoteEndPoint_internal(out int error) { error = 0; java.net.InetSocketAddress remoteAddr = null; if (jSocket == null || !jSocket.isBound()) { return null; } try { remoteAddr = (java.net.InetSocketAddress)jSocket.getRemoteSocketAddress(); } catch (Exception e) { remoteAddr = null; #if DEBUG Console.WriteLine("Caught exception during RemoteEndPoint_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } if (remoteAddr == null || remoteAddr.getAddress() == null || remoteAddr.getPort() <= 0) { error = 10057; //WSAENOTCONN (Socket is not connected) return null; } IPHostEntry lipa = Dns.Resolve(remoteAddr.getHostName()); IPEndPoint ret = new IPEndPoint(lipa.AddressList[0], remoteAddr.getPort()); return ret; } public GHSocket Accept_internal(out int error) { error = 0; if (jServerSocket == null) { throw new InvalidOperationException("You must call Bind and Listen before calling Accept."); } try { /* If this channel is in non-blocking mode then this method will immediately return null if there are no pending connections. Otherwise it will block indefinitely until a new connection is available or an I/O error occurs. */ java.nio.channels.SocketChannel acceptedSocket = jServerSocketChannel.accept(); if (acceptedSocket == null) { error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable) #if DEBUG Console.WriteLine("The Accept_internal is in non-blocking mode and no pending connections are available"); #endif return null; } return new GHStreamSocket(acceptedSocket); } catch (AsynchronousCloseException) { error = 10004; } catch (Exception e) { error = 10061; //WSAECONNREFUSED (Connection refused) #if DEBUG Console.WriteLine("Caught exception during Accept_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } return null; } public void Bind_internal(EndPoint sa, out int error) { error = 0; IPEndPoint addr = sa as IPEndPoint; if (addr == null) { error = 10044; //WSAESOCKTNOSUPPORT (Socket type not supported) return; } if (jSocket == null || jSocket.isBound() || jSocket.isConnected() || jSocketChannel.isConnectionPending()) { error = 10022; //WSAEINVAL (Invalid argument) return; } try { // This code I need because a bug in the java.nio.channels.SocketAdapter, which // returns local port 0 if the socket is not connected (even if the socket is bound) // so I need temporary use regular socket (not channel socket) to bind it to the // local address and use this address in the LocalPoint property and to create the // actual client/server channel sockets // The bug #5076965 (SocketChannel does not report local address after binding to a wildcard ) // See: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5076965 java.net.Socket jTempSocket = new java.net.Socket(); jTempSocket.bind(new java.net.InetSocketAddress(java.net.InetAddress.getByName(addr.Address.ToString()), addr.Port)); jTempLocalSocketAddress = (java.net.InetSocketAddress)jTempSocket.getLocalSocketAddress(); jTempSocket.close(); jSocket.bind(jTempLocalSocketAddress); } catch (Exception e) { error = 10048; //WSAEADDRINUSE (Address already in use) #if DEBUG Console.WriteLine("Caught exception during Bind_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } } public void Close_internal(out int error) { error = 0; if (jServerSocket != null) { try { jServerSocket.close(); } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Caught exception during Close_internal jServerSocket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } try { jServerSocketChannel.close(); } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Caught exception during Close_internal jServerSocketChannel - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } jServerSocket = null; jServerSocketChannel = null; } else if (jSocket != null) { try { jSocket.close(); } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Caught exception during Close_internal jSocket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } try { jSocketChannel.close(); } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Caught exception during Close_internal jSocketChannel - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } jSocket = null; jSocketChannel = null; } } public void Connect_internal(EndPoint sa, out int error) { error = 0; IPEndPoint addr = sa as IPEndPoint; if (addr == null) { error = 10044; //WSAESOCKTNOSUPPORT (Socket type not supported) return; } if (jSocket == null) { error = 10022; //WSAEINVAL (Invalid argument) return; } if (jSocket.isConnected() || jSocketChannel.isConnectionPending()) { error = 10056; //WSAEISCONN (Socket is already connected) return; } try { /* If this channel is in non-blocking mode then an invocation of this method initiates a non-blocking connection operation. If the connection is established immediately, as can happen with a local connection, then this method returns true. Otherwise this method returns false. If this channel is in blocking mode then an invocation of this method will block until the connection is established or an I/O error occurs. */ bool status = jSocketChannel.connect(new java.net.InetSocketAddress( java.net.InetAddress.getByName(addr.Address.ToString()), addr.Port)); if (!status) { error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable) } } catch (java.nio.channels.AlreadyConnectedException ae) { error = 10056; //WSAEISCONN (Socket is already connected) } catch (java.nio.channels.ConnectionPendingException cpe) { error = 10036; //WSAEINPROGRESS (Operation now in progress) } catch (java.nio.channels.UnresolvedAddressException uae) { error = 10039; //WSAEDESTADDRREQ (Destination address required) } catch (java.nio.channels.UnsupportedAddressTypeException uate) { error = 10041; //WSAEPROTOTYPE (Protocol wrong type for socket) } catch (AsynchronousCloseException) { error = 10004; } catch (Exception e) { error = 10061; //WSAECONNREFUSED (Connection refused) #if DEBUG Console.WriteLine("Caught exception during Connect_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } } public void Listen_internal(int backlog, out int error) { error = 0; if (jSocket == null || !jSocket.isBound()) { error = 10022; //WSAEINVAL (Invalid argument) return; } if (jSocket.isConnected() || jSocketChannel.isConnectionPending()) { error = 10056; //WSAEISCONN (Socket is already connected) return; } bool blockMode = jSocketChannel.isBlocking(); bool reuseAddr = jSocket.getReuseAddress(); try { jSocket.close(); } catch (Exception e) { #if DEBUG Console.WriteLine("Caught exception during Listen_internal close old jSocket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } try { jSocketChannel.close(); } catch (Exception e) { #if DEBUG Console.WriteLine("Caught exception during Listen_internal close old jSocketChannel - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } jSocket = null; jSocketChannel = null; try { jServerSocketChannel = java.nio.channels.ServerSocketChannel.open(); jServerSocket = jServerSocketChannel.socket(); jServerSocket.bind(jTempLocalSocketAddress, backlog); jServerSocketChannel.configureBlocking(blockMode); jServerSocket.setReuseAddress(reuseAddr); } catch (Exception e) { error = 10048; //WSAEADDRINUSE (Address already in use) #if DEBUG Console.WriteLine("Caught exception during Listen_internal create server socket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } } public bool Poll_internal (SelectMode mode, int timeout, Socket source, out int error) { error = 0; if (mode == SelectMode.SelectError && !jSocketChannel.isConnectionPending()) { return false; } java.nio.channels.Selector selector = java.nio.channels.Selector.open(); RegisterSelector(selector, ((mode == SelectMode.SelectRead)?0:1), source, out error); if (error != 0) { error = 0; GHSocketFactory.CloseSelector(selector); return (mode == SelectMode.SelectError); } bool retVal = false; long timeOutMillis = 1; if (timeout < 0) { timeOutMillis = 0; } else if (timeout > 999) { timeOutMillis = (long)(timeout / 1000); } int readyCount = 0; try { readyCount = selector.select(timeOutMillis); } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Caught exception during Poll_internal selector.select - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } if (readyCount > 0) { if (jSocket != null && jSocketChannel.isConnectionPending()) { bool status = false; try { status = jSocketChannel.finishConnect(); } catch (Exception e) { #if DEBUG Console.WriteLine("Caught exception during Poll_internal, finishConnect - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } if (status) { retVal = (mode != SelectMode.SelectError); } else { retVal = (mode == SelectMode.SelectError); } } else { retVal = true; } } GHSocketFactory.CloseSelector(selector); return retVal; } public void RegisterSelector(java.nio.channels.Selector selector, int mode, Socket source, out int error) { error = 0; if (jServerSocket != null) { // only accept operation, which included to the read list, is allowed for server sockets if (mode != 0) { // error = 10038; //WSAENOTSOCK (Socket operation on nonsocket) #if DEBUG Console.WriteLine("RegisterSelector, invalid mode {0} for the server socket", mode); #endif return; } try { if (jServerSocketChannel.isBlocking()) { /* A channel must be placed into non-blocking mode before being registered with a selector, and may not be returned to blocking mode until it has been deregistered. */ jServerSocketChannel.configureBlocking(false); } jServerSocketChannel.register(selector, java.nio.channels.SelectionKey.OP_ACCEPT, source); } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Caught exception during RegisterSelector, register server socket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } } else { try { int ops = java.nio.channels.SelectionKey.OP_READ; if (mode > 0) { if (jSocketChannel.isConnectionPending()) { ops = java.nio.channels.SelectionKey.OP_CONNECT; } else { ops = java.nio.channels.SelectionKey.OP_WRITE; } } if (jSocketChannel.isBlocking()) { /* A channel must be placed into non-blocking mode before being registered with a selector, and may not be returned to blocking mode until it has been deregistered. */ jSocketChannel.configureBlocking(false); } jSocketChannel.register(selector, ops, source); } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Caught exception during RegisterSelector, register client socket - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } } } public bool CheckConnectionFinished() { bool status = true; if (jSocket != null && jSocketChannel.isConnectionPending()) { try { status = jSocketChannel.finishConnect(); } catch (Exception e) { status = false; #if DEBUG Console.WriteLine("Caught exception during Poll_internal, finishConnect - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } } return status; } public int Receive_internal(byte[] buffer, int offset, int count, SocketFlags flags, out int error) { error = 0; int ret = 0; if (jSocket == null) { error = 10057; //WSAENOTCONN (Socket is not connected) return ret; } try { if (jSocketChannel.isConnectionPending()) { bool status = jSocketChannel.finishConnect(); if (!status) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Receive_internal, jSocketChannel.finishConnect return false"); #endif return 0; } } else if (!jSocketChannel.isConnected()) { error = 10057; //WSAENOTCONN (Socket is not connected) return ret; } java.nio.ByteBuffer readBuff = java.nio.ByteBuffer.wrap(vmw.common.TypeUtils.ToSByteArray(buffer), offset, count); ret = jSocketChannel.read(readBuff); if (ret < 0) ret = 0; } catch (Exception e) { error = 10054; //WSAECONNRESET (Connection reset by peer) ret = 0; #if DEBUG Console.WriteLine("Caught exception during Receive_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } if (ret == 0 && !jSocketChannel.isBlocking()) { error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable) } return ret; } public int RecvFrom_internal(byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error) { return Receive_internal(buffer, offset, count, flags, out error); } public int Send_internal(byte[] buf, int offset, int count, SocketFlags flags, out int error) { error = 0; int ret = 0; if (jSocket == null) { error = 10057; //WSAENOTCONN (Socket is not connected) return ret; } try { if (jSocketChannel.isConnectionPending()) { bool status = jSocketChannel.finishConnect(); if (!status) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Send_internal, jSocketChannel.finishConnect return false"); #endif return 0; } } else if (!jSocketChannel.isConnected()) { error = 10057; //WSAENOTCONN (Socket is not connected) return ret; } java.nio.ByteBuffer writeBuff = java.nio.ByteBuffer.wrap(vmw.common.TypeUtils.ToSByteArray(buf), offset, count); ret = jSocketChannel.write(writeBuff); if (ret < 0) ret = 0; } catch (Exception e) { error = 10054; //WSAECONNRESET (Connection reset by peer) ret = 0; #if DEBUG Console.WriteLine("Caught exception during Send_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } if (ret == 0 && !jSocketChannel.isBlocking()) { error = 10035; //WSAEWOULDBLOCK (Resource temporarily unavailable) } return ret; } public int SendTo_internal(byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error) { return Send_internal(buffer, offset, count, flags, out error); } public void SetSocketOption_internal (SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error) { error = 0; if (byte_val != null) { error = -1; throw new NotImplementedException(); } if (jSocket == null && jServerSocket == null) { error = 10022; //WSAEINVAL (Invalid argument) return; } switch (level) { case SocketOptionLevel.IPv6: error = 10042; //WSAENOPROTOOPT (Bad protocol option) return; case SocketOptionLevel.IP: if (name != SocketOptionName.NoDelay) { error = 10042; //WSAENOPROTOOPT (Bad protocol option) return; } break; case SocketOptionLevel.Udp: if (name == SocketOptionName.NoDelay) { error = 10042; //WSAENOPROTOOPT (Bad protocol option) } else { error = 10022; //WSAEINVAL (Invalid argument) } return; case SocketOptionLevel.Tcp: if (name != SocketOptionName.NoDelay) { error = 10022; //WSAEINVAL (Invalid argument) return; } break; } try { bool bval = false; int ival = 0; switch (name) { case SocketOptionName.DontLinger: jSocket.setSoLinger(false, 0); break; case SocketOptionName.Linger: LingerOption lval = obj_val as LingerOption; if (lval != null) { jSocket.setSoLinger(lval.Enabled, lval.LingerTime); } else { error = 10022; //WSAEINVAL (Invalid argument) } break; case SocketOptionName.KeepAlive: if (obj_val != null) { bval = ((int)obj_val == 0)?false:true; } else { bval = (int_val == 0)?false:true; } jSocket.setKeepAlive(bval); break; case SocketOptionName.NoDelay: if (obj_val != null) { bval = ((int)obj_val == 0)?false:true; } else { bval = (int_val == 0)?false:true; } jSocket.setTcpNoDelay(bval); break; case SocketOptionName.ReceiveBuffer: ival = int_val; if (obj_val != null) { ival = (int) obj_val; } if (jServerSocket != null) { jServerSocket.setReceiveBufferSize(ival); } else { jSocket.setReceiveBufferSize(ival); } break; case SocketOptionName.ReceiveTimeout: ival = int_val; if (obj_val != null) { ival = (int) obj_val; } if (jServerSocket != null) { jServerSocket.setSoTimeout(ival); } else { jSocket.setSoTimeout(ival); } break; case SocketOptionName.ReuseAddress: if (obj_val != null) { bval = ((int)obj_val == 0)?false:true; } else { bval = (int_val == 0)?false:true; } if (jServerSocket != null) { jServerSocket.setReuseAddress(bval); } else { jSocket.setReuseAddress(bval); } break; case SocketOptionName.SendBuffer: ival = int_val; if (obj_val != null) { ival = (int) obj_val; } jSocket.setSendBufferSize(ival); break; case SocketOptionName.OutOfBandInline: if (obj_val != null) { bval = ((int)obj_val == 0)?false:true; } else { bval = (int_val == 0)?false:true; } jSocket.setOOBInline(bval); break; default: error = 10022; //WSAEINVAL (Invalid argument) break; } } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) obj_val = null; } } public void GetSocketOption_obj_internal(SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error) { obj_val = null; error = 0; if (jSocket == null && jServerSocket == null) { error = 10022; //WSAEINVAL (Invalid argument) return; } switch (level) { case SocketOptionLevel.IPv6: error = 10042; //WSAENOPROTOOPT (Bad protocol option) return; case SocketOptionLevel.IP: if (name != SocketOptionName.NoDelay) { error = 10042; //WSAENOPROTOOPT (Bad protocol option) return; } break; case SocketOptionLevel.Udp: if (name == SocketOptionName.NoDelay) { error = 10042; //WSAENOPROTOOPT (Bad protocol option) } else { error = 10022; //WSAEINVAL (Invalid argument) } return; case SocketOptionLevel.Tcp: if (name != SocketOptionName.NoDelay) { error = 10022; //WSAEINVAL (Invalid argument) return; } break; } try { bool bval = false; int ival = 0; switch (name) { case SocketOptionName.DontLinger: ival = jSocket.getSoLinger(); if (ival == -1) { obj_val = 1; } else { obj_val = 0; } break; case SocketOptionName.Linger: ival = jSocket.getSoLinger(); if (ival == -1) { ival = 0; } LingerOption ret = new LingerOption((ival != 0), ival); obj_val = ret; break; case SocketOptionName.KeepAlive: bval = jSocket.getKeepAlive(); obj_val = ((bval)?1:0); break; case SocketOptionName.NoDelay: bval = jSocket.getTcpNoDelay(); obj_val = ((bval)?1:0); break; case SocketOptionName.ReceiveBuffer: if (jServerSocket != null) { ival = jServerSocket.getReceiveBufferSize(); } else { ival = jSocket.getReceiveBufferSize(); } obj_val = ival; break; case SocketOptionName.ReceiveTimeout: if (jServerSocket != null) { ival = jServerSocket.getSoTimeout(); } else { ival = jSocket.getSoTimeout(); } obj_val = ival; break; case SocketOptionName.ReuseAddress: if (jServerSocket != null) { bval = jServerSocket.getReuseAddress(); } else { bval = jSocket.getReuseAddress(); } obj_val = ((bval)?1:0); break; case SocketOptionName.SendBuffer: ival = jSocket.getSendBufferSize(); obj_val = ival; break; case SocketOptionName.OutOfBandInline: bval = jSocket.getOOBInline(); obj_val = ((bval)?1:0); break; default: error = 10022; //WSAEINVAL (Invalid argument) break; } } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) obj_val = null; } } public void GetSocketOption_arr_internal(SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error) { error = -1; throw new NotImplementedException(); } public int WSAIoctl (int ioctl_code, byte [] input, byte [] output, out int error) { error = -1; throw new NotImplementedException(); } public void Shutdown_internal(SocketShutdown how, out int error) { error = 0; if (jServerSocket != null || jSocket == null || !jSocket.isConnected()) { error = 10057; //WSAENOTCONN (Socket is not connected) return; } try { switch (how) { case SocketShutdown.Receive: jSocket.shutdownInput(); break; case SocketShutdown.Send: jSocket.shutdownOutput(); break; case SocketShutdown.Both: jSocket.shutdownInput(); jSocket.shutdownOutput(); break; } } catch (Exception e) { error = 10022; //WSAEINVAL (Invalid argument) #if DEBUG Console.WriteLine("Caught exception during Shutdown_internal - {0}: {1}\n{2}", e.GetType(), e.Message, e.StackTrace); #endif } } private java.io.FileInputStream searchDefaultCacerts() { try { string javaHome = java.lang.System.getProperty("java.home"); if(javaHome == null) return null; string keyStorePath = javaHome + "/lib/security/cacerts"; //Console.WriteLine("keyStorePath = {0}", keyStorePath); java.io.File f = new java.io.File(keyStorePath); if(!f.exists()) return null; return new java.io.FileInputStream(f); } catch(Exception e) { #if DEBUG //todo log it Console.WriteLine(e.GetType() + ":" + e.Message + "\n" + e.StackTrace); #endif return null; } } private SSLSocketFactory getSSLSocketFactory() { SSLSocketFactory factory = null; try { //reading the keyStore path and password from the environment properties string keyStorePath = java.lang.System.getProperty("javax.net.ssl.keyStore"); java.io.FileInputStream keyStoreStream = null; if (keyStorePath != null) { java.io.File file = new java.io.File(keyStorePath); if(file.exists()) keyStoreStream = new java.io.FileInputStream(file); else keyStoreStream = searchDefaultCacerts(); } else keyStoreStream = searchDefaultCacerts(); string keyStorePassWord = java.lang.System.getProperty("javax.net.ssl.keyStorePassword"); if (keyStorePassWord == null) keyStorePassWord = "changeit"; char[] passphrase = keyStorePassWord.ToCharArray(); //initiating SSLContext SSLContext ctx = SSLContext.getInstance("TLS"); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); KeyStore ks = KeyStore.getInstance("JKS"); if (keyStoreStream != null) ks.load(keyStoreStream,passphrase); else ks.load(null,null); kmf.init(ks, passphrase); tmf.init(ks); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); factory = ctx.getSocketFactory(); } catch (Exception e) { factory = null; #if DEBUG Console.WriteLine("Can't get SSL Socket Factory, the exception is {0}, {1}", e.GetType(), e.Message); #endif } return factory; } public GHSocket ChangeToSSL(EndPoint remote_end) { if (jSocket == null) { throw new InvalidOperationException("The underlying socket is null"); } if (!jSocketChannel.isBlocking()) { throw new NotImplementedException("The SSL Socket for non-blocking mode is not supported"); } SSLSocketFactory factory = getSSLSocketFactory(); if (factory == null) { throw new ApplicationException("Can't get SSL Socket Factory"); } int err; // The problem with local address, when I closed the socket and try to create the new one // bounded to the given local address, I receive exception "Address already in use" IPEndPoint localEndPoint = null; // IPEndPoint localEndPoint = (IPEndPoint) LocalEndPoint_internal(out err); // if (err != 0) // localEndPoint = null; IPEndPoint remoteEndPoint = remote_end as IPEndPoint; if (remoteEndPoint == null) { remoteEndPoint = (IPEndPoint) RemoteEndPoint_internal(out err); if (err != 0) remoteEndPoint = null; } java.net.Socket sslSocket = null; try { if (remoteEndPoint != null) { if (localEndPoint != null) { sslSocket = factory.createSocket( java.net.InetAddress.getByName(remoteEndPoint.Address.ToString()), remoteEndPoint.Port, java.net.InetAddress.getByName(localEndPoint.Address.ToString()), localEndPoint.Port); } else { sslSocket = factory.createSocket( jSocket, remoteEndPoint.Address.ToString(), remoteEndPoint.Port, false); } if (sslSocket != null) { String[] protocols = { "TLSv1", "SSLv3" }; ((SSLSocket)sslSocket).setUseClientMode(true); ((SSLSocket)sslSocket).startHandshake(); } } else { sslSocket = factory.createSocket(); } } catch (Exception e) { sslSocket = null; #if DEBUG Console.WriteLine("Can't create SSL Socket, the exception is {0}, {1}", e.GetType(), e.Message); #endif } if (sslSocket == null) { // throw new ApplicationException("Can't create SSL Socket"); // it is important to the Socket class to distinguish if the underlying // handle (GHSocket) is still valid and can be used as non-SSL, or it is already // closed by this function and can't be used any more. return null; } /* string[] arr = ((SSLSocket)sslSocket).getEnabledProtocols(); if (arr != null) { foreach (string s in arr) Console.WriteLine("s:"+s); } string [] arr1 = ((SSLSocket)sslSocket).getEnabledCipherSuites(); if (arr1 != null) { foreach (string s in arr1) Console.WriteLine("s:"+s); } */ return new GHStreamSocketSSL(sslSocket); } } }