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-2011, 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         if( !dev )
00296                 throw Error("SocketZero: No device available for RawSend");
00297 
00298         // Special case: it seems that sending packets with a size that's an
00299         // exact multiple of 0x40 causes the device to get confused.
00300         //
00301         // To get around that, it is observed in the captures that the size
00302         // is sent in a special 3 byte packet before the real packet.
00303         // Check for this case here.
00304         //
00305         if( (send.GetSize() % 0x40) == 0 ) {
00306                 Protocol::SizePacket packet;
00307                 packet.size = htobs(send.GetSize());
00308                 packet.buffer[2] = 0;           // zero the top byte
00309                 Data sizeCommand(&packet, 3);
00310 
00311                 dev->BulkWrite(m_writeEp, sizeCommand, timeout);
00312         }
00313 
00314         dev->BulkWrite(m_writeEp, send, timeout);
00315 }
00316 
00317 void SocketZero::RawReceive(Data &receive, int timeout)
00318 {
00319         do {
00320                 if( m_queue ) {
00321                         if( !m_queue->DefaultRead(receive, timeout) )
00322                                 throw Timeout("SocketZero::RawReceive: queue DefaultRead returned false (likely a timeout)");
00323                 }
00324                 else {
00325                         m_dev->BulkRead(m_readEp, receive, timeout);
00326                 }
00327                 ddout("SocketZero::RawReceive: Endpoint "
00328                         << (m_queue ? m_queue->GetReadEp() : m_readEp)
00329                         << "\nReceived:\n" << receive);
00330         } while( SequencePacket(receive) );
00331 }
00332 
00333 //
00334 // SequencePacket
00335 //
00336 /// Returns true if this is a sequence packet that should be ignored.
00337 /// This function is used in SocketZero::RawReceive() in order
00338 /// to determine whether to keep reading or not.  By default,
00339 /// this function checks whether the packet is a sequence packet
00340 /// or not, and returns true if so.  Also, if it is a sequence
00341 /// packet, it checks the validity of the sequence number.
00342 ///
00343 /// If sequence packets become important in the future, this
00344 /// function could be changed to call a user-defined callback,
00345 /// in order to handle these things out of band.
00346 ///
00347 bool SocketZero::SequencePacket(const Data &data)
00348 {
00349         // Begin -- Test quiet durty :(
00350         if (m_hideSequencePacket == false) {
00351                 return false;
00352         }
00353         // End -- Test quiet durty :(
00354 
00355         if( data.GetSize() >= MIN_PACKET_SIZE ) {
00356                 MAKE_PACKET(rpack, data);
00357                 if( rpack->socket == 0 &&
00358                     rpack->command == SB_COMMAND_SEQUENCE_HANDSHAKE )
00359                 {
00360                         CheckSequence(0, data);
00361                         return true;
00362                 }
00363         }
00364         return false;   // not a sequence packet
00365 }
00366 
00367 
00368 ///////////////////////////////////////
00369 // SocketZero public API
00370 
00371 void SocketZero::SetRoutingQueue(SocketRoutingQueue &queue)
00372 {
00373         // replace the current queue pointer
00374         m_queue = &queue;
00375 }
00376 
00377 void SocketZero::UnlinkRoutingQueue()
00378 {
00379         m_queue = 0;
00380 }
00381 
00382 void SocketZero::Send(Data &send, int timeout)
00383 {
00384         // force the socket number to 0
00385         if( send.GetSize() >= SB_SOCKET_PACKET_HEADER_SIZE ) {
00386                 MAKE_PACKETPTR_BUF(spack, send.GetBuffer());
00387                 spack->socket = 0;
00388         }
00389 
00390         // This is a socket 0 packet, so force the send packet data's
00391         // socket 0 sequence number to something correct.
00392         if( send.GetSize() >= SB_SOCKET_PACKET_HEADER_SIZE ) {
00393                 MAKE_PACKETPTR_BUF(spack, send.GetBuffer());
00394                 spack->u.socket.sequence = m_zeroSocketSequence;
00395                 m_zeroSocketSequence++;
00396         }
00397 
00398         RawSend(send, timeout);
00399 }
00400 
00401 void SocketZero::Send(Data &send, Data &receive, int timeout)
00402 {
00403         Send(send, timeout);
00404         RawReceive(receive, timeout);
00405 }
00406 
00407 void SocketZero::Send(Barry::Packet &packet, int timeout)
00408 {
00409         Send(packet.m_send, *packet.m_receive, timeout);
00410 }
00411 
00412 void SocketZero::Receive(Data &receive, int timeout)
00413 {
00414         RawReceive(receive, timeout);
00415 }
00416 
00417 
00418 //
00419 // Open
00420 //
00421 /// Open a logical socket on the device.
00422 ///
00423 /// Both the socket number and the flag are based on the response to the
00424 /// SELECT_MODE command.  See Controller::SelectMode() for more info
00425 /// on this.
00426 ///
00427 /// The packet sequence is normal for most socket operations.
00428 ///
00429 ///     - Down: command packet with OPEN_SOCKET
00430 ///     - Up: optional sequence handshake packet
00431 ///     - Up: command response, which repeats the socket and flag data
00432 ///             as confirmation
00433 ///
00434 /// \exception  Barry::Error
00435 ///             Thrown on protocol error.
00436 ///
00437 /// \exception  Barry::BadPassword
00438 ///             Thrown on invalid password, or not enough retries left
00439 ///             on device.
00440 ///
00441 SocketHandle SocketZero::Open(uint16_t socket, const char *password)
00442 {
00443         // Things get a little funky here, as we may be left in an
00444         // intermediate state in the case of a failed password.
00445         // This function should support being called as many times
00446         // as needed to handle the password
00447 
00448         Data send, receive;
00449         ZeroPacket packet(send, receive);
00450 
00451         // save sequence for later close
00452         uint8_t closeFlag = GetZeroSocketSequence();
00453 
00454         if( !m_halfOpen ) {
00455                 // starting fresh
00456                 m_remainingTries = 0;
00457 
00458                 SendOpen(socket, receive);
00459 
00460                 // check for password challenge, or success
00461                 if( packet.Command() == SB_COMMAND_PASSWORD_CHALLENGE ) {
00462                         m_halfOpen = true;
00463                         m_challengeSeed = packet.ChallengeSeed();
00464                         m_remainingTries = packet.RemainingTries();
00465                 }
00466 
00467                 // fall through to challenge code...
00468         }
00469 
00470         if( m_halfOpen ) {
00471                 // half open, device is expecting a password hash... do we
00472                 // have a password?
00473                 if( !password ) {
00474                         throw BadPassword("No password specified.", m_remainingTries, false);
00475                 }
00476 
00477                 // only allow password attempts if there are
00478                 // BARRY_MIN_PASSWORD_TRIES or more tries remaining...
00479                 // we want to give the user at least some chance on a
00480                 // Windows machine before the device commits suicide.
00481                 if( m_remainingTries < BARRY_MIN_PASSWORD_TRIES ) {
00482                         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.",
00483                                 m_remainingTries,
00484                                 true);
00485                 }
00486 
00487                 // save sequence for later close (again after SendOpen())
00488                 closeFlag = GetZeroSocketSequence();
00489 
00490                 SendPasswordHash(socket, password, receive);
00491 
00492                 if( packet.Command() == SB_COMMAND_PASSWORD_FAILED ) {
00493                         m_halfOpen = true;
00494                         m_challengeSeed = packet.ChallengeSeed();
00495                         m_remainingTries = packet.RemainingTries();
00496                         throw BadPassword("Password rejected by device.", m_remainingTries, false);
00497                 }
00498 
00499                 // if we get this far, we are no longer in half-open password
00500                 // mode, so we can reset our flags
00501                 m_halfOpen = false;
00502 
00503                 // fall through to success check...
00504         }
00505 
00506         // If the device thinks that the socket was already open then
00507         // it will tell us by sending an SB_COMMAND_CLOSE_SOCKET.
00508         //
00509         // This happens most commonly when using raw channels which
00510         // haven't been cleanly closed (such as by killing the process
00511         // running Barry) and so the device still thinks the socket
00512         // is open.
00513         //
00514         // Retrying the open will usually succeed, but relies on the
00515         // device software re-creating the channel after it's closed
00516         // so return an error here instead of automatically retrying.
00517         if( packet.Command() == SB_COMMAND_CLOSE_SOCKET )
00518         {
00519                 throw Error("Socket: Device closed socket when trying to open");
00520         }
00521 
00522         if( packet.Command() != SB_COMMAND_OPENED_SOCKET ||
00523             packet.SocketResponse() != socket ||
00524             packet.SocketSequence() != closeFlag )
00525         {
00526                 eout("Packet:\n" << receive);
00527                 throw Error("Socket: Bad OPENED packet in Open");
00528         }
00529 
00530         // success!  save the socket
00531         return SocketHandle(new Socket(*this, socket, closeFlag));
00532 }
00533 
00534 //
00535 // Close
00536 //
00537 /// Closes a non-default socket (i.e. non-zero socket number)
00538 ///
00539 /// The packet sequence is just like Open(), except the command is
00540 /// CLOSE_SOCKET.
00541 ///
00542 /// \exception  Barry::Error
00543 ///
00544 void SocketZero::Close(Socket &socket)
00545 {
00546         if( socket.GetSocket() == 0 )
00547                 return;         // nothing to do
00548 
00549         // build close command
00550         Barry::Protocol::Packet packet;
00551         packet.socket = 0;
00552         packet.size = htobs(SB_SOCKET_PACKET_HEADER_SIZE);
00553         packet.command = SB_COMMAND_CLOSE_SOCKET;
00554         packet.u.socket.socket = htobs(socket.GetSocket());
00555         packet.u.socket.sequence = socket.GetCloseFlag();
00556 
00557         Data command(&packet, SB_SOCKET_PACKET_HEADER_SIZE);
00558         Data response;
00559         try {
00560                 Send(command, response);
00561         }
00562         catch( Usb::Error & ) {
00563                 // reset so this won't be called again
00564                 socket.ForceClosed();
00565 
00566                 eeout(command, response);
00567                 throw;
00568         }
00569 
00570         // starting fresh, reset sequence ID
00571         Protocol::CheckSize(response, SB_PACKET_HEADER_SIZE);
00572         if( IS_COMMAND(response, SB_COMMAND_SEQUENCE_HANDSHAKE) ) {
00573                 CheckSequence(0, response);
00574 
00575                 // still need our ACK
00576                 RawReceive(response);
00577         }
00578 
00579         Protocol::CheckSize(response, SB_SOCKET_PACKET_HEADER_SIZE);
00580         MAKE_PACKET(rpack, response);
00581         // The reply will be SB_COMMAND_CLOSED_SOCKET if the device
00582         // has closed the socket in response to our request.
00583         //
00584         // It's also possible for the reply to be
00585         // SB_COMMAND_REMOTE_CLOSE_SOCKET if the device wanted to
00586         // close the socket at the same time, such as if the channel
00587         // API is being used by the device.
00588         if( ( rpack->command != SB_COMMAND_CLOSED_SOCKET &&
00589               rpack->command != SB_COMMAND_REMOTE_CLOSE_SOCKET ) ||
00590             btohs(rpack->u.socket.socket) != socket.GetSocket() ||
00591             rpack->u.socket.sequence != socket.GetCloseFlag() )
00592         {
00593                 // reset so this won't be called again
00594                 socket.ForceClosed();
00595 
00596                 eout("Packet:\n" << response);
00597                 throw BadPacket(rpack->command, "Socket: Bad CLOSED packet in Close");
00598         }
00599 
00600         if( m_resetOnClose ) {
00601                 Data send, receive;
00602                 ZeroPacket reset_packet(send, receive);
00603                 reset_packet.Reset();
00604 
00605                 Send(reset_packet);
00606                 if( reset_packet.CommandResponse() != SB_COMMAND_RESET_REPLY ) {
00607                         throw BadPacket(reset_packet.CommandResponse(),
00608                                 "Socket: Missing RESET_REPLY in Close");
00609                 }
00610         }
00611 
00612 //      // and finally, there always seems to be an extra read of
00613 //      // an empty packet at the end... just throw it away
00614 //      try {
00615 //              RawReceive(response, 1);
00616 //      }
00617 //      catch( Usb::Timeout & ) {
00618 //      }
00619 
00620         // reset socket and flag
00621         socket.ForceClosed();
00622 }
00623 
00624 //
00625 // ClearHalt
00626 //
00627 /// Clears the USB Halt bit on both the read and write endpoints
00628 ///
00629 void SocketZero::ClearHalt()
00630 {
00631         Usb::Device *dev = m_queue ? m_queue->GetUsbDevice() : m_dev;
00632         if( !dev )
00633                 throw Error("SocketZero: No device available for ClearHalt");
00634 
00635         // clear the read endpoint
00636         if( m_queue ) {
00637                 dev->ClearHalt(m_queue->GetReadEp());
00638         }
00639         else {
00640                 dev->ClearHalt(m_readEp);
00641         }
00642 
00643         // clear the write endpoint
00644         dev->ClearHalt(m_writeEp);
00645 }
00646 
00647 
00648 
00649 
00650 
00651 
00652 //////////////////////////////////////////////////////////////////////////////
00653 // Socket class
00654 
00655 Socket::Socket( SocketZero &zero,
00656                 uint16_t socket,
00657                 uint8_t closeFlag)
00658         : m_zero(&zero)
00659         , m_socket(socket)
00660         , m_closeFlag(closeFlag)
00661         , m_registered(false)
00662 {
00663 }
00664 
00665 Socket::~Socket()
00666 {
00667         // trap exceptions in the destructor
00668         try {
00669                 // a non-default socket has been opened, close it
00670                 Close();
00671         }
00672         catch( std::runtime_error &re ) {
00673                 // do nothing... log it?
00674                 dout("Exception caught in ~Socket: " << re.what());
00675         }
00676 }
00677 
00678 
00679 ////////////////////////////////////
00680 // Socket protected API
00681 
00682 void Socket::CheckSequence(const Data &seq)
00683 {
00684         m_zero->CheckSequence(m_socket, seq);
00685 }
00686 
00687 void Socket::ForceClosed()
00688 {
00689         m_socket = 0;
00690         m_closeFlag = 0;
00691 }
00692 
00693 
00694 ////////////////////////////////////
00695 // Socket public API
00696 
00697 void Socket::Close()
00698 {
00699         UnregisterInterest();
00700         m_zero->Close(*this);
00701 }
00702 
00703 
00704 //
00705 // Send
00706 //
00707 /// Sends 'send' data to device, no receive.
00708 ///
00709 /// \returns    void
00710 ///
00711 /// \exception  Usb::Error on underlying bus errors.
00712 ///
00713 void Socket::Send(Data &send, int timeout)
00714 {
00715         // force the socket number to this socket
00716         if( send.GetSize() >= SB_PACKET_HEADER_SIZE ) {
00717                 MAKE_PACKETPTR_BUF(spack, send.GetBuffer());
00718                 spack->socket = htobs(m_socket);
00719         }
00720         m_zero->RawSend(send, timeout);
00721 }
00722 
00723 //
00724 // Send
00725 //
00726 /// Sends 'send' data to device, and waits for response.
00727 ///
00728 /// \returns    void
00729 ///
00730 /// \exception  Usb::Error on underlying bus errors.
00731 ///
00732 void Socket::Send(Data &send, Data &receive, int timeout)
00733 {
00734         Send(send, timeout);
00735         Receive(receive, timeout);
00736 }
00737 
00738 void Socket::Send(Barry::Packet &packet, int timeout)
00739 {
00740         Send(packet.m_send, *packet.m_receive, timeout);
00741 }
00742 
00743 void Socket::Receive(Data &receive, int timeout)
00744 {
00745         if( m_registered ) {
00746                 if( m_zero->m_queue ) {
00747                         if( !m_zero->m_queue->SocketRead(m_socket, receive, timeout) )
00748                                 throw Timeout("Socket::Receive: queue SocketRead returned false (likely a timeout)");
00749                 }
00750                 else {
00751                         throw std::logic_error("NULL queue pointer in a registered socket read.");
00752                 }
00753         }
00754         else {
00755                 m_zero->RawReceive(receive, timeout);
00756         }
00757 }
00758 
00759 
00760 // FIXME - find a better way to do this?
00761 void Socket::ReceiveData(Data &receive, int timeout)
00762 {
00763         HideSequencePacket(false);
00764         Receive(receive);
00765         HideSequencePacket(true);
00766 }
00767 
00768 void Socket::ClearHalt()
00769 {
00770         m_zero->ClearHalt();
00771 }
00772 
00773 
00774 // FIXME - find a better way to do this?
00775 void Socket::InitSequence(int timeout)
00776 {
00777         Data receive;
00778         receive.Zap();
00779 
00780         HideSequencePacket(false);
00781         Receive(receive);
00782         HideSequencePacket(true);
00783 
00784         Protocol::CheckSize(receive, SB_PACKET_HEADER_SIZE);
00785         CheckSequence(receive);
00786 }
00787 
00788 
00789 // sends the send packet down to the device
00790 // Blocks until response received or timed out in Usb::Device
00791 //
00792 // This function is used to send packet to JVM
00793 void Socket::PacketJVM(Data &send, Data &receive, int timeout)
00794 {
00795         if( ( send.GetSize() < MIN_PACKET_DATA_SIZE ) ||
00796                 ( send.GetSize() > MAX_PACKET_DATA_SIZE ) ) {
00797                 // we don't do that around here
00798                 throw std::logic_error("Socket: unknown send data in PacketJVM()");
00799         }
00800 
00801         Data &inFrag = receive;
00802         receive.Zap();
00803 
00804         // send non-fragmented
00805         Send(send, inFrag, timeout);
00806 
00807         bool done = false;
00808         int blankCount = 0;
00809 
00810         while( !done ) {
00811                 // check the packet's validity
00812                 if( inFrag.GetSize() > 6 ) {
00813                         MAKE_PACKET(rpack, inFrag);
00814 
00815                         blankCount = 0;
00816 
00817                         Protocol::CheckSize(inFrag, SB_PACKET_HEADER_SIZE);
00818 
00819                         switch( rpack->command )
00820                         {
00821                         case SB_COMMAND_SEQUENCE_HANDSHAKE:
00822                                 CheckSequence(inFrag);
00823                                 break;
00824 
00825                         default: {
00826                                 std::ostringstream oss;
00827                                 oss << "Socket: (read) unhandled packet in Packet(): 0x" << std::hex << (unsigned int)rpack->command;
00828                                 eout(oss.str());
00829                                 throw Error(oss.str());
00830                                 }
00831                                 break;
00832                         }
00833                 }
00834                 else if( inFrag.GetSize() == 6 ) {
00835                         done = true;
00836                 }
00837                 else {
00838                         blankCount++;
00839 
00840                         //std::cerr << "Blank! " << blankCount << std::endl;
00841                         if( blankCount == 10 ) {
00842                                 // only ask for more data on stalled sockets
00843                                 // for so long
00844                                 throw Error("Socket: 10 blank packets received");
00845                         }
00846                 }
00847 
00848                 if( !done ) {
00849                         // not done yet, ask for another read
00850                         Receive(inFrag);
00851                 }
00852         }
00853 }
00854 
00855 // sends the send packet down to the device
00856 // Blocks until response received or timed out in Usb::Device
00857 void Socket::PacketData(Data &send, Data &receive, int timeout)
00858 {
00859         if( ( send.GetSize() < MIN_PACKET_DATA_SIZE ) ||
00860                 ( send.GetSize() > MAX_PACKET_DATA_SIZE ) ) {
00861                 // we don't do that around here
00862                 throw std::logic_error("Socket: unknown send data in PacketData()");
00863         }
00864 
00865         Data &inFrag = receive;
00866         receive.Zap();
00867 
00868         // send non-fragmented
00869         Send(send, inFrag, timeout);
00870 
00871         bool done = false;
00872         int blankCount = 0;
00873 
00874         while( !done ) {
00875                 // check the packet's validity
00876                 if( inFrag.GetSize() > 0 ) {
00877                         MAKE_PACKET(rpack, inFrag);
00878 
00879                         blankCount = 0;
00880 
00881                         Protocol::CheckSize(inFrag, SB_PACKET_HEADER_SIZE);
00882 
00883                         switch( rpack->command )
00884                         {
00885                         case SB_COMMAND_SEQUENCE_HANDSHAKE:
00886                                 CheckSequence(inFrag);
00887                                 if (!m_zero->IsSequencePacketHidden())
00888                                         done = true;
00889                                 break;
00890 
00891                         case SB_COMMAND_JL_READY:
00892                         case SB_COMMAND_JL_ACK:
00893                         case SB_COMMAND_JL_HELLO_ACK:
00894                         case SB_COMMAND_JL_RESET_REQUIRED:
00895                                 done = true;
00896                                 break;
00897 
00898                         case SB_COMMAND_JL_GET_DATA_ENTRY:      // This response means that the next packet is the stream
00899                                 done = true;
00900                                 break;
00901 
00902                         case SB_DATA_JL_INVALID:
00903                                 throw BadPacket(rpack->command, "file is not a valid Java code file");
00904                                 break;
00905 
00906                         case SB_COMMAND_JL_NOT_SUPPORTED:
00907                                 throw BadPacket(rpack->command, "device does not support requested command");
00908                                 break;
00909 
00910                         default:
00911                                 // unknown packet, pass it up to the
00912                                 // next higher code layer
00913                                 done = true;
00914                                 break;
00915                         }
00916                 }
00917                 else {
00918                         blankCount++;
00919                         //std::cerr << "Blank! " << blankCount << std::endl;
00920                         if( blankCount == 10 ) {
00921                                 // only ask for more data on stalled sockets
00922                                 // for so long
00923                                 throw Error("Socket: 10 blank packets received");
00924                         }
00925                 }
00926 
00927                 if( !done ) {
00928                         // not done yet, ask for another read
00929                         Receive(inFrag);
00930                 }
00931         }
00932 }
00933 
00934 // sends the send packet down to the device, fragmenting if
00935 // necessary, and returns the response in receive, defragmenting
00936 // if needed
00937 // Blocks until response received or timed out in Usb::Device
00938 //
00939 // This is primarily for Desktop Database packets... Javaloader
00940 // packets use PacketData().
00941 //
00942 void Socket::Packet(Data &send, Data &receive, int timeout)
00943 {
00944         MAKE_PACKET(spack, send);
00945         if( send.GetSize() < MIN_PACKET_SIZE ||
00946             (spack->command != SB_COMMAND_DB_DATA &&
00947              spack->command != SB_COMMAND_DB_DONE) )
00948         {
00949                 // we don't do that around here
00950                 eout("unknown send data in Packet(): " << send);
00951                 throw std::logic_error("Socket: unknown send data in Packet()");
00952         }
00953 
00954         // assume the common case of no fragmentation,
00955         // and use the receive buffer for input... allocate a frag buffer
00956         // later if necessary
00957         Data *inputBuf = &receive;
00958         receive.Zap();
00959 
00960         if( send.GetSize() <= MAX_PACKET_SIZE ) {
00961                 // send non-fragmented
00962                 Send(send, *inputBuf, timeout);
00963         }
00964         else {
00965                 // send fragmented
00966                 unsigned int offset = 0;
00967                 Data outFrag;
00968 
00969                 // You haven't to sequence packet while the whole packet isn't sent
00970                 //  a) No sequence received packet
00971                 //  b) 1°) Sent framgment 1/N
00972                 //     2°) Sent framgment 2/N
00973                 //         ...
00974                 //     N°) Before sent fragment N/N, I enable the sequence packet process.
00975                 //         Sent framgment N/N
00976                 HideSequencePacket(false);
00977 
00978                 do {
00979                         offset = SocketZero::MakeNextFragment(send, outFrag, offset);
00980 
00981                         // Is last packet ?
00982                         MAKE_PACKET(spack, outFrag);
00983 
00984                         if (spack->command != SB_COMMAND_DB_FRAGMENTED)
00985                                 HideSequencePacket(true);
00986 
00987                         Send(outFrag, *inputBuf, timeout);
00988 
00989                         // only process sequence handshakes... once we
00990                         // get to the last fragment, we fall through to normal
00991                         // processing below
00992                         if (spack->command != SB_COMMAND_DB_FRAGMENTED) {
00993                                 MAKE_PACKET(rpack, *inputBuf);
00994 
00995                                 if( offset && inputBuf->GetSize() > 0 ) {
00996                                         Protocol::CheckSize(*inputBuf, SB_PACKET_HEADER_SIZE);
00997 
00998                                         switch( rpack->command )
00999                                         {
01000                                         case SB_COMMAND_SEQUENCE_HANDSHAKE:
01001                                                 CheckSequence(*inputBuf);
01002                                                 break;
01003 
01004                                         default: {
01005                                                 std::ostringstream oss;
01006                                                 oss << "Socket: (send) unhandled packet in Packet(): 0x" << std::hex << (unsigned int)rpack->command;
01007                                                 eout(oss.str());
01008                                                 throw Error(oss.str());
01009                                                 }
01010                                                 break;
01011                                         }
01012                                 }
01013                         }
01014 
01015                 } while( offset > 0 );
01016 
01017                 // To be sure that it's clean...
01018                 HideSequencePacket(true);
01019         }
01020 
01021         std::auto_ptr<Data> inFrag;
01022         bool done = false, frag = false;
01023         int blankCount = 0;
01024         while( !done ) {
01025                 MAKE_PACKET(rpack, *inputBuf);
01026 
01027                 // check the packet's validity
01028                 if( inputBuf->GetSize() > 0 ) {
01029                         blankCount = 0;
01030 
01031                         Protocol::CheckSize(*inputBuf, SB_PACKET_HEADER_SIZE);
01032 
01033                         switch( rpack->command )
01034                         {
01035                         case SB_COMMAND_SEQUENCE_HANDSHAKE:
01036                                 CheckSequence(*inputBuf);
01037                                 break;
01038 
01039                         case SB_COMMAND_DB_DATA:
01040                                 if( frag ) {
01041                                         SocketZero::AppendFragment(receive, *inputBuf);
01042                                 }
01043                                 else {
01044                                         // no copy needed, already in receive,
01045                                         // since inputBuf starts out that way
01046                                 }
01047                                 done = true;
01048                                 break;
01049 
01050                         case SB_COMMAND_DB_FRAGMENTED:
01051                                 // only copy if frag is true, since the
01052                                 // first time through, receive == inputBuf
01053                                 if( frag ) {
01054                                         SocketZero::AppendFragment(receive, *inputBuf);
01055                                 }
01056                                 frag = true;
01057                                 break;
01058 
01059                         case SB_COMMAND_DB_DONE:
01060                                 // no copy needed, already in receive
01061                                 done = true;
01062                                 break;
01063 
01064                         default: {
01065                                 std::ostringstream oss;
01066                                 oss << "Socket: (read) unhandled packet in Packet(): 0x" << std::hex << (unsigned int)rpack->command;
01067                                 eout(oss.str());
01068                                 throw Error(oss.str());
01069                                 }
01070                                 break;
01071                         }
01072                 }
01073                 else {
01074                         blankCount++;
01075                         //std::cerr << "Blank! " << blankCount << std::endl;
01076                         if( blankCount == 10 ) {
01077                                 // only ask for more data on stalled sockets
01078                                 // for so long
01079                                 throw Error("Socket: 10 blank packets received");
01080                         }
01081                 }
01082 
01083                 if( !done ) {
01084                         // not done yet, ask for another read, and
01085                         // create new buffer for fragmented reads
01086                         if( !inFrag.get() ) {
01087                                 inFrag.reset( new Data );
01088                                 inputBuf = inFrag.get();
01089                         }
01090                         Receive(*inputBuf);
01091                 }
01092         }
01093 }
01094 
01095 void Socket::Packet(Barry::Packet &packet, int timeout)
01096 {
01097         Packet(packet.m_send, *packet.m_receive, timeout);
01098 }
01099 
01100 void Socket::Packet(Barry::JLPacket &packet, int timeout)
01101 {
01102         if( packet.HasData() ) {
01103                 HideSequencePacket(false);
01104                 PacketData(packet.m_cmd, *packet.m_receive, timeout);
01105                 HideSequencePacket(true);
01106                 PacketData(packet.m_data, *packet.m_receive, timeout);
01107         }
01108         else {
01109                 PacketData(packet.m_cmd, *packet.m_receive, timeout);
01110         }
01111 }
01112 
01113 void Socket::Packet(Barry::JVMPacket &packet, int timeout)
01114 {
01115         HideSequencePacket(false);
01116         PacketJVM(packet.m_cmd, *packet.m_receive, timeout);
01117         HideSequencePacket(true);
01118 }
01119 
01120 void Socket::NextRecord(Data &receive)
01121 {
01122         Barry::Protocol::Packet packet;
01123         packet.socket = htobs(GetSocket());
01124         packet.size = htobs(7);
01125         packet.command = SB_COMMAND_DB_DONE;
01126         packet.u.db.tableCmd = 0;
01127         packet.u.db.u.command.operation = 0;
01128 
01129         Data command(&packet, 7);
01130         Packet(command, receive);
01131 }
01132 
01133 void Socket::RegisterInterest(SocketRoutingQueue::SocketDataHandlerPtr handler)
01134 {
01135         if( !m_zero->m_queue )
01136                 throw std::logic_error("SocketRoutingQueue required in SocketZero in order to call Socket::RegisterInterest()");
01137 
01138         if( m_registered )
01139                 throw std::logic_error("Socket already registered in Socket::RegisterInterest()!");
01140 
01141         m_zero->m_queue->RegisterInterest(m_socket, handler);
01142         m_registered = true;
01143 }
01144 
01145 void Socket::UnregisterInterest()
01146 {
01147         if( m_registered ) {
01148                 if( m_zero->m_queue )
01149                         m_zero->m_queue->UnregisterInterest(m_socket);
01150                 m_registered = false;
01151         }
01152 }
01153 
01154 
01155 } // namespace Barry
01156