/*******************************************************************************
Jimm Is Mobile Messenger
Copyright (C) 2003 Jimm Project
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Software Foundation; either version 2
of the License, or (at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
********************************************************************************
Author: Vladimir Kryukov
*******************************************************************************/
package protocol.net;
import java.io.*;
import jimm.comm.Util;
/**
*
* @author Vladimir Kryukov
*/
public final class SrvResolver {
private static final String server = "8.8.8.8";
private TcpSocket socket = new TcpSocket();
/**
* Creates a new instance of SrvResolver
*/
public SrvResolver() {
}
private byte[] packet(String[] domain) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(0x12); out.write(0x10); // id
out.write(1); out.write(0); // flags
out.write(0); out.write(1); // queries count
out.write(0); out.write(0); // resources count
out.write(0); out.write(0); // answers count
out.write(0); out.write(0); // additions count
for (String domainPart : domain) {
byte[] l = domainPart.getBytes();
out.write(l.length);
out.write(l);
}
out.write(0);
out.write(0);out.write(33); // type: SRV
out.write(0);out.write(1); // class: Internet
return out.toByteArray();
}
private String read(byte[] data) throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream in = new DataInputStream(bais);
short id = in.readShort(); // id
short flags = in.readShort(); // flags
int questions = in.readShort();
int answers = in.readShort();
in.readShort();
in.readShort();
for (int i = 0; i < questions; ++i) {
while (true) {
int length = in.readUnsignedByte();
if (0 == length) break;
for (int j = 0; j < length; ++j) {
in.readUnsignedByte();
}
}
in.readShort();
in.readShort();
}
for (int i = 0; i < answers; ++i) {
in.readUnsignedShort(); // ...
in.readUnsignedShort(); // type
in.readUnsignedShort(); // class
in.readInt(); // ttl
int rdlength = in.readUnsignedShort(); // length
in.readUnsignedShort();
in.readUnsignedShort();
int port = in.readUnsignedShort(); // port
StringBuilder result = new StringBuilder();
while (true) {
int length = in.readUnsignedByte();
if (0 == length) break;
for (int j = 0; j < length; ++j) {
result.append((char)in.readUnsignedByte());
}
result.append('.');
}
if (443 == port) {
port = 5222;
}
return result.toString().substring(0, result.length() - 1) + ":" + port;
}
return null;
}
public String getXmpp(String domain) {
return get("_xmpp-client._tcp." + domain);
}
public String get(String domain) {
return get(Util.explode(domain, '.'));
}
private String get(String[] domain) {
try {
return sendTcp(packet(domain));
} catch (IOException ex) {
return null;
}
}
private String sendTcp(byte[] message) {
try {
socket.connectTo(server, 53);
byte[] packet = new byte[2 + message.length];
System.arraycopy(message, 0, packet, 2, message.length);
Util.putWordBE(packet, 0, message.length);
socket.write(packet);
socket.flush();
byte[] header = new byte[2];
socket.readFully(header);
byte[] data = new byte[Util.getWordBE(header, 0)];
socket.readFully(data);
return read(data);
} catch (Exception ignored) {
}
return null;
}
public void close() {
socket.close();
}
}