3 /// Class wrapper to encapsulate the Blackberry USB logical socket
7 Copyright (C) 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
26 #include "protostructs.h"
40 //////////////////////////////////////////////////////////////////////////////
43 SocketZero::SocketZero( SocketRoutingQueue
&queue
,
45 uint8_t zeroSocketSequenceStart
)
48 , m_writeEp(writeEndpoint
)
50 , m_zeroSocketSequence(zeroSocketSequenceStart
)
55 , m_modeSequencePacketSeen(false)
60 SocketZero::SocketZero( Device
&dev
,
61 int writeEndpoint
, int readEndpoint
,
62 uint8_t zeroSocketSequenceStart
)
65 , m_writeEp(writeEndpoint
)
66 , m_readEp(readEndpoint
)
67 , m_zeroSocketSequence(zeroSocketSequenceStart
)
72 , m_modeSequencePacketSeen(false)
77 SocketZero::~SocketZero()
79 // nothing to close for socket zero
83 ///////////////////////////////////////
84 // Socket Zero static calls
86 // appends fragment to whole... if whole is empty, simply copies, and
87 // sets command to DATA instead of FRAGMENTED. Always updates the
88 // packet size of whole, to reflect the total size
89 void SocketZero::AppendFragment(Data
&whole
, const Data
&fragment
)
91 if( whole
.GetSize() == 0 ) {
92 // empty, so just copy
96 // has some data already, so just append
97 int size
= whole
.GetSize();
98 unsigned char *buf
= whole
.GetBuffer(size
+ fragment
.GetSize());
99 MAKE_PACKET(fpack
, fragment
);
100 int fragsize
= fragment
.GetSize() - SB_FRAG_HEADER_SIZE
;
102 memcpy(buf
+size
, &fpack
->u
.db
.u
.fragment
, fragsize
);
103 whole
.ReleaseBuffer(size
+ fragsize
);
106 // update whole's size and command type for future sanity
107 Barry::Protocol::Packet
*wpack
= (Barry::Protocol::Packet
*) whole
.GetBuffer();
108 wpack
->size
= htobs((uint16_t) whole
.GetSize());
109 wpack
->command
= SB_COMMAND_DB_DATA
;
110 // don't need to call ReleaseBuffer here, since we're not changing
111 // the real data size, and ReleaseBuffer was called above during copy
114 // If offset is 0, starts fresh, taking the first fragment packet size chunk
115 // out of whole and creating a sendable packet in fragment. Returns the
116 // next offset if there is still more data, or 0 if finished.
117 unsigned int SocketZero::MakeNextFragment(const Data
&whole
, Data
&fragment
, unsigned int offset
)
120 if( whole
.GetSize() < SB_FRAG_HEADER_SIZE
) {
121 eout("Whole packet too short to fragment: " << whole
.GetSize());
122 throw Error("Socket: Whole packet too short to fragment");
126 unsigned int todo
= whole
.GetSize() - SB_FRAG_HEADER_SIZE
- offset
;
127 unsigned int nextOffset
= 0;
128 if( todo
> (MAX_PACKET_SIZE
- SB_FRAG_HEADER_SIZE
) ) {
129 todo
= MAX_PACKET_SIZE
- SB_FRAG_HEADER_SIZE
;
130 nextOffset
= offset
+ todo
;
133 // create fragment header
134 unsigned char *buf
= fragment
.GetBuffer(SB_FRAG_HEADER_SIZE
+ todo
);
135 memcpy(buf
, whole
.GetData(), SB_FRAG_HEADER_SIZE
);
137 // copy over a fragment size of data
138 memcpy(buf
+ SB_FRAG_HEADER_SIZE
, whole
.GetData() + SB_FRAG_HEADER_SIZE
+ offset
, todo
);
140 // update fragment's size and command type
141 Barry::Protocol::Packet
*wpack
= (Barry::Protocol::Packet
*) buf
;
142 wpack
->size
= htobs((uint16_t) (todo
+ SB_FRAG_HEADER_SIZE
));
144 wpack
->command
= SB_COMMAND_DB_FRAGMENTED
;
146 wpack
->command
= SB_COMMAND_DB_DATA
;
148 // adjust the new fragment size
149 fragment
.ReleaseBuffer(SB_FRAG_HEADER_SIZE
+ todo
);
156 ///////////////////////////////////////
157 // SocketZero private API
160 // FIXME - not sure yet whether sequence ID's are per socket or not... if
161 // they are per socket, then this global sequence behaviour will not work,
162 // and we need to track m_sequenceId on a Socket level.
164 void SocketZero::CheckSequence(uint16_t socket
, const Data
&seq
)
166 MAKE_PACKET(spack
, seq
);
167 if( (unsigned int) seq
.GetSize() < SB_SEQUENCE_PACKET_SIZE
) {
168 eout("Short sequence packet:\n" << seq
);
169 throw Error("Socket: invalid sequence packet");
172 // we'll cheat here... if the packet's sequence is 0, we'll
173 // silently restart, otherwise, fail
174 uint32_t sequenceId
= btohl(spack
->u
.sequence
.sequenceId
);
175 if( sequenceId
== 0 ) {
176 // silently restart (will advance below)
180 if( sequenceId
!= m_sequenceId
) {
182 std::ostringstream oss
;
183 oss
<< "Socket 0x" << std::hex
<< (unsigned int)socket
184 << ": out of sequence. "
185 << "(Global sequence: " << m_sequenceId
186 << ". Packet sequence: " << sequenceId
189 throw Error(oss
.str());
192 dout("Bad sequence on socket 0: expected: "
194 << ". Packet sequence: " << sequenceId
);
203 void SocketZero::SendOpen(uint16_t socket
, Data
&receive
)
205 // build open command
206 Barry::Protocol::Packet packet
;
208 packet
.size
= htobs(SB_SOCKET_PACKET_HEADER_SIZE
);
209 packet
.command
= SB_COMMAND_OPEN_SOCKET
;
210 packet
.u
.socket
.socket
= htobs(socket
);
211 packet
.u
.socket
.sequence
= m_zeroSocketSequence
;// overwritten by Send()
213 Data
send(&packet
, SB_SOCKET_PACKET_HEADER_SIZE
);
217 if( Protocol::IsSequencePacket(receive
) ) {
218 m_modeSequencePacketSeen
= true;
219 // during open, we could get a sequence packet in
220 // the middle, from the SelectMode operation
223 } catch( Usb::Error
& ) {
224 eeout(send
, receive
);
228 // receive now holds the Open response
231 // SHA1 hashing logic based on Rick Scott's XmBlackBerry's send_password()
232 void SocketZero::SendPasswordHash(uint16_t socket
, const char *password
, Data
&receive
)
234 unsigned char pwdigest
[SHA_DIGEST_LENGTH
];
235 unsigned char prefixedhash
[SHA_DIGEST_LENGTH
+ 4];
237 // first, hash the password by itself
238 SHA1((unsigned char *) password
, strlen(password
), pwdigest
);
240 // prefix the resulting hash with the provided seed
241 uint32_t seed
= htobl(m_challengeSeed
);
242 memcpy(&prefixedhash
[0], &seed
, sizeof(uint32_t));
243 memcpy(&prefixedhash
[4], pwdigest
, SHA_DIGEST_LENGTH
);
246 SHA1((unsigned char *) prefixedhash
, SHA_DIGEST_LENGTH
+ 4, pwdigest
);
249 size_t size
= SB_SOCKET_PACKET_HEADER_SIZE
+ PASSWORD_CHALLENGE_SIZE
;
251 // build open command
252 Barry::Protocol::Packet packet
;
254 packet
.size
= htobs(size
);
255 packet
.command
= SB_COMMAND_PASSWORD
;
256 packet
.u
.socket
.socket
= htobs(socket
);
257 packet
.u
.socket
.sequence
= m_zeroSocketSequence
;// overwritten by Send()
258 packet
.u
.socket
.u
.password
.remaining_tries
= 0;
259 packet
.u
.socket
.u
.password
.unknown
= 0;
260 packet
.u
.socket
.u
.password
.param
= htobs(0x14); // FIXME - what does this mean?
261 memcpy(packet
.u
.socket
.u
.password
.u
.hash
, pwdigest
,
262 sizeof(packet
.u
.socket
.u
.password
.u
.hash
));
264 // blank password hashes as we don't need these anymore
265 memset(pwdigest
, 0, sizeof(pwdigest
));
266 memset(prefixedhash
, 0, sizeof(prefixedhash
));
268 Data
send(&packet
, size
);
272 // blank password hash as we don't need this anymore either
273 memset(packet
.u
.socket
.u
.password
.u
.hash
, 0,
274 sizeof(packet
.u
.socket
.u
.password
.u
.hash
));
278 if( Protocol::IsSequencePacket(receive
) ) {
279 m_modeSequencePacketSeen
= true;
281 CheckSequence(0, receive
);
283 // still need our ACK
287 // receive now holds the Password response
290 void SocketZero::RawSend(Data
&send
, int timeout
)
292 Usb::Device
*dev
= m_queue
? m_queue
->GetUsbDevice() : m_dev
;
294 throw Error("SocketZero: No device available for RawSend");
296 // Special case: it seems that sending packets with a size that's an
297 // exact multiple of 0x40 causes the device to get confused.
299 // To get around that, it is observed in the captures that the size
300 // is sent in a special 3 byte packet before the real packet.
301 // Check for this case here.
303 if( (send
.GetSize() % 0x40) == 0 ) {
304 Protocol::SizePacket packet
;
305 packet
.size
= htobs(send
.GetSize());
306 packet
.buffer
[2] = 0; // zero the top byte
307 Data
sizeCommand(&packet
, 3);
309 dev
->BulkWrite(m_writeEp
, sizeCommand
, timeout
);
312 dev
->BulkWrite(m_writeEp
, send
, timeout
);
315 void SocketZero::RawReceive(Data
&receive
, int timeout
)
318 receive
= m_pushback_buffer
;
324 if( !m_queue
->DefaultRead(receive
, timeout
) )
325 throw Timeout("SocketZero::RawReceive: queue DefaultRead returned false (likely a timeout)");
328 m_dev
->BulkRead(m_readEp
, receive
, timeout
);
331 ddout("SocketZero::RawReceive: Endpoint "
332 << (m_queue
? m_queue
->GetReadEp() : m_readEp
)
333 << "\nReceived:\n" << receive
);
336 void SocketZero::Pushback(const Data
&buf
)
339 throw Error("Multiple pushbacks");
342 m_pushback_buffer
= buf
;
346 ///////////////////////////////////////
347 // SocketZero public API
349 void SocketZero::SetRoutingQueue(SocketRoutingQueue
&queue
)
351 // replace the current queue pointer
355 void SocketZero::UnlinkRoutingQueue()
360 void SocketZero::Send(Data
&send
, int timeout
)
362 // force the socket number to 0
363 if( send
.GetSize() >= SB_SOCKET_PACKET_HEADER_SIZE
) {
364 MAKE_PACKETPTR_BUF(spack
, send
.GetBuffer());
368 // This is a socket 0 packet, so force the send packet data's
369 // socket 0 sequence number to something correct.
370 if( send
.GetSize() >= SB_SOCKET_PACKET_HEADER_SIZE
) {
371 MAKE_PACKETPTR_BUF(spack
, send
.GetBuffer());
372 spack
->u
.socket
.sequence
= m_zeroSocketSequence
;
373 m_zeroSocketSequence
++;
376 RawSend(send
, timeout
);
379 void SocketZero::Send(Data
&send
, Data
&receive
, int timeout
)
382 RawReceive(receive
, timeout
);
385 void SocketZero::Send(Barry::Packet
&packet
, int timeout
)
387 Send(packet
.m_send
, *packet
.m_receive
, timeout
);
390 void SocketZero::Receive(Data
&receive
, int timeout
)
392 RawReceive(receive
, timeout
);
399 /// Open a logical socket on the device.
401 /// Both the socket number and the flag are based on the response to the
402 /// SELECT_MODE command. See Controller::SelectMode() for more info
405 /// The packet sequence is normal for most socket operations.
407 /// - Down: command packet with OPEN_SOCKET
408 /// - Up: optional sequence handshake packet
409 /// - Up: command response, which repeats the socket and flag data
412 /// \exception Barry::Error
413 /// Thrown on protocol error.
415 /// \exception Barry::BadPassword
416 /// Thrown on invalid password, or not enough retries left
419 SocketHandle
SocketZero::Open(uint16_t socket
, const char *password
)
421 // Things get a little funky here, as we may be left in an
422 // intermediate state in the case of a failed password.
423 // This function should support being called as many times
424 // as needed to handle the password
427 ZeroPacket
packet(send
, receive
);
429 // save sequence for later close
430 uint8_t closeFlag
= GetZeroSocketSequence();
434 m_remainingTries
= 0;
436 // this gets set to true if we see a starting sequence packet
437 // during any of our open and password commands... After
438 // a mode command (like "RIM Desktop", etc.) a starting
439 // sequence packet is sent, and may arrive before or after
440 // the socket open handshake.
441 m_modeSequencePacketSeen
= false;
444 SendOpen(socket
, receive
);
446 // check for password challenge, or success
447 if( packet
.Command() == SB_COMMAND_PASSWORD_CHALLENGE
) {
449 m_challengeSeed
= packet
.ChallengeSeed();
450 m_remainingTries
= packet
.RemainingTries();
453 // fall through to challenge code...
457 // half open, device is expecting a password hash... do we
460 throw BadPassword("No password specified.", m_remainingTries
, false);
463 // only allow password attempts if there are
464 // BARRY_MIN_PASSWORD_TRIES or more tries remaining...
465 // we want to give the user at least some chance on a
466 // Windows machine before the device commits suicide.
467 if( m_remainingTries
< BARRY_MIN_PASSWORD_TRIES
) {
468 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.",
473 // save sequence for later close (again after SendOpen())
474 closeFlag
= GetZeroSocketSequence();
476 SendPasswordHash(socket
, password
, receive
);
478 if( packet
.Command() == SB_COMMAND_PASSWORD_FAILED
) {
480 m_challengeSeed
= packet
.ChallengeSeed();
481 m_remainingTries
= packet
.RemainingTries();
482 throw BadPassword("Password rejected by device.", m_remainingTries
, false);
485 // if we get this far, we are no longer in half-open password
486 // mode, so we can reset our flags
489 // fall through to success check...
492 // If the device thinks that the socket was already open then
493 // it will tell us by sending an SB_COMMAND_CLOSE_SOCKET.
495 // This happens most commonly when using raw channels which
496 // haven't been cleanly closed (such as by killing the process
497 // running Barry) and so the device still thinks the socket
500 // Retrying the open will usually succeed, but relies on the
501 // device software re-creating the channel after it's closed
502 // so return an error here instead of automatically retrying.
503 if( packet
.Command() == SB_COMMAND_CLOSE_SOCKET
)
505 throw SocketCloseOnOpen("Socket: Device closed socket when trying to open (can be caused by the wrong password, or if the device thinks the socket is already open... please try again)");
508 if( packet
.Command() != SB_COMMAND_OPENED_SOCKET
||
509 packet
.SocketResponse() != socket
||
510 packet
.SocketSequence() != closeFlag
)
512 eout("Packet:\n" << receive
);
513 throw Error("Socket: Bad OPENED packet in Open");
516 // if no sequence packet has yet arrived, wait for it here
517 if( !m_modeSequencePacketSeen
) {
519 RawReceive(sequence
);
520 if( !Protocol::IsSequencePacket(sequence
) ) {
521 // if this is not the sequence packet, then it might
522 // just be out of order (some devices do this when
523 // opening the JavaLoader mode), so as a last
524 // ditch effort, do one more read with a short
525 // timeout, and check that as well
527 RawReceive(late_sequence
, 500);
528 if( !Protocol::IsSequencePacket(late_sequence
) ) {
529 throw Error("Could not find mode's starting sequence packet");
532 // ok, so our ditch effort worked, but now we have
533 // a leftover packet on our hands... do a temporary
539 // success! save the socket
540 Socket
*sock
= new Socket(*this, socket
, closeFlag
);
541 SocketHandle
sh(sock
);
543 // if we are running with a routing queue, register the
544 // socket's interest in all its own data. By default, this
545 // data will be queued without a callback handler.
546 // If other application code needs to intercept this with
547 // its own handler, it must call UnregisterInterest() and
548 // re-register its own handler.
550 sock
->RegisterInterest();
559 /// Closes a non-default socket (i.e. non-zero socket number)
561 /// The packet sequence is just like Open(), except the command is
564 /// \exception Barry::Error
566 void SocketZero::Close(Socket
&socket
)
568 if( socket
.GetSocket() == 0 )
569 return; // nothing to do
571 // build close command
572 Barry::Protocol::Packet packet
;
574 packet
.size
= htobs(SB_SOCKET_PACKET_HEADER_SIZE
);
575 packet
.command
= SB_COMMAND_CLOSE_SOCKET
;
576 packet
.u
.socket
.socket
= htobs(socket
.GetSocket());
577 packet
.u
.socket
.sequence
= socket
.GetCloseFlag();
579 Data
command(&packet
, SB_SOCKET_PACKET_HEADER_SIZE
);
582 Send(command
, response
);
584 catch( Usb::Error
& ) {
585 // reset so this won't be called again
586 socket
.ForceClosed();
588 eeout(command
, response
);
592 // starting fresh, reset sequence ID
593 if( Protocol::IsSequencePacket(response
) ) {
594 CheckSequence(0, response
);
596 // still need our ACK
597 RawReceive(response
);
600 Protocol::CheckSize(response
, SB_SOCKET_PACKET_HEADER_SIZE
);
601 MAKE_PACKET(rpack
, response
);
602 // The reply will be SB_COMMAND_CLOSED_SOCKET if the device
603 // has closed the socket in response to our request.
605 // It's also possible for the reply to be
606 // SB_COMMAND_REMOTE_CLOSE_SOCKET if the device wanted to
607 // close the socket at the same time, such as if the channel
608 // API is being used by the device.
609 if( ( rpack
->command
!= SB_COMMAND_CLOSED_SOCKET
&&
610 rpack
->command
!= SB_COMMAND_REMOTE_CLOSE_SOCKET
) ||
611 btohs(rpack
->u
.socket
.socket
) != socket
.GetSocket() ||
612 rpack
->u
.socket
.sequence
!= socket
.GetCloseFlag() )
614 // reset so this won't be called again
615 socket
.ForceClosed();
617 eout("Packet:\n" << response
);
618 throw BadPacket(rpack
->command
, "Socket: Bad CLOSED packet in Close");
621 if( socket
.IsResetOnClose() ) {
623 ZeroPacket
reset_packet(send
, receive
);
624 reset_packet
.Reset();
627 if( reset_packet
.CommandResponse() != SB_COMMAND_RESET_REPLY
) {
628 throw BadPacket(reset_packet
.CommandResponse(),
629 "Socket: Missing RESET_REPLY in Close");
633 // // and finally, there always seems to be an extra read of
634 // // an empty packet at the end... just throw it away
636 // RawReceive(response, 1);
638 // catch( Usb::Timeout & ) {
641 // reset socket and flag
642 socket
.ForceClosed();
649 //////////////////////////////////////////////////////////////////////////////
652 SocketBase::~SocketBase()
656 void SocketBase::CheckSequence(const Data
&seq
)
658 // FIXME - needs implementation
664 /// Sends a fragmented Desktop / Database command packet.
665 /// Assumes that 'send' contains a valid packet, which may or may not
666 /// need fragmentation. If it does, fragmentation will be done
669 void SocketBase::DBFragSend(Data
&send
, int timeout
)
671 MAKE_PACKET(spack
, send
);
672 if( send
.GetSize() < MIN_PACKET_SIZE
||
673 (spack
->command
!= SB_COMMAND_DB_DATA
&&
674 spack
->command
!= SB_COMMAND_DB_DONE
) )
676 // we don't do that around here
677 eout("unknown send data in DBFragSend(): " << send
);
678 throw std::logic_error("Socket: unknown send data in DBFragSend()");
681 if( send
.GetSize() <= MAX_PACKET_SIZE
) {
682 // send non-fragmented
683 SyncSend(send
, timeout
);
687 unsigned int offset
= 0;
691 offset
= SocketZero::MakeNextFragment(send
, outFrag
, offset
);
692 SyncSend(outFrag
, timeout
);
693 } while( offset
> 0 );
701 /// SyncSends 'send' data to device, and waits for response.
705 /// \exception Usb::Error on underlying bus errors.
707 void SocketBase::Send(Data
&send
, Data
&receive
, int timeout
)
709 SyncSend(send
, timeout
);
710 Receive(receive
, timeout
);
713 void SocketBase::Send(Barry::Packet
&packet
, int timeout
)
715 Send(packet
.m_send
, *packet
.m_receive
, timeout
);
718 // sends the send packet down to the device, fragmenting if
719 // necessary, and returns the response in receive, defragmenting
721 // Blocks until response received or timed out in Usb::Device
723 // This is primarily for Desktop Database packets... Javaloader
724 // packets use PacketData().
726 void SocketBase::Packet(Data
&send
, Data
&receive
, int timeout
)
728 // assume the common case of no fragmentation,
729 // and use the receive buffer for input... allocate a frag buffer
730 // later if necessary
731 Data
*inputBuf
= &receive
;
734 DBFragSend(send
, timeout
);
735 Receive(*inputBuf
, timeout
);
737 std::auto_ptr
<Data
> inFrag
;
738 bool done
= false, frag
= false;
741 MAKE_PACKET(rpack
, *inputBuf
);
743 // check the packet's validity
744 if( inputBuf
->GetSize() > 0 ) {
747 Protocol::CheckSize(*inputBuf
, SB_PACKET_HEADER_SIZE
);
749 switch( rpack
->command
)
751 case SB_COMMAND_SEQUENCE_HANDSHAKE
:
752 CheckSequence(*inputBuf
);
755 case SB_COMMAND_DB_DATA
:
757 SocketZero::AppendFragment(receive
, *inputBuf
);
760 // no copy needed, already in receive,
761 // since inputBuf starts out that way
766 case SB_COMMAND_DB_FRAGMENTED
:
767 // only copy if frag is true, since the
768 // first time through, receive == inputBuf
770 SocketZero::AppendFragment(receive
, *inputBuf
);
775 case SB_COMMAND_DB_DONE
:
776 // no copy needed, already in receive
781 std::ostringstream oss
;
782 oss
<< "Socket: (read) unhandled packet in Packet(): 0x" << std::hex
<< (unsigned int)rpack
->command
;
784 throw Error(oss
.str());
791 //std::cerr << "Blank! " << blankCount << std::endl;
792 if( blankCount
== 10 ) {
793 // only ask for more data on stalled sockets
795 throw Error("Socket: 10 blank packets received");
800 // not done yet, ask for another read, and
801 // create new buffer for fragmented reads
802 if( frag
&& !inFrag
.get() ) {
803 inFrag
.reset( new Data
);
804 inputBuf
= inFrag
.get();
811 void SocketBase::Packet(Barry::Packet
&packet
, int timeout
)
813 Packet(packet
.m_send
, *packet
.m_receive
, timeout
);
816 void SocketBase::Packet(Barry::JLPacket
&packet
, int timeout
)
818 if( packet
.HasData() ) {
819 SyncSend(packet
.m_cmd
);
820 PacketData(packet
.m_data
, *packet
.m_receive
, false, timeout
);
823 PacketData(packet
.m_cmd
, *packet
.m_receive
, false, timeout
);
827 void SocketBase::Packet(Barry::JVMPacket
&packet
, int timeout
)
829 PacketJVM(packet
.m_cmd
, *packet
.m_receive
, timeout
);
832 // sends the send packet down to the device
833 // Blocks until response received or timed out in Usb::Device
835 // This function is used to send packet to JVM
836 void SocketBase::PacketJVM(Data
&send
, Data
&receive
, int timeout
)
838 if( ( send
.GetSize() < MIN_PACKET_DATA_SIZE
) ||
839 ( send
.GetSize() > MAX_PACKET_DATA_SIZE
) ) {
840 // we don't do that around here
841 throw std::logic_error("Socket: unknown send data in PacketJVM()");
844 Data
&inFrag
= receive
;
847 // send non-fragmented
848 RawSend(send
, timeout
);
849 Receive(inFrag
, timeout
);
855 // check the packet's validity
856 if( inFrag
.GetSize() > 6 ) {
857 MAKE_PACKET(rpack
, inFrag
);
861 Protocol::CheckSize(inFrag
, SB_PACKET_HEADER_SIZE
);
863 switch( rpack
->command
)
865 case SB_COMMAND_SEQUENCE_HANDSHAKE
:
866 CheckSequence(inFrag
);
870 std::ostringstream oss
;
871 oss
<< "Socket: (read) unhandled packet in Packet(): 0x" << std::hex
<< (unsigned int)rpack
->command
;
873 throw Error(oss
.str());
878 else if( inFrag
.GetSize() == 6 ) {
884 //std::cerr << "Blank! " << blankCount << std::endl;
885 if( blankCount
== 10 ) {
886 // only ask for more data on stalled sockets
888 throw Error("Socket: 10 blank packets received");
893 // not done yet, ask for another read
894 Receive(inFrag
, timeout
);
899 // sends the send packet down to the device
900 // Blocks until response received or timed out in Usb::Device
901 void SocketBase::PacketData(Data
&send
,
903 bool done_on_sequence
,
906 if( ( send
.GetSize() < MIN_PACKET_DATA_SIZE
) ||
907 ( send
.GetSize() > MAX_PACKET_DATA_SIZE
) ) {
908 // we don't do that around here
909 throw std::logic_error("Socket: unknown send data in PacketData()");
912 Data
&inFrag
= receive
;
915 // send non-fragmented
916 SyncSend(send
, timeout
);
917 Receive(inFrag
, timeout
);
923 // check the packet's validity
924 if( inFrag
.GetSize() > 0 ) {
925 MAKE_PACKET(rpack
, inFrag
);
929 Protocol::CheckSize(inFrag
, SB_PACKET_HEADER_SIZE
);
931 switch( rpack
->command
)
933 case SB_COMMAND_SEQUENCE_HANDSHAKE
:
934 // CheckSequence(inFrag);
935 if( done_on_sequence
)
939 case SB_COMMAND_JL_READY
:
940 case SB_COMMAND_JL_ACK
:
941 case SB_COMMAND_JL_HELLO_ACK
:
942 case SB_COMMAND_JL_RESET_REQUIRED
:
946 case SB_COMMAND_JL_GET_DATA_ENTRY
: // This response means that the next packet is the stream
950 case SB_DATA_JL_INVALID
:
951 throw BadPacket(rpack
->command
, "file is not a valid Java code file");
954 case SB_COMMAND_JL_NOT_SUPPORTED
:
955 throw BadPacket(rpack
->command
, "device does not support requested command");
959 // unknown packet, pass it up to the
960 // next higher code layer
967 //std::cerr << "Blank! " << blankCount << std::endl;
968 if( blankCount
== 10 ) {
969 // only ask for more data on stalled sockets
971 throw Error("Socket: 10 blank packets received");
976 // not done yet, ask for another read
982 void SocketBase::NextRecord(Data
&receive
)
984 Barry::Protocol::Packet packet
;
985 packet
.size
= htobs(7);
986 packet
.command
= SB_COMMAND_DB_DONE
;
987 packet
.u
.db
.tableCmd
= 0;
988 packet
.u
.db
.u
.command
.operation
= 0;
990 Data
command(&packet
, 7);
991 Packet(command
, receive
);
996 //////////////////////////////////////////////////////////////////////////////
999 Socket::Socket( SocketZero
&zero
,
1004 , m_closeFlag(closeFlag
)
1005 , m_registered(false)
1006 , m_sequence(new Data
)
1012 // trap exceptions in the destructor
1014 // a non-default socket has been opened, close it
1017 catch( std::runtime_error
&re
) {
1018 // do nothing... log it?
1019 dout("Exception caught in ~Socket: " << re
.what());
1024 ////////////////////////////////////
1025 // Socket protected API
1027 void Socket::ForceClosed()
1033 void Socket::LocalClose()
1035 LocalUnregisterInterest();
1036 m_zero
->Close(*this);
1039 void Socket::LocalUnregisterInterest()
1041 if( m_registered
) {
1042 if( m_zero
->m_queue
)
1043 m_zero
->m_queue
->UnregisterInterest(m_socket
);
1044 m_registered
= false;
1052 /// Sends 'send' data to device, no receive.
1056 /// \exception Usb::Error on underlying bus errors.
1058 void Socket::RawSend(Data
&send
, int timeout
)
1060 // force the socket number to this socket
1061 if( send
.GetSize() >= SB_PACKET_HEADER_SIZE
) {
1062 MAKE_PACKETPTR_BUF(spack
, send
.GetBuffer());
1063 spack
->socket
= htobs(m_socket
);
1065 m_zero
->RawSend(send
, timeout
);
1068 void Socket::SyncSend(Data
&send
, int timeout
)
1070 RawSend(send
, timeout
);
1071 Receive(*m_sequence
, timeout
);
1072 if( !Protocol::IsSequencePacket(*m_sequence
) )
1073 throw Barry::Error("Non-sequence packet in Socket::SyncSend()");
1074 CheckSequence(*m_sequence
);
1077 void Socket::Receive(Data
&receive
, int timeout
)
1079 if( m_registered
) {
1080 if( m_zero
->m_queue
) {
1081 if( !m_zero
->m_queue
->SocketRead(m_socket
, receive
, timeout
) )
1082 throw Timeout("Socket::Receive: queue SocketRead returned false (likely a timeout)");
1085 throw std::logic_error("NULL queue pointer in a registered socket read.");
1087 ddout("Socket::Receive: Endpoint "
1088 << (m_zero
->m_queue
? m_zero
->m_queue
->GetReadEp() : m_zero
->m_readEp
)
1089 << "\nReceived:\n" << receive
);
1092 m_zero
->RawReceive(receive
, timeout
);
1097 void Socket::RegisterInterest(SocketRoutingQueue::SocketDataHandlerPtr handler
)
1099 if( !m_zero
->m_queue
)
1100 throw std::logic_error("SocketRoutingQueue required in SocketZero in order to call Socket::RegisterInterest()");
1102 if( m_registered
) {
1103 std::ostringstream oss
;
1104 oss
<< "Socket (" << m_socket
<< ") already registered in Socket::RegisterInterest()!";
1105 throw std::logic_error(oss
.str());
1108 m_zero
->m_queue
->RegisterInterest(m_socket
, handler
);
1109 m_registered
= true;
1113 } // namespace Barry