1 /**********************************************************************
2 Copyright (c) 2000, 2002 IBM Corp. and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Common Public License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/legal/cpl-v10.html
9 Vicente Fernando - www.alfersoft.com.ar - Initial implementation
10 Christian Perkonig - remote debug
11 **********************************************************************/
12 package net.sourceforge.phpdt.internal.debug.core;
14 import java.io.IOException;
15 import java.io.BufferedReader;
16 import java.io.OutputStream;
17 import java.util.Vector;
19 import org.eclipse.core.runtime.IStatus;
20 import org.eclipse.core.runtime.Status;
21 import org.eclipse.debug.core.DebugException;
23 import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
24 import net.sourceforge.phpdt.internal.debug.core.model.PHPVariable;
25 import net.sourceforge.phpdt.internal.debug.core.model.PHPDBGEvalString;
27 public class PHPDBGInterface {
30 public boolean sessionEnded= false;
31 public int sessType= -1;
32 public int BPUnderHit= 0;
33 public String sessID= new String();
36 private int[] LastBPRead= new int[10];
37 private Vector DBGBPList= new Vector();
38 private PHPStackFrame[] DBGStackList;
39 private PHPVariable[] DBGVariableList;
40 private Vector DBGMods= new Vector();
41 private BufferedReader in;
42 private OutputStream os;
43 private boolean shouldStop= false;
44 private String evalRet= new String("");
45 private String serGlobals= new String("");
46 private int rawCounter=1000;
47 private PHPDBGProxy proxy= null;
49 private int lastCmd=-1;
51 private boolean stopOnError= false;
52 private char[] lastCommand= new char[4];
54 public PHPDBGInterface(BufferedReader in, OutputStream os, PHPDBGProxy proxy) {
61 public int addBreakpoint(String mod_name, int line) throws IOException {
62 return setBreakpoint(mod_name, "", line, PHPDBGBase.BPS_ENABLED + PHPDBGBase.BPS_UNRESOLVED, 0, 0, 0, 0, 0);
65 public void removeBreakpoint(String mod_name, int line, int bpNo) throws IOException {
66 setBreakpoint(mod_name, "", line, PHPDBGBase.BPS_DISABLED, 0, 0, 0, bpNo, 0);
69 public void requestDBGVersion() throws IOException {
70 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
71 PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_VER);
73 DBGPacket.addFrame(DBGFrame);
75 if(proxy.getSocket().isClosed()) return;
76 DBGPacket.sendPacket(os);
79 public void getSourceTree() throws IOException {
80 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
81 PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_SRC_TREE);
83 DBGPacket.addFrame(DBGFrame);
85 if(proxy.getSocket().isClosed()) return;
86 DBGPacket.sendPacket(os);
88 // Wait response (1 second) and read response
93 public void addDBGModName(String modName) throws IOException {
94 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
95 PHPDBGFrame DBGFrame= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
98 DBGFrame.addInt(rawCounter); // FRAME_RAWDATA ID
99 DBGFrame.addInt(modName.length() + 1); // length of rawdata (+ null char)
100 DBGFrame.addString(modName); // file name
101 DBGFrame.addChar('\0'); // null char
103 DBGPacket.addFrame(DBGFrame);
105 if(proxy.getSocket().isClosed()) return;
106 DBGPacket.sendPacket(os);
109 // Returns DBG Breakpoint ID
110 private int setBreakpoint(String mod_name, String condition, int line, int state, int istemp, int hitcount, int skiphits, int bpno, int isunderhit) throws IOException {
113 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
114 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_BPS);
115 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
117 modNo= getModByName(mod_name);
120 DBGFrame1.addInt(modNo); // mod number
122 DBGFrame1.addInt(0); // mod number (0 use file name)
125 DBGFrame1.addInt(line); // line number
128 DBGFrame1.addInt(0); // use mod number
131 DBGFrame1.addInt(rawCounter); // ID of FRAME_RAWDATA to send file name
134 DBGFrame1.addInt(state); // state BPS_*
135 DBGFrame1.addInt(istemp); // istemp
136 DBGFrame1.addInt(hitcount); // hit count
137 DBGFrame1.addInt(skiphits); // skip hits
138 DBGFrame1.addInt(0); // ID of condition
139 DBGFrame1.addInt(bpno); // breakpoint number
140 DBGFrame1.addInt(isunderhit); // is under hit
143 DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID
144 DBGFrame2.addInt(mod_name.length() + 1); // length of rawdata (+ null char)
145 DBGFrame2.addString(mod_name); // file name
146 DBGFrame2.addChar('\0'); // null char
147 // First add file name data
148 DBGPacket.addFrame(DBGFrame2);
151 // Second add command data
152 DBGPacket.addFrame(DBGFrame1);
154 if(proxy.getSocket().isClosed()) return 0;
155 DBGPacket.sendPacket(os);
159 // Wait response (1 second) and read response
163 return LastBPRead[8];
166 private void clearLastBP() {
169 for(i=0; i < LastBPRead.length; i++)
173 private void copyToLastBP(int[] BPBody) {
176 for(i=0; i < LastBPRead.length; i++)
177 LastBPRead[i]= BPBody[i];
180 public void continueExecution() throws IOException {
182 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_CONTINUE);
183 if(proxy.getSocket().isClosed()) return;
184 DBGPacket.sendPacket(os);
185 lastCommand= PHPDBGBase.DBGA_CONTINUE;
188 public void pauseExecution() throws IOException {
189 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.IntToChar4(PHPDBGBase.DBGC_PAUSE));
190 if(proxy.getSocket().isClosed()) return;
191 DBGPacket.sendPacket(os);
194 private int getBPUnderHit() {
196 int[] dbg_bpl_body= new int[10];
198 // look for bp under hit
199 for(i=0; i < DBGBPList.size(); i++) {
200 dbg_bpl_body= (int[]) DBGBPList.get(i);
201 if(dbg_bpl_body[9] == 1) {
202 BPUnder= dbg_bpl_body[8];
208 public int getLastCmd()
218 public void setLastCmd(int cmd)
223 public void stepInto() throws IOException {
225 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPINTO);
226 if(proxy.getSocket().isClosed()) return;
227 DBGPacket.sendPacket(os);
228 lastCommand= PHPDBGBase.DBGA_STEPINTO;
231 public void stepOver() throws IOException {
233 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOVER);
234 if(proxy.getSocket().isClosed()) return;
235 DBGPacket.sendPacket(os);
236 lastCommand= PHPDBGBase.DBGA_STEPOVER;
239 public void stepOut() throws IOException {
241 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STEPOUT);
242 if(proxy.getSocket().isClosed()) return;
243 DBGPacket.sendPacket(os);
244 lastCommand= PHPDBGBase.DBGA_STEPOUT;
247 public void stopExecution() throws IOException {
249 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_STOP);
250 if(proxy.getSocket().isClosed()) return;
251 DBGPacket.sendPacket(os);
254 public PHPVariable[] getVariables(PHPStackFrame stack) throws IOException, DebugException {
255 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
256 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
258 DBGFrame1.addInt(0); // istr = raw data ID
259 DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth
262 DBGPacket.addFrame(DBGFrame1);
264 if(proxy.getSocket().isClosed()) return null;
265 DBGPacket.sendPacket(os);
270 // Process serialized variables
271 PHPDBGEvalString evalStr=new PHPDBGEvalString(stack,serGlobals);
273 DBGVariableList= evalStr.getVars();
275 return DBGVariableList;
278 public void log(String logString) throws IOException, DebugException {
279 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
280 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_LOG);
281 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
284 DBGFrame1.addInt(rawCounter); // ilog
285 DBGFrame1.addInt(1); // type
286 DBGFrame1.addInt(0); // mod_no
287 DBGFrame1.addInt(0); // line_no
288 DBGFrame1.addInt(0); // imod_name
289 DBGFrame1.addInt(0); // ext_info
291 DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID
292 DBGFrame2.addInt(logString.length() + 1); // length of rawdata (+ null char)
293 DBGFrame2.addString(logString); // log string
294 DBGFrame2.addChar('\0'); // null char
296 // Add raw data first
297 DBGPacket.addFrame(DBGFrame2);
299 DBGPacket.addFrame(DBGFrame1);
301 if(proxy.getSocket().isClosed()) return;
302 DBGPacket.sendPacket(os);
308 public PHPVariable[] evalBlock(PHPStackFrame stack, String evalString) throws IOException, DebugException {
309 PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
310 PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
311 PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
314 DBGFrame1.addInt(rawCounter); // istr = raw data ID
315 DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth
317 DBGFrame2.addInt(rawCounter); // FRAME_RAWDATA ID
318 DBGFrame2.addInt(evalString.length() + 1); // length of rawdata (+ null char)
319 DBGFrame2.addString(evalString); // eval block
320 DBGFrame2.addChar('\0'); // null char
322 // Add raw data first
323 DBGPacket.addFrame(DBGFrame2);
325 DBGPacket.addFrame(DBGFrame1);
327 if(proxy.getSocket().isClosed()) return null;
328 DBGPacket.sendPacket(os);
333 PHPDBGEvalString evalStr=new PHPDBGEvalString(stack,evalRet);
335 return evalStr.getVars();
339 public void flushAllPackets() throws IOException {
340 while(readResponse() != 0);
343 public String getModByNo(int modNo) {
348 for(i=0; i < DBGMods.size(); i++) {
349 dbg_mod= (PHPDBGMod) DBGMods.get(i);
350 if(dbg_mod.getNo() == modNo) {
351 return dbg_mod.getName();
357 private int getModByName(String modName) {
362 for(i=0; i < DBGMods.size(); i++) {
363 dbg_mod= (PHPDBGMod) DBGMods.get(i);
364 if(dbg_mod.getName().equalsIgnoreCase(modName)) {
365 return dbg_mod.getNo();
371 private String getRawFrameData(char[] framesInfo, int frameNo) {
373 int[] dbg_frame= new int[2];
375 while(nextFrame < framesInfo.length) {
376 dbg_frame[0] = PHPDBGBase.Char4ToInt(framesInfo, nextFrame); // frame name
377 dbg_frame[1] = PHPDBGBase.Char4ToInt(framesInfo, nextFrame + 4); // frame size
380 if(dbg_frame[1] == 0) return "";
382 switch(dbg_frame[0]) {
383 case PHPDBGBase.FRAME_RAWDATA:
384 if(frameNo == PHPDBGBase.Char4ToInt(framesInfo, nextFrame)) {
385 int toRead= PHPDBGBase.Char4ToInt(framesInfo, nextFrame + 4);
386 return String.copyValueOf(framesInfo, nextFrame + 8, toRead);
391 nextFrame += dbg_frame[1];
397 public int readResponse() throws IOException {
398 int bytesToRead=0, nextFrame=0, i=0, cmdReceived=0, stackIndex=0;
399 boolean errorStack= false;
400 char[] dbg_header_struct_read= new char[16];
401 int[] dbg_header_struct= new int[4];
402 int[] dbg_bpl_tmp= new int[10];
403 int[] dbg_frame= new int[2];
404 int[] dbg_eval_tmp= new int[3];
405 int[] dbg_src_tree_tmp= new int[4];
406 int[] dbg_error_tmp= new int[2];
407 Vector rawList= new Vector();
408 Vector stackList= new Vector();
409 PHPStackFrame[] newStackList;
414 while(readInput(dbg_header_struct_read, 16) != 0) {
415 dbg_header_struct[0] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 0);
416 dbg_header_struct[1] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 4);
417 dbg_header_struct[2] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 8);
418 dbg_header_struct[3] = PHPDBGBase.Char4ToInt(dbg_header_struct_read, 12);
420 // Check DBG sync bytes
421 if(dbg_header_struct[0] != 0x5953) return 0;
423 cmdReceived= dbg_header_struct[1];
424 setLastCmd(cmdReceived);
425 bytesToRead= dbg_header_struct[3];
427 //System.out.println("Response Received: " + cmdReceived);
428 char[] entirePack= new char[bytesToRead];
430 if(bytesToRead > 0) {
431 if(readInput(entirePack, bytesToRead) < bytesToRead) return 0;
434 // First process frames
436 while(nextFrame < bytesToRead) {
437 dbg_frame[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame); // frame name
438 dbg_frame[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // frame size
440 if(dbg_frame[1] == 0) return 0;
441 switch(dbg_frame[0]) {
442 case PHPDBGBase.FRAME_STACK:
443 int[] dbg_stack_new= new int[4];
444 dbg_stack_new[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); // line no
445 dbg_stack_new[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // mod no
446 dbg_stack_new[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8); // scope id
447 dbg_stack_new[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12); // id of description string
449 if(dbg_stack_new[1] != 0 && !errorStack) {
451 PHPStackFrame newStack= new PHPStackFrame(null, getModByNo(dbg_stack_new[1]), dbg_stack_new[0], stackIndex, getRawFrameData(entirePack, dbg_stack_new[3]), dbg_stack_new[1]);
452 stackList.add(newStack);
456 case PHPDBGBase.FRAME_SOURCE:
458 case PHPDBGBase.FRAME_SRC_TREE:
459 dbg_src_tree_tmp[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); // parent_mod_no
460 dbg_src_tree_tmp[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // parent_line_no /* NOT USED */
461 dbg_src_tree_tmp[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8); // mod_no
462 dbg_src_tree_tmp[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12); // imod_name
464 if(getModByNo(dbg_src_tree_tmp[2]).equals("")) {
465 String fileName= new String(getRawFrameData(entirePack, dbg_src_tree_tmp[3]));
467 if(fileName.length() > 0) fileName= fileName.substring(0, fileName.length() - 1);
469 if(dbg_src_tree_tmp[2] != 0) {
470 PHPDBGMod modNew= new PHPDBGMod(dbg_src_tree_tmp[2], fileName);
475 case PHPDBGBase.FRAME_RAWDATA:
477 case PHPDBGBase.FRAME_ERROR:
479 dbg_error_tmp[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); // type /* type of error */
480 dbg_error_tmp[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // imessage /* ID of error message */
483 switch(dbg_error_tmp[0]) {
484 case PHPDBGBase.E_ERROR:
487 case PHPDBGBase.E_WARNING:
490 case PHPDBGBase.E_PARSE:
491 error+= "[Parse Error]";
493 case PHPDBGBase.E_NOTICE:
496 case PHPDBGBase.E_CORE_ERROR:
497 error+= "[Core Error]";
499 case PHPDBGBase.E_CORE_WARNING:
500 error+= "[Core Warning]";
502 case PHPDBGBase.E_COMPILE_ERROR:
503 error+= "[Compile Error]";
505 case PHPDBGBase.E_COMPILE_WARNING:
506 error+= "[Compile Warning]";
508 case PHPDBGBase.E_USER_ERROR:
509 error+= "[User Error]";
511 case PHPDBGBase.E_USER_WARNING:
512 error+= "[User Warning]";
514 case PHPDBGBase.E_USER_NOTICE:
515 error+= "[User Notice]";
518 error+= "[Unexpected Error]";
522 error+= new String(getRawFrameData(entirePack, dbg_error_tmp[1]));
524 if(error.length() > 0) error= error.substring(0, error.length() - 1);
527 PHPDebugCorePlugin.log(new DebugException(new Status(IStatus.WARNING, PHPDebugCorePlugin.PLUGIN_ID, IStatus.OK, error, null)));
528 // To print errors on the console, I must execute a code in the
529 // php context, that write the stderr... I didn't found a better way
530 // TODO: Find a better way????
532 codeExec= "fwrite(fopen('php://stderr', 'w'),\\\"" + error + "\\\");";
534 // evalBlock("eval(\"" + codeExec + "\");");
535 // } catch (DebugException e) {
536 // PHPDebugCorePlugin.log(e);
539 if(lastCommand.equals(PHPDBGBase.DBGA_CONTINUE)) {
541 } else if(lastCommand.equals(PHPDBGBase.DBGA_STEPINTO)) {
543 } else if(lastCommand.equals(PHPDBGBase.DBGA_STEPOUT)) {
545 } else if(lastCommand.equals(PHPDBGBase.DBGA_STEPOVER)) {
550 case PHPDBGBase.FRAME_EVAL:
551 String evalString= new String("");
552 dbg_eval_tmp[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0); // istr
553 dbg_eval_tmp[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4); // iresult
554 dbg_eval_tmp[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8); // ierror
556 evalRet= getRawFrameData(entirePack, dbg_eval_tmp[1]);
557 evalString= getRawFrameData(entirePack, dbg_eval_tmp[0]);
560 case PHPDBGBase.FRAME_BPS:
562 case PHPDBGBase.FRAME_BPL:
563 int[] dbg_bpl_new= new int[10];
564 dbg_bpl_new[0] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
565 dbg_bpl_new[1] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 4);
566 dbg_bpl_new[2] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 8);
567 dbg_bpl_new[3] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 12);
568 dbg_bpl_new[4] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 16);
569 dbg_bpl_new[5] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 20);
570 dbg_bpl_new[6] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 24);
571 dbg_bpl_new[7] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 28);
572 dbg_bpl_new[8] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 32);
573 dbg_bpl_new[9] = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 36);
575 // look if breakpoint already exists in vector
576 for(i=0; i < DBGBPList.size(); i++) {
577 dbg_bpl_tmp= (int[]) DBGBPList.get(i);
578 if(dbg_bpl_tmp[8] == dbg_bpl_new[8]) {
584 // add breakpoint to vector
585 DBGBPList.add(dbg_bpl_new);
586 copyToLastBP(dbg_bpl_new);
589 if(getModByNo(dbg_bpl_new[0]).equals("")) {
590 String fileName= new String(getRawFrameData(entirePack, dbg_bpl_new[2]));
592 if(fileName.length() > 0) fileName= fileName.substring(0, fileName.length() - 1);
593 if(dbg_bpl_new[0] != 0) {
594 PHPDBGMod modNew= new PHPDBGMod(dbg_bpl_new[0], fileName);
599 case PHPDBGBase.FRAME_VER:
601 case PHPDBGBase.FRAME_SID:
602 sid = PHPDBGBase.Char4ToInt(entirePack, nextFrame + 0);
604 case PHPDBGBase.FRAME_SRCLINESINFO:
606 case PHPDBGBase.FRAME_SRCCTXINFO:
608 case PHPDBGBase.FRAME_LOG:
610 case PHPDBGBase.FRAME_PROF:
612 case PHPDBGBase.FRAME_PROF_C:
614 case PHPDBGBase.FRAME_SET_OPT:
618 nextFrame += dbg_frame[1];
621 // Now process command
622 switch(cmdReceived) {
623 case PHPDBGBase.DBGC_REPLY:
625 case PHPDBGBase.DBGC_STARTUP:
627 case PHPDBGBase.DBGC_END:
630 case PHPDBGBase.DBGC_BREAKPOINT:
631 newStackList= new PHPStackFrame[stackList.size()];
632 newStackList= (PHPStackFrame[]) stackList.toArray(newStackList);
633 DBGStackList= newStackList;
634 BPUnderHit= getBPUnderHit();
636 case PHPDBGBase.DBGC_STEPINTO_DONE:
637 case PHPDBGBase.DBGC_STEPOVER_DONE:
638 case PHPDBGBase.DBGC_STEPOUT_DONE:
639 case PHPDBGBase.DBGC_EMBEDDED_BREAK:
640 case PHPDBGBase.DBGC_PAUSE:
642 newStackList= new PHPStackFrame[stackList.size()];
643 newStackList= (PHPStackFrame[]) stackList.toArray(newStackList);
644 DBGStackList= newStackList;
646 case PHPDBGBase.DBGC_ERROR:
648 newStackList= new PHPStackFrame[stackList.size()];
649 newStackList= (PHPStackFrame[]) stackList.toArray(newStackList);
650 DBGStackList= newStackList;
652 case PHPDBGBase.DBGC_LOG:
654 case PHPDBGBase.DBGC_SID:
661 public PHPStackFrame[] getStackList() {
665 private int readInput(char[] buffer, int bytes) throws IOException {
668 for(int i=0; i < bytes; i++) {
670 buffer[i]= (char) (in.read() & 0x00FF);
679 public void setShouldStop() {
680 this.shouldStop= true;
683 public boolean waitResponse(long milliseconds) throws IOException {
684 long timeout= System.currentTimeMillis() + milliseconds;
685 while(System.currentTimeMillis() < timeout) {
686 if(in.ready() || shouldStop) {