ij-16.png   inspectorJ -- JavaTM Profiler
sf project site browse source checkout source
SourceForge.net Logo



src/inspectorj/agent/agentserver.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   inspectorJ - java profiler                                            *
00003  *   Copyright (C) 2007 by James May
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 
00027 #include "inspectorj/agent/agentserver.h"
00028 
00029 using inspectorj::agent::AgentServer;
00030 using namespace inspectorj::jdwp;
00031         
00032 namespace inspectorj {
00033 namespace agent {
00034 
00040 AgentServer::AgentServer(int portNum, AgentPacketHandler *handler)
00041     : portNum(portNum),
00042       pktHandler(handler), 
00043       quit(false),
00044       started(false),
00045       error(0), 
00046       socket(0),
00047       acceptor(0),
00048       agentSocket(0)
00049 {
00050     
00051 }
00052 
00056 AgentServer::~AgentServer()
00057 {
00058     if (socket) {
00059         delete socket;
00060         socket = 0;
00061     }
00062     if (agentSocket) {
00063         delete agentSocket;
00064         agentSocket = 0;
00065     }
00066     if (error) {
00067         delete error;
00068         error = 0;
00069     }
00070 }
00071 
00075 void AgentServer::stop()
00076 {
00077     this->quit = true;
00078     if (socket && socket->is_open()) {
00079         socket->close();
00080     }
00081 
00082     // The server may be waiting to accept a connection at the time
00083     // the jvm is shutting down. Close the acceptor so the server's 
00084     // start function can return and the server thread can die.
00085     if (acceptor) {
00086         acceptor->close();
00087     }
00088 }
00089 
00090 void AgentServer::shutDown()
00091 {    
00092     if (socket) {
00093         if ( socket->is_open() && !quit) {
00094             socket->close();
00095         }        
00096         socket->io_service().stop();
00097     }
00098     this->started = false;
00099     this->quit = false;
00100 }
00101 
00105 bool AgentServer::isStarted()
00106 {
00107     return this->started;
00108 }
00109 
00114 void AgentServer::start()
00115 {    
00116     this->quit = false;
00117     boost::asio::io_service io_service;
00118     
00119     try
00120     {
00121         char handshake[JDWP_HANDSHAKE_LENGTH + 1];
00122         while (!quit) {
00123             this->started = false;
00124             error = new boost::system::error_code();
00125             size_t bytesRead = 0;              
00126             
00127             if (socket) {
00128                 delete socket;
00129                 socket = 0;
00130             }
00131             socket = new tcp::socket(io_service);
00132             
00133             if (agentSocket) {
00134                 delete agentSocket;
00135                 agentSocket = 0;
00136             }
00137             agentSocket = new AgentSocket(socket, error);
00138             pktHandler->setAgentSocket(agentSocket);
00139             pktHandler->attachCurrentThreadToVM();
00140             
00141             if (acceptor) {
00142                 delete acceptor;
00143                 acceptor = 0;
00144             }            
00145             acceptor = new tcp::acceptor(io_service, tcp::endpoint(tcp::v4(), portNum));
00146             acceptor->accept(*socket, *error);
00147             delete acceptor;
00148             acceptor = 0;
00149 
00150 
00151             // Since acceptor->accept(...) blocks while waiting for a connection,
00152             // it's possible that the jvm may be shutdown before a connection is made.
00153             // In this event, acceptor->accept(...) will return as a result of calling 
00154             // acceptor->close() from the main thread. Check this->quit to see if the
00155             // jvm is shutting down.
00156             // @see inspectorj::agent::AgentServer::stop();
00157             if (quit) {
00158                 shutDown();
00159                 return;
00160             }
00161 
00162             this->started = true;
00163             
00164             AgentLogger::info("Accepted client connection");
00165 
00166             // Check for handshake
00167             if (socket->available() < JDWP_HANDSHAKE_LENGTH ) {
00168                 // no handshake yet... wait 1 second
00169                 boost::asio::io_service timer_io_service;            
00170                 boost::asio::deadline_timer t(timer_io_service, boost::posix_time::seconds(1));
00171                 t.wait();  
00172                           
00173                 if (socket->available() < JDWP_HANDSHAKE_LENGTH) {
00174                     // still no handshake... giving up
00175                     AgentLogger::warn("No handshake received from client... disconnecting");
00176                     continue;
00177                 }
00178             }        
00179             
00180             // read handshake from client
00181             if (! agentSocket->read(handshake, JDWP_HANDSHAKE_LENGTH)) continue;           
00182             handshake[JDWP_HANDSHAKE_LENGTH] = '\0';
00183 
00184             // check handshake string
00185             if (strcmp(handshake, JDWP_HANDSHAKE) != 0) {
00186                 // handshake string is not correct... abort
00187                 AgentLogger::warn("Incorrect handshake received from client: [%s]... disconnecting",handshake);
00188                 continue;
00189             }
00190 
00191             boost::asio::write(*socket, boost::asio::buffer(JDWP_HANDSHAKE),
00192                             boost::asio::transfer_all(), *error); 
00193     
00194             // Connection established... Start processing commands
00195             while (!checkError(*error) && !quit)
00196             {               
00197                 // read command packets from the client
00198                 jdwpCmdPacket cmdPacket;
00199         
00200                 if (! agentSocket->read(cmdPacket.len)) continue;
00201                 if (! agentSocket->read(cmdPacket.id)) continue;
00202                 if (! agentSocket->read(cmdPacket.flags)) continue;
00203                 if (! agentSocket->read(cmdPacket.cmdSet)) continue; 
00204                 if (! agentSocket->read(cmdPacket.cmd)) continue;
00205 
00206                 if (cmdPacket.cmdSet == INSPECTORJ_COMMAND_SET)
00207                 {
00208                     if (cmdPacket.cmd == IJ_DISCONNECT)
00209                     {
00210                         break;
00211                     }
00212                     else if (cmdPacket.cmd == IJ_EXIT)
00213                     {
00214                         quit = true;
00215                         break;
00216                     }
00217                 }
00218 
00219                 int dataSize = cmdPacket.len - JDWP_HEADER_LENGTH;
00220                 
00221                 //read cmd data if any
00222                 if ( dataSize > 0 ) {
00223                     cmdPacket.data = new jbyte[dataSize];
00224                     if (! agentSocket->read((char *)cmdPacket.data, dataSize)) continue;
00225                 } else {
00226                     cmdPacket.data = NULL;
00227                 }
00228 
00229                 // Dispatch the JDWPCommand to the AgentPacketHandler.
00230                 // This may be handled synchronously or asynchronously
00231                 // depending on how the command is processed by the
00232                 // command set. 
00233                 // @see inspectorj::agent::commandset::JDWPCommandSet
00234                 pktHandler->processCommand(new JDWPCommand(cmdPacket));
00235             }
00236         }
00237     }
00238     catch (std::exception& e)
00239     {   
00240         // If the server is being shutdown while the it is waiting to read/write
00241         // a command or reply, then a connection aborted exception will be thrown.
00242         // Therefore ignore exceptions that thrown during shutdown.
00243         if (! this->quit ) {
00244             AgentLogger::error("inspectorj server stopping becasue of exception:");
00245             AgentLogger::error(e.what());
00246         }
00247     }
00248 
00249     this->shutDown();
00250 }
00251 
00256 bool AgentServer::checkError(boost::system::error_code& error)
00257 {
00258     if (error) {
00259         if (error != boost::asio::error::eof)
00260             throw boost::system::system_error(error);
00261         }
00262     return error;
00263 }
00264     
00265 } // end namespace agent
00266 } // end namespace inspectorj

Generated on Sun Aug 19 17:07:52 2007 for inspectorJ by  doxygen 1.5.1