Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreutarass2008-04-23 20:11:12 +0000
committereutarass2008-04-23 20:11:12 +0000
commit3be680f61e65a1481bb83537704751d3ff024b2d (patch)
treeffa140769f580ba520022b078b26d1fc3583b2d1 /plugins
parent190f9fd77f29985d2d662dfe6208f170cf079ea5 (diff)
downloadorg.eclipse.tcf-3be680f61e65a1481bb83537704751d3ff024b2d.tar.gz
org.eclipse.tcf-3be680f61e65a1481bb83537704751d3ff024b2d.tar.xz
org.eclipse.tcf-3be680f61e65a1481bb83537704751d3ff024b2d.zip
1. Bug 223520: [tcf] Registers service changes.
2. Fixed discovery periodic UDP broadcast. 3. Fixed json_read_binary_data() - it didn't work for buffers smaller then 3 bytes
Diffstat (limited to 'plugins')
-rw-r--r--plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java41
-rw-r--r--plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java95
-rw-r--r--plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/RegistersProxy.java46
-rw-r--r--plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/protocol/JSON.java67
-rw-r--r--plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IRegisters.java37
5 files changed, 238 insertions, 48 deletions
diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java
index 6056358e7..d3942284b 100644
--- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java
+++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java
@@ -20,6 +20,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
@@ -951,6 +952,46 @@ class TCFSelfTest {
}
}));
}
+ if (!reg_map.isEmpty()) {
+ Random rnd = new Random();
+ List<IRegisters.Location> locs = new ArrayList<IRegisters.Location>();
+ String[] ids = reg_map.keySet().toArray(new String[reg_map.size()]);
+ for (int i = 0; i < rnd.nextInt(32); i++) {
+ String id = ids[rnd.nextInt(ids.length)];
+ IRegisters.RegistersContext ctx = reg_map.get(id);
+ if (!ctx.isReadable()) continue;
+ if (ctx.isReadOnce()) continue;
+ int offs = rnd.nextInt(ctx.getSize());
+ int size = rnd.nextInt(ctx.getSize() - offs) + 1;
+ locs.add(new IRegisters.Location(id, offs, size));
+ }
+ final IRegisters.Location[] loc_arr = locs.toArray(new IRegisters.Location[locs.size()]);
+ cmds.add(rg.getm(loc_arr, new IRegisters.DoneGet() {
+ public void doneGet(IToken token, Exception error, byte[] value) {
+ cmds.remove(token);
+ if (suspended.get(sc.id) != sc) return;
+ if (error != null) {
+ for (IToken t : cmds) t.cancel();
+ exit(error);
+ return;
+ }
+ cmds.add(rg.setm(loc_arr, value, new IRegisters.DoneSet() {
+ public void doneSet(IToken token, Exception error) {
+ cmds.remove(token);
+ if (suspended.get(sc.id) != sc) return;
+ if (error != null) {
+ for (IToken t : cmds) t.cancel();
+ exit(error);
+ return;
+ }
+ if (cmds.isEmpty()) {
+ resume(sc);
+ }
+ }
+ }));
+ }
+ }));
+ }
if (cmds.isEmpty()) {
resume(sc);
}
diff --git a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java
index ace101013..dda4db59e 100644
--- a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java
+++ b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/local/LocatorService.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.tm.internal.tcf.services.local;
+import java.lang.reflect.Method;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
@@ -18,6 +19,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.eclipse.tm.internal.tcf.core.LocalPeer;
@@ -174,52 +176,61 @@ public class LocatorService implements ILocator {
* socket.send(new DatagramPacket(buf, buf.length, ia.getBroadcast(), 1534));
* }
*/
- Enumeration<InetAddress> n = f.getInetAddresses();
- while (n.hasMoreElements()) {
- InetAddress ina = n.nextElement();
- byte[] adr = ina.getAddress();
- if (adr.length != 4) {
- // TODO: Support IPv6
- // System.out.println("Dont support IPv6: " + ina);
- continue;
- }
- /* Since we don't know actual broadcast address,
- * lets try different combinations.
- * Hopefully one of them will work.
- */
- int h = adr[0] & 0xff;
- if (h >= 1 && h <= 127 && h != 38) {
- adr[3] = (byte)255;
- socket.send(new DatagramPacket(buf, buf.length,
- InetAddress.getByAddress(null, adr), 1534));
- adr[2] = (byte)255;
- socket.send(new DatagramPacket(buf, buf.length,
- InetAddress.getByAddress(null, adr), 1534));
- adr[1] = (byte)255;
- }
- else if (h >= 128 && h <= 191) {
- adr[3] = (byte)255;
- socket.send(new DatagramPacket(buf, buf.length,
- InetAddress.getByAddress(null, adr), 1534));
- adr[2] = (byte)255;
+ try {
+ Method m0 = f.getClass().getMethod("getInterfaceAddresses");
+ for (Object ia : (List<?>)m0.invoke(f)) {
+ Method m1 = ia.getClass().getMethod("getBroadcast");
+ socket.send(new DatagramPacket(buf, buf.length, (InetAddress)m1.invoke(ia), 1534));
}
- else {
- adr[3] = (byte)(adr[3] | 0x0f);
- socket.send(new DatagramPacket(buf, buf.length,
- InetAddress.getByAddress(null, adr), 1534));
- adr[3] = (byte)(adr[3] | 0x01f);
- socket.send(new DatagramPacket(buf, buf.length,
- InetAddress.getByAddress(null, adr), 1534));
- adr[3] = (byte)(adr[3] | 0x03f);
- socket.send(new DatagramPacket(buf, buf.length,
- InetAddress.getByAddress(null, adr), 1534));
- adr[3] = (byte)(adr[3] | 0x07f);
+ }
+ catch (Exception x) {
+ Enumeration<InetAddress> n = f.getInetAddresses();
+ while (n.hasMoreElements()) {
+ InetAddress ina = n.nextElement();
+ byte[] adr = ina.getAddress();
+ if (adr.length != 4) {
+ // TODO: Support IPv6
+ // System.out.println("Don't support IPv6: " + ina);
+ continue;
+ }
+ /* Since we don't know actual broadcast address,
+ * lets try different combinations.
+ * Hopefully one of them will work.
+ */
+ int h = adr[0] & 0xff;
+ if (h >= 1 && h <= 127 && h != 38) {
+ adr[3] = (byte)255;
+ socket.send(new DatagramPacket(buf, buf.length,
+ InetAddress.getByAddress(null, adr), 1534));
+ adr[2] = (byte)255;
+ socket.send(new DatagramPacket(buf, buf.length,
+ InetAddress.getByAddress(null, adr), 1534));
+ adr[1] = (byte)255;
+ }
+ else if (h >= 128 && h <= 191) {
+ adr[3] = (byte)255;
+ socket.send(new DatagramPacket(buf, buf.length,
+ InetAddress.getByAddress(null, adr), 1534));
+ adr[2] = (byte)255;
+ }
+ else {
+ adr[3] = (byte)(adr[3] | 0x0f);
+ socket.send(new DatagramPacket(buf, buf.length,
+ InetAddress.getByAddress(null, adr), 1534));
+ adr[3] = (byte)(adr[3] | 0x01f);
+ socket.send(new DatagramPacket(buf, buf.length,
+ InetAddress.getByAddress(null, adr), 1534));
+ adr[3] = (byte)(adr[3] | 0x03f);
+ socket.send(new DatagramPacket(buf, buf.length,
+ InetAddress.getByAddress(null, adr), 1534));
+ adr[3] = (byte)(adr[3] | 0x07f);
+ socket.send(new DatagramPacket(buf, buf.length,
+ InetAddress.getByAddress(null, adr), 1534));
+ adr[3] = (byte)255;
+ }
socket.send(new DatagramPacket(buf, buf.length,
InetAddress.getByAddress(null, adr), 1534));
- adr[3] = (byte)255;
}
- socket.send(new DatagramPacket(buf, buf.length,
- InetAddress.getByAddress(null, adr), 1534));
}
}
}
diff --git a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/RegistersProxy.java b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/RegistersProxy.java
index 42424c063..5c64aae33 100644
--- a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/RegistersProxy.java
+++ b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/RegistersProxy.java
@@ -208,6 +208,37 @@ public class RegistersProxy implements IRegisters {
}.token;
}
+ public IToken getm(Location[] locs, final DoneGet done) {
+ return new Command(channel, this, "getm", new Object[]{ locs }) {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void done(Exception error, Object[] args) {
+ byte[] val = null;
+ if (error == null) {
+ assert args.length == 3;
+ error = toError(args[0], args[1]);
+ String str = (String)args[2];
+ if (str != null) val = Base64.toByteArray(str.toCharArray());
+ }
+ done.doneGet(token, error, val);
+ }
+ }.token;
+ }
+
+ public IToken setm(Location[] locs, byte[] value, final DoneSet done) {
+ return new Command(channel, this, "setm",
+ new Object[]{ locs, Base64.toBase64(value, 0, value.length) }) {
+ @Override
+ public void done(Exception error, Object[] args) {
+ if (error == null) {
+ assert args.length == 2;
+ error = toError(args[0], args[1]);
+ }
+ done.doneSet(token, error);
+ }
+ }.token;
+ }
+
public void addListener(final RegistersListener listener) {
IChannel.IEventListener l = new IChannel.IEventListener() {
@@ -294,4 +325,19 @@ public class RegistersProxy implements IRegisters {
}
return arr;
}
+
+ static {
+ JSON.addObjectWriter(Location.class, new JSON.ObjectWriter() {
+ public void write(Object o) throws IOException {
+ Location l = (Location)o;
+ JSON.write('[');
+ JSON.writeObject(l.id);
+ JSON.write(',');
+ JSON.writeUInt(l.offs);
+ JSON.write(',');
+ JSON.writeUInt(l.size);
+ JSON.write(']');
+ }
+ });
+ }
}
diff --git a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/protocol/JSON.java b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/protocol/JSON.java
index e5dd10c61..f5000fed5 100644
--- a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/protocol/JSON.java
+++ b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/protocol/JSON.java
@@ -30,10 +30,29 @@ import org.eclipse.tm.internal.tcf.core.ReadOnlyMap;
/**
* JSON is TCF preferred marshaling. This class implements generation and parsing of JSON strings.
- * The code is optimized for speed since it is a time-critical part of the framework.
+ * The code is optimized for speed since it is a time-critical part of the framework.
+ *
+ * Reading of JSON produces data structure that consists of objects of these classes:
+ * Boolean, Number, String, Collection, Map.
+ *
+ * Writing of JSON is supported for:
+ * Boolean, Number, String, char[], byte[], Object[], Collection, Map
+ *
+ * Clients can enable writing support for objects of a other classes by
+ * registering ObjectWriter interface implementation.
*/
public class JSON {
+ /**
+ * Clients implement ObjectWriter interface when they want to enable marshaling of
+ * object classes that are not directly supported by JSON library.
+ */
+ public interface ObjectWriter {
+ void write(Object o) throws IOException;
+ }
+
+ private static final Map<Class<?>,ObjectWriter> object_writers = new HashMap<Class<?>,ObjectWriter>();
+
private static char[] tmp_buf = new char[0x1000];
private static byte[] tmp_bbf = new byte[0x1000];
private static int tmp_buf_pos;
@@ -48,8 +67,22 @@ public class JSON {
private static final char[] err_buf = new char[100];
private static int err_buf_pos;
private static int err_buf_cnt;
+
+ /**
+ * Add a handler for converting objects of a particular class into JSON.
+ * @param cls - a class
+ * @param writer - ObjectWriter implementation that provides generation of JSON for a given class.
+ */
+ public static void addObjectWriter(Class<?> cls, ObjectWriter writer) {
+ object_writers.put(cls, writer);
+ }
- private static void write(char ch) {
+ /**
+ * Write a character into JSON output buffer.
+ * Clients should not call this method directly, except from ObjectWriter implementation.
+ * @param ch
+ */
+ public static void write(char ch) {
if (tmp_buf_pos >= tmp_buf.length) {
char[] tmp = new char[tmp_buf.length * 2];
System.arraycopy(tmp_buf, 0, tmp, 0, tmp_buf_pos);
@@ -58,7 +91,13 @@ public class JSON {
tmp_buf[tmp_buf_pos++] = ch;
}
- private static void write(String s) {
+ /**
+ * Write a string into JSON output buffer.
+ * The string is written "as-is". Call writeObject() to convert a String into JSON string.
+ * Clients should not call this method directly, except from ObjectWriter implementation.
+ * @param s - a string
+ */
+ public static void write(String s) {
int l = s.length();
for (int i = 0; i < l; i++) {
char ch = s.charAt(i);
@@ -67,7 +106,12 @@ public class JSON {
}
}
- private static void writeUInt(int n) {
+ /**
+ * Write a non-negative integer number into JSON output buffer.
+ * Clients should not call this method directly, except from ObjectWriter implementation.
+ * @param n - a number
+ */
+ public static void writeUInt(int n) {
assert n >= 0;
if (n >= 10) writeUInt(n / 10);
write((char)('0' + n % 10));
@@ -320,8 +364,13 @@ public class JSON {
return l.toArray();
}
+ /**
+ * Write an object into JSON output buffer.
+ * Clients should not call this method directly, except from ObjectWriter implementation.
+ * @param o - an object to write
+ */
@SuppressWarnings("unchecked")
- private static void writeObject(Object o) throws IOException {
+ public static void writeObject(Object o) throws IOException {
if (o == null) {
write("null");
}
@@ -419,7 +468,13 @@ public class JSON {
write('}');
}
else {
- throw new IOException("JSON: unsupported object type");
+ ObjectWriter writer = object_writers.get(o.getClass());
+ if (writer != null) {
+ writer.write(o);
+ }
+ else {
+ throw new IOException("JSON: unsupported object type");
+ }
}
}
diff --git a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IRegisters.java b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IRegisters.java
index 9fb1de145..73625f295 100644
--- a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IRegisters.java
+++ b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IRegisters.java
@@ -258,6 +258,43 @@ public interface IRegisters extends IService {
}
/**
+ * Read values of multiple locations in registers.
+ * @param locs - array of data locations.
+ * @param done - call back object.
+ * @return - pending command handle.
+ */
+ IToken getm(Location[] locs, DoneGet done);
+
+ /**
+ * Set values of multiple locations in registers.
+ * @param locs - array of data locations.
+ * @param value - value to write into the context.
+ * @param done - call back object.
+ * @return - pending command handle.
+ */
+ IToken setm(Location[] locs, byte[] value, DoneSet done);
+
+ /**
+ * Class Location represents value location in register context
+ */
+ final class Location {
+ /** Register context ID */
+ public final String id;
+
+ /** offset in the context, in bytes */
+ public final int offs;
+
+ /** value size in byte */
+ public final int size;
+
+ public Location(String id, int offs, int size) {
+ this.id = id;
+ this.offs = offs;
+ this.size = size;
+ }
+ }
+
+ /**
* 'get' command call back interface.
*/
interface DoneGet {

Back to the top