socket.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       socket.cc
00003 ///             Class wrapper to encapsulate the Blackberry USB logical socket
00004 ///
00005 
00006 /*
00007     Copyright (C) 2005-2010, Net Direct Inc. (http://www.netdirect.ca/)
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 "socket.h"
00023 #include "usbwrap.h"
00024 #include "data.h"
00025 #include "protocol.h"
00026 #include "protostructs.h"
00027 #include "endian.h"
00028 #include "debug.h"
00029 #include "packet.h"
00030 #include "sha1.h"
00031 #include <sstream>
00032 #include <string.h>
00033 
00034 using namespace Usb;
00035 
00036 
00037 namespace Barry {
00038 
00039 
00040 //////////////////////////////////////////////////////////////////////////////
00041 // SocketZero class
00042 
00043 SocketZero::SocketZero( SocketRoutingQueue &queue,
00044                         int writeEndpoint,
00045                         uint8_t zeroSocketSequenceStart)
00046         : m_dev(0),
00047         m_queue(&queue),
00048         m_writeEp(writeEndpoint),
00049         m_readEp(0),
00050         m_zeroSocketSequence(zeroSocketSequenceStart),
00051         m_sequenceId(0),
00052         m_halfOpen(false),
00053         m_challengeSeed(0),
00054         m_remainingTries(0),
00055         m_hideSequencePacket(true),
00056         m_resetOnClose(false)
00057 {
00058 }
00059 
00060 SocketZero::SocketZero( Device &dev,
00061                         int writeEndpoint, int readEndpoint,
00062                         uint8_t zeroSocketSequenceStart)
00063         : m_dev(&dev),
00064         m_queue(0),
00065         m_writeEp(writeEndpoint),
00066         m_readEp(readEndpoint),
00067         m_zeroSocketSequence(zeroSocketSequenceStart),
00068         m_sequenceId(0),
00069         m_halfOpen(false),
00070         m_challengeSeed(0),
00071         m_remainingTries(0),
00072         m_hideSequencePacket(true),
00073         m_resetOnClose(false)
00074 {
00075 }
00076 
00077 SocketZero::~SocketZero()
00078 {
00079         // nothing to close for socket zero
00080 }
00081 
00082 
00083 ///////////////////////////////////////
00084 // Socket Zero static calls
00085 
00086 // appends fragment to whole... if whole is empty, simply copies, and
00087 // sets command to DATA instead of FRAGMENTED.  Always updates the
00088 // packet size of whole, to reflect the total size
00089 void SocketZero::AppendFragment(Data &whole, const Data &fragment)
00090 {
00091         if( whole.GetSize() == 0 ) {
00092                 // empty, so just copy
00093                 whole = fragment;
00094         }
00095         else {
00096                 // has some data already, so just append
00097                 int size = whole.GetSize();
00098                 unsigned char *buf = whole.GetBuffer(size + fragment.GetSize());
00099                 MAKE_PACKET(fpack, fragment);
00100                 int fragsize = fragment.GetSize() - SB_FRAG_HEADER_SIZE;
00101 
00102                 memcpy(buf+size, &fpack->u.db.u.fragment, fragsize);
00103                 whole.ReleaseBuffer(size + fragsize);
00104         }
00105 
00106         // update whole's size and command type for future sanity
00107         Barry::Protocol::Packet *wpack = (Barry::Protocol::Packet *) whole.GetBuffer();
00108         wpack->size = htobs((uint16_t) whole.GetSize());
00109         wpack->command = SB_COMMAND_DB_DATA;
00110         // don't need to call ReleaseBuffer here, since we're not changing
00111         // the real data size, and ReleaseBuffer was called above during copy
00112 }
00113 
00114 // If offset is 0, starts fresh, taking the first fragment packet size chunk
00115 // out of whole and creating a sendable packet in fragment.  Returns the
00116 // next offset if there is still more data, or 0 if finished.
00117 unsigned int SocketZero::MakeNextFragment(const Data &whole, Data &fragment, unsigned int offset)
00118 {
00119         // sanity check
00120         if( whole.GetSize() < SB_FRAG_HEADER_SIZE ) {
00121                 eout("Whole packet too short to fragment: " << whole.GetSize());
00122                 throw Error("Socket: Whole packet too short to fragment");
00123         }
00124 
00125         // calculate size
00126         unsigned int todo = whole.GetSize() - SB_FRAG_HEADER_SIZE - offset;
00127         unsigned int nextOffset = 0;
00128         if( todo > (MAX_PACKET_SIZE - SB_FRAG_HEADER_SIZE) ) {
00129                 todo = MAX_PACKET_SIZE - SB_FRAG_HEADER_SIZE;
00130                 nextOffset = offset + todo;
00131         }
00132 
00133         // create fragment header
00134         unsigned char *buf = fragment.GetBuffer(SB_FRAG_HEADER_SIZE + todo);
00135         memcpy(buf, whole.GetData(), SB_FRAG_HEADER_SIZE);
00136 
00137         // copy over a fragment size of data
00138         memcpy(buf + SB_FRAG_HEADER_SIZE, whole.GetData() + SB_FRAG_HEADER_SIZE + offset, todo);
00139 
00140         // update fragment's size and command type
00141         Barry::Protocol::Packet *wpack = (Barry::Protocol::Packet *) buf;
00142         wpack->size = htobs((uint16_t) (todo + SB_FRAG_HEADER_SIZE));
00143         if( nextOffset )
00144                 wpack->command = SB_COMMAND_DB_FRAGMENTED;
00145         else
00146                 wpack->command = SB_COMMAND_DB_DATA;
00147 
00148         // adjust the new fragment size
00149         fragment.ReleaseBuffer(SB_FRAG_HEADER_SIZE + todo);
00150 
00151         // return next round
00152         return nextOffset;
00153 }
00154 
00155 
00156 ///////////////////////////////////////
00157 // SocketZero private API
00158 
00159 //
00160 // FIXME - not sure yet whether sequence ID's are per socket or not... if
00161 // they are per socket, then this global sequence behaviour will not work,
00162 // and we need to track m_sequenceId on a Socket level.
00163 //
00164 void SocketZero::CheckSequence(uint16_t socket, const Data &seq)
00165 {
00166         MAKE_PACKET(spack, seq);
00167         if( (unsigned int) seq.GetSize() < SB_SEQUENCE_PACKET_SIZE ) {
00168                 eout("Short sequence packet:\n" << seq);
00169                 throw Error("Socket: invalid sequence packet");
00170         }
00171 
00172         // we'll cheat here... if the packet's sequence is 0, we'll
00173         // silently restart, otherwise, fail
00174         uint32_t sequenceId = btohl(spack->u.sequence.sequenceId);
00175         if( sequenceId == 0 ) {
00176                 // silently restart (will advance below)
00177                 m_sequenceId = 0;
00178         }
00179         else {
00180                 if( sequenceId != m_sequenceId ) {
00181                         if( socket != 0 ) {
00182                                 std::ostringstream oss;
00183                                 oss << "Socket 0x" << std::hex << (unsigned int)socket
00184                                         << ": out of sequence. "
00185                                         << "(Global sequence: " << m_sequenceId
00186                                         << ". Packet sequence: " << sequenceId
00187                                         << ")";
00188                                 eout(oss.str());
00189                                 throw Error(oss.str());
00190                         }
00191                         else {
00192                                 dout("Bad sequence on socket 0: expected: "
00193                                         << m_sequenceId
00194                                         << ". Packet sequence: " << sequenceId);
00195                         }
00196                 }
00197         }
00198 
00199         // advance!
00200         m_sequenceId++;
00201 }
00202 
00203 void SocketZero::SendOpen(uint16_t socket, Data &receive)
00204 {
00205         // build open command
00206         Barry::Protocol::Packet packet;
00207         packet.socket = 0;
00208         packet.size = htobs(SB_SOCKET_PACKET_HEADER_SIZE);
00209         packet.command = SB_COMMAND_OPEN_SOCKET;
00210         packet.u.socket.socket = htobs(socket);
00211         packet.u.socket.sequence = m_zeroSocketSequence;// overwritten by Send()
00212 
00213         Data send(&packet, SB_SOCKET_PACKET_HEADER_SIZE);
00214         try {
00215                 RawSend(send);
00216                 RawReceive(receive);
00217         } catch( Usb::Error & ) {
00218                 eeout(send, receive);
00219                 throw;
00220         }
00221 
00222         // check sequence ID
00223         Protocol::CheckSize(receive, SB_PACKET_HEADER_SIZE);
00224         if( IS_COMMAND(receive, SB_COMMAND_SEQUENCE_HANDSHAKE) ) {
00225                 CheckSequence(0, receive);
00226 
00227                 // still need our ACK
00228                 RawReceive(receive);
00229         }
00230 
00231         // receive now holds the Open response
00232 }
00233 
00234 // SHA1 hashing logic based on Rick Scott's XmBlackBerry's send_password()
00235 void SocketZero::SendPasswordHash(uint16_t socket, const char *password, Data &receive)
00236 {
00237         unsigned char pwdigest[SHA_DIGEST_LENGTH];
00238         unsigned char prefixedhash[SHA_DIGEST_LENGTH + 4];
00239 
00240         // first, hash the password by itself
00241         SHA1((unsigned char *) password, strlen(password), pwdigest);
00242 
00243         // prefix the resulting hash with the provided seed
00244         uint32_t seed = htobl(m_challengeSeed);
00245         memcpy(&prefixedhash[0], &seed, sizeof(uint32_t));
00246         memcpy(&prefixedhash[4], pwdigest, SHA_DIGEST_LENGTH);
00247 
00248         // hash again
00249         SHA1((unsigned char *) prefixedhash, SHA_DIGEST_LENGTH + 4, pwdigest);
00250 
00251 
00252         size_t size = SB_SOCKET_PACKET_HEADER_SIZE + PASSWORD_CHALLENGE_SIZE;
00253 
00254         // build open command
00255         Barry::Protocol::Packet packet;
00256         packet.socket = 0;
00257         packet.size = htobs(size);
00258         packet.command = SB_COMMAND_PASSWORD;
00259         packet.u.socket.socket = htobs(socket);
00260         packet.u.socket.sequence = m_zeroSocketSequence;// overwritten by Send()
00261         packet.u.socket.u.password.remaining_tries = 0;
00262         packet.u.socket.u.password.unknown = 0;
00263         packet.u.socket.u.password.param = htobs(0x14); // FIXME - what does this mean?
00264         memcpy(packet.u.socket.u.password.u.hash, pwdigest,
00265                 sizeof(packet.u.socket.u.password.u.hash));
00266 
00267         // blank password hashes as we don't need these anymore
00268         memset(pwdigest, 0, sizeof(pwdigest));
00269         memset(prefixedhash, 0, sizeof(prefixedhash));
00270 
00271         Data send(&packet, size);
00272         RawSend(send);
00273         RawReceive(receive);
00274 
00275         // blank password hash as we don't need this anymore either
00276         memset(packet.u.socket.u.password.u.hash, 0,
00277                 sizeof(packet.u.socket.u.password.u.hash));
00278         send.Zap();
00279 
00280         // check sequence ID
00281         Protocol::CheckSize(receive, SB_PACKET_HEADER_SIZE);
00282         if( IS_COMMAND(receive, SB_COMMAND_SEQUENCE_HANDSHAKE) ) {
00283                 CheckSequence(0, receive);
00284 
00285                 // still need our ACK
00286                 RawReceive(receive);
00287         }
00288 
00289         // receive now holds the Password response
00290 }
00291 
00292 void SocketZero::RawSend(Data &send, int timeout)
00293 {
00294         Usb::Device *dev = m_queue ? m_queue->GetUsbDevice() : m_dev;
00295 
00296         // Special case: it seems that sending packets with a size that's an
00297         // exact multiple of 0x40 causes the device to get confused.
00298         //
00299         // To get around that, it is observed in the captures that the size
00300         // is sent in a special 3 byte packet before the real packet.
00301         // Check for this case here.
00302         //
00303         if( (send.GetSize() % 0x40) == 0 ) {
00304                 Protocol::SizePacket packet;
00305                 packet.size = htobs(send.GetSize());
00306                 packet.buffer[2] = 0;           // zero the top byte
00307                 Data sizeCommand(&packet, 3);
00308 
00309                 dev->BulkWrite(m_writeEp, sizeCommand);
00310         }
00311 
00312         dev->BulkWrite(m_writeEp, send);
00313 }
00314 
00315 void SocketZero::RawReceive(Data &receive, int timeout)
00316 {
00317         do {
00318                 if( m_queue ) {
00319                         if( !m_queue->DefaultRead(receive, timeout) )
00320                                 throw Timeout("SocketZero::RawReceive: queue DefaultRead returned false (likely a timeout)");
00321                 }
00322                 else {
00323                         m_dev->BulkRead(m_readEp, receive, timeout);
00324                 }
00325                 ddout("SocketZero::RawReceive: Endpoint "
00326                         << (m_queue ? m_queue->GetReadEp() : m_readEp)
00327                         << "\nReceived:\n" << receive);
00328         } while( SequencePacket(receive) );
00329 }
00330 
00331 //
00332 // SequencePacket
00333 //
00334 /// Returns true if this is a sequence packet that should be ignored.
00335 /// This function is used in SocketZero::RawReceive() in order
00336 /// to determine whether to keep reading or not.  By default,
00337 /// this function checks whether the packet is a sequence packet
00338 /// or not, and returns true if so.  Also, if it is a sequence
00339 /// packet, it checks the validity of the sequence number.
00340 ///
00341 /// If sequence packets become important in the future, this
00342 /// function could be changed to call a user-defined callback,
00343 /// in order to handle these things out of band.
00344 ///
00345 bool SocketZero::SequencePacket(const Data &data)
00346 {
00347         // Begin -- Test quiet durty :(
00348         if (m_hideSequencePacket == false) {
00349                 return false;
00350         }
00351         // End -- Test quiet durty :(
00352 
00353         if( data.GetSize() >= MIN_PACKET_SIZE ) {
00354                 MAKE_PACKET(rpack, data);
00355                 if( rpack->socket == 0 &&
00356                     rpack->command == SB_COMMAND_SEQUENCE_HANDSHAKE )
00357                 {
00358                         CheckSequence(0, data);
00359                         return true;
00360                 }
00361         }
00362         return false;   // not a sequence packet
00363 }
00364 
00365 
00366 ///////////////////////////////////////
00367 // SocketZero public API
00368 
00369 void SocketZero::SetRoutingQueue(SocketRoutingQueue &queue)
00370 {
00371         // replace the current queue pointer
00372         m_queue = &queue;
00373 }
00374 
00375 void SocketZero::UnlinkRoutingQueue()
00376 {
00377         m_queue = 0;
00378 }
00379 
00380 void SocketZero::Send(Data &send, int timeout)
00381 {
00382         // force the socket number to 0
00383         if( send.GetSize() >= SB_SOCKET_PACKET_HEADER_SIZE ) {
00384                 MAKE_PACKETPTR_BUF(spack, send.GetBuffer());
00385                 spack->socket = 0;
00386         }
00387 
00388         // This is a socket 0 packet, so force the send packet data's
00389         // socket 0 sequence number to something correct.
00390         if( send.GetSize() >= SB_SOCKET_PACKET_HEADER_SIZE ) {
00391                 MAKE_PACKETPTR_BUF(spack, send.GetBuffer());
00392                 spack->u.socket.sequence = m_zeroSocketSequence;
00393                 m_zeroSocketSequence++;
00394         }
00395 
00396         RawSend(send, timeout);
00397 }
00398 
00399 void SocketZero::Send(Data &send, Data &receive, int timeout)
00400 {
00401         Send(send, timeout);
00402         RawReceive(receive, timeout);
00403 }
00404 
00405 void SocketZero::Send(Barry::Packet &packet, int timeout)
00406 {
00407         Send(packet.m_send, packet.m_receive, timeout);
00408 }
00409 
00410 void SocketZero::Receive(Data &receive, int timeout)
00411 {
00412         RawReceive(receive, timeout);
00413 }
00414 
00415 
00416 //
00417 // Open
00418 //
00419 /// Open a logical socket on the device.
00420 ///
00421 /// Both the socket number and the flag are based on the response to the
00422 /// SELECT_MODE command.  See Controller::SelectMode() for more info
00423 /// on this.
00424 ///
00425 /// The packet sequence is normal for most socket operations.
00426 ///
00427 ///     - Down: command packet with OPEN_SOCKET
00428 ///     - Up: optional sequence handshake packet
00429 ///     - Up: command response, which repeats the socket and flag data
00430 ///             as confirmation
00431 ///
00432 /// \exception  Barry::Error
00433 ///             Thrown on protocol error.
00434 ///
00435 /// \exception  Barry::BadPassword
00436 ///             Thrown on invalid password, or not enough retries left
00437 ///             on device.
00438 ///
00439 SocketHandle SocketZero::Open(uint16_t socket, const char *password)
00440 {
00441         // Things get a little funky here, as we may be left in an
00442         // intermediate state in the case of a failed password.
00443         // This function should support being called as many times
00444         // as needed to handle the password
00445 
00446         Data send, receive;
00447         ZeroPacket packet(send, receive);
00448 
00449         // save sequence for later close
00450         uint8_t closeFlag = GetZeroSocketSequence();
00451 
00452         if( !m_halfOpen ) {
00453                 // starting fresh
00454                 m_remainingTries = 0;
00455 
00456                 SendOpen(socket, receive);
00457 
00458                 // check for password challenge, or success
00459                 if( packet.Command() == SB_COMMAND_PASSWORD_CHALLENGE ) {
00460                         m_halfOpen = true;
00461                         m_challengeSeed = packet.ChallengeSeed();
00462                         m_remainingTries = packet.RemainingTries();
00463                 }
00464 
00465                 // fall through to challenge code...
00466         }
00467 
00468         if( m_halfOpen ) {
00469                 // half open, device is expecting a password hash... do we
00470                 // have a password?
00471                 if( !password ) {
00472                         throw BadPassword("No password specified.", m_remainingTries, false);
00473                 }
00474 
00475                 // only allow password attempts if there are
00476                 // BARRY_MIN_PASSWORD_TRIES or more tries remaining...
00477                 // we want to give the user at least some chance on a
00478                 // Windows machine before the device commits suicide.
00479                 if( m_remainingTries < BARRY_MIN_PASSWORD_TRIES ) {
00480                         throw BadPassword("Fewer than " BARRY_MIN_PASSWORD_TRIES_ASC " password tries remaining in device. Refusing to proceed, to avoid device zapping itself.  Use a Windows client, or re-cradle the device.",
00481                                 m_remainingTries,
00482                                 true);
00483                 }
00484 
00485                 // save sequence for later close (again after SendOpen())
00486                 closeFlag = GetZeroSocketSequence();
00487 
00488                 SendPasswordHash(socket, password, receive);
00489 
00490                 if( packet.Command() == SB_COMMAND_PASSWORD_FAILED ) {
00491                         m_halfOpen = true;
00492                         m_challengeSeed = packet.ChallengeSeed();
00493                         m_remainingTries = packet.RemainingTries();
00494                         throw BadPassword("Password rejected by device.", m_remainingTries, false);
00495                 }
00496 
00497                 // if we get this far, we are no longer in half-open password
00498                 // mode, so we can reset our flags
00499                 m_halfOpen = false;
00500 
00501                 // fall through to success check...
00502         }
00503 
00504         if( packet.Command() != SB_COMMAND_OPENED_SOCKET ||
00505             packet.SocketResponse() != socket ||
00506             packet.SocketSequence() != closeFlag )
00507         {
00508                 eout("Packet:\n" << receive);
00509                 throw Error("Socket: Bad OPENED packet in Open");
00510         }
00511 
00512         // success!  save the socket
00513         return SocketHandle(new Socket(*this, socket, closeFlag));
00514 }
00515 
00516 //
00517 // Close
00518 //
00519 /// Closes a non-default socket (i.e. non-zero socket number)
00520 ///
00521 /// The packet sequence is just like Open(), except the command is
00522 /// CLOSE_SOCKET.
00523 ///
00524 /// \exception  Barry::Error
00525 ///
00526 void SocketZero::Close(Socket &socket)
00527 {
00528         if( socket.GetSocket() == 0 )
00529                 return;         // nothing to do
00530 
00531         // build close command
00532         Barry::Protocol::Packet packet;
00533         packet.socket = 0;
00534         packet.size = htobs(SB_SOCKET_PACKET_HEADER_SIZE);
00535         packet.command = SB_COMMAND_CLOSE_SOCKET;
00536         packet.u.socket.socket = htobs(socket.GetSocket());
00537         packet.u.socket.sequence = socket.GetCloseFlag();
00538 
00539         Data command(&packet, SB_SOCKET_PACKET_HEADER_SIZE);
00540         Data response;
00541         try {
00542                 Send(command, response);
00543         }
00544         catch( Usb::Error & ) {
00545                 // reset so this won't be called again
00546                 socket.ForceClosed();
00547 
00548                 eeout(command, response);
00549                 throw;
00550         }
00551 
00552         // starting fresh, reset sequence ID
00553         Protocol::CheckSize(response, SB_PACKET_HEADER_SIZE);
00554         if( IS_COMMAND(response, SB_COMMAND_SEQUENCE_HANDSHAKE) ) {
00555                 CheckSequence(0, response);
00556 
00557                 // still need our ACK
00558                 RawReceive(response);
00559         }
00560 
00561         Protocol::CheckSize(response, SB_SOCKET_PACKET_HEADER_SIZE);
00562         MAKE_PACKET(rpack, response);
00563         if( rpack->command != SB_COMMAND_CLOSED_SOCKET ||
00564             btohs(rpack->u.socket.socket) != socket.GetSocket() ||
00565             rpack->u.socket.sequence != socket.GetCloseFlag() )
00566         {
00567                 // reset so this won't be called again
00568                 socket.ForceClosed();
00569 
00570                 eout("Packet:\n" << response);
00571                 throw BadPacket(rpack->command, "Socket: Bad CLOSED packet in Close");
00572         }
00573 
00574         if( m_resetOnClose ) {
00575                 Data send, receive;
00576                 ZeroPacket reset_packet(send, receive);
00577                 reset_packet.Reset();
00578 
00579                 Send(reset_packet);
00580                 if( reset_packet.CommandResponse() != SB_COMMAND_RESET_REPLY ) {
00581                         throw BadPacket(reset_packet.CommandResponse(),
00582                                 "Socket: Missing RESET_REPLY in Close");
00583                 }
00584         }
00585 
00586 //      // and finally, there always seems to be an extra read of
00587 //      // an empty packet at the end... just throw it away
00588 //      try {
00589 //              RawReceive(response, 1);
00590 //      }
00591 //      catch( Usb::Timeout & ) {
00592 //      }
00593 
00594         // reset socket and flag
00595         socket.ForceClosed();
00596 }
00597 
00598 
00599 
00600 
00601 
00602 
00603 //////////////////////////////////////////////////////////////////////////////
00604 // Socket class
00605 
00606 Socket::Socket( SocketZero &zero,
00607                 uint16_t socket,
00608                 uint8_t closeFlag)
00609         : m_zero(&zero)
00610         , m_socket(socket)
00611         , m_closeFlag(closeFlag)
00612         , m_registered(false)
00613 {
00614 }
00615 
00616 Socket::~Socket()
00617 {
00618         // trap exceptions in the destructor
00619         try {
00620                 // a non-default socket has been opened, close it
00621                 Close();
00622         }
00623         catch( std::runtime_error &re ) {
00624                 // do nothing... log it?
00625                 dout("Exception caught in ~Socket: " << re.what());
00626         }
00627 }
00628 
00629 
00630 ////////////////////////////////////
00631 // Socket protected API
00632 
00633 void Socket::CheckSequence(const Data &seq)
00634 {
00635         m_zero->CheckSequence(m_socket, seq);
00636 }
00637 
00638 void Socket::ForceClosed()
00639 {
00640         m_socket = 0;
00641         m_closeFlag = 0;
00642 }
00643 
00644 
00645 ////////////////////////////////////
00646 // Socket public API
00647 
00648 void Socket::Close()
00649 {
00650         UnregisterInterest();
00651         m_zero->Close(*this);
00652 }
00653 
00654 
00655 //
00656 // Send
00657 //
00658 /// Sends 'send' data to device, no receive.
00659 ///
00660 /// \returns    void
00661 ///
00662 /// \exception  Usb::Error on underlying bus errors.
00663 ///
00664 void Socket::Send(Data &send, int timeout)
00665 {
00666         // force the socket number to this socket
00667         if( send.GetSize() >= SB_PACKET_HEADER_SIZE ) {
00668                 MAKE_PACKETPTR_BUF(spack, send.GetBuffer());
00669                 spack->socket = htobs(m_socket);
00670         }
00671         m_zero->RawSend(send, timeout);
00672 }
00673 
00674 //
00675 // Send
00676 //
00677 /// Sends 'send' data to device, and waits for response.
00678 ///
00679 /// \returns    void
00680 ///
00681 /// \exception  Usb::Error on underlying bus errors.
00682 ///
00683 void Socket::Send(Data &send, Data &receive, int timeout)
00684 {
00685         Send(send, timeout);
00686         Receive(receive, timeout);
00687 }
00688 
00689 void Socket::Send(Barry::Packet &packet, int timeout)
00690 {
00691         Send(packet.m_send, packet.m_receive, timeout);
00692 }
00693 
00694 void Socket::Receive(Data &receive, int timeout)
00695 {
00696         if( m_registered ) {
00697                 if( m_zero->m_queue ) {
00698                         if( !m_zero->m_queue->SocketRead(m_socket, receive, timeout) )
00699                                 throw Timeout("Socket::Receive: queue SocketRead returned false (likely a timeout)");
00700                 }
00701                 else {
00702                         throw std::logic_error("NULL queue pointer in a registered socket read.");
00703                 }
00704         }
00705         else {
00706                 m_zero->RawReceive(receive, timeout);
00707         }
00708 }
00709 
00710 
00711 // FIXME - find a better way to do this?
00712 void Socket::ReceiveData(Data &receive, int timeout)
00713 {
00714         HideSequencePacket(false);
00715         Receive(receive);
00716         HideSequencePacket(true);
00717 }
00718 
00719 
00720 // FIXME - find a better way to do this?
00721 void Socket::InitSequence(int timeout)
00722 {
00723         Data receive;
00724         receive.Zap();
00725 
00726         HideSequencePacket(false);
00727         Receive(receive);
00728         HideSequencePacket(true);
00729 
00730         Protocol::CheckSize(receive, SB_PACKET_HEADER_SIZE);
00731         CheckSequence(receive);
00732 }
00733 
00734 
00735 // sends the send packet down to the device
00736 // Blocks until response received or timed out in Usb::Device
00737 //
00738 // This function is used to send packet to JVM
00739 void Socket::PacketJVM(Data &send, Data &receive, int timeout)
00740 {
00741         if( ( send.GetSize() < MIN_PACKET_DATA_SIZE ) ||
00742                 ( send.GetSize() > MAX_PACKET_DATA_SIZE ) ) {
00743                 // we don't do that around here
00744                 throw std::logic_error("Socket: unknown send data in PacketJVM()");
00745         }
00746 
00747         Data &inFrag = receive;
00748         receive.Zap();
00749 
00750         // send non-fragmented
00751         Send(send, inFrag, timeout);
00752 
00753         bool done = false;
00754         int blankCount = 0;
00755 
00756         while( !done ) {
00757                 // check the packet's validity
00758                 if( inFrag.GetSize() > 6 ) {
00759                         MAKE_PACKET(rpack, inFrag);
00760 
00761                         blankCount = 0;
00762 
00763                         Protocol::CheckSize(inFrag, SB_PACKET_HEADER_SIZE);
00764 
00765                         switch( rpack->command )
00766                         {
00767                         case SB_COMMAND_SEQUENCE_HANDSHAKE:
00768                                 CheckSequence(inFrag);
00769                                 break;
00770 
00771                         default: {
00772                                 std::ostringstream oss;
00773                                 oss << "Socket: (read) unhandled packet in Packet(): 0x" << std::hex << (unsigned int)rpack->command;
00774                                 eout(oss.str());
00775                                 throw Error(oss.str());
00776                                 }
00777                                 break;
00778                         }
00779                 }
00780                 else if( inFrag.GetSize() == 6 ) {
00781                         done = true;
00782                 }
00783                 else {
00784                         blankCount++;
00785 
00786                         //std::cerr << "Blank! " << blankCount << std::endl;
00787                         if( blankCount == 10 ) {
00788                                 // only ask for more data on stalled sockets
00789                                 // for so long
00790                                 throw Error("Socket: 10 blank packets received");
00791                         }
00792                 }
00793 
00794                 if( !done ) {
00795                         // not done yet, ask for another read
00796                         Receive(inFrag);
00797                 }
00798         }
00799 }
00800 
00801 // sends the send packet down to the device
00802 // Blocks until response received or timed out in Usb::Device
00803 void Socket::PacketData(Data &send, Data &receive, int timeout)
00804 {
00805         if( ( send.GetSize() < MIN_PACKET_DATA_SIZE ) ||
00806                 ( send.GetSize() > MAX_PACKET_DATA_SIZE ) ) {
00807                 // we don't do that around here
00808                 throw std::logic_error("Socket: unknown send data in PacketData()");
00809         }
00810 
00811         Data &inFrag = receive;
00812         receive.Zap();
00813 
00814         // send non-fragmented
00815         Send(send, inFrag, timeout);
00816 
00817         bool done = false;
00818         int blankCount = 0;
00819 
00820         while( !done ) {
00821                 // check the packet's validity
00822                 if( inFrag.GetSize() > 0 ) {
00823                         MAKE_PACKET(rpack, inFrag);
00824 
00825                         blankCount = 0;
00826 
00827                         Protocol::CheckSize(inFrag, SB_PACKET_HEADER_SIZE);
00828 
00829                         switch( rpack->command )
00830                         {
00831                         case SB_COMMAND_SEQUENCE_HANDSHAKE:
00832                                 CheckSequence(inFrag);
00833                                 if (!m_zero->IsSequencePacketHidden())
00834                                         done = true;
00835                                 break;
00836 
00837                         case SB_COMMAND_JL_READY:
00838                         case SB_COMMAND_JL_ACK:
00839                         case SB_COMMAND_JL_HELLO_ACK:
00840                         case SB_COMMAND_JL_RESET_REQUIRED:
00841                                 done = true;
00842                                 break;
00843 
00844                         case SB_COMMAND_JL_GET_DATA_ENTRY:      // This response means that the next packet is the stream
00845                                 done = true;
00846                                 break;
00847 
00848                         case SB_DATA_JL_INVALID:
00849                                 throw BadPacket(rpack->command, "file is not a valid Java code file");
00850                                 break;
00851 
00852                         case SB_COMMAND_JL_NOT_SUPPORTED:
00853                                 throw BadPacket(rpack->command, "device does not support requested command");
00854                                 break;
00855 
00856                         default:
00857                                 // unknown packet, pass it up to the
00858                                 // next higher code layer
00859                                 done = true;
00860                                 break;
00861                         }
00862                 }
00863                 else {
00864                         blankCount++;
00865                         //std::cerr << "Blank! " << blankCount << std::endl;
00866                         if( blankCount == 10 ) {
00867                                 // only ask for more data on stalled sockets
00868                                 // for so long
00869                                 throw Error("Socket: 10 blank packets received");
00870                         }
00871                 }
00872 
00873                 if( !done ) {
00874                         // not done yet, ask for another read
00875                         Receive(inFrag);
00876                 }
00877         }
00878 }
00879 
00880 // sends the send packet down to the device, fragmenting if
00881 // necessary, and returns the response in receive, defragmenting
00882 // if needed
00883 // Blocks until response received or timed out in Usb::Device
00884 //
00885 // This is primarily for Desktop Database packets... Javaloader
00886 // packets use PacketData().
00887 //
00888 void Socket::Packet(Data &send, Data &receive, int timeout)
00889 {
00890         MAKE_PACKET(spack, send);
00891         if( send.GetSize() < MIN_PACKET_SIZE ||
00892             (spack->command != SB_COMMAND_DB_DATA &&
00893              spack->command != SB_COMMAND_DB_DONE) )
00894         {
00895                 // we don't do that around here
00896                 eout("unknown send data in Packet(): " << send);
00897                 throw std::logic_error("Socket: unknown send data in Packet()");
00898         }
00899 
00900         Data inFrag;
00901         receive.Zap();
00902 
00903         if( send.GetSize() <= MAX_PACKET_SIZE ) {
00904                 // send non-fragmented
00905                 Send(send, inFrag, timeout);
00906         }
00907         else {
00908                 // send fragmented
00909                 unsigned int offset = 0;
00910                 Data outFrag;
00911 
00912                 // You haven't to sequence packet while the whole packet isn't sent
00913                 //  a) No sequence received packet
00914                 //  b) 1°) Sent framgment 1/N
00915                 //     2°) Sent framgment 2/N
00916                 //         ...
00917                 //     N°) Before sent fragment N/N, I enable the sequence packet process.
00918                 //         Sent framgment N/N
00919                 HideSequencePacket(false);
00920 
00921                 do {
00922                         offset = SocketZero::MakeNextFragment(send, outFrag, offset);
00923 
00924                         // Is last packet ?
00925                         MAKE_PACKET(spack, outFrag);
00926 
00927                         if (spack->command != SB_COMMAND_DB_FRAGMENTED)
00928                                 HideSequencePacket(true);
00929 
00930                         Send(outFrag, inFrag, timeout);
00931 
00932                         // only process sequence handshakes... once we
00933                         // get to the last fragment, we fall through to normal
00934                         // processing below
00935                         if (spack->command != SB_COMMAND_DB_FRAGMENTED) {
00936                                 MAKE_PACKET(rpack, inFrag);
00937 
00938                                 if( offset && inFrag.GetSize() > 0 ) {
00939                                         Protocol::CheckSize(inFrag, SB_PACKET_HEADER_SIZE);
00940 
00941                                         switch( rpack->command )
00942                                         {
00943                                         case SB_COMMAND_SEQUENCE_HANDSHAKE:
00944                                                 CheckSequence(inFrag);
00945                                                 break;
00946 
00947                                         default: {
00948                                                 std::ostringstream oss;
00949                                                 oss << "Socket: (send) unhandled packet in Packet(): 0x" << std::hex << (unsigned int)rpack->command;
00950                                                 eout(oss.str());
00951                                                 throw Error(oss.str());
00952                                                 }
00953                                                 break;
00954                                         }
00955                                 }
00956                         }
00957 
00958                 } while( offset > 0 );
00959 
00960                 // To be sure that it's clean...
00961                 HideSequencePacket(true);
00962         }
00963 
00964         bool done = false, frag = false;
00965         int blankCount = 0;
00966         while( !done ) {
00967                 MAKE_PACKET(rpack, inFrag);
00968 
00969                 // check the packet's validity
00970                 if( inFrag.GetSize() > 0 ) {
00971                         blankCount = 0;
00972 
00973                         Protocol::CheckSize(inFrag, SB_PACKET_HEADER_SIZE);
00974 
00975                         switch( rpack->command )
00976                         {
00977                         case SB_COMMAND_SEQUENCE_HANDSHAKE:
00978                                 CheckSequence(inFrag);
00979                                 break;
00980 
00981                         case SB_COMMAND_DB_DATA:
00982                                 if( frag ) {
00983                                         SocketZero::AppendFragment(receive, inFrag);
00984                                 }
00985                                 else {
00986                                         receive = inFrag;
00987                                 }
00988                                 done = true;
00989                                 break;
00990 
00991                         case SB_COMMAND_DB_FRAGMENTED:
00992                                 SocketZero::AppendFragment(receive, inFrag);
00993                                 frag = true;
00994                                 break;
00995 
00996                         case SB_COMMAND_DB_DONE:
00997                                 receive = inFrag;
00998                                 done = true;
00999                                 break;
01000 
01001                         default: {
01002                                 std::ostringstream oss;
01003                                 oss << "Socket: (read) unhandled packet in Packet(): 0x" << std::hex << (unsigned int)rpack->command;
01004                                 eout(oss.str());
01005                                 throw Error(oss.str());
01006                                 }
01007                                 break;
01008                         }
01009                 }
01010                 else {
01011                         blankCount++;
01012                         //std::cerr << "Blank! " << blankCount << std::endl;
01013                         if( blankCount == 10 ) {
01014                                 // only ask for more data on stalled sockets
01015                                 // for so long
01016                                 throw Error("Socket: 10 blank packets received");
01017                         }
01018                 }
01019 
01020                 if( !done ) {
01021                         // not done yet, ask for another read
01022                         Receive(inFrag);
01023                 }
01024         }
01025 }
01026 
01027 void Socket::Packet(Barry::Packet &packet, int timeout)
01028 {
01029         Packet(packet.m_send, packet.m_receive, timeout);
01030 }
01031 
01032 void Socket::Packet(Barry::JLPacket &packet, int timeout)
01033 {
01034         if( packet.HasData() ) {
01035                 HideSequencePacket(false);
01036                 PacketData(packet.m_cmd, packet.m_receive, timeout);
01037                 HideSequencePacket(true);
01038                 PacketData(packet.m_data, packet.m_receive, timeout);
01039         }
01040         else {
01041                 PacketData(packet.m_cmd, packet.m_receive, timeout);
01042         }
01043 }
01044 
01045 void Socket::Packet(Barry::JVMPacket &packet, int timeout)
01046 {
01047         HideSequencePacket(false);
01048         PacketJVM(packet.m_cmd, packet.m_receive, timeout);
01049         HideSequencePacket(true);
01050 }
01051 
01052 void Socket::NextRecord(Data &receive)
01053 {
01054         Barry::Protocol::Packet packet;
01055         packet.socket = htobs(GetSocket());
01056         packet.size = htobs(7);
01057         packet.command = SB_COMMAND_DB_DONE;
01058         packet.u.db.tableCmd = 0;
01059         packet.u.db.u.command.operation = 0;
01060 
01061         Data command(&packet, 7);
01062         Packet(command, receive);
01063 }
01064 
01065 void Socket::RegisterInterest(SocketRoutingQueue::SocketDataHandler handler,
01066                                 void *context)
01067 {
01068         if( !m_zero->m_queue )
01069                 throw std::logic_error("SocketRoutingQueue required in SocketZero in order to call Socket::RegisterInterest()");
01070 
01071         if( m_registered )
01072                 throw std::logic_error("Socket already registered in Socket::RegisterInterest()!");
01073 
01074         m_zero->m_queue->RegisterInterest(m_socket, handler, context);
01075         m_registered = true;
01076 }
01077 
01078 void Socket::UnregisterInterest()
01079 {
01080         if( m_registered ) {
01081                 if( m_zero->m_queue )
01082                         m_zero->m_queue->UnregisterInterest(m_socket);
01083                 m_registered = false;
01084         }
01085 }
01086 
01087 
01088 } // namespace Barry
01089 

Generated on 29 Mar 2010 for Barry by  doxygen 1.6.1