/src/ibis/smartsockets/virtual/VirtualSocketAddress.java

https://github.com/interdroid/smartsockets · Java · 342 lines · 227 code · 87 blank · 28 comment · 45 complexity · 2805e08eda3b9a1a6f52a346f11a1773 MD5 · raw file

  1. package ibis.smartsockets.virtual;
  2. import ibis.smartsockets.direct.DirectSocketAddress;
  3. import ibis.smartsockets.util.MalformedAddressException;
  4. import ibis.smartsockets.util.TransferUtils;
  5. import java.io.DataInput;
  6. import java.io.DataOutput;
  7. import java.io.IOException;
  8. import java.io.Serializable;
  9. import java.net.InetAddress;
  10. import java.net.InetSocketAddress;
  11. import java.net.SocketAddress;
  12. import java.net.UnknownHostException;
  13. public class VirtualSocketAddress extends SocketAddress implements Serializable {
  14. private static final long serialVersionUID = 3340517955293464166L;
  15. private final DirectSocketAddress machine;
  16. private final int port;
  17. // This hub field is a hint of the location of the machine. It may be null
  18. // or change over time (e.g., when a hub crashes and a machine registers
  19. // at another hub).
  20. private final DirectSocketAddress hub;
  21. // This field indicates which 'virtual cluster' the machine is part of.
  22. private final String cluster;
  23. // Cache for the coded form of this address
  24. private transient byte [] codedForm;
  25. public VirtualSocketAddress(DataInput in)
  26. throws IOException, MalformedAddressException {
  27. int mlen = in.readShort();
  28. int hlen = in.readShort();
  29. int clen = in.readShort();
  30. byte [] m = new byte[mlen];
  31. in.readFully(m);
  32. machine = DirectSocketAddress.fromBytes(m);
  33. port = in.readInt();
  34. if (hlen > 0) {
  35. byte [] h = new byte[hlen];
  36. in.readFully(h);
  37. hub = DirectSocketAddress.fromBytes(h);
  38. } else {
  39. hub = null;
  40. }
  41. if (clen > 0) {
  42. byte [] c = new byte[clen];
  43. in.readFully(c);
  44. cluster = new String(c);
  45. } else {
  46. cluster= null;
  47. }
  48. }
  49. public VirtualSocketAddress(DirectSocketAddress machine, int port) {
  50. this(machine, port, null, null);
  51. }
  52. public VirtualSocketAddress(DirectSocketAddress machine,
  53. int port, DirectSocketAddress hub, String cluster) {
  54. this.hub = hub;
  55. this.machine = machine;
  56. this.port = port;
  57. this.cluster = cluster;
  58. }
  59. /**
  60. * Construct a new VirtualSocketAddress starting from a String with the
  61. * following format:
  62. *
  63. * MACHINEADDRESS:PORT[@MACHINEADDRESS][#CLUSTER]
  64. *
  65. * The '@MACHINEADDRESS' part is optional and indicates the hub where the
  66. * machine can be found. The '#CLUSTER' part is also optional and indicates
  67. * which virtual cluster the machine belongs to.
  68. *
  69. * @param address
  70. * @throws UnknownHostException
  71. */
  72. public VirtualSocketAddress(String address)
  73. throws UnknownHostException, MalformedAddressException {
  74. int index1 = address.lastIndexOf('@');
  75. int index2 = address.lastIndexOf('#');
  76. if (index2 < index1) {
  77. // The hub is after the cluster (or cluster does not exist).
  78. hub = DirectSocketAddress.getByAddress(address.substring(index1+1));
  79. if (index2 != -1) {
  80. cluster = address.substring(index2+1, index1);
  81. address = address.substring(0, index2);
  82. } else {
  83. cluster = null;
  84. address = address.substring(0, index1);
  85. }
  86. } else if (index2 > index1){
  87. // The hub is before the cluster.
  88. cluster = address.substring(index2+1);
  89. if (index1 != -1) {
  90. hub = DirectSocketAddress.getByAddress(address.substring(index1+1, index2));
  91. address = address.substring(0, index1);
  92. } else {
  93. address = address.substring(0, index2);
  94. hub = null;
  95. }
  96. } else {
  97. // both index1 and index2 are '-1'
  98. cluster = null;
  99. hub = null;
  100. }
  101. int index = address.lastIndexOf(':');
  102. if (index == -1) {
  103. throw new MalformedAddressException("String \"" + address + "\"" +
  104. " does not contain VirtualSocketAddress!");
  105. }
  106. try {
  107. machine = DirectSocketAddress.getByAddress(
  108. address.substring(0, index));
  109. port = Integer.parseInt(address.substring(index+1));
  110. } catch (NumberFormatException e) {
  111. throw new MalformedAddressException("String \"" + address + "\"" +
  112. " does not contain VirtualSocketAddress!", e);
  113. }
  114. }
  115. public VirtualSocketAddress(String machine, int port)
  116. throws UnknownHostException, MalformedAddressException {
  117. this(DirectSocketAddress.getByAddress(machine), port, null, null);
  118. }
  119. public VirtualSocketAddress(String hub, String machine, int port)
  120. throws UnknownHostException, MalformedAddressException {
  121. this(DirectSocketAddress.getByAddress(machine), port,
  122. DirectSocketAddress.getByAddress(hub), null);
  123. }
  124. public void write(DataOutput out) throws IOException {
  125. byte [] m = machine.getAddress();
  126. byte [] h = null;
  127. if (hub != null) {
  128. h = hub.getAddress();
  129. }
  130. byte [] c = null;
  131. if (cluster != null) {
  132. c = cluster.getBytes();
  133. }
  134. out.writeShort(m.length);
  135. out.writeShort(h == null ? 0 : h.length);
  136. out.writeShort(c == null ? 0 : c.length);
  137. out.write(m);
  138. out.writeInt(port);
  139. if (h != null) {
  140. out.write(h);
  141. }
  142. if (c != null) {
  143. out.write(c);
  144. }
  145. }
  146. public DirectSocketAddress hub() {
  147. return hub;
  148. }
  149. public DirectSocketAddress machine() {
  150. return machine;
  151. }
  152. public String cluster() {
  153. return cluster;
  154. }
  155. public int port() {
  156. return port;
  157. }
  158. public byte [] toBytes() {
  159. if (codedForm == null) {
  160. byte [] m = machine.getAddress();
  161. byte [] h = hub == null ? new byte[0] : hub.getAddress();
  162. byte [] c = cluster == null ? new byte[0] : cluster.getBytes();
  163. int len = 3*2 + 4 + m.length;
  164. if (h != null) {
  165. len += h.length;
  166. }
  167. if (c != null) {
  168. len += c.length;
  169. }
  170. codedForm = new byte[len];
  171. TransferUtils.storeShort((short) m.length, codedForm, 0);
  172. TransferUtils.storeShort((short) h.length, codedForm, 2);
  173. TransferUtils.storeShort((short) c.length, codedForm, 4);
  174. System.arraycopy(m, 0, codedForm, 6, m.length);
  175. int off = 6 + m.length;
  176. TransferUtils.storeInt(port, codedForm, off);
  177. off += 4;
  178. System.arraycopy(h, 0, codedForm, off, h.length);
  179. off += h.length;
  180. System.arraycopy(c, 0, codedForm, off, c.length);
  181. }
  182. return codedForm.clone();
  183. }
  184. public String toString() {
  185. return machine.toString() + ":" + port
  186. + (hub == null ? "" : ("@" + hub.toString()))
  187. + (cluster == null ? "" : ("#" + cluster));
  188. }
  189. public boolean equals(Object other) {
  190. if (this == other) {
  191. return true;
  192. }
  193. if (other == null) {
  194. return false;
  195. }
  196. if (!(other instanceof VirtualSocketAddress)) {
  197. return false;
  198. }
  199. // Now compare the addresses. Note that the hub field is not compared,
  200. // since it is only a hint of the location of the machine. It may be
  201. // null in some cases or contain different values if the machine is
  202. // registered at multiple proxies.
  203. VirtualSocketAddress tmp = (VirtualSocketAddress) other;
  204. // The ports must be the same.
  205. if (port != tmp.port) {
  206. return false;
  207. }
  208. // The machine must be the same
  209. return machine.equals(tmp.machine);
  210. }
  211. public int hashCode() {
  212. return machine.hashCode() ^ port;
  213. }
  214. public static VirtualSocketAddress fromBytes(byte [] source, int offset)
  215. throws UnknownHostException, MalformedAddressException {
  216. int mlen = TransferUtils.readShort(source, offset);
  217. int hlen = TransferUtils.readShort(source, offset+2);
  218. int clen = TransferUtils.readShort(source, offset+4);
  219. int off = offset + 6;
  220. DirectSocketAddress machine = DirectSocketAddress.fromBytes(source, off);
  221. off += mlen;
  222. int port = TransferUtils.readInt(source, off);
  223. off += 4;
  224. DirectSocketAddress hub = null;
  225. if (hlen > 0) {
  226. hub = DirectSocketAddress.fromBytes(source, off);
  227. off += hlen;
  228. }
  229. String cluster = null;
  230. if (clen > 0) {
  231. cluster = new String(source, off, clen);
  232. // off += clen;
  233. }
  234. return new VirtualSocketAddress(machine, port, hub, cluster);
  235. }
  236. public static VirtualSocketAddress partialAddress(InetAddress host,
  237. int realport, int virtualport) throws UnknownHostException {
  238. return new VirtualSocketAddress(
  239. DirectSocketAddress.getByAddress(
  240. new InetSocketAddress(host, realport)), virtualport);
  241. }
  242. public static VirtualSocketAddress partialAddress(String hostname,
  243. int realport, int virtualport) throws UnknownHostException {
  244. return new VirtualSocketAddress(
  245. DirectSocketAddress.getByAddress(hostname, realport), virtualport);
  246. }
  247. public static VirtualSocketAddress partialAddress(String hostname,
  248. int port) throws UnknownHostException {
  249. return partialAddress(hostname, port, port);
  250. }
  251. public static VirtualSocketAddress partialAddress(InetAddress host,
  252. int port) throws UnknownHostException {
  253. return partialAddress(host, port, port);
  254. }
  255. }