# packet.cc

Go to the documentation of this file.

    00001 ///
    00002 /// \file       packet.cc
    00003 ///             Low level protocol packet builder class.
    00004 ///             Has knowledge of specific protocol commands in order
    00005 ///             to hide protocol details behind an API.
    00006 ///
    00007
    00008 /*
    00009     Copyright (C) 2005-2011, Net Direct Inc. (http://www.netdirect.ca/)
    00010
    00011     This program is free software; you can redistribute it and/or modify
    00012     it under the terms of the GNU General Public License as published by
    00013     the Free Software Foundation; either version 2 of the License, or
    00014     (at your option) any later version.
    00015
    00016     This program is distributed in the hope that it will be useful,
    00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00019
    00020     See the GNU General Public License in the COPYING file at the
    00021     root directory of this project for more details.
    00022 */
    00023
    00024 #include "packet.h"
    00025 #include "m_desktop.h"
    00026 #include "protocol.h"
    00027 #include "protostructs.h"
    00028 #include "data.h"
    00029 #include "endian.h"
    00030 #include "parser.h"
    00031 #include "builder.h"
    00032 #include "error.h"
    00033 #include <string.h>
    00034
    00035 #define __DEBUG_MODE__
    00036 #include "debug.h"
    00037
    00038
    00039 namespace Barry {
    00040
    00041 //////////////////////////////////////////////////////////////////////////////
    00042 // Packet base class
    00043
    00044 //
    00045 // Command
    00046 //
    00047 /// Returns the command value of the receive packet.  If receive isn't
    00048 /// large enough, throws Error.
    00049 ///
    00050 unsigned int Packet::Command() const
    00051 {
    00052         Protocol::CheckSize(*m_receive, SB_PACKET_HEADER_SIZE);
    00053         MAKE_PACKET(rpack, *m_receive);
    00054         return rpack->command;
    00055 }
    00056
    00057
    00058 //////////////////////////////////////////////////////////////////////////////
    00059 // ZeroPacket class
    00060
    00061 ZeroPacket::ZeroPacket(Data &send, Data &receive)
    00062         : Packet(send, receive)
    00063 {
    00064 }
    00065
    00066 ZeroPacket::~ZeroPacket()
    00067 {
    00068 }
    00069
    00070 //
    00071 // GetAttribute
    00072 //
    00073 /// Builds a command packet for the initial socket-0 handshakes
    00074 /// that fetch certain (some unknown) attributes.  The attributes
    00075 /// appear to exist in an object/attribute sequence, so that's
    00076 /// how we address them here.
    00077 ///
    00078 void ZeroPacket::GetAttribute(unsigned int object, unsigned int attribute)
    00079 {
    00080         size_t size = SB_SOCKET_PACKET_HEADER_SIZE + ATTRIBUTE_FETCH_COMMAND_SIZE;
    00081         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(size));
    00082         Protocol::Packet &packet = *cpack;
    00083
    00084         // socket class sets socket for us
    00085         packet.size = htobs(size);
    00086         packet.command = SB_COMMAND_FETCH_ATTRIBUTE;
    00087         packet.u.socket.socket = htobs(0x00ff); // default non-socket request
    00088         packet.u.socket.sequence = 0;           // filled in by Socket class
    00089         packet.u.socket.u.fetch.object = htobs(object);
    00090         packet.u.socket.u.fetch.attribute = htobs(attribute);
    00091
    00092         m_send.ReleaseBuffer(size);
    00093 }
    00094
    00095 //
    00096 // Echo
    00097 //
    00098 /// Builds command packet for sending echo request.  The parameter
    00099 /// to this command is the number of microseconds elapsed since host
    00100 /// computer startup.
    00101 ///
    00102 void ZeroPacket::Echo(uint64_t us_ticks)
    00103 {
    00104         size_t size = SB_SOCKET_PACKET_HEADER_SIZE + ECHO_COMMAND_SIZE;
    00105         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(size));
    00106         Protocol::Packet &packet = *cpack;
    00107
    00108         packet.size = htobs(size);
    00109         packet.command = SB_COMMAND_ECHO;
    00110         packet.u.socket.socket = htobs(0x00ff); // default non-socket request
    00111         packet.u.socket.sequence = 0;           // filled in by Socket class
    00112         packet.u.socket.u.echo.ticks = htobl(us_ticks);
    00113
    00114         m_send.ReleaseBuffer(size);
    00115 }
    00116
    00117 void ZeroPacket::Reset()
    00118 {
    00119         size_t size = SB_SOCKET_PACKET_HEADER_SIZE;
    00120         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(size));
    00121         Protocol::Packet &packet = *cpack;
    00122
    00123         packet.size = htobs(size);
    00124         packet.command = SB_COMMAND_RESET;
    00125         packet.u.socket.socket = htobs(0x00ff); // default non-socket request
    00126         packet.u.socket.sequence = 0;           // filled in by Socket class
    00127
    00128         m_send.ReleaseBuffer(size);
    00129 }
    00130
    00131 unsigned int ZeroPacket::ObjectID() const
    00132 {
    00133         Protocol::CheckSize(*m_receive, SB_SOCKET_PACKET_HEADER_SIZE);
    00134         MAKE_PACKET(rpack, *m_receive);
    00135         return btohs(rpack->u.socket.u.fetch.object);
    00136 }
    00137
    00138 unsigned int ZeroPacket::AttributeID() const
    00139 {
    00140         Protocol::CheckSize(*m_receive, SB_SOCKET_PACKET_HEADER_SIZE);
    00141         MAKE_PACKET(rpack, *m_receive);
    00142         return btohs(rpack->u.socket.u.fetch.attribute);
    00143 }
    00144
    00145 uint32_t ZeroPacket::ChallengeSeed() const
    00146 {
    00147         Protocol::CheckSize(*m_receive, SB_SOCKET_PACKET_HEADER_SIZE +
    00148                 PASSWORD_CHALLENGE_SEED_SIZE);
    00149         MAKE_PACKET(rpack, *m_receive);
    00150         return btohl(rpack->u.socket.u.password.u.seed);
    00151 }
    00152
    00153 unsigned int ZeroPacket::RemainingTries() const
    00154 {
    00155         Protocol::CheckSize(*m_receive, SB_SOCKET_PACKET_HEADER_SIZE +
    00156                 PASSWORD_CHALLENGE_HEADER_SIZE);
    00157         MAKE_PACKET(rpack, *m_receive);
    00158         // this is a byte, so no byte swapping needed
    00159         return rpack->u.socket.u.password.remaining_tries;
    00160 }
    00161
    00162 unsigned int ZeroPacket::SocketResponse() const
    00163 {
    00164         Protocol::CheckSize(*m_receive, SB_SOCKET_PACKET_HEADER_SIZE);
    00165         MAKE_PACKET(rpack, *m_receive);
    00166         return btohs(rpack->u.socket.socket);
    00167 }
    00168
    00169 unsigned char ZeroPacket::SocketSequence() const
    00170 {
    00171         Protocol::CheckSize(*m_receive, SB_SOCKET_PACKET_HEADER_SIZE);
    00172         MAKE_PACKET(rpack, *m_receive);
    00173         return rpack->u.socket.sequence;        // sequence is a byte
    00174 }
    00175
    00176 uint8_t ZeroPacket::CommandResponse() const
    00177 {
    00178         Protocol::CheckSize(*m_receive, SB_SOCKET_PACKET_HEADER_SIZE);
    00179         MAKE_PACKET(rpack, *m_receive);
    00180         return rpack->command;
    00181 }
    00182
    00183
    00184
    00185 //////////////////////////////////////////////////////////////////////////////
    00186 // DBPacket class
    00187
    00188 DBPacket::DBPacket(Mode::Desktop &con, Data &send, Data &receive)
    00189         : Packet(send, receive)
    00190         , m_con(con)
    00191         , m_last_dbop(0)
    00192 {
    00193 }
    00194
    00195 DBPacket::~DBPacket()
    00196 {
    00197 }
    00198
    00199 //
    00200 // ClearDatabase
    00201 //
    00202 /// Builds a command packet for the CLEAR_DATABASE command code, placing
    00203 /// the data in the send buffer.
    00204 ///
    00205 void DBPacket::ClearDatabase(unsigned int dbId)
    00206 {
    00207         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(9));
    00208         Protocol::Packet &packet = *cpack;
    00209
    00210         // socket class sets socket for us
    00211         packet.size = htobs(9);
    00212         packet.command = SB_COMMAND_DB_DATA;
    00213         packet.u.db.tableCmd = m_con.GetDBCommand(Mode::Desktop::DatabaseAccess);
    00214         packet.u.db.u.command.operation = SB_DBOP_CLEAR_DATABASE;
    00215         packet.u.db.u.command.databaseId = htobs(dbId);
    00216
    00217         m_send.ReleaseBuffer(9);
    00218
    00219         m_last_dbop = SB_DBOP_CLEAR_DATABASE;
    00220 }
    00221
    00222 //
    00223 // GetDBDB
    00224 //
    00225 /// Builds a command packet for the GET_DBDB command code, placing the
    00226 /// data in m_send.
    00227 ///
    00228 void DBPacket::GetDBDB()
    00229 {
    00230         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(7));
    00231         Protocol::Packet &packet = *cpack;
    00232
    00233         // socket class sets socket for us
    00234         packet.size = htobs(7);
    00235         packet.command = SB_COMMAND_DB_DATA;
    00236         packet.u.db.tableCmd = m_con.GetDBCommand(Mode::Desktop::DatabaseAccess);
    00237 //      packet.u.db.u.command.operation = SB_DBOP_GET_DBDB;
    00238         packet.u.db.u.command.operation = SB_DBOP_OLD_GET_DBDB;
    00239
    00240         m_send.ReleaseBuffer(7);
    00241
    00242         m_last_dbop = SB_DBOP_OLD_GET_DBDB;
    00243 }
    00244
    00245 //
    00246 // GetRecordStateTable
    00247 //
    00248 /// Builds a command packet in the send buffer for the
    00249 /// GET_RECORD_STATE_TABLE command.
    00250 ///
    00251 void DBPacket::GetRecordStateTable(unsigned int dbId)
    00252 {
    00253         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(9));
    00254         Protocol::Packet &packet = *cpack;
    00255
    00256         // socket class sets socket for us
    00257         packet.size = htobs(9);
    00258         packet.command = SB_COMMAND_DB_DATA;
    00259         packet.u.db.tableCmd = m_con.GetDBCommand(Mode::Desktop::DatabaseAccess);
    00260         packet.u.db.u.command.operation = SB_DBOP_GET_RECORD_STATE_TABLE;
    00261         packet.u.db.u.command.databaseId = htobs(dbId);
    00262
    00263         m_send.ReleaseBuffer(9);
    00264
    00265         m_last_dbop = SB_DBOP_GET_RECORD_STATE_TABLE;
    00266 }
    00267
    00268 //
    00269 // SetRecordFlags
    00270 //
    00271 /// Builds a command packet in the send buffer for the SET_RECORD_FLAGS
    00272 /// command code.
    00273 ///
    00274 /// FIXME - this API call is incomplete, since there are unknown flags
    00275 ///         in the SetRecordFlags protocol packet.  Currently it is only
    00276 ///         used to set all flags to zero.
    00277 ///
    00278 void DBPacket::SetRecordFlags(unsigned int dbId, unsigned int stateTableIndex,
    00279                             uint8_t flag1)
    00280 {
    00281         size_t size = SB_PACKET_COMMAND_HEADER_SIZE + DBC_RECORD_FLAGS_SIZE;
    00282         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(size));
    00283         Protocol::Packet &packet = *cpack;
    00284
    00285         // socket class sets socket for us
    00286         packet.size = htobs(size);
    00287         packet.command = SB_COMMAND_DB_DATA;
    00288         packet.u.db.tableCmd = m_con.GetDBCommand(Mode::Desktop::DatabaseAccess);
    00289         packet.u.db.u.command.operation = SB_DBOP_SET_RECORD_FLAGS;
    00290         packet.u.db.u.command.databaseId = htobs(dbId);
    00291         packet.u.db.u.command.u.flags.unknown = flag1;
    00292         packet.u.db.u.command.u.flags.index = htobs(stateTableIndex);
    00293         memset(packet.u.db.u.command.u.flags.unknown2, 0, sizeof(packet.u.db.u.command.u.flags.unknown2));
    00294
    00295         m_send.ReleaseBuffer(size);
    00296
    00297         m_last_dbop = SB_DBOP_SET_RECORD_FLAGS;
    00298 }
    00299
    00300 //
    00301 // DeleteRecordByIndex
    00302 //
    00303 /// Builds a command packet in the send buffer for the DELETE_RECORD_BY_INDEX
    00304 /// command code.
    00305 ///
    00306 void DBPacket::DeleteRecordByIndex(unsigned int dbId, unsigned int stateTableIndex)
    00307 {
    00308         size_t size = SB_PACKET_COMMAND_HEADER_SIZE + DBC_RECORD_HEADER_SIZE;
    00309         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(size));
    00310         Protocol::Packet &packet = *cpack;
    00311
    00312         // socket class sets socket for us
    00313         packet.size = htobs(size);
    00314         packet.command = SB_COMMAND_DB_DATA;
    00315         packet.u.db.tableCmd = m_con.GetDBCommand(Mode::Desktop::DatabaseAccess);
    00316         packet.u.db.u.command.operation = SB_DBOP_DELETE_RECORD_BY_INDEX;
    00317         packet.u.db.u.command.databaseId = htobs(dbId);
    00318         packet.u.db.u.command.u.record.recordIndex = htobs(stateTableIndex);
    00319
    00320         m_send.ReleaseBuffer(size);
    00321
    00322         m_last_dbop = SB_DBOP_DELETE_RECORD_BY_INDEX;
    00323 }
    00324
    00325 //
    00326 // GetRecordByIndex
    00327 //
    00328 /// Builds a command packet in the send buffer for the GET_RECORD_BY_INDEX
    00329 /// command code.
    00330 ///
    00331 void DBPacket::GetRecordByIndex(unsigned int dbId, unsigned int stateTableIndex)
    00332 {
    00333         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(11));
    00334         Protocol::Packet &packet = *cpack;
    00335
    00336         // socket class sets socket for us
    00337         packet.size = htobs(11);
    00338         packet.command = SB_COMMAND_DB_DATA;
    00339         packet.u.db.tableCmd = m_con.GetDBCommand(Mode::Desktop::DatabaseAccess);
    00340         packet.u.db.u.command.operation = SB_DBOP_GET_RECORD_BY_INDEX;
    00341         packet.u.db.u.command.databaseId = htobs(dbId);
    00342         packet.u.db.u.command.u.record.recordIndex = htobs(stateTableIndex);
    00343
    00344         m_send.ReleaseBuffer(11);
    00345
    00346         m_last_dbop = SB_DBOP_GET_RECORD_BY_INDEX;
    00347 }
    00348
    00349 //
    00350 // SetRecordByIndex
    00351 //
    00352 /// Builds a command packet in the m_send buffer for the SET_RECORD_BY_INDEX
    00353 /// command code.
    00354 ///
    00355 /// \return     bool
    00356 ///             - true means success
    00357 ///             - false means no data available from Builder object
    00358 ///
    00359 bool DBPacket::SetRecordByIndex(unsigned int dbId, unsigned int stateTableIndex,
    00360                               Builder &build, const IConverter *ic)
    00361 {
    00362         // build packet data
    00363         DBData send(m_send, false);     // send is just a reference to m_send,
    00364                                         // so it is safe to use m_send later
    00365
    00366         size_t header_size = SB_PACKET_COMMAND_HEADER_SIZE + DBC_INDEXED_UPLOAD_HEADER_SIZE;
    00367         if( !build.BuildRecord(send, header_size, ic) )
    00368                 return false;           // no data available
    00369         size_t total_size = m_send.GetSize();
    00370
    00371         // fill in the header values
    00372         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(total_size));
    00373         Protocol::Packet &packet = *cpack;
    00374
    00375         // socket class sets socket for us
    00376         packet.size = htobs(total_size);
    00377         packet.command = SB_COMMAND_DB_DATA;
    00378         packet.u.db.tableCmd = m_con.GetDBCommand(Mode::Desktop::DatabaseAccess);
    00379         packet.u.db.u.command.operation = SB_DBOP_SET_RECORD_BY_INDEX;
    00380         packet.u.db.u.command.databaseId = htobs(dbId);
    00381         packet.u.db.u.command.u.index_upload.unknown = 0;
    00382         packet.u.db.u.command.u.index_upload.index = htobs(stateTableIndex);
    00383
    00384         m_send.ReleaseBuffer(total_size);
    00385
    00386         m_last_dbop = SB_DBOP_SET_RECORD_BY_INDEX;
    00387         return true;
    00388 }
    00389
    00390 //
    00391 // GetRecords
    00392 //
    00393 /// Builds a command packet in the send buffer for the GET_RECORDS
    00394 /// command code.
    00395 ///
    00396 void DBPacket::GetRecords(unsigned int dbId)
    00397 {
    00398         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(9));
    00399         Protocol::Packet &packet = *cpack;
    00400
    00401         // socket class sets socket for us
    00402         packet.size = htobs(9);
    00403         packet.command = SB_COMMAND_DB_DATA;
    00404         packet.u.db.tableCmd = m_con.GetDBCommand(Mode::Desktop::DatabaseAccess);
    00405         packet.u.db.u.command.operation = SB_DBOP_OLD_GET_RECORDS;
    00406         packet.u.db.u.command.databaseId = htobs(dbId);
    00407
    00408         m_send.ReleaseBuffer(9);
    00409
    00410         m_last_dbop = SB_DBOP_OLD_GET_RECORDS;
    00411 }
    00412
    00413 //
    00414 // SetRecord
    00415 //
    00416 /// Builds a command packet in the m_send buffer for the SET_RECORD command
    00417 /// code.
    00418 ///
    00419 /// \return     bool
    00420 ///             - true means success
    00421 ///             - false means no data available from Builder object
    00422 ///
    00423 bool DBPacket::SetRecord(unsigned int dbId, Builder &build, const IConverter *ic)
    00424 {
    00425         // build packet data
    00426         DBData send(m_send, false);     // send is just a reference to m_send,
    00427                                         // so it is safe to use m_send later
    00428
    00429         size_t header_size = SB_PACKET_COMMAND_HEADER_SIZE + DBC_TAGGED_UPLOAD_HEADER_SIZE;
    00430         if( !build.BuildRecord(send, header_size, ic) )
    00431                 return false;           // no data available
    00432         size_t total_size = m_send.GetSize();
    00433
    00434         // fill in the header values
    00435         MAKE_PACKETPTR_BUF(cpack, m_send.GetBuffer(total_size));
    00436         Protocol::Packet &packet = *cpack;
    00437
    00438         // socket class sets socket for us
    00439         packet.size = htobs(total_size);
    00440         packet.command = SB_COMMAND_DB_DATA;
    00441         packet.u.db.tableCmd = m_con.GetDBCommand(Mode::Desktop::DatabaseAccess);
    00442         packet.u.db.u.command.operation = SB_DBOP_SET_RECORD;
    00443         packet.u.db.u.command.databaseId = htobs(dbId);
    00444         packet.u.db.u.command.u.tag_upload.rectype = send.GetRecType();
    00445         packet.u.db.u.command.u.tag_upload.uniqueId = htobl(send.GetUniqueId());
    00446         packet.u.db.u.command.u.tag_upload.unknown2 = 1;        // unknown observed value
    00447
    00448         m_send.ReleaseBuffer(total_size);
    00449
    00450         m_last_dbop = SB_DBOP_SET_RECORD;
    00451         return true;
    00452 }
    00453
    00454
    00455 // throws FIXME if packet doesn't support it
    00456 unsigned int DBPacket::ReturnCode() const
    00457 {
    00458         if( Command() == SB_COMMAND_DB_DONE ) {
    00459                 Protocol::CheckSize(*m_receive, SB_PACKET_DBACCESS_HEADER_SIZE + SB_DBACCESS_RETURN_CODE_SIZE);
    00460                 MAKE_PACKET(rpack, *m_receive);
    00461                 return rpack->u.db.u.return_code;
    00462         }
    00463         else {
    00464                 throw Error("Attempting to extract a return code from the wrong response packet type");
    00465         }
    00466 }
    00467
    00468 //
    00469 // DBOperation
    00470 //
    00471 /// Returns the database operation code from the receive packet, assuming
    00472 /// that receive contains a response packet.  If receive isn't large
    00473 /// enough, throws Error.
    00474 ///
    00475 unsigned int DBPacket::DBOperation() const
    00476 {
    00477         Protocol::CheckSize(*m_receive, SB_PACKET_RESPONSE_HEADER_SIZE);
    00478         MAKE_PACKET(rpack, *m_receive);
    00479         return rpack->u.db.u.response.operation;
    00480 }
    00481
    00482 //
    00483 // Parse
    00484 //
    00485 /// Parses the data in the receive buffer, and attempts to be smart about it,
    00486 /// using the last send command as guidance for what to expect in the
    00487 /// response.
    00488 ///
    00489 /// \returns    bool    true - packet was recognized and parse was attempted
    00490 ///                     false - packet was not recognized
    00491 ///
    00492 bool DBPacket::Parse(Parser &parser, const std::string &dbname,
    00493                         const IConverter *ic)
    00494 {
    00495         size_t offset = 0;
    00496         MAKE_PACKET(rpack, *m_receive);
    00497
    00498         switch( m_last_dbop )
    00499         {
    00500         case SB_DBOP_OLD_GET_RECORDS:
    00501         case SB_DBOP_GET_RECORD_BY_INDEX:
    00502                 offset = SB_PACKET_RESPONSE_HEADER_SIZE + DBR_OLD_TAGGED_RECORD_HEADER_SIZE;
    00503                 Protocol::CheckSize(*m_receive, offset);
    00504
    00505                 // FIXME - this may need adjustment for email records... they
    00506                 // don't seem to have uniqueID's
    00507                 {
    00508                         DBData block(DBData::REC_VERSION_1, dbname,
    00509                                 rpack->u.db.u.response.u.tagged.rectype,
    00510                                 btohl(rpack->u.db.u.response.u.tagged.uniqueId),
    00511                                 offset, *m_receive, false);
    00512                         parser.ParseRecord(block, ic);
    00513                 }
    00514                 return true;
    00515
    00516         default:        // unknown command
    00517                 return false;
    00518         }
    00519 }
    00520
    00521 //
    00522 // ParseMeta
    00523 //
    00524 /// Fills DBData's meta data based on its data block, and the last dbop.
    00525 ///
    00526 bool DBPacket::ParseMeta(DBData &data)
    00527 {
    00528         size_t offset = 0;
    00529         MAKE_PACKET(rpack, data.GetData());
    00530
    00531         switch( m_last_dbop )
    00532         {
    00533         case SB_DBOP_OLD_GET_RECORDS:
    00534         case SB_DBOP_GET_RECORD_BY_INDEX:
    00535                 data.SetVersion(DBData::REC_VERSION_1);
    00536
    00537                 offset = SB_PACKET_RESPONSE_HEADER_SIZE + DBR_OLD_TAGGED_RECORD_HEADER_SIZE;
    00538                 Protocol::CheckSize(data.GetData(), offset);
    00539                 data.SetOffset(offset);
    00540
    00541                 // FIXME - this may need adjustment for email records... they
    00542                 // don't seem to have uniqueID's
    00543                 data.SetIds(rpack->u.db.u.response.u.tagged.rectype,
    00544                         btohl(rpack->u.db.u.response.u.tagged.uniqueId));
    00545                 return true;
    00546
    00547         default:        // unknown command
    00548                 return false;
    00549         }
    00550 }
    00551
    00552
    00553
    00554 //////////////////////////////////////////////////////////////////////////////
    00555 // JLPacket class
    00556
    00557 JLPacket::JLPacket(Data &cmd, Data &send, Data &receive)
    00558         : Packet(send, receive)
    00559         , m_cmd(cmd)
    00560         , m_data(send)
    00561         , m_last_set_size(0)
    00562 {
    00563 }
    00564
    00565 JLPacket::~JLPacket()
    00566 {
    00567 }
    00568
    00569 unsigned int JLPacket::Size()
    00570 {
    00571         Protocol::CheckSize(*m_receive, SB_JLPACKET_HEADER_SIZE + SB_JLRESPONSE_HEADER_SIZE);
    00572         MAKE_JLPACKET(rpack, *m_receive);
    00573         return btohs(rpack->u.response.expect);
    00574 }
    00575
    00576
    00577 // returns 1 or 2 depending on whether cmd or cmd+send are available
    00578 int JLPacket::SimpleCmd(uint8_t cmd, uint8_t unknown, uint16_t size)
    00579 {
    00580         MAKE_JLPACKETPTR_BUF(cpack, m_cmd.GetBuffer(8));
    00581         Protocol::JLPacket &packet = *cpack;
    00582
    00583         // socket class sets socket for us
    00584         packet.size = htobs(8);
    00585         packet.u.command.command = cmd;
    00586         packet.u.command.unknown = unknown;
    00587         packet.u.command.size = htobs(size);
    00588
    00589         m_cmd.ReleaseBuffer(8);
    00590
    00591         return m_last_set_size = 1;
    00592 }
    00593
    00594 int JLPacket::SimpleData(const void *data, uint16_t size)
    00595 {
    00596         uint16_t total = size + 4;
    00597
    00598         MAKE_JLPACKETPTR_BUF(dpack, m_data.GetBuffer(total));
    00599
    00600         // socket class sets socket for us
    00601         dpack->size = htobs(total);
    00602         memcpy(dpack->u.raw, data, size);
    00603
    00604         m_data.ReleaseBuffer(total);
    00605
    00606         return m_last_set_size = 2;
    00607 }
    00608
    00609 int JLPacket::BigEndianData(uint16_t value)
    00610 {
    00611         value = be_htobs(value);
    00612         return SimpleData(&value, sizeof(value));
    00613 }
    00614
    00615 int JLPacket::BigEndianData(uint32_t value)
    00616 {
    00617         value = be_htobl(value);
    00618         return SimpleData(&value, sizeof(value));
    00619 }
    00620
    00621 int JLPacket::SetUnknown1()
    00622 {
    00623         SimpleCmd(SB_COMMAND_JL_SET_UNKNOWN1, 0, 1);
    00624         uint8_t arg = 0;
    00625         return SimpleData(&arg, 1);
    00626 }
    00627
    00628 int JLPacket::SetCodFilename(const std::string &filename)
    00629 {
    00630         SimpleCmd(SB_COMMAND_JL_SET_COD_FILENAME, 0, filename.size());
    00631         return SimpleData(filename.data(), filename.size());
    00632 }
    00633
    00634 int JLPacket::SetCodSize(off_t size)
    00635 {
    00636         SimpleCmd(SB_COMMAND_JL_SET_COD_SIZE, 1, 4);
    00637         return BigEndianData((uint32_t)size);
    00638 }
    00639
    00640 int JLPacket::SetTime(time_t when)
    00641 {
    00642         SimpleCmd(SB_COMMAND_JL_SET_TIME, 0, 4);
    00643         return BigEndianData((uint32_t)when);
    00644 }
    00645
    00646 int JLPacket::GetSubDir(uint16_t id)
    00647 {
    00648         SimpleCmd(SB_COMMAND_JL_GET_SUBDIR, 0, 2);
    00649         return BigEndianData(id);
    00650 }
    00651
    00652 int JLPacket::GetDirEntry(uint8_t entry_cmd, uint16_t id)
    00653 {
    00654         SimpleCmd(entry_cmd, 0, 2);
    00655         return BigEndianData(id);
    00656 }
    00657
    00658 int JLPacket::GetScreenshot()
    00659 {
    00660         SimpleCmd(SB_COMMAND_JL_GET_SCREENSHOT, 0, 4);
    00661         return BigEndianData((uint32_t) 0);
    00662 }
    00663
    00664 int JLPacket::Erase(uint16_t cmd, uint16_t id)
    00665 {
    00666         SimpleCmd(cmd, 0, 2);
    00667         return BigEndianData(id);
    00668 }
    00669
    00670 int JLPacket::GetEventlogEntry(uint16_t entry_num)
    00671 {
    00672         SimpleCmd(SB_COMMAND_JL_GET_LOG_ENTRY, 0, 2);
    00673         return BigEndianData(entry_num);
    00674 }
    00675
    00676 int JLPacket::SaveModule(uint16_t id)
    00677 {
    00678         SimpleCmd(SB_COMMAND_JL_SAVE_MODULE, 0, 2);
    00679         return BigEndianData(id);
    00680 }
    00681
    00682 int JLPacket::PutData(const void *data, uint16_t size)
    00683 {
    00684         SimpleCmd(SB_COMMAND_JL_SEND_DATA, 0, size);
    00685         return SimpleData(data, size);
    00686 }
    00687
    00688
    00689 //////////////////////////////////////////////////////////////////////////////
    00690 // JVMPacket class
    00691
    00692 JVMPacket::JVMPacket(Data &send, Data &receive)
    00693         : Packet(send, receive)
    00694         , m_cmd(send)
    00695 {
    00696 }
    00697
    00698 JVMPacket::~JVMPacket()
    00699 {
    00700 }
    00701
    00702
    00703 unsigned int JVMPacket::Size()
    00704 {
    00705         MAKE_JVMPACKET(rpack, *m_receive);
    00706         Protocol::CheckSize(*m_receive, SB_JVMPACKET_HEADER_SIZE + sizeof(rpack->u.expect));
    00707         return be_btohs(rpack->u.expect);
    00708 }
    00709
    00710
    00711 // Command format (param is optionnal) :
    00712 // 00000000: 05 00 07 00 00 01 8a
    00713 //                             ^^ : command
    00714 //                       ^^^^^ : size of commd + param
    00715 //                 ^^^^^ : packet size
    00716 //           ^^^^^ : socket ID
    00717 void JVMPacket::SimpleCmd(uint8_t cmd)
    00718 {
    00719         // 4 : socket id field + packet size field
    00720         // 2 : size field
    00721         // 1 : command field
    00722         const uint16_t total = 4 + 2 + 1;
    00723
    00724         MAKE_JVMPACKETPTR_BUF(cpack, m_cmd.GetBuffer(total));
    00725         Protocol::JVMPacket &packet = *cpack;
    00726
    00727         // socket class sets socket for us
    00728         packet.size = htobs(total);
    00729         packet.u.command.size = be_htobs(1);
    00730         packet.u.command.command = cmd;
    00731
    00732         m_cmd.ReleaseBuffer(total);
    00733 }
    00734
    00735 // Command with parameter format :
    00736 // 00000000: 05 00 0b 00 00 05 8d 00 00 00 00
    00737 //                                ^^^^^^^^^^^ : param
    00738 //                             ^^ : command
    00739 //                       ^^^^^ : size of commd + param
    00740 //                 ^^^^^ : packet size
    00741 //           ^^^^^ : socket ID
    00742 void JVMPacket::ComplexCmd(uint8_t cmd, const void *param, uint16_t size)
    00743 {
    00744         // 4 : socket id field + packet size field
    00745         // 2 : size field
    00746         // 1 : command field
    00747         uint16_t total = 4 + 2 + 1 + size;
    00748
    00749         MAKE_JVMPACKETPTR_BUF(cpack, m_cmd.GetBuffer(total));
    00750         Protocol::JVMPacket &packet = *cpack;
    00751
    00752         // socket class sets socket for us
    00753         packet.size = htobs(total);
    00754         packet.u.command.size = be_htobs(1 + size);
    00755         packet.u.command.command = cmd;
    00756
    00757         if ((size > 0) && (param != NULL))
    00758                 memcpy(cpack->u.command.raw, param, size);
    00759
    00760         m_cmd.ReleaseBuffer(total);
    00761 }
    00762
    00763
    00764 void JVMPacket::Unknown01() {
    00765         SimpleCmd(SB_COMMAND_JVM_UNKNOWN01);
    00766 }
    00767
    00768
    00769 void JVMPacket::Unknown02() {
    00770         SimpleCmd(SB_COMMAND_JVM_UNKNOWN02);
    00771 }
    00772
    00773
    00774 void JVMPacket::Unknown03() {
    00775         SimpleCmd(SB_COMMAND_JVM_UNKNOWN03);
    00776 }
    00777
    00778
    00779 void JVMPacket::Unknown04() {
    00780         SimpleCmd(SB_COMMAND_JVM_UNKNOWN04);
    00781 }
    00782
    00783
    00784 void JVMPacket::Unknown05() {
    00785         SimpleCmd(SB_COMMAND_JVM_UNKNOWN05);
    00786 }
    00787
    00788
    00789 void JVMPacket::Unknown06() {
    00790         uint32_t param = 0;
    00791
    00792         ComplexCmd(SB_COMMAND_JVM_UNKNOWN06, &param, sizeof(param));
    00793 }
    00794
    00795
    00796 void JVMPacket::Unknown07() {
    00797         uint32_t param = 0;
    00798
    00799         ComplexCmd(SB_COMMAND_JVM_UNKNOWN07, &param, sizeof(param));
    00800 }
    00801
    00802
    00803 void JVMPacket::Unknown08() {
    00804         uint32_t param = 0;
    00805
    00806         ComplexCmd(SB_COMMAND_JVM_UNKNOWN08, &param, sizeof(param));
    00807 }
    00808
    00809
    00810 void JVMPacket::Unknown09() {
    00811         uint32_t param = be_htobl(0x09);
    00812
    00813         ComplexCmd(SB_COMMAND_JVM_UNKNOWN09, &param, sizeof(param));
    00814 }
    00815
    00816
    00817 void JVMPacket::Unknown10() {
    00818         uint32_t param = be_htobl(0x01);
    00819
    00820         ComplexCmd(SB_COMMAND_JVM_UNKNOWN10, &param, sizeof(param));
    00821 }
    00822
    00823
    00824 void JVMPacket::Unknown11(uint32_t id) {
    00825         id = be_htobl(id);
    00826
    00827         ComplexCmd(SB_COMMAND_JVM_UNKNOWN11, &id, sizeof(id));
    00828 }
    00829
    00830
    00831 void JVMPacket::Unknown12(uint32_t id) {
    00832         id = be_htobl(id);
    00833
    00834         ComplexCmd(SB_COMMAND_JVM_UNKNOWN12, &id, sizeof(id));
    00835 }
    00836
    00837
    00838 void JVMPacket::Unknown13(uint32_t id) {
    00839         id = be_htobl(id);
    00840
    00841         ComplexCmd(SB_COMMAND_JVM_UNKNOWN13, &id, sizeof(id));
    00842 }
    00843
    00844
    00845 void JVMPacket::Unknown14(uint32_t id) {
    00846         id = be_htobl(id);
    00847
    00848         ComplexCmd(SB_COMMAND_JVM_UNKNOWN14, &id, sizeof(id));
    00849 }
    00850
    00851
    00852 void JVMPacket::Unknown15(uint32_t id) {
    00853         id = be_htobl(id);
    00854
    00855         ComplexCmd(SB_COMMAND_JVM_UNKNOWN15, &id, sizeof(id));
    00856 }
    00857
    00858
    00859 void JVMPacket::GetModulesList(uint32_t id) {
    00860         id = be_htobl(id);
    00861
    00862         ComplexCmd(SB_COMMAND_JVM_GET_MODULES_LIST, &id, sizeof(id));
    00863 }
    00864
    00865
    00866 void JVMPacket::GetThreadsList() {
    00867         SimpleCmd(SB_COMMAND_JVM_GET_THREADS_LIST);
    00868 }
    00869
    00870
    00871 void JVMPacket::GetConsoleMessage() {
    00872         SimpleCmd(SB_COMMAND_JVM_GET_CONSOLE_MSG);
    00873 }
    00874
    00875
    00876 void JVMPacket::Go()
    00877 {
    00878         SimpleCmd(SB_COMMAND_JVM_GO);
    00879 }
    00880
    00881
    00882 void JVMPacket::Stop()
    00883 {
    00884         // 4 : socket id field + packet size field
    00885         // 2 : value field
    00886         const uint16_t total = 4 + 2;
    00887
    00888         MAKE_JVMPACKETPTR_BUF(cpack, m_cmd.GetBuffer(total));
    00889         Protocol::JVMPacket &packet = *cpack;
    00890
    00891         // socket class sets socket for us
    00892         packet.size = htobs(total);
    00893         packet.u.value = be_htobs(SB_COMMAND_JVM_STOP);
    00894
    00895         m_cmd.ReleaseBuffer(total);
    00896 }
    00897
    00898
    00899 void JVMPacket::GetStatus()
    00900 {
    00901         SimpleCmd(SB_COMMAND_JVM_GET_STATUS);
    00902 }
    00903
    00904 } // namespace Barry
    00905