Client-Hub handshake & Java

Technical discussion about the NMDC and <a href="http://dcpp.net/ADC.html">ADC</A> protocol. The NMDC protocol is documented in the <a href="http://dcpp.net/wiki/">Wiki</a>, so feel free to refer to it.

Moderator: Moderators

Locked
chrisvoo
Posts: 2
Joined: 2006-03-02 17:04
Location: Italy
Contact:

Client-Hub handshake & Java

Post by chrisvoo » 2006-03-02 18:22

Hi to everybody,I'm new here :)
I'm working to some programs in java to connect to hubsoft and explore DC protocol. I've looked to the wiki and I've already seen the example in java for calculating the key. The problem is: I create the Socket and I receive the standard String with $Lock lock Pk=bla| but then the server seems not to be able to receive my answer...and then,after it has passed 10 seconds,the hub said to me that the answer is arrived to late...
In the code I'll post here,I've tried some variations: after all I tried the version found on the wiki and then I tried mine..
However,in this code I use BufferedReader to wait the response of the server..I've tried to deal only characters and,as soon as I receive the character "|",I send the key but nothing..what's the problem?
Thanks to everubody that spends a few minutes for me.
Have a good day.

Code: Select all

/**
  * Contributed by dCoy (method for calculating the key)
  * @author Chrisvoo
  */
 
import java.net.*;
import java.io.*;

  class getLock {
     public static void main(String[]args){
       
    boolean error=false;
   
          try {
            
             // Sockets and IO channels
           Socket s=new Socket(args[0].toString(),Integer.parseInt(args[1]));
           BufferedReader ego = new BufferedReader(new InputStreamReader(System.in));
           DataOutputStream egout = new DataOutputStream(s.getOutputStream());
           BufferedReader from_server = new BufferedReader(new InputStreamReader(s.getInputStream()));
           
           System.out.println("Connecting...");
           
           /* Ok here method readLine() waits for '\n',but even if I use InputStream
            * and method read() to wait for "|",the server seems not to care about me..*/
           
           String answer=from_server.readLine();
           System.out.println("Server's answered,calculating key...");
           String key=generateKey(answer);
           System.out.println("The $lock sent is: "+answer);
           System.out.println("The key sent is: "+key);
           System.out.println("Let's send the key..");
           egout.writeBytes("$Key <"+key+">|"+"$ValidateNick "+"<ChrisVoo>|\r\n");
           System.out.println("Mandata...");
           answer=from_server.readLine();
           System.out.println(answer);
           egout.writeBytes("$Version <0.68>|$MyINFO <nothing>|$GetNickList|\r\n");
           
           
           
           }catch(UnknownHostException e){
              System.out.println("Host unknown");
           }catch(IOException i){
              System.out.println("Error I/O");
           }catch(ArrayIndexOutOfBoundsException a){
              System.out.println("You have to digit \"java getLock nameOfTheHub port\"");
            }
     }



/* It's pretty copied from wiki */

 public static String generateKey(String lockString){
    int i = 0;
    byte[] lock = null;
    byte[] key = null;

    lockString = lockString.substring(0,lockString.indexOf(' '));
    lockString.trim();
    lock = lockString.getBytes();
    key = new byte[lock.length];

    for(i=1;i<lock.length;i++){
        key[i] = (byte)((lock[i] ^ lock[i-1]) & 0xFF);
    }

    key[0] = (byte)((((lock[0] ^ lock[lock.length-1]) ^ lock[lock.length-2]) ^ 5) & 0xFF);

    for(i=0;i<key.length;i++){
        key[i] = (byte)((((key[i]<<4) & 0xF0) | ((key[i]>>4) & 0x0F)) & 0xFF);
    }

    return(dcnEncode(new String(key)));
}

public static String dcnEncode(String string){
    char[] replacements = null;
    int i = 0;
    int index = 0;

    replacements = new char[]{0,5,36,96,124,126};

    for(i=0;i<replacements.length;i++){
        while((index = string.indexOf(replacements[i])) >=0 ){
            string = string.substring(0,index)
                + "/%DCN"+leadz(replacements[i])+"%/"
                + string.substring(index+1,string.length());
        }
    }

    return(string);
  }



private static String leadz(int nr){
    if(nr < 100 && nr > 10){
        return("0"+nr);
    } else if(nr < 10){
        return("00"+nr);
    } else{
        return(""+nr);
    }
  }
}
   /*this is my version 'cause I noticed that Coy's code takes a only a little part
    of the string sent by the server..
        
         public static String generateKey(String lockString){
                int i = 0;
                byte[] lock = null;
                byte[] key = null;

         //     lockString = lockString.substring(0,lockString.indexOf(' ')); the line above was modified by me
         //     otherwise the method took only "$Lock" to calculate the key
                lockString = lockString.substring(lockString.indexOf(' ')+1,lockString.length()-1);
               lockString = lockString.substring(0,lockString.indexOf(' '));
                lockString.trim();
                lock = lockString.getBytes();
                key = new byte[lock.length];

                for(i=1;i<lock.length;i++){
                        key[i] = (byte)((lock[i] ^ lock[i-1]) & 0xFF);
                }

                key[0] = (byte)((((lock[0] ^ lock[lock.length-1]) ^ lock[lock.length-2]) ^ 5) & 0xFF);

                for(i=0;i<key.length;i++){
                        key[i] = (byte)((((key[i]<<4) & 0xF0) | ((key[i]>>4) & 0x0F)) & 0xFF);
                }

                return(dcnEncode(new String(key)));
        }
        public static String dcnEncode(String string){
                char[] replacements = null;
                int i = 0;
                int index = 0;

                replacements = new char[]{0,5,36,96,124,126};

                for(i=0;i<replacements.length;i++){
                        while((index = string.indexOf(replacements[i])) >=0 ){
                                string = string.substring(0,index) + "/%DCN"+leadz(replacements[i])+"%/" + string.substring(index+1,string.length());
                        }
                }

                return(string);
        }

        private static String leadz(int nr){
                if(nr < 100 && nr > 10){
                        return("0"+nr);
                }
                else if(nr < 10){
                        return("00"+nr);
                }
                else{
                        return(""+nr);
                }
        }
    }   */
Chris

GargoyleMT
DC++ Contributor
Posts: 3212
Joined: 2003-01-07 21:46
Location: .pa.us

Post by GargoyleMT » 2006-03-02 18:38

Does the packet dump of the handshake look right - i.e. the line is being sent, not buffered? You can create a dumb hub on the other side with a fixed Lock to test your client against others...

chrisvoo
Posts: 2
Joined: 2006-03-02 17:04
Location: Italy
Contact:

Post by chrisvoo » 2006-03-03 04:14

Ok I haven't sniffed the traffic between client/server yet,I'll do as I can. Another question: the lock part to be calculated is that after $Lock part,isn't it? I.E.

Server> $Lock ABC Pk=YnHUB The lock is ABC,spaces excluded,isn't it? 'cause if it's like this way,the java code on the wiki seems to take only $Lock
part,not ABC..if someone have tested it,could tell me if I'm right?
Another question: if I send a wrong key the server answer "wrong key" or something like this or only directly disconnects me?
Thanks to all.
Chris

GargoyleMT
DC++ Contributor
Posts: 3212
Joined: 2003-01-07 21:46
Location: .pa.us

Post by GargoyleMT » 2006-03-03 11:44

chrisvoo wrote:The lock is ABC,spaces excluded,isn't it?

I think so. But I only contribute patches to DC++. I've never written a client from scratch.

chrisvoo wrote:if I send a wrong key the server answer "wrong key" or something like this or only directly disconnects me?
Thanks to all.

I suspect that different hubs react differently. Some don't check the Lock. I'm sure others do and disconnect you.

[PT]Devilishly
Posts: 96
Joined: 2003-04-18 05:57
Location: Oporto, Portugal
Contact:

Re: Client-Hub handshake & Java

Post by [PT]Devilishly » 2006-06-22 07:06

chrisvoo wrote:The problem is: I create the Socket and I receive the standard String with $Lock lock Pk=bla| but then the server seems not to be able to receive my answer...and then,after it has passed 10 seconds,the hub said to me that the answer is arrived to late...
I used to have this problem, and it was due to my default charset encode..
I didn't test your code, but try to change this line:

Code: Select all

BufferedReader from_server = new BufferedReader(new InputStreamReader(s.getInputStream()));
to:

Code: Select all

BufferedReader from_server = new BufferedReader(new InputStreamReader(s.getInputStream(),"ISO-8859-1"));
and see if your problem is solved..

Locked