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(Barry::Thread::CallbackData *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(Barry::Thread::CallbackData *data)
00173 {
00174         JDWServer *s = (JDWServer *) data->userdata;
00175 
00176         while( !data->stopflag ) {
00177                 if( s->AcceptConnection() &&
00178                         s->AttachToDevice() &&
00179                         s->InitVisibleClassList() &&
00180                         s->Hello() )
00181                 {
00182                         s->Run(data->stopflag);
00183                         s->DetachFromDevice();
00184                 }
00185         }
00186 
00187         return NULL;
00188 }
00189 
00190 
00191 // Returns true if a new connection was accepted and established
00192 bool JDWServer::AcceptConnection()
00193 {
00194         struct sockaddr_in addr;
00195         struct sockaddr *sa = (struct sockaddr*) &addr;
00196         socklen_t addrlen = sizeof(addr);
00197 
00198         acceptfd = accept(sockfd, sa, &addrlen);
00199         if( acceptfd < 0 )
00200                 return false;
00201 
00202         fcntl(acceptfd, F_SETFL, O_NONBLOCK);
00203         return true;
00204 }
00205 
00206 
00207 bool JDWServer::AttachToDevice()
00208 {
00209         targetrunning = false;
00210 
00211         jvmdebug->Open(password.c_str());
00212         jvmdebug->Attach();
00213 
00214         jvmdebug->Unknown01();
00215         jvmdebug->Unknown02();
00216         jvmdebug->Unknown03();
00217         jvmdebug->Unknown04();
00218         jvmdebug->Unknown05();
00219 
00220         jvmdebug->GetModulesList(modulesList);
00221         dout(modulesList);
00222 
00223         // Check debug info for each modules
00224         JVMModulesList::const_iterator b = modulesList.begin();
00225         for ( ; b != modulesList.end(); b++) {
00226                 JDG::CodInfo codInfo;
00227 
00228                 const JVMModulesEntry &entry = *b;
00229 
00230                 bool ret = LoadDebugInfo(debugFileList, entry.UniqueID, entry.Name, codInfo);
00231 
00232                 if (ret == true) {
00233                         appList[entry.UniqueID].Load(codInfo);
00234                 }
00235                 else {
00236                         dout("No debug information found for '" << entry.Name);
00237                         dout("' (" << hex << setfill('0') << setw(8) << entry.UniqueID << ")." << endl)
00238                 }
00239         }
00240 
00241         return true;
00242 }
00243 
00244 
00245 void JDWServer::DetachFromDevice()
00246 {
00247         jvmdebug->Detach();
00248         jvmdebug->Close();
00249 }
00250 
00251 
00252 #define JDWP_HELLO_STRING               "JDWP-Handshake"
00253 
00254 
00255 
00256 bool JDWServer::Hello()
00257 {
00258         bool ret;
00259 
00260         Barry::Data response;
00261 
00262         const size_t len = strlen(JDWP_HELLO_STRING);
00263 
00264         JDWMessage msg(acceptfd);
00265 
00266         do {
00267                 ret = msg.Receive(response);
00268         }
00269         while (!ret);
00270 
00271         size_t size = response.GetSize();
00272         char *str = (char *) response.GetBuffer();
00273 
00274         if (size != len)
00275                 return false;
00276 
00277         if (!strncmp(str, JDWP_HELLO_STRING, len)) {
00278                 Data command(JDWP_HELLO_STRING, len);
00279 
00280                 msg.Send(command);
00281 
00282                 return true;
00283         }
00284 
00285         return false;
00286 }
00287 
00288 
00289 void JDWServer::Run(volatile bool &stopflag)
00290 {
00291         string str;
00292         JDWMessage msg(acceptfd);
00293 
00294         Barry::Data command;
00295 
00296         MAKE_JDWPPACKET(rpack, command);
00297 
00298         loop = true;
00299 
00300         while( loop && !stopflag ) {
00301                 if (targetrunning) {
00302                         // Read JDWP message from device
00303                         int value = jvmdebug->GetConsoleMessage(str);
00304 
00305                         if (value < 0) {
00306                                 bool ret;
00307                                 int status;
00308 
00309                                 ret = jvmdebug->GetStatus(status);
00310 
00311                                 while (!ret) {
00312                                         // Read JDB message from host
00313                                         msg.Receive(command);
00314 
00315                                         if (command.GetSize() > 0) {
00316                                                 // Convert to packet
00317                                                 rpack = (const Barry::Protocol::JDWP::Packet *) command.GetData();
00318 
00319                                                 if (command.GetSize() != be_btohl(rpack->length)) {
00320                                                         dout("Packet size error !!!" << endl);
00321 
00322                                                         // TODO : add throw exception
00323 
00324                                                         continue;
00325                                                 }
00326 
00327                                                 CommandsetProcess(command);
00328 
00329                                                 break;
00330                                         }
00331                                         else
00332                                                 ret = jvmdebug->WaitStatus(status);
00333                                 }
00334                         }
00335                         else {
00336                                 if (printConsoleMessage != NULL)
00337                                         printConsoleMessage(str);
00338                         }
00339                 }
00340                 else {
00341                         // Read JDB message from host
00342                         msg.Receive(command);
00343 
00344                         if (command.GetSize() > 0) {
00345                                 // Convert to packet
00346                                 rpack = (const Barry::Protocol::JDWP::Packet *) command.GetData();
00347 
00348                                 if (command.GetSize() != be_btohl(rpack->length)) {
00349                                         dout("Packet size error !!!" << endl);
00350 
00351                                         // TODO : add throw exception
00352 
00353                                         continue;
00354                                 }
00355 
00356                                 CommandsetProcess(command);
00357                         }
00358 
00359                         usleep(50);
00360                 }
00361         }
00362 }
00363 
00364 
00365 bool JDWServer::Stop()
00366 {
00367         if( handler.get() ) {
00368                 handler->StopFlag();
00369                 handler.reset();
00370         }
00371 
00372         if( sockfd >= 0 ) {
00373                 close(sockfd);
00374                 sockfd = -1;
00375         }
00376 
00377         if( acceptfd >= 0 ) {
00378                 close(acceptfd);
00379                 acceptfd = -1;
00380         }
00381 
00382         return true;
00383 }
00384 
00385 
00386 bool JDWServer::InitVisibleClassList()
00387 {
00388         int index;
00389 
00390         // Skip the cell '0'
00391         // it's very ugly, but I want use an index started at '1' inside of '0'
00392         // JDB works from '1' :(
00393         JDG::ClassEntry e;
00394         visibleClassList.push_back(e);
00395 
00396         // Count and index the class (start to '1')
00397         index = 1;
00398         JDWAppList::iterator it;
00399 
00400         for (it = appList.begin(); it != appList.end(); it++) {
00401                 JDWAppInfo &appInfo = it->second;
00402                 JDG::ClassList &list = appInfo.classList;
00403 
00404                 JDG::ClassList::iterator b;
00405 
00406                 for (b = list.begin(); b != list.end(); b++) {
00407                         // FIXME
00408                         // I don't from class field, we have to filter the class view by JDB
00409 //                      if ((b->type != 0x824) && (b->type != 0x64)) {
00410                         if (b->id == 0xffffffff) {
00411                                 b->index = -1;
00412 
00413                                 continue;
00414                         }
00415 
00416                         b->index = index;
00417 
00418                         visibleClassList.push_back(*b);
00419 
00420                         index++;
00421                 }
00422         }
00423 
00424         visibleClassList.CreateDefaultEntries();
00425 
00426         return true;
00427 }
00428 
00429 
00430 void JDWServer::CommandsetProcess(Data &cmd)
00431 {
00432         MAKE_JDWPPACKET(rpack, cmd);
00433 
00434         switch (rpack->u.command.commandset) {
00435                 case JDWP_CMDSET_VIRTUALMACHINE:
00436                         CommandsetVirtualMachineProcess(cmd);
00437                         break;
00438 
00439                 case JDWP_CMDSET_REFERECENTYPE:
00440                         break;
00441 
00442                 case JDWP_CMDSET_CLASSTYPE:
00443                         break;
00444 
00445                 case JDWP_CMDSET_ARRAYTYPE:
00446                         break;
00447 
00448                 case JDWP_CMDSET_INTERFACETYPE:
00449                         break;
00450 
00451                 case JDWP_CMDSET_METHOD:
00452                         break;
00453 
00454                 case JDWP_CMDSET_FIELD:
00455                         break;
00456 
00457                 case JDWP_CMDSET_OBJECTREFERENCE:
00458                         break;
00459 
00460                 case JDWP_CMDSET_STRINGREFERENCE:
00461                         break;
00462 
00463                 case JDWP_CMDSET_THREADREFERENCE:
00464                         break;
00465 
00466                 case JDWP_CMDSET_THREADGROUPREFERENCE:
00467                         break;
00468 
00469                 case JDWP_CMDSET_ARRAYREFERENCE:
00470                         break;
00471 
00472                 case JDWP_CMDSET_CLASSLOADERREFERENCE:
00473                         break;
00474 
00475                 case JDWP_CMDSET_EVENTREQUEST:
00476                         CommandsetEventRequestProcess(cmd);
00477                         break;
00478 
00479                 case JDWP_CMDSET_STACKFRAME:
00480                         break;
00481 
00482                 case JDWP_CMDSET_CLASSOBJECTREFERENCE:
00483                         break;
00484 
00485                 case JDWP_CMDSET_EVENT:
00486                         break;
00487 
00488                 default:
00489                         // TODO : add exception (or alert)
00490                         dout("Commandset unknown !!!" << endl);
00491         }
00492 }
00493 
00494 
00495 void JDWServer::CommandsetVirtualMachineProcess(Data &cmd)
00496 {
00497         MAKE_JDWPPACKET(rpack, cmd);
00498 
00499         switch (rpack->u.command.command) {
00500                 case JDWP_CMD_VERSION:
00501                         CommandVersion(cmd);
00502                         break;
00503 
00504                 case JDWP_CMD_ALLCLASSES:
00505                         CommandAllClasses(cmd);
00506                         break;
00507 
00508                 case JDWP_CMD_ALLTHREADS:
00509                         CommandAllThreads(cmd);
00510                         break;
00511 
00512                 case JDWP_CMD_DISPOSE:
00513                         loop = false;
00514                         targetrunning = false;
00515                         close(acceptfd);
00516                         acceptfd = -1;
00517                         break;
00518 
00519                 case JDWP_CMD_IDSIZES:
00520                         CommandIdSizes(cmd);
00521                         break;
00522 
00523                 case JDWP_CMD_SUSPEND:
00524                         CommandSuspend(cmd);
00525                         targetrunning = false;
00526                         break;
00527 
00528                 case JDWP_CMD_RESUME:
00529                         CommandResume(cmd);
00530                         targetrunning = true;
00531                         break;
00532 
00533                 case JDWP_CMD_CLASSPATHS:
00534                         CommandClassPaths(cmd);
00535                         break;
00536         }
00537 }
00538 
00539 
00540 void JDWServer::CommandsetEventRequestProcess(Data &cmd)
00541 {
00542         MAKE_JDWPPACKET(rpack, cmd);
00543 
00544         switch (rpack->u.command.command) {
00545                 case JDWP_CMD_SET:
00546                         CommandSet(cmd);
00547                         break;
00548         }
00549 }
00550 
00551 
00552 void JDWServer::CommandVersion(Data &cmd)
00553 {
00554         JDWMessage msg(acceptfd);
00555 
00556         // Build packet data
00557         Data response;
00558 
00559         size_t offset = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
00560 
00561         AddJDWString(response, offset, string("RIM JVM"));
00562         AddJDWInt(response, offset, be_htobl(1));
00563         AddJDWInt(response, offset, be_htobl(4));
00564         AddJDWString(response, offset, string("1.4"));
00565         AddJDWString(response, offset, string("RIM JVM"));
00566 
00567         response.ReleaseBuffer(offset);
00568 
00569 
00570         size_t total_size = response.GetSize();
00571 
00572         // Fill in the header values
00573         MAKE_JDWPPACKETPTR_BUF(cpack, response.GetBuffer(total_size));
00574         Barry::Protocol::JDWP::Packet &packet = *cpack;
00575 
00576 
00577         MAKE_JDWPPACKET(rpack, cmd);
00578 
00579         packet.length = be_htobl(total_size);
00580         packet.id = rpack->id;
00581         packet.flags = 0x80;
00582         packet.u.response.errorcode = be_htobs(0);
00583 
00584         response.ReleaseBuffer(total_size);
00585         msg.Send(response);
00586 }
00587 
00588 
00589 void JDWServer::CommandAllClasses(Data &cmd)
00590 {
00591         size_t i;
00592         int size;
00593 
00594         JDWMessage msg(acceptfd);
00595 
00596         // Build packet data
00597         Data response;
00598 
00599         size_t offset = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
00600 
00601         // Size of known class list
00602         size = visibleClassList.size() - 1;
00603 
00604         AddJDWInt(response, offset, be_htobl(size));
00605 
00606         // Then, write the list of known class
00607         for (i=1; i<visibleClassList.size(); i++) {
00608                 string str = visibleClassList[i].GetFullClassName();
00609 
00610                 str = "L" + str + ";";
00611                 replace_if(str.begin(), str.end(), bind2nd(equal_to<char>(),'.'), '/');
00612 
00613                 AddJDWByte(response, offset, 0x01);
00614                 AddJDWInt(response, offset, i); // Should be equal to visibleClassList[i].index
00615                 AddJDWString(response, offset, str);
00616                 AddJDWInt(response, offset, be_htobl(0x04));
00617         }
00618 
00619         response.ReleaseBuffer(offset);
00620 
00621 
00622         size_t total_size = response.GetSize();
00623 
00624         // Fill in the header values
00625         MAKE_JDWPPACKETPTR_BUF(cpack, response.GetBuffer(total_size));
00626         Barry::Protocol::JDWP::Packet &packet = *cpack;
00627 
00628 
00629         MAKE_JDWPPACKET(rpack, cmd);
00630 
00631         packet.length = be_htobl(total_size);
00632         packet.id = rpack->id;
00633         packet.flags = 0x80;
00634         packet.u.response.errorcode = be_htobs(0);
00635 
00636         response.ReleaseBuffer(total_size);
00637         msg.Send(response);
00638 }
00639 
00640 
00641 void JDWServer::CommandAllThreads(Data &cmd)
00642 {
00643         JDWMessage msg(acceptfd);
00644 
00645         // Get threads list from device
00646         JVMThreadsList list;
00647         jvmdebug->GetThreadsList(list);
00648         dout(list);
00649 
00650         // Build packet data
00651         Data response;
00652 
00653         size_t offset = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
00654 
00655         // Indicate the number of element
00656         AddJDWInt(response, offset, be_htobl(list.size()));
00657 
00658         // Send all threads ID
00659         JVMThreadsList::const_iterator b = list.begin();
00660         for( ; b != list.end(); b++ ) {
00661                 const JVMThreadsEntry &entry = *b;
00662 
00663                 AddJDWInt(response, offset, be_htobl(entry.Id));
00664         }
00665 
00666         response.ReleaseBuffer(offset);
00667 
00668 
00669         size_t total_size = response.GetSize();
00670 
00671         // Fill in the header values
00672         MAKE_JDWPPACKETPTR_BUF(cpack, response.GetBuffer(total_size));
00673         Barry::Protocol::JDWP::Packet &packet = *cpack;
00674 
00675 
00676         MAKE_JDWPPACKET(rpack, cmd);
00677 
00678         packet.length = be_htobl(total_size);
00679         packet.id = rpack->id;
00680         packet.flags = 0x80;
00681         packet.u.response.errorcode = be_htobs(0);
00682 
00683         response.ReleaseBuffer(total_size);
00684         msg.Send(response);
00685 }
00686 
00687 
00688 void JDWServer::CommandIdSizes(Data &cmd)
00689 {
00690         JDWMessage msg(acceptfd);
00691 
00692         MAKE_JDWPPACKET(rpack, cmd);
00693 
00694         size_t size;
00695 
00696         Barry::Protocol::JDWP::Packet packet;
00697 
00698         size = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE
00699                 + JDWP_PACKETVIRTUALMACHINEIDSIZES_DATA_SIZE;
00700 
00701         packet.length = be_htobl(size);
00702         packet.id = rpack->id;
00703         packet.flags = 0x80;
00704         packet.u.response.errorcode = be_htobs(0);
00705         packet.u.response.u.virtualMachine.u.IDSizes.fieldIDSize = be_htobl(0x04);
00706         packet.u.response.u.virtualMachine.u.IDSizes.methodIDSize = be_htobl(0x04);
00707         packet.u.response.u.virtualMachine.u.IDSizes.objectIDSize = be_htobl(0x04);
00708         packet.u.response.u.virtualMachine.u.IDSizes.referenceTypeIDSize = be_htobl(0x04);
00709         packet.u.response.u.virtualMachine.u.IDSizes.frameIDSize = be_htobl(0x04);
00710 
00711         Data response(&packet, size);
00712 
00713         msg.Send(response);
00714 }
00715 
00716 
00717 void JDWServer::CommandSuspend(Data &cmd)
00718 {
00719         JDWMessage msg(acceptfd);
00720 
00721 
00722         // Suspend device
00723         jvmdebug->Stop();
00724 
00725         // Notify debugger
00726         MAKE_JDWPPACKET(rpack, cmd);
00727 
00728         size_t size;
00729 
00730         Barry::Protocol::JDWP::Packet packet;
00731 
00732         size = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
00733 
00734         packet.length = be_htobl(size);
00735         packet.id = rpack->id;
00736         packet.flags = 0x80;
00737         packet.u.response.errorcode = be_htobs(0);
00738 
00739         Data response(&packet, size);
00740 
00741         msg.Send(response);
00742 }
00743 
00744 
00745 void JDWServer::CommandResume(Data &cmd)
00746 {
00747         JDWMessage msg(acceptfd);
00748 
00749 
00750         // Resume device
00751         jvmdebug->Unknown06();
00752         jvmdebug->Unknown07();
00753         jvmdebug->Unknown08();
00754         jvmdebug->Unknown09();
00755         jvmdebug->Unknown10();
00756         jvmdebug->Go();
00757 
00758         // Notify debugger
00759         MAKE_JDWPPACKET(rpack, cmd);
00760 
00761         size_t size;
00762 
00763         Barry::Protocol::JDWP::Packet packet;
00764 
00765         size = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
00766 
00767         packet.length = be_htobl(size);
00768         packet.id = rpack->id;
00769         packet.flags = 0x80;
00770         packet.u.response.errorcode = be_htobs(0);
00771 
00772         Data response(&packet, size);
00773 
00774         msg.Send(response);
00775 }
00776 
00777 
00778 void JDWServer::CommandClassPaths(Data &cmd)
00779 {
00780         JDWMessage msg(acceptfd);
00781 
00782         // Build packet data
00783         Data response;
00784 
00785         size_t offset = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE;
00786 
00787         AddJDWString(response, offset, string(""));
00788         AddJDWInt(response, offset, be_htobl(0));
00789         AddJDWInt(response, offset, be_htobl(0));
00790 
00791         response.ReleaseBuffer(offset);
00792 
00793 
00794         size_t total_size = response.GetSize();
00795 
00796         // Fill in the header values
00797         MAKE_JDWPPACKETPTR_BUF(cpack, response.GetBuffer(total_size));
00798         Barry::Protocol::JDWP::Packet &packet = *cpack;
00799 
00800 
00801         MAKE_JDWPPACKET(rpack, cmd);
00802 
00803         packet.length = be_htobl(total_size);
00804         packet.id = rpack->id;
00805         packet.flags = 0x80;
00806         packet.u.response.errorcode = be_htobs(0);
00807 
00808         response.ReleaseBuffer(total_size);
00809         msg.Send(response);
00810 }
00811 
00812 
00813 
00814 void JDWServer::CommandSet(Data &cmd)
00815 {
00816         static int value = 2;
00817 
00818         JDWMessage msg(acceptfd);
00819 
00820         MAKE_JDWPPACKET(rpack, cmd);
00821 
00822         size_t size;
00823 
00824         Barry::Protocol::JDWP::Packet packet;
00825 
00826         size = JDWP_PACKET_HEADER_SIZE + JDWP_RESPONSE_HEADER_SIZE + sizeof(uint32_t);
00827 
00828         packet.length = be_htobl(size);
00829         packet.id = rpack->id;
00830         packet.flags = 0x80;
00831         packet.u.response.errorcode = be_htobs(0);
00832         packet.u.response.u.value = be_htobl(value);
00833 
00834         Data response(&packet, size);
00835 
00836         msg.Send(response);
00837 
00838         value++;
00839 }
00840 
00841 
00842 }} // namespace Barry::JDWP
00843