# j_server.cc

Go to the documentation of this file.

    00001 ///
    00002 /// \file       j_server.cc
    00003 ///             Server protocol implementation
    00004 ///
    00005
    00006 /*
    00007     Copyright (C) 2009, Nicolas VIVIEN
    00008
    00009     This program is free software; you can redistribute it and/or modify
    00010     it under the terms of the GNU General Public License as published by
    00011     the Free Software Foundation; either version 2 of the License, or
    00012     (at your option) any later version.
    00013
    00014     This program is distributed in the hope that it will be useful,
    00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00017
    00018     See the GNU General Public License in the COPYING file at the
    00019     root directory of this project for more details.
    00020 */
    00021
    00022 #include "j_server.h"
    00023 #include "protocol.h"
    00024 #include "data.h"
    00025 #include "endian.h"
    00026 #include "debug.h"
    00027 #include "j_message.h"
    00028 #include "protostructs.h"
    00029 #include "record-internal.h"
    00030 #include "error.h"
    00031
    00032 #include <unistd.h>
    00033 #include <fcntl.h>
    00034 #include <sys/types.h>
    00035 #include <sys/socket.h>
    00036 #include <netinet/in.h>
    00037 #include <arpa/inet.h>
    00038 #include <netdb.h>
    00039 #include <string.h>
    00040 #include <errno.h>
    00041
    00042 #include <sstream>
    00043 #include <algorithm>
    00044
    00045 using namespace std;
    00046
    00047 namespace Barry { namespace JDWP {
    00048
    00049 static void * acceptThread(void *data);
    00050
    00051
    00052 JDWServer::JDWServer(Barry::Mode::JVMDebug &device,
    00053                         const char *address, int port)
    00054         : jvmdebug(&device)
    00055         , acceptfd(-1)
    00056         , sockfd(-1)
    00057         , address(address)
    00058         , port(port)
    00059         , loop(false)
    00060         , targetrunning(false)
    00061         , printConsoleMessage(0)
    00062 {
    00063         SearchDebugFile(debugFileList);
    00064 }
    00065
    00066
    00067 JDWServer::~JDWServer()
    00068 {
    00069         Stop();
    00070 }
    00071
    00072
    00073 void JDWServer::SetPasswordDevice(string password)
    00074 {
    00075         this->password = password;
    00076 }
    00077
    00078
    00079 void JDWServer::SetConsoleCallback(ConsoleCallbackType callback)
    00080 {
    00081         printConsoleMessage = callback;
    00082 }
    00083
    00084 static const char* h_strerror(int code)
    00085 {
    00086         // Codes and messages taken from the Linux gethostbyname(3) manpage
    00087         switch( code )
    00088         {
    00089         case HOST_NOT_FOUND:
    00090                 return "HOST_NOT_FOUND: The specified host is unknown";
    00091
    00092         case NO_ADDRESS:
    00093                 return "NO_ADDRESS: The requested name is valid but does not have an IP address";
    00094
    00095         case NO_RECOVERY:
    00096                 return "NO_RECOVERY: A non-recoverable name server error occurred";
    00097
    00098         case TRY_AGAIN:
    00099                 return "TRY_AGAIN: A temporary error occurred on an authoritative name server. Try again later.";
    00100
    00101         default:
    00102                 return "Unknown network error code";
    00103         }
    00104 }
    00105
    00106 bool JDWServer::Start()
    00107 {
    00108         int rc;
    00109
    00110         struct hostent *hp;
    00111         struct sockaddr_in sad;
    00112
    00113
    00114         memset((char *) &sad, '\0', sizeof(struct sockaddr_in));
    00115
    00116         if (!address.size())
    00117                 sad.sin_addr.s_addr = INADDR_ANY;
    00118         else {
    00119                 sad.sin_addr.s_addr = inet_addr(address.c_str());
    00120
    00121                 if (sad.sin_addr.s_addr == INADDR_NONE) {
    00122                         hp = gethostbyname(address.c_str());
    00123
    00124                         if (hp == NULL) {
    00125                                 std::ostringstream oss;
    00126                                 oss << "JDWServer::Start: " << h_errno << h_strerror(h_errno);
    00127                                 throw Barry::Error(oss.str());
    00128                         }
    00129
    00130                         memcpy((char*) &sad.sin_addr, (char*) hp->h_addr, (size_t) hp->h_length);
    00131                 }
    00132         }
    00133
    00134         sad.sin_family = AF_INET;
    00135         sad.sin_port = htons((short) (port & 0xFFFF));
    00136
    00137         // Open socket
    00138         sockfd = socket(sad.sin_family, SOCK_STREAM, 0);
    00139
    00140         if (sockfd < 0) {
    00141                 throw Barry::ErrnoError("JDWServer::Start: Cannot open socket.", errno);
    00142         }
    00143
    00144         // Bind
    00145         rc = bind(sockfd, (struct sockaddr *) &sad, sizeof(sad));
    00146
    00147         if (rc < 0) {
    00148                 int code = errno;
    00149
    00150                 close(sockfd);
    00151                 sockfd = -1;
    00152
    00153                 throw Barry::ErrnoError("JDWServer::Start: Cannot bind socket", code);
    00154         }
    00155
    00156         // Listen
    00157         if (listen(sockfd, SOMAXCONN) < 0) {
    00158                 int code = errno;
    00159
    00160                 close(sockfd);
    00161                 sockfd = -1;
    00162
    00163                 throw Barry::ErrnoError("JDWServer::Start: Cannot listen on socket", code);
    00164         }
    00165
    00166         handler.reset(new Thread(sockfd, acceptThread, (void*) this));
    00167
    00168         return true;
    00169 }
    00170
    00171
    00172 static void * acceptThread(void *data)
    00173 {
    00174         JDWServer *s;
    00175
    00176         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    00177
    00178         s = (JDWServer *) data;
    00179
    00180         while (1) {
    00181                 if( s->AcceptConnection() &&
    00182                         s->AttachToDevice() &&
    00183                         s->InitVisibleClassList() &&
    00184                         s->Hello() )
    00185                 {
    00186                         s->Run();
    00187                         s->DetachFromDevice();
    00188                 }
    00189         }
    00190
    00191         return NULL;
    00192 }
    00193
    00194
    00195 // Returns true if a new connection was accepted and established
    00196 bool JDWServer::AcceptConnection()
    00197 {
    00198         struct sockaddr_in addr;
    00199         struct sockaddr *sa = (struct sockaddr*) &addr;
    00200         socklen_t addrlen = sizeof(addr);
    00201
    00202         acceptfd = accept(sockfd, sa, &addrlen);
    00203         if( acceptfd < 0 )
    00204                 return false;
    00205
    00206         fcntl(acceptfd, F_SETFL, O_NONBLOCK);
    00207         return true;
    00208 }
    00209
    00210
    00211 bool JDWServer::AttachToDevice()
    00212 {
    00213         targetrunning = false;
    00214
    00215         jvmdebug->Open(password.c_str());
    00216         jvmdebug->Attach();
    00217
    00218         jvmdebug->Unknown01();
    00219         jvmdebug->Unknown02();
    00220         jvmdebug->Unknown03();
    00221         jvmdebug->Unknown04();
    00222         jvmdebug->Unknown05();
    00223
    00224         jvmdebug->GetModulesList(modulesList);
    00225         dout(modulesList);
    00226
    00227         // Check debug info for each modules
    00228         JVMModulesList::const_iterator b = modulesList.begin();
    00229         for ( ; b != modulesList.end(); b++) {
    00230                 JDG::CodInfo codInfo;
    00231
    00232                 const JVMModulesEntry &entry = *b;
    00233
    00234                 bool ret = LoadDebugInfo(debugFileList, entry.UniqueID, entry.Name, codInfo);
    00235
    00236                 if (ret == true) {
    00237                         appList[entry.UniqueID].Load(codInfo);
    00238                 }
    00239                 else {
    00240                         dout("No debug information found for '" << entry.Name);
    00241                         dout("' (" << hex << setfill('0') << setw(8) << entry.UniqueID << ")." << endl)
    00242                 }
    00243         }
    00244
    00245         return true;
    00246 }
    00247
    00248
    00249 void JDWServer::DetachFromDevice()
    00250 {
    00251         jvmdebug->Detach();
    00252         jvmdebug->Close();
    00253 }
    00254
    00255
    00256 #define JDWP_HELLO_STRING               "JDWP-Handshake"
    00257
    00258
    00259
    00260 bool JDWServer::Hello()
    00261 {
    00262         bool ret;
    00263
    00264         Barry::Data response;
    00265
    00266         const size_t len = strlen(JDWP_HELLO_STRING);
    00267
    00268         JDWMessage msg(acceptfd);
    00269
    00270         do {
    00271                 ret = msg.Receive(response);
    00272         }
    00273         while (!ret);
    00274
    00275         size_t size = response.GetSize();
    00276         char *str = (char *) response.GetBuffer();
    00277
    00278         if (size != len)
    00279                 return false;
    00280
    00281         if (!strncmp(str, JDWP_HELLO_STRING, len)) {
    00282                 Data command(JDWP_HELLO_STRING, len);
    00283
    00284                 msg.Send(command);
    00285
    00286                 return true;
    00287         }
    00288
    00289         return false;
    00290 }
    00291
    00292
    00293 void JDWServer::Run()
    00294 {
    00295         string str;
    00296         JDWMessage msg(acceptfd);
    00297
    00298         Barry::Data command;
    00299
    00300         MAKE_JDWPPACKET(rpack, command);
    00301
    00302         loop = true;
    00303
    00304         while (loop) {
    00305                 if (targetrunning) {
    00306                         // Read JDWP message from device
    00307                         int value = jvmdebug->GetConsoleMessage(str);
    00308
    00309                         if (value < 0) {
    00310                                 bool ret;
    00311                                 int status;
    00312
    00313                                 ret = jvmdebug->GetStatus(status);
    00314
    00315                                 while (!ret) {
    00316                                         // Read JDB message from host
    00317                                         msg.Receive(command);
    00318
    00319                                         if (command.GetSize() > 0) {
    00320                                                 // Convert to packet
    00321                                                 rpack = (const Barry::Protocol::JDWP::Packet *) command.GetData();
    00322
    00323                                                 if (command.GetSize() != be_btohl(rpack->length)) {
    00324                                                         dout("Packet size error !!!" << endl);
    00325
    00326                                                         // TODO : add throw exception
    00327
    00328                                                         continue;
    00329                                                 }
    00330
    00331                                                 CommandsetProcess(command);
    00332
    00333                                                 break;
    00334                                         }
    00335                                         else
    00336                                                 ret = jvmdebug->WaitStatus(status);
    00337                                 }
    00338                         }
    00339                         else {
    00340                                 if (printConsoleMessage != NULL)
    00341                                         printConsoleMessage(str);
    00342                         }
    00343                 }
    00344                 else {
    00345                         // Read JDB message from host
    00346                         msg.Receive(command);
    00347
    00348                         if (command.GetSize() > 0) {
    00349                                 // Convert to packet
    00350                                 rpack = (const Barry::Protocol::JDWP::Packet *) command.GetData();
    00351
    00352                                 if (command.GetSize() != be_btohl(rpack->length)) {
    00353                                         dout("Packet size error !!!" << endl);
    00354
    00355                                         // TODO : add throw exception
    00356
    00357                                         continue;
    00358                                 }
    00359
    00360                                 CommandsetProcess(command);
    00361                         }
    00362
    00363                         usleep(50);
    00364                 }
    00365         }
    00366 }
    00367
    00368
    00369 bool JDWServer::Stop()
    00370 {
    00371         if( handler.get() ) {
    00372                 handler->Dispose();
    00373                 handler.reset();
    00374         }
    00375
    00376         if( sockfd >= 0 ) {
    00377                 close(sockfd);
    00378                 sockfd = -1;
    00379         }
    00380
    00381         if( acceptfd >= 0 ) {
    00382                 close(acceptfd);
    00383                 acceptfd = -1;
    00384         }
    00385
    00386         return true;
    00387 }
    00388
    00389
    00390 bool JDWServer::InitVisibleClassList()
    00391 {
    00392         int index;
    00393
    00394         // Skip the cell '0'
    00395         // it's very ugly, but I want use an index started at '1' inside of '0'
    00396         // JDB works from '1' :(
    00397         JDG::ClassEntry e;
    00398         visibleClassList.push_back(e);
    00399
    00400         // Count and index the class (start to '1')
    00401         index = 1;
    00402         JDWAppList::iterator it;
    00403
    00404         for (it = appList.begin(); it != appList.end(); it++) {
    00405                 JDWAppInfo &appInfo = it->second;
    00406                 JDG::ClassList &list = appInfo.classList;
    00407
    00408                 JDG::ClassList::iterator b;
    00409
    00410                 for (b = list.begin(); b != list.end(); b++) {
    00411                         // FIXME
    00412                         // I don't from class field, we have to filter the class view by JDB
    00413 //                      if ((b->type != 0x824) && (b->type != 0x64)) {
    00414                         if (b->id == 0xffffffff) {
    00415                                 b->index = -1;
    00416
    00417                                 continue;
    00418                         }
    00419
    00420                         b->index = index;
    00421
    00422                         visibleClassList.push_back(*b);
    00423
    00424                         index++;
    00425                 }
    00426         }
    00427
    00428         visibleClassList.CreateDefaultEntries();
    00429
    00430         return true;
    00431 }
    00432
    00433
    00434 void JDWServer::CommandsetProcess(Data &cmd)
    00435 {
    00436         MAKE_JDWPPACKET(rpack, cmd);
    00437
    00438         switch (rpack->u.command.commandset) {
    00439                 case JDWP_CMDSET_VIRTUALMACHINE:
    00440                         CommandsetVirtualMachineProcess(cmd);
    00441                         break;
    00442
    00443                 case JDWP_CMDSET_REFERECENTYPE:
    00444                         break;
    00445
    00446                 case JDWP_CMDSET_CLASSTYPE:
    00447                         break;
    00448
    00449                 case JDWP_CMDSET_ARRAYTYPE:
    00450                         break;
    00451
    00452                 case JDWP_CMDSET_INTERFACETYPE:
    00453                         break;
    00454
    00455                 case JDWP_CMDSET_METHOD:
    00456                         break;
    00457
    00458                 case JDWP_CMDSET_FIELD:
    00459                         break;
    00460
    00461                 case JDWP_CMDSET_OBJECTREFERENCE:
    00462                         break;
    00463
    00464                 case JDWP_CMDSET_STRINGREFERENCE:
    00465                         break;
    00466
    00467                 case JDWP_CMDSET_THREADREFERENCE:
    00468                         break;
    00469
    00470                 case JDWP_CMDSET_THREADGROUPREFERENCE:
    00471                         break;
    00472
    00473                 case JDWP_CMDSET_ARRAYREFERENCE:
    00474                         break;
    00475
    00476                 case JDWP_CMDSET_CLASSLOADERREFERENCE:
    00477                         break;
    00478
    00479                 case JDWP_CMDSET_EVENTREQUEST:
    00480                         CommandsetEventRequestProcess(cmd);
    00481                         break;
    00482
    00483                 case JDWP_CMDSET_STACKFRAME:
    00484                         break;
    00485
    00486                 case JDWP_CMDSET_CLASSOBJECTREFERENCE:
    00487                         break;
    00488
    00489                 case JDWP_CMDSET_EVENT:
    00490                         break;
    00491
    00492                 default:
    00493                         // TODO : add exception (or alert)
    00494                         dout("Commandset unknown !!!" << endl);
    00495         }
    00496 }
    00497
    00498
    00499 void JDWServer::CommandsetVirtualMachineProcess(Data &cmd)
    00500 {
    00501         MAKE_JDWPPACKET(rpack, cmd);
    00502
    00503         switch (rpack->u.command.command) {
    00504                 case JDWP_CMD_VERSION:
    00505                         CommandVersion(cmd);
    00506                         break;
    00507
    00508                 case JDWP_CMD_ALLCLASSES:
    00509                         CommandAllClasses(cmd);
    00510                         break;
    00511
    00512                 case JDWP_CMD_ALLTHREADS:
    00513                         CommandAllThreads(cmd);
    00514                         break;
    00515
    00516                 case JDWP_CMD_DISPOSE:
    00517                         loop = false;
    00518                         targetrunning = false;
    00519                         close(acceptfd);
    00520                         acceptfd = -1;
    00521                         break;
    00522
    00523                 case JDWP_CMD_IDSIZES:
    00524                         CommandIdSizes(cmd);
    00525                         break;
    00526
    00527                 case JDWP_CMD_SUSPEND:
    00528                         CommandSuspend(cmd);
    00529                         targetrunning = false;
    00530                         break;
    00531
    00532                 case JDWP_CMD_RESUME:
    00533                         CommandResume(cmd);
    00534                         targetrunning = true;
    00535                         break;
    00536
    00537                 case JDWP_CMD_CLASSPATHS:
    00538                         CommandClassPaths(cmd);
    00539                         break;
    00540         }
    00541 }
    00542
    00543
    00544 void JDWServer::CommandsetEventRequestProcess(Data &cmd)
    00545 {
    00546         MAKE_JDWPPACKET(rpack, cmd);
    00547
    00548         switch (rpack->u.command.command) {
    00549                 case JDWP_CMD_SET:
    00550                         CommandSet(cmd);
    00551                         break;
    00552         }
    00553 }
    00554
    00555
    00556 void JDWServer::CommandVersion(Data &cmd)
    00557 {
    00558         JDWMessage msg(acceptfd);
    00559
    00560         // Build packet data
    00561         Data response;
    00562
    00563         size_t offset = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
    00564
    00565         AddJDWString(response, offset, string("RIM JVM"));
    00566         AddJDWInt(response, offset, be_htobl(1));
    00567         AddJDWInt(response, offset, be_htobl(4));
    00568         AddJDWString(response, offset, string("1.4"));
    00569         AddJDWString(response, offset, string("RIM JVM"));
    00570
    00571         response.ReleaseBuffer(offset);
    00572
    00573
    00574         size_t total_size = response.GetSize();
    00575
    00576         // Fill in the header values
    00577         MAKE_JDWPPACKETPTR_BUF(cpack, response.GetBuffer(total_size));
    00578         Barry::Protocol::JDWP::Packet &packet = *cpack;
    00579
    00580
    00581         MAKE_JDWPPACKET(rpack, cmd);
    00582
    00583         packet.length = be_htobl(total_size);
    00584         packet.id = rpack->id;
    00585         packet.flags = 0x80;
    00586         packet.u.response.errorcode = be_htobs(0);
    00587
    00588         response.ReleaseBuffer(total_size);
    00589         msg.Send(response);
    00590 }
    00591
    00592
    00593 void JDWServer::CommandAllClasses(Data &cmd)
    00594 {
    00595         size_t i;
    00596         int size;
    00597
    00598         JDWMessage msg(acceptfd);
    00599
    00600         // Build packet data
    00601         Data response;
    00602
    00603         size_t offset = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
    00604
    00605         // Size of known class list
    00606         size = visibleClassList.size() - 1;
    00607
    00608         AddJDWInt(response, offset, be_htobl(size));
    00609
    00610         // Then, write the list of known class
    00611         for (i=1; i<visibleClassList.size(); i++) {
    00612                 string str = visibleClassList[i].GetFullClassName();
    00613
    00614                 str = "L" + str + ";";
    00615                 replace_if(str.begin(), str.end(), bind2nd(equal_to<char>(),'.'), '/');
    00616
    00617                 AddJDWByte(response, offset, 0x01);
    00618                 AddJDWInt(response, offset, i); // Should be equal to visibleClassList[i].index
    00619                 AddJDWString(response, offset, str);
    00620                 AddJDWInt(response, offset, be_htobl(0x04));
    00621         }
    00622
    00623         response.ReleaseBuffer(offset);
    00624
    00625
    00626         size_t total_size = response.GetSize();
    00627
    00628         // Fill in the header values
    00629         MAKE_JDWPPACKETPTR_BUF(cpack, response.GetBuffer(total_size));
    00630         Barry::Protocol::JDWP::Packet &packet = *cpack;
    00631
    00632
    00633         MAKE_JDWPPACKET(rpack, cmd);
    00634
    00635         packet.length = be_htobl(total_size);
    00636         packet.id = rpack->id;
    00637         packet.flags = 0x80;
    00638         packet.u.response.errorcode = be_htobs(0);
    00639
    00640         response.ReleaseBuffer(total_size);
    00641         msg.Send(response);
    00642 }
    00643
    00644
    00645 void JDWServer::CommandAllThreads(Data &cmd)
    00646 {
    00647         JDWMessage msg(acceptfd);
    00648
    00649         // Get threads list from device
    00650         JVMThreadsList list;
    00651         jvmdebug->GetThreadsList(list);
    00652         dout(list);
    00653
    00654         // Build packet data
    00655         Data response;
    00656
    00657         size_t offset = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
    00658
    00659         // Indicate the number of element
    00660         AddJDWInt(response, offset, be_htobl(list.size()));
    00661
    00662         // Send all threads ID
    00663         JVMThreadsList::const_iterator b = list.begin();
    00664         for( ; b != list.end(); b++ ) {
    00665                 const JVMThreadsEntry &entry = *b;
    00666
    00667                 AddJDWInt(response, offset, be_htobl(entry.Id));
    00668         }
    00669
    00670         response.ReleaseBuffer(offset);
    00671
    00672
    00673         size_t total_size = response.GetSize();
    00674
    00675         // Fill in the header values
    00676         MAKE_JDWPPACKETPTR_BUF(cpack, response.GetBuffer(total_size));
    00677         Barry::Protocol::JDWP::Packet &packet = *cpack;
    00678
    00679
    00680         MAKE_JDWPPACKET(rpack, cmd);
    00681
    00682         packet.length = be_htobl(total_size);
    00683         packet.id = rpack->id;
    00684         packet.flags = 0x80;
    00685         packet.u.response.errorcode = be_htobs(0);
    00686
    00687         response.ReleaseBuffer(total_size);
    00688         msg.Send(response);
    00689 }
    00690
    00691
    00692 void JDWServer::CommandIdSizes(Data &cmd)
    00693 {
    00694         JDWMessage msg(acceptfd);
    00695
    00696         MAKE_JDWPPACKET(rpack, cmd);
    00697
    00698         size_t size;
    00699
    00700         Barry::Protocol::JDWP::Packet packet;
    00701
    00702         size = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE
    00703                 + JDWP_PACKETVIRTUALMACHINEIDSIZES_DATA_SIZE;
    00704
    00705         packet.length = be_htobl(size);
    00706         packet.id = rpack->id;
    00707         packet.flags = 0x80;
    00708         packet.u.response.errorcode = be_htobs(0);
    00709         packet.u.response.u.virtualMachine.u.IDSizes.fieldIDSize = be_htobl(0x04);
    00710         packet.u.response.u.virtualMachine.u.IDSizes.methodIDSize = be_htobl(0x04);
    00711         packet.u.response.u.virtualMachine.u.IDSizes.objectIDSize = be_htobl(0x04);
    00712         packet.u.response.u.virtualMachine.u.IDSizes.referenceTypeIDSize = be_htobl(0x04);
    00713         packet.u.response.u.virtualMachine.u.IDSizes.frameIDSize = be_htobl(0x04);
    00714
    00715         Data response(&packet, size);
    00716
    00717         msg.Send(response);
    00718 }
    00719
    00720
    00721 void JDWServer::CommandSuspend(Data &cmd)
    00722 {
    00723         JDWMessage msg(acceptfd);
    00724
    00725
    00726         // Suspend device
    00727         jvmdebug->Stop();
    00728
    00729         // Notify debugger
    00730         MAKE_JDWPPACKET(rpack, cmd);
    00731
    00732         size_t size;
    00733
    00734         Barry::Protocol::JDWP::Packet packet;
    00735
    00736         size = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
    00737
    00738         packet.length = be_htobl(size);
    00739         packet.id = rpack->id;
    00740         packet.flags = 0x80;
    00741         packet.u.response.errorcode = be_htobs(0);
    00742
    00743         Data response(&packet, size);
    00744
    00745         msg.Send(response);
    00746 }
    00747
    00748
    00749 void JDWServer::CommandResume(Data &cmd)
    00750 {
    00751         JDWMessage msg(acceptfd);
    00752
    00753
    00754         // Resume device
    00755         jvmdebug->Unknown06();
    00756         jvmdebug->Unknown07();
    00757         jvmdebug->Unknown08();
    00758         jvmdebug->Unknown09();
    00759         jvmdebug->Unknown10();
    00760         jvmdebug->Go();
    00761
    00762         // Notify debugger
    00763         MAKE_JDWPPACKET(rpack, cmd);
    00764
    00765         size_t size;
    00766
    00767         Barry::Protocol::JDWP::Packet packet;
    00768
    00769         size = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
    00770
    00771         packet.length = be_htobl(size);
    00772         packet.id = rpack->id;
    00773         packet.flags = 0x80;
    00774         packet.u.response.errorcode = be_htobs(0);
    00775
    00776         Data response(&packet, size);
    00777
    00778         msg.Send(response);
    00779 }
    00780
    00781
    00782 void JDWServer::CommandClassPaths(Data &cmd)
    00783 {
    00784         JDWMessage msg(acceptfd);
    00785
    00786         // Build packet data
    00787         Data response;
    00788
    00789         size_t offset = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
    00790
    00791         AddJDWString(response, offset, string(""));
    00792         AddJDWInt(response, offset, be_htobl(0));
    00793         AddJDWInt(response, offset, be_htobl(0));
    00794
    00795         response.ReleaseBuffer(offset);
    00796
    00797
    00798         size_t total_size = response.GetSize();
    00799
    00800         // Fill in the header values
    00801         MAKE_JDWPPACKETPTR_BUF(cpack, response.GetBuffer(total_size));
    00802         Barry::Protocol::JDWP::Packet &packet = *cpack;
    00803
    00804
    00805         MAKE_JDWPPACKET(rpack, cmd);
    00806
    00807         packet.length = be_htobl(total_size);
    00808         packet.id = rpack->id;
    00809         packet.flags = 0x80;
    00810         packet.u.response.errorcode = be_htobs(0);
    00811
    00812         response.ReleaseBuffer(total_size);
    00813         msg.Send(response);
    00814 }
    00815
    00816
    00817
    00818 void JDWServer::CommandSet(Data &cmd)
    00819 {
    00820         static int value = 2;
    00821
    00822         JDWMessage msg(acceptfd);
    00823
    00824         MAKE_JDWPPACKET(rpack, cmd);
    00825
    00826         size_t size;
    00827
    00828         Barry::Protocol::JDWP::Packet packet;
    00829
    00830         size = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE + sizeof(uint32_t);
    00831
    00832         packet.length = be_htobl(size);
    00833         packet.id = rpack->id;
    00834         packet.flags = 0x80;
    00835         packet.u.response.errorcode = be_htobs(0);
    00836         packet.u.response.u.value = be_htobl(value);
    00837
    00838         Data response(&packet, size);
    00839
    00840         msg.Send(response);
    00841
    00842         value++;
    00843 }
    00844
    00845
    00846 }} // namespace Barry::JDWP
    00847