Open wenfer opened 7 months ago
I would check the x11 server logs to see if there is anything helpful there. You can also compare the the java classes to the C library. There could be something it does differently before submitting the request.
/the code is convert from rust(x11rb), that's work in rust,i show you code
fn main() {
let (conn, screen_num) = x11rb::connect(None).unwrap();
let rc = conn.generate_id().unwrap();
let empty = Range8 { first: 0, last: 0 };
let empty_ext = ExtRange {
major: empty,
minor: record::Range16 { first: 0, last: 0 },
};
let range = record::Range {
core_requests: empty,
core_replies: empty,
ext_requests: empty_ext,
ext_replies: empty_ext,
delivered_events: empty,
device_events: Range8 {
// We want notification of core X11 events between key press and motion notify
first: xproto::KEY_PRESS_EVENT,
last: xproto::MOTION_NOTIFY_EVENT,
},
errors: empty,
client_started: false,
client_died: false,
};
let _ = conn.record_create_context(rc,
0,
&[CS::ALL_CLIENTS.into()],
&[range]);
for reply in conn.record_enable_context(rc).unwrap() {
match reply {
Ok(reply) => {
//todo something
}
Err(err) => {
println!("error:{}", err);
}
}
}
}```
The problem is with ProtocolPluginService
if(plugin.getMajorVersion() != majorOpcode) {
return false; //client must match server version
}
I assumed this was a way to make sure the versions between the client and server matched.
What needs to happen is the plugin should send a QueryVersion request and return the major and minor versions so ProtocolPluginService can check they match.
I started working on this in the fix-plugins branch. Now I am getting a LengthError.
LengthError(firstErrorOffset=0, sequenceNumber=34, badValue=0, minorOpcode=0, majorOpcode=-109)
com.github.moaxcp.x11client.X11ErrorException: LengthError(firstErrorOffset=0, sequenceNumber=34, badValue=0, minorOpcode=0, majorOpcode=-109)
at app//com.github.moaxcp.x11client.XProtocolService.readReply(XProtocolService.java:87)
at app//com.github.moaxcp.x11client.XProtocolService.send(XProtocolService.java:66)
at app//com.github.moaxcp.x11client.X11Client.send(X11Client.java:238)
at app//com.github.moaxcp.x11client.RecordIT.test(RecordIT.java:43)
I added a sync after the CreateContext request and that is the request causing the failure. From there I logged the request. Can you tell if the length is correct?
CreateContext(context=83886081, elementHeader=0, clientSpecs=[3], ranges=[Range(coreRequests=Range8(first=0, last=0), coreReplies=Range8(first=0, last=0), extRequests=ExtRange(major=Range8(first=0, last=0), minor=Range16(first=0, last=0)), extReplies=ExtRange(major=Range8(first=0, last=0), minor=Range16(first=0, last=0)), deliveredEvents=Range8(first=0, last=0), deviceEvents=Range8(first=2, last=6), errors=Range8(first=0, last=0), clientStarted=false, clientDied=false)]), size: 48, length: 12
Or maybe the write method is generated wrong?
@Override
public void write(byte offset, X11Output out) throws IOException {
out.writeCard8((byte)(Byte.toUnsignedInt(OPCODE) + Byte.toUnsignedInt(offset)));
out.writePad(1);
out.writeCard16((short) getLength());
out.writeCard32(context);
out.writeCard8(elementHeader);
out.writePad(3);
int numClientSpecs = clientSpecs.size();
out.writeCard32(numClientSpecs);
int numRanges = ranges.size();
out.writeCard32(numRanges);
out.writeCard32(clientSpecs);
for(Range t : ranges) {
t.write(out);
}
out.writePadAlign(getSize());
}
i see release 0.13.0,it's fixed ? i can't get from maven central , did pushed to nexus ?
I added a sync after the CreateContext request and that is the request causing the failure. From there I logged the request. Can you tell if the length is correct?
CreateContext(context=83886081, elementHeader=0, clientSpecs=[3], ranges=[Range(coreRequests=Range8(first=0, last=0), coreReplies=Range8(first=0, last=0), extRequests=ExtRange(major=Range8(first=0, last=0), minor=Range16(first=0, last=0)), extReplies=ExtRange(major=Range8(first=0, last=0), minor=Range16(first=0, last=0)), deliveredEvents=Range8(first=0, last=0), deviceEvents=Range8(first=2, last=6), errors=Range8(first=0, last=0), clientStarted=false, clientDied=false)]), size: 48, length: 12
Or maybe the write method is generated wrong?
@Override public void write(byte offset, X11Output out) throws IOException { out.writeCard8((byte)(Byte.toUnsignedInt(OPCODE) + Byte.toUnsignedInt(offset))); out.writePad(1); out.writeCard16((short) getLength()); out.writeCard32(context); out.writeCard8(elementHeader); out.writePad(3); int numClientSpecs = clientSpecs.size(); out.writeCard32(numClientSpecs); int numRanges = ranges.size(); out.writeCard32(numRanges); out.writeCard32(clientSpecs); for(Range t : ranges) { t.write(out); } out.writePadAlign(getSize()); }
sorry , i dont know x11 more , so i can't help you ,i just test record plugin in rust , that's all
Anything is possible but length is the error returned. I was just wondering what the length should be. Can you compare it to the length in rust? Or even compare the binary results? There are a few structs involved so it could be an issue with structs. I will have to look into it more.
Now
which request lengtherror in ? show me the java code, i'll try help
I think I figured it out I just need to find some time to work on it. The problem is in writing the output. This is what CreateContext has.
@Override
public void write(byte offset, X11Output out) throws IOException {
out.writeCard8((byte)(Byte.toUnsignedInt(OPCODE) + Byte.toUnsignedInt(offset)));
out.writePad(1);
out.writeCard16((short) getLength());
out.writeCard32(context);
out.writeCard8(elementHeader);
out.writePad(3);
int numClientSpecs = clientSpecs.size();
out.writeCard32(numClientSpecs);
int numRanges = ranges.size();
out.writeCard32(numRanges);
out.writeCard32(clientSpecs);
for(Range t : ranges) {
t.write(out);
}
out.writePadAlign(getSize());
}
For the rust client this is what I found.
let mut request0 = vec![
major_opcode,
CREATE_CONTEXT_REQUEST,
0,
0,
context_bytes[0],
context_bytes[1],
context_bytes[2],
context_bytes[3],
element_header_bytes[0],
0,
0,
0,
num_client_specs_bytes[0],
num_client_specs_bytes[1],
num_client_specs_bytes[2],
num_client_specs_bytes[3],
num_ranges_bytes[0],
num_ranges_bytes[1],
num_ranges_bytes[2],
num_ranges_bytes[3],
];
The problem is here out.writeCard8((byte)(Byte.toUnsignedInt(OPCODE) + Byte.toUnsignedInt(offset)));
. The first byte is the addition of the opcode and the offset or majorOpcode. When what should happen is the majorOpcode should be the first byte followed by OPCODE.
I have to change the gradle-plugin to write the OPCODE instead of a padding for these extensions.
This explains why BigRequest works and all of the QueryVersion requests for the extensions because their OPCODE is 0 but everything else fails.
The problem is here
out.writeCard8((byte)(Byte.toUnsignedInt(OPCODE) + Byte.toUnsignedInt(offset)));
. The first byte is the addition of the opcode and the offset or majorOpcode. When what should happen is the majorOpcode should be the first byte followed by OPCODE.I have to change the gradle-plugin to write the OPCODE instead of a padding for these extensions.
This explains why BigRequest works and all of the QueryVersion requests for the extensions because their OPCODE is 0 but everything else fails.
you are hero !!!
This should be fixed now in 0.14.0
i try in 0.14.0, the samples code return EnableContextReply field category is 4, in rust code category is 0, look like not fixed
One thing I noticed is you are supposed to use two clients for this. One for the control client and one for the data client. So I added a data client.
try (X11Client control = X11Client.connect()) {
int rc = control.nextResourceId();
Range8 empty = Range8.builder().build();
ExtRange emptyExtRange = ExtRange.builder()
.major(empty)
.minor(Range16.builder().build())
.build();
Range range = Range.builder()
.deviceEvents(Range8.builder().first(KeyPressEvent.NUMBER).last(MotionNotifyEvent.NUMBER).build())
.coreRequests(empty)
.coreReplies(empty)
.extRequests(emptyExtRange)
.extReplies(emptyExtRange)
.deliveredEvents(empty)
.clientStarted(false)
.errors(empty)
.clientDied(false)
.build();
CreateContext createContext = CreateContext.builder()
.context(rc)
.clientSpecs(Collections.singletonList(Cs.ALL_CLIENTS.getValue()))
.elementHeader((byte) 0)
.ranges(Collections.singletonList(range))
.build();
control.send(createContext);
control.sync();
EnableContext enableContext = EnableContext
.builder()
.context(rc)
.build();
try (X11Client data = X11Client.connect()) {
EnableContextReply enableContextReply = data.send(enableContext);
log.info(String.format("enableContextReply: %s", enableContextReply));
}
}
I still get a category == 4 reply though.
The rust client shows an issue that I'm not sure my client is made to handle. It looks like it has mutliple replies.
for reply in data_conn.record_enable_context(rc)? {
let reply = reply?;
if reply.client_swapped {
println!("Byte swapped clients are unsupported");
} else if reply.category == RECORD_FROM_SERVER {
let mut remaining = &reply.data[..];
let mut should_exit = false;
while !remaining.is_empty() {
let (r, exit) = print_reply_data(&reply.data)?;
remaining = r;
if exit {
should_exit = true;
}
}
if should_exit {
break;
}
} else if reply.category == START_OF_DATA {
println!("Press Escape to exit...");
} else {
println!("Got a reply with an unsupported category: {:?}", reply);
}
}
The current client does not support multiple replies for one request and I'm not sure it makes sense to me yet. Maybe these are events though. I'm just not sure.
To test multiple replies I added this.
try (X11Client data = X11Client.connect()) {
EnableContextReply enableContextReply = data.send(enableContext);
log.info(String.format("enableContextReply: %s", enableContextReply));
data.getNextEvent();
data.getNextEvent();
}
Then I get an error
com.github.moaxcp.x11client.X11ClientException: reply not expected when reading events
at app//com.github.moaxcp.x11client.XProtocolService.getNextEvent(XProtocolService.java:138)
at app//com.github.moaxcp.x11client.X11Client.getNextEvent(X11Client.java:251)
at app//com.github.moaxcp.x11client.RecordIT.test(RecordIT.java:54)
at java.base@17.0.7/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base@17.0.7/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
It seems like a special case for the record extension and I'm not sure how to change the api for it.
I added this PR that seems to work. https://github.com/moaxcp/x11-client/pull/27
I updated the PR to help in reading the data in the record replies. Reading x11 replies is going to be tricky because I also need to track the sequence numbers of the requests to figure out what reply is being read.
I updated the PR with everything I have. I don't think it will work for reading requests and replies but it does work for most examples I have seen online.
I merged the PR and published the changes in 0.15.0. It should show up in maven soon.
my code
the code can't work, got this exception
is somewhere wrong?