gt: 				if (readBytes != waitForBytes){
context: /*
   * This file is part of SecureDataSocket
   * Copyright (C) 2017 Jakob Bode and Matthias Sekul
   *
   * SecureDataSocket is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * SecureDataSocket is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with SecureDataSocket.  If not, see <http://www.gnu.org/licenses/>
   */
  
  package com.cryptolib;
  
  import org.bouncycastle.util.encoders.Base64;
  
  //import java.lang.IllegalArgumentException;
  import java.lang.IllegalStateException;
  import java.net.SocketTimeoutException;
  import java.io.IOException;
  import java.io.*;
  import java.net.ServerSocket;
  import java.net.Socket;
  import java.net.InetSocketAddress;
  import java.net.SocketAddress;
  import java.util.concurrent.TimeUnit;
  import java.security.InvalidKeyException;
  import java.security.NoSuchAlgorithmException;
  import javax.crypto.IllegalBlockSizeException;
  import java.security.SecureRandom;
  
  public class CryptoSocket implements CryptoSocketInterface {
  		private Channel channel = null;
  		private ServerSocket server = null;
  		private Socket socket = null;
  		private OutputStream out = null;
  		private InputStream in = null;
  		private CryptoObject cobject = null;
  		private boolean verified = false;
  		private boolean connected = false;
  		private boolean running = false;
  
  		/**
  		* Constructor.
  		* channel defines the interface, which will be used for the 
  		* sharedsecretexchange.
  		* If you call listen() afterwards, connections from the given
  		* destination are accepted.
  		* If you otherwise call connect() afterwards, the other device will be 
  		* searched in the localnetwork via broadcast and when found, a 
  		* connection will be set up.
  		*/
  		//public CryptoSocket(Channel channel){
  		//	this.channel = channel;
  		//}
  
  		/**
  		* Constructor.
  		* channel defines the interface, which will be used for the 
  		* sharedsecretexchange.
  		* If you call listen() afterwards, only connections from the given
  		* destination are accepted.
  		* If you otherwise call connect() afterwards, you will connect to the
  		* given destination.
  		*/
  		public CryptoSocket(Channel channel){
  			this.channel = channel;
  		}
  
  		public SocketAddress listen(int port) throws IOException, SocketTimeoutException, CryptoSocketException {
  			if (this.channel.type == ChannelType.WLAN){
  				this.server = new ServerSocket(port);
  				this.running = true;
  				while (this.running){
  					this.createCryptoObject();
  					while (this.running){
  						this.socket = this.server.accept();
  
  						if (!(this.channel.id.equals("") || this.channel.id.equals(":") || this.channel.id.equals("::")) && !this.channel.id.equals(socket.getRemoteSocketAddress().toString())){
  							socket.close();
  							continue;
  						}
  
  						break;
  					}
  
  					//System.out.println("Begin crypto protocol..");
  					// begin crypto protocol
  					this.out = this.socket.getOutputStream();
  					this.in = this.socket.getInputStream();
  
  					if (!this.setup()){
  						continue;
  					}
  
  					if (!this.exchange(false)){
  						continue;
  					}
  
  					this.connected = true;
  					break;
  				}
  
  				return this.socket.getRemoteSocketAddress();
  			}
  			if (this.channel.type == ChannelType.MANUAL) {
  				if (!this.verified) {
  					throw new CryptoSocketException("call setSharedSecret or createSharedSecret before listen, if the ChannelType MANUAL is used.");
  				}
  				else {	
  					this.server = new ServerSocket(port);
  					this.running = true;
  					while (this.running){
  						this.socket = this.server.accept();
  
  						if (!(this.channel.id.equals("") || this.channel.id.equals(":") || this.channel.id.equals("::")) && !this.channel.id.equals(socket.getRemoteSocketAddress().toString())){
  							socket.close();
  							continue;
  						}
  
  						break;
  					}
  
  					//System.out.println("Begin crypto protocol..");
  					// begin crypto protocol
  					this.out = this.socket.getOutputStream();
  					this.in = this.socket.getInputStream();
  					this.connected = true;
  					//check if the same sharedSecret was used
  					byte[] check = new byte[1];
  					new SecureRandom().nextBytes(check);
  
  					try{
  						this.write(check);
  					} catch(UnverifiedException e){
  						throw new CryptoSocketException("impossible Error while sharedSecret check");
  					}
  
  					byte[] ans = new byte[1];
  					this.read(true, ans);
  					byte[] check2 = new byte[1];
  					this.read(true, check2);
  					check2[0] += 1;
  
  					try{
  						this.write(check2);
  					} catch(UnverifiedException e){
  						throw new CryptoSocketException("impossible Error while sharedSecret check");
  					}
  
  					if (check[0]+1 != ans[0]) {
  						this.connected = false;
  						throw new CryptoSocketException("not the same sharedSecret is used. maybe the wrong device connected to you");
  					}
  
  					return this.socket.getRemoteSocketAddress();
  				}
  			}
  			return null;
  		}
  
  		public boolean connect() throws CryptoSocketException, IOException, SocketTimeoutException {
  			if (this.channel.type == ChannelType.WLAN){
  				this.createCryptoObject();
  
  				if (!this.channel.id.equals("")){
  					String tmp = new StringBuilder(this.channel.id).reverse().toString();
  
  					if (!tmp.contains(":")){
  						throw new CryptoSocketException("for a WLAN channel the identifier needs to be ip port combination e.g. 127.0.0.1:1337 or ::1:4711");
  					}
  
  					String[] stringParts = tmp.split(":", 2);
  
  
  					if (2 != stringParts.length){
  						throw new CryptoSocketException("for a WLAN channel the identifier needs to be ip port combination e.g. 127.0.0.1:1337 or ::1:4711");
  					}
  
  					stringParts[0] = new StringBuilder(stringParts[0]).reverse().toString();
  					stringParts[1] = new StringBuilder(stringParts[1]).reverse().toString();
  					String serveraddress = stringParts[1];
  					String port = stringParts[0];
  					InetSocketAddress address = null;
  
  					try {
  						address = new InetSocketAddress(serveraddress, Integer.parseInt(port));
  					} catch (Exception e) {
  						throw new CryptoSocketException("for a WLAN channel the identifier needs to be ip port combination e.g. 127.0.0.1:1337 or ::1:4711");
  					}
  
  					this.socket = new Socket(address.getHostString(), address.getPort());
  				} else {
  					//Search server via broadcast
  					//TODO implement
  					//while not implemented throw Exception
  					throw new CryptoSocketException("Serversearch via broadcast is not implemented at the Moment.");
  				}
  
  				// begin crypto protocol
  				//System.out.println("Begin crypto protocol..");
  				this.out = this.socket.getOutputStream();
  				this.in = this.socket.getInputStream();
  				if (!this.setup()){
  					return false;
  				}
  
  				if (!this.exchange(true)){
  					return false;
  				}
  
  				this.connected = true;
  				return true;
  			}
  			if (this.channel.type == ChannelType.MANUAL) {
  				if (!this.channel.id.equals("")){
  					String tmp = new StringBuilder(this.channel.id).reverse().toString();
  
  					if (!tmp.contains(":")){
  						throw new CryptoSocketException("for a MANUAL channel the identifier needs to be ip-port-sharedsecret combination e.g. 127.0.0.1:1337:mySharedSecretMySharedSecret1234 or ::1:4711:mySharedSecretMySharedSecret1234");
  					}
  
  					String[] stringParts = tmp.split(":", 3);
  
  
  					if (3 != stringParts.length){
  						throw new CryptoSocketException("for a MANUAL channel the identifier needs to be ip-port-sharedsecret combination e.g. 127.0.0.1:1337:mySharedSecretMySharedSecret1234 or ::1:4711:mySharedSecretMySharedSecret1234");
  					}
  
  					stringParts[0] = new StringBuilder(stringParts[0]).reverse().toString();
  					stringParts[1] = new StringBuilder(stringParts[1]).reverse().toString();
  					stringParts[2] = new StringBuilder(stringParts[2]).reverse().toString();
  					this.setSharedSecret(stringParts[0]);
  					String serveraddress = stringParts[2];
  					String port = stringParts[1];
  					InetSocketAddress address = null;
  
  					try {
  						address = new InetSocketAddress(serveraddress, Integer.parseInt(port));
  					} catch (Exception e) {
  						throw new CryptoSocketException("for a MANUAL channel the identifier needs to be ip-port-sharedsecret combination e.g. 127.0.0.1:1337:mySharedSecretMySharedSecret1234 or ::1:4711:mySharedSecretMySharedSecret1234");
  					}
  
  					this.socket = new Socket(address.getHostString(), address.getPort());
  				} else {
  					throw new CryptoSocketException("for a MANUAL channel the identifier needs to be ip-port-sharedsecret combination e.g. 127.0.0.1:1337:mySharedSecretMySharedSecret1234 or ::1:4711:mySharedSecretMySharedSecret1234");
  				}
  
  				// begin crypto protocol
  				//System.out.println("Begin crypto protocol..");
  				this.out = this.socket.getOutputStream();
  				this.in = this.socket.getInputStream();
  				this.connected = true;
  				//check if the same sharedSecret was used
  				byte[] check = new byte[1];
  				this.read(true, check);
  				check[0] += 1;
  				try{
  					this.write(check);
  				}
  				catch(UnverifiedException e){	
  					throw new CryptoSocketException("impossible Error while sharedSecret check");
  				}
  				check = new byte[1];
  				new SecureRandom().nextBytes(check);
  				try{
  					this.write(check);
  				}
  				catch(UnverifiedException e){	
  					throw new CryptoSocketException("impossible Error while sharedSecret check");
  				}
  				byte[] ans = new byte[1];
  				this.read(true, ans);
  				if (ans[0] != check[0]+1){
  					this.connected = false;
  					throw new CryptoSocketException("not the same sharedSecret is used. maybe you connected to the wrong device");
  				}
  				return true;
  			}
  			return false;
  		}
  
  		private boolean setup() throws IOException{
  			boolean sentAck = false;
  			boolean receivedAck = false;
  			byte [] data = "Ready".getBytes();
  			byte [] read = null;
  			this.out.write(data);
  			this.out.flush();
  			int readBytes = 0;
  			int sleepSecond = 0;
  			int waitForBytes = 5;
  			while (sleepSecond < 300){
  
  				if (waitForBytes > this.in.available()){
  					try {
  						TimeUnit.SECONDS.sleep(1);
  					} catch(InterruptedException ie){
  						return false;
  					}
  
  					sleepSecond = sleepSecond + 1;
  					continue;
  				}
  
  				read = new byte[waitForBytes];
  				readBytes = this.in.read(read);
  
  