Brak odpowiedzi serwera GG

0

Witam,
Implementuję protokół GG, którego opis znajduje się tutaj//toxygen.net/libgadu/protocol/. Uprzedzę pytania dlaczego nie korzystam z gotowej implementacji JGGAPI? Dlatego, że jest ona przestarzała i nie uwzględnia wszystkich funkcjonalności. Moim problemem jest to, że gdy połączę się już z odpowiednim serwerem, odbiorę pakiet z ziarnem a gdy wyślę pakiet logowania nie otrzymuję żadnej odpowiedzi z jego strony. Ma ktoś pomysły dlaczego?

public static void main(String[] args) {                                       
                                        ServerCommunication sc = new ServerCommunication();
					Host host = sc.preConnect(numer_gg);
					sc.connect(host);
			
					ServerMessageChecker svc = new ServerMessageChecker(sc.getInputStream());
					ServerMessageListener sml = new ServerMessageListener();
					svc.addServerMessageListener(sml);
					
					Thread thread = new Thread(svc);
					thread.start();
					
					GGPackageHeader packageHeader = new GGPackageHeader(CommunicatorConstans.GG_LOGIN_PACKAGE, 0);
					GGLoginPackage loginPackage = new GGLoginPackage(packageHeader);
					loginPackage.setNumber(numer_gg);
					loginPackage.setLanguage(new byte[]{'p','l'});
					loginPackage.setHashType(CommunicatorConstans.SHA1_ALGORITM);
					loginPackage.setPasswordHash("hasło", "otrzymane_ziarno"));
					loginPackage.setStatus(14);
					loginPackage.setFlags(0);
					loginPackage.setFeatures(871);
					loginPackage.setImageSize((byte)100);
					loginPackage.setVersion(new byte[]{'1','.','0'});
					loginPackage.calculateLenght();
					

					sc.getOutputStream().write(loginPackage.getPackageContent());
					sc.getOutputStream().flush();
					
					System.out.println(sc.getRequester().getInputStream().read());
                                        //zawsze jest puste
}
					

package communicator.server.communication;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ServerMessageChecker implements Runnable{

	private BufferedInputStream inputStream;
	private List<IServerMessageEventListener> listeners = new ArrayList<IServerMessageEventListener>();
	
	public ServerMessageChecker(BufferedInputStream inputStream) {
		this.inputStream = inputStream;
	}
	
	public synchronized void addServerMessageListener (IServerMessageEventListener listener) {
		listeners.add(listener);
	}
	public synchronized void removeServerMessageListener (IServerMessageEventListener listener) {
		listeners.remove(listener);
	}
	
	@Override
	public void run() {
		try {
			while (true) {
				if (this.inputStream.available() != 0) {
					for (IServerMessageEventListener listener:listeners){
						listener.handleEvent(new ServerMessageEvent(this, this.inputStream));
                                                //listener jak narazie wypisuje otrzymany pakiet
                                        }

				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

	public BufferedInputStream getInputStream() {
		return inputStream;
	}
	public void setInputStream(BufferedInputStream inputStream) {
		this.inputStream = inputStream;
	}
	public List<IServerMessageEventListener> getListeners() {
		return listeners;
	}
	public void setListeners(List<IServerMessageEventListener> listeners) {
		this.listeners = listeners;
	}

}
public class ServerCommunication {
	
	private OutputStream outputStream;
	private BufferedInputStream inputStream;
	private Socket requester = null;
	
	public Host preConnect(int number) throws Exception {
		URL url = new URL("http://appmsg.gadu-gadu.pl/appsvc/appmsg_ver8.asp?fmnumber=" + number + "&lastmsg=0&version=11.2.35.10307");
		
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		connection.setRequestMethod("GET");
		
		BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
		long timeStart = System.currentTimeMillis();
		while (!reader.ready()){
			if (timeStart - System.currentTimeMillis() > 3000)
				throw new Exception("Connection timeout");
		}
		String tmp, response = "";
		while ((tmp = reader.readLine()) != null) {
			response += tmp;
			System.out.println("response" + response + "/response");
		}
		Host host = new Host();
		host.setUrl(response.split("\\s")[2].split(":")[0]);
		host.setPort(Integer.valueOf(response.split("\\s")[2].split(":")[1]));
		
		return host;
	}
	
	public void connect(Host host) throws UnknownHostException, IOException {
		this.requester = new Socket();
		SocketAddress socketAddress = new InetSocketAddress(host.getUrl(), host.getPort());
		this.requester.connect(socketAddress, 3000);
		this.requester.setKeepAlive(true);
		
		this.outputStream = requester.getOutputStream();
		this.outputStream.flush();
		
		this.inputStream = new BufferedInputStream(requester.getInputStream());
	}
	
	public void disconnect() throws IOException {
		if (this.requester != null)
			this.requester.close();
	}
	public Socket getRequester() {
		return requester;
	}
	public void setRequester(Socket requester) {
		this.requester = requester;
	}
	public OutputStream getOutputStream() {
		return outputStream;
	}
	public void setOutputStream(OutputStream outputStream) {
		this.outputStream = outputStream;
	}
	public BufferedInputStream getInputStream() {
		return inputStream;
	}
	public void setInputStream(BufferedInputStream inputStream) {
		this.inputStream = inputStream;
	}
}
//dla czytelności zostawiłem tylko istone pola i metody
public class GGLoginPackage extends GGPackageHeader implements Serializable, OutgoingPackage{
	

	private static final long serialVersionUID = -3727130558660044185L;
	
	private int number;
	private byte language[] = new byte[2];
	private byte hashType;
	private byte passwordHash[] = new byte[64];
	private int status;
	private int flags;
	private int features;
	private int localIP = 0;
	private short localPort = 0;
	private int externalIP = 0;
	private short externalPort = 0;
	private byte imageSize;
	private byte unknown = 100;
	private int versionLenght;
	private byte version[];
	private int descriptionSize;
	private byte description[];

	
	@Override
	public byte[] getPackageContent() {
		byte[] result;
		
		ByteBuffer buf = ByteBuffer.allocate(this.getLenght());
		buf.order(ByteOrder.LITTLE_ENDIAN);
		
		buf.putInt(this.getType());
		buf.putInt(this.getLenght() - 8);
		buf.put(this.language);
		buf.put(this.hashType);
		buf.put(this.passwordHash);
		buf.putInt(this.status);
		buf.putInt(this.flags);
		buf.putInt(this.features);
		buf.putInt(this.localIP);
		buf.putShort(this.localPort);
		buf.putInt(this.externalIP);
		buf.putShort(this.externalPort);
		buf.put(this.imageSize);
		buf.put(this.unknown);
		buf.putInt(this.versionLenght);
		buf.put(this.version);
		buf.putInt(this.descriptionSize);
		buf.put(this.description);
		
		result = buf.array();
		
		return result;
	}

	public void setPasswordHash(String password, byte[] seed) {
		MessageDigest digest = null;
		byte[] passwordHash = null;
		
		try {
			digest = MessageDigest.getInstance("SHA-1");
			digest.reset();
			digest.update(seed);

			passwordHash = digest.digest(password.getBytes("UTF-8"));
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		for (int i = 0; i < this.passwordHash.length; i++) {
			this.passwordHash[i] = '\0';

			if (i < passwordHash.length)
				this.passwordHash[i] = passwordHash[i];
		}
	}

}
0

Bez analizy kodu, zapewne nie otrzymujesz odpowiedzi bo w nagłówku pakietu deklarujesz inną długość wiadomości niż wysyłasz (serwer czeka na dane).

0

Ten aspekt już sprawdziłem i długość podaję dobrą. Dzięki za zainteresowanie :)

0

Ta linijka:
buf.putInt(this.getLenght() - 8) ?

Ile zwraca this.getLenght() ?

Nie wiem jak wygląda u ciebie GGPackageHeader.

0

GGPackageHeader wygląda następująco:

public class GGPackageHeader{
	
	private int type;
	private int lenght;
	
	public GGPackageHeader(int type, int lenght) {
		this.type = type;
		this.lenght = lenght;
	}
	
	public GGPackageHeader(byte[] byteArray) {
		ByteBuffer buf = ByteBuffer.wrap(byteArray);
		buf.order(ByteOrder.LITTLE_ENDIAN);
		
		this.type = buf.getInt();
		this.lenght = buf.getInt();
	}
}

A długość pakietu jest obliczana za pomocą metody calculateLenght(), która wygląda następująco dla pakietu GGLoginPackage

	public void calculateLenght() {
		int result = 113;
		
		result += this.version.length;
		result += this.description.length;
		setLenght(result);
	}

Początkowa wartość 113 to jest suma bajtów jakie zajmują kolejno wszystkie pola tego pakietu włącznie z typem i długością. Dlatego też, gdy wysyłam do serwera pakiet, należy odjąć 8 bajtów (4 bajty na typ i 4 na długość). Generalnie niepotrzebnie dodaję tu te 8 bajtów skoro je później odejmuje... (docelowo to poprawię, bo jest bez sensu)

1

LoginPacket u mnie ma Length = 138 (sprawdziłem teraz u siebie, tyle że w version wysyłam "Gadu-Gadu Client build 8.0.0.7669")

Gdzie masz put(this.number) ?

0

Oh faktycznie pominąłem ten numer... dzięki za spostrzeżenie. Dodałem to, niestety nie pomogło.

Jeśli chodzi o sumę bajtów to wychodzi tyle samo co Tobie jeśli uwzględnię podaną przez Ciebie wersję.

Jeśli chodzi o to hasło to ono jest dopełnione do 64.

Edit:// Dzięki serdeczne :) Pomogła mi podana przez Ciebie wersja :). W momencie, gdy ją dodałem w postaci jaką podałeś, serwer odpowiedział :). Wielkie dzięki :)

0

OK, to daj ptaszka i jak coś to do usług :)
Mała uwaga co do Twojego kodu: bardzo Ci się przyda potem automatyczne wyliczanie długości pakietu (a nie żeby na sztywno podawać)

1 użytkowników online, w tym zalogowanych: 0, gości: 1