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-2012, 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 // AddRecord
00415 //
00416 /// Builds a command packet in the m_send buffer for the ADD_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::AddRecord(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_ADD_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_ADD_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