vish4071
vish4071

Reputation: 5287

readLine() does not work properly

I've written a code to implement SSL sockets (server / client) and certificate authentication etc. is being done properly. The code stops when it is trying to read string passed to server by the client. Please help.

This is the file I'm using to create SSLServerSocket:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Random;

import javax.net.ssl.*;

public class Server {

    private String ksname;
    private char kspass[], ctpass[];
    private int port;
    private InetAddress ip;

    public Server(){
        ksname = null;
        kspass = new char[200];
        ctpass = new char[200];
        kspass = null;ctpass = null;
        port = 10000 + (new Random()).nextInt(10000);
        try {
            ip = InetAddress.getByName("127.0.0.1");
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public Server(String cname, String cpass, String pass, int p, String host){
        ksname = cname;
        kspass = new char[200];
        kspass = cpass.toCharArray();
        ctpass = new char[200];
        ctpass = pass.toCharArray();
        port = p;
        try {
            ip = InetAddress.getByName(host);
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public SSLServerSocket getServer(){
        SSLServerSocket s = null;
        try {
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream(ksname), kspass);
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, ctpass);
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(kmf.getKeyManagers(), null, null);
            SSLServerSocketFactory ssf = sc.getServerSocketFactory();
            s = (SSLServerSocket) ssf.createServerSocket(port,0,ip);
            System.out.println("Server created on port " + port +"\n");
        } catch (KeyStoreException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (CertificateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (KeyManagementException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return s;
    }
}

This is the code for the server:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Map;
import java.util.Random;

import javax.net.ssl.*;

public class MServer {

    private SSLSocket c = null;
    private BufferedReader r = null;
    private BufferedWriter w = null;
    private int port = 10579;

    private void execute(){
        Server server = new Server("ppp.jks", "user", "pass", port, "127.0.0.1");
        SSLServerSocket s = server.getServer();
        printServerSocketInfo(s);
        try {
            c = (SSLSocket) s.accept();
            printSocketInfo(c);
            r = new BufferedReader(new InputStreamReader(c.getInputStream()));
            w = new BufferedWriter(new OutputStreamWriter(c.getOutputStream()));

            System.out.println("in m");
            System.out.flush();
            String str = null;
            str = r.readLine();
            System.out.println(str);
            if(str.equals("hi")){
                w.write("Connection OK");
                System.out.println("Connection OK2");
            }

            while((str = r.readLine()) != null){
                if(str.equals("done")){
                    break;
                }
                resolve(str);
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private void resolve(String str){
        //does something
    }

    private void printMessage(int returnValue, int correctReturnValue, String printFor){
        //something
    }

    private static void printSocketInfo(SSLSocket s) {
          System.out.println("Socket class: "+s.getClass());
          System.out.println("   Remote address = "
             +s.getInetAddress().toString());
          System.out.println("   Remote port = "+s.getPort());
          System.out.println("   Local socket address = "
             +s.getLocalSocketAddress().toString());
          System.out.println("   Local address = "
             +s.getLocalAddress().toString());
          System.out.println("   Local port = "+s.getLocalPort());
          System.out.println("   Need client authentication = "
             +s.getNeedClientAuth());
          SSLSession ss = s.getSession();
          System.out.println("   Cipher suite = "+ss.getCipherSuite());
          System.out.println("   Protocol = "+ss.getProtocol());
    }

    private static void printServerSocketInfo(SSLServerSocket s) {
          System.out.println("Server socket class: "+s.getClass());
          System.out.println("   Socket address = "
             +s.getInetAddress().toString());
          System.out.println("   Socket port = "
             +s.getLocalPort());
          System.out.println("   Need client authentication = "
             +s.getNeedClientAuth());
          System.out.println("   Want client authentication = "
             +s.getWantClientAuth());
          System.out.println("   Use client mode = "
             +s.getUseClientMode());
    }

    public static void main(String args[]){
        MServer m = new MServer();
        m.execute();
    }

}

and client:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class ReqResServer {
    private BufferedWriter w1 = null;
    private BufferedWriter w2 = null;
    private BufferedReader r1 = null;
    private BufferedReader r2 = null;
    private SSLSocket c1 = null;
    private SSLSocket c2 = null;
    private int port = 24910;

    public void doClient(){
        SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
        System.out.println("f created");
        try {
            c1 = (SSLSocket) f.createSocket("127.0.0.1", 10579);
            System.out.println("c1 created");
            printSocketInfo(c1);
            c1.startHandshake();
            w1 = new BufferedWriter(new OutputStreamWriter(c1.getOutputStream()));
            r1 = new BufferedReader(new InputStreamReader(c1.getInputStream()));

            w1.write("hi");
            System.out.println("hi");
            String str = r1.readLine();
            System.out.println("before if " + str);
            if(str.equals("Connection OK")){
                //do something
                System.out.println(str);
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private static void printSocketInfo(SSLSocket s) {
        System.out.println("Socket class: "+s.getClass());
        System.out.println("   Remote address = "
           +s.getInetAddress().toString());
        System.out.println("   Remote port = "+s.getPort());
        System.out.println("   Local socket address = "
           +s.getLocalSocketAddress().toString());
        System.out.println("   Local address = "
           +s.getLocalAddress().toString());
        System.out.println("   Local port = "+s.getLocalPort());
        System.out.println("   Need client authentication = "
           +s.getNeedClientAuth());
        SSLSession ss = s.getSession();
        System.out.println("   Cipher suite = "+ss.getCipherSuite());
        System.out.println("   Protocol = "+ss.getProtocol());
    }

    public static void main(String args[]){
        ReqResServer req1 = new ReqResServer();
        req1.doClient();
    }

}

And here is the output: server console:

Server created on port 10579

Server socket class: class sun.security.ssl.SSLServerSocketImpl
Socket address = /127.0.0.1
Socket port = 10579
Need client authentication = false
Want client authentication = false
Use client mode = false
Socket class: class sun.security.ssl.SSLSocketImpl
Remote address = /127.0.0.1
Remote port = 51297
Local socket address = /127.0.0.1:10579
Local address = /127.0.0.1
Local port = 10579
Need client authentication = false
Cipher suite = TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Protocol = TLSv1.2
in m
null

ie. it does not print hi and continue as it should. and client console:

f created
c1 created
Socket class: class sun.security.ssl.SSLSocketImpl
   Remote address = /127.0.0.1
   Remote port = 10579
   Local socket address = /127.0.0.1:51297
   Local address = /127.0.0.1
   Local port = 51297
   Need client authentication = false
   Cipher suite = TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
   Protocol = TLSv1.2
hi

which clearly means w1.write("hi") is being executed.

So, why the code does not continue? I've spent over 3 hours on this and I'm not getting anywhere. Its a bit exhaustive but any help would be appreciated.

Upvotes: 0

Views: 479

Answers (1)

Steffen Ullrich
Steffen Ullrich

Reputation: 123674

First you are using a BufferedWriter which means that anything you write to it might not be flushed immediately. Then you only write hi, that is you write these two characters but not a line end. But you wait for a line end when doing readLine. This functions expects a full line, which includes the line end. It will only return once it receives the line end or the socket gets closed.

Upvotes: 1

Related Questions